summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2021-09-01 11:08:40 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2021-10-01 12:16:21 +0000
commit03c549e0392f92c02536d3f86d5e1d8dfa3435ac (patch)
treefe49d170a929b34ba82cd10db1a0bd8e3760fa4b /chromium/net/third_party/quiche
parent5d013f5804a0d91fcf6c626b2d6fb6eca5c845b0 (diff)
downloadqtwebengine-chromium-03c549e0392f92c02536d3f86d5e1d8dfa3435ac.tar.gz
BASELINE: Update Chromium to 91.0.4472.160
Change-Id: I0def1f08a2412aeed79a9ab95dd50eb5c3f65f31 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/net/third_party/quiche')
-rw-r--r--chromium/net/third_party/quiche/BUILD.gn39
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/api/quiche_bug_tracker.h15
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/api/quiche_logging.h1
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/api/quiche_string_piece.h19
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/api/quiche_text_utils.h11
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/api/quiche_text_utils_test.cc5
-rw-r--r--chromium/net/third_party/quiche/src/common/quiche_endian.h6
-rw-r--r--chromium/net/third_party/quiche/src/epoll_server/simple_epoll_server.cc2
-rw-r--r--chromium/net/third_party/quiche/src/epoll_server/simple_epoll_server.h1
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_adapter.h99
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.cc68
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.h105
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_session.h41
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_util.cc40
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_util.h15
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_visitor_interface.h178
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/mock_http2_visitor.h124
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.cc189
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.h52
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.cc82
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.h48
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.cc164
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.h53
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter_test.cc88
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.cc129
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.h56
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/test_utils.cc127
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/test_utils.h29
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/test_utils_test.cc96
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/window_manager.cc99
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/window_manager.h74
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/window_manager_test.cc171
-rw-r--r--chromium/net/third_party/quiche/src/http2/decoder/decode_status.cc2
-rw-r--r--chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder.cc16
-rw-r--r--chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder.h6
-rw-r--r--chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_test.cc13
-rw-r--r--chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder.cc13
-rw-r--r--chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/altsvc_payload_decoder.cc5
-rw-r--r--chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/data_payload_decoder.cc5
-rw-r--r--chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/goaway_payload_decoder.cc5
-rw-r--r--chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/headers_payload_decoder.cc5
-rw-r--r--chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/payload_decoder_base_test_util.h2
-rw-r--r--chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder.cc6
-rw-r--r--chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder_test.cc34
-rw-r--r--chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/push_promise_payload_decoder.cc2
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_decoder.cc3
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.cc5
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.h5
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.cc4
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.h5
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.cc24
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.h5
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state_test.cc15
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.cc6
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.cc53
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.h77
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_test.cc19
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_collector.cc16
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder.cc4
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_type_decoder.cc4
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_collector.cc7
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/hpack_string.cc73
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/hpack_string.h78
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/hpack_string_test.cc149
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder.cc2
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_example.cc6
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.cc1
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_round_trip_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/http2/http2_constants.cc6
-rw-r--r--chromium/net/third_party/quiche/src/http2/http2_constants.h8
-rw-r--r--chromium/net/third_party/quiche/src/http2/http2_structures_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/http2/platform/api/http2_bug_tracker.h12
-rw-r--r--chromium/net/third_party/quiche/src/http2/platform/api/http2_string_utils.h15
-rw-r--r--chromium/net/third_party/quiche/src/http2/platform/api/http2_string_utils_test.cc98
-rw-r--r--chromium/net/third_party/quiche/src/http2/test_tools/frame_parts.cc10
-rw-r--r--chromium/net/third_party/quiche/src/http2/tools/http2_frame_builder.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_base.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_buffer.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_gso_batch_writer.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_sendmmsg_batch_writer.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/chlo_extractor.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.cc68
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.cc42
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.cc13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.cc71
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_simulator_test.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.cc15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_decrypter.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_encrypter.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_decrypter.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/certificate_view.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_decrypter.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_encrypter.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_server_test.cc39
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.cc37
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.cc23
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/proof_source_x509.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache_test.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.cc29
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc41
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.cc59
-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_decrypter.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_encrypter.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.cc16
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.cc115
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_ack_frame.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_frames_test.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_new_connection_id_frame.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_new_connection_id_frame.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_retire_connection_id_frame.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_rst_stream_frame.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_stop_sending_frame.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc442
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_constants.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_constants.h37
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_decoder.cc293
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_decoder.h45
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_decoder_test.cc135
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_encoder.cc92
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_encoder.h26
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_encoder_test.cc63
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_frames.h14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_header_list.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream_test.cc100
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream_test.cc47
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.cc21
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream_test.cc25
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_server_initiated_spdy_stream.cc43
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_server_initiated_spdy_stream.h32
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.cc27
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.cc48
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_test.cc158
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream_test.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_server_stream_base_test.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc685
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.h258
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc651
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc270
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h53
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc119
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc42
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc32
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.cc271
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.h117
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/packet_number_indexed_queue.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.cc25
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.cc94
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h31
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table.cc98
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h40
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table_test.cc35
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table_test.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.cc23
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store_test.cc66
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.cc30
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet_test.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_config.cc126
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_config.h39
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_config_test.cc18
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection.cc738
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection.h97
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_id.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_id_manager.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_id_manager.h15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_id_manager_test.cc16
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.h15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc658
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_constants.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc20
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager_test.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.cc30
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_data_writer.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.cc190
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_dispatcher_test.cc173
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_flags_list.h48
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_flow_controller.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_framer.cc540
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_framer.h30
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_framer_test.cc196
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_interval_deque.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_legacy_version_encapsulator.cc27
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_linux_socket_utils.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_one_block_arena.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.cc236
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_creator_test.cc47
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_number.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_number.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packets.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packets.h11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packets_test.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_path_validator.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_path_validator_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_protocol_flags_list.h13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc70
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_session.cc185
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_session.h21
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc29
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream.cc86
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.cc30
-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_buffer.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_test.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.cc21
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager_test.cc18
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_types.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_types.h17
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_udp_socket_posix.cc13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_udp_socket_test.cc439
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.cc42
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_utils.cc85
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_utils.h23
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_utils_test.cc20
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_versions.cc28
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_chlo_extractor.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_chlo_extractor.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc96
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker_test.cc57
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_handshaker.cc43
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_handshaker.h15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.cc150
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.h14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.cc13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/web_transport_interface.h130
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/web_transport_stream_adapter.cc116
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/web_transport_stream_adapter.h66
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_client_bin.cc27
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_client_session.cc261
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_client_session.h75
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.cc73
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_dispatcher.cc22
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_dispatcher.h9
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_epoll_client.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.cc71
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_epoll_server.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_epoll_server.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_server_backend.cc88
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_server_backend.h17
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_server_bin.cc27
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_server_session.cc431
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_server_session.h68
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_utils.cc34
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_utils.h19
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils_test.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address.cc17
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h22
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_uint128.h19
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/qbone_tunnel_info.cc37
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/qbone_tunnel_info.h29
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device.cc15
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_interface.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_test.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_client.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_client_test.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc22
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.cc33
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.h59
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_integration_test.cc30
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc93
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h46
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream_test.cc42
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/web_transport_fingerprint_proof_verifier.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_time_wait_list_manager.h12
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_id_manager_peer.h29
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc31
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h9
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc28
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_backend.cc139
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_backend.h34
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.cc29
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.h69
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_quic_framer.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/queue.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/queue.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h11
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_backend_response.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_base.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_interop_test_bin.cc44
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc51
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h11
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend_test.cc16
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_server_bin.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.cc25
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h17
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.cc31
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session_test.cc40
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.cc67
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc97
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.cc23
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h11
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_tcp_like_trace_converter.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.cc129
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/web_transport_test_visitors.h137
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/fifo_write_scheduler.h242
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/fifo_write_scheduler_test.cc103
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.cc61
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h24
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter_test.cc7
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.cc34
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h7
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder_test.cc70
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.cc65
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.h111
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry_test.cc119
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.cc168
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h118
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table_test.cc266
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.cc27
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.h13
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table_test.cc17
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.cc29
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h10
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/http2_priority_write_scheduler.h44
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/lifo_write_scheduler.h238
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/lifo_write_scheduler_test.cc174
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler.h24
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.cc9
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.h4
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_frame_builder.cc7
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_frame_builder.h7
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_framer.cc15
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_framer.h3
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_framer_test.cc70
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.cc6
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.h22
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.cc16
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.h6
-rw-r--r--chromium/net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h3
-rw-r--r--chromium/net/third_party/quiche/src/spdy/platform/api/spdy_containers.h17
-rw-r--r--chromium/net/third_party/quiche/src/spdy/platform/api/spdy_mem_slice.h54
-rw-r--r--chromium/net/third_party/quiche/src/spdy/platform/api/spdy_mem_slice_test.cc47
-rw-r--r--chromium/net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h19
-rw-r--r--chromium/net/third_party/quiche/src/spdy/platform/api/spdy_string_utils_test.cc129
425 files changed, 12184 insertions, 7233 deletions
diff --git a/chromium/net/third_party/quiche/BUILD.gn b/chromium/net/third_party/quiche/BUILD.gn
index e74d858ff3b..7b567969912 100644
--- a/chromium/net/third_party/quiche/BUILD.gn
+++ b/chromium/net/third_party/quiche/BUILD.gn
@@ -45,7 +45,6 @@ source_set("quiche") {
"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_string_piece.h",
"src/common/platform/api/quiche_text_utils.h",
"src/common/platform/api/quiche_time_utils.h",
"src/common/quiche_data_reader.cc",
@@ -123,8 +122,6 @@ source_set("quiche") {
"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/hpack_string.cc",
- "src/http2/hpack/hpack_string.h",
"src/http2/hpack/http2_hpack_constants.cc",
"src/http2/hpack/http2_hpack_constants.h",
"src/http2/hpack/huffman/hpack_huffman_decoder.cc",
@@ -346,10 +343,16 @@ source_set("quiche") {
"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",
@@ -360,6 +363,8 @@ source_set("quiche") {
"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",
@@ -428,6 +433,8 @@ source_set("quiche") {
"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",
@@ -535,6 +542,8 @@ source_set("quiche") {
"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",
@@ -560,7 +569,6 @@ source_set("quiche") {
"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_ptr_util.h",
"src/quic/platform/api/quic_reference_counted.h",
"src/quic/platform/api/quic_server_stats.h",
"src/quic/platform/api/quic_sleep.h",
@@ -568,7 +576,6 @@ source_set("quiche") {
"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/platform/api/quic_uint128.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",
@@ -579,7 +586,6 @@ source_set("quiche") {
"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/fifo_write_scheduler.h",
"src/spdy/core/hpack/hpack_constants.cc",
"src/spdy/core/hpack/hpack_constants.h",
"src/spdy/core/hpack/hpack_decoder_adapter.cc",
@@ -597,7 +603,6 @@ source_set("quiche") {
"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/lifo_write_scheduler.h",
"src/spdy/core/priority_write_scheduler.h",
"src/spdy/core/recording_headers_handler.cc",
"src/spdy/core/recording_headers_handler.h",
@@ -616,6 +621,8 @@ source_set("quiche") {
"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",
@@ -631,7 +638,6 @@ source_set("quiche") {
"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_mem_slice.h",
"src/spdy/platform/api/spdy_string_utils.h",
]
}
@@ -949,6 +955,8 @@ source_set("quic_test_tools_core") {
"src/quic/test_tools/quic_stream_sequencer_peer.h",
"src/quic/test_tools/quic_sustained_bandwidth_recorder_peer.cc",
"src/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h",
+ "src/quic/test_tools/quic_test_backend.cc",
+ "src/quic/test_tools/quic_test_backend.h",
"src/quic/test_tools/quic_test_utils.cc",
"src/quic/test_tools/quic_test_utils.h",
"src/quic/test_tools/quic_time_wait_list_manager_peer.cc",
@@ -1044,10 +1052,6 @@ source_set("simple_quic_tools_core") {
sources = [
"src/quic/core/chlo_extractor.cc",
"src/quic/core/chlo_extractor.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_stream.cc",
- "src/quic/core/http/quic_spdy_client_stream.h",
"src/quic/core/http/quic_spdy_server_stream_base.cc",
"src/quic/core/http/quic_spdy_server_stream_base.h",
"src/quic/core/quic_buffered_packet_store.cc",
@@ -1224,7 +1228,6 @@ source_set("quiche_tests") {
"src/http2/hpack/decoder/hpack_string_collector.h",
"src/http2/hpack/decoder/hpack_string_decoder_test.cc",
"src/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc",
- "src/http2/hpack/hpack_string_test.cc",
"src/http2/hpack/http2_hpack_constants_test.cc",
"src/http2/hpack/huffman/hpack_huffman_decoder_test.cc",
"src/http2/hpack/huffman/hpack_huffman_encoder_test.cc",
@@ -1344,6 +1347,7 @@ source_set("quiche_tests") {
"src/quic/core/quic_circular_deque_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",
"src/quic/core/quic_connection_id_test.cc",
"src/quic/core/quic_connection_test.cc",
"src/quic/core/quic_control_frame_manager_test.cc",
@@ -1420,7 +1424,6 @@ source_set("quiche_tests") {
"src/spdy/core/array_output_buffer.cc",
"src/spdy/core/array_output_buffer.h",
"src/spdy/core/array_output_buffer_test.cc",
- "src/spdy/core/fifo_write_scheduler_test.cc",
"src/spdy/core/hpack/hpack_decoder_adapter_test.cc",
"src/spdy/core/hpack/hpack_encoder_test.cc",
"src/spdy/core/hpack/hpack_entry_test.cc",
@@ -1429,7 +1432,6 @@ source_set("quiche_tests") {
"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/lifo_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",
@@ -1440,8 +1442,6 @@ source_set("quiche_tests") {
"src/spdy/core/spdy_header_block_test.cc",
"src/spdy/core/spdy_header_storage_test.cc",
"src/spdy/core/spdy_intrusive_list_test.cc",
- "src/spdy/core/spdy_no_op_visitor.cc",
- "src/spdy/core/spdy_no_op_visitor.h",
"src/spdy/core/spdy_pinnable_buffer_piece_test.cc",
"src/spdy/core/spdy_prefixed_buffer_reader_test.cc",
"src/spdy/core/spdy_protocol_test.cc",
@@ -1450,7 +1450,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_mem_slice_test.cc",
"src/spdy/platform/api/spdy_string_utils_test.cc",
"src/spdy/platform/api/spdy_test_helpers.h",
]
@@ -1490,10 +1489,6 @@ source_set("quiche_tests") {
"//net:epoll_server",
"//net:epoll_server_test_tools",
]
-
- if (!is_chromeos_ash) {
- sources += [ "src/quic/core/quic_udp_socket_test.cc" ]
- }
}
}
diff --git a/chromium/net/third_party/quiche/src/common/platform/api/quiche_bug_tracker.h b/chromium/net/third_party/quiche/src/common/platform/api/quiche_bug_tracker.h
new file mode 100644
index 00000000000..0e8e456209a
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/platform/api/quiche_bug_tracker.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_BUG_TRACKER_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_BUG_TRACKER_H_
+
+#include "net/quiche/common/platform/impl/quiche_bug_tracker_impl.h"
+
+#define QUICHE_BUG QUICHE_BUG_IMPL
+#define QUICHE_BUG_IF QUICHE_BUG_IF_IMPL
+#define QUICHE_PEER_BUG QUICHE_PEER_BUG_IMPL
+#define QUICHE_PEER_BUG_IF QUICHE_PEER_BUG_IF_IMPL
+
+#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_BUG_TRACKER_H_
diff --git a/chromium/net/third_party/quiche/src/common/platform/api/quiche_logging.h b/chromium/net/third_party/quiche/src/common/platform/api/quiche_logging.h
index e3278ebfc37..940d492199d 100644
--- a/chromium/net/third_party/quiche/src/common/platform/api/quiche_logging.h
+++ b/chromium/net/third_party/quiche/src/common/platform/api/quiche_logging.h
@@ -40,6 +40,7 @@
#define QUICHE_LOG_ERROR_IS_ON() QUICHE_LOG_ERROR_IS_ON_IMPL()
#define QUICHE_CHECK(condition) QUICHE_CHECK_IMPL(condition)
+#define QUICHE_CHECK_OK(condition) QUICHE_CHECK_OK_IMPL(condition)
#define QUICHE_CHECK_EQ(val1, val2) QUICHE_CHECK_EQ_IMPL(val1, val2)
#define QUICHE_CHECK_NE(val1, val2) QUICHE_CHECK_NE_IMPL(val1, val2)
#define QUICHE_CHECK_LE(val1, val2) QUICHE_CHECK_LE_IMPL(val1, val2)
diff --git a/chromium/net/third_party/quiche/src/common/platform/api/quiche_string_piece.h b/chromium/net/third_party/quiche/src/common/platform/api/quiche_string_piece.h
deleted file mode 100644
index ca58aae6d68..00000000000
--- a/chromium/net/third_party/quiche/src/common/platform/api/quiche_string_piece.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_STRING_PIECE_H_
-#define QUICHE_COMMON_PLATFORM_API_QUICHE_STRING_PIECE_H_
-
-#include "absl/strings/string_view.h"
-#include "net/quiche/common/platform/impl/quiche_string_piece_impl.h"
-
-namespace quiche {
-
-inline size_t QuicheHashStringPair(absl::string_view a, absl::string_view b) {
- return QuicheHashStringPairImpl(a, b);
-}
-
-} // namespace quiche
-
-#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_STRING_PIECE_H_
diff --git a/chromium/net/third_party/quiche/src/common/platform/api/quiche_text_utils.h b/chromium/net/third_party/quiche/src/common/platform/api/quiche_text_utils.h
index 1d3a86eb440..42b4115a5de 100644
--- a/chromium/net/third_party/quiche/src/common/platform/api/quiche_text_utils.h
+++ b/chromium/net/third_party/quiche/src/common/platform/api/quiche_text_utils.h
@@ -28,17 +28,6 @@ class QUICHE_EXPORT QuicheTextUtils {
quiche::QuicheTextUtilsImpl::RemoveLeadingAndTrailingWhitespace(data);
}
- // Returns a new string representing |in|.
- static std::string Uint64ToString(uint64_t in) {
- return quiche::QuicheTextUtilsImpl::Uint64ToString(in);
- }
-
- // This converts a uint32 into an 8-character hexidecimal
- // representation. Return value: 8 characters of ASCII string.
- static std::string Hex(uint32_t v) {
- return quiche::QuicheTextUtilsImpl::Hex(v);
- }
-
// Base64 encodes with no padding |data_len| bytes of |data| into |output|.
static void Base64Encode(const uint8_t* data,
size_t data_len,
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/platform/api/quiche_text_utils_test.cc
index 634e7354c93..d6d1f4d443e 100644
--- a/chromium/net/third_party/quiche/src/common/platform/api/quiche_text_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/common/platform/api/quiche_text_utils_test.cc
@@ -33,11 +33,6 @@ TEST_F(QuicheTextUtilsTest, RemoveLeadingAndTrailingWhitespace) {
}
}
-TEST_F(QuicheTextUtilsTest, Uint64ToString) {
- EXPECT_EQ("123", quiche::QuicheTextUtils::Uint64ToString(123));
- EXPECT_EQ("1234", quiche::QuicheTextUtils::Uint64ToString(1234));
-}
-
TEST_F(QuicheTextUtilsTest, HexDump) {
// Verify output of the HexDump method is as expected.
char packet[] = {
diff --git a/chromium/net/third_party/quiche/src/common/quiche_endian.h b/chromium/net/third_party/quiche/src/common/quiche_endian.h
index f322b044062..032e2da4b93 100644
--- a/chromium/net/third_party/quiche/src/common/quiche_endian.h
+++ b/chromium/net/third_party/quiche/src/common/quiche_endian.h
@@ -19,8 +19,7 @@ enum Endianness {
};
// Provide utility functions that convert from/to network order (big endian)
-// to/from host order (can be either little or big endian depending on the
-// platform).
+// to/from host order (little endian).
class QUICHE_EXPORT_PRIVATE QuicheEndian {
public:
// Convert |x| from host order (little endian) to network order (big endian).
@@ -41,9 +40,6 @@ class QUICHE_EXPORT_PRIVATE QuicheEndian {
static uint32_t NetToHost32(uint32_t x) { return HostToNet32(x); }
static uint64_t NetToHost64(uint64_t x) { return HostToNet64(x); }
- // Returns true if current host order is little endian.
- static bool HostIsLittleEndian() { return true; }
-
// Left public for tests.
template <typename T>
static T PortableByteSwap(T input) {
diff --git a/chromium/net/third_party/quiche/src/epoll_server/simple_epoll_server.cc b/chromium/net/third_party/quiche/src/epoll_server/simple_epoll_server.cc
index 09831dbf764..28c301eb1d9 100644
--- a/chromium/net/third_party/quiche/src/epoll_server/simple_epoll_server.cc
+++ b/chromium/net/third_party/quiche/src/epoll_server/simple_epoll_server.cc
@@ -444,7 +444,7 @@ void SimpleEpollServer::RegisterAlarm(int64_t timeout_time_in_us, AlarmCB* ac) {
EPOLL_VLOG(4) << "RegisteringAlarm " << ac << " at : " << timeout_time_in_us;
CHECK(ac);
if (all_alarms_.find(ac) != all_alarms_.end()) {
- EPOLL_BUG << "Alarm already exists";
+ EPOLL_BUG(epoll_bug_1_1) << "Alarm already exists";
}
auto alarm_iter = alarm_map_.insert(std::make_pair(timeout_time_in_us, ac));
diff --git a/chromium/net/third_party/quiche/src/epoll_server/simple_epoll_server.h b/chromium/net/third_party/quiche/src/epoll_server/simple_epoll_server.h
index d2d36837826..85b3a08f1bc 100644
--- a/chromium/net/third_party/quiche/src/epoll_server/simple_epoll_server.h
+++ b/chromium/net/third_party/quiche/src/epoll_server/simple_epoll_server.h
@@ -487,6 +487,7 @@ class EPOLL_EXPORT_PRIVATE SimpleEpollServer {
// Summary:
// Returns true when the SimpleEpollServer() is being destroyed.
bool in_shutdown() const { return in_shutdown_; }
+ bool ShutdownCalled() const { return in_shutdown(); }
// Compatibility stub.
void Shutdown() {}
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
new file mode 100644
index 00000000000..5ea6045af22
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_adapter.h
@@ -0,0 +1,99 @@
+#ifndef QUICHE_HTTP2_ADAPTER_HTTP2_ADAPTER_H_
+#define QUICHE_HTTP2_ADAPTER_HTTP2_ADAPTER_H_
+
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "absl/types/span.h"
+#include "http2/adapter/http2_protocol.h"
+#include "http2/adapter/http2_session.h"
+#include "http2/adapter/http2_visitor_interface.h"
+
+namespace http2 {
+namespace adapter {
+
+// Http2Adapter is an HTTP/2-processing class that exposes an interface similar
+// to the nghttp2 library for processing the HTTP/2 wire format. As nghttp2
+// parses HTTP/2 frames and invokes callbacks on Http2Adapter, Http2Adapter then
+// invokes corresponding callbacks on its passed-in Http2VisitorInterface.
+// Http2Adapter is a base class shared between client-side and server-side
+// implementations.
+class Http2Adapter {
+ public:
+ enum class Perspective {
+ kClient,
+ kServer,
+ };
+
+ Http2Adapter(const Http2Adapter&) = delete;
+ Http2Adapter& operator=(const Http2Adapter&) = delete;
+
+ // Processes the incoming |bytes| as HTTP/2 and invokes callbacks on the
+ // |visitor_| as appropriate.
+ virtual ssize_t ProcessBytes(absl::string_view bytes) = 0;
+
+ // Submits the |settings| to be written to the peer, e.g., as part of the
+ // HTTP/2 connection preface.
+ virtual void SubmitSettings(absl::Span<const Http2Setting> settings) = 0;
+
+ // Submits a PRIORITY frame for the given stream.
+ virtual void SubmitPriorityForStream(Http2StreamId stream_id,
+ Http2StreamId parent_stream_id,
+ int weight,
+ bool exclusive) = 0;
+
+ // 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().
+ virtual void SubmitPing(Http2PingId ping_id) = 0;
+
+ // 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). To submit a GOAWAY with |last_accepted_stream_id| with the
+ // maximum stream ID, signaling imminent connection termination, call
+ // SubmitShutdownNotice() instead (though this is only possible server-side).
+ virtual void SubmitGoAway(Http2StreamId last_accepted_stream_id,
+ Http2ErrorCode error_code,
+ absl::string_view opaque_data) = 0;
+
+ // Submits a WINDOW_UPDATE for the given stream (a |stream_id| of 0 indicates
+ // a connection-level WINDOW_UPDATE).
+ virtual void SubmitWindowUpdate(Http2StreamId stream_id,
+ int window_increment) = 0;
+
+ // Submits a METADATA frame for the given stream (a |stream_id| of 0 indicates
+ // connection-level METADATA). If |fin|, the frame will also have the
+ // END_METADATA flag set.
+ virtual void SubmitMetadata(Http2StreamId stream_id, bool fin) = 0;
+
+ // Returns serialized bytes for writing to the wire.
+ // Writes should be submitted to Http2Adapter first, so that Http2Adapter
+ // has data to serialize and return in this method.
+ virtual std::string GetBytesToWrite(absl::optional<size_t> max_bytes) = 0;
+
+ // Returns the connection-level flow control window for the peer.
+ virtual int GetPeerConnectionWindow() const = 0;
+
+ // Marks the given amount of data as consumed for the given stream, which
+ // enables the nghttp2 layer to trigger WINDOW_UPDATEs as appropriate.
+ virtual void MarkDataConsumedForStream(Http2StreamId stream_id,
+ size_t num_bytes) = 0;
+
+ protected:
+ // Subclasses should expose a public factory method for constructing and
+ // initializing (via Initialize()) adapter instances.
+ explicit Http2Adapter(Http2VisitorInterface& visitor) : visitor_(visitor) {}
+ virtual ~Http2Adapter() {}
+
+ // Accessors. Do not transfer ownership.
+ Http2VisitorInterface& visitor() { return visitor_; }
+
+ private:
+ // Http2Adapter will invoke callbacks upon the |visitor_| while processing.
+ Http2VisitorInterface& visitor_;
+};
+
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_HTTP2_ADAPTER_H_
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
new file mode 100644
index 00000000000..18e8985ff4b
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.cc
@@ -0,0 +1,68 @@
+#include "http2/adapter/http2_protocol.h"
+
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+
+namespace http2 {
+namespace adapter {
+
+const char kHttp2MethodPseudoHeader[] = ":method";
+const char kHttp2SchemePseudoHeader[] = ":scheme";
+const char kHttp2AuthorityPseudoHeader[] = ":authority";
+const char kHttp2PathPseudoHeader[] = ":path";
+const char kHttp2StatusPseudoHeader[] = ":status";
+
+absl::string_view Http2SettingsIdToString(uint16_t id) {
+ switch (id) {
+ case Http2KnownSettingsId::HEADER_TABLE_SIZE:
+ return "SETTINGS_HEADER_TABLE_SIZE";
+ case Http2KnownSettingsId::ENABLE_PUSH:
+ return "SETTINGS_ENABLE_PUSH";
+ case Http2KnownSettingsId::MAX_CONCURRENT_STREAMS:
+ return "SETTINGS_MAX_CONCURRENT_STREAMS";
+ case Http2KnownSettingsId::INITIAL_WINDOW_SIZE:
+ return "SETTINGS_INITIAL_WINDOW_SIZE";
+ case Http2KnownSettingsId::MAX_FRAME_SIZE:
+ return "SETTINGS_MAX_FRAME_SIZE";
+ case Http2KnownSettingsId::MAX_HEADER_LIST_SIZE:
+ return "SETTINGS_MAX_HEADER_LIST_SIZE";
+ }
+ return "SETTINGS_UNKNOWN";
+}
+
+absl::string_view Http2ErrorCodeToString(Http2ErrorCode error_code) {
+ switch (error_code) {
+ case Http2ErrorCode::NO_ERROR:
+ return "NO_ERROR";
+ case Http2ErrorCode::PROTOCOL_ERROR:
+ return "PROTOCOL_ERROR";
+ case Http2ErrorCode::INTERNAL_ERROR:
+ return "INTERNAL_ERROR";
+ case Http2ErrorCode::FLOW_CONTROL_ERROR:
+ return "FLOW_CONTROL_ERROR";
+ case Http2ErrorCode::SETTINGS_TIMEOUT:
+ return "SETTINGS_TIMEOUT";
+ case Http2ErrorCode::STREAM_CLOSED:
+ return "STREAM_CLOSED";
+ case Http2ErrorCode::FRAME_SIZE_ERROR:
+ return "FRAME_SIZE_ERROR";
+ case Http2ErrorCode::REFUSED_STREAM:
+ return "REFUSED_STREAM";
+ case Http2ErrorCode::CANCEL:
+ return "CANCEL";
+ case Http2ErrorCode::COMPRESSION_ERROR:
+ return "COMPRESSION_ERROR";
+ case Http2ErrorCode::CONNECT_ERROR:
+ return "CONNECT_ERROR";
+ case Http2ErrorCode::ENHANCE_YOUR_CALM:
+ return "ENHANCE_YOUR_CALM";
+ case Http2ErrorCode::INADEQUATE_SECURITY:
+ return "INADEQUATE_SECURITY";
+ case Http2ErrorCode::HTTP_1_1_REQUIRED:
+ return "HTTP_1_1_REQUIRED";
+ }
+ return "UNKNOWN_ERROR";
+}
+
+} // namespace adapter
+} // namespace http2
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
new file mode 100644
index 00000000000..49e5f161620
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.h
@@ -0,0 +1,105 @@
+#ifndef QUICHE_HTTP2_ADAPTER_HTTP2_PROTOCOL_H_
+#define QUICHE_HTTP2_ADAPTER_HTTP2_PROTOCOL_H_
+
+#include <cstdint>
+#include <string>
+#include <utility>
+
+#include "base/integral_types.h"
+#include "absl/base/attributes.h"
+#include "absl/strings/string_view.h"
+
+namespace http2 {
+namespace adapter {
+
+// Represents an HTTP/2 stream ID, consistent with nghttp2.
+using Http2StreamId = int32_t;
+
+// Represents an HTTP/2 SETTINGS parameter as specified in RFC 7540 Section 6.5.
+using Http2SettingsId = uint16_t;
+
+// Represents the payload of an HTTP/2 PING frame.
+using Http2PingId = uint64_t;
+
+// 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>;
+
+// Represents an HTTP/2 SETTINGS key-value parameter.
+struct Http2Setting {
+ Http2SettingsId id;
+ uint32_t value;
+};
+
+// The maximum possible stream ID.
+const Http2StreamId kMaxStreamId = 0x7FFFFFFF;
+
+// The stream ID that represents the connection (e.g., for connection-level flow
+// control updates).
+const Http2StreamId kConnectionStreamId = 0;
+
+// The default value for the size of the largest frame payload, according to RFC
+// 7540 Section 6.5.2 (SETTINGS_MAX_FRAME_SIZE).
+const int kDefaultFramePayloadSizeLimit = 16 * 1024;
+
+// The default value for the initial stream flow control window size, according
+// to RFC 7540 Section 6.9.2.
+const int kDefaultInitialStreamWindowSize = 64 * 1024 - 1;
+
+// The pseudo-header fields as specified in RFC 7540 Section 8.1.2.3 (request)
+// and Section 8.1.2.4 (response).
+ABSL_CONST_INIT extern const char kHttp2MethodPseudoHeader[];
+ABSL_CONST_INIT extern const char kHttp2SchemePseudoHeader[];
+ABSL_CONST_INIT extern const char kHttp2AuthorityPseudoHeader[];
+ABSL_CONST_INIT extern const char kHttp2PathPseudoHeader[];
+ABSL_CONST_INIT extern const char kHttp2StatusPseudoHeader[];
+
+// HTTP/2 error codes as specified in RFC 7540 Section 7.
+enum class Http2ErrorCode {
+ NO_ERROR = 0x0,
+ PROTOCOL_ERROR = 0x1,
+ INTERNAL_ERROR = 0x2,
+ FLOW_CONTROL_ERROR = 0x3,
+ SETTINGS_TIMEOUT = 0x4,
+ STREAM_CLOSED = 0x5,
+ FRAME_SIZE_ERROR = 0x6,
+ REFUSED_STREAM = 0x7,
+ CANCEL = 0x8,
+ COMPRESSION_ERROR = 0x9,
+ CONNECT_ERROR = 0xA,
+ ENHANCE_YOUR_CALM = 0xB,
+ INADEQUATE_SECURITY = 0xC,
+ HTTP_1_1_REQUIRED = 0xD,
+ MAX_ERROR_CODE = HTTP_1_1_REQUIRED,
+};
+
+// The SETTINGS parameters defined in RFC 7540 Section 6.5.2. Endpoints may send
+// SETTINGS parameters outside of these definitions as per RFC 7540 Section 5.5.
+// This is explicitly an enum instead of an enum class for ease of implicit
+// conversion to the underlying Http2SettingsId type and use with non-standard
+// extension SETTINGS parameters.
+enum Http2KnownSettingsId : Http2SettingsId {
+ HEADER_TABLE_SIZE = 0x1,
+ MIN_SETTING = HEADER_TABLE_SIZE,
+ ENABLE_PUSH = 0x2,
+ MAX_CONCURRENT_STREAMS = 0x3,
+ INITIAL_WINDOW_SIZE = 0x4,
+ MAX_FRAME_SIZE = 0x5,
+ MAX_HEADER_LIST_SIZE = 0x6,
+ MAX_SETTING = MAX_HEADER_LIST_SIZE
+};
+
+// Returns a human-readable string representation of the given SETTINGS |id| for
+// logging/debugging. Returns "SETTINGS_UNKNOWN" for IDs outside of the RFC 7540
+// Section 6.5.2 definitions.
+absl::string_view Http2SettingsIdToString(uint16_t id);
+
+// Returns a human-readable string representation of the given |error_code| for
+// logging/debugging. Returns "UNKNOWN_ERROR" for errors outside of RFC 7540
+// Section 7 definitions.
+absl::string_view Http2ErrorCodeToString(Http2ErrorCode error_code);
+
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_HTTP2_PROTOCOL_H_
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
new file mode 100644
index 00000000000..ddbed4477b5
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_session.h
@@ -0,0 +1,41 @@
+#ifndef QUICHE_HTTP2_ADAPTER_HTTP2_SESSION_H_
+#define QUICHE_HTTP2_ADAPTER_HTTP2_SESSION_H_
+
+#include <cstdint>
+
+#include "absl/strings/string_view.h"
+#include "http2/adapter/http2_protocol.h"
+
+namespace http2 {
+namespace adapter {
+
+struct Http2SessionCallbacks {};
+
+// A class to represent the state of a single HTTP/2 connection.
+class Http2Session {
+ public:
+ Http2Session() = default;
+ virtual ~Http2Session() {}
+
+ virtual ssize_t ProcessBytes(absl::string_view bytes) = 0;
+
+ virtual int Consume(Http2StreamId stream_id, size_t num_bytes) = 0;
+
+ virtual bool want_read() const = 0;
+ virtual bool want_write() const = 0;
+ 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
+
+#endif // QUICHE_HTTP2_ADAPTER_HTTP2_SESSION_H_
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
new file mode 100644
index 00000000000..40deeb29332
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_util.cc
@@ -0,0 +1,40 @@
+#include "http2/adapter/http2_util.h"
+
+namespace http2 {
+namespace adapter {
+
+spdy::SpdyErrorCode TranslateErrorCode(Http2ErrorCode code) {
+ switch (code) {
+ case Http2ErrorCode::NO_ERROR:
+ return spdy::ERROR_CODE_NO_ERROR;
+ case Http2ErrorCode::PROTOCOL_ERROR:
+ return spdy::ERROR_CODE_PROTOCOL_ERROR;
+ case Http2ErrorCode::INTERNAL_ERROR:
+ return spdy::ERROR_CODE_INTERNAL_ERROR;
+ case Http2ErrorCode::FLOW_CONTROL_ERROR:
+ return spdy::ERROR_CODE_FLOW_CONTROL_ERROR;
+ case Http2ErrorCode::SETTINGS_TIMEOUT:
+ return spdy::ERROR_CODE_SETTINGS_TIMEOUT;
+ case Http2ErrorCode::STREAM_CLOSED:
+ return spdy::ERROR_CODE_STREAM_CLOSED;
+ case Http2ErrorCode::FRAME_SIZE_ERROR:
+ return spdy::ERROR_CODE_FRAME_SIZE_ERROR;
+ case Http2ErrorCode::REFUSED_STREAM:
+ return spdy::ERROR_CODE_REFUSED_STREAM;
+ case Http2ErrorCode::CANCEL:
+ return spdy::ERROR_CODE_CANCEL;
+ case Http2ErrorCode::COMPRESSION_ERROR:
+ return spdy::ERROR_CODE_COMPRESSION_ERROR;
+ case Http2ErrorCode::CONNECT_ERROR:
+ return spdy::ERROR_CODE_CONNECT_ERROR;
+ case Http2ErrorCode::ENHANCE_YOUR_CALM:
+ return spdy::ERROR_CODE_ENHANCE_YOUR_CALM;
+ case Http2ErrorCode::INADEQUATE_SECURITY:
+ return spdy::ERROR_CODE_INADEQUATE_SECURITY;
+ case Http2ErrorCode::HTTP_1_1_REQUIRED:
+ return spdy::ERROR_CODE_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
new file mode 100644
index 00000000000..e9ae2a59561
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_util.h
@@ -0,0 +1,15 @@
+#ifndef QUICHE_HTTP2_ADAPTER_HTTP2_UTIL_H_
+#define QUICHE_HTTP2_ADAPTER_HTTP2_UTIL_H_
+
+#include "http2/adapter/http2_protocol.h"
+#include "spdy/core/spdy_protocol.h"
+
+namespace http2 {
+namespace adapter {
+
+spdy::SpdyErrorCode TranslateErrorCode(Http2ErrorCode code);
+
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_HTTP2_UTIL_H_
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
new file mode 100644
index 00000000000..765e9f43896
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_visitor_interface.h
@@ -0,0 +1,178 @@
+#ifndef QUICHE_HTTP2_ADAPTER_HTTP2_VISITOR_INTERFACE_H_
+#define QUICHE_HTTP2_ADAPTER_HTTP2_VISITOR_INTERFACE_H_
+
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "http2/adapter/http2_protocol.h"
+
+namespace http2 {
+namespace adapter {
+
+// Http2VisitorInterface contains callbacks for receiving HTTP/2-level events. A
+// processor like NghttpAdapter parses HTTP/2 frames and invokes the callbacks
+// on an instance of this interface. Prefer a void return type for these
+// callbacks, instead setting output parameters as needed.
+//
+// Example sequences of calls/events:
+// GET:
+// - OnBeginHeadersForStream()
+// - OnHeaderForStream()
+// - OnEndHeadersForStream()
+// - OnEndStream()
+//
+// POST:
+// - OnBeginHeadersForStream()
+// - OnHeaderForStream()
+// - OnEndHeadersForStream()
+// - OnBeginDataForStream()
+// - OnDataForStream()
+// - OnEndStream()
+//
+// Request canceled mid-stream, e.g, with error code CANCEL:
+// - OnBeginHeadersForStream()
+// - OnHeaderForStream()
+// - OnEndHeadersForStream()
+// - OnRstStream()
+// - OnAbortStream()
+//
+// Request closed mid-stream, e.g., with error code NO_ERROR:
+// - OnBeginHeadersForStream()
+// - OnHeaderForStream()
+// - OnEndHeadersForStream()
+// - 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.
+class Http2VisitorInterface {
+ public:
+ Http2VisitorInterface(const Http2VisitorInterface&) = delete;
+ Http2VisitorInterface& operator=(const Http2VisitorInterface&) = delete;
+ virtual ~Http2VisitorInterface() = default;
+
+ // Called when a connection-level processing error has been encountered.
+ virtual void OnConnectionError() = 0;
+
+ // Called when a non-ack SETTINGS frame is received.
+ virtual void OnSettingsStart() = 0;
+
+ // Called for each SETTINGS id-value pair.
+ virtual void OnSetting(Http2Setting setting) = 0;
+
+ // Called at the end of a non-ack SETTINGS frame.
+ virtual void OnSettingsEnd() = 0;
+
+ // Called when a SETTINGS ack frame is received.
+ virtual void OnSettingsAck() = 0;
+
+ // Called when the connection receives the header block for a HEADERS frame on
+ // a stream but has not yet parsed individual headers.
+ virtual void OnBeginHeadersForStream(Http2StreamId stream_id) = 0;
+
+ // Called when the connection receives the header |key| and |value| for a
+ // stream. The HTTP/2 pseudo-headers defined in RFC 7540 Sections 8.1.2.3 and
+ // 8.1.2.4 are also conveyed in this callback. This method is called after
+ // OnBeginHeadersForStream().
+ virtual void OnHeaderForStream(Http2StreamId stream_id, absl::string_view key,
+ absl::string_view value) = 0;
+
+ // Called when the connection has received the complete header block for a
+ // logical HEADERS frame on a stream (which may contain CONTINUATION frames,
+ // transparent to the user).
+ virtual void OnEndHeadersForStream(Http2StreamId stream_id) = 0;
+
+ // Called when the connection receives the beginning of a DATA frame. The data
+ // payload will be provided via subsequent calls to OnDataForStream().
+ virtual void OnBeginDataForStream(Http2StreamId stream_id,
+ size_t payload_length) = 0;
+
+ // Called when the connection receives some |data| (as part of a DATA frame
+ // payload) for a stream.
+ virtual void OnDataForStream(Http2StreamId stream_id,
+ absl::string_view data) = 0;
+
+ // Called when the peer sends the END_STREAM flag on a stream, indicating that
+ // the peer will not send additional headers or data for that stream.
+ 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().
+ 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,
+ Http2ErrorCode error_code) = 0;
+
+ // Called when the connection receives a PRIORITY frame.
+ virtual void OnPriorityForStream(Http2StreamId stream_id,
+ Http2StreamId parent_stream_id, int weight,
+ bool exclusive) = 0;
+
+ // Called when the connection receives a PING frame.
+ virtual void OnPing(Http2PingId ping_id, bool is_ack) = 0;
+
+ // Called when the connection receives a PUSH_PROMISE frame. The server push
+ // request headers follow in calls to OnHeaderForStream() with |stream_id|.
+ virtual void OnPushPromiseForStream(Http2StreamId stream_id,
+ Http2StreamId promised_stream_id) = 0;
+
+ // Called when the connection receives a GOAWAY frame.
+ virtual void OnGoAway(Http2StreamId last_accepted_stream_id,
+ Http2ErrorCode error_code,
+ absl::string_view opaque_data) = 0;
+
+ // Called when the connection receives a WINDOW_UPDATE frame. For
+ // connection-level window updates, the |stream_id| will be 0.
+ virtual void OnWindowUpdate(Http2StreamId stream_id,
+ int window_increment) = 0;
+
+ // Called when the connection is ready to send data for a stream. The
+ // implementation should write at most |length| bytes of the data payload to
+ // the |destination_buffer| and set |end_stream| to true IFF there will be no
+ // more data sent on this stream. Sets |written| to the number of bytes
+ // written to the |destination_buffer| or a negative value if an error occurs.
+ virtual void OnReadyToSendDataForStream(Http2StreamId stream_id,
+ char* destination_buffer,
+ size_t length,
+ ssize_t* written,
+ bool* end_stream) = 0;
+
+ // Called when the connection is ready to write metadata for |stream_id| to
+ // the wire. The implementation should write at most |length| bytes of the
+ // serialized metadata payload to the |buffer| and set |written| to the number
+ // of bytes written or a negative value if there was an error.
+ virtual void OnReadyToSendMetadataForStream(Http2StreamId stream_id,
+ char* buffer, size_t length,
+ ssize_t* written) = 0;
+
+ // Called when the connection receives the beginning of a METADATA frame
+ // (which may itself be the middle of a logical metadata block). The metadata
+ // payload will be provided via subsequent calls to OnMetadataForStream().
+ virtual void OnBeginMetadataForStream(Http2StreamId stream_id,
+ size_t payload_length) = 0;
+
+ // Called when the connection receives |metadata| as part of a METADATA frame
+ // payload for a stream.
+ virtual void OnMetadataForStream(Http2StreamId stream_id,
+ absl::string_view metadata) = 0;
+
+ // Called when the connection has finished receiving a logical metadata block
+ // for a stream. Note that there may be multiple metadata blocks for a stream.
+ virtual void OnMetadataEndForStream(Http2StreamId stream_id) = 0;
+
+ protected:
+ Http2VisitorInterface() = default;
+};
+
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_HTTP2_VISITOR_INTERFACE_H_
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
new file mode 100644
index 00000000000..a5c83712fd7
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/mock_http2_visitor.h
@@ -0,0 +1,124 @@
+#ifndef QUICHE_HTTP2_ADAPTER_MOCK_HTTP2_VISITOR_INTERFACE_H_
+#define QUICHE_HTTP2_ADAPTER_MOCK_HTTP2_VISITOR_INTERFACE_H_
+
+#include "http2/adapter/http2_visitor_interface.h"
+#include "common/platform/api/quiche_test.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+
+// A mock visitor class, for use in tests.
+class MockHttp2Visitor : public Http2VisitorInterface {
+ public:
+ MockHttp2Visitor() = default;
+
+ MOCK_METHOD(void, OnConnectionError, (), (override));
+ MOCK_METHOD(void, OnSettingsStart, (), (override));
+ MOCK_METHOD(void, OnSetting, (Http2Setting setting), (override));
+ MOCK_METHOD(void, OnSettingsEnd, (), (override));
+ MOCK_METHOD(void, OnSettingsAck, (), (override));
+ MOCK_METHOD(void,
+ OnBeginHeadersForStream,
+ (Http2StreamId stream_id),
+ (override));
+
+ MOCK_METHOD(void,
+ OnHeaderForStream,
+ (Http2StreamId stream_id,
+ absl::string_view key,
+ absl::string_view value),
+ (override));
+
+ MOCK_METHOD(void,
+ OnEndHeadersForStream,
+ (Http2StreamId stream_id),
+ (override));
+
+ MOCK_METHOD(void,
+ OnBeginDataForStream,
+ (Http2StreamId stream_id, size_t payload_length),
+ (override));
+
+ MOCK_METHOD(void,
+ OnDataForStream,
+ (Http2StreamId stream_id, absl::string_view data),
+ (override));
+
+ MOCK_METHOD(void, OnEndStream, (Http2StreamId stream_id), (override));
+
+ MOCK_METHOD(void,
+ OnRstStream,
+ (Http2StreamId stream_id, Http2ErrorCode error_code),
+ (override));
+
+ MOCK_METHOD(void, OnCloseStream, (Http2StreamId stream_id), (override));
+
+ MOCK_METHOD(void,
+ OnAbortStream,
+ (Http2StreamId stream_id, Http2ErrorCode error_code),
+ (override));
+
+ MOCK_METHOD(void,
+ OnPriorityForStream,
+ (Http2StreamId stream_id,
+ Http2StreamId parent_stream_id,
+ int weight,
+ bool exclusive),
+ (override));
+
+ MOCK_METHOD(void, OnPing, (Http2PingId ping_id, bool is_ack), (override));
+
+ MOCK_METHOD(void,
+ OnPushPromiseForStream,
+ (Http2StreamId stream_id, Http2StreamId promised_stream_id),
+ (override));
+
+ MOCK_METHOD(void,
+ OnGoAway,
+ (Http2StreamId last_accepted_stream_id,
+ Http2ErrorCode error_code,
+ absl::string_view opaque_data),
+ (override));
+
+ MOCK_METHOD(void,
+ OnWindowUpdate,
+ (Http2StreamId stream_id, int window_increment),
+ (override));
+
+ MOCK_METHOD(void,
+ OnReadyToSendDataForStream,
+ (Http2StreamId stream_id,
+ char* destination_buffer,
+ size_t length,
+ ssize_t* written,
+ bool* end_stream),
+ (override));
+
+ MOCK_METHOD(
+ void,
+ OnReadyToSendMetadataForStream,
+ (Http2StreamId stream_id, char* buffer, size_t length, ssize_t* written),
+ (override));
+
+ MOCK_METHOD(void,
+ OnBeginMetadataForStream,
+ (Http2StreamId stream_id, size_t payload_length),
+ (override));
+
+ MOCK_METHOD(void,
+ OnMetadataForStream,
+ (Http2StreamId stream_id, absl::string_view metadata),
+ (override));
+
+ MOCK_METHOD(void,
+ OnMetadataEndForStream,
+ (Http2StreamId stream_id),
+ (override));
+};
+
+} // namespace test
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_MOCK_HTTP2_VISITOR_INTERFACE_H_
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
new file mode 100644
index 00000000000..337f230b796
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.cc
@@ -0,0 +1,189 @@
+#include "http2/adapter/nghttp2_callbacks.h"
+
+#include <cstdint>
+#include <cstring>
+
+#include "absl/strings/string_view.h"
+#include "http2/adapter/http2_protocol.h"
+#include "http2/adapter/http2_visitor_interface.h"
+#include "http2/adapter/nghttp2_util.h"
+#include "third_party/nghttp2/nghttp2.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 {
+
+int OnBeginFrame(nghttp2_session* /* session */,
+ const nghttp2_frame_hd* header,
+ void* user_data) {
+ auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
+ if (header->type == NGHTTP2_DATA) {
+ visitor->OnBeginDataForStream(header->stream_id, header->length);
+ }
+ return 0;
+}
+
+int OnFrameReceived(nghttp2_session* /* session */,
+ const nghttp2_frame* frame,
+ void* user_data) {
+ auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
+ const Http2StreamId stream_id = frame->hd.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
+ // callbacks. This callback handles the point at which the entire logical
+ // frame has been received and processed.
+ case NGHTTP2_DATA:
+ if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
+ visitor->OnEndStream(stream_id);
+ }
+ break;
+ case NGHTTP2_HEADERS: {
+ if (frame->hd.flags & NGHTTP2_FLAG_END_HEADERS) {
+ visitor->OnEndHeadersForStream(stream_id);
+ }
+ if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
+ visitor->OnEndStream(stream_id);
+ }
+ break;
+ }
+ case NGHTTP2_PRIORITY: {
+ nghttp2_priority_spec priority_spec = frame->priority.pri_spec;
+ visitor->OnPriorityForStream(stream_id, priority_spec.stream_id,
+ priority_spec.weight,
+ priority_spec.exclusive != 0);
+ break;
+ }
+ case NGHTTP2_RST_STREAM: {
+ visitor->OnRstStream(stream_id,
+ ToHttp2ErrorCode(frame->rst_stream.error_code));
+ break;
+ }
+ case NGHTTP2_SETTINGS:
+ if (frame->hd.flags & NGHTTP2_FLAG_ACK) {
+ visitor->OnSettingsAck();
+ } else {
+ visitor->OnSettingsStart();
+ for (int i = 0; i < frame->settings.niv; ++i) {
+ nghttp2_settings_entry entry = frame->settings.iv[i];
+ // The nghttp2_settings_entry uses int32_t for the ID; we must cast.
+ visitor->OnSetting(Http2Setting{
+ .id = static_cast<Http2SettingsId>(entry.settings_id),
+ .value = entry.value});
+ }
+ visitor->OnSettingsEnd();
+ }
+ break;
+ case NGHTTP2_PUSH_PROMISE:
+ // This case is handled by headers-related callbacks:
+ // 1. visitor->OnPushPromiseForStream() is invoked in the client-side
+ // OnHeadersStart() adapter callback, as nghttp2 only allows clients
+ // to receive PUSH_PROMISE frames.
+ // 2. visitor->OnHeaderForStream() is invoked for each server push
+ // request header in the PUSH_PROMISE header block.
+ // 3. This switch statement is reached once all server push request
+ // headers have been parsed.
+ break;
+ case NGHTTP2_PING: {
+ Http2PingId ping_id;
+ std::memcpy(&ping_id, frame->ping.opaque_data, sizeof(Http2PingId));
+ visitor->OnPing(quiche::QuicheEndian::NetToHost64(ping_id),
+ (frame->hd.flags & NGHTTP2_FLAG_ACK) != 0);
+ break;
+ }
+ case NGHTTP2_GOAWAY: {
+ absl::string_view opaque_data(
+ reinterpret_cast<const char*>(frame->goaway.opaque_data),
+ frame->goaway.opaque_data_len);
+ visitor->OnGoAway(frame->goaway.last_stream_id,
+ ToHttp2ErrorCode(frame->goaway.error_code),
+ opaque_data);
+ break;
+ }
+ case NGHTTP2_WINDOW_UPDATE: {
+ visitor->OnWindowUpdate(stream_id,
+ frame->window_update.window_size_increment);
+ break;
+ }
+ case NGHTTP2_CONTINUATION:
+ // This frame type should not be passed to any callbacks, according to
+ // https://nghttp2.org/documentation/enums.html#c.NGHTTP2_CONTINUATION.
+ QUICHE_LOG(ERROR) << "Unexpected receipt of NGHTTP2_CONTINUATION type!";
+ break;
+ case NGHTTP2_ALTSVC:
+ break;
+ case NGHTTP2_ORIGIN:
+ break;
+ }
+
+ return 0;
+}
+
+int OnBeginHeaders(nghttp2_session* /* session */,
+ const nghttp2_frame* frame,
+ void* user_data) {
+ auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
+ visitor->OnBeginHeadersForStream(frame->hd.stream_id);
+ return 0;
+}
+
+int OnHeader(nghttp2_session* /* session */,
+ const nghttp2_frame* frame,
+ nghttp2_rcbuf* name,
+ nghttp2_rcbuf* value,
+ uint8_t flags,
+ void* user_data) {
+ auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
+ visitor->OnHeaderForStream(frame->hd.stream_id, ToStringView(name),
+ ToStringView(value));
+ return 0;
+}
+
+int OnDataChunk(nghttp2_session* /* session */,
+ uint8_t flags,
+ Http2StreamId stream_id,
+ const uint8_t* data,
+ size_t len,
+ void* user_data) {
+ auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
+ visitor->OnDataForStream(
+ stream_id, absl::string_view(reinterpret_cast<const char*>(data), len));
+ return 0;
+}
+
+int OnStreamClosed(nghttp2_session* /* session */,
+ Http2StreamId stream_id,
+ 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));
+ }
+ return 0;
+}
+
+ssize_t OnReadyToReadDataForStream(nghttp2_session* /* session */,
+ Http2StreamId stream_id,
+ uint8_t* dest_buffer,
+ size_t max_length,
+ uint32_t* data_flags,
+ nghttp2_data_source* source,
+ void* user_data) {
+ auto* visitor = static_cast<Http2VisitorInterface*>(source->ptr);
+ ssize_t bytes_to_send = 0;
+ bool end_stream = false;
+ visitor->OnReadyToSendDataForStream(stream_id,
+ reinterpret_cast<char*>(dest_buffer),
+ max_length, &bytes_to_send, &end_stream);
+ if (bytes_to_send >= 0 && end_stream) {
+ *data_flags |= NGHTTP2_DATA_FLAG_EOF;
+ }
+ return bytes_to_send;
+}
+
+} // 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
new file mode 100644
index 00000000000..7e6ce7c38d2
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.h
@@ -0,0 +1,52 @@
+#ifndef QUICHE_HTTP2_ADAPTER_NGHTTP2_CALLBACKS_H_
+#define QUICHE_HTTP2_ADAPTER_NGHTTP2_CALLBACKS_H_
+
+#include "http2/adapter/http2_protocol.h"
+#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
+
+namespace http2 {
+namespace adapter {
+
+// The following functions are nghttp2 callbacks that Nghttp2Adapter sets at the
+// beginning of its lifetime. It is expected that |user_data| holds an
+// Http2VisitorInterface.
+
+// Callback once a frame header has been received.
+int OnBeginFrame(nghttp2_session* session, const nghttp2_frame_hd* header,
+ void* user_data);
+
+// Callback once a complete frame has been received.
+int OnFrameReceived(nghttp2_session* session, const nghttp2_frame* frame,
+ void* user_data);
+
+// Callback at the start of a frame carrying headers.
+int OnBeginHeaders(nghttp2_session* session,
+ const nghttp2_frame* frame,
+ void* user_data);
+
+// Callback once a name-value header has been received.
+int OnHeader(nghttp2_session* session, const nghttp2_frame* frame,
+ nghttp2_rcbuf* name, nghttp2_rcbuf* value, uint8_t flags,
+ void* user_data);
+
+// Callback once a chunk of data (from a DATA frame payload) has been received.
+int OnDataChunk(nghttp2_session* session, uint8_t flags,
+ Http2StreamId stream_id, const uint8_t* data, size_t len,
+ void* user_data);
+
+// Callback once a stream has been closed.
+int OnStreamClosed(nghttp2_session* session, Http2StreamId stream_id,
+ uint32_t error_code, void* user_data);
+
+// Callback once nghttp2 is ready to read data from |source| into |dest_buffer|.
+ssize_t OnReadyToReadDataForStream(nghttp2_session* session,
+ Http2StreamId stream_id,
+ uint8_t* dest_buffer, size_t max_length,
+ uint32_t* data_flags,
+ nghttp2_data_source* source,
+ void* user_data);
+
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_NGHTTP2_CALLBACKS_H_
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
new file mode 100644
index 00000000000..e1341481ae5
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.cc
@@ -0,0 +1,82 @@
+#include "http2/adapter/nghttp2_util.h"
+
+#include <cstdint>
+
+#include "absl/strings/string_view.h"
+#include "http2/adapter/http2_protocol.h"
+#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
+#include "common/platform/api/quiche_logging.h"
+
+namespace http2 {
+namespace adapter {
+
+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));
+}
+
+absl::string_view ToStringView(nghttp2_rcbuf* rc_buffer) {
+ nghttp2_vec buffer = nghttp2_rcbuf_get_buf(rc_buffer);
+ return absl::string_view(reinterpret_cast<const char*>(buffer.base),
+ buffer.len);
+}
+
+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) {
+ 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;
+ nghttp2_nvs.push_back(std::move(header));
+ }
+
+ return nghttp2_nvs;
+}
+
+std::vector<nghttp2_nv> GetResponseNghttp2Nvs(
+ const spdy::Http2HeaderBlock& headers,
+ absl::string_view response_code) {
+ // Allocate enough for all headers and also the :status pseudoheader.
+ const int num_headers = headers.size();
+ auto nghttp2_nvs = std::vector<nghttp2_nv>(num_headers + 1);
+
+ // Add the :status pseudoheader first.
+ nghttp2_nv status;
+ status.name = ToUint8Ptr(kHttp2StatusPseudoHeader);
+ status.namelen = strlen(kHttp2StatusPseudoHeader);
+ status.value = ToUint8Ptr(response_code.data());
+ status.valuelen = response_code.size();
+ status.flags = NGHTTP2_FLAG_NONE;
+ nghttp2_nvs.push_back(std::move(status));
+
+ // Add the remaining headers.
+ for (const auto header_pair : headers) {
+ nghttp2_nv header;
+ header.name = ToUint8Ptr(header_pair.first.data());
+ header.namelen = header_pair.first.size();
+ header.value = ToUint8Ptr(header_pair.second.data());
+ header.valuelen = header_pair.second.size();
+ header.flags = NGHTTP2_FLAG_NONE;
+ nghttp2_nvs.push_back(std::move(header));
+ }
+
+ return nghttp2_nvs;
+}
+
+Http2ErrorCode ToHttp2ErrorCode(uint32_t wire_error_code) {
+ if (wire_error_code > static_cast<int>(Http2ErrorCode::MAX_ERROR_CODE)) {
+ return Http2ErrorCode::INTERNAL_ERROR;
+ }
+ return static_cast<Http2ErrorCode>(wire_error_code);
+}
+
+} // namespace adapter
+} // namespace http2
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
new file mode 100644
index 00000000000..3fcbfcd068c
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.h
@@ -0,0 +1,48 @@
+// Various utility/conversion functions for compatibility with the nghttp2 API.
+
+#ifndef QUICHE_HTTP2_ADAPTER_NGHTTP2_UTIL_H_
+#define QUICHE_HTTP2_ADAPTER_NGHTTP2_UTIL_H_
+
+#include <cstdint>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "absl/types/span.h"
+#include "http2/adapter/http2_protocol.h"
+#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
+#include "spdy/core/spdy_header_block.h"
+
+namespace http2 {
+namespace adapter {
+
+// Return codes to represent various errors.
+inline constexpr int kStreamCallbackFailureStatus =
+ NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+inline constexpr int kCancelStatus = NGHTTP2_ERR_CANCEL;
+
+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);
+
+// Returns the nghttp2 header structure from the given request |headers|, which
+// must have the correct pseudoheaders preceding other headers.
+std::vector<nghttp2_nv> GetRequestNghttp2Nvs(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
+// |response_code| is passed in separately from |headers| for lifetime reasons.
+std::vector<nghttp2_nv> GetResponseNghttp2Nvs(
+ const spdy::Http2HeaderBlock& headers,
+ absl::string_view response_code);
+
+// Returns the HTTP/2 error code corresponding to the raw wire value, as defined
+// in RFC 7540 Section 7. Unrecognized error codes are treated as INTERNAL_ERROR
+// based on the RFC 7540 Section 7 suggestion.
+Http2ErrorCode ToHttp2ErrorCode(uint32_t wire_error_code);
+
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_NGHTTP2_UTIL_H_
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
new file mode 100644
index 00000000000..7b7d2a2229b
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.cc
@@ -0,0 +1,164 @@
+#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 "spdy/core/spdy_protocol.h"
+
+namespace http2 {
+namespace adapter {
+
+namespace {
+
+using spdy::SpdyFrameIR;
+using spdy::SpdyGoAwayIR;
+using spdy::SpdyPingIR;
+using spdy::SpdyPriorityIR;
+using spdy::SpdySettingsIR;
+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,
+ Options options) {
+ // Using `new` to access a non-public constructor.
+ return absl::WrapUnique(new OgHttp2Adapter(visitor, std::move(options)));
+}
+
+OgHttp2Adapter::~OgHttp2Adapter() {}
+
+ssize_t OgHttp2Adapter::ProcessBytes(absl::string_view bytes) {
+ return session_->ProcessBytes(bytes);
+}
+
+void OgHttp2Adapter::SubmitSettings(absl::Span<const Http2Setting> settings) {
+ auto settings_ir = absl::make_unique<SpdySettingsIR>();
+ for (const Http2Setting& setting : settings) {
+ settings_ir->AddSetting(setting.id, setting.value);
+ }
+ session_->EnqueueFrame(std::move(settings_ir));
+}
+
+void OgHttp2Adapter::SubmitPriorityForStream(Http2StreamId stream_id,
+ Http2StreamId parent_stream_id,
+ int weight,
+ bool exclusive) {
+ session_->EnqueueFrame(absl::make_unique<SpdyPriorityIR>(
+ stream_id, parent_stream_id, weight, exclusive));
+}
+
+void OgHttp2Adapter::SubmitPing(Http2PingId ping_id) {
+ session_->EnqueueFrame(absl::make_unique<SpdyPingIR>(ping_id));
+}
+
+void OgHttp2Adapter::SubmitGoAway(Http2StreamId last_accepted_stream_id,
+ Http2ErrorCode error_code,
+ absl::string_view opaque_data) {
+ session_->EnqueueFrame(absl::make_unique<SpdyGoAwayIR>(
+ last_accepted_stream_id, TranslateErrorCode(error_code),
+ std::string(opaque_data)));
+}
+void OgHttp2Adapter::SubmitWindowUpdate(Http2StreamId stream_id,
+ int window_increment) {
+ session_->EnqueueFrame(
+ absl::make_unique<SpdyWindowUpdateIR>(stream_id, window_increment));
+}
+
+void OgHttp2Adapter::SubmitMetadata(Http2StreamId stream_id, bool fin) {
+ SPDY_BUG(oghttp2_submit_metadata) << "Not implemented";
+}
+
+std::string OgHttp2Adapter::GetBytesToWrite(absl::optional<size_t> max_bytes) {
+ return session_->GetBytesToWrite(max_bytes);
+}
+
+int OgHttp2Adapter::GetPeerConnectionWindow() const {
+ return session_->GetRemoteWindowSize();
+}
+
+void OgHttp2Adapter::MarkDataConsumedForStream(Http2StreamId stream_id,
+ size_t num_bytes) {
+ session_->Consume(stream_id, num_bytes);
+}
+
+const Http2Session& OgHttp2Adapter::session() const {
+ return *session_;
+}
+
+OgHttp2Adapter::OgHttp2Adapter(Http2VisitorInterface& visitor, Options options)
+ : Http2Adapter(visitor),
+ session_(absl::make_unique<OgHttp2Session>(visitor, std::move(options))) {
+}
+
+} // namespace adapter
+} // namespace http2
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
new file mode 100644
index 00000000000..1f32cfc6ddd
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.h
@@ -0,0 +1,53 @@
+#ifndef QUICHE_HTTP2_ADAPTER_OGHTTP2_ADAPTER_H_
+#define QUICHE_HTTP2_ADAPTER_OGHTTP2_ADAPTER_H_
+
+#include <memory>
+
+#include "http2/adapter/http2_adapter.h"
+#include "http2/adapter/http2_session.h"
+
+namespace http2 {
+namespace adapter {
+
+class OgHttp2Adapter : public Http2Adapter {
+ public:
+ struct Options {
+ Perspective context;
+ };
+ static std::unique_ptr<OgHttp2Adapter> Create(Http2VisitorInterface& visitor,
+ Options options);
+
+ ~OgHttp2Adapter();
+
+ // From Http2Adapter.
+ ssize_t ProcessBytes(absl::string_view bytes) override;
+ void SubmitSettings(absl::Span<const Http2Setting> settings) override;
+ void SubmitPriorityForStream(Http2StreamId stream_id,
+ Http2StreamId parent_stream_id,
+ int weight,
+ bool exclusive) override;
+ void SubmitPing(Http2PingId ping_id) override;
+ void SubmitGoAway(Http2StreamId last_accepted_stream_id,
+ Http2ErrorCode error_code,
+ absl::string_view opaque_data) override;
+ void SubmitWindowUpdate(Http2StreamId stream_id,
+ int window_increment) override;
+ void SubmitMetadata(Http2StreamId stream_id, bool fin) override;
+ std::string GetBytesToWrite(absl::optional<size_t> max_bytes) override;
+ int GetPeerConnectionWindow() const override;
+ void MarkDataConsumedForStream(Http2StreamId stream_id,
+ size_t num_bytes) override;
+
+ const Http2Session& session() const;
+
+ private:
+ OgHttp2Adapter(Http2VisitorInterface& visitor, Options options);
+
+ class OgHttp2Session;
+ std::unique_ptr<OgHttp2Session> session_;
+};
+
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_OGHTTP2_ADAPTER_H_
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
new file mode 100644
index 00000000000..3c04c06d7ec
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter_test.cc
@@ -0,0 +1,88 @@
+#include "http2/adapter/oghttp2_adapter.h"
+
+#include "http2/adapter/mock_http2_visitor.h"
+#include "http2/adapter/test_utils.h"
+#include "common/platform/api/quiche_test.h"
+#include "spdy/platform/api/spdy_test_helpers.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+namespace {
+
+class OgHttp2AdapterTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ OgHttp2Adapter::Options options;
+ adapter_ = OgHttp2Adapter::Create(http2_visitor_, options);
+ }
+
+ testing::StrictMock<MockHttp2Visitor> http2_visitor_;
+ std::unique_ptr<OgHttp2Adapter> adapter_;
+};
+
+TEST_F(OgHttp2AdapterTest, ProcessBytes) {
+ EXPECT_SPDY_BUG(adapter_->ProcessBytes("fake data"), "Not implemented");
+}
+
+TEST_F(OgHttp2AdapterTest, SubmitMetadata) {
+ EXPECT_SPDY_BUG(adapter_->SubmitMetadata(3, true), "Not implemented");
+}
+
+TEST_F(OgHttp2AdapterTest, GetPeerConnectionWindow) {
+ int peer_window = 0;
+ EXPECT_SPDY_BUG(peer_window = adapter_->GetPeerConnectionWindow(),
+ "Not implemented");
+ EXPECT_GT(peer_window, 0);
+}
+
+TEST_F(OgHttp2AdapterTest, MarkDataConsumedForStream) {
+ EXPECT_SPDY_BUG(adapter_->MarkDataConsumedForStream(1, 11),
+ "Stream 1 not found");
+}
+
+TEST_F(OgHttp2AdapterTest, TestSerialize) {
+ EXPECT_FALSE(adapter_->session().want_read());
+ EXPECT_FALSE(adapter_->session().want_write());
+
+ adapter_->SubmitSettings(
+ {{HEADER_TABLE_SIZE, 128}, {MAX_FRAME_SIZE, 128 << 10}});
+ EXPECT_TRUE(adapter_->session().want_write());
+
+ adapter_->SubmitPriorityForStream(3, 1, 255, true);
+ 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_FALSE(adapter_->session().want_write());
+}
+
+TEST_F(OgHttp2AdapterTest, TestPartialSerialize) {
+ EXPECT_FALSE(adapter_->session().want_write());
+
+ adapter_->SubmitSettings(
+ {{HEADER_TABLE_SIZE, 128}, {MAX_FRAME_SIZE, 128 << 10}});
+ adapter_->SubmitGoAway(13, Http2ErrorCode::NO_ERROR, "And don't come back!");
+ adapter_->SubmitPing(42);
+ EXPECT_TRUE(adapter_->session().want_write());
+
+ const std::string first_part = adapter_->GetBytesToWrite(10);
+ EXPECT_TRUE(adapter_->session().want_write());
+ const std::string second_part = adapter_->GetBytesToWrite(absl::nullopt);
+ EXPECT_FALSE(adapter_->session().want_write());
+ EXPECT_THAT(
+ absl::StrCat(first_part, second_part),
+ ContainsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::GOAWAY, spdy::SpdyFrameType::PING}));
+}
+
+} // 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
new file mode 100644
index 00000000000..46d33b61798
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.cc
@@ -0,0 +1,129 @@
+#include "http2/adapter/test_frame_sequence.h"
+
+#include "http2/adapter/http2_util.h"
+#include "spdy/core/spdy_framer.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+
+TestFrameSequence& TestFrameSequence::ClientPreface() {
+ preface_ = spdy::kHttp2ConnectionHeaderPrefix;
+ frames_.push_back(absl::make_unique<spdy::SpdySettingsIR>());
+ return *this;
+}
+
+TestFrameSequence& TestFrameSequence::ServerPreface() {
+ frames_.push_back(absl::make_unique<spdy::SpdySettingsIR>());
+ return *this;
+}
+
+TestFrameSequence& TestFrameSequence::Data(Http2StreamId stream_id,
+ absl::string_view payload,
+ bool fin,
+ absl::optional<int> padding_length) {
+ auto data = absl::make_unique<spdy::SpdyDataIR>(stream_id, payload);
+ data->set_fin(fin);
+ if (padding_length) {
+ data->set_padding_len(padding_length.value());
+ }
+ frames_.push_back(std::move(data));
+ return *this;
+}
+
+TestFrameSequence& TestFrameSequence::RstStream(Http2StreamId stream_id,
+ Http2ErrorCode error) {
+ frames_.push_back(absl::make_unique<spdy::SpdyRstStreamIR>(
+ stream_id, TranslateErrorCode(error)));
+ return *this;
+}
+
+TestFrameSequence& TestFrameSequence::Settings(
+ absl::Span<Http2Setting> values) {
+ auto settings = absl::make_unique<spdy::SpdySettingsIR>();
+ for (const Http2Setting& setting : values) {
+ settings->AddSetting(setting.id, setting.value);
+ }
+ frames_.push_back(std::move(settings));
+ return *this;
+}
+
+TestFrameSequence& TestFrameSequence::SettingsAck() {
+ auto settings = absl::make_unique<spdy::SpdySettingsIR>();
+ settings->set_is_ack(true);
+ frames_.push_back(std::move(settings));
+ return *this;
+}
+
+TestFrameSequence& TestFrameSequence::Ping(Http2PingId id) {
+ frames_.push_back(absl::make_unique<spdy::SpdyPingIR>(id));
+ return *this;
+}
+
+TestFrameSequence& TestFrameSequence::PingAck(Http2PingId id) {
+ auto ping = absl::make_unique<spdy::SpdyPingIR>(id);
+ ping->set_is_ack(true);
+ frames_.push_back(std::move(ping));
+ return *this;
+}
+
+TestFrameSequence& TestFrameSequence::GoAway(Http2StreamId last_good_stream_id,
+ Http2ErrorCode error,
+ absl::string_view payload) {
+ frames_.push_back(absl::make_unique<spdy::SpdyGoAwayIR>(
+ last_good_stream_id, TranslateErrorCode(error), std::string(payload)));
+ return *this;
+}
+
+TestFrameSequence& TestFrameSequence::Headers(Http2StreamId stream_id,
+ spdy::Http2HeaderBlock block,
+ bool fin) {
+ auto headers =
+ absl::make_unique<spdy::SpdyHeadersIR>(stream_id, std::move(block));
+ headers->set_fin(fin);
+ frames_.push_back(std::move(headers));
+ return *this;
+}
+
+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);
+}
+
+TestFrameSequence& TestFrameSequence::WindowUpdate(Http2StreamId stream_id,
+ int32_t delta) {
+ frames_.push_back(
+ absl::make_unique<spdy::SpdyWindowUpdateIR>(stream_id, delta));
+ return *this;
+}
+
+TestFrameSequence& TestFrameSequence::Priority(Http2StreamId stream_id,
+ Http2StreamId parent_stream_id,
+ int weight,
+ bool exclusive) {
+ frames_.push_back(absl::make_unique<spdy::SpdyPriorityIR>(
+ stream_id, parent_stream_id, weight, exclusive));
+ return *this;
+}
+
+std::string TestFrameSequence::Serialize() {
+ std::string result;
+ if (!preface_.empty()) {
+ result = preface_;
+ }
+ spdy::SpdyFramer framer(spdy::SpdyFramer::ENABLE_COMPRESSION);
+ for (const auto& frame : frames_) {
+ spdy::SpdySerializedFrame f = framer.SerializeFrame(*frame);
+ absl::StrAppend(&result, absl::string_view(f));
+ }
+ return result;
+}
+
+} // namespace test
+} // namespace adapter
+} // namespace http2
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
new file mode 100644
index 00000000000..dd110c1a729
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.h
@@ -0,0 +1,56 @@
+#ifndef QUICHE_HTTP2_ADAPTER_TEST_FRAME_SEQUENCE_H_
+#define QUICHE_HTTP2_ADAPTER_TEST_FRAME_SEQUENCE_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "http2/adapter/http2_protocol.h"
+#include "spdy/core/spdy_protocol.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+
+class TestFrameSequence {
+ public:
+ TestFrameSequence() = default;
+
+ TestFrameSequence& ClientPreface();
+ TestFrameSequence& ServerPreface();
+ TestFrameSequence& Data(Http2StreamId stream_id,
+ absl::string_view payload,
+ bool fin = false,
+ absl::optional<int> padding_length = absl::nullopt);
+ TestFrameSequence& RstStream(Http2StreamId stream_id, Http2ErrorCode error);
+ TestFrameSequence& Settings(absl::Span<Http2Setting> values);
+ TestFrameSequence& SettingsAck();
+ TestFrameSequence& Ping(Http2PingId id);
+ TestFrameSequence& PingAck(Http2PingId id);
+ TestFrameSequence& GoAway(Http2StreamId last_good_stream_id,
+ Http2ErrorCode error,
+ absl::string_view payload = "");
+ TestFrameSequence& Headers(Http2StreamId stream_id,
+ spdy::Http2HeaderBlock block,
+ bool fin = false);
+ TestFrameSequence& Headers(Http2StreamId stream_id,
+ absl::Span<const Header> headers,
+ bool fin = false);
+ TestFrameSequence& WindowUpdate(Http2StreamId stream_id, int32_t delta);
+ TestFrameSequence& Priority(Http2StreamId stream_id,
+ Http2StreamId parent_stream_id,
+ int weight,
+ bool exclusive);
+
+ std::string Serialize();
+
+ private:
+ std::string preface_;
+ std::vector<std::unique_ptr<spdy::SpdyFrameIR>> frames_;
+};
+
+} // namespace test
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_TEST_FRAME_SEQUENCE_H_
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
new file mode 100644
index 00000000000..9e1db9954f2
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/test_utils.cc
@@ -0,0 +1,127 @@
+#include "http2/adapter/test_utils.h"
+
+#include "spdy/core/spdy_frame_reader.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+namespace {
+
+using TypeAndOptionalLength =
+ std::pair<spdy::SpdyFrameType, absl::optional<size_t>>;
+
+std::vector<std::pair<const char*, std::string>> LogFriendly(
+ const std::vector<TypeAndOptionalLength>& types_and_lengths) {
+ std::vector<std::pair<const char*, std::string>> out;
+ out.reserve(types_and_lengths.size());
+ for (const auto type_and_length : types_and_lengths) {
+ out.push_back({spdy::FrameTypeToString(type_and_length.first),
+ type_and_length.second
+ ? absl::StrCat(type_and_length.second.value())
+ : "<unspecified>"});
+ }
+ 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.
+class SpdyControlFrameMatcher
+ : public testing::MatcherInterface<const std::string> {
+ public:
+ explicit SpdyControlFrameMatcher(
+ std::vector<TypeAndOptionalLength> types_and_lengths)
+ : expected_types_and_lengths_(std::move(types_and_lengths)) {}
+
+ bool MatchAndExplain(const std::string s,
+ testing::MatchResultListener* listener) const override {
+ spdy::SpdyFrameReader reader(s.data(), s.size());
+
+ for (TypeAndOptionalLength expected : expected_types_and_lengths_) {
+ if (!MatchAndExplainOneFrame(expected.first, expected.second, &reader,
+ listener)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool MatchAndExplainOneFrame(spdy::SpdyFrameType expected_type,
+ absl::optional<size_t> expected_length,
+ spdy::SpdyFrameReader* reader,
+ testing::MatchResultListener* listener) const {
+ uint32_t payload_length;
+ if (!reader->ReadUInt24(&payload_length)) {
+ *listener << "; unable to read length field for expected_type "
+ << FrameTypeToString(expected_type) << ". data too short!";
+ return false;
+ }
+
+ if (expected_length && payload_length != expected_length.value()) {
+ *listener << "; actual length: " << payload_length
+ << " but expected length: " << expected_length.value();
+ return false;
+ }
+
+ uint8_t raw_type;
+ if (!reader->ReadUInt8(&raw_type)) {
+ *listener << "; unable to read type field for expected_type "
+ << FrameTypeToString(expected_type) << ". data too short!";
+ return false;
+ }
+
+ if (!spdy::IsDefinedFrameType(raw_type)) {
+ *listener << "; expected type " << FrameTypeToString(expected_type)
+ << " but raw type " << static_cast<int>(raw_type)
+ << " is not a defined frame type!";
+ return false;
+ }
+
+ spdy::SpdyFrameType actual_type = spdy::ParseFrameType(raw_type);
+ if (actual_type != expected_type) {
+ *listener << "; actual type: " << FrameTypeToString(actual_type)
+ << " but expected type: " << FrameTypeToString(expected_type);
+ return false;
+ }
+
+ // Seek past flags (1B), stream ID (4B), and payload. Reach the next frame.
+ reader->Seek(5 + payload_length);
+ return true;
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ *os << "Data contains frames of types in sequence "
+ << LogFriendly(expected_types_and_lengths_);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "Data does not contain frames of types in sequence "
+ << LogFriendly(expected_types_and_lengths_);
+ }
+
+ private:
+ const std::vector<TypeAndOptionalLength> expected_types_and_lengths_;
+};
+
+} // namespace
+
+testing::Matcher<const std::string> ContainsFrames(
+ 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(
+ std::vector<spdy::SpdyFrameType> types) {
+ std::vector<std::pair<spdy::SpdyFrameType, absl::optional<size_t>>>
+ types_and_lengths;
+ types_and_lengths.reserve(types.size());
+ for (spdy::SpdyFrameType type : types) {
+ types_and_lengths.push_back({type, absl::nullopt});
+ }
+ return MakeMatcher(new SpdyControlFrameMatcher(std::move(types_and_lengths)));
+}
+
+} // 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
new file mode 100644
index 00000000000..6276bf1fe45
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/test_utils.h
@@ -0,0 +1,29 @@
+#ifndef QUICHE_HTTP2_ADAPTER_TEST_UTILS_H_
+#define QUICHE_HTTP2_ADAPTER_TEST_UTILS_H_
+
+#include <string>
+#include <vector>
+
+#include "common/platform/api/quiche_test.h"
+#include "spdy/core/spdy_protocol.h"
+
+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(
+ 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(
+ std::vector<spdy::SpdyFrameType> types);
+
+} // namespace test
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_TEST_UTILS_H_
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
new file mode 100644
index 00000000000..e8f4ebda350
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/test_utils_test.cc
@@ -0,0 +1,96 @@
+#include "http2/adapter/test_utils.h"
+
+#include "common/platform/api/quiche_test.h"
+#include "spdy/core/spdy_framer.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+namespace {
+
+using spdy::SpdyFramer;
+
+TEST(ContainsFrames, Empty) {
+ EXPECT_THAT("", ContainsFrames(std::vector<spdy::SpdyFrameType>{}));
+}
+
+TEST(ContainsFrames, SingleFrameWithLength) {
+ SpdyFramer framer{SpdyFramer::ENABLE_COMPRESSION};
+
+ spdy::SpdyPingIR ping{511};
+ EXPECT_THAT(framer.SerializeFrame(ping),
+ ContainsFrames({{spdy::SpdyFrameType::PING, 8}}));
+
+ spdy::SpdyWindowUpdateIR window_update{1, 101};
+ EXPECT_THAT(framer.SerializeFrame(window_update),
+ ContainsFrames({{spdy::SpdyFrameType::WINDOW_UPDATE, 4}}));
+
+ spdy::SpdyDataIR data{3, "Some example data, ha ha!"};
+ EXPECT_THAT(framer.SerializeFrame(data),
+ ContainsFrames({{spdy::SpdyFrameType::DATA, 25}}));
+}
+
+TEST(ContainsFrames, 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}}));
+
+ 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}}));
+
+ spdy::Http2HeaderBlock block;
+ block[":method"] = "GET";
+ block[":path"] = "/example";
+ block[":authority"] = "example.com";
+ spdy::SpdyHeadersIR headers{17, std::move(block)};
+ EXPECT_THAT(framer.SerializeFrame(headers),
+ ContainsFrames({{spdy::SpdyFrameType::HEADERS, absl::nullopt}}));
+}
+
+TEST(ContainsFrames, MultipleFrames) {
+ SpdyFramer framer{SpdyFramer::ENABLE_COMPRESSION};
+
+ spdy::SpdyPingIR ping{511};
+ spdy::SpdyWindowUpdateIR window_update{1, 101};
+ spdy::SpdyDataIR data{3, "Some example data, ha ha!"};
+ spdy::SpdyRstStreamIR rst_stream{7, spdy::ERROR_CODE_REFUSED_STREAM};
+ spdy::SpdyGoAwayIR goaway{13, spdy::ERROR_CODE_ENHANCE_YOUR_CALM,
+ "Consider taking some deep breaths."};
+ spdy::Http2HeaderBlock block;
+ block[":method"] = "GET";
+ block[":path"] = "/example";
+ block[":authority"] = "example.com";
+ spdy::SpdyHeadersIR headers{17, std::move(block)};
+
+ const std::string frame_sequence =
+ absl::StrCat(absl::string_view(framer.SerializeFrame(ping)),
+ absl::string_view(framer.SerializeFrame(window_update)),
+ absl::string_view(framer.SerializeFrame(data)),
+ absl::string_view(framer.SerializeFrame(rst_stream)),
+ absl::string_view(framer.SerializeFrame(goaway)),
+ absl::string_view(framer.SerializeFrame(headers)));
+ 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}}));
+ EXPECT_THAT(
+ frame_sequence,
+ ContainsFrames(
+ {spdy::SpdyFrameType::PING, spdy::SpdyFrameType::WINDOW_UPDATE,
+ spdy::SpdyFrameType::DATA, spdy::SpdyFrameType::RST_STREAM,
+ spdy::SpdyFrameType::GOAWAY, spdy::SpdyFrameType::HEADERS}));
+}
+
+} // namespace
+} // namespace test
+} // namespace adapter
+} // namespace http2
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
new file mode 100644
index 00000000000..a1b92d5bf2c
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/window_manager.cc
@@ -0,0 +1,99 @@
+#include "http2/adapter/window_manager.h"
+
+#include <utility>
+
+#include "common/platform/api/quiche_logging.h"
+#include "spdy/platform/api/spdy_bug_tracker.h"
+
+namespace http2 {
+namespace adapter {
+
+WindowManager::WindowManager(size_t window_size_limit,
+ WindowUpdateListener listener)
+ : limit_(window_size_limit), window_(window_size_limit), buffered_(0),
+ listener_(std::move(listener)) {}
+
+void WindowManager::OnWindowSizeLimitChange(const size_t new_limit) {
+ QUICHE_VLOG(2) << "WindowManager@" << this
+ << " OnWindowSizeLimitChange from old limit of " << limit_
+ << " to new limit of " << new_limit;
+ if (new_limit > limit_) {
+ window_ += (new_limit - limit_);
+ } else {
+ SPDY_BUG(H2 window decrease)
+ << "Window size limit decrease not currently supported.";
+ }
+ limit_ = new_limit;
+}
+
+void WindowManager::SetWindowSizeLimit(size_t new_limit) {
+ QUICHE_VLOG(2) << "WindowManager@" << this
+ << " SetWindowSizeLimit from old limit of " << limit_
+ << " to new limit of " << new_limit;
+ limit_ = new_limit;
+ MaybeNotifyListener();
+}
+
+bool WindowManager::MarkDataBuffered(size_t bytes) {
+ QUICHE_VLOG(2) << "WindowManager@" << this << " window: " << window_
+ << " bytes: " << bytes;
+ if (window_ < bytes) {
+ QUICHE_VLOG(2) << "WindowManager@" << this << " window underflow "
+ << "window: " << window_ << " bytes: " << bytes;
+ window_ = 0;
+ } else {
+ window_ -= bytes;
+ }
+ buffered_ += bytes;
+ if (window_ == 0) {
+ // If data hasn't been flushed in a while there may be space available.
+ MaybeNotifyListener();
+ }
+ return window_ > 0;
+}
+
+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;
+ buffered_ = 0;
+ } else {
+ buffered_ -= bytes;
+ }
+ MaybeNotifyListener();
+}
+
+void WindowManager::MaybeNotifyListener() {
+ if (buffered_ + window_ > limit_) {
+ QUICHE_LOG(ERROR) << "Flow control violation; limit: " << limit_
+ << " buffered: " << buffered_ << " window: " << window_;
+ return;
+ }
+ // 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_);
+ bool send_update = false;
+ if (delta >= kDesiredMinDelta) {
+ // This particular window update was sent because the available delta
+ // exceeded the desired minimum.
+ send_update = true;
+ } else if (window_ < kDesiredMinWindow) {
+ // This particular window update was sent because the quota available to the
+ // peer at this moment is less than the desired minimum.
+ send_update = true;
+ }
+ if (send_update && delta > 0) {
+ QUICHE_VLOG(2) << "WindowManager@" << this
+ << " Informing listener of delta: " << delta;
+ listener_(delta);
+ window_ += delta;
+ }
+}
+
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/window_manager.h b/chromium/net/third_party/quiche/src/http2/adapter/window_manager.h
new file mode 100644
index 00000000000..277c24f960e
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/window_manager.h
@@ -0,0 +1,74 @@
+#ifndef QUICHE_HTTP2_ADAPTER_WINDOW_MANAGER_H_
+#define QUICHE_HTTP2_ADAPTER_WINDOW_MANAGER_H_
+
+#include <functional>
+
+namespace http2 {
+namespace adapter {
+
+namespace test {
+class WindowManagerPeer;
+}
+
+// This class keeps track of a HTTP/2 flow control window, notifying a listener
+// when a window update needs to be sent. This class is not thread-safe.
+class WindowManager {
+ public:
+ // A WindowUpdateListener is invoked when it is time to send a window update.
+ typedef std::function<void(size_t)> WindowUpdateListener;
+
+ WindowManager(size_t window_size_limit,
+ WindowUpdateListener listener);
+
+ size_t CurrentWindowSize() const { return window_; }
+ size_t WindowSizeLimit() const { return limit_; }
+
+ // Called when the window size limit is changed (typically via settings) but
+ // no window update should be sent.
+ void OnWindowSizeLimitChange(size_t new_limit);
+
+ // Sets the window size limit to |new_limit| and notifies the listener to
+ // update as necessary.
+ void SetWindowSizeLimit(size_t new_limit);
+
+ // Increments the running total of data bytes buffered. Returns true iff there
+ // is more window remaining.
+ bool MarkDataBuffered(size_t bytes);
+
+ // Increments the running total of data bytes that have been flushed or
+ // dropped. Invokes the listener if the current window is smaller than some
+ // threshold and there is quota available to send.
+ void MarkDataFlushed(size_t bytes);
+
+ // Convenience method, used when incoming data is immediately dropped or
+ // ignored.
+ void MarkWindowConsumed(size_t bytes) {
+ MarkDataBuffered(bytes);
+ MarkDataFlushed(bytes);
+ }
+
+ private:
+ friend class test::WindowManagerPeer;
+
+ void MaybeNotifyListener();
+
+ // The upper bound on the flow control window. The GFE attempts to maintain a
+ // window of this size at the peer as data is proxied through.
+ size_t limit_;
+
+ // The current flow control window that has not been advertised to the peer
+ // and not yet consumed. The peer can send this many bytes before becoming
+ // blocked.
+ size_t window_;
+
+ // The amount of data already buffered, which should count against the flow
+ // control window upper bound.
+ size_t buffered_;
+
+ WindowUpdateListener listener_;
+};
+
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_WINDOW_MANAGER_H_
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
new file mode 100644
index 00000000000..549fd1c3e1a
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/window_manager_test.cc
@@ -0,0 +1,171 @@
+#include "http2/adapter/window_manager.h"
+
+#include <list>
+
+#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"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+
+// Use the peer to access private vars of WindowManager.
+class WindowManagerPeer {
+ public:
+ explicit WindowManagerPeer(const WindowManager& wm) : wm_(wm) {}
+
+ size_t buffered() {
+ return wm_.buffered_;
+ }
+
+ private:
+ const WindowManager& wm_;
+};
+
+namespace {
+
+class WindowManagerTest : public ::testing::Test {
+ protected:
+ WindowManagerTest()
+ : wm_(kDefaultLimit, absl::bind_front(&WindowManagerTest::OnCall, this)),
+ peer_(wm_) {}
+
+ void OnCall(size_t s) {
+ call_sequence_.push_back(s);
+ }
+
+ const size_t kDefaultLimit = 32 * 1024 * 3;
+ std::list<size_t> call_sequence_;
+ WindowManager wm_;
+ WindowManagerPeer peer_;
+ ::http2::test::Http2Random random_;
+};
+
+// A few no-op calls.
+TEST_F(WindowManagerTest, NoOps) {
+ wm_.SetWindowSizeLimit(kDefaultLimit);
+ wm_.SetWindowSizeLimit(0);
+ wm_.SetWindowSizeLimit(kDefaultLimit);
+ wm_.MarkDataBuffered(0);
+ wm_.MarkDataFlushed(0);
+ EXPECT_TRUE(call_sequence_.empty());
+}
+
+// This test verifies that WindowManager does not notify its listener when data
+// is only buffered, and never flushed.
+TEST_F(WindowManagerTest, DataOnlyBuffered) {
+ size_t total = 0;
+ while (total < kDefaultLimit) {
+ size_t s = std::min<size_t>(kDefaultLimit - total, random_.Uniform(1024));
+ total += s;
+ wm_.MarkDataBuffered(s);
+ }
+ EXPECT_THAT(call_sequence_, ::testing::IsEmpty());
+}
+
+// This test verifies that WindowManager does notify its listener when data is
+// buffered and subsequently flushed.
+TEST_F(WindowManagerTest, DataBufferedAndFlushed) {
+ size_t total_buffered = 0;
+ size_t total_flushed = 0;
+ while (call_sequence_.empty()) {
+ size_t buffered =
+ std::min<size_t>(kDefaultLimit - total_buffered, random_.Uniform(1024));
+ wm_.MarkDataBuffered(buffered);
+ total_buffered += buffered;
+ EXPECT_TRUE(call_sequence_.empty());
+ size_t flushed = random_.Uniform(total_buffered - total_flushed);
+ wm_.MarkDataFlushed(flushed);
+ total_flushed += flushed;
+ }
+ // If WindowManager decided to send an update, at least one third of the
+ // window must have been consumed by buffered data.
+ EXPECT_GE(total_buffered, kDefaultLimit / 3);
+}
+
+// Window manager should avoid window underflow.
+TEST_F(WindowManagerTest, AvoidWindowUnderflow) {
+ EXPECT_EQ(wm_.CurrentWindowSize(), wm_.WindowSizeLimit());
+ // Don't buffer more than the total window!
+ wm_.MarkDataBuffered(wm_.WindowSizeLimit() + 1);
+ EXPECT_EQ(wm_.CurrentWindowSize(), 0);
+}
+
+// Window manager should GFE_BUG and avoid buffered underflow.
+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_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_EQ(peer_.buffered(), 0);
+}
+
+// This test verifies that WindowManager notifies its listener when window is
+// consumed (data is ignored or immediately dropped).
+TEST_F(WindowManagerTest, WindowConsumed) {
+ size_t consumed = kDefaultLimit / 3 - 1;
+ wm_.MarkWindowConsumed(consumed);
+ EXPECT_TRUE(call_sequence_.empty());
+ const size_t extra = 1;
+ wm_.MarkWindowConsumed(extra);
+ EXPECT_THAT(call_sequence_, testing::ElementsAre(consumed + extra));
+}
+
+// This test verifies that WindowManager notifies its listener when the window
+// size limit is increased.
+TEST_F(WindowManagerTest, ListenerCalledOnSizeUpdate) {
+ wm_.SetWindowSizeLimit(kDefaultLimit - 1024);
+ EXPECT_TRUE(call_sequence_.empty());
+ wm_.SetWindowSizeLimit(kDefaultLimit * 5);
+ // Because max(outstanding window, previous limit) is kDefaultLimit, it is
+ // only appropriate to increase the window by kDefaultLimit * 4.
+ EXPECT_THAT(call_sequence_, testing::ElementsAre(kDefaultLimit * 4));
+}
+
+// This test verifies that when data is buffered and then the limit is
+// decreased, WindowManager only notifies the listener once any outstanding
+// window has been consumed.
+TEST_F(WindowManagerTest, WindowUpdateAfterLimitDecreased) {
+ wm_.MarkDataBuffered(kDefaultLimit - 1024);
+ wm_.SetWindowSizeLimit(kDefaultLimit - 2048);
+
+ // Now there are 2048 bytes of window outstanding beyond the current limit,
+ // and we have 1024 bytes of data buffered beyond the current limit. This is
+ // intentional, to be sure that WindowManager works properly if the limit is
+ // decreased at runtime.
+
+ wm_.MarkDataFlushed(512);
+ EXPECT_TRUE(call_sequence_.empty());
+ wm_.MarkDataFlushed(512);
+ EXPECT_TRUE(call_sequence_.empty());
+ wm_.MarkDataFlushed(512);
+ EXPECT_TRUE(call_sequence_.empty());
+ wm_.MarkDataFlushed(1024);
+ EXPECT_THAT(call_sequence_, testing::ElementsAre(512));
+}
+
+// For normal behavior, we only call MaybeNotifyListener() when data is
+// flushed. But if window runs out entirely, we still need to call
+// MaybeNotifyListener() to avoid becoming artificially blocked when data isn't
+// being flushed.
+TEST_F(WindowManagerTest, ZeroWindowNotification) {
+ // Consume a byte of window, but not enough to trigger an update.
+ wm_.MarkWindowConsumed(1);
+
+ // Buffer the remaining window.
+ wm_.MarkDataBuffered(kDefaultLimit - 1);
+ // Listener is notified of the remaining byte of possible window.
+ EXPECT_THAT(call_sequence_, testing::ElementsAre(1));
+}
+
+} // namespace
+} // namespace test
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/decoder/decode_status.cc b/chromium/net/third_party/quiche/src/http2/decoder/decode_status.cc
index 60d682551a2..a5d2c6fedb9 100644
--- a/chromium/net/third_party/quiche/src/http2/decoder/decode_status.cc
+++ b/chromium/net/third_party/quiche/src/http2/decoder/decode_status.cc
@@ -21,7 +21,7 @@ std::ostream& operator<<(std::ostream& out, DecodeStatus v) {
// Since the value doesn't come over the wire, only a programming bug should
// result in reaching this point.
int unknown = static_cast<int>(v);
- HTTP2_BUG << "Unknown DecodeStatus " << unknown;
+ HTTP2_BUG(http2_bug_147_1) << "Unknown DecodeStatus " << unknown;
return out << "DecodeStatus(" << unknown << ")";
}
diff --git a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder.cc
index 449d6493802..55dea39cdb2 100644
--- a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder.cc
+++ b/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder.cc
@@ -28,7 +28,7 @@ std::ostream& operator<<(std::ostream& out, Http2FrameDecoder::State v) {
// Since the value doesn't come over the wire, only a programming bug should
// result in reaching this point.
int unknown = static_cast<int>(v);
- HTTP2_BUG << "Http2FrameDecoder::State " << unknown;
+ HTTP2_BUG(http2_bug_155_1) << "Http2FrameDecoder::State " << unknown;
return out << "Http2FrameDecoder::State(" << unknown << ")";
}
@@ -158,12 +158,7 @@ DecodeStatus Http2FrameDecoder::StartDecodingPayload(DecodeBuffer* db) {
break;
case Http2FrameType::PRIORITY_UPDATE:
- if (GetHttp2RestartFlag(http2_parse_priority_update_frame)) {
- HTTP2_RESTART_FLAG_COUNT_N(http2_parse_priority_update_frame, 1, 2);
- status = StartDecodingPriorityUpdatePayload(&subset);
- } else {
- status = StartDecodingUnknownPayload(&subset);
- }
+ status = StartDecodingPriorityUpdatePayload(&subset);
break;
default:
@@ -237,12 +232,7 @@ DecodeStatus Http2FrameDecoder::ResumeDecodingPayload(DecodeBuffer* db) {
break;
case Http2FrameType::PRIORITY_UPDATE:
- if (GetHttp2RestartFlag(http2_parse_priority_update_frame)) {
- HTTP2_RESTART_FLAG_COUNT_N(http2_parse_priority_update_frame, 2, 2);
- status = ResumeDecodingPriorityUpdatePayload(&subset);
- } else {
- status = ResumeDecodingUnknownPayload(&subset);
- }
+ status = ResumeDecodingPriorityUpdatePayload(&subset);
break;
default:
diff --git a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder.h b/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder.h
index 53e4bbe7c2b..295a0b04c7f 100644
--- a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder.h
+++ b/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder.h
@@ -77,6 +77,12 @@ class QUICHE_EXPORT_PRIVATE Http2FrameDecoder {
// Returns kDecodeError if the frame's padding or length wasn't valid (i.e. if
// the decoder called either the listener's OnPaddingTooLong or
// OnFrameSizeError method).
+ //
+ // If the decode buffer contains the entirety of a frame payload or field,
+ // then the corresponding Http2FrameDecoderListener::On*Payload(),
+ // OnHpackFragment(), OnGoAwayOpaqueData(), or OnAltSvcValueData() method is
+ // guaranteed to be called exactly once, with the entire payload or field in a
+ // single chunk.
DecodeStatus DecodeFrame(DecodeBuffer* db);
//////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_test.cc
index 0b0b4153d90..b09a5d086c5 100644
--- a/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/decoder/http2_frame_decoder_test.cc
@@ -558,16 +558,9 @@ TEST_F(Http2FrameDecoderTest, PriorityUpdatePayload) {
};
Http2FrameHeader header(7, Http2FrameType::PRIORITY_UPDATE, 0, 0);
- if (GetHttp2RestartFlag(http2_parse_priority_update_frame)) {
- FrameParts expected(header, "abc");
- expected.SetOptPriorityUpdate(Http2PriorityUpdateFields{5});
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
- } else {
- FrameParts expected(header, absl::string_view("\x00\x00\x00\x05"
- "abc",
- 7));
- EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
- }
+ FrameParts expected(header, "abc");
+ expected.SetOptPriorityUpdate(Http2PriorityUpdateFields{5});
+ EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
}
TEST_F(Http2FrameDecoderTest, UnknownPayload) {
diff --git a/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder.cc
index b8f29bc3177..43ade26797f 100644
--- a/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder.cc
+++ b/chromium/net/third_party/quiche/src/http2/decoder/http2_structure_decoder.cc
@@ -21,7 +21,8 @@ namespace http2 {
uint32_t Http2StructureDecoder::IncompleteStart(DecodeBuffer* db,
uint32_t target_size) {
if (target_size > sizeof buffer_) {
- HTTP2_BUG << "target_size too large for buffer: " << target_size;
+ HTTP2_BUG(http2_bug_154_1)
+ << "target_size too large for buffer: " << target_size;
return 0;
}
const uint32_t num_to_copy = db->MinLengthRemaining(target_size);
@@ -53,8 +54,9 @@ bool Http2StructureDecoder::ResumeFillingBuffer(DecodeBuffer* db,
<< ": target_size=" << target_size << "; offset_=" << offset_
<< "; db->Remaining=" << db->Remaining();
if (target_size < offset_) {
- HTTP2_BUG << "Already filled buffer_! target_size=" << target_size
- << " offset_=" << offset_;
+ HTTP2_BUG(http2_bug_154_2)
+ << "Already filled buffer_! target_size=" << target_size
+ << " offset_=" << offset_;
return false;
}
const uint32_t needed = target_size - offset_;
@@ -74,8 +76,9 @@ bool Http2StructureDecoder::ResumeFillingBuffer(DecodeBuffer* db,
<< "; *remaining_payload=" << *remaining_payload
<< "; db->Remaining=" << db->Remaining();
if (target_size < offset_) {
- HTTP2_BUG << "Already filled buffer_! target_size=" << target_size
- << " offset_=" << offset_;
+ HTTP2_BUG(http2_bug_154_3)
+ << "Already filled buffer_! target_size=" << target_size
+ << " offset_=" << offset_;
return false;
}
const uint32_t needed = target_size - offset_;
diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/altsvc_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/altsvc_payload_decoder.cc
index 2b341047e9f..39d3fc9efbd 100644
--- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/altsvc_payload_decoder.cc
+++ b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/altsvc_payload_decoder.cc
@@ -31,7 +31,8 @@ std::ostream& operator<<(std::ostream& out,
// Since the value doesn't come over the wire, only a programming bug should
// result in reaching this point.
int unknown = static_cast<int>(v);
- HTTP2_BUG << "Invalid AltSvcPayloadDecoder::PayloadState: " << unknown;
+ HTTP2_BUG(http2_bug_163_1)
+ << "Invalid AltSvcPayloadDecoder::PayloadState: " << unknown;
return out << "AltSvcPayloadDecoder::PayloadState(" << unknown << ")";
}
@@ -104,7 +105,7 @@ DecodeStatus AltSvcPayloadDecoder::ResumeDecodingPayload(
payload_state_ = PayloadState::kMaybeDecodedStruct;
continue;
}
- HTTP2_BUG << "PayloadState: " << payload_state_;
+ HTTP2_BUG(http2_bug_163_2) << "PayloadState: " << payload_state_;
}
}
diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/data_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/data_payload_decoder.cc
index 03e442dc0b8..5868d43fe35 100644
--- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/data_payload_decoder.cc
+++ b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/data_payload_decoder.cc
@@ -29,7 +29,8 @@ std::ostream& operator<<(std::ostream& out,
// Since the value doesn't come over the wire, only a programming bug should
// result in reaching this point.
int unknown = static_cast<int>(v);
- HTTP2_BUG << "Invalid DataPayloadDecoder::PayloadState: " << unknown;
+ HTTP2_BUG(http2_bug_174_1)
+ << "Invalid DataPayloadDecoder::PayloadState: " << unknown;
return out << "DataPayloadDecoder::PayloadState(" << unknown << ")";
}
@@ -120,7 +121,7 @@ DecodeStatus DataPayloadDecoder::ResumeDecodingPayload(FrameDecoderState* state,
payload_state_ = PayloadState::kSkipPadding;
return DecodeStatus::kDecodeInProgress;
}
- HTTP2_BUG << "PayloadState: " << payload_state_;
+ HTTP2_BUG(http2_bug_174_2) << "PayloadState: " << payload_state_;
return DecodeStatus::kDecodeError;
}
diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/goaway_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/goaway_payload_decoder.cc
index 17b7e7dd534..a2cfd09673b 100644
--- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/goaway_payload_decoder.cc
+++ b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/goaway_payload_decoder.cc
@@ -31,7 +31,8 @@ std::ostream& operator<<(std::ostream& out,
// Since the value doesn't come over the wire, only a programming bug should
// result in reaching this point.
int unknown = static_cast<int>(v);
- HTTP2_BUG << "Invalid GoAwayPayloadDecoder::PayloadState: " << unknown;
+ HTTP2_BUG(http2_bug_167_1)
+ << "Invalid GoAwayPayloadDecoder::PayloadState: " << unknown;
return out << "GoAwayPayloadDecoder::PayloadState(" << unknown << ")";
}
@@ -114,7 +115,7 @@ DecodeStatus GoAwayPayloadDecoder::ResumeDecodingPayload(
payload_state_ = PayloadState::kHandleFixedFieldsStatus;
continue;
}
- HTTP2_BUG << "PayloadState: " << payload_state_;
+ HTTP2_BUG(http2_bug_167_2) << "PayloadState: " << payload_state_;
}
}
diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/headers_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/headers_payload_decoder.cc
index 9b219d71427..a312fb944b6 100644
--- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/headers_payload_decoder.cc
+++ b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/headers_payload_decoder.cc
@@ -33,7 +33,8 @@ std::ostream& operator<<(std::ostream& out,
// Since the value doesn't come over the wire, only a programming bug should
// result in reaching this point.
int unknown = static_cast<int>(v);
- HTTP2_BUG << "Invalid HeadersPayloadDecoder::PayloadState: " << unknown;
+ HTTP2_BUG(http2_bug_189_1)
+ << "Invalid HeadersPayloadDecoder::PayloadState: " << unknown;
return out << "HeadersPayloadDecoder::PayloadState(" << unknown << ")";
}
@@ -170,7 +171,7 @@ DecodeStatus HeadersPayloadDecoder::ResumeDecodingPayload(
payload_state_ = PayloadState::kReadPayload;
continue;
}
- HTTP2_BUG << "PayloadState: " << payload_state_;
+ HTTP2_BUG(http2_bug_189_2) << "PayloadState: " << payload_state_;
}
}
diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/payload_decoder_base_test_util.h b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/payload_decoder_base_test_util.h
index 464b0cb1d59..feea5e5ef0f 100644
--- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/payload_decoder_base_test_util.h
+++ b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/payload_decoder_base_test_util.h
@@ -385,7 +385,7 @@ class AbstractPaddablePayloadDecoderTest
auto& listener = listener_;
Validator validator =
[header, expected_missing_length, &listener](
- const DecodeBuffer& input,
+ const DecodeBuffer&,
DecodeStatus status) -> ::testing::AssertionResult {
VERIFY_EQ(DecodeStatus::kDecodeError, status);
VERIFY_FALSE(listener.IsInProgress());
diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder.cc
index d115c358b37..bf7821625cf 100644
--- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder.cc
+++ b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder.cc
@@ -31,8 +31,8 @@ std::ostream& operator<<(std::ostream& out,
// Since the value doesn't come over the wire, only a programming bug should
// result in reaching this point.
int unknown = static_cast<int>(v);
- HTTP2_BUG << "Invalid PriorityUpdatePayloadDecoder::PayloadState: "
- << unknown;
+ HTTP2_BUG(http2_bug_173_1)
+ << "Invalid PriorityUpdatePayloadDecoder::PayloadState: " << unknown;
return out << "PriorityUpdatePayloadDecoder::PayloadState(" << unknown << ")";
}
@@ -118,7 +118,7 @@ DecodeStatus PriorityUpdatePayloadDecoder::ResumeDecodingPayload(
payload_state_ = PayloadState::kHandleFixedFieldsStatus;
continue;
}
- HTTP2_BUG << "PayloadState: " << payload_state_;
+ HTTP2_BUG(http2_bug_173_2) << "PayloadState: " << payload_state_;
}
}
diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder_test.cc
index 39d0afc98be..41b7dc85bce 100644
--- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/priority_update_payload_decoder_test.cc
@@ -61,31 +61,14 @@ struct Listener : public FramePartsCollector {
}
};
-// Avoid initialization of test class when flag is false, because base class
-// method AbstractPayloadDecoderTest::SetUp() crashes if
-// IsSupportedHttp2FrameType(PRIORITY_UPDATE) returns false.
-std::vector<bool> GetTestParams() {
- if (GetHttp2RestartFlag(http2_parse_priority_update_frame)) {
- return {true}; // Actual Boolean value is ignored.
- } else {
- return {};
- }
-}
-
class PriorityUpdatePayloadDecoderTest
: public AbstractPayloadDecoderTest<PriorityUpdatePayloadDecoder,
PriorityUpdatePayloadDecoderPeer,
- Listener>,
- public ::testing::WithParamInterface<bool> {};
-
-INSTANTIATE_TEST_SUITE_P(MaybeRunTest,
- PriorityUpdatePayloadDecoderTest,
- ::testing::ValuesIn(GetTestParams()));
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PriorityUpdatePayloadDecoderTest);
+ Listener> {};
// Confirm we get an error if the payload is not long enough to hold
// Http2PriorityUpdateFields.
-TEST_P(PriorityUpdatePayloadDecoderTest, Truncated) {
+TEST_F(PriorityUpdatePayloadDecoderTest, Truncated) {
auto approve_size = [](size_t size) {
return size != Http2PriorityUpdateFields::EncodedSize();
};
@@ -98,9 +81,9 @@ class PriorityUpdatePayloadLengthTests
: public AbstractPayloadDecoderTest<PriorityUpdatePayloadDecoder,
PriorityUpdatePayloadDecoderPeer,
Listener>,
- public ::testing::WithParamInterface<std::tuple<uint32_t, bool>> {
+ public ::testing::WithParamInterface<uint32_t> {
protected:
- PriorityUpdatePayloadLengthTests() : length_(std::get<0>(GetParam())) {
+ PriorityUpdatePayloadLengthTests() : length_(GetParam()) {
HTTP2_VLOG(1) << "################ length_=" << length_
<< " ################";
}
@@ -108,12 +91,9 @@ class PriorityUpdatePayloadLengthTests
const uint32_t length_;
};
-INSTANTIATE_TEST_SUITE_P(
- VariousLengths,
- PriorityUpdatePayloadLengthTests,
- ::testing::Combine(::testing::Values(0, 1, 2, 3, 4, 5, 6),
- ::testing::ValuesIn(GetTestParams())));
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PriorityUpdatePayloadLengthTests);
+INSTANTIATE_TEST_SUITE_P(VariousLengths,
+ PriorityUpdatePayloadLengthTests,
+ ::testing::Values(0, 1, 2, 3, 4, 5, 6));
TEST_P(PriorityUpdatePayloadLengthTests, ValidLength) {
Http2PriorityUpdateFields priority_update;
diff --git a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/push_promise_payload_decoder.cc b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/push_promise_payload_decoder.cc
index efb15208341..95fb5f5e662 100644
--- a/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/push_promise_payload_decoder.cc
+++ b/chromium/net/third_party/quiche/src/http2/decoder/payload_decoders/push_promise_payload_decoder.cc
@@ -155,7 +155,7 @@ DecodeStatus PushPromisePayloadDecoder::ResumeDecodingPayload(
payload_state_ = PayloadState::kResumeDecodingPushPromiseFields;
return status;
}
- HTTP2_BUG << "PayloadState: " << payload_state_;
+ HTTP2_BUG(http2_bug_183_1) << "PayloadState: " << payload_state_;
}
}
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_decoder.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_decoder.cc
index 9c63f03c3af..0a4c71cb754 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_decoder.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_block_decoder.cc
@@ -10,7 +10,6 @@
#include "http2/platform/api/http2_flag_utils.h"
#include "http2/platform/api/http2_flags.h"
#include "http2/platform/api/http2_logging.h"
-#include "http2/platform/api/http2_string_utils.h"
namespace http2 {
@@ -56,7 +55,7 @@ DecodeStatus HpackBlockDecoder::Decode(DecodeBuffer* db) {
std::string HpackBlockDecoder::DebugString() const {
return absl::StrCat(
"HpackBlockDecoder(", entry_decoder_.DebugString(), ", listener@",
- Http2Hex(reinterpret_cast<intptr_t>(listener_)),
+ absl::Hex(reinterpret_cast<intptr_t>(listener_)),
(before_entry_ ? ", between entries)" : ", in an entry)"));
}
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.cc
index 45d7a78b3df..0f1336ed29e 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.cc
@@ -21,11 +21,6 @@ HpackDecoder::HpackDecoder(HpackDecoderListener* listener,
HpackDecoder::~HpackDecoder() = default;
-void HpackDecoder::set_tables_debug_listener(
- HpackDecoderTablesDebugListener* debug_listener) {
- decoder_state_.set_tables_debug_listener(debug_listener);
-}
-
void HpackDecoder::set_max_string_size_bytes(size_t max_string_size_bytes) {
entry_buffer_.set_max_string_size_bytes(max_string_size_bytes);
}
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.h
index b5fdecd0d67..01d32a38ac1 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.h
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.h
@@ -45,11 +45,6 @@ class QUICHE_EXPORT_PRIVATE HpackDecoder {
HpackDecoder(const HpackDecoder&) = delete;
HpackDecoder& operator=(const HpackDecoder&) = delete;
- // Set listener to be notified of insertions into the HPACK dynamic table,
- // and uses of those entries.
- void set_tables_debug_listener(
- HpackDecoderTablesDebugListener* debug_listener);
-
// max_string_size specifies the maximum size of an on-the-wire string (name
// or value, plain or Huffman encoded) that will be accepted. See sections
// 5.1 and 5.2 of RFC 7541. This is a defense against OOM attacks; HTTP/2
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.cc
index a665be8c62d..d1dea19330e 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.cc
@@ -13,8 +13,8 @@ HpackDecoderNoOpListener::HpackDecoderNoOpListener() = default;
HpackDecoderNoOpListener::~HpackDecoderNoOpListener() = default;
void HpackDecoderNoOpListener::OnHeaderListStart() {}
-void HpackDecoderNoOpListener::OnHeader(const HpackString& /*name*/,
- const HpackString& /*value*/) {}
+void HpackDecoderNoOpListener::OnHeader(const std::string& /*name*/,
+ const std::string& /*value*/) {}
void HpackDecoderNoOpListener::OnHeaderListEnd() {}
void HpackDecoderNoOpListener::OnHeaderErrorDetected(
absl::string_view /*error_message*/) {}
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.h
index bbb05449715..d341025c82c 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.h
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.h
@@ -9,7 +9,6 @@
#define QUICHE_HTTP2_HPACK_DECODER_HPACK_DECODER_LISTENER_H_
#include "absl/strings/string_view.h"
-#include "http2/hpack/hpack_string.h"
#include "http2/hpack/http2_hpack_constants.h"
#include "common/platform/api/quiche_export.h"
@@ -28,7 +27,7 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderListener {
// Called for each header name-value pair that is decoded, in the order they
// appear in the HPACK block. Multiple values for a given key will be emitted
// as multiple calls to OnHeader.
- virtual void OnHeader(const HpackString& name, const HpackString& value) = 0;
+ virtual void OnHeader(const std::string& name, const std::string& value) = 0;
// OnHeaderListEnd is called after successfully decoding an HPACK block into
// an HTTP/2 header list. Will only be called once per block, even if it
@@ -49,7 +48,7 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderNoOpListener
~HpackDecoderNoOpListener() override;
void OnHeaderListStart() override;
- void OnHeader(const HpackString& name, const HpackString& value) override;
+ void OnHeader(const std::string& name, const std::string& value) override;
void OnHeaderListEnd() override;
void OnHeaderErrorDetected(absl::string_view error_message) override;
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.cc
index 528f1b69893..3140a19e5f5 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.cc
@@ -4,7 +4,8 @@
#include "http2/hpack/decoder/hpack_decoder_state.h"
-#include "http2/hpack/hpack_string.h"
+#include <utility>
+
#include "http2/http2_constants.h"
#include "http2/platform/api/http2_logging.h"
#include "http2/platform/api/http2_macros.h"
@@ -12,11 +13,11 @@
namespace http2 {
namespace {
-HpackString ExtractHpackString(HpackDecoderStringBuffer* string_buffer) {
+std::string ExtractString(HpackDecoderStringBuffer* string_buffer) {
if (string_buffer->IsBuffered()) {
- return HpackString(string_buffer->ReleaseString());
+ return string_buffer->ReleaseString();
} else {
- auto result = HpackString(string_buffer->str());
+ auto result = std::string(string_buffer->str());
string_buffer->Reset();
return result;
}
@@ -34,11 +35,6 @@ HpackDecoderState::HpackDecoderState(HpackDecoderListener* listener)
error_(HpackDecodingError::kOk) {}
HpackDecoderState::~HpackDecoderState() = default;
-void HpackDecoderState::set_tables_debug_listener(
- HpackDecoderTablesDebugListener* debug_listener) {
- decoder_tables_.set_debug_listener(debug_listener);
-}
-
void HpackDecoderState::ApplyHeaderTableSizeSetting(
uint32_t header_table_size) {
HTTP2_DVLOG(2) << "HpackDecoderState::ApplyHeaderTableSizeSetting("
@@ -114,10 +110,10 @@ void HpackDecoderState::OnNameIndexAndLiteralValue(
allow_dynamic_table_size_update_ = false;
const HpackStringPair* entry = decoder_tables_.Lookup(name_index);
if (entry != nullptr) {
- HpackString value(ExtractHpackString(value_buffer));
+ std::string value(ExtractString(value_buffer));
listener_->OnHeader(entry->name, value);
if (entry_type == HpackEntryType::kIndexedLiteralHeader) {
- decoder_tables_.Insert(entry->name, value);
+ decoder_tables_.Insert(entry->name, std::move(value));
}
} else {
ReportError(HpackDecodingError::kInvalidNameIndex, "");
@@ -138,11 +134,11 @@ void HpackDecoderState::OnLiteralNameAndValue(
return;
}
allow_dynamic_table_size_update_ = false;
- HpackString name(ExtractHpackString(name_buffer));
- HpackString value(ExtractHpackString(value_buffer));
+ std::string name(ExtractString(name_buffer));
+ std::string value(ExtractString(value_buffer));
listener_->OnHeader(name, value);
if (entry_type == HpackEntryType::kIndexedLiteralHeader) {
- decoder_tables_.Insert(name, value);
+ decoder_tables_.Insert(std::move(name), std::move(value));
}
}
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.h
index cb2ff6d18eb..14b4184bd5a 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.h
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.h
@@ -43,11 +43,6 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderState : public HpackWholeEntryListener {
// The listener may be changed at any time.
HpackDecoderListener* listener() const { return listener_; }
- // Set listener to be notified of insertions into the HPACK dynamic table,
- // and uses of those entries.
- void set_tables_debug_listener(
- HpackDecoderTablesDebugListener* debug_listener);
-
// ApplyHeaderTableSizeSetting notifies this object that this endpoint has
// received a SETTINGS ACK frame acknowledging an earlier SETTINGS frame from
// this endpoint specifying a new value for SETTINGS_HEADER_TABLE_SIZE (the
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state_test.cc
index 500156595e0..698c655c961 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state_test.cc
@@ -10,7 +10,6 @@
#include <vector>
#include "absl/strings/string_view.h"
-#include "http2/hpack/hpack_string.h"
#include "http2/hpack/http2_hpack_constants.h"
#include "http2/http2_constants.h"
#include "http2/platform/api/http2_logging.h"
@@ -36,10 +35,12 @@ namespace {
class MockHpackDecoderListener : public HpackDecoderListener {
public:
- MOCK_METHOD0(OnHeaderListStart, void());
- MOCK_METHOD2(OnHeader,
- void(const HpackString& name, const HpackString& value));
- MOCK_METHOD0(OnHeaderListEnd, void());
+ MOCK_METHOD(void, OnHeaderListStart, (), (override));
+ MOCK_METHOD(void,
+ OnHeader,
+ (const std::string& name, const std::string& value),
+ (override));
+ MOCK_METHOD(void, OnHeaderListEnd, (), (override));
MOCK_METHOD(void,
OnHeaderErrorDetected,
(absl::string_view error_message),
@@ -155,8 +156,8 @@ class HpackDecoderStateTest : public QuicheTest {
const HpackStringPair* entry =
Lookup(dynamic_index + kFirstDynamicTableIndex - 1);
VERIFY_NE(entry, nullptr);
- VERIFY_EQ(entry->name.ToStringPiece(), name);
- VERIFY_EQ(entry->value.ToStringPiece(), value);
+ VERIFY_EQ(entry->name, name);
+ VERIFY_EQ(entry->value, value);
return AssertionSuccess();
}
AssertionResult VerifyNoEntry(size_t dynamic_index) {
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.cc
index 2a2184664d2..8f2243d7f6b 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.cc
@@ -25,7 +25,8 @@ std::ostream& operator<<(std::ostream& out,
// Since the value doesn't come over the wire, only a programming bug should
// result in reaching this point.
int unknown = static_cast<int>(v);
- HTTP2_BUG << "Invalid HpackDecoderStringBuffer::State: " << unknown;
+ HTTP2_BUG(http2_bug_50_1)
+ << "Invalid HpackDecoderStringBuffer::State: " << unknown;
return out << "HpackDecoderStringBuffer::State(" << unknown << ")";
}
@@ -44,7 +45,8 @@ std::ostream& operator<<(std::ostream& out,
// Since the value doesn't come over the wire, only a programming bug should
// result in reaching this point.
auto v2 = static_cast<int>(v);
- HTTP2_BUG << "Invalid HpackDecoderStringBuffer::Backing: " << v2;
+ HTTP2_BUG(http2_bug_50_2)
+ << "Invalid HpackDecoderStringBuffer::Backing: " << v2;
return out << "HpackDecoderStringBuffer::Backing(" << v2 << ")";
}
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.cc
index 1b2cc11c7c3..9f50ec78490 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.cc
@@ -4,6 +4,7 @@
#include "http2/hpack/decoder/hpack_decoder_tables.h"
+#include "absl/strings/str_cat.h"
#include "http2/hpack/http2_hpack_constants.h"
#include "http2/platform/api/http2_logging.h"
@@ -34,8 +35,23 @@ const std::vector<HpackStringPair>* GetStaticTable() {
} // namespace
-HpackDecoderTablesDebugListener::HpackDecoderTablesDebugListener() = default;
-HpackDecoderTablesDebugListener::~HpackDecoderTablesDebugListener() = default;
+HpackStringPair::HpackStringPair(std::string name, std::string value)
+ : name(std::move(name)), value(std::move(value)) {
+ HTTP2_DVLOG(3) << DebugString() << " ctor";
+}
+
+HpackStringPair::~HpackStringPair() {
+ HTTP2_DVLOG(3) << DebugString() << " dtor";
+}
+
+std::string HpackStringPair::DebugString() const {
+ return absl::StrCat("HpackStringPair(name=", name, ", value=", value, ")");
+}
+
+std::ostream& operator<<(std::ostream& os, const HpackStringPair& p) {
+ os << p.DebugString();
+ return os;
+}
HpackDecoderStaticTable::HpackDecoderStaticTable(
const std::vector<HpackStringPair>* table)
@@ -50,13 +66,8 @@ const HpackStringPair* HpackDecoderStaticTable::Lookup(size_t index) const {
return nullptr;
}
-HpackDecoderDynamicTable::HpackDecoderTableEntry::HpackDecoderTableEntry(
- const HpackString& name,
- const HpackString& value)
- : HpackStringPair(name, value) {}
-
HpackDecoderDynamicTable::HpackDecoderDynamicTable()
- : insert_count_(kFirstDynamicTableIndex - 1), debug_listener_(nullptr) {}
+ : insert_count_(kFirstDynamicTableIndex - 1) {}
HpackDecoderDynamicTable::~HpackDecoderDynamicTable() = default;
void HpackDecoderDynamicTable::DynamicTableSizeUpdate(size_t size_limit) {
@@ -69,12 +80,12 @@ void HpackDecoderDynamicTable::DynamicTableSizeUpdate(size_t size_limit) {
// TODO(jamessynge): Check somewhere before here that names received from the
// peer are valid (e.g. are lower-case, no whitespace, etc.).
-void HpackDecoderDynamicTable::Insert(const HpackString& name,
- const HpackString& value) {
- HpackDecoderTableEntry entry(name, value);
+void HpackDecoderDynamicTable::Insert(std::string name, std::string value) {
+ HpackStringPair entry(std::move(name), std::move(value));
size_t entry_size = entry.size();
HTTP2_DVLOG(2) << "InsertEntry of size=" << entry_size
- << "\n name: " << name << "\n value: " << value;
+ << "\n name: " << entry.name
+ << "\n value: " << entry.value;
if (entry_size > size_limit_) {
HTTP2_DVLOG(2) << "InsertEntry: entry larger than table, removing "
<< table_.size() << " entries, of total size "
@@ -84,11 +95,6 @@ void HpackDecoderDynamicTable::Insert(const HpackString& name,
return;
}
++insert_count_;
- if (debug_listener_ != nullptr) {
- entry.time_added = debug_listener_->OnEntryInserted(entry, insert_count_);
- HTTP2_DVLOG(2) << "OnEntryInserted returned time_added=" << entry.time_added
- << " for insert_count_=" << insert_count_;
- }
size_t insert_limit = size_limit_ - entry_size;
EnsureSizeNoMoreThan(insert_limit);
table_.push_front(entry);
@@ -100,13 +106,7 @@ void HpackDecoderDynamicTable::Insert(const HpackString& name,
const HpackStringPair* HpackDecoderDynamicTable::Lookup(size_t index) const {
if (index < table_.size()) {
- const HpackDecoderTableEntry& entry = table_[index];
- if (debug_listener_ != nullptr) {
- size_t insert_count_of_index = insert_count_ + table_.size() - index;
- debug_listener_->OnUseEntry(entry, insert_count_of_index,
- entry.time_added);
- }
- return &entry;
+ return &table_[index];
}
return nullptr;
}
@@ -137,11 +137,6 @@ void HpackDecoderDynamicTable::RemoveLastEntry() {
HpackDecoderTables::HpackDecoderTables() = default;
HpackDecoderTables::~HpackDecoderTables() = default;
-void HpackDecoderTables::set_debug_listener(
- HpackDecoderTablesDebugListener* debug_listener) {
- dynamic_table_.set_debug_listener(debug_listener);
-}
-
const HpackStringPair* HpackDecoderTables::Lookup(size_t index) const {
if (index < kFirstDynamicTableIndex) {
return static_table_.Lookup(index);
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 5f56cf2f01b..f75916d67df 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
@@ -19,11 +19,13 @@
#include <stddef.h>
#include <cstdint>
+#include <iosfwd>
+#include <string>
+#include <utility>
#include <vector>
-#include "http2/hpack/hpack_string.h"
#include "http2/http2_constants.h"
-#include "http2/platform/api/http2_containers.h"
+#include "quic/core/quic_circular_deque.h"
#include "common/platform/api/quiche_export.h"
namespace http2 {
@@ -31,37 +33,23 @@ namespace test {
class HpackDecoderTablesPeer;
} // namespace test
-// HpackDecoderTablesDebugListener supports a QUIC experiment, enabling
-// the gathering of information about the time-line of use of HPACK
-// dynamic table entries.
-class QUICHE_EXPORT_PRIVATE HpackDecoderTablesDebugListener {
- public:
- HpackDecoderTablesDebugListener();
- virtual ~HpackDecoderTablesDebugListener();
-
- HpackDecoderTablesDebugListener(const HpackDecoderTablesDebugListener&) =
- delete;
- HpackDecoderTablesDebugListener& operator=(
- const HpackDecoderTablesDebugListener&) = delete;
-
- // The entry has been inserted into the dynamic table. insert_count starts at
- // 62 because 61 is the last index in the static table; insert_count increases
- // by 1 with each insert into the dynamic table; it is not incremented when
- // when a entry is too large to fit into the dynamic table at all (which has
- // the effect of emptying the dynamic table).
- // Returns a value that can be used as time_added in OnUseEntry.
- virtual int64_t OnEntryInserted(const HpackStringPair& entry,
- size_t insert_count) = 0;
-
- // The entry has been used, either for the name or for the name and value.
- // insert_count is the same as passed to OnEntryInserted when entry was
- // inserted to the dynamic table, and time_added is the value that was
- // returned by OnEntryInserted.
- virtual void OnUseEntry(const HpackStringPair& entry,
- size_t insert_count,
- int64_t time_added) = 0;
+struct QUICHE_EXPORT_PRIVATE HpackStringPair {
+ HpackStringPair(std::string name, std::string value);
+ ~HpackStringPair();
+
+ // Returns the size of a header entry with this name and value, per the RFC:
+ // http://httpwg.org/specs/rfc7541.html#calculating.table.size
+ size_t size() const { return 32 + name.size() + value.size(); }
+
+ std::string DebugString() const;
+
+ const std::string name;
+ const std::string value;
};
+QUICHE_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
+ const HpackStringPair& p);
+
// See http://httpwg.org/specs/rfc7541.html#static.table.definition for the
// contents, and http://httpwg.org/specs/rfc7541.html#index.address.space for
// info about accessing the static table.
@@ -93,13 +81,6 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderDynamicTable {
HpackDecoderDynamicTable(const HpackDecoderDynamicTable&) = delete;
HpackDecoderDynamicTable& operator=(const HpackDecoderDynamicTable&) = delete;
- // Set the listener to be notified of insertions into this table, and later
- // uses of those entries. Added for evaluation of changes to QUIC's use
- // of HPACK.
- void set_debug_listener(HpackDecoderTablesDebugListener* debug_listener) {
- debug_listener_ = debug_listener;
- }
-
// Sets a new size limit, received from the peer; performs evictions if
// necessary to ensure that the current size does not exceed the new limit.
// The caller needs to have validated that size_limit does not
@@ -108,7 +89,7 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderDynamicTable {
// Insert entry if possible.
// If entry is too large to insert, then dynamic table will be empty.
- void Insert(const HpackString& name, const HpackString& value);
+ void Insert(std::string name, std::string value);
// If index is valid, returns a pointer to the entry, otherwise returns
// nullptr.
@@ -119,10 +100,6 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderDynamicTable {
private:
friend class test::HpackDecoderTablesPeer;
- struct HpackDecoderTableEntry : public HpackStringPair {
- HpackDecoderTableEntry(const HpackString& name, const HpackString& value);
- int64_t time_added;
- };
// Drop older entries to ensure the size is not greater than limit.
void EnsureSizeNoMoreThan(size_t limit);
@@ -130,7 +107,7 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderDynamicTable {
// Removes the oldest dynamic table entry.
void RemoveLastEntry();
- Http2Deque<HpackDecoderTableEntry> table_;
+ quic::QuicCircularDeque<HpackStringPair> table_;
// The last received DynamicTableSizeUpdate value, initialized to
// SETTINGS_HEADER_TABLE_SIZE.
@@ -141,7 +118,6 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderDynamicTable {
// insert_count_ and debug_listener_ are used by a QUIC experiment; remove
// when the experiment is done.
size_t insert_count_;
- HpackDecoderTablesDebugListener* debug_listener_;
};
class QUICHE_EXPORT_PRIVATE HpackDecoderTables {
@@ -152,11 +128,6 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderTables {
HpackDecoderTables(const HpackDecoderTables&) = delete;
HpackDecoderTables& operator=(const HpackDecoderTables&) = delete;
- // Set the listener to be notified of insertions into the dynamic table, and
- // later uses of those entries. Added for evaluation of changes to QUIC's use
- // of HPACK.
- void set_debug_listener(HpackDecoderTablesDebugListener* debug_listener);
-
// Sets a new size limit, received from the peer; performs evictions if
// necessary to ensure that the current size does not exceed the new limit.
// The caller needs to have validated that size_limit does not
@@ -167,10 +138,8 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderTables {
// Insert entry if possible.
// If entry is too large to insert, then dynamic table will be empty.
- // TODO(jamessynge): Add methods for moving the string(s) into the table,
- // or for otherwise avoiding unnecessary copies.
- void Insert(const HpackString& name, const HpackString& value) {
- dynamic_table_.Insert(name, value);
+ void Insert(std::string name, std::string value) {
+ dynamic_table_.Insert(std::move(name), std::move(value));
}
// If index is valid, returns a pointer to the entry, otherwise returns
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables_test.cc
index a3e4ee097a0..b7ed5273264 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables_test.cc
@@ -205,7 +205,7 @@ class HpackDecoderTablesTest : public HpackDecoderStaticTableTest {
// move up by 1 index.
AssertionResult Insert(const std::string& name, const std::string& value) {
size_t old_count = num_dynamic_entries();
- tables_.Insert(HpackString(name), HpackString(value));
+ tables_.Insert(name, value);
FakeInsert(name, value);
VERIFY_EQ(old_count + 1, fake_dynamic_table_.size());
FakeTrim(dynamic_size_limit());
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_test.cc
index dc6ab5813cf..ce44ccb04b5 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_test.cc
@@ -15,7 +15,6 @@
#include "http2/hpack/decoder/hpack_decoder_listener.h"
#include "http2/hpack/decoder/hpack_decoder_state.h"
#include "http2/hpack/decoder/hpack_decoder_tables.h"
-#include "http2/hpack/hpack_string.h"
#include "http2/hpack/http2_hpack_constants.h"
#include "http2/hpack/tools/hpack_block_builder.h"
#include "http2/hpack/tools/hpack_example.h"
@@ -63,10 +62,12 @@ typedef std::vector<HpackHeaderEntry> HpackHeaderEntries;
// and with VerifyDynamicTableContents.
class MockHpackDecoderListener : public HpackDecoderListener {
public:
- MOCK_METHOD0(OnHeaderListStart, void());
- MOCK_METHOD2(OnHeader,
- void(const HpackString& name, const HpackString& value));
- MOCK_METHOD0(OnHeaderListEnd, void());
+ MOCK_METHOD(void, OnHeaderListStart, (), (override));
+ MOCK_METHOD(void,
+ OnHeader,
+ (const std::string& name, const std::string& value),
+ (override));
+ MOCK_METHOD(void, OnHeaderListEnd, (), (override));
MOCK_METHOD(void,
OnHeaderErrorDetected,
(absl::string_view error_message),
@@ -95,10 +96,10 @@ class HpackDecoderTest : public QuicheTestWithParam<bool>,
// Called for each header name-value pair that is decoded, in the order they
// appear in the HPACK block. Multiple values for a given key will be emitted
// as multiple calls to OnHeader.
- void OnHeader(const HpackString& name, const HpackString& value) override {
+ void OnHeader(const std::string& name, const std::string& value) override {
ASSERT_TRUE(saw_start_);
ASSERT_FALSE(saw_end_);
- header_entries_.emplace_back(name.ToString(), value.ToString());
+ header_entries_.emplace_back(name, value);
}
// OnHeaderBlockEnd is called after successfully decoding an HPACK block. Will
@@ -190,8 +191,8 @@ class HpackDecoderTest : public QuicheTestWithParam<bool>,
const HpackStringPair* entry =
Lookup(dynamic_index + kFirstDynamicTableIndex - 1);
VERIFY_NE(entry, nullptr);
- VERIFY_EQ(entry->name.ToStringPiece(), name);
- VERIFY_EQ(entry->value.ToStringPiece(), value);
+ VERIFY_EQ(entry->name, name);
+ VERIFY_EQ(entry->value, value);
return AssertionSuccess();
}
AssertionResult VerifyNoEntry(size_t dynamic_index) {
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_collector.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_collector.cc
index a228b6a274e..de7d2e2edac 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_collector.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_collector.cc
@@ -4,10 +4,10 @@
#include "http2/hpack/decoder/hpack_entry_collector.h"
+#include "absl/strings/str_cat.h"
#include "http2/hpack/decoder/hpack_string_collector.h"
#include "http2/hpack/http2_hpack_constants.h"
#include "http2/platform/api/http2_logging.h"
-#include "http2/platform/api/http2_string_utils.h"
#include "http2/platform/api/http2_test_helpers.h"
#include "common/platform/api/quiche_test.h"
@@ -254,25 +254,25 @@ std::string HpackEntryCollector::ToString() const {
if (header_type_ == kInvalidHeaderType) {
result += "<unset>";
} else {
- Http2StrAppend(&result, header_type_);
+ absl::StrAppend(&result, header_type_);
}
}
if (index_ != 0) {
- Http2StrAppend(&result, " Index=", index_);
+ absl::StrAppend(&result, " Index=", index_);
}
if (!name_.IsClear()) {
- Http2StrAppend(&result, " Name", name_.ToString());
+ absl::StrAppend(&result, " Name", name_.ToString());
}
if (!value_.IsClear()) {
- Http2StrAppend(&result, " Value", value_.ToString());
+ absl::StrAppend(&result, " Value", value_.ToString());
}
if (!started_) {
EXPECT_FALSE(ended_);
- Http2StrAppend(&result, " !started");
+ absl::StrAppend(&result, " !started");
} else if (!ended_) {
- Http2StrAppend(&result, " !ended");
+ absl::StrAppend(&result, " !ended");
} else {
- Http2StrAppend(&result, " Complete");
+ absl::StrAppend(&result, " Complete");
}
return result;
}
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder.cc
index 4e4a4da6da3..deb07a6dcdc 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder.cc
@@ -86,7 +86,7 @@ DecodeStatus HpackEntryDecoder::Start(DecodeBuffer* db,
return status;
}
- HTTP2_BUG << "Unreachable";
+ HTTP2_BUG(http2_bug_63_1) << "Unreachable";
return DecodeStatus::kDecodeError;
}
@@ -252,7 +252,7 @@ bool HpackEntryDecoder::DispatchOnType(HpackEntryDecoderListener* listener) {
return true;
}
- HTTP2_BUG << "Unreachable, entry_type=" << entry_type;
+ HTTP2_BUG(http2_bug_63_2) << "Unreachable, entry_type=" << entry_type;
return true;
}
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_type_decoder.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_type_decoder.cc
index 99a0770556f..bdfaddc6229 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_type_decoder.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_entry_type_decoder.cc
@@ -9,7 +9,6 @@
#include "http2/platform/api/http2_flag_utils.h"
#include "http2/platform/api/http2_flags.h"
#include "http2/platform/api/http2_logging.h"
-#include "http2/platform/api/http2_string_utils.h"
namespace http2 {
@@ -354,7 +353,8 @@ DecodeStatus HpackEntryTypeDecoder::Start(DecodeBuffer* db) {
// All of those bits are 1, so the varint extends into another byte.
return varint_decoder_.StartExtended(7, db);
}
- HTTP2_BUG << "Unreachable, byte=" << std::hex << static_cast<uint32_t>(byte);
+ HTTP2_BUG(http2_bug_66_1)
+ << "Unreachable, byte=" << std::hex << static_cast<uint32_t>(byte);
HTTP2_CODE_COUNT_N(decompress_failure_3, 17, 23);
return DecodeStatus::kDecodeError;
}
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_collector.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_collector.cc
index 178096ccee2..eeed643d3ff 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_collector.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_string_collector.cc
@@ -9,7 +9,8 @@
#include <iosfwd>
#include <ostream>
-#include "http2/platform/api/http2_string_utils.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
#include "http2/platform/api/http2_test_helpers.h"
#include "common/platform/api/quiche_test.h"
@@ -69,7 +70,7 @@ void HpackStringCollector::OnStringData(const char* data, size_t length) {
absl::string_view sp(data, length);
EXPECT_TRUE(IsInProgress()) << ToString();
EXPECT_LE(sp.size(), len) << ToString();
- Http2StrAppend(&s, sp);
+ absl::StrAppend(&s, sp);
EXPECT_LE(s.size(), len) << ToString();
}
@@ -116,7 +117,7 @@ std::ostream& operator<<(std::ostream& out, const HpackStringCollector& v) {
if (!v.s.empty() && v.len != v.s.size()) {
out << " (" << v.s.size() << ")";
}
- return out << ", String=\"" << Http2HexEscape(v.s) << "\")";
+ return out << ", String=\"" << absl::CHexEscape(v.s) << "\")";
}
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/hpack_string.cc b/chromium/net/third_party/quiche/src/http2/hpack/hpack_string.cc
deleted file mode 100644
index fb9691cf9a6..00000000000
--- a/chromium/net/third_party/quiche/src/http2/hpack/hpack_string.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "http2/hpack/hpack_string.h"
-
-#include <utility>
-
-#include "absl/strings/str_cat.h"
-#include "http2/platform/api/http2_logging.h"
-
-namespace http2 {
-
-HpackString::HpackString(const char* data) : str_(data) {}
-HpackString::HpackString(absl::string_view str) : str_(std::string(str)) {}
-HpackString::HpackString(std::string str) : str_(std::move(str)) {}
-HpackString::HpackString(const HpackString& other) = default;
-HpackString::~HpackString() = default;
-
-absl::string_view HpackString::ToStringPiece() const {
- return str_;
-}
-
-bool HpackString::operator==(const HpackString& other) const {
- return str_ == other.str_;
-}
-bool HpackString::operator==(absl::string_view str) const {
- return str == str_;
-}
-
-bool operator==(absl::string_view a, const HpackString& b) {
- return b == a;
-}
-bool operator!=(absl::string_view a, const HpackString& b) {
- return !(b == a);
-}
-bool operator!=(const HpackString& a, const HpackString& b) {
- return !(a == b);
-}
-bool operator!=(const HpackString& a, absl::string_view b) {
- return !(a == b);
-}
-std::ostream& operator<<(std::ostream& out, const HpackString& v) {
- return out << v.ToString();
-}
-
-HpackStringPair::HpackStringPair(const HpackString& name,
- const HpackString& value)
- : name(name), value(value) {
- HTTP2_DVLOG(3) << DebugString() << " ctor";
-}
-
-HpackStringPair::HpackStringPair(absl::string_view name,
- absl::string_view value)
- : name(name), value(value) {
- HTTP2_DVLOG(3) << DebugString() << " ctor";
-}
-
-HpackStringPair::~HpackStringPair() {
- HTTP2_DVLOG(3) << DebugString() << " dtor";
-}
-
-std::string HpackStringPair::DebugString() const {
- return absl::StrCat("HpackStringPair(name=", name.ToString(),
- ", value=", value.ToString(), ")");
-}
-
-std::ostream& operator<<(std::ostream& os, const HpackStringPair& p) {
- os << p.DebugString();
- return os;
-}
-
-} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/hpack_string.h b/chromium/net/third_party/quiche/src/http2/hpack/hpack_string.h
deleted file mode 100644
index 78960467c99..00000000000
--- a/chromium/net/third_party/quiche/src/http2/hpack/hpack_string.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_HTTP2_HPACK_HPACK_STRING_H_
-#define QUICHE_HTTP2_HPACK_HPACK_STRING_H_
-
-// HpackString is currently a very simple container for a string, but allows us
-// to relatively easily experiment with alternate string storage mechanisms for
-// handling strings to be encoded with HPACK, or decoded from HPACK, such as
-// a ref-counted string.
-
-#include <stddef.h>
-
-#include <iosfwd>
-#include <string>
-
-#include "absl/strings/string_view.h"
-#include "common/platform/api/quiche_export.h"
-
-namespace http2 {
-
-class QUICHE_EXPORT_PRIVATE HpackString {
- public:
- explicit HpackString(const char* data);
- explicit HpackString(absl::string_view str);
- explicit HpackString(std::string str);
- HpackString(const HpackString& other);
-
- // Not sure yet whether this move ctor is required/sensible.
- HpackString(HpackString&& other) = default;
-
- ~HpackString();
-
- size_t size() const { return str_.size(); }
- const std::string& ToString() const { return str_; }
- absl::string_view ToStringPiece() const;
-
- bool operator==(const HpackString& other) const;
-
- bool operator==(absl::string_view str) const;
-
- private:
- std::string str_;
-};
-
-QUICHE_EXPORT_PRIVATE bool operator==(absl::string_view a,
- const HpackString& b);
-QUICHE_EXPORT_PRIVATE bool operator!=(absl::string_view a,
- const HpackString& b);
-QUICHE_EXPORT_PRIVATE bool operator!=(const HpackString& a,
- const HpackString& b);
-QUICHE_EXPORT_PRIVATE bool operator!=(const HpackString& a,
- absl::string_view b);
-QUICHE_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
- const HpackString& v);
-
-struct QUICHE_EXPORT_PRIVATE HpackStringPair {
- HpackStringPair(const HpackString& name, const HpackString& value);
- HpackStringPair(absl::string_view name, absl::string_view value);
- ~HpackStringPair();
-
- // Returns the size of a header entry with this name and value, per the RFC:
- // http://httpwg.org/specs/rfc7541.html#calculating.table.size
- size_t size() const { return 32 + name.size() + value.size(); }
-
- std::string DebugString() const;
-
- const HpackString name;
- const HpackString value;
-};
-
-QUICHE_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
- const HpackStringPair& p);
-
-} // namespace http2
-
-#endif // QUICHE_HTTP2_HPACK_HPACK_STRING_H_
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/hpack_string_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/hpack_string_test.cc
deleted file mode 100644
index c8462e82d03..00000000000
--- a/chromium/net/third_party/quiche/src/http2/hpack/hpack_string_test.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "http2/hpack/hpack_string.h"
-
-// Tests of HpackString.
-
-#include <utility>
-
-#include "http2/platform/api/http2_logging.h"
-#include "http2/platform/api/http2_test_helpers.h"
-#include "common/platform/api/quiche_test.h"
-
-using ::testing::AssertionFailure;
-using ::testing::AssertionResult;
-using ::testing::AssertionSuccess;
-
-namespace http2 {
-namespace test {
-namespace {
-
-const char kStr0[] = "s0: Some string to be copied into another string.";
-const char kStr1[] = "S1 - some string to be copied into yet another string.";
-
-class HpackStringTest : public QuicheTest {
- protected:
- AssertionResult VerifyNotEqual(HpackString* actual,
- const std::string& not_expected_str) {
- const char* not_expected_ptr = not_expected_str.c_str();
- absl::string_view not_expected_sp(not_expected_str);
-
- VERIFY_NE(*actual, not_expected_ptr);
- VERIFY_NE(*actual, not_expected_sp);
- VERIFY_NE(*actual, not_expected_str);
- VERIFY_NE(actual->ToStringPiece(), not_expected_sp);
-
- if (!(not_expected_ptr != *actual)) {
- return AssertionFailure();
- }
- if (!(not_expected_sp != *actual)) {
- return AssertionFailure();
- }
- if (!(not_expected_str != *actual)) {
- return AssertionFailure();
- }
- if (!(not_expected_sp != actual->ToStringPiece())) {
- return AssertionFailure();
- }
-
- return AssertionSuccess();
- }
-
- AssertionResult VerifyEqual(HpackString* actual,
- const std::string& expected_str) {
- VERIFY_EQ(actual->size(), expected_str.size());
-
- const char* expected_ptr = expected_str.c_str();
- const absl::string_view expected_sp(expected_str);
-
- VERIFY_EQ(*actual, expected_ptr);
- VERIFY_EQ(*actual, expected_sp);
- VERIFY_EQ(*actual, expected_str);
- VERIFY_EQ(actual->ToStringPiece(), expected_sp);
-
- if (!(expected_sp == *actual)) {
- return AssertionFailure();
- }
- if (!(expected_ptr == *actual)) {
- return AssertionFailure();
- }
- if (!(expected_str == *actual)) {
- return AssertionFailure();
- }
- if (!(expected_sp == actual->ToStringPiece())) {
- return AssertionFailure();
- }
-
- return AssertionSuccess();
- }
-};
-
-TEST_F(HpackStringTest, CharArrayConstructor) {
- HpackString hs0(kStr0);
- EXPECT_TRUE(VerifyEqual(&hs0, kStr0));
- EXPECT_TRUE(VerifyNotEqual(&hs0, kStr1));
-
- HpackString hs1(kStr1);
- EXPECT_TRUE(VerifyEqual(&hs1, kStr1));
- EXPECT_TRUE(VerifyNotEqual(&hs1, kStr0));
-}
-
-TEST_F(HpackStringTest, StringPieceConstructor) {
- absl::string_view sp0(kStr0);
- HpackString hs0(sp0);
- EXPECT_TRUE(VerifyEqual(&hs0, kStr0));
- EXPECT_TRUE(VerifyNotEqual(&hs0, kStr1));
-
- absl::string_view sp1(kStr1);
- HpackString hs1(sp1);
- EXPECT_TRUE(VerifyEqual(&hs1, kStr1));
- EXPECT_TRUE(VerifyNotEqual(&hs1, kStr0));
-}
-
-TEST_F(HpackStringTest, MoveStringConstructor) {
- std::string str0(kStr0);
- HpackString hs0(str0);
- EXPECT_TRUE(VerifyEqual(&hs0, kStr0));
- EXPECT_TRUE(VerifyNotEqual(&hs0, kStr1));
-
- std::string str1(kStr1);
- HpackString hs1(str1);
- EXPECT_TRUE(VerifyEqual(&hs1, kStr1));
- EXPECT_TRUE(VerifyNotEqual(&hs1, kStr0));
-}
-
-TEST_F(HpackStringTest, CopyConstructor) {
- absl::string_view sp0(kStr0);
- HpackString hs0(sp0);
- HpackString hs1(hs0);
- EXPECT_EQ(hs0, hs1);
-
- EXPECT_TRUE(VerifyEqual(&hs0, kStr0));
- EXPECT_TRUE(VerifyEqual(&hs1, kStr0));
-
- EXPECT_TRUE(VerifyNotEqual(&hs0, kStr1));
- EXPECT_TRUE(VerifyNotEqual(&hs1, kStr1));
-}
-
-TEST_F(HpackStringTest, MoveConstructor) {
- absl::string_view sp0(kStr0);
- HpackString hs0(sp0);
- EXPECT_TRUE(VerifyEqual(&hs0, kStr0));
- EXPECT_TRUE(VerifyNotEqual(&hs0, ""));
-
- HpackString hs1(std::move(hs0));
- EXPECT_NE(hs0, hs1);
-
- EXPECT_TRUE(VerifyEqual(&hs1, kStr0));
- EXPECT_TRUE(VerifyEqual(&hs0, ""));
- EXPECT_TRUE(VerifyNotEqual(&hs1, ""));
-
- HTTP2_LOG(INFO) << hs0;
- HTTP2_LOG(INFO) << hs1;
-}
-
-} // namespace
-} // namespace test
-} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder.cc b/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder.cc
index 8f85304b8d5..3dbda955f0d 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder.cc
@@ -46,7 +46,7 @@ void HpackBlockBuilder::AppendEntryTypeAndVarint(HpackEntryType entry_type,
prefix_length = 4;
break;
default:
- HTTP2_BUG << "Unreached, entry_type=" << entry_type;
+ HTTP2_BUG(http2_bug_110_1) << "Unreached, entry_type=" << entry_type;
high_bits = 0;
prefix_length = 0;
break;
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 25f44c905dc..00664b27f14 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
@@ -40,9 +40,9 @@ void HpackExampleToStringOrDie(absl::string_view example, std::string* output) {
example.remove_prefix(pos + 1);
continue;
}
- HTTP2_BUG << "Can't parse byte " << static_cast<int>(c0)
- << absl::StrCat(" (0x", Http2Hex(c0), ")")
- << "\nExample: " << example;
+ HTTP2_BUG(http2_bug_107_1)
+ << "Can't parse byte " << static_cast<int>(c0)
+ << absl::StrCat(" (0x", absl::Hex(c0), ")") << "\nExample: " << example;
}
QUICHE_CHECK_LT(0u, output->size()) << "Example is empty.";
}
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.cc b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.cc
index 5ba0b74245a..a9e6e74cb07 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.cc
@@ -5,7 +5,6 @@
#include "http2/hpack/varint/hpack_varint_decoder.h"
#include "absl/strings/str_cat.h"
-#include "http2/platform/api/http2_string_utils.h"
namespace http2 {
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 7b73edb8d94..a8ba99a8a31 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
@@ -162,7 +162,7 @@ class HpackVarintRoundTripTest : public RandomDecoderTest {
for (const uint64_t value : values) {
Encode(value, prefix_length); // Sets buffer_.
- std::string msg = absl::StrCat("value=", value, " (0x", Http2Hex(value),
+ std::string msg = absl::StrCat("value=", value, " (0x", absl::Hex(value),
"), prefix_length=", prefix_length,
", expected_bytes=", expected_bytes, "\n",
Http2HexDump(buffer_));
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 d333cf45ecf..2faf2f94ebe 100644
--- a/chromium/net/third_party/quiche/src/http2/http2_constants.cc
+++ b/chromium/net/third_party/quiche/src/http2/http2_constants.cc
@@ -53,7 +53,7 @@ std::string Http2FrameFlagsToString(Http2FrameType type, uint8_t flags) {
if (!s.empty()) {
s.push_back('|');
}
- Http2StrAppend(&s, v);
+ absl::StrAppend(&s, v);
flags ^= bit;
};
if (flags & 0x01) {
@@ -123,7 +123,7 @@ std::string Http2ErrorCodeToString(uint32_t v) {
case 0xd:
return "HTTP_1_1_REQUIRED";
}
- return absl::StrCat("UnknownErrorCode(0x", Http2Hex(v), ")");
+ return absl::StrCat("UnknownErrorCode(0x", absl::Hex(v), ")");
}
std::string Http2ErrorCodeToString(Http2ErrorCode v) {
return Http2ErrorCodeToString(static_cast<uint32_t>(v));
@@ -144,7 +144,7 @@ std::string Http2SettingsParameterToString(uint32_t v) {
case 0x6:
return "MAX_HEADER_LIST_SIZE";
}
- return absl::StrCat("UnknownSettingsParameter(0x", Http2Hex(v), ")");
+ return absl::StrCat("UnknownSettingsParameter(0x", absl::Hex(v), ")");
}
std::string Http2SettingsParameterToString(Http2SettingsParameter v) {
return Http2SettingsParameterToString(static_cast<uint32_t>(v));
diff --git a/chromium/net/third_party/quiche/src/http2/http2_constants.h b/chromium/net/third_party/quiche/src/http2/http2_constants.h
index cd05eb45d1b..65e55dbc1db 100644
--- a/chromium/net/third_party/quiche/src/http2/http2_constants.h
+++ b/chromium/net/third_party/quiche/src/http2/http2_constants.h
@@ -48,12 +48,8 @@ enum class Http2FrameType : uint8_t {
// Is the frame type known/supported?
inline bool IsSupportedHttp2FrameType(uint32_t v) {
- if (GetHttp2RestartFlag(http2_parse_priority_update_frame) &&
- v == static_cast<uint32_t>(Http2FrameType::PRIORITY_UPDATE)) {
- return true;
- }
-
- return v <= static_cast<uint32_t>(Http2FrameType::ALTSVC);
+ return v <= static_cast<uint32_t>(Http2FrameType::ALTSVC) ||
+ v == static_cast<uint32_t>(Http2FrameType::PRIORITY_UPDATE);
}
inline bool IsSupportedHttp2FrameType(Http2FrameType v) {
return IsSupportedHttp2FrameType(static_cast<uint32_t>(v));
diff --git a/chromium/net/third_party/quiche/src/http2/http2_structures_test.cc b/chromium/net/third_party/quiche/src/http2/http2_structures_test.cc
index ffd67b3dacc..44712bc13b9 100644
--- a/chromium/net/third_party/quiche/src/http2/http2_structures_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/http2_structures_test.cc
@@ -21,7 +21,6 @@
#include "absl/strings/str_cat.h"
#include "http2/http2_structures_test_util.h"
-#include "http2/platform/api/http2_string_utils.h"
#include "http2/platform/api/http2_test_helpers.h"
#include "http2/test_tools/http2_random.h"
#include "common/platform/api/quiche_test.h"
diff --git a/chromium/net/third_party/quiche/src/http2/platform/api/http2_bug_tracker.h b/chromium/net/third_party/quiche/src/http2/platform/api/http2_bug_tracker.h
index 93ad67717f1..6f2fe51418e 100644
--- a/chromium/net/third_party/quiche/src/http2/platform/api/http2_bug_tracker.h
+++ b/chromium/net/third_party/quiche/src/http2/platform/api/http2_bug_tracker.h
@@ -5,10 +5,16 @@
#ifndef QUICHE_HTTP2_PLATFORM_API_HTTP2_BUG_TRACKER_H_
#define QUICHE_HTTP2_PLATFORM_API_HTTP2_BUG_TRACKER_H_
-#include "net/http2/platform/impl/http2_bug_tracker_impl.h"
+#include "common/platform/api/quiche_bug_tracker.h"
+
+#define HTTP2_BUG QUICHE_BUG
+#define HTTP2_BUG_IF QUICHE_BUG_IF
+
+// V2 macros are the same as all the HTTP2_BUG flavor above, but they take a
+// bug_id parameter.
+#define HTTP2_BUG_V2 QUICHE_BUG
+#define HTTP2_BUG_IF_V2 QUICHE_BUG_IF
-#define HTTP2_BUG HTTP2_BUG_IMPL
-#define HTTP2_BUG_IF HTTP2_BUG_IF_IMPL
#define FLAGS_http2_always_log_bugs_for_tests \
FLAGS_http2_always_log_bugs_for_tests_IMPL
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 ec421b7efb9..087bd254a96 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
@@ -15,11 +15,6 @@
namespace http2 {
template <typename... Args>
-inline void Http2StrAppend(std::string* output, const Args&... args) {
- Http2StrAppendImpl(output, std::forward<const Args&>(args)...);
-}
-
-template <typename... Args>
inline std::string Http2StringPrintf(const Args&... args) {
return Http2StringPrintfImpl(std::forward<const Args&>(args)...);
}
@@ -36,16 +31,6 @@ inline std::string Http2HexDump(absl::string_view data) {
return Http2HexDumpImpl(data);
}
-inline std::string Http2HexEscape(absl::string_view data) {
- return Http2HexEscapeImpl(data);
-}
-
-template <typename Number>
-inline std::string Http2Hex(Number number) {
- static_assert(std::is_integral<Number>::value, "Number has to be an int");
- return Http2HexImpl(number);
-}
-
} // namespace http2
#endif // QUICHE_HTTP2_PLATFORM_API_HTTP2_STRING_UTILS_H_
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
index 1621b52d82a..9ee7869edd3 100644
--- 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
@@ -4,110 +4,12 @@
#include "http2/platform/api/http2_string_utils.h"
-#include <cstdint>
-
-#include "absl/strings/string_view.h"
#include "common/platform/api/quiche_test.h"
namespace http2 {
namespace test {
namespace {
-TEST(Http2StringUtilsTest, Http2StrAppend) {
- // No arguments on empty string.
- std::string output;
- Http2StrAppend(&output);
- EXPECT_TRUE(output.empty());
-
- // Single string-like argument.
- const char kFoo[] = "foo";
- const std::string string_foo(kFoo);
- const absl::string_view stringpiece_foo(string_foo);
- Http2StrAppend(&output, kFoo);
- EXPECT_EQ("foo", output);
- Http2StrAppend(&output, string_foo);
- EXPECT_EQ("foofoo", output);
- Http2StrAppend(&output, stringpiece_foo);
- EXPECT_EQ("foofoofoo", output);
-
- // No arguments on non-empty string.
- Http2StrAppend(&output);
- EXPECT_EQ("foofoofoo", output);
-
- output.clear();
-
- // Two string-like arguments.
- const char kBar[] = "bar";
- const absl::string_view stringpiece_bar(kBar);
- const std::string string_bar(kBar);
- Http2StrAppend(&output, kFoo, kBar);
- EXPECT_EQ("foobar", output);
- Http2StrAppend(&output, kFoo, string_bar);
- EXPECT_EQ("foobarfoobar", output);
- Http2StrAppend(&output, kFoo, stringpiece_bar);
- EXPECT_EQ("foobarfoobarfoobar", output);
- Http2StrAppend(&output, string_foo, kBar);
- EXPECT_EQ("foobarfoobarfoobarfoobar", output);
-
- output.clear();
-
- Http2StrAppend(&output, string_foo, string_bar);
- EXPECT_EQ("foobar", output);
- Http2StrAppend(&output, string_foo, stringpiece_bar);
- EXPECT_EQ("foobarfoobar", output);
- Http2StrAppend(&output, stringpiece_foo, kBar);
- EXPECT_EQ("foobarfoobarfoobar", output);
- Http2StrAppend(&output, stringpiece_foo, string_bar);
- EXPECT_EQ("foobarfoobarfoobarfoobar", output);
-
- output.clear();
-
- Http2StrAppend(&output, stringpiece_foo, stringpiece_bar);
- EXPECT_EQ("foobar", output);
-
- // Many-many arguments.
- Http2StrAppend(&output, "foo", "bar", "baz", "qux", "quux", "quuz", "corge",
- "grault", "garply", "waldo", "fred", "plugh", "xyzzy", "thud");
- EXPECT_EQ(
- "foobarfoobarbazquxquuxquuzcorgegraultgarplywaldofredplughxyzzythud",
- output);
-
- output.clear();
-
- // Numerical arguments.
- const int16_t i = 1;
- const uint64_t u = 8;
- const double d = 3.1415;
-
- Http2StrAppend(&output, i, " ", u);
- EXPECT_EQ("1 8", output);
- Http2StrAppend(&output, d, i, i, u, i);
- EXPECT_EQ("1 83.14151181", output);
- Http2StrAppend(&output, "i: ", i, ", u: ", u, ", d: ", d);
- EXPECT_EQ("1 83.14151181i: 1, u: 8, d: 3.1415", output);
-
- output.clear();
-
- // Boolean arguments.
- const bool t = true;
- const bool f = false;
-
- Http2StrAppend(&output, t);
- EXPECT_EQ("1", output);
- Http2StrAppend(&output, f);
- EXPECT_EQ("10", output);
- Http2StrAppend(&output, f, t, t, f);
- EXPECT_EQ("100110", output);
-
- output.clear();
-
- // Mixed string-like, numerical, and Boolean arguments.
- Http2StrAppend(&output, kFoo, i, string_foo, f, u, t, stringpiece_bar, d, t);
- EXPECT_EQ("foo1foo081bar3.14151", output);
- Http2StrAppend(&output, d, t, t, string_bar, i, u, kBar, t, d, f);
- EXPECT_EQ("foo1foo081bar3.141513.141511bar18bar13.14150", output);
-}
-
TEST(Http2StringUtilsTest, Http2StringPrintf) {
EXPECT_EQ("", Http2StringPrintf("%s", ""));
EXPECT_EQ("foobar", Http2StringPrintf("%sbar", "foo"));
diff --git a/chromium/net/third_party/quiche/src/http2/test_tools/frame_parts.cc b/chromium/net/third_party/quiche/src/http2/test_tools/frame_parts.cc
index 1a148709665..a053beb10df 100644
--- a/chromium/net/third_party/quiche/src/http2/test_tools/frame_parts.cc
+++ b/chromium/net/third_party/quiche/src/http2/test_tools/frame_parts.cc
@@ -6,9 +6,9 @@
#include <type_traits>
+#include "absl/strings/escaping.h"
#include "http2/http2_structures_test_util.h"
#include "http2/platform/api/http2_logging.h"
-#include "http2/platform/api/http2_string_utils.h"
#include "http2/platform/api/http2_test_helpers.h"
#include "common/platform/api/quiche_test.h"
@@ -442,16 +442,16 @@ void FrameParts::OnFrameSizeError(const Http2FrameHeader& header) {
void FrameParts::OutputTo(std::ostream& out) const {
out << "FrameParts{\n frame_header_: " << frame_header_ << "\n";
if (!payload_.empty()) {
- out << " payload_=\"" << Http2HexEscape(payload_) << "\"\n";
+ out << " payload_=\"" << absl::CHexEscape(payload_) << "\"\n";
}
if (!padding_.empty()) {
- out << " padding_=\"" << Http2HexEscape(padding_) << "\"\n";
+ out << " padding_=\"" << absl::CHexEscape(padding_) << "\"\n";
}
if (!altsvc_origin_.empty()) {
- out << " altsvc_origin_=\"" << Http2HexEscape(altsvc_origin_) << "\"\n";
+ out << " altsvc_origin_=\"" << absl::CHexEscape(altsvc_origin_) << "\"\n";
}
if (!altsvc_value_.empty()) {
- out << " altsvc_value_=\"" << Http2HexEscape(altsvc_value_) << "\"\n";
+ out << " altsvc_value_=\"" << absl::CHexEscape(altsvc_value_) << "\"\n";
}
if (opt_priority_) {
out << " priority=" << opt_priority_.value() << "\n";
diff --git a/chromium/net/third_party/quiche/src/http2/tools/http2_frame_builder.cc b/chromium/net/third_party/quiche/src/http2/tools/http2_frame_builder.cc
index d6cd11059f4..1481594fbe5 100644
--- a/chromium/net/third_party/quiche/src/http2/tools/http2_frame_builder.cc
+++ b/chromium/net/third_party/quiche/src/http2/tools/http2_frame_builder.cc
@@ -11,7 +11,7 @@
#include <netinet/in.h> // for htonl, htons
#endif
-#include "http2/platform/api/http2_string_utils.h"
+#include "absl/strings/str_cat.h"
#include "common/platform/api/quiche_test.h"
namespace http2 {
@@ -31,7 +31,7 @@ Http2FrameBuilder::Http2FrameBuilder(const Http2FrameHeader& v) {
}
void Http2FrameBuilder::Append(absl::string_view s) {
- Http2StrAppend(&buffer_, s);
+ absl::StrAppend(&buffer_, s);
}
void Http2FrameBuilder::AppendBytes(const void* data, uint32_t num_bytes) {
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 b2fd80c9a72..8b4a27f0866 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
@@ -7,7 +7,6 @@
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_flags.h"
-#include "quic/platform/api/quic_ptr_util.h"
#include "quic/platform/api/quic_server_stats.h"
namespace quic {
@@ -121,10 +120,10 @@ WriteResult QuicBatchWriterBase::InternalWritePacket(
// Since buffered_writes has been emptied, this write must have been
// buffered successfully.
- QUIC_BUG_IF(!buffered) << "Failed to push to an empty batch buffer."
- << " self_addr:" << self_address.ToString()
- << ", peer_addr:" << peer_address.ToString()
- << ", buf_len:" << buf_len;
+ QUIC_BUG_IF(quic_bug_10826_1, !buffered)
+ << "Failed to push to an empty batch buffer."
+ << " self_addr:" << self_address.ToString()
+ << ", peer_addr:" << peer_address.ToString() << ", buf_len:" << buf_len;
}
result.send_time_offset = release_time.release_time_offset;
diff --git a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_buffer.cc b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_buffer.cc
index 0de792dded8..8a450d78114 100644
--- a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_buffer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_buffer.cc
@@ -75,11 +75,12 @@ QuicBatchWriterBuffer::PushResult QuicBatchWriterBuffer::PushBufferedWrite(
} else if (IsInternalBuffer(buffer, buf_len)) {
memmove(next_write_location, buffer, buf_len);
} else {
- QUIC_BUG << "Buffer[" << static_cast<const void*>(buffer) << ", "
- << static_cast<const void*>(buffer + buf_len)
- << ") overlaps with internal buffer["
- << static_cast<const void*>(buffer_) << ", "
- << static_cast<const void*>(buffer_end()) << ")";
+ QUIC_BUG(quic_bug_10831_1)
+ << "Buffer[" << static_cast<const void*>(buffer) << ", "
+ << static_cast<const void*>(buffer + buf_len)
+ << ") overlaps with internal buffer["
+ << static_cast<const void*>(buffer_) << ", "
+ << static_cast<const void*>(buffer_end()) << ")";
return result;
}
result.buffer_copied = true;
diff --git a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_gso_batch_writer.h b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_gso_batch_writer.h
index 75683d17b6d..f87e9f8e78d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_gso_batch_writer.h
+++ b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_gso_batch_writer.h
@@ -100,7 +100,7 @@ class QUIC_EXPORT_PRIVATE QuicGsoBatchWriter : public QuicUdpBatchWriter {
batch_buffer().PopBufferedWrite(buffered_writes().size());
- QUIC_BUG_IF(!buffered_writes().empty())
+ QUIC_BUG_IF(quic_bug_12544_1, !buffered_writes().empty())
<< "All packets should have been written on a successful return";
return result;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_sendmmsg_batch_writer.cc b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_sendmmsg_batch_writer.cc
index ec8e4ae55be..d5c03298607 100644
--- a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_sendmmsg_batch_writer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_sendmmsg_batch_writer.cc
@@ -55,7 +55,8 @@ QuicSendmmsgBatchWriter::InternalFlushImpl(size_t cmsg_space,
QUICHE_DCHECK_EQ(0, num_packets_sent);
break;
} else if (num_packets_sent == 0) {
- QUIC_BUG << "WriteMultiplePackets returned OK, but no packets were sent.";
+ QUIC_BUG(quic_bug_10825_1)
+ << "WriteMultiplePackets returned OK, but no packets were sent.";
write_result = WriteResult(WRITE_STATUS_ERROR, EIO);
break;
}
@@ -74,7 +75,7 @@ QuicSendmmsgBatchWriter::InternalFlushImpl(size_t cmsg_space,
return result;
}
- QUIC_BUG_IF(!buffered_writes().empty())
+ QUIC_BUG_IF(quic_bug_12537_1, !buffered_writes().empty())
<< "All packets should have been written on a successful return";
write_result.bytes_written = result.bytes_written;
return result;
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 198d455b724..48fe9a82c05 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
@@ -15,6 +15,7 @@
#include "quic/core/crypto/quic_encrypter.h"
#include "quic/core/frames/quic_ack_frequency_frame.h"
#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"
@@ -81,7 +82,8 @@ class ChloFramerVisitor : public QuicFramerVisitorInterface,
bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) override;
bool OnAckFrequencyFrame(const QuicAckFrequencyFrame& farme) override;
void OnPacketComplete() override {}
- bool IsValidStatelessResetToken(QuicUint128 token) const override;
+ bool IsValidStatelessResetToken(
+ const StatelessResetToken& token) const override;
void OnAuthenticatedIetfStatelessResetPacket(
const QuicIetfStatelessResetPacket& /*packet*/) override {}
void OnKeyUpdate(KeyUpdateReason /*reason*/) override;
@@ -303,7 +305,7 @@ bool ChloFramerVisitor::OnAckFrequencyFrame(
}
bool ChloFramerVisitor::IsValidStatelessResetToken(
- QuicUint128 /*token*/) const {
+ const StatelessResetToken& /*token*/) const {
return false;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.cc
index babb6e35f0a..657cad1a46a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.cc
@@ -171,42 +171,43 @@ void BandwidthSampler::OnPacketSent(
if (unacked_packet_map_ != nullptr && !unacked_packet_map_->empty()) {
QuicPacketNumber maybe_least_unacked =
unacked_packet_map_->GetLeastUnacked();
- QUIC_BUG << "BandwidthSampler in-flight packet map has exceeded maximum "
- "number of tracked packets("
- << max_tracked_packets_
- << "). First tracked: " << connection_state_map_.first_packet()
- << "; last tracked: " << connection_state_map_.last_packet()
- << "; entry_slots_used: "
- << connection_state_map_.entry_slots_used()
- << "; number_of_present_entries: "
- << connection_state_map_.number_of_present_entries()
- << "; packet number: " << packet_number
- << "; unacked_map: " << unacked_packet_map_->DebugString()
- << "; total_bytes_sent: " << total_bytes_sent_
- << "; total_bytes_acked: " << total_bytes_acked_
- << "; total_bytes_lost: " << total_bytes_lost_
- << "; total_bytes_neutered: " << total_bytes_neutered_
- << "; last_acked_packet_sent_time: "
- << last_acked_packet_sent_time_
- << "; total_bytes_sent_at_last_acked_packet: "
- << total_bytes_sent_at_last_acked_packet_
- << "; least_unacked_packet_info: "
- << (unacked_packet_map_->IsUnacked(maybe_least_unacked)
- ? unacked_packet_map_
- ->GetTransmissionInfo(maybe_least_unacked)
- .DebugString()
- : "n/a");
+ QUIC_BUG(quic_bug_10437_1)
+ << "BandwidthSampler in-flight packet map has exceeded maximum "
+ "number of tracked packets("
+ << max_tracked_packets_
+ << "). First tracked: " << connection_state_map_.first_packet()
+ << "; last tracked: " << connection_state_map_.last_packet()
+ << "; entry_slots_used: " << connection_state_map_.entry_slots_used()
+ << "; number_of_present_entries: "
+ << connection_state_map_.number_of_present_entries()
+ << "; packet number: " << packet_number
+ << "; unacked_map: " << unacked_packet_map_->DebugString()
+ << "; total_bytes_sent: " << total_bytes_sent_
+ << "; total_bytes_acked: " << total_bytes_acked_
+ << "; total_bytes_lost: " << total_bytes_lost_
+ << "; total_bytes_neutered: " << total_bytes_neutered_
+ << "; last_acked_packet_sent_time: " << last_acked_packet_sent_time_
+ << "; total_bytes_sent_at_last_acked_packet: "
+ << total_bytes_sent_at_last_acked_packet_
+ << "; least_unacked_packet_info: "
+ << (unacked_packet_map_->IsUnacked(maybe_least_unacked)
+ ? unacked_packet_map_
+ ->GetTransmissionInfo(maybe_least_unacked)
+ .DebugString()
+ : "n/a");
} else {
- QUIC_BUG << "BandwidthSampler in-flight packet map has exceeded maximum "
- "number of tracked packets.";
+ QUIC_BUG(quic_bug_10437_2)
+ << "BandwidthSampler in-flight packet map has exceeded maximum "
+ "number of tracked packets.";
}
}
bool success = connection_state_map_.Emplace(packet_number, sent_time, bytes,
bytes_in_flight + bytes, *this);
- QUIC_BUG_IF(!success) << "BandwidthSampler failed to insert the packet "
- "into the map, most likely because it's already "
- "in it.";
+ QUIC_BUG_IF(quic_bug_10437_3, !success)
+ << "BandwidthSampler failed to insert the packet "
+ "into the map, most likely because it's already "
+ "in it.";
}
void BandwidthSampler::OnPacketNeutered(QuicPacketNumber packet_number) {
@@ -355,7 +356,8 @@ BandwidthSample BandwidthSampler::OnPacketAcknowledgedInner(
// current packet was sent. In that case, there is no bandwidth sample to
// make.
if (sent_packet.last_acked_packet_sent_time == QuicTime::Zero()) {
- QUIC_BUG << "sent_packet.last_acked_packet_sent_time is zero";
+ QUIC_BUG(quic_bug_10437_4)
+ << "sent_packet.last_acked_packet_sent_time is zero";
return BandwidthSample();
}
@@ -427,8 +429,8 @@ BandwidthSample BandwidthSampler::OnPacketAcknowledgedInner(
bool BandwidthSampler::ChooseA0Point(QuicByteCount total_bytes_acked,
AckPoint* a0) {
if (a0_candidates_.empty()) {
- QUIC_BUG << "No A0 point candicates. total_bytes_acked:"
- << total_bytes_acked;
+ QUIC_BUG(quic_bug_10437_5)
+ << "No A0 point candicates. total_bytes_acked:" << total_bytes_acked;
return false;
}
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 dfb834cd05b..d24e50efdbc 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
@@ -9,6 +9,7 @@
#include "quic/core/quic_time.h"
#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_flag_utils.h"
+#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
namespace quic {
@@ -188,7 +189,6 @@ void Bbr2NetworkModel::OnCongestionEventStart(
void Bbr2NetworkModel::AdaptLowerBounds(
const Bbr2CongestionEvent& congestion_event) {
if (Params().bw_lo_mode_ != Bbr2Params::DEFAULT) {
- QUICHE_DCHECK(Params().bw_startup);
if (congestion_event.bytes_lost == 0) {
return;
}
@@ -202,6 +202,10 @@ void Bbr2NetworkModel::AdaptLowerBounds(
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_ =
@@ -227,12 +231,13 @@ void Bbr2NetworkModel::AdaptLowerBounds(
static_cast<double>(congestion_event.prior_cwnd));
break;
case Bbr2Params::DEFAULT:
- QUIC_BUG << "Unreachable case 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_, so this backs
- // that multiplication out to allow the pacing rate to decrease,
- // but not below bandwidth_latest_ * 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_ *
@@ -241,6 +246,15 @@ void Bbr2NetworkModel::AdaptLowerBounds(
// 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();
+ }
// This early return ignores inflight_lo as well.
return;
}
@@ -273,13 +287,7 @@ void Bbr2NetworkModel::OnCongestionEventFinish(
QuicPacketNumber least_unacked_packet,
const Bbr2CongestionEvent& congestion_event) {
if (congestion_event.end_of_round_trip) {
- if (!reset_max_bytes_delivered_) {
- bytes_lost_in_round_ = 0;
- loss_events_in_round_ = 0;
- } else {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_reset_max_bytes_delivered, 1, 2);
- OnNewRound();
- }
+ OnNewRound();
}
bandwidth_sampler_.RemoveObsoletePackets(least_unacked_packet);
@@ -354,19 +362,11 @@ bool Bbr2NetworkModel::IsInflightTooHigh(
}
void Bbr2NetworkModel::RestartRoundEarly() {
- if (!reset_max_bytes_delivered_) {
- bytes_lost_in_round_ = 0;
- loss_events_in_round_ = 0;
- max_bytes_delivered_in_round_ = 0;
- } else {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_reset_max_bytes_delivered, 2, 2);
- OnNewRound();
- }
+ OnNewRound();
round_trip_counter_.RestartRound();
}
void Bbr2NetworkModel::OnNewRound() {
- QUICHE_DCHECK(reset_max_bytes_delivered_);
bytes_lost_in_round_ = 0;
loss_events_in_round_ = 0;
max_bytes_delivered_in_round_ = 0;
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 8b53c1b741d..8f5d4185dfc 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
@@ -208,9 +208,6 @@ struct QUIC_EXPORT_PRIVATE Bbr2Params {
// Set the pacing gain to 25% larger than the recent BW increase in STARTUP.
bool decrease_startup_pacing_at_end_of_round = false;
-
- // Latch the flag for quic_bbr2_bw_startup.
- const bool bw_startup = GetQuicReloadableFlag(quic_bbr2_bw_startup);
};
class QUIC_EXPORT_PRIVATE RoundTripCounter {
@@ -538,6 +535,9 @@ class QUIC_EXPORT_PRIVATE Bbr2NetworkModel {
QuicBandwidth bandwidth_latest_ = QuicBandwidth::Zero();
// Max bandwidth of recent rounds. Updated once per round.
QuicBandwidth bandwidth_lo_ = bandwidth_lo_default();
+ // bandwidth_lo_ at the beginning of a round with loss. Only used when the
+ // bw_lo_mode is non-default.
+ QuicBandwidth prior_bandwidth_lo_ = QuicBandwidth::Zero();
// Max inflight in the current round. Updated once per congestion event.
QuicByteCount inflight_latest_ = 0;
@@ -552,8 +552,6 @@ class QUIC_EXPORT_PRIVATE Bbr2NetworkModel {
bool full_bandwidth_reached_ = false;
QuicBandwidth full_bandwidth_baseline_ = QuicBandwidth::Zero();
QuicRoundTripCount rounds_without_bandwidth_growth_ = 0;
- const bool reset_max_bytes_delivered_ =
- GetQuicReloadableFlag(quic_bbr2_reset_max_bytes_delivered);
};
enum class Bbr2Mode : uint8_t {
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 78bd06d4b24..9045d7e034b 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
@@ -205,10 +205,10 @@ Bbr2ProbeBwMode::AdaptUpperBoundsResult Bbr2ProbeBwMode::MaybeAdaptUpperBounds(
model_->total_bytes_acked() -
congestion_event.last_packet_send_state.total_bytes_acked;
} else {
- QUIC_BUG << "Total_bytes_acked(" << model_->total_bytes_acked()
- << ") < send_state.total_bytes_acked("
- << congestion_event.last_packet_send_state.total_bytes_acked
- << ")";
+ QUIC_BUG(quic_bug_10436_1)
+ << "Total_bytes_acked(" << model_->total_bytes_acked()
+ << ") < send_state.total_bytes_acked("
+ << congestion_event.last_packet_send_state.total_bytes_acked << ")";
}
}
if (model_->IsInflightTooHigh(congestion_event,
@@ -394,8 +394,9 @@ void Bbr2ProbeBwMode::ProbeInflightHighUpward(
model_->set_inflight_hi(new_inflight_hi);
} else {
- QUIC_BUG << "Not growing inflight_hi due to wrap around. Old value:"
- << model_->inflight_hi() << ", new value:" << new_inflight_hi;
+ QUIC_BUG(quic_bug_10436_2)
+ << "Not growing inflight_hi due to wrap around. Old value:"
+ << model_->inflight_hi() << ", new value:" << new_inflight_hi;
}
}
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 a29d7aea3c2..d0f61277283 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
@@ -105,19 +105,12 @@ void Bbr2Sender::SetFromConfig(const QuicConfig& config,
config.HasClientRequestedIndependentOption(kB2CL, perspective)) {
params_.avoid_too_low_probe_bw_cwnd = false;
}
- if (GetQuicReloadableFlag(quic_bbr2_fewer_startup_round_trips) &&
- config.HasClientRequestedIndependentOption(k1RTT, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_fewer_startup_round_trips, 1, 2);
+ if (config.HasClientRequestedIndependentOption(k1RTT, perspective)) {
params_.startup_full_bw_rounds = 1;
}
- if (GetQuicReloadableFlag(quic_bbr2_fewer_startup_round_trips) &&
- config.HasClientRequestedIndependentOption(k2RTT, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_fewer_startup_round_trips, 2, 2);
+ if (config.HasClientRequestedIndependentOption(k2RTT, perspective)) {
params_.startup_full_bw_rounds = 2;
}
- if (config.HasClientRequestedIndependentOption(kB2LO, perspective)) {
- params_.ignore_inflight_lo = true;
- }
if (config.HasClientRequestedIndependentOption(kB2HR, perspective)) {
params_.inflight_hi_headroom = 0.15;
}
@@ -133,9 +126,10 @@ void Bbr2Sender::ApplyConnectionOptions(
if (ContainsQuicTag(connection_options, kBBQ2)) {
params_.startup_cwnd_gain = 2.885;
params_.drain_cwnd_gain = 2.885;
- if (params_.bw_startup) {
- model_.set_cwnd_gain(params_.startup_cwnd_gain);
- }
+ model_.set_cwnd_gain(params_.startup_cwnd_gain);
+ }
+ if (ContainsQuicTag(connection_options, kB2LO)) {
+ params_.ignore_inflight_lo = true;
}
if (ContainsQuicTag(connection_options, kB2NE)) {
params_.always_exit_startup_on_excess_loss = false;
@@ -146,9 +140,7 @@ void Bbr2Sender::ApplyConnectionOptions(
if (ContainsQuicTag(connection_options, kB2H2)) {
params_.limit_inflight_hi_by_max_delivered = true;
}
- if (GetQuicReloadableFlag(quic_bbr2_use_bytes_delivered) &&
- ContainsQuicTag(connection_options, kB2DL)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_bbr2_use_bytes_delivered);
+ if (ContainsQuicTag(connection_options, kB2DL)) {
params_.use_bytes_delivered_for_inflight_hi = true;
}
if (ContainsQuicTag(connection_options, kB2RC)) {
@@ -157,20 +149,16 @@ void Bbr2Sender::ApplyConnectionOptions(
if (ContainsQuicTag(connection_options, kBSAO)) {
model_.EnableOverestimateAvoidance();
}
- if (params_.bw_startup && ContainsQuicTag(connection_options, kBBQ6)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_bw_startup, 1, 4);
+ if (ContainsQuicTag(connection_options, kBBQ6)) {
params_.decrease_startup_pacing_at_end_of_round = true;
}
- if (params_.bw_startup && ContainsQuicTag(connection_options, kBBQ7)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_bw_startup, 2, 4);
+ if (ContainsQuicTag(connection_options, kBBQ7)) {
params_.bw_lo_mode_ = Bbr2Params::QuicBandwidthLoMode::MIN_RTT_REDUCTION;
}
- if (params_.bw_startup && ContainsQuicTag(connection_options, kBBQ8)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_bw_startup, 3, 4);
+ if (ContainsQuicTag(connection_options, kBBQ8)) {
params_.bw_lo_mode_ = Bbr2Params::QuicBandwidthLoMode::INFLIGHT_REDUCTION;
}
- if (params_.bw_startup && ContainsQuicTag(connection_options, kBBQ9)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_bw_startup, 4, 4);
+ if (ContainsQuicTag(connection_options, kBBQ9)) {
params_.bw_lo_mode_ = Bbr2Params::QuicBandwidthLoMode::CWND_REDUCTION;
}
}
@@ -248,6 +236,16 @@ void Bbr2Sender::OnCongestionEvent(bool /*rtt_updated*/,
model_.OnCongestionEventStart(event_time, acked_packets, lost_packets,
&congestion_event);
+ if (InSlowStart()) {
+ if (!lost_packets.empty()) {
+ connection_stats_->slowstart_packets_lost += lost_packets.size();
+ connection_stats_->slowstart_bytes_lost += congestion_event.bytes_lost;
+ }
+ if (congestion_event.end_of_round_trip) {
+ ++connection_stats_->slowstart_num_rtts;
+ }
+ }
+
// Number of mode changes allowed for this congestion event.
int mode_changes_allowed = kMaxModeChangesPerCongestionEvent;
while (true) {
@@ -266,16 +264,19 @@ void Bbr2Sender::OnCongestionEvent(bool /*rtt_updated*/,
BBR2_MODE_DISPATCH(Enter(event_time, &congestion_event));
--mode_changes_allowed;
if (mode_changes_allowed < 0) {
- QUIC_BUG << "Exceeded max number of mode changes per congestion event.";
+ QUIC_BUG(quic_bug_10443_1)
+ << "Exceeded max number of mode changes per congestion event.";
break;
}
}
UpdatePacingRate(congestion_event.bytes_acked);
- QUIC_BUG_IF(pacing_rate_.IsZero()) << "Pacing rate must not be zero!";
+ QUIC_BUG_IF(quic_bug_10443_2, pacing_rate_.IsZero())
+ << "Pacing rate must not be zero!";
UpdateCongestionWindow(congestion_event.bytes_acked);
- QUIC_BUG_IF(cwnd_ == 0u) << "Congestion window must not be zero!";
+ QUIC_BUG_IF(quic_bug_10443_3, cwnd_ == 0u)
+ << "Congestion window must not be zero!";
model_.OnCongestionEventFinish(unacked_packets_->GetLeastUnacked(),
congestion_event);
@@ -320,9 +321,17 @@ void Bbr2Sender::UpdatePacingRate(QuicByteCount bytes_acked) {
}
QuicBandwidth target_rate = model_.pacing_gain() * model_.BandwidthEstimate();
- if (model_.full_bandwidth_reached() ||
- params_.decrease_startup_pacing_at_end_of_round ||
- params_.bw_lo_mode_ != Bbr2Params::DEFAULT) {
+ if (model_.full_bandwidth_reached()) {
+ pacing_rate_ = target_rate;
+ return;
+ }
+ if (params_.decrease_startup_pacing_at_end_of_round &&
+ model_.pacing_gain() < Params().startup_pacing_gain) {
+ pacing_rate_ = target_rate;
+ return;
+ }
+ if (params_.bw_lo_mode_ != Bbr2Params::DEFAULT &&
+ model_.loss_events_in_round() > 0) {
pacing_rate_ = target_rate;
return;
}
@@ -378,6 +387,10 @@ void Bbr2Sender::OnPacketSent(QuicTime sent_time,
<< ", total_acked:" << model_.total_bytes_acked()
<< ", total_lost:" << model_.total_bytes_lost() << " @ "
<< sent_time;
+ if (InSlowStart()) {
+ ++connection_stats_->slowstart_packets_sent;
+ connection_stats_->slowstart_bytes_sent += bytes;
+ }
if (bytes_in_flight == 0 && params().avoid_unnecessary_probe_rtt) {
OnExitQuiescence(sent_time);
}
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 9cd5966e91f..e26760e0bf9 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
@@ -122,9 +122,6 @@ class DefaultTopologyParams {
class Bbr2SimulatorTest : public QuicTest {
protected:
Bbr2SimulatorTest() : simulator_(&random_) {
- // Enable this for all tests because it moves where cwnd and pacing gain
- // are initialized.
- SetQuicReloadableFlag(quic_bbr2_bw_startup, true);
// Prevent the server(receiver), which only sends acks, from closing
// connection due to too many outstanding packets.
SetQuicFlag(FLAGS_quic_max_tracked_packet_count, 1000000);
@@ -596,7 +593,6 @@ TEST_F(Bbr2DefaultTopologyTest, PacketLossOnSmallBufferStartup) {
// Test the number of losses decreases with packet-conservation pacing.
TEST_F(Bbr2DefaultTopologyTest, PacketLossBBQ6SmallBufferStartup) {
- SetQuicReloadableFlag(quic_bbr2_bw_startup, true);
SetConnectionOption(kBBQ2); // Increase CWND gain.
SetConnectionOption(kBBQ6);
DefaultTopologyParams params;
@@ -612,7 +608,6 @@ TEST_F(Bbr2DefaultTopologyTest, PacketLossBBQ6SmallBufferStartup) {
// Test the number of losses decreases with min_rtt packet-conservation pacing.
TEST_F(Bbr2DefaultTopologyTest, PacketLossBBQ7SmallBufferStartup) {
- SetQuicReloadableFlag(quic_bbr2_bw_startup, true);
SetConnectionOption(kBBQ2); // Increase CWND gain.
SetConnectionOption(kBBQ7);
DefaultTopologyParams params;
@@ -628,7 +623,6 @@ TEST_F(Bbr2DefaultTopologyTest, PacketLossBBQ7SmallBufferStartup) {
// Test the number of losses decreases with Inflight packet-conservation pacing.
TEST_F(Bbr2DefaultTopologyTest, PacketLossBBQ8SmallBufferStartup) {
- SetQuicReloadableFlag(quic_bbr2_bw_startup, true);
SetConnectionOption(kBBQ2); // Increase CWND gain.
SetConnectionOption(kBBQ8);
DefaultTopologyParams params;
@@ -644,7 +638,6 @@ TEST_F(Bbr2DefaultTopologyTest, PacketLossBBQ8SmallBufferStartup) {
// Test the number of losses decreases with CWND packet-conservation pacing.
TEST_F(Bbr2DefaultTopologyTest, PacketLossBBQ9SmallBufferStartup) {
- SetQuicReloadableFlag(quic_bbr2_bw_startup, true);
SetConnectionOption(kBBQ2); // Increase CWND gain.
SetConnectionOption(kBBQ9);
DefaultTopologyParams params;
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 0f6b80ff233..5a9a532e688 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
@@ -23,16 +23,14 @@ Bbr2StartupMode::Bbr2StartupMode(const Bbr2Sender* sender,
sender_->connection_stats_->slowstart_count = 1;
sender_->connection_stats_->slowstart_duration = QuicTimeAccumulator();
sender_->connection_stats_->slowstart_duration.Start(now);
- if (sender->Params().bw_startup) {
- // Enter() is never called for Startup, so the gains needs to be set here.
- model_->set_pacing_gain(Params().startup_pacing_gain);
- model_->set_cwnd_gain(Params().startup_cwnd_gain);
- }
+ // Enter() is never called for Startup, so the gains needs to be set here.
+ model_->set_pacing_gain(Params().startup_pacing_gain);
+ model_->set_cwnd_gain(Params().startup_cwnd_gain);
}
void Bbr2StartupMode::Enter(QuicTime /*now*/,
const Bbr2CongestionEvent* /*congestion_event*/) {
- QUIC_BUG << "Bbr2StartupMode::Enter should not be called";
+ QUIC_BUG(quic_bug_10463_1) << "Bbr2StartupMode::Enter should not be called";
}
void Bbr2StartupMode::Leave(QuicTime now,
@@ -63,7 +61,6 @@ Bbr2Mode Bbr2StartupMode::OnCongestionEvent(
if (Params().decrease_startup_pacing_at_end_of_round) {
QUICHE_DCHECK_GT(model_->pacing_gain(), 0);
- QUICHE_DCHECK(Params().bw_startup);
if (congestion_event.end_of_round_trip &&
!congestion_event.last_sample_is_app_limited) {
// Multiply by startup_pacing_gain, so if the bandwidth doubles,
@@ -92,10 +89,6 @@ Bbr2Mode Bbr2StartupMode::OnCongestionEvent(
}
max_bw_at_round_beginning_ = model_->MaxBandwidth();
}
- } else if (!Params().bw_startup) {
- // When the flag is enabled, set these in the constructor.
- model_->set_pacing_gain(Params().startup_pacing_gain);
- model_->set_cwnd_gain(Params().startup_cwnd_gain);
}
// TODO(wub): Maybe implement STARTUP => PROBE_RTT.
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.cc
index 521aa4a7a10..f9b7ac42c09 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.cc
@@ -69,9 +69,9 @@ LossDetectionInterface::DetectionStats GeneralLossAlgorithm::DetectLosses(
auto it = unacked_packets.begin();
if (least_in_flight_.IsInitialized() && least_in_flight_ >= packet_number) {
if (least_in_flight_ > unacked_packets.largest_sent_packet() + 1) {
- QUIC_BUG << "least_in_flight: " << least_in_flight_
- << " is greater than largest_sent_packet + 1: "
- << unacked_packets.largest_sent_packet() + 1;
+ QUIC_BUG(quic_bug_10430_1) << "least_in_flight: " << least_in_flight_
+ << " is greater than largest_sent_packet + 1: "
+ << unacked_packets.largest_sent_packet() + 1;
} else {
it += (least_in_flight_ - packet_number);
packet_number = least_in_flight_;
@@ -181,7 +181,7 @@ void GeneralLossAlgorithm::Initialize(PacketNumberSpace packet_number_space,
LossDetectionInterface* parent) {
parent_ = parent;
if (packet_number_space_ < NUM_PACKET_NUMBER_SPACES) {
- QUIC_BUG << "Cannot switch packet_number_space";
+ QUIC_BUG(quic_bug_10430_2) << "Cannot switch packet_number_space";
return;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h
index 1911e385348..0047b0f0448 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h
@@ -79,7 +79,7 @@ class QUIC_EXPORT_PRIVATE RttStats {
// Sets an initial RTT to be used for SmoothedRtt before any RTT updates.
void set_initial_rtt(QuicTime::Delta initial_rtt) {
if (initial_rtt.ToMicroseconds() <= 0) {
- QUIC_BUG << "Attempt to set initial rtt to <= 0.";
+ QUIC_BUG(quic_bug_10453_1) << "Attempt to set initial rtt to <= 0.";
return;
}
initial_rtt_ = initial_rtt;
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
index 77691fdcf09..562da98c414 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
@@ -361,7 +361,8 @@ void TcpCubicSenderBytes::MaybeIncreaseCwnd(
QuicByteCount acked_bytes,
QuicByteCount prior_in_flight,
QuicTime event_time) {
- QUIC_BUG_IF(InRecovery()) << "Never increase the CWND during recovery.";
+ QUIC_BUG_IF(quic_bug_10439_1, InRecovery())
+ << "Never increase the CWND during recovery.";
// Do not increase the congestion window unless the sender is close to using
// the current window.
if (!IsCwndLimited(prior_in_flight)) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.cc
index 3668487eac9..2bf8d864b00 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.cc
@@ -93,7 +93,8 @@ void UberLossAlgorithm::SpuriousLossDetected(
void UberLossAlgorithm::SetLossDetectionTuner(
std::unique_ptr<LossDetectionTunerInterface> tuner) {
if (tuner_ != nullptr) {
- QUIC_BUG << "LossDetectionTuner can only be set once when session begins.";
+ QUIC_BUG(quic_bug_10469_1)
+ << "LossDetectionTuner can only be set once when session begins.";
return;
}
tuner_ = std::move(tuner);
@@ -119,7 +120,8 @@ void UberLossAlgorithm::MaybeStartTuning() {
SetReorderingShift(*tuned_parameters_.reordering_shift);
SetReorderingThreshold(*tuned_parameters_.reordering_threshold);
} else {
- QUIC_BUG << "Tuner started but some parameters are missing";
+ QUIC_BUG(quic_bug_10469_2)
+ << "Tuner started but some parameters are missing";
}
}
@@ -204,7 +206,7 @@ void UberLossAlgorithm::DisablePacketThresholdForRuntPackets() {
void UberLossAlgorithm::ResetLossDetection(PacketNumberSpace space) {
if (space >= NUM_PACKET_NUMBER_SPACES) {
- QUIC_BUG << "Invalid packet number space: " << space;
+ QUIC_BUG(quic_bug_10469_3) << "Invalid packet number space: " << space;
return;
}
general_loss_algorithms_[space].Reset();
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_decrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_decrypter.cc
index 32a2ebfc0e0..69724ba88fc 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_decrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_decrypter.cc
@@ -88,7 +88,8 @@ bool AeadBaseDecrypter::SetKey(absl::string_view key) {
bool AeadBaseDecrypter::SetNoncePrefix(absl::string_view nonce_prefix) {
if (use_ietf_nonce_construction_) {
- QUIC_BUG << "Attempted to set nonce prefix on IETF QUIC crypter";
+ QUIC_BUG(quic_bug_10709_1)
+ << "Attempted to set nonce prefix on IETF QUIC crypter";
return false;
}
QUICHE_DCHECK_EQ(nonce_prefix.size(), nonce_size_ - sizeof(QuicPacketNumber));
@@ -101,7 +102,7 @@ bool AeadBaseDecrypter::SetNoncePrefix(absl::string_view nonce_prefix) {
bool AeadBaseDecrypter::SetIV(absl::string_view iv) {
if (!use_ietf_nonce_construction_) {
- QUIC_BUG << "Attempted to set IV on Google QUIC crypter";
+ QUIC_BUG(quic_bug_10709_2) << "Attempted to set IV on Google QUIC crypter";
return false;
}
QUICHE_DCHECK_EQ(iv.size(), nonce_size_);
@@ -158,7 +159,8 @@ bool AeadBaseDecrypter::DecryptPacket(uint64_t packet_number,
}
if (have_preliminary_key_) {
- QUIC_BUG << "Unable to decrypt while key diversification is pending";
+ QUIC_BUG(quic_bug_10709_3)
+ << "Unable to decrypt while key diversification is pending";
return false;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_encrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_encrypter.cc
index a7100c5fa24..f4878e5a6d0 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_encrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_encrypter.cc
@@ -78,7 +78,8 @@ bool AeadBaseEncrypter::SetKey(absl::string_view key) {
bool AeadBaseEncrypter::SetNoncePrefix(absl::string_view nonce_prefix) {
if (use_ietf_nonce_construction_) {
- QUIC_BUG << "Attempted to set nonce prefix on IETF QUIC crypter";
+ QUIC_BUG(quic_bug_10634_1)
+ << "Attempted to set nonce prefix on IETF QUIC crypter";
return false;
}
QUICHE_DCHECK_EQ(nonce_prefix.size(), nonce_size_ - sizeof(QuicPacketNumber));
@@ -91,7 +92,7 @@ bool AeadBaseEncrypter::SetNoncePrefix(absl::string_view nonce_prefix) {
bool AeadBaseEncrypter::SetIV(absl::string_view iv) {
if (!use_ietf_nonce_construction_) {
- QUIC_BUG << "Attempted to set IV on Google QUIC crypter";
+ QUIC_BUG(quic_bug_10634_2) << "Attempted to set IV on Google QUIC crypter";
return false;
}
QUICHE_DCHECK_EQ(iv.size(), nonce_size_);
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_decrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_decrypter.cc
index 95cd509267a..fd21c7342bf 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_decrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_decrypter.cc
@@ -12,12 +12,12 @@ namespace quic {
bool AesBaseDecrypter::SetHeaderProtectionKey(absl::string_view key) {
if (key.size() != GetKeySize()) {
- QUIC_BUG << "Invalid key size for header protection";
+ QUIC_BUG(quic_bug_10649_1) << "Invalid key size for header protection";
return false;
}
if (AES_set_encrypt_key(reinterpret_cast<const uint8_t*>(key.data()),
key.size() * 8, &pne_key_) != 0) {
- QUIC_BUG << "Unexpected failure of AES_set_encrypt_key";
+ QUIC_BUG(quic_bug_10649_2) << "Unexpected failure of AES_set_encrypt_key";
return false;
}
return true;
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.cc
index 663056dd41e..fb25a334e47 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.cc
@@ -12,12 +12,13 @@ namespace quic {
bool AesBaseEncrypter::SetHeaderProtectionKey(absl::string_view key) {
if (key.size() != GetKeySize()) {
- QUIC_BUG << "Invalid key size for header protection: " << key.size();
+ QUIC_BUG(quic_bug_10726_1)
+ << "Invalid key size for header protection: " << key.size();
return false;
}
if (AES_set_encrypt_key(reinterpret_cast<const uint8_t*>(key.data()),
key.size() * 8, &pne_key_) != 0) {
- QUIC_BUG << "Unexpected failure of AES_set_encrypt_key";
+ QUIC_BUG(quic_bug_10726_2) << "Unexpected failure of AES_set_encrypt_key";
return false;
}
return true;
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 7a20602337d..c21dd202b2d 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
@@ -495,8 +495,9 @@ bool CertificateView::VerifySignature(absl::string_view data,
uint16_t signature_algorithm) const {
if (PublicKeyTypeFromSignatureAlgorithm(signature_algorithm) !=
PublicKeyTypeFromKey(public_key_.get())) {
- QUIC_BUG << "Mismatch between the requested signature algorithm and the "
- "type of the public key.";
+ QUIC_BUG(quic_bug_10640_1)
+ << "Mismatch between the requested signature algorithm and the "
+ "type of the public key.";
return false;
}
@@ -587,8 +588,9 @@ skip:
std::string CertificatePrivateKey::Sign(absl::string_view input,
uint16_t signature_algorithm) {
if (!ValidForSignatureAlgorithm(signature_algorithm)) {
- QUIC_BUG << "Mismatch between the requested signature algorithm and the "
- "type of the private key.";
+ QUIC_BUG(quic_bug_10640_2)
+ << "Mismatch between the requested signature algorithm and the "
+ "type of the private key.";
return "";
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_decrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_decrypter.cc
index 1b8af25c451..b1be3d6155f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_decrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_decrypter.cc
@@ -17,7 +17,7 @@ namespace quic {
bool ChaChaBaseDecrypter::SetHeaderProtectionKey(absl::string_view key) {
if (key.size() != GetKeySize()) {
- QUIC_BUG << "Invalid key size for header protection";
+ QUIC_BUG(quic_bug_10620_1) << "Invalid key size for header protection";
return false;
}
memcpy(pne_key_, key.data(), key.size());
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_encrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_encrypter.cc
index f667f1cdc8a..1dfe8e6193f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_encrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_encrypter.cc
@@ -15,7 +15,7 @@ namespace quic {
bool ChaChaBaseEncrypter::SetHeaderProtectionKey(absl::string_view key) {
if (key.size() != GetKeySize()) {
- QUIC_BUG << "Invalid key size for header protection";
+ QUIC_BUG(quic_bug_10656_1) << "Invalid key size for header protection";
return false;
}
memcpy(pne_key_, key.data(), key.size());
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.cc
index 9628ed904fe..6dcb989b9e8 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.cc
@@ -8,6 +8,7 @@
#include <string>
#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "quic/core/crypto/crypto_framer.h"
@@ -16,7 +17,6 @@
#include "quic/core/quic_socket_address_coder.h"
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_map_util.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "common/quiche_endian.h"
namespace quic {
@@ -221,9 +221,10 @@ QuicErrorCode CryptoHandshakeMessage::GetUint64(QuicTag tag,
return GetPOD(tag, out, sizeof(uint64_t));
}
-QuicErrorCode CryptoHandshakeMessage::GetUint128(QuicTag tag,
- QuicUint128* out) const {
- return GetPOD(tag, out, sizeof(QuicUint128));
+QuicErrorCode CryptoHandshakeMessage::GetStatelessResetToken(
+ QuicTag tag,
+ StatelessResetToken* out) const {
+ return GetPOD(tag, out, kStatelessResetTokenLength);
}
size_t CryptoHandshakeMessage::size() const {
@@ -296,7 +297,7 @@ std::string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
if (it->second.size() == 4) {
uint32_t value;
memcpy(&value, it->second.data(), sizeof(value));
- ret += quiche::QuicheTextUtils::Uint64ToString(value);
+ absl::StrAppend(&ret, value);
done = true;
}
break;
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h
index 61fb75735c6..9550c153e49 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h
@@ -13,8 +13,8 @@
#include "absl/strings/string_view.h"
#include "quic/core/quic_packets.h"
+#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_export.h"
-#include "quic/platform/api/quic_uint128.h"
namespace quic {
@@ -110,7 +110,9 @@ class QUIC_EXPORT_PRIVATE CryptoHandshakeMessage {
absl::string_view* out) const;
QuicErrorCode GetUint32(QuicTag tag, uint32_t* out) const;
QuicErrorCode GetUint64(QuicTag tag, uint64_t* out) const;
- QuicErrorCode GetUint128(QuicTag tag, QuicUint128* out) const;
+
+ QuicErrorCode GetStatelessResetToken(QuicTag tag,
+ StatelessResetToken* out) const;
// size returns 4 (message tag) + 2 (uint16_t, number of entries) +
// (4 (tag) + 4 (end offset))*tag_value_map_.size() + ∑ value sizes.
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 99f537213b7..e08d90b1c08 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
@@ -267,6 +267,9 @@ const QuicTag kAPTO = TAG('A', 'P', 'T', 'O'); // Use 1.5 * initial RTT before
const QuicTag kELDT = TAG('E', 'L', 'D', 'T'); // Enable Loss Detection Tuning
+const QuicTag kRVCM = TAG('R', 'V', 'C', 'M'); // Validate the new address
+ // upon client address change.
+
// Optional support of truncated Connection IDs. If sent by a peer, the value
// is the minimum number of bytes allowed for the connection ID sent to the
// peer.
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 323aec10316..7414eda8692 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
@@ -12,6 +12,7 @@
#include "absl/base/macros.h"
#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
#include "quic/core/crypto/cert_compressor.h"
@@ -57,24 +58,23 @@ const char kOldConfigId[] = "old-config-id";
} // namespace
struct TestParams {
- TestParams(ParsedQuicVersionVector supported_versions)
- : supported_versions(std::move(supported_versions)) {}
-
friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
os << " versions: "
- << ParsedQuicVersionVectorToString(p.supported_versions) << " }";
+ << ParsedQuicVersionVectorToString(p.supported_versions)
+ << " } allow_sni_without_dots: " << p.allow_sni_without_dots;
return os;
}
// Versions supported by client and server.
ParsedQuicVersionVector supported_versions;
+ bool allow_sni_without_dots;
};
// Used by ::testing::PrintToStringParamName().
std::string PrintToString(const TestParams& p) {
std::string rv = ParsedQuicVersionVectorToString(p.supported_versions);
std::replace(rv.begin(), rv.end(), ',', '_');
- return rv;
+ return absl::StrCat(rv, "_allow_sni_without_dots_", p.allow_sni_without_dots);
}
// Constructs various test permutations.
@@ -84,7 +84,9 @@ std::vector<TestParams> GetTestParams() {
// Start with all versions, remove highest on each iteration.
ParsedQuicVersionVector supported_versions = AllSupportedVersions();
while (!supported_versions.empty()) {
- params.push_back(TestParams(supported_versions));
+ for (bool allow_sni_without_dots : {false, true}) {
+ params.push_back({supported_versions, allow_sni_without_dots});
+ }
supported_versions.erase(supported_versions.begin());
}
@@ -108,6 +110,8 @@ class CryptoServerTest : public QuicTestWithParam<TestParams> {
signed_config_(new QuicSignedServerConfig),
chlo_packet_size_(kDefaultMaxPacketSize) {
supported_versions_ = GetParam().supported_versions;
+ SetQuicReloadableFlag(quic_and_tls_allow_sni_without_dots,
+ GetParam().allow_sni_without_dots);
config_.set_enable_serving_sct(true);
client_version_ = supported_versions_.front();
@@ -377,27 +381,34 @@ INSTANTIATE_TEST_SUITE_P(CryptoServerTests,
TEST_P(CryptoServerTest, BadSNI) {
// clang-format off
- static const char* const kBadSNIs[] = {
+ std::vector<std::string> badSNIs = {
"",
- "foo",
"#00",
"#ff00",
"127.0.0.1",
"ffee::1",
};
+ if (!GetParam().allow_sni_without_dots) {
+ badSNIs.push_back("foo");
+ }
// clang-format on
- for (size_t i = 0; i < ABSL_ARRAYSIZE(kBadSNIs); i++) {
- CryptoHandshakeMessage msg =
- crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
- {"SNI", kBadSNIs[i]},
- {"VER\0", client_version_string_}},
- kClientHelloMinimumSize);
+ for (const std::string& bad_sni : badSNIs) {
+ CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
+ {{"PDMD", "X509"}, {"SNI", bad_sni}, {"VER\0", client_version_string_}},
+ kClientHelloMinimumSize);
ShouldFailMentioning("SNI", msg);
const HandshakeFailureReason kRejectReasons[] = {
SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
}
+
+ if (GetParam().allow_sni_without_dots) {
+ CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
+ {{"PDMD", "X509"}, {"SNI", "foo"}, {"VER\0", client_version_string_}},
+ kClientHelloMinimumSize);
+ ShouldSucceed(msg);
+ }
}
TEST_P(CryptoServerTest, DefaultCert) {
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 a2e205bbbb2..2c8435035c9 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
@@ -176,7 +176,8 @@ const uint8_t* InitialSaltForVersion(const ParsedQuicVersion& version,
*out_len = ABSL_ARRAYSIZE(kReservedForNegotiationSalt);
return kReservedForNegotiationSalt;
}
- QUIC_BUG << "No initial obfuscation salt for version " << version;
+ QUIC_BUG(quic_bug_10699_1)
+ << "No initial obfuscation salt for version " << version;
*out_len = ABSL_ARRAYSIZE(kReservedForNegotiationSalt);
return kReservedForNegotiationSalt;
}
@@ -219,8 +220,9 @@ bool RetryIntegrityKeysForVersion(const ParsedQuicVersion& version,
static_assert(SupportedVersions().size() == 6u,
"Supported versions out of sync with retry integrity keys");
if (!version.UsesTls()) {
- QUIC_BUG << "Attempted to get retry integrity keys for invalid version "
- << version;
+ QUIC_BUG(quic_bug_10699_2)
+ << "Attempted to get retry integrity keys for invalid version "
+ << version;
return false;
} else if (version == ParsedQuicVersion::RFCv1()) {
*key = absl::string_view(
@@ -256,7 +258,8 @@ bool RetryIntegrityKeysForVersion(const ParsedQuicVersion& version,
ABSL_ARRAYSIZE(kReservedForNegotiationRetryIntegrityNonce));
return true;
}
- QUIC_BUG << "Attempted to get retry integrity keys for version " << version;
+ QUIC_BUG(quic_bug_10699_3)
+ << "Attempted to get retry integrity keys for version " << version;
return false;
}
@@ -277,8 +280,8 @@ void CryptoUtils::CreateInitialObfuscators(Perspective perspective,
crypters->decrypter = std::make_unique<NullDecrypter>(perspective);
return;
}
- QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
- connection_id, version.transport_version))
+ QUIC_BUG_IF(quic_bug_12871_1, !QuicUtils::IsConnectionIdValidForVersion(
+ connection_id, version.transport_version))
<< "CreateTlsInitialCrypters: attempted to use connection ID "
<< connection_id << " which is invalid with version " << version;
const EVP_MD* hash = EVP_sha256();
@@ -292,7 +295,7 @@ void CryptoUtils::CreateInitialObfuscators(Perspective perspective,
HKDF_extract(handshake_secret.data(), &handshake_secret_len, hash,
reinterpret_cast<const uint8_t*>(connection_id.data()),
connection_id.length(), salt, salt_len);
- QUIC_BUG_IF(!hkdf_extract_success)
+ QUIC_BUG_IF(quic_bug_12871_2, !hkdf_extract_success)
<< "HKDF_extract failed when creating initial crypters";
handshake_secret.resize(handshake_secret_len);
@@ -325,18 +328,21 @@ bool CryptoUtils::ValidateRetryIntegrityTag(
absl::string_view integrity_tag) {
unsigned char computed_integrity_tag[kRetryIntegrityTagLength];
if (integrity_tag.length() != ABSL_ARRAYSIZE(computed_integrity_tag)) {
- QUIC_BUG << "Invalid retry integrity tag length " << integrity_tag.length();
+ QUIC_BUG(quic_bug_10699_4)
+ << "Invalid retry integrity tag length " << integrity_tag.length();
return false;
}
char retry_pseudo_packet[kMaxIncomingPacketSize + 256];
QuicDataWriter writer(ABSL_ARRAYSIZE(retry_pseudo_packet),
retry_pseudo_packet);
if (!writer.WriteLengthPrefixedConnectionId(original_connection_id)) {
- QUIC_BUG << "Failed to write original connection ID in retry pseudo packet";
+ QUIC_BUG(quic_bug_10699_5)
+ << "Failed to write original connection ID in retry pseudo packet";
return false;
}
if (!writer.WriteStringPiece(retry_without_tag)) {
- QUIC_BUG << "Failed to write retry without tag in retry pseudo packet";
+ QUIC_BUG(quic_bug_10699_6)
+ << "Failed to write retry without tag in retry pseudo packet";
return false;
}
absl::string_view key;
@@ -351,7 +357,7 @@ bool CryptoUtils::ValidateRetryIntegrityTag(
absl::string_view plaintext; // Plaintext is empty.
if (!crypter.Encrypt(nonce, associated_data, plaintext,
computed_integrity_tag)) {
- QUIC_BUG << "Failed to compute retry integrity tag";
+ QUIC_BUG(quic_bug_10699_7) << "Failed to compute retry integrity tag";
return false;
}
if (CRYPTO_memcmp(computed_integrity_tag, integrity_tag.data(),
@@ -484,7 +490,8 @@ bool CryptoUtils::DeriveKeys(const ParsedQuicVersion& version,
}
case Diversification::PENDING: {
if (perspective == Perspective::IS_SERVER) {
- QUIC_BUG << "Pending diversification is only for clients.";
+ QUIC_BUG(quic_bug_10699_8)
+ << "Pending diversification is only for clients.";
return false;
}
@@ -502,7 +509,8 @@ bool CryptoUtils::DeriveKeys(const ParsedQuicVersion& version,
}
case Diversification::NOW: {
if (perspective == Perspective::IS_CLIENT) {
- QUIC_BUG << "Immediate diversification is only for servers.";
+ QUIC_BUG(quic_bug_10699_9)
+ << "Immediate diversification is only for servers.";
return false;
}
@@ -734,7 +742,8 @@ std::string CryptoUtils::EarlyDataReasonToString(
RETURN_STRING_LITERAL(ssl_early_data_quic_parameter_mismatch);
}
#endif
- QUIC_BUG_IF(reason < 0 || reason > ssl_early_data_reason_max_value)
+ QUIC_BUG_IF(quic_bug_12871_3,
+ reason < 0 || reason > ssl_early_data_reason_max_value)
<< "Unknown ssl_early_data_reason_t " << reason;
return "unknown ssl_early_data_reason_t";
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.cc
index aefbcf5817a..bdf3a081d02 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.cc
@@ -8,11 +8,11 @@
#include <cstring>
#include <string>
+#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "third_party/boringssl/src/include/openssl/curve25519.h"
#include "quic/core/crypto/quic_random.h"
#include "quic/platform/api/quic_bug_tracker.h"
-#include "quic/platform/api/quic_ptr_util.h"
namespace quic {
@@ -25,7 +25,7 @@ std::unique_ptr<Curve25519KeyExchange> Curve25519KeyExchange::New(
QuicRandom* rand) {
std::unique_ptr<Curve25519KeyExchange> result =
New(Curve25519KeyExchange::NewPrivateKey(rand));
- QUIC_BUG_IF(result == nullptr);
+ QUIC_BUG_IF(quic_bug_12891_1, result == nullptr);
return result;
}
@@ -47,7 +47,9 @@ std::unique_ptr<Curve25519KeyExchange> Curve25519KeyExchange::New(
return nullptr;
}
- auto ka = QuicWrapUnique(new Curve25519KeyExchange);
+ // Use absl::WrapUnique(new) instead of std::make_unique because
+ // Curve25519KeyExchange has a private constructor.
+ auto ka = absl::WrapUnique(new Curve25519KeyExchange);
memcpy(ka->private_key_, private_key.data(), X25519_PRIVATE_KEY_LEN);
X25519_public_from_private(ka->public_key_, ka->private_key_);
return ka;
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.cc
index 411dd3b9bb5..c4e66c80e73 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.cc
@@ -19,7 +19,8 @@ std::unique_ptr<SynchronousKeyExchange> CreateLocalSynchronousKeyExchange(
case kP256:
return P256KeyExchange::New(private_key);
default:
- QUIC_BUG << "Unknown key exchange method: " << QuicTagToString(type);
+ QUIC_BUG(quic_bug_10712_1)
+ << "Unknown key exchange method: " << QuicTagToString(type);
return nullptr;
}
}
@@ -35,7 +36,8 @@ std::unique_ptr<SynchronousKeyExchange> CreateLocalSynchronousKeyExchange(
return P256KeyExchange::New();
break;
default:
- QUIC_BUG << "Unknown key exchange method: " << QuicTagToString(type);
+ QUIC_BUG(quic_bug_10712_2)
+ << "Unknown key exchange method: " << QuicTagToString(type);
return nullptr;
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.cc
index 5e0c9fb9fc0..fd611bd3695 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.cc
@@ -6,11 +6,11 @@
#include <cstdint>
+#include "absl/numeric/int128.h"
#include "absl/strings/string_view.h"
#include "quic/core/quic_data_reader.h"
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_bug_tracker.h"
-#include "quic/platform/api/quic_uint128.h"
#include "common/quiche_endian.h"
namespace quic {
@@ -35,13 +35,13 @@ bool NullDecrypter::SetHeaderProtectionKey(absl::string_view key) {
}
bool NullDecrypter::SetPreliminaryKey(absl::string_view /*key*/) {
- QUIC_BUG << "Should not be called";
+ QUIC_BUG(quic_bug_10652_1) << "Should not be called";
return false;
}
bool NullDecrypter::SetDiversificationNonce(
const DiversificationNonce& /*nonce*/) {
- QUIC_BUG << "Should not be called";
+ QUIC_BUG(quic_bug_10652_2) << "Should not be called";
return true;
}
@@ -53,7 +53,7 @@ bool NullDecrypter::DecryptPacket(uint64_t /*packet_number*/,
size_t max_output_length) {
QuicDataReader reader(ciphertext.data(), ciphertext.length(),
quiche::HOST_BYTE_ORDER);
- QuicUint128 hash;
+ absl::uint128 hash;
if (!ReadHash(&reader, &hash)) {
return false;
@@ -61,7 +61,8 @@ bool NullDecrypter::DecryptPacket(uint64_t /*packet_number*/,
absl::string_view plaintext = reader.ReadRemainingPayload();
if (plaintext.length() > max_output_length) {
- QUIC_BUG << "Output buffer must be larger than the plaintext.";
+ QUIC_BUG(quic_bug_10652_3)
+ << "Output buffer must be larger than the plaintext.";
return false;
}
if (hash != ComputeHash(associated_data, plaintext)) {
@@ -106,19 +107,19 @@ QuicPacketCount NullDecrypter::GetIntegrityLimit() const {
return std::numeric_limits<QuicPacketCount>::max();
}
-bool NullDecrypter::ReadHash(QuicDataReader* reader, QuicUint128* hash) {
+bool NullDecrypter::ReadHash(QuicDataReader* reader, absl::uint128* hash) {
uint64_t lo;
uint32_t hi;
if (!reader->ReadUInt64(&lo) || !reader->ReadUInt32(&hi)) {
return false;
}
- *hash = MakeQuicUint128(hi, lo);
+ *hash = absl::MakeUint128(hi, lo);
return true;
}
-QuicUint128 NullDecrypter::ComputeHash(const absl::string_view data1,
- const absl::string_view data2) const {
- QuicUint128 correct_hash;
+absl::uint128 NullDecrypter::ComputeHash(const absl::string_view data1,
+ const absl::string_view data2) const {
+ absl::uint128 correct_hash;
if (perspective_ == Perspective::IS_CLIENT) {
// Peer is a server.
correct_hash = QuicUtils::FNV1a_128_Hash_Three(data1, data2, "Server");
@@ -126,7 +127,7 @@ QuicUint128 NullDecrypter::ComputeHash(const absl::string_view data1,
// Peer is a client.
correct_hash = QuicUtils::FNV1a_128_Hash_Three(data1, data2, "Client");
}
- QuicUint128 mask = MakeQuicUint128(UINT64_C(0x0), UINT64_C(0xffffffff));
+ absl::uint128 mask = absl::MakeUint128(UINT64_C(0x0), UINT64_C(0xffffffff));
mask <<= 96;
correct_hash &= ~mask;
return correct_hash;
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.h b/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.h
index fd06d3a6ee8..b36fa82848b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.h
@@ -8,11 +8,11 @@
#include <cstddef>
#include <cstdint>
+#include "absl/numeric/int128.h"
#include "absl/strings/string_view.h"
#include "quic/core/crypto/quic_decrypter.h"
#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_export.h"
-#include "quic/platform/api/quic_uint128.h"
namespace quic {
@@ -53,9 +53,9 @@ class QUIC_EXPORT_PRIVATE NullDecrypter : public QuicDecrypter {
QuicPacketCount GetIntegrityLimit() const override;
private:
- bool ReadHash(QuicDataReader* reader, QuicUint128* hash);
- QuicUint128 ComputeHash(absl::string_view data1,
- absl::string_view data2) const;
+ bool ReadHash(QuicDataReader* reader, absl::uint128* hash);
+ absl::uint128 ComputeHash(absl::string_view data1,
+ absl::string_view data2) const;
Perspective perspective_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter.cc
index dd9cfd9eb95..a38532148b6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter.cc
@@ -4,6 +4,7 @@
#include "quic/core/crypto/null_encrypter.h"
+#include "absl/numeric/int128.h"
#include "absl/strings/string_view.h"
#include "quic/core/quic_data_writer.h"
#include "quic/core/quic_utils.h"
@@ -41,7 +42,7 @@ bool NullEncrypter::EncryptPacket(uint64_t /*packet_number*/,
if (max_output_length < len) {
return false;
}
- QuicUint128 hash;
+ absl::uint128 hash;
if (perspective_ == Perspective::IS_SERVER) {
hash =
QuicUtils::FNV1a_128_Hash_Three(associated_data, plaintext, "Server");
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.cc
index 0ce7a24fa8c..2a13c2e5a5c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.cc
@@ -10,13 +10,13 @@
#include <string>
#include <utility>
+#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "third_party/boringssl/src/include/openssl/ec.h"
#include "third_party/boringssl/src/include/openssl/ecdh.h"
#include "third_party/boringssl/src/include/openssl/err.h"
#include "third_party/boringssl/src/include/openssl/evp.h"
#include "quic/platform/api/quic_logging.h"
-#include "quic/platform/api/quic_ptr_util.h"
namespace quic {
@@ -57,7 +57,7 @@ std::unique_ptr<P256KeyExchange> P256KeyExchange::New(absl::string_view key) {
return nullptr;
}
- return QuicWrapUnique(
+ return absl::WrapUnique(
new P256KeyExchange(std::move(private_key), public_key));
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source_x509.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source_x509.cc
index 06c694000cf..d61df716c3a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source_x509.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source_x509.cc
@@ -88,18 +88,20 @@ bool ProofSourceX509::AddCertificateChain(
QuicReferenceCountedPointer<Chain> chain,
CertificatePrivateKey key) {
if (chain->certs.empty()) {
- QUIC_BUG << "Empty certificate chain supplied.";
+ QUIC_BUG(quic_bug_10644_1) << "Empty certificate chain supplied.";
return false;
}
std::unique_ptr<CertificateView> leaf =
CertificateView::ParseSingleCertificate(chain->certs[0]);
if (leaf == nullptr) {
- QUIC_BUG << "Unable to parse X.509 leaf certificate in the supplied chain.";
+ QUIC_BUG(quic_bug_10644_2)
+ << "Unable to parse X.509 leaf certificate in the supplied chain.";
return false;
}
if (!key.MatchesPublicKey(*leaf)) {
- QUIC_BUG << "Private key does not match the leaf certificate.";
+ QUIC_BUG(quic_bug_10644_3)
+ << "Private key does not match the leaf certificate.";
return false;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache_test.cc
index 5b94e54e08c..8af7f373ea7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache_test.cc
@@ -6,10 +6,10 @@
#include <string>
+#include "absl/strings/str_cat.h"
#include "quic/core/crypto/cert_compressor.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 {
@@ -85,8 +85,7 @@ TEST_F(QuicCompressedCertsCacheTest, CacheMissDueToEviction) {
for (unsigned int i = 0;
i < QuicCompressedCertsCache::kQuicCompressedCertsCacheSize; i++) {
EXPECT_EQ(certs_cache_.Size(), i + 1);
- certs_cache_.Insert(chain, quiche::QuicheTextUtils::Uint64ToString(i), "",
- quiche::QuicheTextUtils::Uint64ToString(i));
+ certs_cache_.Insert(chain, absl::StrCat(i), "", absl::StrCat(i));
}
EXPECT_EQ(certs_cache_.MaxSize(), certs_cache_.Size());
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 45db92bd494..c886cbe989e 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
@@ -9,6 +9,7 @@
#include <string>
#include "absl/base/macros.h"
+#include "absl/memory/memory.h"
#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
@@ -33,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 "quic/platform/api/quic_ptr_util.h"
#include "common/platform/api/quiche_text_utils.h"
namespace quic {
@@ -134,15 +134,6 @@ QuicCryptoClientConfig::CachedState::GetServerConfig() const {
return scfg_.get();
}
-void QuicCryptoClientConfig::CachedState::add_server_nonce(
- const std::string& server_nonce) {
- server_nonces_.push(server_nonce);
-}
-
-bool QuicCryptoClientConfig::CachedState::has_server_nonce() const {
- return !server_nonces_.empty();
-}
-
QuicCryptoClientConfig::CachedState::ServerConfigState
QuicCryptoClientConfig::CachedState::SetServerConfig(
absl::string_view server_config,
@@ -363,17 +354,6 @@ void QuicCryptoClientConfig::CachedState::InitializeFrom(
++generation_counter_;
}
-std::string QuicCryptoClientConfig::CachedState::GetNextServerNonce() {
- if (server_nonces_.empty()) {
- QUIC_BUG
- << "Attempting to consume a server nonce that was never designated.";
- return "";
- }
- const std::string server_nonce = server_nonces_.front();
- server_nonces_.pop();
- return server_nonce;
-}
-
void QuicCryptoClientConfig::SetDefaults() {
// Key exchange methods.
kexs = {kC255, kP256};
@@ -395,7 +375,7 @@ QuicCryptoClientConfig::CachedState* QuicCryptoClientConfig::LookupOrCreate(
}
CachedState* cached = new CachedState;
- cached_states_.insert(std::make_pair(server_id, QuicWrapUnique(cached)));
+ cached_states_.insert(std::make_pair(server_id, absl::WrapUnique(cached)));
bool cache_populated = PopulateFromCanonicalConfig(server_id, cached);
QUIC_CLIENT_HISTOGRAM_BOOL(
"QuicCryptoClientConfig.PopulatedFromCanonicalConfig", cache_populated,
@@ -495,8 +475,9 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
CryptoHandshakeMessage* out,
std::string* error_details) const {
QUICHE_DCHECK(error_details != nullptr);
- QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
- connection_id, preferred_version.transport_version))
+ QUIC_BUG_IF(quic_bug_12943_2,
+ !QuicUtils::IsConnectionIdValidForVersion(
+ connection_id, preferred_version.transport_version))
<< "FillClientHello: attempted to use connection ID " << connection_id
<< " which is invalid with version " << preferred_version;
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h
index b02f621b97c..bb0626094db 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h
@@ -175,18 +175,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
void set_cert_sct(absl::string_view cert_sct);
- // Adds the servernonce to the queue of server nonces.
- void add_server_nonce(const std::string& server_nonce);
-
- // If true, the crypto config contains at least one server nonce, and the
- // client should use one of these nonces.
- bool has_server_nonce() const;
-
- // This function should only be called when has_server_nonce is true.
- // Returns the next server_nonce specified by the server and removes it
- // from the queue of nonces.
- std::string GetNextServerNonce();
-
// SetProofVerifyDetails takes ownership of |details|.
void SetProofVerifyDetails(ProofVerifyDetails* details);
@@ -227,8 +215,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
// scfg contains the cached, parsed value of |server_config|.
mutable std::unique_ptr<CryptoHandshakeMessage> scfg_;
-
- QuicQueue<std::string> server_nonces_;
};
// Used to filter server ids for partial config deletion.
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc
index 536083fb70d..6dd09677fb9 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc
@@ -81,45 +81,6 @@ TEST_F(QuicCryptoClientConfigTest, CachedState_SetProofVerifyDetails) {
EXPECT_EQ(details, state.proof_verify_details());
}
-TEST_F(QuicCryptoClientConfigTest, CachedState_ServerNonce) {
- QuicCryptoClientConfig::CachedState state;
- EXPECT_FALSE(state.has_server_nonce());
-
- std::string server_nonce = "nonce_1";
- state.add_server_nonce(server_nonce);
- EXPECT_TRUE(state.has_server_nonce());
- EXPECT_EQ(server_nonce, state.GetNextServerNonce());
- EXPECT_FALSE(state.has_server_nonce());
-
- // Allow the ID to be set multiple times. It's unusual that this would
- // happen, but not impossible.
- server_nonce = "nonce_2";
- state.add_server_nonce(server_nonce);
- EXPECT_TRUE(state.has_server_nonce());
- EXPECT_EQ(server_nonce, state.GetNextServerNonce());
- server_nonce = "nonce_3";
- state.add_server_nonce(server_nonce);
- EXPECT_EQ(server_nonce, state.GetNextServerNonce());
- EXPECT_FALSE(state.has_server_nonce());
-
- // Test FIFO behavior.
- const std::string first_nonce = "first_nonce";
- const std::string second_nonce = "second_nonce";
- state.add_server_nonce(first_nonce);
- state.add_server_nonce(second_nonce);
- EXPECT_TRUE(state.has_server_nonce());
- EXPECT_EQ(first_nonce, state.GetNextServerNonce());
- EXPECT_EQ(second_nonce, state.GetNextServerNonce());
-}
-
-TEST_F(QuicCryptoClientConfigTest, CachedState_ServerNonceConsumedBeforeSet) {
- QuicCryptoClientConfig::CachedState state;
- EXPECT_FALSE(state.has_server_nonce());
- EXPECT_QUIC_BUG(state.GetNextServerNonce(),
- "Attempting to consume a server nonce "
- "that was never designated.");
-}
-
TEST_F(QuicCryptoClientConfigTest, CachedState_InitializeFrom) {
QuicCryptoClientConfig::CachedState state;
QuicCryptoClientConfig::CachedState other;
@@ -130,7 +91,6 @@ TEST_F(QuicCryptoClientConfigTest, CachedState_InitializeFrom) {
EXPECT_EQ(state.source_address_token(), other.source_address_token());
EXPECT_EQ(state.certs(), other.certs());
EXPECT_EQ(1u, other.generation_counter());
- EXPECT_FALSE(state.has_server_nonce());
}
TEST_F(QuicCryptoClientConfigTest, InchoateChlo) {
@@ -492,7 +452,6 @@ TEST_F(QuicCryptoClientConfigTest, ProcessReject) {
AllSupportedVersionsWithQuicCrypto().front().transport_version, "",
&cached, out_params, &error),
IsQuicNoError());
- EXPECT_FALSE(cached.has_server_nonce());
}
TEST_F(QuicCryptoClientConfigTest, ProcessRejectWithLongTTL) {
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 da04f4f1ca1..4f19533b008 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
@@ -140,7 +140,7 @@ class ValidateClientHelloHelper {
delete;
~ValidateClientHelloHelper() {
- QUIC_BUG_IF(done_cb_ != nullptr)
+ QUIC_BUG_IF(quic_bug_12963_1, done_cb_ != nullptr)
<< "Deleting ValidateClientHelloHelper with a pending callback.";
}
@@ -155,7 +155,8 @@ class ValidateClientHelloHelper {
}
void DetachCallback() {
- QUIC_BUG_IF(done_cb_ == nullptr) << "Callback already detached.";
+ QUIC_BUG_IF(quic_bug_10630_1, done_cb_ == nullptr)
+ << "Callback already detached.";
done_cb_ = nullptr;
}
@@ -737,12 +738,29 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
std::unique_ptr<ProofSource::Details> proof_source_details,
std::unique_ptr<ProcessClientHelloContext> context,
const Configs& configs) const {
- QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
- context->connection_id(), context->transport_version()))
+ QUIC_BUG_IF(quic_bug_12963_2,
+ !QuicUtils::IsConnectionIdValidForVersion(
+ context->connection_id(), context->transport_version()))
<< "ProcessClientHelloAfterGetProof: attempted to use connection ID "
<< 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->signed_config() || !context->signed_config()->chain) {
+ // No chain.
+ context->validate_chlo_result()->info.reject_reasons.push_back(
+ SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
+ } else if (!ValidateExpectedLeafCertificate(
+ context->client_hello(),
+ context->signed_config()->chain->certs)) {
+ // Has chain but leaf is invalid.
+ context->validate_chlo_result()->info.reject_reasons.push_back(
+ INVALID_EXPECTED_LEAF_CERTIFICATE);
+ }
+ }
+
if (found_error) {
context->Fail(QUIC_HANDSHAKE_FAILED, "Failed to get proof");
return;
@@ -824,8 +842,9 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterCalculateSharedKeys(
absl::string_view public_value,
std::unique_ptr<ProcessClientHelloContext> context,
const Configs& configs) const {
- QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
- context->connection_id(), context->transport_version()))
+ QUIC_BUG_IF(quic_bug_12963_3,
+ !QuicUtils::IsConnectionIdValidForVersion(
+ context->connection_id(), context->transport_version()))
<< "ProcessClientHelloAfterCalculateSharedKeys:"
" attempted to use connection ID "
<< context->connection_id() << " which is invalid with version "
@@ -835,9 +854,7 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterCalculateSharedKeys(
// If we are already using the fallback config, or there is no fallback
// config to use, just bail out of the handshake.
if (configs.fallback == nullptr ||
- context->signed_config()->config == configs.fallback ||
- !GetQuicReloadableFlag(
- send_quic_fallback_server_config_on_leto_error)) {
+ context->signed_config()->config == configs.fallback) {
context->Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
"Failed to calculate shared key");
} else {
@@ -1134,9 +1151,10 @@ void QuicCryptoServerConfig::SelectNewPrimaryConfig(
if (configs.empty()) {
if (primary_config_ != nullptr) {
- QUIC_BUG << "No valid QUIC server config. Keeping the current config.";
+ QUIC_BUG(quic_bug_10630_2)
+ << "No valid QUIC server config. Keeping the current config.";
} else {
- QUIC_BUG << "No valid QUIC server config.";
+ QUIC_BUG(quic_bug_10630_3) << "No valid QUIC server config.";
}
return;
}
@@ -1276,13 +1294,15 @@ void QuicCryptoServerConfig::EvaluateClientHello(
// No valid source address token.
}
- 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 (!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) {
@@ -1455,7 +1475,8 @@ void QuicCryptoServerConfig::BuildRejection(
// The client may have requested a certificate chain.
if (!ClientDemandsX509Proof(context.client_hello())) {
- QUIC_BUG << "x509 certificates not supported in proof demand";
+ QUIC_BUG(quic_bug_10630_4)
+ << "x509 certificates not supported in proof demand";
return;
}
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 4f3ad0819e4..464f2bbfc36 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,6 +98,9 @@ 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_decrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_decrypter.cc
index 02be1a1cd26..bd3a0c385e7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_decrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_decrypter.cc
@@ -56,7 +56,7 @@ std::unique_ptr<QuicDecrypter> QuicDecrypter::CreateFromCipherSuite(
case TLS1_CK_CHACHA20_POLY1305_SHA256:
return std::make_unique<ChaCha20Poly1305TlsDecrypter>();
default:
- QUIC_BUG << "TLS cipher suite is unknown to QUIC";
+ QUIC_BUG(quic_bug_10660_1) << "TLS cipher suite is unknown to QUIC";
return nullptr;
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_encrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_encrypter.cc
index 4f7f7c9cd6d..70a936743a2 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_encrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_encrypter.cc
@@ -53,7 +53,7 @@ std::unique_ptr<QuicEncrypter> QuicEncrypter::CreateFromCipherSuite(
case TLS1_CK_CHACHA20_POLY1305_SHA256:
return std::make_unique<ChaCha20Poly1305TlsEncrypter>();
default:
- QUIC_BUG << "TLS cipher suite is unknown to QUIC";
+ QUIC_BUG(quic_bug_10711_1) << "TLS cipher suite is unknown to QUIC";
return nullptr;
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc
index 9b5636c0824..381de7eeafb 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc
@@ -62,7 +62,8 @@ EncryptionLevel TlsConnection::QuicEncryptionLevel(
case ssl_encryption_application:
return ENCRYPTION_FORWARD_SECURE;
default:
- QUIC_BUG << "Invalid ssl_encryption_level_t " << static_cast<int>(level);
+ QUIC_BUG(quic_bug_10698_1)
+ << "Invalid ssl_encryption_level_t " << static_cast<int>(level);
return ENCRYPTION_INITIAL;
}
}
@@ -80,7 +81,8 @@ enum ssl_encryption_level_t TlsConnection::BoringEncryptionLevel(
case ENCRYPTION_FORWARD_SECURE:
return ssl_encryption_application;
default:
- QUIC_BUG << "Invalid encryption level " << static_cast<int>(level);
+ QUIC_BUG(quic_bug_10698_2)
+ << "Invalid encryption level " << static_cast<int>(level);
return ssl_encryption_initial;
}
}
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 f4d0ac2ed4f..8926909cd78 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
@@ -27,26 +27,22 @@ bssl::UniquePtr<SSL_CTX> TlsServerConnection::CreateSslCtx(
// We don't actually need the TicketCrypter here, but we need to know
// whether it's set.
if (proof_source->GetTicketCrypter()) {
- QUIC_RESTART_FLAG_COUNT_N(quic_session_tickets_always_enabled, 1, 3);
+ 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_RESTART_FLAG_COUNT_N(quic_session_tickets_always_enabled, 2, 3);
+ QUIC_CODE_COUNT(quic_session_tickets_disabled_by_flag);
SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_NO_TICKET);
} else {
- QUIC_RESTART_FLAG_COUNT_N(quic_session_tickets_always_enabled, 3, 3);
+ QUIC_CODE_COUNT(quic_session_tickets_disabled);
}
- if (GetQuicRestartFlag(quic_enable_zero_rtt_for_tls_v2) &&
- (proof_source->GetTicketCrypter() ||
- GetQuicRestartFlag(quic_session_tickets_always_enabled))) {
+ if (proof_source->GetTicketCrypter() ||
+ GetQuicRestartFlag(quic_session_tickets_always_enabled)) {
SSL_CTX_set_early_data_enabled(ssl_ctx.get(), 1);
}
SSL_CTX_set_select_certificate_cb(
ssl_ctx.get(), &TlsServerConnection::EarlySelectCertCallback);
- if (GetQuicRestartFlag(quic_tls_prefer_server_cipher_and_curve_list)) {
- QUIC_RESTART_FLAG_COUNT(quic_tls_prefer_server_cipher_and_curve_list);
- SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_CIPHER_SERVER_PREFERENCE);
- }
+ SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_CIPHER_SERVER_PREFERENCE);
return ssl_ctx;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.cc
index 8cbd06e66b2..14df9c3a27c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.cc
@@ -22,7 +22,6 @@
#include "quic/core/quic_utils.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 {
@@ -75,7 +74,6 @@ constexpr uint64_t kMaxAckDelayExponentTransportParam = 20;
constexpr uint64_t kDefaultAckDelayExponentTransportParam = 3;
constexpr uint64_t kMaxMaxAckDelayTransportParam = 16383;
constexpr uint64_t kDefaultMaxAckDelayTransportParam = 25;
-constexpr size_t kStatelessResetTokenLength = 16;
constexpr uint64_t kMinActiveConnectionIdLimitTransportParam = 2;
constexpr uint64_t kDefaultActiveConnectionIdLimitTransportParam = 2;
@@ -131,7 +129,7 @@ std::string TransportParameterIdToString(
case TransportParameters::kMinAckDelay:
return "min_ack_delay_us";
}
- return "Unknown(" + quiche::QuicheTextUtils::Uint64ToString(param_id) + ")";
+ return absl::StrCat("Unknown(", param_id, ")");
}
bool TransportParameterIdIsKnown(
@@ -212,17 +210,17 @@ bool TransportParameters::IntegerParameter::Write(
return true;
}
if (!writer->WriteVarInt62(param_id_)) {
- QUIC_BUG << "Failed to write param_id for " << *this;
+ QUIC_BUG(quic_bug_10743_1) << "Failed to write param_id for " << *this;
return false;
}
const QuicVariableLengthIntegerLength value_length =
QuicDataWriter::GetVarInt62Len(value_);
if (!writer->WriteVarInt62(value_length)) {
- QUIC_BUG << "Failed to write value_length for " << *this;
+ QUIC_BUG(quic_bug_10743_2) << "Failed to write value_length for " << *this;
return false;
}
if (!writer->WriteVarInt62(value_, value_length)) {
- QUIC_BUG << "Failed to write value for " << *this;
+ QUIC_BUG(quic_bug_10743_3) << "Failed to write value for " << *this;
return false;
}
return true;
@@ -257,8 +255,7 @@ std::string TransportParameters::IntegerParameter::ToString(
return "";
}
std::string rv = for_use_in_list ? " " : "";
- rv += TransportParameterIdToString(param_id_) + " ";
- rv += quiche::QuicheTextUtils::Uint64ToString(value_);
+ absl::StrAppend(&rv, TransportParameterIdToString(param_id_), " ", value_);
if (!IsValid()) {
rv += " (Invalid)";
}
@@ -387,8 +384,8 @@ std::string TransportParameters::ToString() const {
rv += " " + TransportParameterIdToString(kGoogleKeyUpdateNotYetSupported);
}
for (const auto& kv : custom_parameters) {
- rv += " 0x" + quiche::QuicheTextUtils::Hex(static_cast<uint32_t>(kv.first));
- rv += "=";
+ absl::StrAppend(&rv, " 0x", absl::Hex(static_cast<uint32_t>(kv.first)),
+ "=");
static constexpr size_t kMaxPrintableLength = 32;
if (kv.second.length() <= kMaxPrintableLength) {
rv += absl::BytesToHexString(kv.second);
@@ -563,7 +560,7 @@ bool TransportParameters::AreValid(std::string* error_details) const {
if (preferred_address &&
(!preferred_address->ipv4_socket_address.host().IsIPv4() ||
!preferred_address->ipv6_socket_address.host().IsIPv6())) {
- QUIC_BUG << "Preferred address family failure";
+ QUIC_BUG(quic_bug_10743_4) << "Preferred address family failure";
*error_details = "Internal preferred address family failure";
return false;
}
@@ -612,13 +609,13 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
std::vector<uint8_t>* out) {
std::string error_details;
if (!in.AreValid(&error_details)) {
- QUIC_BUG << "Not serializing invalid transport parameters: "
- << error_details;
+ QUIC_BUG(quic_bug_10743_5)
+ << "Not serializing invalid transport parameters: " << error_details;
return false;
}
if (in.version == 0 || (in.perspective == Perspective::IS_SERVER &&
in.supported_versions.empty())) {
- QUIC_BUG << "Refusing to serialize without versions";
+ QUIC_BUG(quic_bug_10743_6) << "Refusing to serialize without versions";
return false;
}
@@ -701,14 +698,15 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
!writer.WriteStringPieceVarInt62(
absl::string_view(original_destination_connection_id.data(),
original_destination_connection_id.length()))) {
- QUIC_BUG << "Failed to write original_destination_connection_id "
- << original_destination_connection_id << " for " << in;
+ QUIC_BUG(quic_bug_10743_7)
+ << "Failed to write original_destination_connection_id "
+ << original_destination_connection_id << " for " << in;
return false;
}
}
if (!in.max_idle_timeout_ms.Write(&writer)) {
- QUIC_BUG << "Failed to write idle_timeout for " << in;
+ QUIC_BUG(quic_bug_10743_8) << "Failed to write idle_timeout for " << in;
return false;
}
@@ -721,8 +719,9 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
!writer.WriteStringPieceVarInt62(absl::string_view(
reinterpret_cast<const char*>(in.stateless_reset_token.data()),
in.stateless_reset_token.size()))) {
- QUIC_BUG << "Failed to write stateless_reset_token of length "
- << in.stateless_reset_token.size() << " for " << in;
+ QUIC_BUG(quic_bug_10743_9)
+ << "Failed to write stateless_reset_token of length "
+ << in.stateless_reset_token.size() << " for " << in;
return false;
}
}
@@ -739,7 +738,7 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
!in.active_connection_id_limit.Write(&writer) ||
!in.max_datagram_frame_size.Write(&writer) ||
!in.initial_round_trip_time_us.Write(&writer)) {
- QUIC_BUG << "Failed to write integers for " << in;
+ QUIC_BUG(quic_bug_10743_10) << "Failed to write integers for " << in;
return false;
}
@@ -747,7 +746,8 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
if (in.disable_active_migration) {
if (!writer.WriteVarInt62(TransportParameters::kDisableActiveMigration) ||
!writer.WriteVarInt62(/* transport parameter length */ 0)) {
- QUIC_BUG << "Failed to write disable_active_migration for " << in;
+ QUIC_BUG(quic_bug_10743_11)
+ << "Failed to write disable_active_migration for " << in;
return false;
}
}
@@ -761,7 +761,7 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
if (v4_address_bytes.length() != 4 || v6_address_bytes.length() != 16 ||
in.preferred_address->stateless_reset_token.size() !=
kStatelessResetTokenLength) {
- QUIC_BUG << "Bad lengths " << *in.preferred_address;
+ QUIC_BUG(quic_bug_10743_12) << "Bad lengths " << *in.preferred_address;
return false;
}
const uint64_t preferred_address_length =
@@ -783,7 +783,8 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
!writer.WriteBytes(
in.preferred_address->stateless_reset_token.data(),
in.preferred_address->stateless_reset_token.size())) {
- QUIC_BUG << "Failed to write preferred_address for " << in;
+ QUIC_BUG(quic_bug_10743_13)
+ << "Failed to write preferred_address for " << in;
return false;
}
}
@@ -797,8 +798,9 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
!writer.WriteStringPieceVarInt62(
absl::string_view(initial_source_connection_id.data(),
initial_source_connection_id.length()))) {
- QUIC_BUG << "Failed to write initial_source_connection_id "
- << initial_source_connection_id << " for " << in;
+ QUIC_BUG(quic_bug_10743_14)
+ << "Failed to write initial_source_connection_id "
+ << initial_source_connection_id << " for " << in;
return false;
}
}
@@ -812,8 +814,9 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
!writer.WriteStringPieceVarInt62(
absl::string_view(retry_source_connection_id.data(),
retry_source_connection_id.length()))) {
- QUIC_BUG << "Failed to write retry_source_connection_id "
- << retry_source_connection_id << " for " << in;
+ QUIC_BUG(quic_bug_10743_15)
+ << "Failed to write retry_source_connection_id "
+ << retry_source_connection_id << " for " << in;
return false;
}
}
@@ -827,15 +830,17 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
if (!writer.WriteVarInt62(TransportParameters::kGoogleConnectionOptions) ||
!writer.WriteVarInt62(
/* transport parameter length */ connection_options_length)) {
- QUIC_BUG << "Failed to write google_connection_options of length "
- << connection_options_length << " for " << in;
+ QUIC_BUG(quic_bug_10743_16)
+ << "Failed to write google_connection_options of length "
+ << connection_options_length << " for " << in;
return false;
}
for (const QuicTag& connection_option :
in.google_connection_options.value()) {
if (!writer.WriteTag(connection_option)) {
- QUIC_BUG << "Failed to write google_connection_option "
- << QuicTagToString(connection_option) << " for " << in;
+ QUIC_BUG(quic_bug_10743_17)
+ << "Failed to write google_connection_option "
+ << QuicTagToString(connection_option) << " for " << in;
return false;
}
}
@@ -845,8 +850,9 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
if (in.user_agent_id.has_value()) {
if (!writer.WriteVarInt62(TransportParameters::kGoogleUserAgentId) ||
!writer.WriteStringPieceVarInt62(in.user_agent_id.value())) {
- QUIC_BUG << "Failed to write Google user agent ID \""
- << in.user_agent_id.value() << "\" for " << in;
+ QUIC_BUG(quic_bug_10743_18)
+ << "Failed to write Google user agent ID \""
+ << in.user_agent_id.value() << "\" for " << in;
return false;
}
}
@@ -856,7 +862,8 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
if (!writer.WriteVarInt62(
TransportParameters::kGoogleKeyUpdateNotYetSupported) ||
!writer.WriteVarInt62(/* transport parameter length */ 0)) {
- QUIC_BUG << "Failed to write key_update_not_yet_supported for " << in;
+ QUIC_BUG(quic_bug_10743_19)
+ << "Failed to write key_update_not_yet_supported for " << in;
return false;
}
}
@@ -873,18 +880,21 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
!writer.WriteVarInt62(
/* transport parameter length */ google_version_length) ||
!writer.WriteUInt32(in.version)) {
- QUIC_BUG << "Failed to write Google version extension for " << in;
+ QUIC_BUG(quic_bug_10743_20)
+ << "Failed to write Google version extension for " << in;
return false;
}
if (in.perspective == Perspective::IS_SERVER) {
if (!writer.WriteUInt8(sizeof(QuicVersionLabel) *
in.supported_versions.size())) {
- QUIC_BUG << "Failed to write versions length for " << in;
+ QUIC_BUG(quic_bug_10743_21)
+ << "Failed to write versions length for " << in;
return false;
}
for (QuicVersionLabel version_label : in.supported_versions) {
if (!writer.WriteUInt32(version_label)) {
- QUIC_BUG << "Failed to write supported version for " << in;
+ QUIC_BUG(quic_bug_10743_22)
+ << "Failed to write supported version for " << in;
return false;
}
}
@@ -895,13 +905,15 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
if (param_id % 31 == 27) {
// See the "Reserved Transport Parameters" section of
// draft-ietf-quic-transport.
- QUIC_BUG << "Serializing custom_parameters with GREASE ID " << param_id
- << " is not allowed";
+ QUIC_BUG(quic_bug_10743_23)
+ << "Serializing custom_parameters with GREASE ID " << param_id
+ << " is not allowed";
return false;
}
if (!writer.WriteVarInt62(param_id) ||
!writer.WriteStringPieceVarInt62(kv.second)) {
- QUIC_BUG << "Failed to write custom parameter " << param_id;
+ QUIC_BUG(quic_bug_10743_24)
+ << "Failed to write custom parameter " << param_id;
return false;
}
}
@@ -928,8 +940,8 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
if (!writer.WriteVarInt62(grease_id) ||
!writer.WriteStringPieceVarInt62(
absl::string_view(grease_contents, grease_length))) {
- QUIC_BUG << "Failed to write GREASE parameter "
- << TransportParameterIdToString(grease_id);
+ QUIC_BUG(quic_bug_10743_25) << "Failed to write GREASE parameter "
+ << TransportParameterIdToString(grease_id);
return false;
}
}
@@ -1253,8 +1265,8 @@ bool SerializeTransportParametersForTicket(
std::vector<uint8_t>* out) {
std::string error_details;
if (!in.AreValid(&error_details)) {
- QUIC_BUG << "Not serializing invalid transport parameters: "
- << error_details;
+ QUIC_BUG(quic_bug_10743_26)
+ << "Not serializing invalid transport parameters: " << error_details;
return false;
}
@@ -1286,8 +1298,9 @@ bool SerializeTransportParametersForTicket(
application_data.size()) ||
!EVP_DigestUpdate(hash_ctx.get(), &parameter_version,
sizeof(parameter_version))) {
- QUIC_BUG << "Unexpected failure of EVP_Digest functions when hashing "
- "Transport Parameters for ticket";
+ QUIC_BUG(quic_bug_10743_27)
+ << "Unexpected failure of EVP_Digest functions when hashing "
+ "Transport Parameters for ticket";
return false;
}
@@ -1304,16 +1317,18 @@ bool SerializeTransportParametersForTicket(
!DigestUpdateIntegerParam(hash_ctx.get(), in.initial_max_streams_uni) ||
!DigestUpdateIntegerParam(hash_ctx.get(),
in.active_connection_id_limit)) {
- QUIC_BUG << "Unexpected failure of EVP_Digest functions when hashing "
- "Transport Parameters for ticket";
+ QUIC_BUG(quic_bug_10743_28)
+ << "Unexpected failure of EVP_Digest functions when hashing "
+ "Transport Parameters for ticket";
return false;
}
uint8_t disable_active_migration = in.disable_active_migration ? 1 : 0;
if (!EVP_DigestUpdate(hash_ctx.get(), &disable_active_migration,
sizeof(disable_active_migration)) ||
!EVP_DigestFinal(hash_ctx.get(), out->data() + 1, nullptr)) {
- QUIC_BUG << "Unexpected failure of EVP_Digest functions when hashing "
- "Transport Parameters for ticket";
+ QUIC_BUG(quic_bug_10743_29)
+ << "Unexpected failure of EVP_Digest functions when hashing "
+ "Transport Parameters for ticket";
return false;
}
return true;
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters_test.cc
index 3d23ae6a33b..81707c51885 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters_test.cc
@@ -448,7 +448,7 @@ TEST_P(TransportParametersTest, NoClientParamsWithStatelessResetToken) {
orig_params.max_udp_payload_size.set_value(kMaxPacketSizeForTest);
std::vector<uint8_t> out;
- bool ok;
+ bool ok = true;
EXPECT_QUIC_BUG(
ok = SerializeTransportParameters(version_, orig_params, &out),
"Not serializing invalid transport parameters: Client cannot send "
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_ack_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_ack_frame.cc
index 7c112c2c5e0..724833e02f0 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_ack_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_ack_frame.cc
@@ -96,7 +96,7 @@ bool PacketNumberQueue::RemoveUpTo(QuicPacketNumber higher) {
void PacketNumberQueue::RemoveSmallestInterval() {
// TODO(wub): Move this QUIC_BUG to upper level.
- QUIC_BUG_IF(packet_number_intervals_.Size() < 2)
+ QUIC_BUG_IF(quic_bug_12614_1, packet_number_intervals_.Size() < 2)
<< (Empty() ? "No intervals to remove."
: "Can't remove the last interval.");
packet_number_intervals_.PopFront();
@@ -171,7 +171,7 @@ std::ostream& operator<<(std::ostream& os, const PacketNumberQueue& q) {
(interval.max() - interval.min() > kMaxPrintRange)) {
// If min>max, it's really a bug, so QUIC_BUG it to
// catch it in development.
- QUIC_BUG_IF(interval.min() >= interval.max())
+ QUIC_BUG_IF(quic_bug_12614_2, interval.min() >= interval.max())
<< "Ack Range minimum (" << interval.min() << "Not less than max ("
<< interval.max() << ")";
// print range as min...max rather than full list.
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.cc
index 0eee910af5d..e17c3e76c7c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "quic/core/quic_constants.h"
+#include "quic/core/quic_error_codes.h"
#include "quic/core/quic_types.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.cc
index e54e2544c0c..ad10d601c31 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.cc
@@ -267,7 +267,7 @@ void SetControlFrameId(QuicControlFrameId control_frame_id, QuicFrame* frame) {
frame->new_token_frame->control_frame_id = control_frame_id;
return;
default:
- QUIC_BUG
+ QUIC_BUG(quic_bug_12594_1)
<< "Try to set control frame id of a frame without control frame id";
}
}
@@ -318,7 +318,8 @@ QuicFrame CopyRetransmittableControlFrame(const QuicFrame& frame) {
copy = QuicFrame(new QuicNewTokenFrame(*frame.new_token_frame));
break;
default:
- QUIC_BUG << "Try to copy a non-retransmittable control frame: " << frame;
+ QUIC_BUG(quic_bug_10533_1)
+ << "Try to copy a non-retransmittable control frame: " << frame;
copy = QuicFrame(QuicPingFrame(kInvalidControlFrameId));
break;
}
@@ -412,7 +413,7 @@ QuicFrame CopyQuicFrame(QuicBufferAllocator* allocator,
copy = QuicFrame(new QuicAckFrequencyFrame(*frame.ack_frequency_frame));
break;
default:
- QUIC_BUG << "Cannot copy frame: " << frame;
+ QUIC_BUG(quic_bug_10533_2) << "Cannot copy frame: " << frame;
copy = QuicFrame(QuicPingFrame(kInvalidControlFrameId));
break;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frames_test.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frames_test.cc
index d5ca0a4d624..c11be9eb016 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frames_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frames_test.cc
@@ -116,7 +116,8 @@ TEST_F(QuicFramesTest, NewConnectionIdFrameToString) {
new_connection_id_frame.connection_id = TestConnectionId(2);
new_connection_id_frame.sequence_number = 2u;
new_connection_id_frame.retire_prior_to = 1u;
- new_connection_id_frame.stateless_reset_token = MakeQuicUint128(0, 1);
+ new_connection_id_frame.stateless_reset_token =
+ StatelessResetToken{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
std::ostringstream stream;
stream << new_connection_id_frame;
EXPECT_EQ(
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_connection_id_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_connection_id_frame.cc
index fa99dfe7b6b..b4c68ff78dd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_connection_id_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_connection_id_frame.cc
@@ -10,7 +10,7 @@ QuicNewConnectionIdFrame::QuicNewConnectionIdFrame(
QuicControlFrameId control_frame_id,
QuicConnectionId connection_id,
QuicConnectionIdSequenceNumber sequence_number,
- const QuicUint128 stateless_reset_token,
+ StatelessResetToken stateless_reset_token,
uint64_t retire_prior_to)
: control_frame_id(control_frame_id),
connection_id(connection_id),
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_connection_id_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_connection_id_frame.h
index 4cf0258ca10..9c3d2053d34 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_connection_id_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_connection_id_frame.h
@@ -11,7 +11,6 @@
#include "quic/core/quic_constants.h"
#include "quic/core/quic_error_codes.h"
#include "quic/core/quic_types.h"
-#include "quic/platform/api/quic_uint128.h"
namespace quic {
@@ -20,7 +19,7 @@ struct QUIC_EXPORT_PRIVATE QuicNewConnectionIdFrame {
QuicNewConnectionIdFrame(QuicControlFrameId control_frame_id,
QuicConnectionId connection_id,
QuicConnectionIdSequenceNumber sequence_number,
- const QuicUint128 stateless_reset_token,
+ StatelessResetToken stateless_reset_token,
uint64_t retire_prior_to);
friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
@@ -32,7 +31,7 @@ struct QUIC_EXPORT_PRIVATE QuicNewConnectionIdFrame {
QuicControlFrameId control_frame_id = kInvalidControlFrameId;
QuicConnectionId connection_id = EmptyQuicConnectionId();
QuicConnectionIdSequenceNumber sequence_number = 0;
- QuicUint128 stateless_reset_token;
+ StatelessResetToken stateless_reset_token;
uint64_t retire_prior_to;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_retire_connection_id_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_retire_connection_id_frame.h
index c6fc4117d18..3a8a4dac986 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_retire_connection_id_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_retire_connection_id_frame.h
@@ -10,7 +10,6 @@
#include "quic/core/quic_constants.h"
#include "quic/core/quic_error_codes.h"
#include "quic/core/quic_types.h"
-#include "quic/platform/api/quic_uint128.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_rst_stream_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_rst_stream_frame.cc
index 646425a674c..d70f217bc14 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_rst_stream_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_rst_stream_frame.cc
@@ -4,6 +4,8 @@
#include "quic/core/frames/quic_rst_stream_frame.h"
+#include "quic/core/quic_error_codes.h"
+
namespace quic {
QuicRstStreamFrame::QuicRstStreamFrame(QuicControlFrameId control_frame_id,
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_stop_sending_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_stop_sending_frame.cc
index ad02337b5ef..93eed75ccc4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_stop_sending_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_stop_sending_frame.cc
@@ -4,6 +4,8 @@
#include "quic/core/frames/quic_stop_sending_frame.h"
+#include "quic/core/quic_error_codes.h"
+
namespace quic {
QuicStopSendingFrame::QuicStopSendingFrame(QuicControlFrameId control_frame_id,
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 2000733ba9a..aceebe1b33b 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
@@ -16,6 +16,7 @@
#include "quic/core/crypto/null_encrypter.h"
#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_data_writer.h"
#include "quic/core/quic_epoll_connection_helper.h"
#include "quic/core/quic_error_codes.h"
@@ -24,6 +25,7 @@
#include "quic/core/quic_packet_writer_wrapper.h"
#include "quic/core/quic_packets.h"
#include "quic/core/quic_session.h"
+#include "quic/core/quic_types.h"
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_epoll.h"
#include "quic/platform/api/quic_error_code_wrappers.h"
@@ -55,9 +57,11 @@
#include "quic/test_tools/quic_stream_id_manager_peer.h"
#include "quic/test_tools/quic_stream_peer.h"
#include "quic/test_tools/quic_stream_sequencer_peer.h"
+#include "quic/test_tools/quic_test_backend.h"
#include "quic/test_tools/quic_test_client.h"
#include "quic/test_tools/quic_test_server.h"
#include "quic/test_tools/quic_test_utils.h"
+#include "quic/test_tools/quic_transport_test_tools.h"
#include "quic/test_tools/server_thread.h"
#include "quic/test_tools/simple_session_cache.h"
#include "quic/tools/quic_backend_response.h"
@@ -66,7 +70,6 @@
#include "quic/tools/quic_server.h"
#include "quic/tools/quic_simple_client_stream.h"
#include "quic/tools/quic_simple_server_stream.h"
-#include "common/platform/api/quiche_text_utils.h"
using spdy::kV3LowestPriority;
using spdy::SpdyFramer;
@@ -74,6 +77,7 @@ using spdy::SpdyHeaderBlock;
using spdy::SpdySerializedFrame;
using spdy::SpdySettingsIR;
using ::testing::_;
+using ::testing::Assign;
using ::testing::Invoke;
using ::testing::NiceMock;
@@ -198,7 +202,6 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
AddToCache("/foo", 200, kFooResponseBody);
AddToCache("/bar", 200, kBarResponseBody);
// Enable fixes for bugs found in tests and prod.
- SetQuicRestartFlag(quic_enable_zero_rtt_for_tls_v2, true);
}
~EndToEndTest() override { QuicRecyclePort(server_address_.port()); }
@@ -221,6 +224,7 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
client->UseConnectionIdLength(override_server_connection_id_length_);
client->UseClientConnectionIdLength(override_client_connection_id_length_);
client->client()->set_connection_debug_visitor(connection_debug_visitor_);
+ client->client()->set_enable_web_transport(enable_web_transport_);
client->Connect();
return client;
}
@@ -357,6 +361,11 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
}
bool Initialize() {
+ if (enable_web_transport_) {
+ SetQuicReloadableFlag(quic_h3_datagram, true);
+ memory_cache_backend_.set_enable_webtransport(true);
+ }
+
QuicTagVector copt;
server_config_.SetConnectionOptionsToSend(copt);
copt = client_extra_copts_;
@@ -369,6 +378,7 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
copt.push_back(kILD0);
}
copt.push_back(kPLE1);
+ copt.push_back(kRVCM);
client_config_.SetConnectionOptionsToSend(copt);
// Start the server first, because CreateQuicClient() attempts
@@ -669,6 +679,77 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
return WaitForFooResponseAndCheckIt(client_.get());
}
+ WebTransportHttp3* CreateWebTransportSession(const std::string& path,
+ bool wait_for_server_response) {
+ // Wait until we receive the settings from the server indicating
+ // WebTransport support.
+ client_->WaitUntil(
+ 2000, [this]() { return GetClientSession()->SupportsWebTransport(); });
+ if (!GetClientSession()->SupportsWebTransport()) {
+ return nullptr;
+ }
+
+ spdy::SpdyHeaderBlock headers;
+ headers[":scheme"] = "https";
+ headers[":authority"] = "localhost";
+ headers[":path"] = path;
+ headers[":method"] = "CONNECT";
+ headers[":protocol"] = "webtransport";
+
+ client_->SendMessage(headers, "", /*fin=*/false);
+ QuicSpdyStream* stream = client_->latest_created_stream();
+ if (stream->web_transport() == nullptr) {
+ return nullptr;
+ }
+ WebTransportSessionId id = client_->latest_created_stream()->id();
+ QuicSpdySession* client_session = GetClientSession();
+ if (client_session->GetWebTransportSession(id) == nullptr) {
+ return nullptr;
+ }
+ WebTransportHttp3* session = client_session->GetWebTransportSession(id);
+ if (wait_for_server_response) {
+ client_->WaitUntil(-1,
+ [stream]() { return stream->headers_decompressed(); });
+ EXPECT_TRUE(session->ready());
+ }
+ return session;
+ }
+
+ NiceMock<MockClientVisitor>& SetupWebTransportVisitor(
+ WebTransportHttp3* session) {
+ auto visitor_owned = std::make_unique<NiceMock<MockClientVisitor>>();
+ NiceMock<MockClientVisitor>& visitor = *visitor_owned;
+ session->SetVisitor(std::move(visitor_owned));
+ return visitor;
+ }
+
+ std::string ReadDataFromWebTransportStreamUntilFin(
+ WebTransportStream* stream) {
+ std::string buffer;
+ while (true) {
+ bool can_read = false;
+ auto visitor = std::make_unique<MockStreamVisitor>();
+ EXPECT_CALL(*visitor, OnCanRead()).WillOnce(Assign(&can_read, true));
+ stream->SetVisitor(std::move(visitor));
+ client_->WaitUntil(5000 /*ms*/, [&can_read]() { return can_read; });
+ if (!can_read) {
+ ADD_FAILURE() << "Waiting for readable data on stream "
+ << stream->GetStreamId() << " timed out";
+ return buffer;
+ }
+
+ WebTransportStream::ReadResult result = stream->Read(&buffer);
+ if (result.fin) {
+ return buffer;
+ }
+ if (result.bytes_read == 0) {
+ ADD_FAILURE() << "No progress made while reading from stream "
+ << stream->GetStreamId();
+ return buffer;
+ }
+ }
+ }
+
ScopedEnvironmentForThreads environment_;
bool initialized_;
// If true, the Initialize() function will create |client_| and starts to
@@ -677,7 +758,7 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
bool connect_to_server_on_initialize_;
QuicSocketAddress server_address_;
std::string server_hostname_;
- QuicMemoryCacheBackend memory_cache_backend_;
+ QuicTestBackend memory_cache_backend_;
std::unique_ptr<ServerThread> server_thread_;
std::unique_ptr<QuicTestClient> client_;
QuicConnectionDebugVisitor* connection_debug_visitor_ = nullptr;
@@ -696,6 +777,7 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
int override_server_connection_id_length_ = -1;
int override_client_connection_id_length_ = -1;
uint8_t expected_server_connection_id_length_;
+ bool enable_web_transport_ = false;
};
// Run all end to end tests with all supported versions.
@@ -1794,8 +1876,11 @@ TEST_P(EndToEndTest, RetransmissionAfterZeroRTTRejectBeforeOneRtt) {
ON_CALL(visitor, OnZeroRttRejected(_)).WillByDefault(Invoke([this]() {
EXPECT_FALSE(GetClientSession()->IsEncryptionEstablished());
- // Trigger an OnCanWrite() to make sure no unencrypted data will be written.
- GetClientSession()->OnCanWrite();
+ if (!GetQuicReloadableFlag(quic_donot_write_mid_packet_processing)) {
+ // Trigger an OnCanWrite() to make sure no unencrypted data will be
+ // written.
+ GetClientSession()->OnCanWrite();
+ }
}));
// The 0-RTT handshake should fail.
@@ -2386,6 +2471,50 @@ TEST_P(EndToEndTest, ResetConnection) {
SendSynchronousBarRequestAndCheckResponse();
}
+// Regression test for b/180737158.
+TEST_P(
+ EndToEndTest,
+ 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);
+ ASSERT_TRUE(Initialize());
+ if (!version_.SupportsAntiAmplificationLimit()) {
+ return;
+ }
+ // Perform a full 1-RTT handshake to get the new session ticket such that the
+ // next connection will perform a 0-RTT handshake.
+ EXPECT_TRUE(client_->client()->WaitForHandshakeConfirmed());
+ client_->Disconnect();
+
+ server_thread_->Pause();
+ // Drop the 1st server packet which is the coalesced INITIAL + HANDSHAKE +
+ // 1RTT.
+ PacketDroppingTestWriter* writer = new PacketDroppingTestWriter();
+ writer->set_fake_drop_first_n_packets(1);
+ QuicDispatcherPeer::UseWriter(
+ QuicServerPeer::GetDispatcher(server_thread_->server()), writer);
+ server_thread_->Resume();
+
+ // 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"));
+ }
+}
+
TEST_P(EndToEndTest, MaxStreamsUberTest) {
// Connect with lower fake packet loss than we'd like to test. Until
// b/10126687 is fixed, losing handshake packets is pretty brutal.
@@ -3209,7 +3338,8 @@ TEST_P(EndToEndTest, ServerSendPublicReset) {
QuicConfig* config = client_session->config();
ASSERT_TRUE(config);
EXPECT_TRUE(config->HasReceivedStatelessResetToken());
- QuicUint128 stateless_reset_token = config->ReceivedStatelessResetToken();
+ StatelessResetToken stateless_reset_token =
+ config->ReceivedStatelessResetToken();
// Send the public reset.
QuicConnection* client_connection = GetClientConnection();
@@ -3221,8 +3351,8 @@ TEST_P(EndToEndTest, ServerSendPublicReset) {
Perspective::IS_SERVER, kQuicDefaultConnectionIdLength);
std::unique_ptr<QuicEncryptedPacket> packet;
if (version_.HasIetfInvariantHeader()) {
- packet = framer.BuildIetfStatelessResetPacket(connection_id,
- stateless_reset_token);
+ packet = framer.BuildIetfStatelessResetPacket(
+ connection_id, /*received_packet_length=*/100, stateless_reset_token);
} else {
packet = framer.BuildPublicResetPacket(header);
}
@@ -3251,7 +3381,8 @@ TEST_P(EndToEndTest, ServerSendPublicResetWithDifferentConnectionId) {
QuicConfig* config = client_session->config();
ASSERT_TRUE(config);
EXPECT_TRUE(config->HasReceivedStatelessResetToken());
- QuicUint128 stateless_reset_token = config->ReceivedStatelessResetToken();
+ StatelessResetToken stateless_reset_token =
+ config->ReceivedStatelessResetToken();
// Send the public reset.
QuicConnection* client_connection = GetClientConnection();
ASSERT_TRUE(client_connection);
@@ -3265,8 +3396,9 @@ TEST_P(EndToEndTest, ServerSendPublicResetWithDifferentConnectionId) {
NiceMock<MockQuicConnectionDebugVisitor> visitor;
client_connection->set_debug_visitor(&visitor);
if (version_.HasIetfInvariantHeader()) {
- packet = framer.BuildIetfStatelessResetPacket(incorrect_connection_id,
- stateless_reset_token);
+ packet = framer.BuildIetfStatelessResetPacket(
+ incorrect_connection_id, /*received_packet_length=*/100,
+ stateless_reset_token);
EXPECT_CALL(visitor, OnIncorrectConnectionId(incorrect_connection_id))
.Times(0);
} else {
@@ -3518,8 +3650,7 @@ class ServerStreamWithErrorResponseBody : public QuicSimpleServerStream {
QUIC_DLOG(INFO) << "Sending error response for stream " << id();
SpdyHeaderBlock headers;
headers[":status"] = "500";
- headers["content-length"] =
- quiche::QuicheTextUtils::Uint64ToString(response_body_.size());
+ headers["content-length"] = absl::StrCat(response_body_.size());
// This method must call CloseReadSide to cause the test case, StopReading
// is not sufficient.
QuicStreamPeer::CloseReadSide(this);
@@ -3736,8 +3867,7 @@ TEST_P(EndToEndTest, Trailers) {
SpdyHeaderBlock headers;
headers[":status"] = "200";
- headers["content-length"] =
- quiche::QuicheTextUtils::Uint64ToString(kBody.size());
+ headers["content-length"] = absl::StrCat(kBody.size());
SpdyHeaderBlock trailers;
trailers["some-trailing-header"] = "trailing-header-value";
@@ -3750,13 +3880,11 @@ TEST_P(EndToEndTest, Trailers) {
EXPECT_EQ(trailers, client_->response_trailers());
}
-// TODO(b/151749109): Test server push for IETF QUIC.
class EndToEndTestServerPush : public EndToEndTest {
protected:
const size_t kNumMaxStreams = 10;
EndToEndTestServerPush() : EndToEndTest() {
- SetQuicFlag(FLAGS_quic_enable_http3_server_push, true);
client_config_.SetMaxBidirectionalStreamsToSend(kNumMaxStreams);
server_config_.SetMaxBidirectionalStreamsToSend(kNumMaxStreams);
client_config_.SetMaxUnidirectionalStreamsToSend(kNumMaxStreams);
@@ -3791,8 +3919,7 @@ class EndToEndTestServerPush : public EndToEndTest {
: absl::StrCat("This is server push response body for ", url);
SpdyHeaderBlock response_headers;
response_headers[":status"] = "200";
- response_headers["content-length"] =
- quiche::QuicheTextUtils::Uint64ToString(body.size());
+ response_headers["content-length"] = absl::StrCat(body.size());
push_resources.push_back(QuicBackendResponse::ServerPushInfo(
resource_url, std::move(response_headers), kV3LowestPriority, body));
}
@@ -3869,12 +3996,11 @@ TEST_P(EndToEndTestServerPush, ServerPushUnderLimit) {
// them with requests later.
ASSERT_TRUE(Initialize());
- EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
if (version_.UsesHttp3()) {
- static_cast<QuicSpdySession*>(client_->client()->session())
- ->SetMaxPushId(kMaxQuicStreamId);
+ 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);
@@ -3918,8 +4044,6 @@ TEST_P(EndToEndTestServerPush, ServerPushUnderLimit) {
TEST_P(EndToEndTestServerPush, ServerPushOverLimitNonBlocking) {
if (version_.UsesHttp3()) {
- // TODO(b/142504641): Re-enable this test when we support push streams
- // arriving before the corresponding promises.
ASSERT_TRUE(Initialize());
return;
}
@@ -3929,10 +4053,6 @@ TEST_P(EndToEndTestServerPush, ServerPushOverLimitNonBlocking) {
// immediately after pushing resources.
ASSERT_TRUE(Initialize());
EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
- if (version_.UsesHttp3()) {
- static_cast<QuicSpdySession*>(client_->client()->session())
- ->SetMaxPushId(kMaxQuicStreamId);
- }
// Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
@@ -3974,6 +4094,11 @@ TEST_P(EndToEndTestServerPush, ServerPushOverLimitNonBlocking) {
}
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
@@ -3991,10 +4116,6 @@ TEST_P(EndToEndTestServerPush, ServerPushOverLimitWithBlocking) {
ASSERT_TRUE(Initialize());
EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
- if (version_.UsesHttp3()) {
- static_cast<QuicSpdySession*>(client_->client()->session())
- ->SetMaxPushId(kMaxQuicStreamId);
- }
// Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
@@ -4092,8 +4213,7 @@ TEST_P(EndToEndTest, DISABLED_TestHugePostWithPacketLoss) {
headers[":path"] = "/foo";
headers[":scheme"] = "https";
headers[":authority"] = server_hostname_;
- headers["content-length"] =
- quiche::QuicheTextUtils::Uint64ToString(request_body_size_bytes);
+ headers["content-length"] = absl::StrCat(request_body_size_bytes);
client_->SendMessage(headers, "", /*fin=*/false);
@@ -4320,7 +4440,11 @@ TEST_P(EndToEndTest,
client_.reset(CreateQuicClient(client_writer_));
EXPECT_EQ("", client_->SendSynchronousRequest("/foo"));
- EXPECT_THAT(client_->connection_error(), IsError(QUIC_HANDSHAKE_FAILED));
+ 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));
+ }
}
// Regression test for b/116200989.
@@ -4418,7 +4542,7 @@ TEST_P(EndToEndTest, PreSharedKey) {
if (version_.UsesTls()) {
// TODO(b/154162689) add PSK support to QUIC+TLS.
- bool ok;
+ bool ok = true;
EXPECT_QUIC_BUG(ok = Initialize(),
"QUIC client pre-shared keys not yet supported with TLS");
EXPECT_FALSE(ok);
@@ -4441,7 +4565,7 @@ TEST_P(EndToEndTest, QUIC_TEST_DISABLED_IN_CHROME(PreSharedKeyMismatch)) {
if (version_.UsesTls()) {
// TODO(b/154162689) add PSK support to QUIC+TLS.
- bool ok;
+ bool ok = true;
EXPECT_QUIC_BUG(ok = Initialize(),
"QUIC client pre-shared keys not yet supported with TLS");
EXPECT_FALSE(ok);
@@ -4468,7 +4592,7 @@ TEST_P(EndToEndTest, QUIC_TEST_DISABLED_IN_CHROME(PreSharedKeyNoClient)) {
if (version_.UsesTls()) {
// TODO(b/154162689) add PSK support to QUIC+TLS.
- bool ok;
+ bool ok = true;
EXPECT_QUIC_BUG(ok = Initialize(),
"QUIC server pre-shared keys not yet supported with TLS");
EXPECT_FALSE(ok);
@@ -4489,7 +4613,7 @@ TEST_P(EndToEndTest, QUIC_TEST_DISABLED_IN_CHROME(PreSharedKeyNoServer)) {
if (version_.UsesTls()) {
// TODO(b/154162689) add PSK support to QUIC+TLS.
- bool ok;
+ bool ok = true;
EXPECT_QUIC_BUG(ok = Initialize(),
"QUIC client pre-shared keys not yet supported with TLS");
EXPECT_FALSE(ok);
@@ -4508,9 +4632,8 @@ TEST_P(EndToEndTest, RequestAndStreamRstInOnePacket) {
// (and the FIN) after the response body.
std::string response_body(1305, 'a');
SpdyHeaderBlock response_headers;
- response_headers[":status"] = quiche::QuicheTextUtils::Uint64ToString(200);
- response_headers["content-length"] =
- quiche::QuicheTextUtils::Uint64ToString(response_body.length());
+ response_headers[":status"] = absl::StrCat(200);
+ response_headers["content-length"] = absl::StrCat(response_body.length());
memory_cache_backend_.AddSpecialResponse(
server_hostname_, "/test_url", std::move(response_headers), response_body,
QuicBackendResponse::INCOMPLETE_RESPONSE);
@@ -5127,34 +5250,6 @@ TEST_P(EndToEndTest, TooBigStreamIdClosesConnection) {
IS_IETF_STREAM_FRAME(client_session->transport_close_frame_type()));
}
-TEST_P(EndToEndTest, TestMaxPushId) {
- if (!version_.HasIetfQuicFrames()) {
- // MaxPushId is only implemented for IETF QUIC.
- Initialize();
- return;
- }
- SetQuicFlag(FLAGS_quic_enable_http3_server_push, true);
- ASSERT_TRUE(Initialize());
-
- EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
- QuicSpdyClientSession* client_session = GetClientSession();
- ASSERT_TRUE(client_session);
- client_session->SetMaxPushId(kMaxQuicStreamId);
-
- client_->SendSynchronousRequest("/foo");
-
- EXPECT_TRUE(client_session->CanCreatePushStreamWithId(kMaxQuicStreamId));
-
- server_thread_->Pause();
- QuicSpdySession* server_session = GetServerSession();
- if (server_session != nullptr) {
- EXPECT_TRUE(server_session->CanCreatePushStreamWithId(kMaxQuicStreamId));
- } else {
- ADD_FAILURE() << "Missing server session";
- }
- server_thread_->Resume();
-}
-
TEST_P(EndToEndTest, CustomTransportParameters) {
if (!version_.UsesTls()) {
// Custom transport parameters are only supported with TLS.
@@ -5624,6 +5719,213 @@ TEST_P(EndToEndTest, TlsResumptionDisabledOnTheFly) {
ADD_FAILURE() << "Client should not have 10 resumption tickets.";
}
+TEST_P(EndToEndTest, WebTransportSessionSetup) {
+ enable_web_transport_ = true;
+ ASSERT_TRUE(Initialize());
+
+ if (!version_.UsesHttp3()) {
+ return;
+ }
+
+ WebTransportHttp3* web_transport =
+ CreateWebTransportSession("/echo", /*wait_for_server_response=*/true);
+
+ server_thread_->Pause();
+ QuicSpdySession* server_session = GetServerSession();
+ EXPECT_TRUE(server_session->GetWebTransportSession(web_transport->id()) !=
+ nullptr);
+ server_thread_->Resume();
+}
+
+TEST_P(EndToEndTest, WebTransportSessionWithLoss) {
+ enable_web_transport_ = true;
+ // Enable loss to verify all permutations of receiving SETTINGS and
+ // request/response data.
+ SetPacketLossPercentage(30);
+ ASSERT_TRUE(Initialize());
+
+ if (!version_.UsesHttp3()) {
+ return;
+ }
+
+ WebTransportHttp3* web_transport =
+ CreateWebTransportSession("/echo", /*wait_for_server_response=*/true);
+
+ server_thread_->Pause();
+ QuicSpdySession* server_session = GetServerSession();
+ EXPECT_TRUE(server_session->GetWebTransportSession(web_transport->id()) !=
+ nullptr);
+ server_thread_->Resume();
+}
+
+TEST_P(EndToEndTest, WebTransportSessionUnidirectionalStream) {
+ enable_web_transport_ = true;
+ ASSERT_TRUE(Initialize());
+
+ if (!version_.UsesHttp3()) {
+ return;
+ }
+
+ WebTransportHttp3* session =
+ CreateWebTransportSession("/echo", /*wait_for_server_response=*/true);
+ ASSERT_TRUE(session != nullptr);
+ NiceMock<MockClientVisitor>& visitor = SetupWebTransportVisitor(session);
+
+ WebTransportStream* outgoing_stream =
+ session->OpenOutgoingUnidirectionalStream();
+ ASSERT_TRUE(outgoing_stream != nullptr);
+ EXPECT_TRUE(outgoing_stream->Write("test"));
+ EXPECT_TRUE(outgoing_stream->SendFin());
+
+ bool stream_received = false;
+ EXPECT_CALL(visitor, OnIncomingUnidirectionalStreamAvailable())
+ .WillOnce(Assign(&stream_received, true));
+ client_->WaitUntil(2000, [&stream_received]() { return stream_received; });
+ EXPECT_TRUE(stream_received);
+ WebTransportStream* received_stream =
+ session->AcceptIncomingUnidirectionalStream();
+ ASSERT_TRUE(received_stream != nullptr);
+ std::string received_data;
+ WebTransportStream::ReadResult result = received_stream->Read(&received_data);
+ EXPECT_EQ(received_data, "test");
+ EXPECT_TRUE(result.fin);
+}
+
+TEST_P(EndToEndTest, WebTransportSessionUnidirectionalStreamSentEarly) {
+ enable_web_transport_ = true;
+ SetPacketLossPercentage(30);
+ ASSERT_TRUE(Initialize());
+
+ if (!version_.UsesHttp3()) {
+ return;
+ }
+
+ WebTransportHttp3* session =
+ CreateWebTransportSession("/echo", /*wait_for_server_response=*/false);
+ ASSERT_TRUE(session != nullptr);
+ NiceMock<MockClientVisitor>& visitor = SetupWebTransportVisitor(session);
+
+ WebTransportStream* outgoing_stream =
+ session->OpenOutgoingUnidirectionalStream();
+ ASSERT_TRUE(outgoing_stream != nullptr);
+ EXPECT_TRUE(outgoing_stream->Write("test"));
+ EXPECT_TRUE(outgoing_stream->SendFin());
+
+ bool stream_received = false;
+ EXPECT_CALL(visitor, OnIncomingUnidirectionalStreamAvailable())
+ .WillOnce(Assign(&stream_received, true));
+ client_->WaitUntil(5000, [&stream_received]() { return stream_received; });
+ EXPECT_TRUE(stream_received);
+ WebTransportStream* received_stream =
+ session->AcceptIncomingUnidirectionalStream();
+ ASSERT_TRUE(received_stream != nullptr);
+ std::string received_data;
+ WebTransportStream::ReadResult result = received_stream->Read(&received_data);
+ EXPECT_EQ(received_data, "test");
+ EXPECT_TRUE(result.fin);
+}
+
+TEST_P(EndToEndTest, WebTransportSessionBidirectionalStream) {
+ enable_web_transport_ = true;
+ ASSERT_TRUE(Initialize());
+
+ if (!version_.UsesHttp3()) {
+ return;
+ }
+
+ WebTransportHttp3* session =
+ CreateWebTransportSession("/echo", /*wait_for_server_response=*/true);
+ ASSERT_TRUE(session != nullptr);
+
+ WebTransportStream* stream = session->OpenOutgoingBidirectionalStream();
+ ASSERT_TRUE(stream != nullptr);
+ EXPECT_TRUE(stream->Write("test"));
+ EXPECT_TRUE(stream->SendFin());
+
+ std::string received_data = ReadDataFromWebTransportStreamUntilFin(stream);
+ EXPECT_EQ(received_data, "test");
+}
+
+TEST_P(EndToEndTest, WebTransportSessionBidirectionalStreamWithBuffering) {
+ enable_web_transport_ = true;
+ SetPacketLossPercentage(30);
+ ASSERT_TRUE(Initialize());
+
+ if (!version_.UsesHttp3()) {
+ return;
+ }
+
+ WebTransportHttp3* session =
+ CreateWebTransportSession("/echo", /*wait_for_server_response=*/false);
+ ASSERT_TRUE(session != nullptr);
+
+ WebTransportStream* stream = session->OpenOutgoingBidirectionalStream();
+ ASSERT_TRUE(stream != nullptr);
+ EXPECT_TRUE(stream->Write("test"));
+ EXPECT_TRUE(stream->SendFin());
+
+ std::string received_data = ReadDataFromWebTransportStreamUntilFin(stream);
+ EXPECT_EQ(received_data, "test");
+}
+
+TEST_P(EndToEndTest, WebTransportSessionServerBidirectionalStream) {
+ enable_web_transport_ = true;
+ ASSERT_TRUE(Initialize());
+
+ if (!version_.UsesHttp3()) {
+ return;
+ }
+
+ WebTransportHttp3* session =
+ CreateWebTransportSession("/echo", /*wait_for_server_response=*/false);
+ ASSERT_TRUE(session != nullptr);
+ NiceMock<MockClientVisitor>& visitor = SetupWebTransportVisitor(session);
+
+ bool stream_received = false;
+ EXPECT_CALL(visitor, OnIncomingBidirectionalStreamAvailable())
+ .WillOnce(Assign(&stream_received, true));
+ client_->WaitUntil(5000, [&stream_received]() { return stream_received; });
+ EXPECT_TRUE(stream_received);
+
+ WebTransportStream* stream = session->AcceptIncomingBidirectionalStream();
+ ASSERT_TRUE(stream != nullptr);
+ EXPECT_TRUE(stream->Write("test"));
+ EXPECT_TRUE(stream->SendFin());
+
+ std::string received_data = ReadDataFromWebTransportStreamUntilFin(stream);
+ EXPECT_EQ(received_data, "test");
+}
+
+TEST_P(EndToEndTest, WebTransportDatagrams) {
+ enable_web_transport_ = true;
+ ASSERT_TRUE(Initialize());
+
+ if (!version_.UsesHttp3()) {
+ return;
+ }
+
+ WebTransportHttp3* session =
+ CreateWebTransportSession("/echo", /*wait_for_server_response=*/true);
+ ASSERT_TRUE(session != nullptr);
+ NiceMock<MockClientVisitor>& visitor = SetupWebTransportVisitor(session);
+
+ SimpleBufferAllocator allocator;
+ for (int i = 0; i < 10; i++) {
+ absl::string_view datagram = "test";
+ 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));
+ }
+
+ int received = 0;
+ EXPECT_CALL(visitor, OnDatagramReceived(_)).WillRepeatedly([&received]() {
+ received++;
+ });
+ client_->WaitUntil(5000, [&received]() { return received > 0; });
+ EXPECT_GT(received, 0);
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_constants.cc b/chromium/net/third_party/quiche/src/quic/core/http/http_constants.cc
index b3262d25b7d..f3ed523647f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_constants.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_constants.cc
@@ -17,10 +17,14 @@ std::string H3SettingsToString(Http3AndQpackSettingsIdentifiers identifier) {
RETURN_STRING_LITERAL(SETTINGS_QPACK_MAX_TABLE_CAPACITY);
RETURN_STRING_LITERAL(SETTINGS_MAX_FIELD_SECTION_SIZE);
RETURN_STRING_LITERAL(SETTINGS_QPACK_BLOCKED_STREAMS);
+ RETURN_STRING_LITERAL(SETTINGS_H3_DATAGRAM);
+ RETURN_STRING_LITERAL(SETTINGS_WEBTRANS_DRAFT00);
}
return absl::StrCat("UNSUPPORTED_SETTINGS_TYPE(", identifier, ")");
}
+const absl::string_view kUserAgentHeaderName = "user-agent";
+
#undef RETURN_STRING_LITERAL // undef for jumbo builds
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_constants.h b/chromium/net/third_party/quiche/src/quic/core/http/http_constants.h
index 8c68e74bccc..c13a1a8c2b2 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_constants.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_constants.h
@@ -8,22 +8,26 @@
#include <cstdint>
#include <string>
+#include "absl/strings/string_view.h"
#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_export.h"
namespace quic {
// Unidirectional stream types.
-
-// https://quicwg.org/base-drafts/draft-ietf-quic-http.html#unidirectional-streams
-const uint64_t kControlStream = 0x00;
-const uint64_t kServerPushStream = 0x01;
-// https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#enc-dec-stream-def
-const uint64_t kQpackEncoderStream = 0x02;
-const uint64_t kQpackDecoderStream = 0x03;
+enum : uint64_t {
+ // https://quicwg.org/base-drafts/draft-ietf-quic-http.html#unidirectional-streams
+ kControlStream = 0x00,
+ kServerPushStream = 0x01,
+ // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#enc-dec-stream-def
+ kQpackEncoderStream = 0x02,
+ kQpackDecoderStream = 0x03,
+ // https://ietf-wg-webtrans.github.io/draft-ietf-webtrans-http3/draft-ietf-webtrans-http3.html#name-unidirectional-streams
+ kWebTransportUnidirectionalStream = 0x54,
+};
// This includes control stream, QPACK encoder stream, and QPACK decoder stream.
-const QuicStreamCount kHttp3StaticUnidirectionalStreamCount = 3;
+enum : QuicStreamCount { kHttp3StaticUnidirectionalStreamCount = 3 };
// HTTP/3 and QPACK settings identifiers.
// https://quicwg.org/base-drafts/draft-ietf-quic-http.html#settings-parameters
@@ -34,6 +38,10 @@ enum Http3AndQpackSettingsIdentifiers : uint64_t {
// Same value as spdy::SETTINGS_MAX_HEADER_LIST_SIZE.
SETTINGS_MAX_FIELD_SECTION_SIZE = 0x06,
SETTINGS_QPACK_BLOCKED_STREAMS = 0x07,
+ // draft-ietf-masque-h3-datagram.
+ SETTINGS_H3_DATAGRAM = 0x276,
+ // draft-ietf-webtrans-http3-00
+ SETTINGS_WEBTRANS_DRAFT00 = 0x2b603742,
};
// Returns HTTP/3 SETTINGS identifier as a string.
@@ -42,17 +50,22 @@ QUIC_EXPORT std::string H3SettingsToString(
// Default maximum dynamic table capacity, communicated via
// SETTINGS_QPACK_MAX_TABLE_CAPACITY.
-const QuicByteCount kDefaultQpackMaxDynamicTableCapacity = 64 * 1024; // 64 KB
+enum : QuicByteCount {
+ kDefaultQpackMaxDynamicTableCapacity = 64 * 1024 // 64 KB
+};
// Default limit on the size of uncompressed headers,
// communicated via SETTINGS_MAX_HEADER_LIST_SIZE.
-const QuicByteCount kDefaultMaxUncompressedHeaderSize = 16 * 1024; // 16 KB
+enum : QuicByteCount {
+ kDefaultMaxUncompressedHeaderSize = 16 * 1024 // 16 KB
+};
// Default limit on number of blocked streams, communicated via
// SETTINGS_QPACK_BLOCKED_STREAMS.
-const uint64_t kDefaultMaximumBlockedStreams = 100;
+enum : uint64_t { kDefaultMaximumBlockedStreams = 100 };
-const char kUserAgentHeaderName[] = "user-agent";
+ABSL_CONST_INIT QUIC_EXPORT_PRIVATE extern const absl::string_view
+ kUserAgentHeaderName;
} // namespace quic
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 fe33a817152..3544cfddf9a 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
@@ -5,6 +5,7 @@
#include "quic/core/http/http_decoder.h"
#include <cstdint>
+#include <limits>
#include "absl/base/attributes.h"
#include "absl/strings/string_view.h"
@@ -20,8 +21,10 @@
namespace quic {
-HttpDecoder::HttpDecoder(Visitor* visitor)
+HttpDecoder::HttpDecoder(Visitor* visitor) : HttpDecoder(visitor, Options()) {}
+HttpDecoder::HttpDecoder(Visitor* visitor, Options options)
: visitor_(visitor),
+ allow_web_transport_stream_(options.allow_web_transport_stream),
state_(STATE_READING_FRAME_TYPE),
current_frame_type_(0),
current_length_field_length_(0),
@@ -106,12 +109,21 @@ QuicByteCount HttpDecoder::ProcessInput(const char* data, QuicByteCount len) {
continue_processing = ReadFramePayload(&reader);
break;
case STATE_FINISH_PARSING:
- continue_processing = FinishParsing();
+ continue_processing = FinishParsing(&reader);
+ break;
+ case STATE_PARSING_NO_LONGER_POSSIBLE:
+ continue_processing = false;
+ QUIC_BUG(HttpDecoder PARSING_NO_LONGER_POSSIBLE)
+ << "HttpDecoder called after an indefinite-length frame has been "
+ "received";
+ RaiseError(QUIC_INTERNAL_ERROR,
+ "HttpDecoder called after an indefinite-length frame has "
+ "been received");
break;
case STATE_ERROR:
break;
default:
- QUIC_BUG << "Invalid state: " << state_;
+ QUIC_BUG(quic_bug_10411_1) << "Invalid state: " << state_;
}
}
@@ -192,6 +204,19 @@ bool HttpDecoder::ReadFrameLength(QuicDataReader* reader) {
QUICHE_DCHECK(success);
}
+ // WEBTRANSPORT_STREAM frames are indefinitely long, and thus require
+ // special handling; the number after the frame type is actually the
+ // WebTransport session ID, and not the length.
+ if (allow_web_transport_stream_ &&
+ current_frame_type_ ==
+ static_cast<uint64_t>(HttpFrameType::WEBTRANSPORT_STREAM)) {
+ visitor_->OnWebTransportStreamFrameType(
+ current_length_field_length_ + current_type_field_length_,
+ current_frame_length_);
+ state_ = STATE_PARSING_NO_LONGER_POSSIBLE;
+ return false;
+ }
+
if (current_frame_length_ > MaxFrameLength(current_frame_type_)) {
RaiseError(QUIC_HTTP_FRAME_TOO_LARGE, "Frame is too large.");
return false;
@@ -238,13 +263,7 @@ bool HttpDecoder::ReadFrameLength(QuicDataReader* reader) {
continue_processing = visitor_->OnPriorityUpdateFrameStart(header_length);
break;
case static_cast<uint64_t>(HttpFrameType::ACCEPT_CH):
- if (GetQuicReloadableFlag(quic_parse_accept_ch_frame)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_parse_accept_ch_frame);
- continue_processing = visitor_->OnAcceptChFrameStart(header_length);
- } else {
- continue_processing = visitor_->OnUnknownFrameStart(
- current_frame_type_, header_length, current_frame_length_);
- }
+ continue_processing = visitor_->OnAcceptChFrameStart(header_length);
break;
default:
continue_processing = visitor_->OnUnknownFrameStart(
@@ -288,11 +307,11 @@ bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
break;
}
case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): {
- BufferFramePayload(reader);
+ continue_processing = BufferOrParsePayload(reader);
break;
}
case static_cast<uint64_t>(HttpFrameType::SETTINGS): {
- BufferFramePayload(reader);
+ continue_processing = BufferOrParsePayload(reader);
break;
}
case static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE): {
@@ -361,33 +380,23 @@ bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
break;
}
case static_cast<uint64_t>(HttpFrameType::GOAWAY): {
- BufferFramePayload(reader);
+ continue_processing = BufferOrParsePayload(reader);
break;
}
case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID): {
- BufferFramePayload(reader);
+ continue_processing = BufferOrParsePayload(reader);
break;
}
case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE): {
- // TODO(bnc): Avoid buffering if the entire frame is present, and
- // instead parse directly out of |reader|.
- BufferFramePayload(reader);
+ continue_processing = BufferOrParsePayload(reader);
break;
}
case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE_REQUEST_STREAM): {
- // TODO(bnc): Avoid buffering if the entire frame is present, and
- // instead parse directly out of |reader|.
- BufferFramePayload(reader);
+ continue_processing = BufferOrParsePayload(reader);
break;
}
case static_cast<uint64_t>(HttpFrameType::ACCEPT_CH): {
- if (GetQuicReloadableFlag(quic_parse_accept_ch_frame)) {
- // TODO(bnc): Avoid buffering if the entire frame is present, and
- // instead parse directly out of |reader|.
- BufferFramePayload(reader);
- } else {
- continue_processing = HandleUnknownFramePayload(reader);
- }
+ continue_processing = BufferOrParsePayload(reader);
break;
}
default: {
@@ -396,14 +405,15 @@ bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
}
}
- if (remaining_frame_length_ == 0) {
+ // BufferOrParsePayload() may have advanced |state_|.
+ if (state_ == STATE_READING_FRAME_PAYLOAD && remaining_frame_length_ == 0) {
state_ = STATE_FINISH_PARSING;
}
return continue_processing;
}
-bool HttpDecoder::FinishParsing() {
+bool HttpDecoder::FinishParsing(QuicDataReader* reader) {
QUICHE_DCHECK_EQ(0u, remaining_frame_length_);
bool continue_processing = true;
@@ -418,28 +428,15 @@ bool HttpDecoder::FinishParsing() {
break;
}
case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): {
- CancelPushFrame frame;
- QuicDataReader reader(buffer_.data(), current_frame_length_);
- if (!reader.ReadVarInt62(&frame.push_id)) {
- RaiseError(QUIC_HTTP_FRAME_ERROR,
- "Unable to read CANCEL_PUSH push_id.");
- return false;
- }
- if (!reader.IsDoneReading()) {
- RaiseError(QUIC_HTTP_FRAME_ERROR,
- "Superfluous data in CANCEL_PUSH frame.");
- return false;
- }
- continue_processing = visitor_->OnCancelPushFrame(frame);
+ // 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): {
- SettingsFrame frame;
- QuicDataReader reader(buffer_.data(), current_frame_length_);
- if (!ParseSettingsFrame(&reader, &frame)) {
- return false;
- }
- continue_processing = visitor_->OnSettingsFrame(frame);
+ // 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::PUSH_PROMISE): {
@@ -447,70 +444,33 @@ bool HttpDecoder::FinishParsing() {
break;
}
case static_cast<uint64_t>(HttpFrameType::GOAWAY): {
- QuicDataReader reader(buffer_.data(), current_frame_length_);
- GoAwayFrame frame;
- if (!reader.ReadVarInt62(&frame.id)) {
- RaiseError(QUIC_HTTP_FRAME_ERROR, "Unable to read GOAWAY ID.");
- return false;
- }
- if (!reader.IsDoneReading()) {
- RaiseError(QUIC_HTTP_FRAME_ERROR, "Superfluous data in GOAWAY frame.");
- return false;
- }
- continue_processing = visitor_->OnGoAwayFrame(frame);
+ // 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::MAX_PUSH_ID): {
- QuicDataReader reader(buffer_.data(), current_frame_length_);
- MaxPushIdFrame frame;
- if (!reader.ReadVarInt62(&frame.push_id)) {
- RaiseError(QUIC_HTTP_FRAME_ERROR,
- "Unable to read MAX_PUSH_ID push_id.");
- return false;
- }
- if (!reader.IsDoneReading()) {
- RaiseError(QUIC_HTTP_FRAME_ERROR,
- "Superfluous data in MAX_PUSH_ID frame.");
- return false;
- }
- continue_processing = visitor_->OnMaxPushIdFrame(frame);
+ // 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): {
- // TODO(bnc): Avoid buffering if the entire frame is present, and
- // instead parse directly out of |reader|.
- PriorityUpdateFrame frame;
- QuicDataReader reader(buffer_.data(), current_frame_length_);
- if (!ParsePriorityUpdateFrame(&reader, &frame)) {
- return false;
- }
- continue_processing = visitor_->OnPriorityUpdateFrame(frame);
+ // 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): {
- // TODO(bnc): Avoid buffering if the entire frame is present, and
- // instead parse directly out of |reader|.
- PriorityUpdateFrame frame;
- QuicDataReader reader(buffer_.data(), current_frame_length_);
- if (!ParseNewPriorityUpdateFrame(&reader, &frame)) {
- return false;
- }
- continue_processing = visitor_->OnPriorityUpdateFrame(frame);
+ // 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::ACCEPT_CH): {
- if (GetQuicReloadableFlag(quic_parse_accept_ch_frame)) {
- // TODO(bnc): Avoid buffering if the entire frame is present, and
- // instead parse directly out of |reader|.
- AcceptChFrame frame;
- QuicDataReader reader(buffer_.data(), current_frame_length_);
- if (!ParseAcceptChFrame(&reader, &frame)) {
- return false;
- }
- continue_processing = visitor_->OnAcceptChFrame(frame);
- } else {
- continue_processing = visitor_->OnUnknownFrameEnd();
- }
+ // If frame payload is not empty, FinishParsing() is skipped.
+ QUICHE_DCHECK_EQ(0u, current_frame_length_);
+ continue_processing = BufferOrParsePayload(reader);
break;
}
default:
@@ -548,18 +508,129 @@ void HttpDecoder::DiscardFramePayload(QuicDataReader* reader) {
}
}
-void HttpDecoder::BufferFramePayload(QuicDataReader* reader) {
- if (current_frame_length_ == remaining_frame_length_) {
- buffer_.erase(buffer_.size());
- buffer_.reserve(current_frame_length_);
+bool HttpDecoder::BufferOrParsePayload(QuicDataReader* reader) {
+ QUICHE_DCHECK_EQ(current_frame_length_,
+ buffer_.size() + remaining_frame_length_);
+
+ bool continue_processing = true;
+
+ if (buffer_.empty() && reader->BytesRemaining() >= current_frame_length_) {
+ // |*reader| contains entire payload, which might be empty.
+ remaining_frame_length_ = 0;
+ QuicDataReader current_payload_reader(reader->PeekRemainingPayload().data(),
+ current_frame_length_);
+ continue_processing = ParseEntirePayload(&current_payload_reader);
+ reader->Seek(current_frame_length_);
+ } else {
+ if (buffer_.empty()) {
+ buffer_.reserve(current_frame_length_);
+ }
+
+ // Buffer as much of the payload as |*reader| contains.
+ QuicByteCount bytes_to_read = std::min<QuicByteCount>(
+ remaining_frame_length_, reader->BytesRemaining());
+ absl::StrAppend(&buffer_, reader->PeekRemainingPayload().substr(
+ /* pos = */ 0, bytes_to_read));
+ reader->Seek(bytes_to_read);
+ remaining_frame_length_ -= bytes_to_read;
+
+ QUICHE_DCHECK_EQ(current_frame_length_,
+ buffer_.size() + remaining_frame_length_);
+
+ if (remaining_frame_length_ > 0) {
+ QUICHE_DCHECK(reader->IsDoneReading());
+ return true;
+ }
+
+ QuicDataReader buffer_reader(buffer_);
+ continue_processing = ParseEntirePayload(&buffer_reader);
+ buffer_.clear();
+ }
+
+ current_length_field_length_ = 0;
+ current_type_field_length_ = 0;
+ state_ = STATE_READING_FRAME_TYPE;
+ return continue_processing;
+}
+
+bool HttpDecoder::ParseEntirePayload(QuicDataReader* reader) {
+ QUICHE_DCHECK_EQ(current_frame_length_, reader->BytesRemaining());
+ QUICHE_DCHECK_EQ(0u, remaining_frame_length_);
+
+ switch (current_frame_type_) {
+ case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): {
+ CancelPushFrame frame;
+ if (!reader->ReadVarInt62(&frame.push_id)) {
+ RaiseError(QUIC_HTTP_FRAME_ERROR,
+ "Unable to read CANCEL_PUSH push_id.");
+ return false;
+ }
+ if (!reader->IsDoneReading()) {
+ RaiseError(QUIC_HTTP_FRAME_ERROR,
+ "Superfluous data in CANCEL_PUSH frame.");
+ return false;
+ }
+ return visitor_->OnCancelPushFrame(frame);
+ }
+ case static_cast<uint64_t>(HttpFrameType::SETTINGS): {
+ SettingsFrame frame;
+ if (!ParseSettingsFrame(reader, &frame)) {
+ return false;
+ }
+ return visitor_->OnSettingsFrame(frame);
+ }
+ case static_cast<uint64_t>(HttpFrameType::GOAWAY): {
+ GoAwayFrame frame;
+ if (!reader->ReadVarInt62(&frame.id)) {
+ RaiseError(QUIC_HTTP_FRAME_ERROR, "Unable to read GOAWAY ID.");
+ return false;
+ }
+ if (!reader->IsDoneReading()) {
+ RaiseError(QUIC_HTTP_FRAME_ERROR, "Superfluous data in GOAWAY frame.");
+ return false;
+ }
+ return visitor_->OnGoAwayFrame(frame);
+ }
+ case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID): {
+ MaxPushIdFrame frame;
+ if (!reader->ReadVarInt62(&frame.push_id)) {
+ RaiseError(QUIC_HTTP_FRAME_ERROR,
+ "Unable to read MAX_PUSH_ID push_id.");
+ return false;
+ }
+ if (!reader->IsDoneReading()) {
+ RaiseError(QUIC_HTTP_FRAME_ERROR,
+ "Superfluous data in MAX_PUSH_ID frame.");
+ return false;
+ }
+ return visitor_->OnMaxPushIdFrame(frame);
+ }
+ case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE): {
+ PriorityUpdateFrame frame;
+ if (!ParsePriorityUpdateFrame(reader, &frame)) {
+ return false;
+ }
+ return visitor_->OnPriorityUpdateFrame(frame);
+ }
+ case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE_REQUEST_STREAM): {
+ PriorityUpdateFrame frame;
+ if (!ParseNewPriorityUpdateFrame(reader, &frame)) {
+ return false;
+ }
+ return visitor_->OnPriorityUpdateFrame(frame);
+ }
+ case static_cast<uint64_t>(HttpFrameType::ACCEPT_CH): {
+ AcceptChFrame frame;
+ if (!ParseAcceptChFrame(reader, &frame)) {
+ return false;
+ }
+ return visitor_->OnAcceptChFrame(frame);
+ }
+ default:
+ // Only above frame types are parsed by ParseEntirePayload().
+ QUICHE_NOTREACHED();
+ return false;
}
- QuicByteCount bytes_to_read = std::min<QuicByteCount>(
- remaining_frame_length_, reader->BytesRemaining());
- bool success = reader->ReadBytes(
- &(buffer_[0]) + current_frame_length_ - remaining_frame_length_,
- bytes_to_read);
- QUICHE_DCHECK(success);
- remaining_frame_length_ -= bytes_to_read;
}
void HttpDecoder::BufferFrameLength(QuicDataReader* reader) {
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 fe955c32bf8..a351415e964 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
@@ -27,6 +27,11 @@ class QuicDataReader;
// session.
class QUIC_EXPORT_PRIVATE HttpDecoder {
public:
+ struct QUIC_EXPORT_PRIVATE Options {
+ // Indicates that WEBTRANSPORT_STREAM should be parsed.
+ bool allow_web_transport_stream = false;
+ };
+
class QUIC_EXPORT_PRIVATE Visitor {
public:
virtual ~Visitor() {}
@@ -109,6 +114,15 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// Called when an ACCEPT_CH frame has been successfully parsed.
virtual bool OnAcceptChFrame(const AcceptChFrame& frame) = 0;
+ // Called when a WEBTRANSPORT_STREAM frame type and the session ID varint
+ // immediately following it has been received. Any further parsing should
+ // be done by the stream itself, and not the parser. Note that this does not
+ // return bool, because WEBTRANSPORT_STREAM always causes the parsing
+ // process to cease.
+ virtual void OnWebTransportStreamFrameType(
+ QuicByteCount header_length,
+ WebTransportSessionId session_id) = 0;
+
// Called when a frame of unknown type |frame_type| has been received.
// Frame type might be reserved, Visitor must make sure to ignore.
// |header_length| and |payload_length| are the length of the frame header
@@ -126,6 +140,7 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// |visitor| must be non-null, and must outlive HttpDecoder.
explicit HttpDecoder(Visitor* visitor);
+ explicit HttpDecoder(Visitor* visitor, Options options);
~HttpDecoder();
@@ -162,6 +177,7 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
STATE_READING_FRAME_TYPE,
STATE_READING_FRAME_PAYLOAD,
STATE_FINISH_PARSING,
+ STATE_PARSING_NO_LONGER_POSSIBLE,
STATE_ERROR
};
@@ -175,14 +191,17 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// if there are any errors. Returns whether processing should continue.
bool ReadFrameLength(QuicDataReader* reader);
- // Reads the payload of the current frame from |reader| and processes it,
- // possibly buffering the data or invoking the visitor. Returns whether
- // processing should continue.
+ // Depending on the frame type, reads and processes the payload of the current
+ // frame from |reader| and calls visitor methods, or calls
+ // BufferOrParsePayload(). Returns whether processing should continue.
bool ReadFramePayload(QuicDataReader* reader);
- // Optionally parses buffered data; calls visitor method to signal that frame
- // had been parsed completely. Returns whether processing should continue.
- bool FinishParsing();
+ // For frame types parsed by BufferOrParsePayload(), this method is only
+ // called if frame payload is empty, at it calls BufferOrParsePayload(). For
+ // other frame types, this method directly calls visitor methods to signal
+ // that frame had been parsed completely. Returns whether processing should
+ // continue.
+ bool FinishParsing(QuicDataReader* reader);
// Read payload of unknown frame from |reader| and call
// Visitor::OnUnknownFramePayload(). Returns true decoding should continue,
@@ -192,8 +211,16 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// Discards any remaining frame payload from |reader|.
void DiscardFramePayload(QuicDataReader* reader);
- // Buffers any remaining frame payload from |reader| into |buffer_|.
- void BufferFramePayload(QuicDataReader* reader);
+ // Buffers any remaining frame payload from |*reader| into |buffer_| if
+ // necessary. Parses the frame payload if complete. Parses out of |*reader|
+ // without unnecessary copy if |*reader| has entire payload.
+ // Returns whether processing should continue.
+ bool BufferOrParsePayload(QuicDataReader* reader);
+
+ // Parses the entire payload of certain kinds of frames that are parsed in a
+ // single pass. |reader| must have at least |current_frame_length_| bytes.
+ // Returns whether processing should continue.
+ bool ParseEntirePayload(QuicDataReader* reader);
// Buffers any remaining frame length field from |reader| into
// |length_buffer_|.
@@ -230,6 +257,8 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// Visitor to invoke when messages are parsed.
Visitor* const visitor_; // Unowned.
+ // Whether WEBTRANSPORT_STREAM should be parsed.
+ bool allow_web_transport_stream_;
// Current state of the parsing.
HttpDecoderState state_;
// Type of the frame currently being parsed.
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 1be5084f77d..aac020a97a7 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
@@ -15,6 +15,7 @@
#include "quic/core/http/http_frames.h"
#include "quic/core/quic_data_writer.h"
#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_test.h"
#include "quic/test_tools/quic_test_utils.h"
@@ -109,6 +110,10 @@ class MockVisitor : public HttpDecoder::Visitor {
(QuicByteCount header_length),
(override));
MOCK_METHOD(bool, OnAcceptChFrame, (const AcceptChFrame& frame), (override));
+ MOCK_METHOD(void,
+ OnWebTransportStreamFrameType,
+ (QuicByteCount header_length, WebTransportSessionId session_id),
+ (override));
MOCK_METHOD(bool,
OnUnknownFrameStart,
@@ -867,11 +872,43 @@ TEST_F(HttpDecoderTest, CorruptFrame) {
"\x04" // length
"\x05" // valid stream id
"foo", // superfluous data
- "Superfluous data in GOAWAY frame."}};
+ "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);
@@ -881,6 +918,7 @@ TEST_F(HttpDecoderTest, CorruptFrame) {
}
{
HttpDecoder decoder(&visitor_);
+ EXPECT_CALL(visitor_, OnAcceptChFrameStart(_)).Times(AnyNumber());
EXPECT_CALL(visitor_, OnError(&decoder));
absl::string_view input(test_data.input);
@@ -1194,10 +1232,6 @@ TEST_F(HttpDecoderTest, CorruptNewPriorityUpdateFrame) {
}
TEST_F(HttpDecoderTest, AcceptChFrame) {
- if (!GetQuicReloadableFlag(quic_parse_accept_ch_frame)) {
- return;
- }
-
InSequence s;
std::string input1 = absl::HexStringToBytes(
"4089" // type (ACCEPT_CH)
@@ -1272,72 +1306,41 @@ TEST_F(HttpDecoderTest, AcceptChFrame) {
EXPECT_EQ("", decoder_.error_detail());
}
-TEST_F(HttpDecoderTest, CorruptAcceptChFrame) {
- if (!GetQuicReloadableFlag(quic_parse_accept_ch_frame)) {
- // TODO(bnc): merge this test into HttpDecoderTest.CorruptFrame when
- // deprecating flag.
- return;
- }
+TEST_F(HttpDecoderTest, WebTransportStreamDisabled) {
+ InSequence s;
- EXPECT_CALL(visitor_, OnAcceptChFrameStart(_)).Times(AnyNumber());
+ // Unknown frame of type 0x41 and length 0x104.
+ std::string input = absl::HexStringToBytes("40414104");
+ EXPECT_CALL(visitor_, OnUnknownFrameStart(0x41, input.size(), 0x104));
+ EXPECT_EQ(ProcessInput(input), input.size());
+}
- struct {
- const char* const input;
- const char* const error_message;
- } kTestData[] = {{"\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."}};
+TEST(HttpDecoderTestNoFixture, WebTransportStream) {
+ HttpDecoder::Options options;
+ options.allow_web_transport_stream = true;
+ testing::StrictMock<MockVisitor> visitor;
+ HttpDecoder decoder(&visitor, options);
+
+ // WebTransport stream for session ID 0x104, with four bytes of extra data.
+ std::string input = absl::HexStringToBytes("40414104ffffffff");
+ EXPECT_CALL(visitor, OnWebTransportStreamFrameType(4, 0x104));
+ QuicByteCount bytes = decoder.ProcessInput(input.data(), input.size());
+ EXPECT_EQ(bytes, 4u);
+}
- for (const auto& test_data : kTestData) {
- {
- HttpDecoder decoder(&visitor_);
- EXPECT_CALL(visitor_, OnError(&decoder));
+TEST(HttpDecoderTestNoFixture, WebTransportStreamError) {
+ HttpDecoder::Options options;
+ options.allow_web_transport_stream = true;
+ testing::StrictMock<MockVisitor> visitor;
+ HttpDecoder decoder(&visitor, options);
- 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_, OnError(&decoder));
+ std::string input = absl::HexStringToBytes("404100");
+ EXPECT_CALL(visitor, OnWebTransportStreamFrameType(_, _));
+ decoder.ProcessInput(input.data(), input.size());
- 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_CALL(visitor, OnError(_));
+ EXPECT_QUIC_BUG(decoder.ProcessInput(input.data(), input.size()),
+ "HttpDecoder called after an indefinite-length frame");
}
TEST_F(HttpDecoderTest, DecodeSettings) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.cc b/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.cc
index fafe3b83d08..2fbc2380cf7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.cc
@@ -76,27 +76,6 @@ QuicByteCount HttpEncoder::SerializeHeadersFrameHeader(
}
// static
-QuicByteCount HttpEncoder::SerializeCancelPushFrame(
- const CancelPushFrame& cancel_push,
- std::unique_ptr<char[]>* output) {
- QuicByteCount payload_length =
- QuicDataWriter::GetVarInt62Len(cancel_push.push_id);
- QuicByteCount total_length =
- GetTotalLength(payload_length, HttpFrameType::CANCEL_PUSH);
-
- output->reset(new char[total_length]);
- QuicDataWriter writer(total_length, output->get());
-
- if (WriteFrameHeader(payload_length, HttpFrameType::CANCEL_PUSH, &writer) &&
- writer.WriteVarInt62(cancel_push.push_id)) {
- return total_length;
- }
- QUIC_DLOG(ERROR)
- << "Http encoder failed when attempting to serialize cancel push frame.";
- return 0;
-}
-
-// static
QuicByteCount HttpEncoder::SerializeSettingsFrame(
const SettingsFrame& settings,
std::unique_ptr<char[]>* output) {
@@ -134,32 +113,6 @@ QuicByteCount HttpEncoder::SerializeSettingsFrame(
}
// static
-QuicByteCount HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
- const PushPromiseFrame& push_promise,
- std::unique_ptr<char[]>* output) {
- QuicByteCount payload_length =
- QuicDataWriter::GetVarInt62Len(push_promise.push_id) +
- push_promise.headers.length();
- // GetTotalLength() is not used because headers will not be serialized.
- QuicByteCount total_length =
- QuicDataWriter::GetVarInt62Len(payload_length) +
- QuicDataWriter::GetVarInt62Len(
- static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE)) +
- QuicDataWriter::GetVarInt62Len(push_promise.push_id);
-
- output->reset(new char[total_length]);
- QuicDataWriter writer(total_length, output->get());
-
- if (WriteFrameHeader(payload_length, HttpFrameType::PUSH_PROMISE, &writer) &&
- writer.WriteVarInt62(push_promise.push_id)) {
- return total_length;
- }
- QUIC_DLOG(ERROR)
- << "Http encoder failed when attempting to serialize push promise frame.";
- return 0;
-}
-
-// static
QuicByteCount HttpEncoder::SerializeGoAwayFrame(
const GoAwayFrame& goaway,
std::unique_ptr<char[]>* output) {
@@ -180,32 +133,12 @@ QuicByteCount HttpEncoder::SerializeGoAwayFrame(
}
// static
-QuicByteCount HttpEncoder::SerializeMaxPushIdFrame(
- const MaxPushIdFrame& max_push_id,
- std::unique_ptr<char[]>* output) {
- QuicByteCount payload_length =
- QuicDataWriter::GetVarInt62Len(max_push_id.push_id);
- QuicByteCount total_length =
- GetTotalLength(payload_length, HttpFrameType::MAX_PUSH_ID);
-
- output->reset(new char[total_length]);
- QuicDataWriter writer(total_length, output->get());
-
- if (WriteFrameHeader(payload_length, HttpFrameType::MAX_PUSH_ID, &writer) &&
- writer.WriteVarInt62(max_push_id.push_id)) {
- return total_length;
- }
- QUIC_DLOG(ERROR)
- << "Http encoder failed when attempting to serialize max push id frame.";
- return 0;
-}
-
-// static
QuicByteCount HttpEncoder::SerializePriorityUpdateFrame(
const PriorityUpdateFrame& priority_update,
std::unique_ptr<char[]>* output) {
if (priority_update.prioritized_element_type != REQUEST_STREAM) {
- QUIC_BUG << "PRIORITY_UPDATE for push streams not implemented";
+ QUIC_BUG(quic_bug_10402_1)
+ << "PRIORITY_UPDATE for push streams not implemented";
return 0;
}
@@ -315,4 +248,25 @@ QuicByteCount HttpEncoder::SerializeGreasingFrame(
return 0;
}
+QuicByteCount HttpEncoder::SerializeWebTransportStreamFrameHeader(
+ WebTransportSessionId session_id,
+ std::unique_ptr<char[]>* output) {
+ uint64_t stream_type =
+ static_cast<uint64_t>(HttpFrameType::WEBTRANSPORT_STREAM);
+ QuicByteCount header_length = QuicDataWriter::GetVarInt62Len(stream_type) +
+ QuicDataWriter::GetVarInt62Len(session_id);
+
+ *output = std::make_unique<char[]>(header_length);
+ QuicDataWriter writer(header_length, output->get());
+ bool success =
+ writer.WriteVarInt62(stream_type) && writer.WriteVarInt62(session_id);
+ if (success && writer.remaining() == 0) {
+ return header_length;
+ }
+
+ QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
+ "WEBTRANSPORT_STREAM frame header.";
+ return 0;
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.h b/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.h
index 429502b0cbb..0a8aa84e0b7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.h
@@ -8,6 +8,7 @@
#include <memory>
#include "quic/core/http/http_frames.h"
#include "quic/core/quic_error_codes.h"
+#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_export.h"
namespace quic {
@@ -32,35 +33,16 @@ class QUIC_EXPORT_PRIVATE HttpEncoder {
QuicByteCount payload_length,
std::unique_ptr<char[]>* output);
- // Serializes a CANCEL_PUSH frame into a new buffer stored in |output|.
- // Returns the length of the buffer on success, or 0 otherwise.
- static QuicByteCount SerializeCancelPushFrame(
- const CancelPushFrame& cancel_push,
- std::unique_ptr<char[]>* output);
-
// Serializes a SETTINGS frame into a new buffer stored in |output|.
// Returns the length of the buffer on success, or 0 otherwise.
static QuicByteCount SerializeSettingsFrame(const SettingsFrame& settings,
std::unique_ptr<char[]>* output);
- // Serializes the header and push_id of a PUSH_PROMISE frame into a new buffer
- // stored in |output|. Returns the length of the buffer on success, or 0
- // otherwise.
- static QuicByteCount SerializePushPromiseFrameWithOnlyPushId(
- const PushPromiseFrame& push_promise,
- std::unique_ptr<char[]>* output);
-
// Serializes a GOAWAY frame into a new buffer stored in |output|.
// Returns the length of the buffer on success, or 0 otherwise.
static QuicByteCount SerializeGoAwayFrame(const GoAwayFrame& goaway,
std::unique_ptr<char[]>* output);
- // Serializes a MAX_PUSH frame into a new buffer stored in |output|.
- // Returns the length of the buffer on success, or 0 otherwise.
- static QuicByteCount SerializeMaxPushIdFrame(
- const MaxPushIdFrame& max_push_id,
- std::unique_ptr<char[]>* output);
-
// Serializes a PRIORITY_UPDATE frame into a new buffer stored in |output|.
// Returns the length of the buffer on success, or 0 otherwise.
static QuicByteCount SerializePriorityUpdateFrame(
@@ -75,6 +57,12 @@ class QUIC_EXPORT_PRIVATE HttpEncoder {
// Serializes a frame with reserved frame type specified in
// https://tools.ietf.org/html/draft-ietf-quic-http-25#section-7.2.9.
static QuicByteCount SerializeGreasingFrame(std::unique_ptr<char[]>* output);
+
+ // Serializes a WEBTRANSPORT_STREAM frame header as specified in
+ // https://www.ietf.org/archive/id/draft-ietf-webtrans-http3-00.html#name-client-initiated-bidirectio
+ static QuicByteCount SerializeWebTransportStreamFrameHeader(
+ WebTransportSessionId session_id,
+ std::unique_ptr<char[]>* output);
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_encoder_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/http_encoder_test.cc
index ad25cc40dd5..66e988facca 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_encoder_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_encoder_test.cc
@@ -39,22 +39,6 @@ TEST(HttpEncoderTest, SerializeHeadersFrameHeader) {
output, ABSL_ARRAYSIZE(output));
}
-TEST(HttpEncoderTest, SerializeCancelPushFrame) {
- CancelPushFrame cancel_push;
- cancel_push.push_id = 0x01;
- char output[] = {// type (CANCEL_PUSH)
- 0x03,
- // length
- 0x1,
- // Push Id
- 0x01};
- std::unique_ptr<char[]> buffer;
- uint64_t length = HttpEncoder::SerializeCancelPushFrame(cancel_push, &buffer);
- EXPECT_EQ(ABSL_ARRAYSIZE(output), length);
- quiche::test::CompareCharArraysWithHexError(
- "CANCEL_PUSH", buffer.get(), length, output, ABSL_ARRAYSIZE(output));
-}
-
TEST(HttpEncoderTest, SerializeSettingsFrame) {
SettingsFrame settings;
settings.values[1] = 2;
@@ -83,24 +67,6 @@ TEST(HttpEncoderTest, SerializeSettingsFrame) {
output, ABSL_ARRAYSIZE(output));
}
-TEST(HttpEncoderTest, SerializePushPromiseFrameWithOnlyPushId) {
- PushPromiseFrame push_promise;
- push_promise.push_id = 0x01;
- push_promise.headers = "Headers";
- char output[] = {// type (PUSH_PROMISE)
- 0x05,
- // length
- 0x8,
- // Push Id
- 0x01};
- std::unique_ptr<char[]> buffer;
- uint64_t length = HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
- push_promise, &buffer);
- EXPECT_EQ(ABSL_ARRAYSIZE(output), length);
- quiche::test::CompareCharArraysWithHexError(
- "PUSH_PROMISE", buffer.get(), length, output, ABSL_ARRAYSIZE(output));
-}
-
TEST(HttpEncoderTest, SerializeGoAwayFrame) {
GoAwayFrame goaway;
goaway.id = 0x1;
@@ -117,22 +83,6 @@ TEST(HttpEncoderTest, SerializeGoAwayFrame) {
output, ABSL_ARRAYSIZE(output));
}
-TEST(HttpEncoderTest, SerializeMaxPushIdFrame) {
- MaxPushIdFrame max_push_id;
- max_push_id.push_id = 0x1;
- char output[] = {// type (MAX_PUSH_ID)
- 0x0D,
- // length
- 0x1,
- // Push Id
- 0x01};
- std::unique_ptr<char[]> buffer;
- uint64_t length = HttpEncoder::SerializeMaxPushIdFrame(max_push_id, &buffer);
- EXPECT_EQ(ABSL_ARRAYSIZE(output), length);
- quiche::test::CompareCharArraysWithHexError(
- "MAX_PUSH_ID", buffer.get(), length, output, ABSL_ARRAYSIZE(output));
-}
-
TEST(HttpEncoderTest, SerializePriorityUpdateFrame) {
PriorityUpdateFrame priority_update1;
priority_update1.prioritized_element_type = REQUEST_STREAM;
@@ -173,5 +123,18 @@ TEST(HttpEncoderTest, SerializeAcceptChFrame) {
output2, ABSL_ARRAYSIZE(output2));
}
+TEST(HttpEncoderTest, SerializeWebTransportStreamFrameHeader) {
+ WebTransportSessionId session_id = 0x17;
+ char output[] = {0x40, 0x41, // type (WEBTRANSPORT_STREAM)
+ 0x17}; // session ID
+
+ std::unique_ptr<char[]> buffer;
+ uint64_t length =
+ HttpEncoder::SerializeWebTransportStreamFrameHeader(session_id, &buffer);
+ EXPECT_EQ(sizeof(output), length);
+ quiche::test::CompareCharArraysWithHexError(
+ "WEBTRANSPORT_STREAM", buffer.get(), length, output, sizeof(output));
+}
+
} // namespace test
} // namespace quic
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 34c3d607c0e..56e53487b24 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
@@ -16,6 +16,7 @@
#include "absl/strings/string_view.h"
#include "quic/core/http/http_constants.h"
#include "quic/core/quic_types.h"
+#include "spdy/core/spdy_protocol.h"
namespace quic {
@@ -33,6 +34,8 @@ enum class HttpFrameType {
ACCEPT_CH = 0x89,
// https://tools.ietf.org/html/draft-ietf-httpbis-priority-02
PRIORITY_UPDATE_REQUEST_STREAM = 0xF0700,
+ // https://www.ietf.org/archive/id/draft-ietf-webtrans-http3-00.html
+ WEBTRANSPORT_STREAM = 0x41,
};
// 7.2.1. DATA
@@ -102,6 +105,7 @@ struct QUIC_EXPORT_PRIVATE SettingsFrame {
//
// The PUSH_PROMISE frame (type=0x05) is used to carry a request header
// set from server to client, as in HTTP/2.
+// TODO(b/171463363): Remove.
struct QUIC_EXPORT_PRIVATE PushPromiseFrame {
PushId push_id;
absl::string_view headers;
@@ -182,15 +186,7 @@ struct QUIC_EXPORT_PRIVATE PriorityUpdateFrame {
// https://tools.ietf.org/html/draft-davidben-http-client-hint-reliability-02
//
struct QUIC_EXPORT_PRIVATE AcceptChFrame {
- struct QUIC_EXPORT_PRIVATE OriginValuePair {
- std::string origin;
- std::string value;
- bool operator==(const OriginValuePair& rhs) const {
- return origin == rhs.origin && value == rhs.value;
- }
- };
-
- std::vector<OriginValuePair> entries;
+ std::vector<spdy::AcceptChOriginValuePair> entries;
bool operator==(const AcceptChFrame& rhs) const {
return entries.size() == rhs.entries.size() &&
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info.cc
index a32a6a8dbc9..36011804056 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info.cc
@@ -98,7 +98,7 @@ QuicAsyncStatus QuicClientPromisedInfo::FinalValidation() {
// This shouldn't be possible, as |ClientRequest| guards against
// closed stream for the synchronous case. And in the
// asynchronous case, a RST can only be caught by |OnAlarm()|.
- QUIC_BUG << "missing promised stream" << id_;
+ QUIC_BUG(quic_bug_10378_1) << "missing promised stream" << id_;
}
QuicClientPushPromiseIndex::Delegate* delegate = client_request_delegate_;
session_->DeletePromised(this);
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_header_list.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_header_list.cc
index f7f656754e5..7ac768dcc05 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_header_list.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_header_list.cc
@@ -32,7 +32,7 @@ QuicHeaderList& QuicHeaderList::operator=(QuicHeaderList&& other) = default;
QuicHeaderList::~QuicHeaderList() {}
void QuicHeaderList::OnHeaderBlockStart() {
- QUIC_BUG_IF(current_header_list_size_ != 0)
+ QUIC_BUG_IF(quic_bug_12518_1, current_header_list_size_ != 0)
<< "OnHeaderBlockStart called more than once!";
}
@@ -42,7 +42,7 @@ void QuicHeaderList::OnHeader(absl::string_view name, absl::string_view value) {
if (current_header_list_size_ < max_header_list_size_) {
current_header_list_size_ += name.size();
current_header_list_size_ += value.size();
- current_header_list_size_ += QpackEntry::kSizeOverhead;
+ current_header_list_size_ += kQpackEntrySizeOverhead;
header_list_.emplace_back(std::string(name), std::string(value));
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream.cc
index d8cfbdf3ba8..2b9f485a436 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream.cc
@@ -84,8 +84,9 @@ bool QuicHeadersStream::OnStreamFrameAcked(QuicStreamOffset offset,
std::min(acked_length, header.full_length - header_offset);
if (header.unacked_length < header_length) {
- QUIC_BUG << "Unsent stream data is acked. unacked_length: "
- << header.unacked_length << " acked_length: " << header_length;
+ QUIC_BUG(quic_bug_10416_1)
+ << "Unsent stream data is acked. unacked_length: "
+ << header.unacked_length << " acked_length: " << header_length;
OnUnrecoverableError(QUIC_INTERNAL_ERROR,
"Unsent stream data is acked");
return false;
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 cfccc922688..55dafac3756 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
@@ -73,17 +73,6 @@ using testing::WithArgs;
namespace quic {
namespace test {
-
-class MockQuicHpackDebugVisitor : public QuicHpackDebugVisitor {
- public:
- MockQuicHpackDebugVisitor() : QuicHpackDebugVisitor() {}
- MockQuicHpackDebugVisitor(const MockQuicHpackDebugVisitor&) = delete;
- MockQuicHpackDebugVisitor& operator=(const MockQuicHpackDebugVisitor&) =
- delete;
-
- MOCK_METHOD(void, OnUseEntry, (QuicTime::Delta elapsed), (override));
-};
-
namespace {
class MockVisitor : public SpdyFramerVisitorInterface {
@@ -766,95 +755,6 @@ TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) {
headers_stream_));
}
-TEST_P(QuicHeadersStreamTest, HpackDecoderDebugVisitor) {
- auto hpack_decoder_visitor =
- std::make_unique<StrictMock<MockQuicHpackDebugVisitor>>();
- {
- InSequence seq;
- // Number of indexed representations generated in headers below.
- for (int i = 1; i < 28; i++) {
- EXPECT_CALL(*hpack_decoder_visitor,
- OnUseEntry(QuicTime::Delta::FromMilliseconds(i)))
- .Times(4);
- }
- }
- QuicSpdySessionPeer::SetHpackDecoderDebugVisitor(
- &session_, std::move(hpack_decoder_visitor));
-
- // Create some headers we expect to generate entries in HPACK's
- // dynamic table, in addition to content-length.
- headers_["key0"] = std::string(1 << 1, '.');
- headers_["key1"] = std::string(1 << 2, '.');
- headers_["key2"] = std::string(1 << 3, '.');
- for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
- stream_id += next_stream_id_) {
- for (bool fin : {false, true}) {
- for (SpdyPriority priority = 0; priority < 7; ++priority) {
- // Replace with "WriteHeadersAndSaveData"
- SpdySerializedFrame frame;
- if (perspective() == Perspective::IS_SERVER) {
- SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
- headers_frame.set_fin(fin);
- headers_frame.set_has_priority(true);
- headers_frame.set_weight(Spdy3PriorityToHttp2Weight(0));
- frame = framer_->SerializeFrame(headers_frame);
- EXPECT_CALL(session_, OnStreamHeadersPriority(
- stream_id, spdy::SpdyStreamPrecedence(0)));
- } else {
- SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
- headers_frame.set_fin(fin);
- frame = framer_->SerializeFrame(headers_frame);
- }
- EXPECT_CALL(session_,
- OnStreamHeaderList(stream_id, fin, frame.size(), _))
- .WillOnce(Invoke(this, &QuicHeadersStreamTest::SaveHeaderList));
- stream_frame_.data_buffer = frame.data();
- stream_frame_.data_length = frame.size();
- connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
- headers_stream_->OnStreamFrame(stream_frame_);
- stream_frame_.offset += frame.size();
- CheckHeaders();
- }
- }
- }
-}
-
-TEST_P(QuicHeadersStreamTest, HpackEncoderDebugVisitor) {
- auto hpack_encoder_visitor =
- std::make_unique<StrictMock<MockQuicHpackDebugVisitor>>();
- if (perspective() == Perspective::IS_SERVER) {
- InSequence seq;
- for (int i = 1; i < 4; i++) {
- EXPECT_CALL(*hpack_encoder_visitor,
- OnUseEntry(QuicTime::Delta::FromMilliseconds(i)));
- }
- } else {
- InSequence seq;
- for (int i = 1; i < 28; i++) {
- EXPECT_CALL(*hpack_encoder_visitor,
- OnUseEntry(QuicTime::Delta::FromMilliseconds(i)));
- }
- }
- QuicSpdySessionPeer::SetHpackEncoderDebugVisitor(
- &session_, std::move(hpack_encoder_visitor));
-
- for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
- stream_id += next_stream_id_) {
- for (bool fin : {false, true}) {
- if (perspective() == Perspective::IS_SERVER) {
- WriteAndExpectResponseHeaders(stream_id, fin);
- connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
- } else {
- for (SpdyPriority priority = 0; priority < 7; ++priority) {
- // TODO(rch): implement priorities correctly.
- WriteAndExpectRequestHeaders(stream_id, fin, 0);
- connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
- }
- }
- }
- }
-}
-
TEST_P(QuicHeadersStreamTest, AckSentData) {
EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId(
connection_->transport_version()),
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 35d590286cb..fbd7b2eb18e 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
@@ -233,6 +233,13 @@ bool QuicReceiveControlStream::OnAcceptChFrame(const AcceptChFrame& frame) {
return true;
}
+void QuicReceiveControlStream::OnWebTransportStreamFrameType(
+ QuicByteCount /*header_length*/,
+ WebTransportSessionId /*session_id*/) {
+ QUIC_BUG(WEBTRANSPORT_STREAM on Control Stream)
+ << "Parsed WEBTRANSPORT_STREAM on a control stream.";
+}
+
bool QuicReceiveControlStream::OnUnknownFrameStart(
uint64_t frame_type,
QuicByteCount /*header_length*/,
@@ -263,8 +270,7 @@ bool QuicReceiveControlStream::ValidateFrameType(HttpFrameType frame_type) {
frame_type == HttpFrameType::PUSH_PROMISE) ||
(spdy_session()->perspective() == Perspective::IS_CLIENT &&
frame_type == HttpFrameType::MAX_PUSH_ID) ||
- (GetQuicReloadableFlag(quic_parse_accept_ch_frame) &&
- spdy_session()->perspective() == Perspective::IS_SERVER &&
+ (spdy_session()->perspective() == Perspective::IS_SERVER &&
frame_type == HttpFrameType::ACCEPT_CH)) {
stream_delegate()->OnStreamError(
QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM,
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h
index 326dba3e38a..4ed01043662 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h
@@ -58,14 +58,14 @@ class QUIC_EXPORT_PRIVATE QuicReceiveControlStream
bool OnPriorityUpdateFrame(const PriorityUpdateFrame& frame) override;
bool OnAcceptChFrameStart(QuicByteCount header_length) override;
bool OnAcceptChFrame(const AcceptChFrame& frame) override;
+ void OnWebTransportStreamFrameType(QuicByteCount header_length,
+ WebTransportSessionId session_id) override;
bool OnUnknownFrameStart(uint64_t frame_type,
QuicByteCount header_length,
QuicByteCount payload_length) override;
bool OnUnknownFramePayload(absl::string_view payload) override;
bool OnUnknownFrameEnd() override;
- void SetUnblocked() { sequencer()->SetUnblocked(); }
-
QuicSpdySession* spdy_session() { return spdy_session_; }
private:
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 3e4532f4a66..c9133436e9f 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
@@ -4,13 +4,13 @@
#include "quic/core/http/quic_receive_control_stream.h"
+#include "absl/memory/memory.h"
#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "quic/core/http/http_constants.h"
#include "quic/core/qpack/qpack_header_table.h"
#include "quic/core/quic_types.h"
#include "quic/core/quic_utils.h"
-#include "quic/platform/api/quic_ptr_util.h"
#include "quic/test_tools/qpack/qpack_encoder_peer.h"
#include "quic/test_tools/quic_spdy_session_peer.h"
#include "quic/test_tools/quic_stream_peer.h"
@@ -106,7 +106,7 @@ class QuicReceiveControlStreamTest : public QuicTestWithParam<TestParams> {
stream_ = new TestStream(GetNthClientInitiatedBidirectionalStreamId(
GetParam().version.transport_version, 0),
&session_);
- session_.ActivateStream(QuicWrapUnique(stream_));
+ session_.ActivateStream(absl::WrapUnique(stream_));
}
Perspective perspective() const { return GetParam().perspective; }
@@ -303,14 +303,12 @@ TEST_P(QuicReceiveControlStreamTest, ReceiveGoAwayFrame) {
}
TEST_P(QuicReceiveControlStreamTest, PushPromiseOnControlStreamShouldClose) {
- PushPromiseFrame push_promise;
- push_promise.push_id = 0x01;
- push_promise.headers = "Headers";
- std::unique_ptr<char[]> buffer;
- uint64_t length = HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
- push_promise, &buffer);
- QuicStreamFrame frame(receive_control_stream_->id(), false, 1, buffer.get(),
- length);
+ std::string push_promise_frame = absl::HexStringToBytes(
+ "05" // PUSH_PROMISE
+ "01" // length
+ "00"); // push ID
+ QuicStreamFrame frame(receive_control_stream_->id(), false, 1,
+ push_promise_frame);
EXPECT_CALL(
*connection_,
CloseConnection(QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM, _, _))
@@ -404,8 +402,7 @@ TEST_P(QuicReceiveControlStreamTest, AcceptChFrameBeforeSettings) {
"4089" // type (ACCEPT_CH)
"00"); // length
- if (GetQuicReloadableFlag(quic_parse_accept_ch_frame) &&
- perspective() == Perspective::IS_SERVER) {
+ if (perspective() == Perspective::IS_SERVER) {
EXPECT_CALL(*connection_,
CloseConnection(
QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM,
@@ -449,23 +446,17 @@ TEST_P(QuicReceiveControlStreamTest, ReceiveAcceptChFrame) {
"4089" // type (ACCEPT_CH)
"00"); // length
- if (GetQuicReloadableFlag(quic_parse_accept_ch_frame)) {
- if (perspective() == Perspective::IS_CLIENT) {
- EXPECT_CALL(debug_visitor, OnAcceptChFrameReceived(_));
- } else {
- EXPECT_CALL(*connection_,
- CloseConnection(
- QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM,
- "Invalid frame type 137 received on control stream.", _))
- .WillOnce(
- Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
- EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
- EXPECT_CALL(session_, OnConnectionClosed(_, _));
- }
+ if (perspective() == Perspective::IS_CLIENT) {
+ EXPECT_CALL(debug_visitor, OnAcceptChFrameReceived(_));
} else {
- EXPECT_CALL(debug_visitor,
- OnUnknownFrameReceived(id, /* frame_type = */ 0x89,
- /* payload_length = */ 0));
+ EXPECT_CALL(*connection_,
+ CloseConnection(
+ QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM,
+ "Invalid frame type 137 received on control stream.", _))
+ .WillOnce(
+ Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
+ EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
+ EXPECT_CALL(session_, OnConnectionClosed(_, _));
}
receive_control_stream_->OnStreamFrame(
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.cc
index 833413039a7..79555e05967 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.cc
@@ -27,7 +27,8 @@ QuicSendControlStream::QuicSendControlStream(QuicStreamId id,
spdy_session_(spdy_session) {}
void QuicSendControlStream::OnStreamReset(const QuicRstStreamFrame& /*frame*/) {
- QUIC_BUG << "OnStreamReset() called for write unidirectional stream.";
+ QUIC_BUG(quic_bug_10382_1)
+ << "OnStreamReset() called for write unidirectional stream.";
}
bool QuicSendControlStream::OnStopSending(QuicRstStreamErrorCode /* code */) {
@@ -103,24 +104,6 @@ void QuicSendControlStream::WritePriorityUpdate(
nullptr);
}
-void QuicSendControlStream::SendMaxPushIdFrame(PushId max_push_id) {
- QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, session()->perspective());
- QuicConnection::ScopedPacketFlusher flusher(session()->connection());
- MaybeSendSettingsFrame();
-
- MaxPushIdFrame frame;
- frame.push_id = max_push_id;
- if (spdy_session_->debug_visitor()) {
- spdy_session_->debug_visitor()->OnMaxPushIdFrameSent(frame);
- }
-
- std::unique_ptr<char[]> buffer;
- QuicByteCount frame_length =
- HttpEncoder::SerializeMaxPushIdFrame(frame, &buffer);
- WriteOrBufferData(absl::string_view(buffer.get(), frame_length),
- /*fin = */ false, nullptr);
-}
-
void QuicSendControlStream::SendGoAway(QuicStreamId id) {
QuicConnection::ScopedPacketFlusher flusher(session()->connection());
MaybeSendSettingsFrame();
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.h
index 155b423ae72..face80632af 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.h
@@ -37,10 +37,6 @@ class QUIC_EXPORT_PRIVATE QuicSendControlStream : public QuicStream {
// first frame sent on this stream.
void MaybeSendSettingsFrame();
- // Send a MAX_PUSH_ID frame on this stream, and a SETTINGS frame beforehand if
- // one has not been already sent. Must only be called for a client.
- void SendMaxPushIdFrame(PushId max_push_id);
-
// Send a PRIORITY_UPDATE frame on this stream, and a SETTINGS frame
// beforehand if one has not been already sent.
void WritePriorityUpdate(const PriorityUpdateFrame& priority_update);
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 fe849733c82..d1be0df27ca 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
@@ -14,6 +14,7 @@
#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 {
namespace test {
@@ -133,6 +134,25 @@ TEST_P(QuicSendControlStreamTest, WriteSettings) {
"4040" // 0x40 as the reserved frame type
"01" // 1 byte frame length
"61"); // payload "a"
+ if (GetQuicReloadableFlag(quic_h3_datagram)) {
+ expected_write_data = absl::HexStringToBytes(
+ "00" // stream type: control stream
+ "04" // frame type: SETTINGS frame
+ "0e" // frame length
+ "01" // SETTINGS_QPACK_MAX_TABLE_CAPACITY
+ "40ff" // 255
+ "06" // SETTINGS_MAX_HEADER_LIST_SIZE
+ "4400" // 1024
+ "07" // SETTINGS_QPACK_BLOCKED_STREAMS
+ "10" // 16
+ "4040" // 0x40 as the reserved settings id
+ "14" // 20
+ "4276" // SETTINGS_H3_DATAGRAM
+ "01" // 1
+ "4040" // 0x40 as the reserved frame type
+ "01" // 1 byte frame length
+ "61"); // payload "a"
+ }
auto buffer = std::make_unique<char[]>(expected_write_data.size());
QuicDataWriter writer(expected_write_data.size(), buffer.get());
@@ -158,8 +178,9 @@ TEST_P(QuicSendControlStreamTest, WriteSettings) {
.WillOnce(Invoke(save_write_data));
send_control_stream_->MaybeSendSettingsFrame();
- EXPECT_EQ(expected_write_data,
- absl::string_view(writer.data(), writer.length()));
+ quiche::test::CompareCharArraysWithHexError(
+ "settings", writer.data(), writer.length(), expected_write_data.data(),
+ expected_write_data.length());
}
TEST_P(QuicSendControlStreamTest, WriteSettingsOnlyOnce) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_initiated_spdy_stream.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_initiated_spdy_stream.cc
new file mode 100644
index 00000000000..37a53898d01
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_initiated_spdy_stream.cc
@@ -0,0 +1,43 @@
+// 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 "quic/core/http/quic_server_initiated_spdy_stream.h"
+#include "quic/core/quic_error_codes.h"
+
+namespace quic {
+
+void QuicServerInitiatedSpdyStream::OnBodyAvailable() {
+ QUIC_BUG(Body received in QuicServerInitiatedSpdyStream)
+ << "Received body data in QuicServerInitiatedSpdyStream.";
+ OnUnrecoverableError(
+ QUIC_INTERNAL_ERROR,
+ "Received HTTP/3 body data in a server-initiated bidirectional stream");
+}
+
+size_t QuicServerInitiatedSpdyStream::WriteHeaders(
+ spdy::SpdyHeaderBlock /*header_block*/,
+ bool /*fin*/,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> /*ack_listener*/) {
+ QUIC_BUG(Writing headers in QuicServerInitiatedSpdyStream)
+ << "Attempting to write headers in QuicServerInitiatedSpdyStream";
+ OnUnrecoverableError(QUIC_INTERNAL_ERROR,
+ "Attempted to send HTTP/3 headers in a server-initiated "
+ "bidirectional stream");
+ return 0;
+}
+
+void QuicServerInitiatedSpdyStream::OnInitialHeadersComplete(
+ bool /*fin*/,
+ size_t /*frame_len*/,
+ const QuicHeaderList& /*header_list*/) {
+ QUIC_PEER_BUG(Reading headers in QuicServerInitiatedSpdyStream)
+ << "Attempting to receive headers in QuicServerInitiatedSpdyStream";
+
+ OnUnrecoverableError(IETF_QUIC_PROTOCOL_VIOLATION,
+ "Received HTTP/3 headers in a server-initiated "
+ "bidirectional stream without an extension setting "
+ "explicitly allowing those");
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_initiated_spdy_stream.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_initiated_spdy_stream.h
new file mode 100644
index 00000000000..a13dc65cd13
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_initiated_spdy_stream.h
@@ -0,0 +1,32 @@
+// 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_QUIC_CORE_HTTP_QUIC_SERVER_INITIATED_SPDY_STREAM_H_
+#define QUICHE_QUIC_CORE_HTTP_QUIC_SERVER_INITIATED_SPDY_STREAM_H_
+
+#include "quic/core/http/quic_spdy_stream.h"
+
+namespace quic {
+
+// QuicServerInitiatedSpdyStream is a subclass of QuicSpdyStream meant to handle
+// WebTransport traffic on server-initiated bidirectional streams. Receiving or
+// sending any other traffic on this stream will result in a CONNECTION_CLOSE.
+class QUIC_EXPORT_PRIVATE QuicServerInitiatedSpdyStream
+ : public QuicSpdyStream {
+ public:
+ using QuicSpdyStream::QuicSpdyStream;
+
+ void OnBodyAvailable() override;
+ size_t WriteHeaders(spdy::SpdyHeaderBlock header_block,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface>
+ ack_listener) override;
+ void OnInitialHeadersComplete(bool fin,
+ size_t frame_len,
+ const QuicHeaderList& header_list) override;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_HTTP_QUIC_SERVER_INITIATED_SPDY_STREAM_H_
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 f91146b3b49..b955835e2b8 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
@@ -40,9 +40,7 @@ void QuicServerSessionBase::Initialize() {
crypto_stream_ =
CreateQuicCryptoServerStream(crypto_config_, compressed_certs_cache_);
QuicSpdySession::Initialize();
- if (GetQuicRestartFlag(quic_enable_zero_rtt_for_tls_v2)) {
- SendSettingsToCryptoStream();
- }
+ SendSettingsToCryptoStream();
}
void QuicServerSessionBase::OnConfigNegotiated() {
@@ -173,9 +171,10 @@ void QuicServerSessionBase::OnCongestionWindowChange(QuicTime now) {
bandwidth_estimate_sent_to_client_);
const int32_t max_bw_estimate_bytes_per_second =
BandwidthToCachedParameterBytesPerSecond(max_bandwidth_estimate);
- QUIC_BUG_IF(max_bw_estimate_bytes_per_second < 0)
+ QUIC_BUG_IF(quic_bug_12513_1, max_bw_estimate_bytes_per_second < 0)
<< max_bw_estimate_bytes_per_second;
- QUIC_BUG_IF(bw_estimate_bytes_per_second < 0) << bw_estimate_bytes_per_second;
+ QUIC_BUG_IF(quic_bug_10393_1, bw_estimate_bytes_per_second < 0)
+ << bw_estimate_bytes_per_second;
CachedNetworkParameters cached_network_params;
cached_network_params.set_bandwidth_estimate_bytes_per_second(
@@ -207,13 +206,15 @@ void QuicServerSessionBase::OnCongestionWindowChange(QuicTime now) {
bool QuicServerSessionBase::ShouldCreateIncomingStream(QuicStreamId id) {
if (!connection()->connected()) {
- QUIC_BUG << "ShouldCreateIncomingStream called when disconnected";
+ QUIC_BUG(quic_bug_10393_2)
+ << "ShouldCreateIncomingStream called when disconnected";
return false;
}
if (QuicUtils::IsServerInitiatedStreamId(transport_version(), id)) {
- QUIC_BUG << "ShouldCreateIncomingStream called with server initiated "
- "stream ID.";
+ QUIC_BUG(quic_bug_10393_3)
+ << "ShouldCreateIncomingStream called with server initiated "
+ "stream ID.";
return false;
}
@@ -229,12 +230,13 @@ bool QuicServerSessionBase::ShouldCreateIncomingStream(QuicStreamId id) {
bool QuicServerSessionBase::ShouldCreateOutgoingBidirectionalStream() {
if (!connection()->connected()) {
- QUIC_BUG
+ QUIC_BUG(quic_bug_12513_2)
<< "ShouldCreateOutgoingBidirectionalStream called when disconnected";
return false;
}
if (!crypto_stream_->encryption_established()) {
- QUIC_BUG << "Encryption not established so no outgoing stream created.";
+ QUIC_BUG(quic_bug_10393_4)
+ << "Encryption not established so no outgoing stream created.";
return false;
}
@@ -243,12 +245,13 @@ bool QuicServerSessionBase::ShouldCreateOutgoingBidirectionalStream() {
bool QuicServerSessionBase::ShouldCreateOutgoingUnidirectionalStream() {
if (!connection()->connected()) {
- QUIC_BUG
+ QUIC_BUG(quic_bug_12513_3)
<< "ShouldCreateOutgoingUnidirectionalStream called when disconnected";
return false;
}
if (!crypto_stream_->encryption_established()) {
- QUIC_BUG << "Encryption not established so no outgoing stream created.";
+ QUIC_BUG(quic_bug_10393_5)
+ << "Encryption not established so no outgoing stream created.";
return false;
}
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 f9483fefeeb..29750f2e3cf 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
@@ -9,6 +9,7 @@
#include <string>
#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"
@@ -21,7 +22,6 @@
#include "quic/core/tls_server_handshaker.h"
#include "quic/platform/api/quic_expect_bug.h"
#include "quic/platform/api/quic_flags.h"
-#include "quic/platform/api/quic_ptr_util.h"
#include "quic/platform/api/quic_socket_address.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/crypto_test_utils.h"
@@ -83,14 +83,14 @@ class TestServerSession : public QuicServerSessionBase {
}
QuicSpdyStream* stream = new QuicSimpleServerStream(
id, this, BIDIRECTIONAL, quic_simple_server_backend_);
- ActivateStream(QuicWrapUnique(stream));
+ ActivateStream(absl::WrapUnique(stream));
return stream;
}
QuicSpdyStream* CreateIncomingStream(PendingStream* pending) override {
QuicSpdyStream* stream = new QuicSimpleServerStream(
pending, this, BIDIRECTIONAL, quic_simple_server_backend_);
- ActivateStream(QuicWrapUnique(stream));
+ ActivateStream(absl::WrapUnique(stream));
return stream;
}
@@ -107,7 +107,7 @@ class TestServerSession : public QuicServerSessionBase {
QuicSpdyStream* stream = new QuicSimpleServerStream(
GetNextOutgoingUnidirectionalStreamId(), this, WRITE_UNIDIRECTIONAL,
quic_simple_server_backend_);
- ActivateStream(QuicWrapUnique(stream));
+ ActivateStream(absl::WrapUnique(stream));
return stream;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.cc
index ba5b457052e..b71cba9958f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.cc
@@ -7,7 +7,9 @@
#include <string>
#include <utility>
+#include "absl/memory/memory.h"
#include "quic/core/crypto/crypto_protocol.h"
+#include "quic/core/http/quic_server_initiated_spdy_stream.h"
#include "quic/core/http/quic_spdy_client_stream.h"
#include "quic/core/http/spdy_utils.h"
#include "quic/core/quic_server_id.h"
@@ -16,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 "quic/platform/api/quic_ptr_util.h"
namespace quic {
@@ -66,7 +67,8 @@ bool QuicSpdyClientSession::ShouldCreateOutgoingBidirectionalStream() {
}
bool QuicSpdyClientSession::ShouldCreateOutgoingUnidirectionalStream() {
- QUIC_BUG << "Try to create outgoing unidirectional client data streams";
+ QUIC_BUG(quic_bug_10396_1)
+ << "Try to create outgoing unidirectional client data streams";
return false;
}
@@ -83,7 +85,8 @@ QuicSpdyClientSession::CreateOutgoingBidirectionalStream() {
QuicSpdyClientStream*
QuicSpdyClientSession::CreateOutgoingUnidirectionalStream() {
- QUIC_BUG << "Try to create outgoing unidirectional client data streams";
+ QUIC_BUG(quic_bug_10396_2)
+ << "Try to create outgoing unidirectional client data streams";
return nullptr;
}
@@ -102,6 +105,18 @@ const QuicCryptoClientStreamBase* QuicSpdyClientSession::GetCryptoStream()
return crypto_stream_.get();
}
+bool QuicSpdyClientSession::IsKnownServerAddress(
+ const QuicSocketAddress& address) const {
+ return std::find(known_server_addresses_.cbegin(),
+ known_server_addresses_.cend(),
+ address) != known_server_addresses_.cend();
+}
+
+void QuicSpdyClientSession::AddKnownServerAddress(
+ const QuicSocketAddress& address) {
+ known_server_addresses_.push_back(address);
+}
+
void QuicSpdyClientSession::CryptoConnect() {
QUICHE_DCHECK(flow_controller());
crypto_stream_->CryptoConnect();
@@ -125,7 +140,8 @@ int QuicSpdyClientSession::GetNumReceivedServerConfigUpdates() const {
bool QuicSpdyClientSession::ShouldCreateIncomingStream(QuicStreamId id) {
if (!connection()->connected()) {
- QUIC_BUG << "ShouldCreateIncomingStream called when disconnected";
+ QUIC_BUG(quic_bug_10396_3)
+ << "ShouldCreateIncomingStream called when disconnected";
return false;
}
if (goaway_received() && respect_goaway_) {
@@ -135,8 +151,9 @@ bool QuicSpdyClientSession::ShouldCreateIncomingStream(QuicStreamId id) {
}
if (QuicUtils::IsClientInitiatedStreamId(transport_version(), id)) {
- QUIC_BUG << "ShouldCreateIncomingStream called with client initiated "
- "stream ID.";
+ QUIC_BUG(quic_bug_10396_4)
+ << "ShouldCreateIncomingStream called with client initiated "
+ "stream ID.";
return false;
}
@@ -150,7 +167,8 @@ bool QuicSpdyClientSession::ShouldCreateIncomingStream(QuicStreamId id) {
}
if (VersionHasIetfQuicFrames(transport_version()) &&
- QuicUtils::IsBidirectionalStreamId(id, version())) {
+ QuicUtils::IsBidirectionalStreamId(id, version()) &&
+ !WillNegotiateWebTransport()) {
connection()->CloseConnection(
QUIC_HTTP_SERVER_INITIATED_BIDIRECTIONAL_STREAM,
"Server created bidirectional stream.",
@@ -165,7 +183,7 @@ QuicSpdyStream* QuicSpdyClientSession::CreateIncomingStream(
PendingStream* pending) {
QuicSpdyStream* stream =
new QuicSpdyClientStream(pending, this, READ_UNIDIRECTIONAL);
- ActivateStream(QuicWrapUnique(stream));
+ ActivateStream(absl::WrapUnique(stream));
return stream;
}
@@ -173,9 +191,17 @@ QuicSpdyStream* QuicSpdyClientSession::CreateIncomingStream(QuicStreamId id) {
if (!ShouldCreateIncomingStream(id)) {
return nullptr;
}
- QuicSpdyStream* stream =
- new QuicSpdyClientStream(id, this, READ_UNIDIRECTIONAL);
- ActivateStream(QuicWrapUnique(stream));
+ QuicSpdyStream* stream;
+ if (version().UsesHttp3() &&
+ QuicUtils::IsBidirectionalStreamId(id, version())) {
+ QUIC_BUG_IF(QuicServerInitiatedSpdyStream but no WebTransport support,
+ !WillNegotiateWebTransport())
+ << "QuicServerInitiatedSpdyStream created but no WebTransport support";
+ stream = new QuicServerInitiatedSpdyStream(id, this, BIDIRECTIONAL);
+ } else {
+ stream = new QuicSpdyClientStream(id, this, READ_UNIDIRECTIONAL);
+ }
+ ActivateStream(absl::WrapUnique(stream));
return stream;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h
index c21eeea4c81..88df049e06d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h
@@ -20,7 +20,8 @@ namespace quic {
class QuicConnection;
class QuicServerId;
-class QUIC_NO_EXPORT QuicSpdyClientSession : public QuicSpdyClientSessionBase {
+class QUIC_EXPORT_PRIVATE QuicSpdyClientSession
+ : public QuicSpdyClientSessionBase {
public:
// Takes ownership of |connection|. Caller retains ownership of
// |promised_by_url|.
@@ -41,6 +42,9 @@ class QUIC_NO_EXPORT QuicSpdyClientSession : public QuicSpdyClientSessionBase {
QuicSpdyClientStream* CreateOutgoingUnidirectionalStream() override;
QuicCryptoClientStreamBase* GetMutableCryptoStream() override;
const QuicCryptoClientStreamBase* GetCryptoStream() const override;
+ bool IsKnownServerAddress(const QuicSocketAddress& address) const override;
+
+ void AddKnownServerAddress(const QuicSocketAddress& address);
bool IsAuthorized(const std::string& authority) override;
@@ -106,6 +110,8 @@ class QUIC_NO_EXPORT QuicSpdyClientSession : public QuicSpdyClientSessionBase {
std::unique_ptr<QuicCryptoClientStreamBase> crypto_stream_;
QuicServerId server_id_;
QuicCryptoClientConfig* crypto_config_;
+ // Server addresses that are known to the client.
+ std::vector<QuicSocketAddress> known_server_addresses_;
// If this is set to false, the client will ignore server GOAWAYs and allow
// the creation of streams regardless of the high chance they will fail.
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.cc
index 49f0198a041..56a976442c9 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.cc
@@ -142,7 +142,7 @@ bool QuicSpdyClientSessionBase::HandlePromised(QuicStreamId /* associated_id */,
if (GetPromisedById(promised_id)) {
// OnPromiseHeadersComplete() would have closed the connection if
// promised id is a duplicate.
- QUIC_BUG << "Duplicate promise for id " << promised_id;
+ QUIC_BUG(quic_bug_10412_1) << "Duplicate promise for id " << promised_id;
return false;
}
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 e2b5003bc4a..7197c8ab7ed 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
@@ -10,6 +10,7 @@
#include <vector>
#include "absl/base/macros.h"
+#include "absl/memory/memory.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "quic/core/crypto/null_decrypter.h"
@@ -25,7 +26,6 @@
#include "quic/core/tls_client_handshaker.h"
#include "quic/platform/api/quic_expect_bug.h"
#include "quic/platform/api/quic_flags.h"
-#include "quic/platform/api/quic_ptr_util.h"
#include "quic/platform/api/quic_socket_address.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/crypto_test_utils.h"
@@ -83,7 +83,7 @@ class TestQuicSpdyClientSession : public QuicSpdyClientSession {
}
MockQuicSpdyClientStream* stream =
new MockQuicSpdyClientStream(id, this, READ_UNIDIRECTIONAL);
- ActivateStream(QuicWrapUnique(stream));
+ ActivateStream(absl::WrapUnique(stream));
return stream;
}
};
@@ -97,7 +97,6 @@ class QuicSpdyClientSessionTest : public QuicTestWithParam<ParsedQuicVersion> {
QuicUtils::GetInvalidStreamId(GetParam().transport_version)) {
auto client_cache = std::make_unique<test::SimpleSessionCache>();
client_session_cache_ = client_cache.get();
- SetQuicRestartFlag(quic_enable_zero_rtt_for_tls_v2, true);
client_crypto_config_ = std::make_unique<QuicCryptoClientConfig>(
crypto_test_utils::ProofVerifierForTesting(), std::move(client_cache));
server_crypto_config_ = crypto_test_utils::CryptoServerConfigForTesting();
@@ -596,13 +595,13 @@ TEST_P(QuicSpdyClientSessionTest, InvalidFramedPacketReceived) {
}
TEST_P(QuicSpdyClientSessionTest, PushPromiseOnPromiseHeaders) {
- // Initialize crypto before the client session will create a stream.
- CompleteCryptoHandshake();
-
if (VersionHasIetfQuicFrames(connection_->transport_version())) {
- session_->SetMaxPushId(10);
+ return;
}
+ // Initialize crypto before the client session will create a stream.
+ CompleteCryptoHandshake();
+
MockQuicSpdyClientStream* stream = static_cast<MockQuicSpdyClientStream*>(
session_->CreateOutgoingBidirectionalStream());
@@ -612,6 +611,10 @@ TEST_P(QuicSpdyClientSessionTest, PushPromiseOnPromiseHeaders) {
}
TEST_P(QuicSpdyClientSessionTest, PushPromiseStreamIdTooHigh) {
+ if (VersionHasIetfQuicFrames(connection_->transport_version())) {
+ return;
+ }
+
// Initialize crypto before the client session will create a stream.
CompleteCryptoHandshake();
QuicStreamId stream_id =
@@ -628,18 +631,6 @@ TEST_P(QuicSpdyClientSessionTest, PushPromiseStreamIdTooHigh) {
headers.OnHeader(":scheme", "https");
headers.OnHeaderBlockEnd(0, 0);
- if (VersionHasIetfQuicFrames(connection_->transport_version())) {
- session_->SetMaxPushId(10);
- // TODO(b/136295430) Use PushId to represent Push IDs instead of
- // QuicStreamId.
- EXPECT_CALL(
- *connection_,
- CloseConnection(QUIC_INVALID_STREAM_ID,
- "Received push stream id higher than MAX_PUSH_ID.", _));
- const PushId promise_id = 11;
- session_->OnPromiseHeaderList(stream_id, promise_id, 0, headers);
- return;
- }
const QuicStreamId promise_id = GetNthServerInitiatedUnidirectionalStreamId(
connection_->transport_version(), 11);
session_->OnPromiseHeaderList(stream_id, promise_id, 0, headers);
@@ -661,13 +652,13 @@ TEST_P(QuicSpdyClientSessionTest, PushPromiseOnPromiseHeadersAlreadyClosed) {
}
TEST_P(QuicSpdyClientSessionTest, PushPromiseOutOfOrder) {
- // Initialize crypto before the client session will create a stream.
- CompleteCryptoHandshake();
-
if (VersionHasIetfQuicFrames(connection_->transport_version())) {
- session_->SetMaxPushId(10);
+ return;
}
+ // Initialize crypto before the client session will create a stream.
+ CompleteCryptoHandshake();
+
MockQuicSpdyClientStream* stream = static_cast<MockQuicSpdyClientStream*>(
session_->CreateOutgoingBidirectionalStream());
@@ -930,6 +921,10 @@ TEST_P(QuicSpdyClientSessionTest,
}
TEST_P(QuicSpdyClientSessionTest, TooManyPushPromises) {
+ if (VersionHasIetfQuicFrames(connection_->transport_version())) {
+ return;
+ }
+
// Initialize crypto before the client session will create a stream.
CompleteCryptoHandshake();
QuicStreamId stream_id =
@@ -938,10 +933,6 @@ TEST_P(QuicSpdyClientSessionTest, TooManyPushPromises) {
session_.get(), std::make_unique<QuicSpdyClientStream>(
stream_id, session_.get(), BIDIRECTIONAL));
- if (VersionHasIetfQuicFrames(connection_->transport_version())) {
- session_->SetMaxPushId(kMaxQuicStreamId);
- }
-
EXPECT_CALL(*connection_, OnStreamReset(_, QUIC_REFUSED_STREAM));
for (size_t promise_count = 0; promise_count <= session_->get_max_promises();
@@ -1268,119 +1259,6 @@ TEST_P(QuicSpdyClientSessionTest,
connection_, crypto_stream_, AlpnForVersion(connection_->version()));
}
-TEST_P(QuicSpdyClientSessionTest, SetMaxPushIdBeforeEncryptionEstablished) {
- // 0-RTT is TLS-only, MAX_PUSH_ID frame is HTTP/3-only.
- if (!session_->version().UsesTls() || !session_->version().UsesHttp3()) {
- return;
- }
-
- CompleteFirstConnection();
-
- CreateConnection();
- StrictMock<MockHttp3DebugVisitor> debug_visitor;
- session_->set_debug_visitor(&debug_visitor);
-
- // No MAX_PUSH_ID frame is sent before encryption is established.
- session_->SetMaxPushId(5);
-
- EXPECT_FALSE(session_->IsEncryptionEstablished());
- EXPECT_FALSE(session_->OneRttKeysAvailable());
- EXPECT_EQ(ENCRYPTION_INITIAL, session_->connection()->encryption_level());
-
- // MAX_PUSH_ID frame is sent upon encryption establishment with the value set
- // by the earlier SetMaxPushId() call.
- EXPECT_CALL(debug_visitor, OnSettingsFrameSent(_));
- EXPECT_CALL(debug_visitor, OnMaxPushIdFrameSent(_))
- .WillOnce(Invoke(
- [](const MaxPushIdFrame& frame) { EXPECT_EQ(5u, frame.push_id); }));
- session_->CryptoConnect();
- testing::Mock::VerifyAndClearExpectations(&debug_visitor);
-
- EXPECT_TRUE(session_->IsEncryptionEstablished());
- EXPECT_FALSE(session_->OneRttKeysAvailable());
- EXPECT_EQ(ENCRYPTION_ZERO_RTT, session_->connection()->encryption_level());
-
- // Another SetMaxPushId() call with the same value does not trigger sending
- // another MAX_PUSH_ID frame.
- session_->SetMaxPushId(5);
-
- // Calling SetMaxPushId() with a different value results in sending another
- // MAX_PUSH_ID frame.
- EXPECT_CALL(debug_visitor, OnMaxPushIdFrameSent(_))
- .WillOnce(Invoke(
- [](const MaxPushIdFrame& frame) { EXPECT_EQ(10u, frame.push_id); }));
- session_->SetMaxPushId(10);
- testing::Mock::VerifyAndClearExpectations(&debug_visitor);
-
- QuicConfig config = DefaultQuicConfig();
- crypto_test_utils::HandshakeWithFakeServer(
- &config, server_crypto_config_.get(), &helper_, &alarm_factory_,
- connection_, crypto_stream_, AlpnForVersion(connection_->version()));
-
- EXPECT_TRUE(session_->IsEncryptionEstablished());
- EXPECT_TRUE(session_->OneRttKeysAvailable());
- EXPECT_EQ(ENCRYPTION_FORWARD_SECURE,
- session_->connection()->encryption_level());
- EXPECT_TRUE(session_->GetCryptoStream()->IsResumption());
-}
-
-TEST_P(QuicSpdyClientSessionTest, SetMaxPushIdAfterEncryptionEstablished) {
- // 0-RTT is TLS-only, MAX_PUSH_ID frame is HTTP/3-only.
- if (!session_->version().UsesTls() || !session_->version().UsesHttp3()) {
- return;
- }
-
- CompleteFirstConnection();
-
- CreateConnection();
- StrictMock<MockHttp3DebugVisitor> debug_visitor;
- session_->set_debug_visitor(&debug_visitor);
-
- EXPECT_FALSE(session_->IsEncryptionEstablished());
- EXPECT_FALSE(session_->OneRttKeysAvailable());
- EXPECT_EQ(ENCRYPTION_INITIAL, session_->connection()->encryption_level());
-
- // No MAX_PUSH_ID frame is sent if SetMaxPushId() has not been called.
- EXPECT_CALL(debug_visitor, OnSettingsFrameSent(_));
- session_->CryptoConnect();
- testing::Mock::VerifyAndClearExpectations(&debug_visitor);
-
- EXPECT_TRUE(session_->IsEncryptionEstablished());
- EXPECT_FALSE(session_->OneRttKeysAvailable());
- EXPECT_EQ(ENCRYPTION_ZERO_RTT, session_->connection()->encryption_level());
-
- // Calling SetMaxPushId() for the first time after encryption is established
- // results in sending a MAX_PUSH_ID frame.
- EXPECT_CALL(debug_visitor, OnMaxPushIdFrameSent(_))
- .WillOnce(Invoke(
- [](const MaxPushIdFrame& frame) { EXPECT_EQ(5u, frame.push_id); }));
- session_->SetMaxPushId(5);
- testing::Mock::VerifyAndClearExpectations(&debug_visitor);
-
- // Another SetMaxPushId() call with the same value does not trigger sending
- // another MAX_PUSH_ID frame.
- session_->SetMaxPushId(5);
-
- // Calling SetMaxPushId() with a different value results in sending another
- // MAX_PUSH_ID frame.
- EXPECT_CALL(debug_visitor, OnMaxPushIdFrameSent(_))
- .WillOnce(Invoke(
- [](const MaxPushIdFrame& frame) { EXPECT_EQ(10u, frame.push_id); }));
- session_->SetMaxPushId(10);
- testing::Mock::VerifyAndClearExpectations(&debug_visitor);
-
- QuicConfig config = DefaultQuicConfig();
- crypto_test_utils::HandshakeWithFakeServer(
- &config, server_crypto_config_.get(), &helper_, &alarm_factory_,
- connection_, crypto_stream_, AlpnForVersion(connection_->version()));
-
- EXPECT_TRUE(session_->IsEncryptionEstablished());
- EXPECT_TRUE(session_->OneRttKeysAvailable());
- EXPECT_EQ(ENCRYPTION_FORWARD_SECURE,
- session_->connection()->encryption_level());
- EXPECT_TRUE(session_->GetCryptoStream()->IsResumption());
-}
-
TEST_P(QuicSpdyClientSessionTest, BadSettingsInZeroRttResumption) {
if (!session_->version().UsesHttp3()) {
return;
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.cc
index 931bfb3fdcb..d264ba64879 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.cc
@@ -10,6 +10,7 @@
#include "quic/core/http/quic_client_promised_info.h"
#include "quic/core/http/quic_spdy_client_session.h"
#include "quic/core/http/spdy_utils.h"
+#include "quic/core/http/web_transport_http3.h"
#include "quic/core/quic_alarm.h"
#include "quic/platform/api/quic_logging.h"
#include "spdy/core/spdy_protocol.h"
@@ -58,6 +59,15 @@ void QuicSpdyClientStream::OnInitialHeadersComplete(
return;
}
+ if (web_transport() != nullptr) {
+ web_transport()->HeadersReceived(response_headers_);
+ if (!web_transport()->ready()) {
+ // Rejected due to status not being 200, or other reason.
+ WriteOrBufferData("", /*fin=*/true, nullptr);
+ return;
+ }
+ }
+
if (!ParseHeaderStatusCode(response_headers_, &response_code_)) {
QUIC_DLOG(ERROR) << "Received invalid response code: "
<< response_headers_[":status"].as_string()
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h
index b62f49639eb..231846508e4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h
@@ -19,7 +19,7 @@ class QuicSpdyClientSession;
// All this does right now is send an SPDY request, and aggregate the
// SPDY response.
-class QUIC_NO_EXPORT QuicSpdyClientStream : public QuicSpdyStream {
+class QUIC_EXPORT_PRIVATE QuicSpdyClientStream : public QuicSpdyStream {
public:
QuicSpdyClientStream(QuicStreamId id,
QuicSpdyClientSession* session,
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream_test.cc
index c1ad5c6a17c..fa4943dcda7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream_test.cc
@@ -8,6 +8,7 @@
#include <string>
#include <utility>
+#include "absl/strings/str_cat.h"
#include "quic/core/crypto/null_encrypter.h"
#include "quic/core/http/quic_spdy_client_session.h"
#include "quic/core/http/spdy_utils.h"
@@ -18,7 +19,6 @@
#include "quic/test_tools/crypto_test_utils.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"
using spdy::SpdyHeaderBlock;
using testing::_;
@@ -283,8 +283,7 @@ TEST_P(QuicSpdyClientStreamTest, ReceivingTrailers) {
// promised by the final offset field.
SpdyHeaderBlock trailer_block;
trailer_block["trailer key"] = "trailer value";
- trailer_block[kFinalOffsetHeaderKey] =
- quiche::QuicheTextUtils::Uint64ToString(body_.size());
+ trailer_block[kFinalOffsetHeaderKey] = absl::StrCat(body_.size());
auto trailers = AsHeaderList(trailer_block);
stream_->OnStreamHeaderList(true, trailers.uncompressed_header_bytes(),
trailers);
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_server_stream_base_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_server_stream_base_test.cc
index bada26378f4..fe630de5108 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_server_stream_base_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_server_stream_base_test.cc
@@ -4,8 +4,8 @@
#include "quic/core/http/quic_spdy_server_stream_base.h"
+#include "absl/memory/memory.h"
#include "quic/core/crypto/null_encrypter.h"
-#include "quic/platform/api/quic_ptr_util.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_spdy_session_peer.h"
#include "quic/test_tools/quic_stream_peer.h"
@@ -41,7 +41,7 @@ class QuicSpdyServerStreamBaseTest : public QuicTest {
new TestQuicSpdyServerStream(GetNthClientInitiatedBidirectionalStreamId(
session_.transport_version(), 0),
&session_, BIDIRECTIONAL);
- session_.ActivateStream(QuicWrapUnique(stream_));
+ session_.ActivateStream(absl::WrapUnique(stream_));
helper_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
}
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 91530d36443..16948101c6c 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
@@ -7,6 +7,7 @@
#include <algorithm>
#include <cstdint>
#include <limits>
+#include <memory>
#include <string>
#include <utility>
@@ -18,6 +19,7 @@
#include "quic/core/http/http_decoder.h"
#include "quic/core/http/http_frames.h"
#include "quic/core/http/quic_headers_stream.h"
+#include "quic/core/http/web_transport_http3.h"
#include "quic/core/quic_error_codes.h"
#include "quic/core/quic_types.h"
#include "quic/core/quic_utils.h"
@@ -55,39 +57,13 @@ using spdy::SpdyStreamId;
namespace quic {
+ABSL_CONST_INIT const size_t kMaxUnassociatedWebTransportStreams = 24;
+
namespace {
#define ENDPOINT \
(perspective() == Perspective::IS_SERVER ? "Server: " : "Client: ")
-class HeaderTableDebugVisitor : public HpackHeaderTable::DebugVisitorInterface {
- public:
- HeaderTableDebugVisitor(const QuicClock* clock,
- std::unique_ptr<QuicHpackDebugVisitor> visitor)
- : clock_(clock), headers_stream_hpack_visitor_(std::move(visitor)) {}
- HeaderTableDebugVisitor(const HeaderTableDebugVisitor&) = delete;
- HeaderTableDebugVisitor& operator=(const HeaderTableDebugVisitor&) = delete;
-
- int64_t OnNewEntry(const HpackEntry& entry) override {
- QUIC_DVLOG(1) << entry.GetDebugString();
- return (clock_->ApproximateNow() - QuicTime::Zero()).ToMicroseconds();
- }
-
- void OnUseEntry(const HpackEntry& entry) override {
- const QuicTime::Delta elapsed(
- clock_->ApproximateNow() -
- QuicTime::Delta::FromMicroseconds(entry.time_added()) -
- QuicTime::Zero());
- QUIC_DVLOG(1) << entry.GetDebugString() << " " << elapsed.ToMilliseconds()
- << " ms";
- headers_stream_hpack_visitor_->OnUseEntry(elapsed);
- }
-
- private:
- const QuicClock* clock_;
- std::unique_ptr<QuicHpackDebugVisitor> headers_stream_hpack_visitor_;
-};
-
// Class to forward ACCEPT_CH frame to QuicSpdySession,
// and ignore every other frame.
class AlpsFrameDecoder : public HttpDecoder::Visitor {
@@ -112,7 +88,17 @@ class AlpsFrameDecoder : public HttpDecoder::Visitor {
bool OnSettingsFrameStart(QuicByteCount /*header_length*/) override {
return true;
}
- bool OnSettingsFrame(const SettingsFrame& /*frame*/) override { return true; }
+ bool OnSettingsFrame(const SettingsFrame& frame) override {
+ if (settings_frame_received_via_alps_) {
+ error_detail_ = "multiple SETTINGS frames";
+ return false;
+ }
+
+ settings_frame_received_via_alps_ = true;
+
+ error_detail_ = session_->OnSettingsFrameViaAlps(frame);
+ return !error_detail_;
+ }
bool OnDataFrameStart(QuicByteCount /*header_length*/, QuicByteCount
/*payload_length*/) override {
error_detail_ = "DATA frame forbidden";
@@ -174,6 +160,11 @@ class AlpsFrameDecoder : public HttpDecoder::Visitor {
session_->OnAcceptChFrameReceivedViaAlps(frame);
return true;
}
+ void OnWebTransportStreamFrameType(
+ QuicByteCount /*header_length*/,
+ WebTransportSessionId /*session_id*/) override {
+ QUICHE_NOTREACHED();
+ }
bool OnUnknownFrameStart(uint64_t /*frame_type*/,
QuicByteCount
/*header_length*/,
@@ -192,6 +183,9 @@ class AlpsFrameDecoder : public HttpDecoder::Visitor {
private:
QuicSpdySession* const session_;
absl::optional<std::string> error_detail_;
+
+ // True if SETTINGS frame has been received via ALPS.
+ bool settings_frame_received_via_alps_ = false;
};
} // namespace
@@ -366,7 +360,8 @@ class QuicSpdySession::SpdyFramerVisitor
return;
}
- QUIC_BUG_IF(session_->destruction_indicator() != 123456789)
+ QUIC_BUG_IF(quic_bug_12477_1,
+ session_->destruction_indicator() != 123456789)
<< "QuicSpdyStream use after free. "
<< session_->destruction_indicator() << QuicStackTrace();
@@ -430,7 +425,7 @@ class QuicSpdySession::SpdyFramerVisitor
size_t payload_len,
size_t frame_len) override {
if (payload_len == 0) {
- QUIC_BUG << "Zero payload length.";
+ QUIC_BUG(quic_bug_10360_1) << "Zero payload length.";
return;
}
int compression_pct = 100 - (100 * frame_len) / payload_len;
@@ -460,10 +455,6 @@ class QuicSpdySession::SpdyFramerVisitor
QuicHeaderList header_list_;
};
-QuicHpackDebugVisitor::QuicHpackDebugVisitor() {}
-
-QuicHpackDebugVisitor::~QuicHpackDebugVisitor() {}
-
Http3DebugVisitor::Http3DebugVisitor() {}
Http3DebugVisitor::~Http3DebugVisitor() {}
@@ -481,8 +472,10 @@ QuicSpdySession::QuicSpdySession(
supported_versions,
/*num_expected_unidirectional_static_streams = */
VersionUsesHttp3(connection->transport_version())
- ? kHttp3StaticUnidirectionalStreamCount
- : 0),
+ ? static_cast<QuicStreamCount>(
+ kHttp3StaticUnidirectionalStreamCount)
+ : 0u,
+ std::make_unique<DatagramObserver>(this)),
send_control_stream_(nullptr),
receive_control_stream_(nullptr),
qpack_encoder_receive_stream_(nullptr),
@@ -505,22 +498,17 @@ QuicSpdySession::QuicSpdySession(
debug_visitor_(nullptr),
destruction_indicator_(123456789),
server_push_enabled_(true),
- ietf_server_push_enabled_(
- GetQuicFlag(FLAGS_quic_enable_http3_server_push)),
- http3_max_push_id_sent_(false),
- goaway_with_max_stream_id_(
- GetQuicReloadableFlag(quic_goaway_with_max_stream_id)) {
- if (goaway_with_max_stream_id_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_goaway_with_max_stream_id, 1, 2);
- }
+ next_available_datagram_flow_id_(perspective() == Perspective::IS_SERVER
+ ? kFirstDatagramFlowIdServer
+ : kFirstDatagramFlowIdClient) {
h2_deframer_.set_visitor(spdy_framer_visitor_.get());
h2_deframer_.set_debug_visitor(spdy_framer_visitor_.get());
spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get());
}
QuicSpdySession::~QuicSpdySession() {
- QUIC_BUG_IF(destruction_indicator_ != 123456789)
- << "QuicSpdyStream use after free. " << destruction_indicator_
+ QUIC_BUG_IF(quic_bug_12477_2, destruction_indicator_ != 123456789)
+ << "QuicSpdySession use after free. " << destruction_indicator_
<< QuicStackTrace();
destruction_indicator_ = 987654321;
}
@@ -566,6 +554,13 @@ void QuicSpdySession::FillSettingsFrame() {
qpack_maximum_blocked_streams_;
settings_.values[SETTINGS_MAX_FIELD_SECTION_SIZE] =
max_inbound_header_list_size_;
+ if (ShouldNegotiateHttp3Datagram() && version().UsesHttp3()) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_h3_datagram);
+ settings_.values[SETTINGS_H3_DATAGRAM] = 1;
+ }
+ if (WillNegotiateWebTransport()) {
+ settings_.values[SETTINGS_WEBTRANS_DRAFT00] = 1;
+ }
}
void QuicSpdySession::OnDecoderStreamError(QuicErrorCode error_code,
@@ -688,7 +683,7 @@ bool QuicSpdySession::OnPriorityUpdateForRequestStream(QuicStreamId stream_id,
buffered_stream_priorities_.size(),
", which should not exceed the incoming stream limit of ",
max_open_incoming_bidirectional_streams());
- QUIC_BUG << error_message;
+ QUIC_BUG(quic_bug_10360_2) << error_message;
connection()->CloseConnection(
QUIC_INTERNAL_ERROR, error_message,
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -705,7 +700,7 @@ bool QuicSpdySession::OnPriorityUpdateForPushStream(QuicStreamId /*push_id*/,
}
size_t QuicSpdySession::ProcessHeaderData(const struct iovec& iov) {
- QUIC_BUG_IF(destruction_indicator_ != 123456789)
+ QUIC_BUG_IF(quic_bug_12477_4, destruction_indicator_ != 123456789)
<< "QuicSpdyStream use after free. " << destruction_indicator_
<< QuicStackTrace();
return h2_deframer_.ProcessInput(static_cast<char*>(iov.iov_base),
@@ -747,7 +742,7 @@ void QuicSpdySession::WriteHttp3PriorityUpdate(
}
void QuicSpdySession::OnHttp3GoAway(uint64_t id) {
- QUIC_BUG_IF(!version().UsesHttp3())
+ QUIC_BUG_IF(quic_bug_12477_5, !version().UsesHttp3())
<< "HTTP/3 GOAWAY received on version " << version();
if (last_received_http3_goaway_id_.has_value() &&
@@ -815,40 +810,21 @@ void QuicSpdySession::SendHttp3GoAway(QuicErrorCode error_code,
}
QuicStreamId stream_id;
- if (goaway_with_max_stream_id_) {
- stream_id = QuicUtils::GetMaxClientInitiatedBidirectionalStreamId(
- transport_version());
- if (last_sent_http3_goaway_id_.has_value()) {
- if (last_sent_http3_goaway_id_.value() == stream_id) {
- // Do not send GOAWAY twice.
- return;
- }
- if (last_sent_http3_goaway_id_.value() < stream_id) {
- // A previous GOAWAY frame was sent with smaller stream ID. This is not
- // possible, because the only time a GOAWAY frame with non-maximal
- // stream ID is sent is right before closing connection.
- QUIC_BUG << "GOAWAY frame with smaller ID already sent.";
- return;
- }
- }
- } else {
- stream_id = GetLargestPeerCreatedStreamId(/*unidirectional = */ false);
-
- if (stream_id == QuicUtils::GetInvalidStreamId(transport_version())) {
- // No client-initiated bidirectional streams received yet.
- // Send 0 to let client know that all requests can be retried.
- stream_id = 0;
- } else {
- // Tell client that streams starting with the next after the largest
- // received one can be retried.
- stream_id += QuicUtils::StreamIdDelta(transport_version());
+ stream_id = QuicUtils::GetMaxClientInitiatedBidirectionalStreamId(
+ transport_version());
+ if (last_sent_http3_goaway_id_.has_value()) {
+ if (last_sent_http3_goaway_id_.value() == stream_id) {
+ // Do not send GOAWAY twice.
+ return;
}
- if (last_sent_http3_goaway_id_.has_value() &&
- last_sent_http3_goaway_id_.value() <= stream_id) {
- // MUST not send GOAWAY with identifier larger than previously sent.
- // Do not bother sending one with same identifier as before, since
- // GOAWAY frames on the control stream are guaranteed to be processed in
- // order.
+ if (last_sent_http3_goaway_id_.value() < stream_id) {
+ // A previous GOAWAY frame was sent with smaller stream ID. This is not
+ // possible, because the only time a GOAWAY frame with non-maximal
+ // stream ID is sent is right before closing connection.
+ QUIC_BUG(quic_bug_10360_3)
+ << "Not sending GOAWAY frame with " << stream_id
+ << " because one with " << last_sent_http3_goaway_id_.value()
+ << " already sent on connection " << connection()->connection_id();
return;
}
}
@@ -857,77 +833,33 @@ void QuicSpdySession::SendHttp3GoAway(QuicErrorCode error_code,
last_sent_http3_goaway_id_ = stream_id;
}
-void QuicSpdySession::SendHttp3Shutdown() {
- if (goaway_with_max_stream_id_) {
- SendHttp3GoAway(QUIC_PEER_GOING_AWAY, "Server shutdown");
- return;
- }
-
- QUICHE_DCHECK_EQ(perspective(), Perspective::IS_SERVER);
- QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
- QuicStreamCount advertised_max_incoming_bidirectional_streams =
- GetAdvertisedMaxIncomingBidirectionalStreams();
- const QuicStreamId stream_id =
- QuicUtils::GetFirstBidirectionalStreamId(transport_version(),
- Perspective::IS_CLIENT) +
- QuicUtils::StreamIdDelta(transport_version()) *
- advertised_max_incoming_bidirectional_streams;
- if (last_sent_http3_goaway_id_.has_value() &&
- last_sent_http3_goaway_id_.value() < stream_id) {
- send_control_stream_->SendGoAway(last_sent_http3_goaway_id_.value());
- return;
- }
- send_control_stream_->SendGoAway(stream_id);
- last_sent_http3_goaway_id_ = stream_id;
-}
-
void QuicSpdySession::WritePushPromise(QuicStreamId original_stream_id,
QuicStreamId promised_stream_id,
SpdyHeaderBlock headers) {
if (perspective() == Perspective::IS_CLIENT) {
- QUIC_BUG << "Client shouldn't send PUSH_PROMISE";
+ QUIC_BUG(quic_bug_10360_4) << "Client shouldn't send PUSH_PROMISE";
return;
}
- if (!VersionUsesHttp3(transport_version())) {
- SpdyPushPromiseIR push_promise(original_stream_id, promised_stream_id,
- std::move(headers));
- // PUSH_PROMISE must not be the last frame sent out, at least followed by
- // response headers.
- push_promise.set_fin(false);
-
- SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise));
- headers_stream()->WriteOrBufferData(
- absl::string_view(frame.data(), frame.size()), false, nullptr);
- return;
- }
-
- if (!max_push_id_.has_value() || promised_stream_id > max_push_id_.value()) {
- QUIC_BUG
- << "Server shouldn't send push id higher than client's MAX_PUSH_ID.";
+ if (VersionUsesHttp3(transport_version())) {
+ QUIC_BUG(quic_bug_12477_6)
+ << "Support for server push over HTTP/3 has been removed.";
return;
}
- // Encode header list.
- std::string encoded_headers =
- qpack_encoder_->EncodeHeaderList(original_stream_id, headers, nullptr);
-
- if (debug_visitor_) {
- debug_visitor_->OnPushPromiseFrameSent(original_stream_id,
- promised_stream_id, headers);
- }
+ SpdyPushPromiseIR push_promise(original_stream_id, promised_stream_id,
+ std::move(headers));
+ // PUSH_PROMISE must not be the last frame sent out, at least followed by
+ // response headers.
+ push_promise.set_fin(false);
- PushPromiseFrame frame;
- frame.push_id = promised_stream_id;
- frame.headers = encoded_headers;
- QuicSpdyStream* stream = GetOrCreateSpdyDataStream(original_stream_id);
- stream->WritePushPromise(frame);
+ SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise));
+ headers_stream()->WriteOrBufferData(
+ absl::string_view(frame.data(), frame.size()), false, nullptr);
}
bool QuicSpdySession::server_push_enabled() const {
- return VersionUsesHttp3(transport_version())
- ? ietf_server_push_enabled_ && max_push_id_.has_value()
- : server_push_enabled_;
+ return VersionUsesHttp3(transport_version()) ? false : server_push_enabled_;
}
void QuicSpdySession::SendInitialData() {
@@ -936,10 +868,6 @@ void QuicSpdySession::SendInitialData() {
}
QuicConnection::ScopedPacketFlusher flusher(connection());
send_control_stream_->MaybeSendSettingsFrame();
- if (perspective() == Perspective::IS_CLIENT && max_push_id_.has_value() &&
- !http3_max_push_id_sent_) {
- SendMaxPushId();
- }
}
QpackEncoder* QuicSpdySession::qpack_encoder() {
@@ -968,9 +896,10 @@ QuicSpdyStream* QuicSpdySession::GetOrCreateSpdyDataStream(
const QuicStreamId stream_id) {
QuicStream* stream = GetOrCreateStream(stream_id);
if (stream && stream->is_static()) {
- QUIC_BUG << "GetOrCreateSpdyDataStream returns static stream " << stream_id
- << " in version " << transport_version() << "\n"
- << QuicStackTrace();
+ QUIC_BUG(quic_bug_10360_5)
+ << "GetOrCreateSpdyDataStream returns static stream " << stream_id
+ << " in version " << transport_version() << "\n"
+ << QuicStackTrace();
connection()->CloseConnection(
QUIC_INVALID_STREAM_ID,
absl::StrCat("stream ", stream_id, " is static"),
@@ -990,6 +919,15 @@ void QuicSpdySession::OnNewEncryptionKeyAvailable(
}
}
+bool QuicSpdySession::ShouldNegotiateWebTransport() {
+ return false;
+}
+
+bool QuicSpdySession::WillNegotiateWebTransport() {
+ return ShouldNegotiateHttp3Datagram() && version().UsesHttp3() &&
+ ShouldNegotiateWebTransport();
+}
+
// True if there are open HTTP requests.
bool QuicSpdySession::ShouldKeepConnectionAlive() const {
QUICHE_DCHECK(VersionUsesHttp3(transport_version()) ||
@@ -1050,7 +988,7 @@ void QuicSpdySession::OnPromiseHeaderList(
const QuicHeaderList& /*header_list*/) {
std::string error =
"OnPromiseHeaderList should be overridden in client code.";
- QUIC_BUG << error;
+ QUIC_BUG(quic_bug_10360_6) << error;
connection()->CloseConnection(QUIC_INTERNAL_ERROR, error,
ConnectionCloseBehavior::SILENT_CLOSE);
}
@@ -1069,6 +1007,7 @@ bool QuicSpdySession::ResumeApplicationState(ApplicationState* cached_state) {
if (debug_visitor_ != nullptr) {
debug_visitor_->OnSettingsFrameResumed(out);
}
+ QUICHE_DCHECK(streams_waiting_for_settings_.empty());
for (const auto& setting : out.values) {
OnSetting(setting.first, setting.second);
}
@@ -1113,10 +1052,41 @@ bool QuicSpdySession::OnSettingsFrame(const SettingsFrame& frame) {
return false;
}
}
+ for (QuicStreamId stream_id : streams_waiting_for_settings_) {
+ QUICHE_DCHECK(ShouldBufferRequestsUntilSettings());
+ QuicSpdyStream* stream = GetOrCreateSpdyDataStream(stream_id);
+ if (stream == nullptr) {
+ // The stream may no longer exist, since it is possible for a stream to
+ // get reset while waiting for the SETTINGS frame.
+ continue;
+ }
+ stream->OnDataAvailable();
+ }
+ streams_waiting_for_settings_.clear();
return true;
}
+absl::optional<std::string> QuicSpdySession::OnSettingsFrameViaAlps(
+ const SettingsFrame& frame) {
+ QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
+
+ if (debug_visitor_ != nullptr) {
+ debug_visitor_->OnSettingsFrameReceivedViaAlps(frame);
+ }
+ for (const auto& setting : frame.values) {
+ if (!OnSetting(setting.first, setting.second)) {
+ // Do not bother adding the setting identifier or value to the error
+ // message, because OnSetting() already closed the connection, therefore
+ // the error message will be ignored.
+ return "error parsing setting";
+ }
+ }
+ return absl::nullopt;
+}
+
bool QuicSpdySession::OnSetting(uint64_t id, uint64_t value) {
+ any_settings_received_ = true;
+
if (VersionUsesHttp3(transport_version())) {
// SETTINGS frame received on the control stream.
switch (id) {
@@ -1127,8 +1097,7 @@ bool QuicSpdySession::OnSetting(uint64_t id, uint64_t value) {
<< value;
// Communicate |value| to encoder, because it is used for encoding
// Required Insert Count.
- bool success = qpack_encoder_->SetMaximumDynamicTableCapacity(value);
- if (GetQuicRestartFlag(quic_enable_zero_rtt_for_tls_v2) && !success) {
+ if (!qpack_encoder_->SetMaximumDynamicTableCapacity(value)) {
CloseConnectionWithDetails(
was_zero_rtt_rejected()
? QUIC_HTTP_ZERO_RTT_REJECTION_SETTINGS_MISMATCH
@@ -1137,7 +1106,7 @@ bool QuicSpdySession::OnSetting(uint64_t id, uint64_t value) {
? "Server rejected 0-RTT, aborting because "
: "",
"Server sent an SETTINGS_QPACK_MAX_TABLE_CAPACITY: ",
- value, "while current value is: ",
+ value, " while current value is: ",
qpack_encoder_->MaximumDynamicTableCapacity()));
return false;
}
@@ -1151,8 +1120,7 @@ bool QuicSpdySession::OnSetting(uint64_t id, uint64_t value) {
QUIC_DVLOG(1) << ENDPOINT
<< "SETTINGS_MAX_FIELD_SECTION_SIZE received with value "
<< value;
- if (GetQuicRestartFlag(quic_enable_zero_rtt_for_tls_v2) &&
- max_outbound_header_list_size_ !=
+ if (max_outbound_header_list_size_ !=
std::numeric_limits<size_t>::max() &&
max_outbound_header_list_size_ > value) {
CloseConnectionWithDetails(
@@ -1163,7 +1131,7 @@ bool QuicSpdySession::OnSetting(uint64_t id, uint64_t value) {
? "Server rejected 0-RTT, aborting because "
: "",
"Server sent an SETTINGS_MAX_FIELD_SECTION_SIZE: ",
- value, "which reduces current value: ",
+ value, " which reduces current value: ",
max_outbound_header_list_size_));
return false;
}
@@ -1173,8 +1141,7 @@ bool QuicSpdySession::OnSetting(uint64_t id, uint64_t value) {
QUIC_DVLOG(1) << ENDPOINT
<< "SETTINGS_QPACK_BLOCKED_STREAMS received with value "
<< value;
- bool success = qpack_encoder_->SetMaximumBlockedStreams(value);
- if (GetQuicRestartFlag(quic_enable_zero_rtt_for_tls_v2) && !success) {
+ if (!qpack_encoder_->SetMaximumBlockedStreams(value)) {
CloseConnectionWithDetails(
was_zero_rtt_rejected()
? QUIC_HTTP_ZERO_RTT_REJECTION_SETTINGS_MISMATCH
@@ -1183,7 +1150,7 @@ bool QuicSpdySession::OnSetting(uint64_t id, uint64_t value) {
? "Server rejected 0-RTT, aborting because "
: "",
"Server sent an SETTINGS_QPACK_BLOCKED_STREAMS: ",
- value, "which reduces current value: ",
+ value, " which reduces current value: ",
qpack_encoder_->maximum_blocked_streams()));
return false;
}
@@ -1201,6 +1168,45 @@ bool QuicSpdySession::OnSetting(uint64_t id, uint64_t value) {
absl::StrCat("received HTTP/2 specific setting in HTTP/3 session: ",
id));
return false;
+ case SETTINGS_H3_DATAGRAM: {
+ if (!ShouldNegotiateHttp3Datagram()) {
+ break;
+ }
+ QUIC_DVLOG(1) << ENDPOINT << "SETTINGS_H3_DATAGRAM received with value "
+ << value;
+ if (!version().UsesHttp3()) {
+ break;
+ }
+ if (value != 0 && value != 1) {
+ std::string error_details = absl::StrCat(
+ "received SETTINGS_H3_DATAGRAM with invalid value ", value);
+ QUIC_PEER_BUG(quic_peer_bug_10360_7) << ENDPOINT << error_details;
+ CloseConnectionWithDetails(QUIC_HTTP_RECEIVE_SPDY_SETTING,
+ error_details);
+ return false;
+ }
+ h3_datagram_supported_ = !!value;
+ break;
+ }
+ case SETTINGS_WEBTRANS_DRAFT00:
+ if (!WillNegotiateWebTransport()) {
+ break;
+ }
+ QUIC_DVLOG(1) << ENDPOINT
+ << "SETTINGS_ENABLE_WEBTRANSPORT received with value "
+ << value;
+ if (value != 0 && value != 1) {
+ std::string error_details = absl::StrCat(
+ "received SETTINGS_ENABLE_WEBTRANSPORT with invalid value ",
+ value);
+ QUIC_PEER_BUG(invalid SETTINGS_ENABLE_WEBTRANSPORT value)
+ << ENDPOINT << error_details;
+ CloseConnectionWithDetails(QUIC_HTTP_RECEIVE_SPDY_SETTING,
+ error_details);
+ return false;
+ }
+ peer_supports_webtransport_ = (value == 1);
+ break;
default:
QUIC_DVLOG(1) << ENDPOINT << "Unknown setting identifier " << id
<< " received with value " << value;
@@ -1344,20 +1350,6 @@ void QuicSpdySession::OnCompressedFrameSize(size_t frame_len) {
frame_len_ += frame_len;
}
-void QuicSpdySession::SetHpackEncoderDebugVisitor(
- std::unique_ptr<QuicHpackDebugVisitor> visitor) {
- spdy_framer_.SetEncoderHeaderTableDebugVisitor(
- std::unique_ptr<HeaderTableDebugVisitor>(new HeaderTableDebugVisitor(
- connection()->helper()->GetClock(), std::move(visitor))));
-}
-
-void QuicSpdySession::SetHpackDecoderDebugVisitor(
- std::unique_ptr<QuicHpackDebugVisitor> visitor) {
- h2_deframer_.SetDecoderHeaderTableDebugVisitor(
- std::make_unique<HeaderTableDebugVisitor>(
- connection()->helper()->GetClock(), std::move(visitor)));
-}
-
void QuicSpdySession::CloseConnectionWithDetails(QuicErrorCode error,
const std::string& details) {
connection()->CloseConnection(
@@ -1368,13 +1360,13 @@ bool QuicSpdySession::HasActiveRequestStreams() const {
return GetNumActiveStreams() + num_draining_streams() > 0;
}
-bool QuicSpdySession::ProcessPendingStream(PendingStream* pending) {
+QuicStream* QuicSpdySession::ProcessPendingStream(PendingStream* pending) {
QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
QUICHE_DCHECK(connection()->connected());
struct iovec iov;
if (!pending->sequencer()->GetReadableRegion(&iov)) {
// The first byte hasn't been received yet.
- return false;
+ return nullptr;
}
QuicDataReader reader(static_cast<char*>(iov.iov_base), iov.iov_len);
@@ -1387,7 +1379,7 @@ bool QuicSpdySession::ProcessPendingStream(PendingStream* pending) {
// Mark all bytes consumed in order to close stream.
pending->MarkConsumed(pending->sequencer()->close_offset());
}
- return false;
+ return nullptr;
}
pending->MarkConsumed(stream_type_length);
@@ -1395,72 +1387,87 @@ bool QuicSpdySession::ProcessPendingStream(PendingStream* pending) {
case kControlStream: { // HTTP/3 control stream.
if (receive_control_stream_) {
CloseConnectionOnDuplicateHttp3UnidirectionalStreams("Control");
- return false;
+ return nullptr;
}
auto receive_stream =
std::make_unique<QuicReceiveControlStream>(pending, this);
receive_control_stream_ = receive_stream.get();
ActivateStream(std::move(receive_stream));
- receive_control_stream_->SetUnblocked();
QUIC_DVLOG(1) << ENDPOINT << "Receive Control stream is created";
if (debug_visitor_ != nullptr) {
debug_visitor_->OnPeerControlStreamCreated(
receive_control_stream_->id());
}
- return true;
+ return receive_control_stream_;
}
case kServerPushStream: { // Push Stream.
QuicSpdyStream* stream = CreateIncomingStream(pending);
- stream->SetUnblocked();
- return true;
+ return stream;
}
case kQpackEncoderStream: { // QPACK encoder stream.
if (qpack_encoder_receive_stream_) {
CloseConnectionOnDuplicateHttp3UnidirectionalStreams("QPACK encoder");
- return false;
+ return nullptr;
}
auto encoder_receive = std::make_unique<QpackReceiveStream>(
pending, this, qpack_decoder_->encoder_stream_receiver());
qpack_encoder_receive_stream_ = encoder_receive.get();
ActivateStream(std::move(encoder_receive));
- qpack_encoder_receive_stream_->SetUnblocked();
QUIC_DVLOG(1) << ENDPOINT << "Receive QPACK Encoder stream is created";
if (debug_visitor_ != nullptr) {
debug_visitor_->OnPeerQpackEncoderStreamCreated(
qpack_encoder_receive_stream_->id());
}
- return true;
+ return qpack_encoder_receive_stream_;
}
case kQpackDecoderStream: { // QPACK decoder stream.
if (qpack_decoder_receive_stream_) {
CloseConnectionOnDuplicateHttp3UnidirectionalStreams("QPACK decoder");
- return false;
+ return nullptr;
}
auto decoder_receive = std::make_unique<QpackReceiveStream>(
pending, this, qpack_encoder_->decoder_stream_receiver());
qpack_decoder_receive_stream_ = decoder_receive.get();
ActivateStream(std::move(decoder_receive));
- qpack_decoder_receive_stream_->SetUnblocked();
QUIC_DVLOG(1) << ENDPOINT << "Receive QPACK Decoder stream is created";
if (debug_visitor_ != nullptr) {
debug_visitor_->OnPeerQpackDecoderStreamCreated(
qpack_decoder_receive_stream_->id());
}
- return true;
+ return qpack_decoder_receive_stream_;
}
- default:
- 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());
+ case kWebTransportUnidirectionalStream: {
+ // Note that this checks whether WebTransport is enabled on the receiver
+ // side, as we may receive WebTransport streams before peer's SETTINGS are
+ // received.
+ // TODO(b/184156476): consider whether this means we should drop buffered
+ // streams if we don't receive indication of WebTransport support.
+ if (!WillNegotiateWebTransport()) {
+ // Treat as unknown stream type.
+ break;
}
- pending->StopReading();
+ QUIC_DVLOG(1) << ENDPOINT << "Created an incoming WebTransport stream "
+ << pending->id();
+ auto stream_owned =
+ std::make_unique<WebTransportHttp3UnidirectionalStream>(pending,
+ this);
+ WebTransportHttp3UnidirectionalStream* stream = stream_owned.get();
+ ActivateStream(std::move(stream_owned));
+ return stream;
+ }
+ default:
+ break;
}
- return false;
+ 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());
+ }
+ pending->StopReading();
+ return nullptr;
}
void QuicSpdySession::MaybeInitializeHttp3UnidirectionalStreams() {
@@ -1505,15 +1512,12 @@ void QuicSpdySession::MaybeInitializeHttp3UnidirectionalStreams() {
}
void QuicSpdySession::BeforeConnectionCloseSent() {
- if (!GetQuicReloadableFlag(quic_send_goaway_with_connection_close) ||
- !VersionUsesHttp3(transport_version()) || !IsEncryptionEstablished()) {
+ if (!VersionUsesHttp3(transport_version()) || !IsEncryptionEstablished()) {
return;
}
QUICHE_DCHECK_EQ(perspective(), Perspective::IS_SERVER);
- QUIC_CODE_COUNT(quic_send_goaway_with_connection_close);
-
QuicStreamId stream_id =
GetLargestPeerCreatedStreamId(/*unidirectional = */ false);
@@ -1528,13 +1532,15 @@ void QuicSpdySession::BeforeConnectionCloseSent() {
}
if (last_sent_http3_goaway_id_.has_value() &&
last_sent_http3_goaway_id_.value() <= stream_id) {
- if (goaway_with_max_stream_id_) {
- // A previous GOAWAY frame was sent with smaller stream ID. This is not
- // possible, because this is the only method sending a GOAWAY frame with
- // non-maximal stream ID, and this must only be called once, right
- // before closing connection.
- QUIC_BUG << "GOAWAY frame with smaller ID already sent.";
- }
+ // A previous GOAWAY frame was sent with smaller stream ID. This is not
+ // possible, because this is the only method sending a GOAWAY frame with
+ // non-maximal stream ID, and this must only be called once, right
+ // before closing connection.
+ QUIC_BUG(QuicGoawayFrameAlreadySent)
+ << "Not sending GOAWAY frame with " << stream_id << " because one with "
+ << last_sent_http3_goaway_id_.value() << " already sent on connection "
+ << connection()->connection_id();
+
// MUST not send GOAWAY with identifier larger than previously sent.
// Do not bother sending one with same identifier as before, since GOAWAY
// frames on the control stream are guaranteed to be processed in order.
@@ -1551,38 +1557,6 @@ void QuicSpdySession::OnCanCreateNewOutgoingStream(bool unidirectional) {
}
}
-void QuicSpdySession::SetMaxPushId(PushId max_push_id) {
- QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
- QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, perspective());
- if (max_push_id_.has_value()) {
- QUICHE_DCHECK_GE(max_push_id, max_push_id_.value());
- }
-
- if (!max_push_id_.has_value() && max_push_id == 0) {
- // The default max_push_id is 0. So no need to send out MaxPushId frame.
- return;
- }
-
- ietf_server_push_enabled_ = true;
-
- if (max_push_id_.has_value()) {
- if (max_push_id == max_push_id_.value()) {
- QUIC_DVLOG(1) << "Not changing max_push_id: " << max_push_id;
- return;
- }
-
- QUIC_DVLOG(1) << "Setting max_push_id to: " << max_push_id
- << " from: " << max_push_id_.value();
- } else {
- QUIC_DVLOG(1) << "Setting max_push_id to: " << max_push_id << " from unset";
- }
- max_push_id_ = max_push_id;
-
- if (IsEncryptionEstablished()) {
- SendMaxPushId();
- }
-}
-
bool QuicSpdySession::OnMaxPushIdFrame(PushId max_push_id) {
QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
QUICHE_DCHECK_EQ(Perspective::IS_SERVER, perspective());
@@ -1615,21 +1589,6 @@ bool QuicSpdySession::OnMaxPushIdFrame(PushId max_push_id) {
return true;
}
-void QuicSpdySession::SendMaxPushId() {
- QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
- QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, perspective());
-
- send_control_stream_->SendMaxPushIdFrame(max_push_id_.value());
- http3_max_push_id_sent_ = true;
-}
-
-void QuicSpdySession::EnableServerPush() {
- QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
- QUICHE_DCHECK_EQ(perspective(), Perspective::IS_SERVER);
-
- ietf_server_push_enabled_ = true;
-}
-
bool QuicSpdySession::goaway_received() const {
return VersionUsesHttp3(transport_version())
? last_received_http3_goaway_id_.has_value()
@@ -1642,17 +1601,17 @@ bool QuicSpdySession::goaway_sent() const {
: transport_goaway_sent();
}
-bool QuicSpdySession::CanCreatePushStreamWithId(PushId push_id) {
+bool QuicSpdySession::CanCreatePushStreamWithId(PushId /* push_id */) {
+ // TODO(b/171463363): Remove this method.
QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
- return ietf_server_push_enabled_ && max_push_id_.has_value() &&
- max_push_id_.value() >= push_id;
+ return false;
}
void QuicSpdySession::CloseConnectionOnDuplicateHttp3UnidirectionalStreams(
absl::string_view type) {
- QUIC_PEER_BUG << absl::StrCat("Received a duplicate ", type,
- " stream: Closing connection.");
+ QUIC_PEER_BUG(quic_peer_bug_10360_9) << absl::StrCat(
+ "Received a duplicate ", type, " stream: Closing connection.");
CloseConnectionWithDetails(QUIC_HTTP_DUPLICATE_UNIDIRECTIONAL_STREAM,
absl::StrCat(type, " stream is received twice."));
}
@@ -1703,6 +1662,214 @@ void QuicSpdySession::LogHeaderCompressionRatioHistogram(
}
}
+QuicDatagramFlowId QuicSpdySession::GetNextDatagramFlowId() {
+ QuicDatagramFlowId result = next_available_datagram_flow_id_;
+ next_available_datagram_flow_id_ += kDatagramFlowIdIncrement;
+ return result;
+}
+
+MessageStatus QuicSpdySession::SendHttp3Datagram(QuicDatagramFlowId flow_id,
+ absl::string_view payload) {
+ size_t slice_length =
+ QuicDataWriter::GetVarInt62Len(flow_id) + payload.length();
+ QuicUniqueBufferPtr buffer = MakeUniqueBuffer(
+ connection()->helper()->GetStreamSendBufferAllocator(), slice_length);
+ QuicDataWriter writer(slice_length, buffer.get());
+ if (!writer.WriteVarInt62(flow_id)) {
+ QUIC_BUG(quic_bug_10360_10) << "Failed to write HTTP/3 datagram flow ID";
+ return MESSAGE_STATUS_INTERNAL_ERROR;
+ }
+ if (!writer.WriteBytes(payload.data(), payload.length())) {
+ QUIC_BUG(quic_bug_10360_11) << "Failed to write HTTP/3 datagram payload";
+ return MESSAGE_STATUS_INTERNAL_ERROR;
+ }
+
+ QuicMemSlice slice(std::move(buffer), slice_length);
+ return datagram_queue()->SendOrQueueDatagram(std::move(slice));
+}
+
+void QuicSpdySession::RegisterHttp3FlowId(
+ QuicDatagramFlowId flow_id,
+ QuicSpdySession::Http3DatagramVisitor* visitor) {
+ QUICHE_DCHECK_NE(visitor, nullptr);
+ auto insertion_result = h3_datagram_registrations_.insert({flow_id, visitor});
+ QUIC_BUG_IF(quic_bug_12477_7, !insertion_result.second)
+ << "Attempted to doubly register HTTP/3 flow ID " << flow_id;
+}
+
+void QuicSpdySession::UnregisterHttp3FlowId(QuicDatagramFlowId flow_id) {
+ size_t num_erased = h3_datagram_registrations_.erase(flow_id);
+ QUIC_BUG_IF(quic_bug_12477_8, num_erased != 1)
+ << "Attempted to unregister unknown HTTP/3 flow ID " << flow_id;
+}
+
+void QuicSpdySession::SetMaxTimeInQueueForFlowId(
+ QuicDatagramFlowId /*flow_id*/,
+ QuicTime::Delta max_time_in_queue) {
+ // TODO(b/184598230): implement this in a way that works for multiple sessions
+ // on a same connection.
+ datagram_queue()->SetMaxTimeInQueue(max_time_in_queue);
+}
+
+void QuicSpdySession::OnMessageReceived(absl::string_view message) {
+ QuicSession::OnMessageReceived(message);
+ if (!h3_datagram_supported_) {
+ QUIC_DLOG(ERROR) << "Ignoring unexpected received HTTP/3 datagram";
+ return;
+ }
+ QuicDataReader reader(message);
+ QuicDatagramFlowId flow_id;
+ if (!reader.ReadVarInt62(&flow_id)) {
+ QUIC_DLOG(ERROR) << "Failed to parse flow ID in received HTTP/3 datagram";
+ return;
+ }
+ auto it = h3_datagram_registrations_.find(flow_id);
+ if (it == h3_datagram_registrations_.end()) {
+ // TODO(dschinazi) buffer unknown HTTP/3 datagram flow IDs for a short
+ // period of time in case they were reordered.
+ QUIC_DLOG(ERROR) << "Received unknown HTTP/3 datagram flow ID " << flow_id;
+ return;
+ }
+ absl::string_view payload = reader.ReadRemainingPayload();
+ it->second->OnHttp3Datagram(flow_id, payload);
+}
+
+bool QuicSpdySession::SupportsWebTransport() {
+ return WillNegotiateWebTransport() && h3_datagram_supported_ &&
+ peer_supports_webtransport_;
+}
+
+WebTransportHttp3* QuicSpdySession::GetWebTransportSession(
+ WebTransportSessionId id) {
+ if (!SupportsWebTransport()) {
+ return nullptr;
+ }
+ if (!IsValidWebTransportSessionId(id, version())) {
+ return nullptr;
+ }
+ QuicSpdyStream* connect_stream = GetOrCreateSpdyDataStream(id);
+ if (connect_stream == nullptr) {
+ return nullptr;
+ }
+ return connect_stream->web_transport();
+}
+
+bool QuicSpdySession::ShouldProcessIncomingRequests() {
+ if (!ShouldBufferRequestsUntilSettings()) {
+ return true;
+ }
+
+ return any_settings_received_;
+}
+
+void QuicSpdySession::OnStreamWaitingForClientSettings(QuicStreamId id) {
+ QUICHE_DCHECK(ShouldBufferRequestsUntilSettings());
+ QUICHE_DCHECK(QuicUtils::IsBidirectionalStreamId(id, version()));
+ streams_waiting_for_settings_.insert(id);
+}
+
+void QuicSpdySession::AssociateIncomingWebTransportStreamWithSession(
+ WebTransportSessionId session_id,
+ QuicStreamId stream_id) {
+ if (QuicUtils::IsOutgoingStreamId(version(), stream_id, perspective())) {
+ QUIC_BUG(AssociateIncomingWebTransportStreamWithSession got outgoing stream)
+ << ENDPOINT
+ << "AssociateIncomingWebTransportStreamWithSession() got an outgoing "
+ "stream ID: "
+ << stream_id;
+ return;
+ }
+ WebTransportHttp3* session = GetWebTransportSession(session_id);
+ if (session != nullptr) {
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Successfully associated incoming WebTransport stream "
+ << stream_id << " with session ID " << session_id;
+
+ session->AssociateStream(stream_id);
+ return;
+ }
+ // Evict the oldest streams until we are under the limit.
+ while (buffered_streams_.size() >= kMaxUnassociatedWebTransportStreams) {
+ QUIC_DVLOG(1) << ENDPOINT << "Removing stream "
+ << buffered_streams_.front().stream_id
+ << " from buffered streams as the queue is full.";
+ ResetStream(buffered_streams_.front().stream_id,
+ QUIC_STREAM_WEBTRANSPORT_BUFFERED_STREAMS_LIMIT_EXCEEDED);
+ buffered_streams_.pop_front();
+ }
+ QUIC_DVLOG(1) << ENDPOINT << "Received a WebTransport stream " << stream_id
+ << " for session ID " << session_id
+ << " but cannot associate it; buffering instead.";
+ buffered_streams_.push_back(
+ BufferedWebTransportStream{session_id, stream_id});
+}
+
+void QuicSpdySession::ProcessBufferedWebTransportStreamsForSession(
+ WebTransportHttp3* session) {
+ const WebTransportSessionId session_id = session->id();
+ QUIC_DVLOG(1) << "Processing buffered WebTransport streams for "
+ << session_id;
+ auto it = buffered_streams_.begin();
+ while (it != buffered_streams_.end()) {
+ if (it->session_id == session_id) {
+ QUIC_DVLOG(1) << "Unbuffered and associated WebTransport stream "
+ << it->stream_id << " with session " << it->session_id;
+ session->AssociateStream(it->stream_id);
+ it = buffered_streams_.erase(it);
+ } else {
+ it++;
+ }
+ }
+}
+
+WebTransportHttp3UnidirectionalStream*
+QuicSpdySession::CreateOutgoingUnidirectionalWebTransportStream(
+ WebTransportHttp3* session) {
+ if (!CanOpenNextOutgoingUnidirectionalStream()) {
+ return nullptr;
+ }
+
+ QuicStreamId stream_id = GetNextOutgoingUnidirectionalStreamId();
+ auto stream_owned = std::make_unique<WebTransportHttp3UnidirectionalStream>(
+ stream_id, this, session->id());
+ WebTransportHttp3UnidirectionalStream* stream = stream_owned.get();
+ ActivateStream(std::move(stream_owned));
+ stream->WritePreamble();
+ session->AssociateStream(stream_id);
+ return stream;
+}
+
+QuicSpdyStream* QuicSpdySession::CreateOutgoingBidirectionalWebTransportStream(
+ WebTransportHttp3* session) {
+ QuicSpdyStream* stream = CreateOutgoingBidirectionalStream();
+ if (stream == nullptr) {
+ return nullptr;
+ }
+ QuicStreamId stream_id = stream->id();
+ stream->ConvertToWebTransportDataStream(session->id());
+ if (stream->web_transport_stream() == nullptr) {
+ // An error in ConvertToWebTransportDataStream() would result in
+ // CONNECTION_CLOSE, thus we don't need to do anything here.
+ return nullptr;
+ }
+ session->AssociateStream(stream_id);
+ return stream;
+}
+
+void QuicSpdySession::OnDatagramProcessed(
+ absl::optional<MessageStatus> /*status*/) {
+ // TODO(b/184598230): make this work with multiple datagram flows.
+}
+
+void QuicSpdySession::DatagramObserver::OnDatagramProcessed(
+ absl::optional<MessageStatus> status) {
+ session_->OnDatagramProcessed(status);
+}
+
+bool QuicSpdySession::ShouldNegotiateHttp3Datagram() {
+ return GetQuicReloadableFlag(quic_h3_datagram);
+}
+
#undef ENDPOINT // undef for jumbo builds
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.h
index 3c3d558a1fe..b2004845306 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
@@ -6,10 +6,12 @@
#define QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_SESSION_H_
#include <cstddef>
+#include <list>
#include <memory>
#include <string>
#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "quic/core/http/http_frames.h"
@@ -24,10 +26,12 @@
#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 "spdy/core/http2_frame_decoder_adapter.h"
@@ -37,24 +41,9 @@ namespace test {
class QuicSpdySessionPeer;
} // namespace test
-// QuicHpackDebugVisitor gathers data used for understanding HPACK HoL
-// dynamics. Specifically, it is to help predict the compression
-// penalty of avoiding HoL by chagning how the dynamic table is used.
-// In chromium, the concrete instance populates an UMA
-// histogram with the data.
-class QUIC_EXPORT_PRIVATE QuicHpackDebugVisitor {
- public:
- QuicHpackDebugVisitor();
- QuicHpackDebugVisitor(const QuicHpackDebugVisitor&) = delete;
- QuicHpackDebugVisitor& operator=(const QuicHpackDebugVisitor&) = delete;
-
- virtual ~QuicHpackDebugVisitor();
+class WebTransportHttp3UnidirectionalStream;
- // For each HPACK indexed representation processed, |elapsed| is
- // the time since the corresponding entry was added to the dynamic
- // table.
- virtual void OnUseEntry(QuicTime::Delta elapsed) = 0;
-};
+QUIC_EXPORT_PRIVATE extern const size_t kMaxUnassociatedWebTransportStreams;
class QUIC_EXPORT_PRIVATE Http3DebugVisitor {
public:
@@ -85,12 +74,15 @@ class QUIC_EXPORT_PRIVATE Http3DebugVisitor {
virtual void OnPeerQpackDecoderStreamCreated(QuicStreamId /*stream_id*/) = 0;
// Incoming HTTP/3 frames in ALPS TLS extension.
+ virtual void OnSettingsFrameReceivedViaAlps(const SettingsFrame& /*frame*/) {}
virtual void OnAcceptChFrameReceivedViaAlps(const AcceptChFrame& /*frame*/) {}
// Incoming HTTP/3 frames on the control stream.
+ // TODO(b/171463363): Remove.
virtual void OnCancelPushFrameReceived(const CancelPushFrame& /*frame*/) {}
virtual void OnSettingsFrameReceived(const SettingsFrame& /*frame*/) = 0;
virtual void OnGoAwayFrameReceived(const GoAwayFrame& /*frame*/) {}
+ // TODO(b/171463363): Remove.
virtual void OnMaxPushIdFrameReceived(const MaxPushIdFrame& /*frame*/) {}
virtual void OnPriorityUpdateFrameReceived(
const PriorityUpdateFrame& /*frame*/) {}
@@ -104,10 +96,12 @@ class QUIC_EXPORT_PRIVATE Http3DebugVisitor {
QuicByteCount /*compressed_headers_length*/) {}
virtual void OnHeadersDecoded(QuicStreamId /*stream_id*/,
QuicHeaderList /*headers*/) {}
+ // TODO(b/171463363): Remove.
virtual void OnPushPromiseFrameReceived(QuicStreamId /*stream_id*/,
QuicStreamId /*push_id*/,
QuicByteCount
/*compressed_headers_length*/) {}
+ // TODO(b/171463363): Remove.
virtual void OnPushPromiseDecoded(QuicStreamId /*stream_id*/,
QuicStreamId /*push_id*/,
QuicHeaderList /*headers*/) {}
@@ -120,6 +114,7 @@ class QUIC_EXPORT_PRIVATE Http3DebugVisitor {
// Outgoing HTTP/3 frames on the control stream.
virtual void OnSettingsFrameSent(const SettingsFrame& /*frame*/) = 0;
virtual void OnGoAwayFrameSent(QuicStreamId /*stream_id*/) {}
+ // TODO(b/171463363): Remove.
virtual void OnMaxPushIdFrameSent(const MaxPushIdFrame& /*frame*/) {}
virtual void OnPriorityUpdateFrameSent(const PriorityUpdateFrame& /*frame*/) {
}
@@ -130,6 +125,7 @@ class QUIC_EXPORT_PRIVATE Http3DebugVisitor {
virtual void OnHeadersFrameSent(
QuicStreamId /*stream_id*/,
const spdy::SpdyHeaderBlock& /*header_block*/) {}
+ // TODO(b/171463363): Remove.
virtual void OnPushPromiseFrameSent(
QuicStreamId /*stream_id*/,
QuicStreamId
@@ -243,10 +239,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// before encryption gets established.
void SendHttp3GoAway(QuicErrorCode error_code, const std::string& reason);
- // Same as SendHttp3GoAway(). TODO(bnc): remove when
- // gfe2_reloadable_flag_quic_goaway_with_max_stream_id flag is deprecated.
- void SendHttp3Shutdown();
-
// Write |headers| for |promised_stream_id| on |original_stream_id| in a
// PUSH_PROMISE frame to peer.
virtual void WritePushPromise(QuicStreamId original_stream_id,
@@ -262,11 +254,7 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// Returns whether server push is enabled.
// For a Google QUIC client this always returns false.
// For a Google QUIC server this is set by incoming SETTINGS_ENABLE_PUSH.
- // For an IETF QUIC client this returns true if SetMaxPushId() has ever been
- // called.
- // For an IETF QUIC server this returns true if EnableServerPush() has been
- // called and the server has received at least one MAX_PUSH_ID frame from the
- // client.
+ // For an IETF QUIC client or server this returns false.
bool server_push_enabled() const;
// Called when the control stream receives HTTP/3 SETTINGS.
@@ -274,9 +262,18 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// cached values, true otherwise.
virtual bool OnSettingsFrame(const SettingsFrame& frame);
- // Called when a SETTINGS is parsed from an incoming SETTINGS frame.
- // Returns false in case of 0-RTT if received SETTINGS is incompatible with
- // cached value, true otherwise.
+ // Called when an HTTP/3 SETTINGS frame is received via ALPS.
+ // Returns an error message if an error has occurred, or nullopt otherwise.
+ // May or may not close the connection on error.
+ absl::optional<std::string> OnSettingsFrameViaAlps(
+ const SettingsFrame& frame);
+
+ // Called when a setting is parsed from a SETTINGS frame received on the
+ // control stream or from cached application state.
+ // Returns true on success.
+ // Returns false if received setting is incompatible with cached value (in
+ // case of 0-RTT) or with previously received value (in case of ALPS).
+ // Also closes the connection on error.
bool OnSetting(uint64_t id, uint64_t value);
// Return true if this session wants to release headers stream's buffer
@@ -322,6 +319,7 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
void OnCompressedFrameSize(size_t frame_len);
// Called when a PUSH_PROMISE frame has been received.
+ // TODO(b/171463363): Remove.
void OnPushPromise(spdy::SpdyStreamId stream_id,
spdy::SpdyStreamId promised_stream_id);
@@ -334,34 +332,16 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// those streams are not initialized yet.
void OnCanCreateNewOutgoingStream(bool unidirectional) override;
- // Sets |max_push_id_| and sends a MAX_PUSH_ID frame.
- // This method must only be called if protocol is IETF QUIC and perspective is
- // client. |max_push_id| must be greater than or equal to current
- // |max_push_id_|.
- void SetMaxPushId(PushId max_push_id);
-
// Sets |max_push_id_|.
// This method must only be called if protocol is IETF QUIC and perspective is
// server. It must only be called if a MAX_PUSH_ID frame is received.
// Returns whether |max_push_id| is greater than or equal to current
// |max_push_id_|.
+ // TODO(b/171463363): Remove.
bool OnMaxPushIdFrame(PushId max_push_id);
- // Enables server push.
- // Must only be called when using IETF QUIC, for which server push is disabled
- // by default. Server push defaults to enabled and cannot be disabled for
- // Google QUIC.
- // Must only be called for a server. A client can effectively disable push by
- // never calling SetMaxPushId().
- void EnableServerPush();
-
- // Returns true if push is enabled and a push with |push_id| can be created.
- // For a server this means that EnableServerPush() has been called, at least
- // one MAX_PUSH_ID frame has been received, and the largest received
- // MAX_PUSH_ID value is greater than or equal to |push_id|.
- // For a client this means that SetMaxPushId() has been called with
- // |max_push_id| greater than or equal to |push_id|.
- // Must only be called when using IETF QUIC.
+ // TODO(b/171463363): Remove.
+ // Returns false.
bool CanCreatePushStreamWithId(PushId push_id);
int32_t destruction_indicator() const { return destruction_indicator_; }
@@ -417,6 +397,99 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// extension.
virtual void OnAcceptChFrameReceivedViaAlps(const AcceptChFrame& /*frame*/);
+ // Generates a new HTTP/3 datagram flow ID.
+ QuicDatagramFlowId GetNextDatagramFlowId();
+
+ // Whether HTTP/3 datagrams are supported on this session, based on received
+ // SETTINGS.
+ bool h3_datagram_supported() const { return h3_datagram_supported_; }
+
+ // Sends an HTTP/3 datagram. The flow ID is not part of |payload|.
+ MessageStatus SendHttp3Datagram(QuicDatagramFlowId flow_id,
+ absl::string_view payload);
+
+ class QUIC_EXPORT_PRIVATE Http3DatagramVisitor {
+ public:
+ virtual ~Http3DatagramVisitor() {}
+
+ // Called when an HTTP/3 datagram is received. |payload| does not contain
+ // the flow ID.
+ virtual void OnHttp3Datagram(QuicDatagramFlowId flow_id,
+ absl::string_view payload) = 0;
+ };
+
+ // Registers |visitor| to receive HTTP/3 datagrams for flow ID |flow_id|. This
+ // must not be called on a previously register flow ID without first calling
+ // UnregisterHttp3FlowId. |visitor| must be valid until a corresponding call
+ // to UnregisterHttp3FlowId. The flow ID must be unregistered before the
+ // QuicSpdySession is destroyed.
+ void RegisterHttp3FlowId(QuicDatagramFlowId flow_id,
+ Http3DatagramVisitor* visitor);
+
+ // Unregister a given HTTP/3 datagram flow ID.
+ void UnregisterHttp3FlowId(QuicDatagramFlowId flow_id);
+
+ // Sets max time in queue for a specified datagram flow ID.
+ void SetMaxTimeInQueueForFlowId(QuicDatagramFlowId flow_id,
+ QuicTime::Delta max_time_in_queue);
+
+ // Override from QuicSession to support HTTP/3 datagrams.
+ void OnMessageReceived(absl::string_view message) override;
+
+ // Indicates whether the HTTP/3 session supports WebTransport.
+ bool SupportsWebTransport();
+
+ // Indicates whether the HTTP/3 session will indicate WebTransport support to
+ // the peer.
+ bool WillNegotiateWebTransport();
+
+ // Returns a WebTransport session by its session ID. Returns nullptr if no
+ // session is associated with the given ID.
+ WebTransportHttp3* GetWebTransportSession(WebTransportSessionId id);
+
+ // If true, no data on bidirectional streams will be processed by the server
+ // until the SETTINGS are received. Only works for HTTP/3.
+ bool ShouldBufferRequestsUntilSettings() {
+ return version().UsesHttp3() && perspective() == Perspective::IS_SERVER &&
+ WillNegotiateWebTransport();
+ }
+
+ // Returns if the incoming bidirectional streams should process data. This is
+ // usually true, but in certain cases we would want to wait until the settings
+ // are received.
+ bool ShouldProcessIncomingRequests();
+
+ void OnStreamWaitingForClientSettings(QuicStreamId id);
+
+ // Links the specified stream with a WebTransport session. If the session is
+ // not present, it is buffered until a corresponding stream is found.
+ void AssociateIncomingWebTransportStreamWithSession(
+ WebTransportSessionId session_id,
+ QuicStreamId stream_id);
+
+ void ProcessBufferedWebTransportStreamsForSession(WebTransportHttp3* session);
+
+ bool CanOpenOutgoingUnidirectionalWebTransportStream(
+ WebTransportSessionId /*id*/) {
+ return CanOpenNextOutgoingUnidirectionalStream();
+ }
+ bool CanOpenOutgoingBidirectionalWebTransportStream(
+ WebTransportSessionId /*id*/) {
+ return CanOpenNextOutgoingBidirectionalStream();
+ }
+
+ // Creates an outgoing unidirectional WebTransport stream. Returns nullptr if
+ // the stream cannot be created due to flow control or some other reason.
+ WebTransportHttp3UnidirectionalStream*
+ CreateOutgoingUnidirectionalWebTransportStream(WebTransportHttp3* session);
+
+ // Creates an outgoing bidirectional WebTransport stream. Returns nullptr if
+ // the stream cannot be created due to flow control or some other reason.
+ QuicSpdyStream* CreateOutgoingBidirectionalWebTransportStream(
+ WebTransportHttp3* session);
+
+ QuicSpdyStream* GetOrCreateSpdyDataStream(const QuicStreamId stream_id);
+
protected:
// Override CreateIncomingStream(), CreateOutgoingBidirectionalStream() and
// CreateOutgoingUnidirectionalStream() with QuicSpdyStream return type to
@@ -426,8 +499,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
virtual QuicSpdyStream* CreateOutgoingBidirectionalStream() = 0;
virtual QuicSpdyStream* CreateOutgoingUnidirectionalStream() = 0;
- QuicSpdyStream* GetOrCreateSpdyDataStream(const QuicStreamId stream_id);
-
// If an incoming stream can be created, return true.
virtual bool ShouldCreateIncomingStream(QuicStreamId id) = 0;
@@ -436,16 +507,20 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
virtual bool ShouldCreateOutgoingBidirectionalStream() = 0;
virtual bool ShouldCreateOutgoingUnidirectionalStream() = 0;
+ // Indicates whether the underlying backend can accept and process
+ // WebTransport sessions over HTTP/3.
+ virtual bool ShouldNegotiateWebTransport();
+
// Returns true if there are open HTTP requests.
bool ShouldKeepConnectionAlive() const override;
// Overridden to buffer incoming unidirectional streams for version 99.
bool UsesPendingStreams() const override;
- // Overridden to Process HTTP/3 stream types. H/3 streams will be created from
- // pending streams accordingly if the stream type can be read. Returns true if
- // unidirectional streams are created.
- bool ProcessPendingStream(PendingStream* pending) override;
+ // Processes incoming unidirectional streams; parses the stream type, and
+ // creates a new stream of the corresponding type. Returns the pointer to the
+ // newly created stream, or nullptr if the stream type is not yet available.
+ QuicStream* ProcessPendingStream(PendingStream* pending) override;
size_t WriteHeadersOnHeadersStreamImpl(
QuicStreamId id,
@@ -460,20 +535,10 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
EncryptionLevel level,
std::unique_ptr<QuicEncrypter> encrypter) override;
- // Optional, enables instrumentation related to go/quic-hpack.
- void SetHpackEncoderDebugVisitor(
- std::unique_ptr<QuicHpackDebugVisitor> visitor);
- void SetHpackDecoderDebugVisitor(
- std::unique_ptr<QuicHpackDebugVisitor> visitor);
-
// Sets the maximum size of the header compression table spdy_framer_ is
// willing to use to encode header blocks.
void UpdateHeaderEncoderTableSize(uint32_t value);
- // Called when SETTINGS_ENABLE_PUSH is received, only supported on
- // server side.
- void UpdateEnableServerPush(bool value);
-
bool IsConnected() { return connection()->connected(); }
const QuicReceiveControlStream* receive_control_stream() const {
@@ -488,11 +553,33 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// QuicConnectionVisitorInterface method.
void BeforeConnectionCloseSent() override;
+ // Called whenever a datagram is dequeued or dropped from datagram_queue().
+ virtual void OnDatagramProcessed(absl::optional<MessageStatus> status);
+
+ // Returns true if HTTP/3 datagram extension should be supported.
+ virtual bool ShouldNegotiateHttp3Datagram();
+
private:
friend class test::QuicSpdySessionPeer;
class SpdyFramerVisitor;
+ // Proxies OnDatagramProcessed() calls to the session.
+ class QUIC_EXPORT_PRIVATE DatagramObserver
+ : public QuicDatagramQueue::Observer {
+ public:
+ explicit DatagramObserver(QuicSpdySession* session) : session_(session) {}
+ void OnDatagramProcessed(absl::optional<MessageStatus> status) override;
+
+ private:
+ QuicSpdySession* session_; // not owned
+ };
+
+ struct QUIC_EXPORT_PRIVATE BufferedWebTransportStream {
+ WebTransportSessionId session_id;
+ QuicStreamId stream_id;
+ };
+
// The following methods are called by the SimpleVisitor.
// Called when a HEADERS frame has been received.
@@ -515,9 +602,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// established, and again when 1-RTT keys are available.
void SendInitialData();
- // Send a MAX_PUSH_ID frame. Used in IETF QUIC only.
- void SendMaxPushId();
-
void FillSettingsFrame();
std::unique_ptr<QpackEncoder> qpack_encoder_;
@@ -585,6 +669,7 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// after encryption is established, the push ID in the most recently sent
// MAX_PUSH_ID frame.
// Once set, never goes back to unset.
+ // TODO(b/171463363): Remove.
absl::optional<PushId> max_push_id_;
// Not owned by the session.
@@ -603,11 +688,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// Defaults to true.
bool server_push_enabled_;
- // Used in IETF QUIC only. Defaults to false.
- // Server push is enabled for a server by calling EnableServerPush().
- // Server push is enabled for a client by calling SetMaxPushId().
- bool ietf_server_push_enabled_;
-
// 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_;
@@ -615,13 +695,31 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// frame has been sent yet.
absl::optional<uint64_t> last_sent_http3_goaway_id_;
- // Only used by a client, only with IETF QUIC. True if a MAX_PUSH_ID frame
- // has been sent, in which case |max_push_id_| has the value sent in the most
- // recent MAX_PUSH_ID frame. Once true, never goes back to false.
- bool http3_max_push_id_sent_;
+ // Value of the smallest unused HTTP/3 datagram flow ID that this endpoint's
+ // datagram flow ID allocation service will use next.
+ QuicDatagramFlowId next_available_datagram_flow_id_;
+
+ // Whether both this endpoint and our peer support HTTP/3 datagrams.
+ bool h3_datagram_supported_ = false;
+
+ // Whether the peer has indicated WebTransport support.
+ bool peer_supports_webtransport_ = false;
+
+ absl::flat_hash_map<QuicDatagramFlowId, Http3DatagramVisitor*>
+ h3_datagram_registrations_;
+
+ // Whether any settings have been received, either from the peer or from a
+ // session ticket.
+ bool any_settings_received_ = false;
+
+ // If ShouldBufferRequestsUntilSettings() is true, all streams that are
+ // blocked by that are tracked here.
+ absl::flat_hash_set<QuicStreamId> streams_waiting_for_settings_;
- // Latched value of reloadable flag quic_goaway_with_max_stream_id.
- const bool goaway_with_max_stream_id_;
+ // WebTransport streams that do not have a session associated with them.
+ // Limited to kMaxUnassociatedWebTransportStreams; when the list is full,
+ // oldest streams are evicated first.
+ std::list<BufferedWebTransportStream> buffered_streams_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc
index c2ab731e948..d8bfa782aa7 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
@@ -11,6 +11,7 @@
#include <utility>
#include "absl/base/macros.h"
+#include "absl/memory/memory.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
@@ -20,6 +21,8 @@
#include "quic/core/frames/quic_streams_blocked_frame.h"
#include "quic/core/http/http_constants.h"
#include "quic/core/http/http_encoder.h"
+#include "quic/core/http/quic_header_list.h"
+#include "quic/core/http/web_transport_http3.h"
#include "quic/core/qpack/qpack_header_table.h"
#include "quic/core/quic_config.h"
#include "quic/core/quic_crypto_stream.h"
@@ -33,7 +36,6 @@
#include "quic/platform/api/quic_expect_bug.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_map_util.h"
-#include "quic/platform/api/quic_ptr_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"
@@ -48,6 +50,7 @@
#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"
using spdy::kV3HighestPriority;
@@ -60,6 +63,7 @@ using spdy::SpdySerializedFrame;
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::AtLeast;
+using ::testing::ElementsAre;
using ::testing::InSequence;
using ::testing::Invoke;
using ::testing::Return;
@@ -254,14 +258,14 @@ class TestSession : public QuicSpdySession {
TestStream* CreateOutgoingBidirectionalStream() override {
TestStream* stream = new TestStream(GetNextOutgoingBidirectionalStreamId(),
this, BIDIRECTIONAL);
- ActivateStream(QuicWrapUnique(stream));
+ ActivateStream(absl::WrapUnique(stream));
return stream;
}
TestStream* CreateOutgoingUnidirectionalStream() override {
TestStream* stream = new TestStream(GetNextOutgoingUnidirectionalStreamId(),
this, WRITE_UNIDIRECTIONAL);
- ActivateStream(QuicWrapUnique(stream));
+ ActivateStream(absl::WrapUnique(stream));
return stream;
}
@@ -279,7 +283,7 @@ class TestSession : public QuicSpdySession {
id, this,
DetermineStreamType(id, connection()->version(), perspective(),
/*is_incoming=*/true, BIDIRECTIONAL));
- ActivateStream(QuicWrapUnique(stream));
+ ActivateStream(absl::WrapUnique(stream));
return stream;
}
}
@@ -290,7 +294,7 @@ class TestSession : public QuicSpdySession {
pending, this,
DetermineStreamType(id, connection()->version(), perspective(),
/*is_incoming=*/true, BIDIRECTIONAL));
- ActivateStream(QuicWrapUnique(stream));
+ ActivateStream(absl::WrapUnique(stream));
return stream;
}
@@ -351,6 +355,9 @@ class TestSession : public QuicSpdySession {
GetEncryptionLevelToSendApplicationData());
}
+ bool ShouldNegotiateWebTransport() override { return supports_webtransport_; }
+ void set_supports_webtransport(bool value) { supports_webtransport_ = value; }
+
MOCK_METHOD(void, OnAcceptChFrame, (const AcceptChFrame&), (override));
using QuicSession::closed_streams;
@@ -362,6 +369,7 @@ class TestSession : public QuicSpdySession {
StrictMock<TestCryptoStream> crypto_stream_;
bool writev_consumes_all_data_;
+ bool supports_webtransport_ = false;
};
class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
@@ -442,6 +450,8 @@ class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
closed_streams_.insert(id);
}
+ ParsedQuicVersion version() const { return connection_->version(); }
+
QuicTransportVersion transport_version() const {
return connection_->transport_version();
}
@@ -473,13 +483,27 @@ class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
return std::string(priority_buffer.get(), priority_frame_length);
}
+ // TODO(b/171463363): Remove.
std::string SerializeMaxPushIdFrame(PushId push_id) {
- MaxPushIdFrame max_push_id_frame;
- max_push_id_frame.push_id = push_id;
- std::unique_ptr<char[]> buffer;
- QuicByteCount frame_length =
- HttpEncoder::SerializeMaxPushIdFrame(max_push_id_frame, &buffer);
- return std::string(buffer.get(), frame_length);
+ const QuicByteCount payload_length =
+ QuicDataWriter::GetVarInt62Len(push_id);
+
+ const QuicByteCount total_length =
+ QuicDataWriter::GetVarInt62Len(
+ static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID)) +
+ QuicDataWriter::GetVarInt62Len(payload_length) +
+ QuicDataWriter::GetVarInt62Len(push_id);
+
+ std::string max_push_id_frame(total_length, '\0');
+ QuicDataWriter writer(total_length, &*max_push_id_frame.begin());
+
+ QUICHE_CHECK(writer.WriteVarInt62(
+ static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID)));
+ QUICHE_CHECK(writer.WriteVarInt62(payload_length));
+ QUICHE_CHECK(writer.WriteVarInt62(push_id));
+ QUICHE_CHECK_EQ(0u, writer.remaining());
+
+ return max_push_id_frame;
}
QuicStreamId StreamCountToId(QuicStreamCount stream_count,
@@ -518,6 +542,55 @@ class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
testing::Mock::VerifyAndClearExpectations(connection_);
}
+ void ReceiveWebTransportSettings() {
+ SettingsFrame settings;
+ settings.values[SETTINGS_H3_DATAGRAM] = 1;
+ settings.values[SETTINGS_WEBTRANS_DRAFT00] = 1;
+ std::string data =
+ std::string(1, kControlStream) + EncodeSettings(settings);
+ QuicStreamId control_stream_id =
+ session_.perspective() == Perspective::IS_SERVER
+ ? GetNthClientInitiatedUnidirectionalStreamId(transport_version(),
+ 3)
+ : GetNthServerInitiatedUnidirectionalStreamId(transport_version(),
+ 3);
+ QuicStreamFrame frame(control_stream_id, /*fin=*/false, /*offset=*/0, data);
+ session_.OnStreamFrame(frame);
+ }
+
+ 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);
+ QuicSpdyStream* stream =
+ static_cast<QuicSpdyStream*>(session_.GetOrCreateStream(session_id));
+ QuicHeaderList headers;
+ headers.OnHeaderBlockStart();
+ headers.OnHeader(":method", "CONNECT");
+ headers.OnHeader(":protocol", "webtransport");
+ headers.OnHeader("datagram-flow-id",
+ absl::StrCat(session_.GetNextDatagramFlowId()));
+ stream->OnStreamHeaderList(/*fin=*/true, 0, headers);
+ WebTransportHttp3* web_transport =
+ session_.GetWebTransportSession(session_id);
+ ASSERT_TRUE(web_transport != nullptr);
+ spdy::SpdyHeaderBlock header_block;
+ web_transport->HeadersReceived(header_block);
+ }
+
+ void ReceiveWebTransportUnidirectionalStream(WebTransportSessionId session_id,
+ QuicStreamId stream_id) {
+ char buffer[256];
+ QuicDataWriter data_writer(sizeof(buffer), buffer);
+ ASSERT_TRUE(data_writer.WriteVarInt62(kWebTransportUnidirectionalStream));
+ ASSERT_TRUE(data_writer.WriteVarInt62(session_id));
+ ASSERT_TRUE(data_writer.WriteStringPiece("test data"));
+ std::string data(buffer, data_writer.length());
+ QuicStreamFrame frame(stream_id, /*fin=*/false, /*offset=*/0, data);
+ session_.OnStreamFrame(frame);
+ }
+
MockQuicConnectionHelper helper_;
MockAlarmFactory alarm_factory_;
StrictMock<MockQuicConnection>* connection_;
@@ -1130,15 +1203,8 @@ TEST_P(QuicSpdySessionTestServer, SendHttp3GoAway) {
EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
- if (GetQuicReloadableFlag(quic_goaway_with_max_stream_id)) {
- // Send max stream id (currently 32 bits).
- EXPECT_CALL(debug_visitor, OnGoAwayFrameSent(/* stream_id = */ 0xfffffffc));
- } else {
- // No client-initiated stream has been received, therefore a GOAWAY frame
- // with stream ID = 0 is sent to notify the client that all requests can be
- // retried on a different connection.
- EXPECT_CALL(debug_visitor, OnGoAwayFrameSent(/* stream_id = */ 0));
- }
+ // Send max stream id (currently 32 bits).
+ EXPECT_CALL(debug_visitor, OnGoAwayFrameSent(/* stream_id = */ 0xfffffffc));
session_.SendHttp3GoAway(QUIC_PEER_GOING_AWAY, "Goaway");
EXPECT_TRUE(session_.goaway_sent());
@@ -1181,15 +1247,8 @@ TEST_P(QuicSpdySessionTestServer, SendHttp3GoAwayAfterStreamIsCreated) {
EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
- if (GetQuicReloadableFlag(quic_goaway_with_max_stream_id)) {
- // Send max stream id (currently 32 bits).
- EXPECT_CALL(debug_visitor, OnGoAwayFrameSent(/* stream_id = */ 0xfffffffc));
- } else {
- // The first stream, of kTestStreamId = 0, could already have been
- // processed. A GOAWAY frame is sent to notify the client that requests
- // starting with stream ID = 4 can be retried on a different connection.
- EXPECT_CALL(debug_visitor, OnGoAwayFrameSent(/* stream_id = */ 4));
- }
+ // Send max stream id (currently 32 bits).
+ EXPECT_CALL(debug_visitor, OnGoAwayFrameSent(/* stream_id = */ 0xfffffffc));
session_.SendHttp3GoAway(QUIC_PEER_GOING_AWAY, "Goaway");
EXPECT_TRUE(session_.goaway_sent());
@@ -1198,59 +1257,6 @@ TEST_P(QuicSpdySessionTestServer, SendHttp3GoAwayAfterStreamIsCreated) {
session_.SendHttp3GoAway(QUIC_PEER_GOING_AWAY, "Goaway");
}
-TEST_P(QuicSpdySessionTestServer, SendHttp3Shutdown) {
- if (GetQuicReloadableFlag(quic_goaway_with_max_stream_id)) {
- return;
- }
-
- if (!VersionUsesHttp3(transport_version())) {
- return;
- }
-
- CompleteHandshake();
- StrictMock<MockHttp3DebugVisitor> debug_visitor;
- session_.set_debug_visitor(&debug_visitor);
-
- EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
- .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
- EXPECT_CALL(debug_visitor, OnGoAwayFrameSent(_));
- session_.SendHttp3Shutdown();
- EXPECT_TRUE(session_.goaway_sent());
-
- const QuicStreamId kTestStreamId =
- GetNthClientInitiatedBidirectionalStreamId(transport_version(), 0);
- EXPECT_CALL(*connection_, OnStreamReset(kTestStreamId, _)).Times(0);
- EXPECT_TRUE(session_.GetOrCreateStream(kTestStreamId));
-}
-
-TEST_P(QuicSpdySessionTestServer, SendHttp3GoAwayAfterShutdownNotice) {
- if (GetQuicReloadableFlag(quic_goaway_with_max_stream_id)) {
- return;
- }
-
- if (!VersionUsesHttp3(transport_version())) {
- return;
- }
-
- CompleteHandshake();
- StrictMock<MockHttp3DebugVisitor> debug_visitor;
- session_.set_debug_visitor(&debug_visitor);
-
- EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
- .Times(2)
- .WillRepeatedly(Return(WriteResult(WRITE_STATUS_OK, 0)));
- EXPECT_CALL(debug_visitor, OnGoAwayFrameSent(_)).Times(2);
-
- session_.SendHttp3Shutdown();
- EXPECT_TRUE(session_.goaway_sent());
- session_.SendHttp3GoAway(QUIC_PEER_GOING_AWAY, "Goaway");
-
- const QuicStreamId kTestStreamId =
- GetNthClientInitiatedBidirectionalStreamId(transport_version(), 0);
- EXPECT_CALL(*connection_, OnStreamReset(kTestStreamId, _)).Times(0);
- EXPECT_TRUE(session_.GetOrCreateStream(kTestStreamId));
-}
-
TEST_P(QuicSpdySessionTestServer, DoNotSendGoAwayTwice) {
CompleteHandshake();
if (VersionHasIetfQuicFrames(transport_version())) {
@@ -1833,6 +1839,7 @@ TEST_P(QuicSpdySessionTestServer, DrainingStreamsDoNotCountAsOpened) {
}
}
+// TODO(b/171463363): Remove.
TEST_P(QuicSpdySessionTestServer, ReduceMaxPushId) {
if (!VersionUsesHttp3(transport_version())) {
return;
@@ -2924,12 +2931,12 @@ TEST_P(QuicSpdySessionTestClient, IgnoreCancelPush) {
EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(_));
session_.OnStreamFrame(data2);
- CancelPushFrame cancel_push{/* push_id = */ 0};
- std::unique_ptr<char[]> buffer;
- auto frame_length =
- HttpEncoder::SerializeCancelPushFrame(cancel_push, &buffer);
+ std::string cancel_push_frame = absl::HexStringToBytes(
+ "03" // CANCEL_PUSH
+ "01" // length
+ "00"); // push ID
QuicStreamFrame data3(receive_control_stream_id, /* fin = */ false, offset,
- absl::string_view(buffer.get(), frame_length));
+ cancel_push_frame);
EXPECT_CALL(debug_visitor, OnCancelPushFrameReceived(_));
session_.OnStreamFrame(data3);
}
@@ -3135,12 +3142,12 @@ TEST_P(QuicSpdySessionTestServer, IgnoreCancelPush) {
EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(_));
session_.OnStreamFrame(data2);
- CancelPushFrame cancel_push{/* push_id = */ 0};
- std::unique_ptr<char[]> buffer;
- auto frame_length =
- HttpEncoder::SerializeCancelPushFrame(cancel_push, &buffer);
+ std::string cancel_push_frame = absl::HexStringToBytes(
+ "03" // CANCEL_PUSH
+ "01" // length
+ "00"); // push ID
QuicStreamFrame data3(receive_control_stream_id, /* fin = */ false, offset,
- absl::string_view(buffer.get(), frame_length));
+ cancel_push_frame);
EXPECT_CALL(debug_visitor, OnCancelPushFrameReceived(_));
session_.OnStreamFrame(data3);
}
@@ -3175,13 +3182,11 @@ TEST_P(QuicSpdySessionTestServer, Http3GoAwayWhenClosingConnection) {
EXPECT_EQ(stream_id, QuicSessionPeer::GetLargestPeerCreatedStreamId(
&session_, /*unidirectional = */ false));
- if (GetQuicReloadableFlag(quic_send_goaway_with_connection_close)) {
- // Stream with stream_id is already received and potentially processed,
- // therefore a GOAWAY frame is sent with the next stream ID.
- EXPECT_CALL(debug_visitor,
- OnGoAwayFrameSent(
- stream_id + QuicUtils::StreamIdDelta(transport_version())));
- }
+ // Stream with stream_id is already received and potentially processed,
+ // therefore a GOAWAY frame is sent with the next stream ID.
+ EXPECT_CALL(debug_visitor,
+ OnGoAwayFrameSent(stream_id +
+ QuicUtils::StreamIdDelta(transport_version())));
// Close connection.
EXPECT_CALL(*writer_, WritePacket(_, _, _, _, _))
@@ -3197,25 +3202,6 @@ TEST_P(QuicSpdySessionTestServer, Http3GoAwayWhenClosingConnection) {
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
-TEST_P(QuicSpdySessionTestClient, SendInitialMaxPushIdIfSet) {
- if (!VersionUsesHttp3(transport_version())) {
- return;
- }
-
- StrictMock<MockHttp3DebugVisitor> debug_visitor;
- session_.set_debug_visitor(&debug_visitor);
-
- const PushId max_push_id = 5;
- session_.SetMaxPushId(max_push_id);
-
- InSequence s;
- EXPECT_CALL(debug_visitor, OnSettingsFrameSent(_));
- const MaxPushIdFrame max_push_id_frame{max_push_id};
- EXPECT_CALL(debug_visitor, OnMaxPushIdFrameSent(max_push_id_frame));
-
- CompleteHandshake();
-}
-
TEST_P(QuicSpdySessionTestClient, DoNotSendInitialMaxPushIdIfNotSet) {
if (!VersionUsesHttp3(transport_version())) {
return;
@@ -3230,21 +3216,6 @@ TEST_P(QuicSpdySessionTestClient, DoNotSendInitialMaxPushIdIfNotSet) {
CompleteHandshake();
}
-TEST_P(QuicSpdySessionTestClient, DoNotSendInitialMaxPushIdIfSetToDefaut) {
- if (!VersionUsesHttp3(transport_version())) {
- return;
- }
-
- StrictMock<MockHttp3DebugVisitor> debug_visitor;
- session_.set_debug_visitor(&debug_visitor);
-
- session_.SetMaxPushId(0);
-
- InSequence s;
- EXPECT_CALL(debug_visitor, OnSettingsFrameSent(_));
- CompleteHandshake();
-}
-
TEST_P(QuicSpdySessionTestClient, ReceiveSpdySettingInHttp3) {
if (!VersionUsesHttp3(transport_version())) {
return;
@@ -3268,10 +3239,6 @@ TEST_P(QuicSpdySessionTestClient, ReceiveAcceptChFrame) {
return;
}
- if (!GetQuicReloadableFlag(quic_parse_accept_ch_frame)) {
- return;
- }
-
StrictMock<MockHttp3DebugVisitor> debug_visitor;
session_.set_debug_visitor(&debug_visitor);
@@ -3330,11 +3297,9 @@ TEST_P(QuicSpdySessionTestClient, AcceptChViaAlps) {
"03" // length of value
"626172"); // value "bar"
- if (GetQuicReloadableFlag(quic_parse_accept_ch_frame)) {
- AcceptChFrame expected_accept_ch_frame{{{"foo", "bar"}}};
- EXPECT_CALL(debug_visitor,
- OnAcceptChFrameReceivedViaAlps(expected_accept_ch_frame));
- }
+ AcceptChFrame expected_accept_ch_frame{{{"foo", "bar"}}};
+ EXPECT_CALL(debug_visitor,
+ OnAcceptChFrameReceivedViaAlps(expected_accept_ch_frame));
auto error = session_.OnAlpsData(
reinterpret_cast<const uint8_t*>(serialized_accept_ch_frame.data()),
@@ -3375,6 +3340,408 @@ TEST_P(QuicSpdySessionTestClient, AlpsIncompleteFrame) {
EXPECT_EQ("incomplete HTTP/3 frame", error.value());
}
+// After receiving a SETTINGS frame via ALPS,
+// another SETTINGS frame is still allowed on control frame.
+TEST_P(QuicSpdySessionTestClient, SettingsViaAlpsThenOnControlStream) {
+ if (!VersionUsesHttp3(transport_version())) {
+ return;
+ }
+
+ QpackEncoder* qpack_encoder = session_.qpack_encoder();
+ EXPECT_EQ(0u, qpack_encoder->MaximumDynamicTableCapacity());
+ EXPECT_EQ(0u, qpack_encoder->maximum_blocked_streams());
+
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_.set_debug_visitor(&debug_visitor);
+
+ std::string serialized_settings_frame1 = absl::HexStringToBytes(
+ "04" // type (SETTINGS)
+ "05" // length
+ "01" // SETTINGS_QPACK_MAX_TABLE_CAPACITY
+ "4400" // 0x0400 = 1024
+ "07" // SETTINGS_QPACK_BLOCKED_STREAMS
+ "20"); // 0x20 = 32
+
+ SettingsFrame expected_settings_frame1{
+ {{SETTINGS_QPACK_MAX_TABLE_CAPACITY, 1024},
+ {SETTINGS_QPACK_BLOCKED_STREAMS, 32}}};
+ EXPECT_CALL(debug_visitor,
+ OnSettingsFrameReceivedViaAlps(expected_settings_frame1));
+
+ auto error = session_.OnAlpsData(
+ reinterpret_cast<const uint8_t*>(serialized_settings_frame1.data()),
+ serialized_settings_frame1.size());
+ EXPECT_FALSE(error);
+
+ EXPECT_EQ(1024u, qpack_encoder->MaximumDynamicTableCapacity());
+ EXPECT_EQ(32u, qpack_encoder->maximum_blocked_streams());
+
+ const QuicStreamId control_stream_id =
+ GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
+ EXPECT_CALL(debug_visitor, OnPeerControlStreamCreated(control_stream_id));
+
+ std::string stream_type = absl::HexStringToBytes("00");
+ session_.OnStreamFrame(QuicStreamFrame(control_stream_id, /* fin = */ false,
+ /* offset = */ 0, stream_type));
+
+ // SETTINGS_QPACK_MAX_TABLE_CAPACITY, if advertised again, MUST have identical
+ // value.
+ // SETTINGS_QPACK_BLOCKED_STREAMS is a limit. Limits MUST NOT be reduced, but
+ // increasing is okay.
+ SettingsFrame expected_settings_frame2{
+ {{SETTINGS_QPACK_MAX_TABLE_CAPACITY, 1024},
+ {SETTINGS_QPACK_BLOCKED_STREAMS, 48}}};
+ EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(expected_settings_frame2));
+ std::string serialized_settings_frame2 = absl::HexStringToBytes(
+ "04" // type (SETTINGS)
+ "05" // length
+ "01" // SETTINGS_QPACK_MAX_TABLE_CAPACITY
+ "4400" // 0x0400 = 1024
+ "07" // SETTINGS_QPACK_BLOCKED_STREAMS
+ "30"); // 0x30 = 48
+ session_.OnStreamFrame(QuicStreamFrame(control_stream_id, /* fin = */ false,
+ /* offset = */ stream_type.length(),
+ serialized_settings_frame2));
+
+ EXPECT_EQ(1024u, qpack_encoder->MaximumDynamicTableCapacity());
+ EXPECT_EQ(48u, qpack_encoder->maximum_blocked_streams());
+}
+
+// A SETTINGS frame received via ALPS and another one on the control stream
+// cannot have conflicting values.
+TEST_P(QuicSpdySessionTestClient,
+ SettingsViaAlpsConflictsSettingsViaControlStream) {
+ if (!VersionUsesHttp3(transport_version())) {
+ return;
+ }
+
+ QpackEncoder* qpack_encoder = session_.qpack_encoder();
+ EXPECT_EQ(0u, qpack_encoder->MaximumDynamicTableCapacity());
+
+ std::string serialized_settings_frame1 = absl::HexStringToBytes(
+ "04" // type (SETTINGS)
+ "03" // length
+ "01" // SETTINGS_QPACK_MAX_TABLE_CAPACITY
+ "4400"); // 0x0400 = 1024
+
+ auto error = session_.OnAlpsData(
+ reinterpret_cast<const uint8_t*>(serialized_settings_frame1.data()),
+ serialized_settings_frame1.size());
+ EXPECT_FALSE(error);
+
+ EXPECT_EQ(1024u, qpack_encoder->MaximumDynamicTableCapacity());
+
+ const QuicStreamId control_stream_id =
+ GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
+
+ std::string stream_type = absl::HexStringToBytes("00");
+ session_.OnStreamFrame(QuicStreamFrame(control_stream_id, /* fin = */ false,
+ /* offset = */ 0, stream_type));
+
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_HTTP_ZERO_RTT_RESUMPTION_SETTINGS_MISMATCH,
+ "Server sent an SETTINGS_QPACK_MAX_TABLE_CAPACITY: "
+ "32 while current value is: 1024",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
+ std::string serialized_settings_frame2 = absl::HexStringToBytes(
+ "04" // type (SETTINGS)
+ "02" // length
+ "01" // SETTINGS_QPACK_MAX_TABLE_CAPACITY
+ "20"); // 0x20 = 32
+ session_.OnStreamFrame(QuicStreamFrame(control_stream_id, /* fin = */ false,
+ /* offset = */ stream_type.length(),
+ serialized_settings_frame2));
+}
+
+TEST_P(QuicSpdySessionTestClient, AlpsTwoSettingsFrame) {
+ if (!VersionUsesHttp3(transport_version())) {
+ return;
+ }
+
+ std::string banned_frame = absl::HexStringToBytes(
+ "04" // type (SETTINGS)
+ "00" // length
+ "04" // type (SETTINGS)
+ "00"); // length
+
+ auto error =
+ session_.OnAlpsData(reinterpret_cast<const uint8_t*>(banned_frame.data()),
+ banned_frame.size());
+ ASSERT_TRUE(error);
+ EXPECT_EQ("multiple SETTINGS frames", error.value());
+}
+
+TEST_P(QuicSpdySessionTestClient, GetNextDatagramFlowId) {
+ if (!version().UsesHttp3()) {
+ return;
+ }
+ EXPECT_EQ(session_.GetNextDatagramFlowId(), 0u);
+ EXPECT_EQ(session_.GetNextDatagramFlowId(), 2u);
+ EXPECT_EQ(session_.GetNextDatagramFlowId(), 4u);
+ EXPECT_EQ(session_.GetNextDatagramFlowId(), 6u);
+}
+
+TEST_P(QuicSpdySessionTestServer, GetNextDatagramFlowId) {
+ if (!version().UsesHttp3()) {
+ return;
+ }
+ EXPECT_EQ(session_.GetNextDatagramFlowId(), 1u);
+ EXPECT_EQ(session_.GetNextDatagramFlowId(), 3u);
+ EXPECT_EQ(session_.GetNextDatagramFlowId(), 5u);
+ EXPECT_EQ(session_.GetNextDatagramFlowId(), 7u);
+}
+
+TEST_P(QuicSpdySessionTestClient, H3DatagramSetting) {
+ if (!version().UsesHttp3()) {
+ return;
+ }
+ SetQuicReloadableFlag(quic_h3_datagram, true);
+ // HTTP/3 datagrams aren't supported before SETTINGS are received.
+ EXPECT_FALSE(session_.h3_datagram_supported());
+ // Receive SETTINGS.
+ SettingsFrame settings;
+ settings.values[SETTINGS_H3_DATAGRAM] = 1;
+ std::string data = std::string(1, kControlStream) + EncodeSettings(settings);
+ QuicStreamId stream_id =
+ GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 3);
+ QuicStreamFrame frame(stream_id, /*fin=*/false, /*offset=*/0, data);
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ session_.set_debug_visitor(&debug_visitor);
+ EXPECT_CALL(debug_visitor, OnPeerControlStreamCreated(stream_id));
+ EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(settings));
+ session_.OnStreamFrame(frame);
+ // HTTP/3 datagrams are now supported.
+ EXPECT_TRUE(session_.h3_datagram_supported());
+}
+
+TEST_P(QuicSpdySessionTestClient, H3DatagramRegistration) {
+ if (!version().UsesHttp3()) {
+ return;
+ }
+ CompleteHandshake();
+ SetQuicReloadableFlag(quic_h3_datagram, true);
+ QuicSpdySessionPeer::SetH3DatagramSupported(&session_, true);
+ SavingHttp3DatagramVisitor h3_datagram_visitor;
+ QuicDatagramFlowId flow_id = session_.GetNextDatagramFlowId();
+ ASSERT_EQ(QuicDataWriter::GetVarInt62Len(flow_id), 1);
+ uint8_t datagram[256];
+ datagram[0] = flow_id;
+ for (size_t i = 1; i < ABSL_ARRAYSIZE(datagram); i++) {
+ datagram[i] = i;
+ }
+ session_.RegisterHttp3FlowId(flow_id, &h3_datagram_visitor);
+ session_.OnMessageReceived(absl::string_view(
+ reinterpret_cast<const char*>(datagram), sizeof(datagram)));
+ EXPECT_THAT(
+ h3_datagram_visitor.received_h3_datagrams(),
+ ElementsAre(SavingHttp3DatagramVisitor::SavedHttp3Datagram{
+ flow_id, std::string(reinterpret_cast<const char*>(datagram + 1),
+ sizeof(datagram) - 1)}));
+ session_.UnregisterHttp3FlowId(flow_id);
+}
+
+TEST_P(QuicSpdySessionTestClient, SendHttp3Datagram) {
+ if (!version().UsesHttp3()) {
+ return;
+ }
+ CompleteHandshake();
+ SetQuicReloadableFlag(quic_h3_datagram, true);
+ QuicSpdySessionPeer::SetH3DatagramSupported(&session_, true);
+ QuicDatagramFlowId flow_id = session_.GetNextDatagramFlowId();
+ std::string h3_datagram_payload = {1, 2, 3, 4, 5, 6};
+ EXPECT_CALL(*connection_, SendMessage(1, _, false))
+ .WillOnce(Return(MESSAGE_STATUS_SUCCESS));
+ EXPECT_EQ(session_.SendHttp3Datagram(flow_id, h3_datagram_payload),
+ MESSAGE_STATUS_SUCCESS);
+}
+
+TEST_P(QuicSpdySessionTestClient, WebTransportSetting) {
+ if (!version().UsesHttp3()) {
+ return;
+ }
+ SetQuicReloadableFlag(quic_h3_datagram, true);
+ session_.set_supports_webtransport(true);
+
+ EXPECT_FALSE(session_.SupportsWebTransport());
+
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ // Note that this does not actually fill out correct settings because the
+ // settings are filled in at the construction time.
+ EXPECT_CALL(debug_visitor, OnSettingsFrameSent(_));
+ session_.set_debug_visitor(&debug_visitor);
+ CompleteHandshake();
+
+ SettingsFrame server_settings;
+ server_settings.values[SETTINGS_H3_DATAGRAM] = 1;
+ server_settings.values[SETTINGS_WEBTRANS_DRAFT00] = 1;
+ std::string data =
+ std::string(1, kControlStream) + EncodeSettings(server_settings);
+ QuicStreamId stream_id =
+ GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 3);
+ QuicStreamFrame frame(stream_id, /*fin=*/false, /*offset=*/0, data);
+ EXPECT_CALL(debug_visitor, OnPeerControlStreamCreated(stream_id));
+ EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(server_settings));
+ session_.OnStreamFrame(frame);
+ EXPECT_TRUE(session_.SupportsWebTransport());
+}
+
+TEST_P(QuicSpdySessionTestClient, WebTransportSettingSetToZero) {
+ if (!version().UsesHttp3()) {
+ return;
+ }
+ SetQuicReloadableFlag(quic_h3_datagram, true);
+ session_.set_supports_webtransport(true);
+
+ EXPECT_FALSE(session_.SupportsWebTransport());
+
+ StrictMock<MockHttp3DebugVisitor> debug_visitor;
+ // Note that this does not actually fill out correct settings because the
+ // settings are filled in at the construction time.
+ EXPECT_CALL(debug_visitor, OnSettingsFrameSent(_));
+ session_.set_debug_visitor(&debug_visitor);
+ CompleteHandshake();
+
+ SettingsFrame server_settings;
+ server_settings.values[SETTINGS_H3_DATAGRAM] = 1;
+ server_settings.values[SETTINGS_WEBTRANS_DRAFT00] = 0;
+ std::string data =
+ std::string(1, kControlStream) + EncodeSettings(server_settings);
+ QuicStreamId stream_id =
+ GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 3);
+ QuicStreamFrame frame(stream_id, /*fin=*/false, /*offset=*/0, data);
+ EXPECT_CALL(debug_visitor, OnPeerControlStreamCreated(stream_id));
+ EXPECT_CALL(debug_visitor, OnSettingsFrameReceived(server_settings));
+ session_.OnStreamFrame(frame);
+ EXPECT_FALSE(session_.SupportsWebTransport());
+}
+
+TEST_P(QuicSpdySessionTestServer, WebTransportSetting) {
+ if (!version().UsesHttp3()) {
+ return;
+ }
+ SetQuicReloadableFlag(quic_h3_datagram, true);
+ session_.set_supports_webtransport(true);
+
+ EXPECT_FALSE(session_.SupportsWebTransport());
+ EXPECT_FALSE(session_.ShouldProcessIncomingRequests());
+
+ CompleteHandshake();
+
+ ReceiveWebTransportSettings();
+ EXPECT_TRUE(session_.SupportsWebTransport());
+ EXPECT_TRUE(session_.ShouldProcessIncomingRequests());
+}
+
+TEST_P(QuicSpdySessionTestServer, BufferingIncomingStreams) {
+ if (!version().UsesHttp3()) {
+ return;
+ }
+ SetQuicReloadableFlag(quic_h3_datagram, true);
+ session_.set_supports_webtransport(true);
+
+ CompleteHandshake();
+ QuicStreamId session_id =
+ GetNthClientInitiatedBidirectionalStreamId(transport_version(), 1);
+
+ QuicStreamId data_stream_id =
+ GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 4);
+ ReceiveWebTransportUnidirectionalStream(session_id, data_stream_id);
+
+ ReceiveWebTransportSettings();
+
+ ReceiveWebTransportSession(session_id);
+ WebTransportHttp3* web_transport =
+ session_.GetWebTransportSession(session_id);
+ ASSERT_TRUE(web_transport != nullptr);
+
+ EXPECT_EQ(web_transport->NumberOfAssociatedStreams(), 1u);
+
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillRepeatedly(Invoke(&ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(session_id, _));
+ EXPECT_CALL(
+ *connection_,
+ OnStreamReset(data_stream_id, QUIC_STREAM_WEBTRANSPORT_SESSION_GONE));
+ session_.ResetStream(session_id, QUIC_STREAM_INTERNAL_ERROR);
+}
+
+TEST_P(QuicSpdySessionTestServer, BufferingIncomingStreamsLimit) {
+ if (!version().UsesHttp3()) {
+ return;
+ }
+ SetQuicReloadableFlag(quic_h3_datagram, true);
+ session_.set_supports_webtransport(true);
+
+ CompleteHandshake();
+ QuicStreamId session_id =
+ GetNthClientInitiatedBidirectionalStreamId(transport_version(), 1);
+
+ const int streams_to_send = kMaxUnassociatedWebTransportStreams + 4;
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillRepeatedly(Invoke(&ClearControlFrame));
+ EXPECT_CALL(*connection_,
+ OnStreamReset(
+ _, QUIC_STREAM_WEBTRANSPORT_BUFFERED_STREAMS_LIMIT_EXCEEDED))
+ .Times(4);
+ for (int i = 0; i < streams_to_send; i++) {
+ QuicStreamId data_stream_id =
+ GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 4 + i);
+ ReceiveWebTransportUnidirectionalStream(session_id, data_stream_id);
+ }
+
+ ReceiveWebTransportSettings();
+
+ ReceiveWebTransportSession(session_id);
+ WebTransportHttp3* web_transport =
+ session_.GetWebTransportSession(session_id);
+ ASSERT_TRUE(web_transport != nullptr);
+
+ EXPECT_EQ(web_transport->NumberOfAssociatedStreams(),
+ kMaxUnassociatedWebTransportStreams);
+
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillRepeatedly(Invoke(&ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(_, _))
+ .Times(kMaxUnassociatedWebTransportStreams + 1);
+ session_.ResetStream(session_id, QUIC_STREAM_INTERNAL_ERROR);
+}
+
+TEST_P(QuicSpdySessionTestServer, ResetOutgoingWebTransportStreams) {
+ if (!version().UsesHttp3()) {
+ return;
+ }
+ SetQuicReloadableFlag(quic_h3_datagram, true);
+ session_.set_supports_webtransport(true);
+
+ CompleteHandshake();
+ QuicStreamId session_id =
+ GetNthClientInitiatedBidirectionalStreamId(transport_version(), 1);
+
+ ReceiveWebTransportSettings();
+ ReceiveWebTransportSession(session_id);
+ WebTransportHttp3* web_transport =
+ session_.GetWebTransportSession(session_id);
+ ASSERT_TRUE(web_transport != nullptr);
+
+ session_.set_writev_consumes_all_data(true);
+ EXPECT_TRUE(web_transport->CanOpenNextOutgoingUnidirectionalStream());
+ EXPECT_EQ(web_transport->NumberOfAssociatedStreams(), 0u);
+ WebTransportStream* stream =
+ web_transport->OpenOutgoingUnidirectionalStream();
+ EXPECT_EQ(web_transport->NumberOfAssociatedStreams(), 1u);
+ ASSERT_TRUE(stream != nullptr);
+ QuicStreamId stream_id = stream->GetStreamId();
+
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillRepeatedly(Invoke(&ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(session_id, _));
+ EXPECT_CALL(*connection_,
+ OnStreamReset(stream_id, QUIC_STREAM_WEBTRANSPORT_SESSION_GONE));
+ session_.ResetStream(session_id, QUIC_STREAM_INTERNAL_ERROR);
+ EXPECT_EQ(web_transport->NumberOfAssociatedStreams(), 0u);
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc
index 6ab6bb0aa68..4d4cc95f94d 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
@@ -5,18 +5,23 @@
#include "quic/core/http/quic_spdy_stream.h"
#include <limits>
+#include <memory>
#include <string>
#include <utility>
#include "absl/base/macros.h"
#include "absl/strings/numbers.h"
+#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "quic/core/http/http_constants.h"
#include "quic/core/http/http_decoder.h"
#include "quic/core/http/quic_spdy_session.h"
#include "quic/core/http/spdy_utils.h"
+#include "quic/core/http/web_transport_http3.h"
#include "quic/core/qpack/qpack_decoder.h"
#include "quic/core/qpack/qpack_encoder.h"
+#include "quic/core/quic_error_codes.h"
+#include "quic/core/quic_types.h"
#include "quic/core/quic_utils.h"
#include "quic/core/quic_versions.h"
#include "quic/core/quic_write_blocked_list.h"
@@ -164,6 +169,12 @@ class QuicSpdyStream::HttpDecoderVisitor : public HttpDecoder::Visitor {
return false;
}
+ void OnWebTransportStreamFrameType(
+ QuicByteCount header_length,
+ WebTransportSessionId session_id) override {
+ stream_->OnWebTransportStreamFrameType(header_length, session_id);
+ }
+
bool OnUnknownFrameStart(uint64_t frame_type,
QuicByteCount header_length,
QuicByteCount payload_length) override {
@@ -192,6 +203,16 @@ class QuicSpdyStream::HttpDecoderVisitor : public HttpDecoder::Visitor {
: "Client:" \
" ")
+namespace {
+HttpDecoder::Options HttpDecoderOptionsForBidiStream(
+ QuicSpdySession* spdy_session) {
+ HttpDecoder::Options options;
+ options.allow_web_transport_stream =
+ spdy_session->WillNegotiateWebTransport();
+ return options;
+}
+} // namespace
+
QuicSpdyStream::QuicSpdyStream(QuicStreamId id,
QuicSpdySession* spdy_session,
StreamType type)
@@ -206,7 +227,8 @@ QuicSpdyStream::QuicSpdyStream(QuicStreamId id,
trailers_decompressed_(false),
trailers_consumed_(false),
http_decoder_visitor_(std::make_unique<HttpDecoderVisitor>(this)),
- decoder_(http_decoder_visitor_.get()),
+ decoder_(http_decoder_visitor_.get(),
+ HttpDecoderOptionsForBidiStream(spdy_session)),
sequencer_offset_(0),
is_decoder_processing_input_(false),
ack_listener_(nullptr),
@@ -269,6 +291,10 @@ size_t QuicSpdyStream::WriteHeaders(
SpdyHeaderBlock header_block,
bool fin,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
+ if (!AssertNotWebTransportDataStream("writing headers")) {
+ return 0;
+ }
+
QuicConnection::ScopedPacketFlusher flusher(spdy_session_->connection());
// Send stream type for server push stream
if (VersionUsesHttp3(transport_version()) && type() == WRITE_UNIDIRECTIONAL &&
@@ -287,6 +313,8 @@ size_t QuicSpdyStream::WriteHeaders(
nullptr);
}
+ MaybeProcessSentWebTransportHeaders(header_block);
+
size_t bytes_written =
WriteHeadersImpl(std::move(header_block), fin, std::move(ack_listener));
if (!VersionUsesHttp3(transport_version()) && fin) {
@@ -301,6 +329,9 @@ size_t QuicSpdyStream::WriteHeaders(
}
void QuicSpdyStream::WriteOrBufferBody(absl::string_view data, bool fin) {
+ if (!AssertNotWebTransportDataStream("writing body data")) {
+ return;
+ }
if (!VersionUsesHttp3(transport_version()) || data.length() == 0) {
WriteOrBufferData(data, fin, nullptr);
return;
@@ -335,7 +366,8 @@ size_t QuicSpdyStream::WriteTrailers(
SpdyHeaderBlock trailer_block,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
if (fin_sent()) {
- QUIC_BUG << "Trailers cannot be sent after a FIN, on stream " << id();
+ QUIC_BUG(quic_bug_10410_1)
+ << "Trailers cannot be sent after a FIN, on stream " << id();
return 0;
}
@@ -347,8 +379,7 @@ size_t QuicSpdyStream::WriteTrailers(
QUIC_DLOG(INFO) << ENDPOINT << "Inserting trailer: ("
<< kFinalOffsetHeaderKey << ", " << final_offset << ")";
trailer_block.insert(
- std::make_pair(kFinalOffsetHeaderKey,
- quiche::QuicheTextUtils::Uint64ToString(final_offset)));
+ std::make_pair(kFinalOffsetHeaderKey, absl::StrCat(final_offset)));
}
// Write the trailing headers with a FIN, and close stream for writing:
@@ -372,35 +403,6 @@ size_t QuicSpdyStream::WriteTrailers(
return bytes_written;
}
-void QuicSpdyStream::WritePushPromise(const PushPromiseFrame& frame) {
- QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
- std::unique_ptr<char[]> push_promise_frame_with_id;
- const size_t push_promise_frame_length =
- HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
- frame, &push_promise_frame_with_id);
-
- unacked_frame_headers_offsets_.Add(send_buffer().stream_offset(),
- send_buffer().stream_offset() +
- push_promise_frame_length +
- frame.headers.length());
-
- // Write Push Promise frame header and push id.
- QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
- << " is writing Push Promise frame header of length "
- << push_promise_frame_length << " , with promised id "
- << frame.push_id;
- WriteOrBufferData(absl::string_view(push_promise_frame_with_id.get(),
- push_promise_frame_length),
- /* fin = */ false, /* ack_listener = */ nullptr);
-
- // Write response headers.
- QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
- << " is writing Push Promise request header of length "
- << frame.headers.length();
- WriteOrBufferData(frame.headers, /* fin = */ false,
- /* ack_listener = */ nullptr);
-}
-
QuicConsumedData QuicSpdyStream::WritevBody(const struct iovec* iov,
int count,
bool fin) {
@@ -647,6 +649,8 @@ void QuicSpdyStream::OnInitialHeadersComplete(
headers_decompressed_ = true;
header_list_ = header_list;
+ MaybeProcessReceivedWebTransportHeaders();
+
if (VersionUsesHttp3(transport_version())) {
if (fin) {
OnStreamFrame(QuicStreamFrame(id(), /* fin = */ true,
@@ -725,6 +729,11 @@ void QuicSpdyStream::OnPriorityFrame(
}
void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) {
+ if (web_transport_data_ != nullptr) {
+ QuicStream::OnStreamReset(frame);
+ return;
+ }
+
// TODO(bnc): Merge the two blocks below when both
// quic_abort_qpack_on_stream_reset and quic_fix_on_stream_reset are
// deprecated.
@@ -765,7 +774,7 @@ void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) {
void QuicSpdyStream::Reset(QuicRstStreamErrorCode error) {
if (VersionUsesHttp3(transport_version()) && !fin_received() &&
- spdy_session_->qpack_decoder()) {
+ spdy_session_->qpack_decoder() && web_transport_data_ == nullptr) {
QUIC_CODE_COUNT_N(quic_abort_qpack_on_stream_reset, 2, 2);
spdy_session_->qpack_decoder()->OnStreamReset(id());
if (GetQuicReloadableFlag(quic_abort_qpack_on_stream_reset)) {
@@ -788,6 +797,16 @@ void QuicSpdyStream::OnDataAvailable() {
return;
}
+ if (web_transport_data_ != nullptr) {
+ web_transport_data_->adapter.OnDataAvailable();
+ return;
+ }
+
+ if (!spdy_session()->ShouldProcessIncomingRequests()) {
+ spdy_session()->OnStreamWaitingForClientSettings(id());
+ return;
+ }
+
if (is_decoder_processing_input_) {
// Let the outermost nested OnDataAvailable() call do the work.
return;
@@ -814,6 +833,9 @@ void QuicSpdyStream::OnDataAvailable() {
if (blocked_on_decoding_headers_) {
return;
}
+ if (web_transport_data_ != nullptr) {
+ return;
+ }
}
// Do not call OnBodyAvailable() until headers are consumed.
@@ -845,6 +867,24 @@ void QuicSpdyStream::OnClose() {
visitor_ = nullptr;
visitor->OnClose(this);
}
+
+ if (web_transport_ != nullptr) {
+ web_transport_->CloseAllAssociatedStreams();
+ }
+ if (web_transport_data_ != nullptr) {
+ WebTransportHttp3* web_transport =
+ spdy_session_->GetWebTransportSession(web_transport_data_->session_id);
+ if (web_transport == nullptr) {
+ // Since there is no guaranteed destruction order for streams, the session
+ // could be already removed from the stream map by the time we reach here.
+ QUIC_DLOG(WARNING) << ENDPOINT << "WebTransport stream " << id()
+ << " attempted to notify parent session "
+ << web_transport_data_->session_id
+ << ", but the session could not be found.";
+ return;
+ }
+ web_transport->OnStreamClosed(id());
+ }
}
void QuicSpdyStream::OnCanWrite() {
@@ -1084,6 +1124,36 @@ bool QuicSpdyStream::OnPushPromiseFrameEnd() {
return OnHeadersFrameEnd();
}
+void QuicSpdyStream::OnWebTransportStreamFrameType(
+ QuicByteCount header_length,
+ WebTransportSessionId session_id) {
+ QUIC_DVLOG(1) << ENDPOINT << " Received WEBTRANSPORT_STREAM on stream "
+ << id() << " for session " << session_id;
+ sequencer()->MarkConsumed(header_length);
+
+ if (headers_payload_length_ > 0 || headers_decompressed_) {
+ QUIC_PEER_BUG(WEBTRANSPORT_STREAM received on HTTP request)
+ << ENDPOINT << "Stream " << id()
+ << " tried to convert to WebTransport, but it already "
+ "has HTTP data on it";
+ Reset(QUIC_STREAM_FRAME_UNEXPECTED);
+ }
+ if (QuicUtils::IsOutgoingStreamId(spdy_session_->version(), id(),
+ spdy_session_->perspective())) {
+ QUIC_PEER_BUG(WEBTRANSPORT_STREAM received on outgoing request)
+ << ENDPOINT << "Stream " << id()
+ << " tried to convert to WebTransport, but only the "
+ "initiator of the stream can do it.";
+ Reset(QUIC_STREAM_FRAME_UNEXPECTED);
+ }
+
+ QUICHE_DCHECK(web_transport_ == nullptr);
+ web_transport_data_ =
+ std::make_unique<WebTransportDataStream>(this, session_id);
+ spdy_session_->AssociateIncomingWebTransportStreamWithSession(session_id,
+ id());
+}
+
bool QuicSpdyStream::OnUnknownFrameStart(uint64_t frame_type,
QuicByteCount header_length,
QuicByteCount payload_length) {
@@ -1162,5 +1232,137 @@ size_t QuicSpdyStream::WriteHeadersImpl(
return encoded_headers.size();
}
+void QuicSpdyStream::MaybeProcessReceivedWebTransportHeaders() {
+ if (!spdy_session_->SupportsWebTransport()) {
+ return;
+ }
+ if (session()->perspective() != Perspective::IS_SERVER) {
+ return;
+ }
+ QUICHE_DCHECK(IsValidWebTransportSessionId(id(), version()));
+
+ std::string method;
+ std::string protocol;
+ absl::optional<QuicDatagramFlowId> flow_id;
+ for (const auto& header : header_list_) {
+ const std::string& header_name = header.first;
+ const std::string& header_value = header.second;
+ if (header_name == ":method") {
+ if (!method.empty() || header_value.empty()) {
+ return;
+ }
+ method = header_value;
+ }
+ if (header_name == ":protocol") {
+ if (!protocol.empty() || header_value.empty()) {
+ return;
+ }
+ protocol = header_value;
+ }
+ if (header_name == "datagram-flow-id") {
+ if (flow_id.has_value() || header_value.empty()) {
+ return;
+ }
+ QuicDatagramFlowId flow_id_out;
+ if (!absl::SimpleAtoi(header_value, &flow_id_out)) {
+ return;
+ }
+ flow_id = flow_id_out;
+ }
+ }
+
+ if (method != "CONNECT" || protocol != "webtransport" ||
+ !flow_id.has_value()) {
+ return;
+ }
+
+ web_transport_ =
+ std::make_unique<WebTransportHttp3>(spdy_session_, this, id(), *flow_id);
+}
+
+void QuicSpdyStream::MaybeProcessSentWebTransportHeaders(
+ spdy::SpdyHeaderBlock& headers) {
+ if (!spdy_session_->SupportsWebTransport()) {
+ return;
+ }
+ if (session()->perspective() != Perspective::IS_CLIENT) {
+ return;
+ }
+ QUICHE_DCHECK(IsValidWebTransportSessionId(id(), version()));
+
+ const auto method_it = headers.find(":method");
+ const auto protocol_it = headers.find(":protocol");
+ if (method_it == headers.end() || protocol_it == headers.end()) {
+ return;
+ }
+ if (method_it->second != "CONNECT" && protocol_it->second != "webtransport") {
+ return;
+ }
+
+ QuicDatagramFlowId flow_id = spdy_session_->GetNextDatagramFlowId();
+ headers["datagram-flow-id"] = absl::StrCat(flow_id);
+
+ web_transport_ =
+ std::make_unique<WebTransportHttp3>(spdy_session_, this, id(), flow_id);
+}
+
+void QuicSpdyStream::OnCanWriteNewData() {
+ if (web_transport_data_ != nullptr) {
+ web_transport_data_->adapter.OnCanWriteNewData();
+ }
+}
+
+bool QuicSpdyStream::AssertNotWebTransportDataStream(
+ absl::string_view operation) {
+ if (web_transport_data_ != nullptr) {
+ QUIC_BUG(Invalid operation on WebTransport stream)
+ << "Attempted to " << operation << " on WebTransport data stream "
+ << id() << " associated with session "
+ << web_transport_data_->session_id;
+ OnUnrecoverableError(QUIC_INTERNAL_ERROR,
+ absl::StrCat("Attempted to ", operation,
+ " on WebTransport data stream"));
+ return false;
+ }
+ return true;
+}
+
+void QuicSpdyStream::ConvertToWebTransportDataStream(
+ WebTransportSessionId session_id) {
+ if (send_buffer().stream_offset() != 0) {
+ QUIC_BUG(Sending WEBTRANSPORT_STREAM when data already sent)
+ << "Attempted to send a WEBTRANSPORT_STREAM frame when other data has "
+ "already been sent on the stream.";
+ OnUnrecoverableError(QUIC_INTERNAL_ERROR,
+ "Attempted to send a WEBTRANSPORT_STREAM frame when "
+ "other data has already been sent on the stream.");
+ return;
+ }
+
+ std::unique_ptr<char[]> header;
+ QuicByteCount header_size =
+ HttpEncoder::SerializeWebTransportStreamFrameHeader(session_id, &header);
+ if (header_size == 0) {
+ QUIC_BUG(Failed to serialize WEBTRANSPORT_STREAM)
+ << "Failed to serialize a WEBTRANSPORT_STREAM frame.";
+ OnUnrecoverableError(QUIC_INTERNAL_ERROR,
+ "Failed to serialize a WEBTRANSPORT_STREAM frame.");
+ return;
+ }
+
+ WriteOrBufferData(absl::string_view(header.get(), header_size), /*fin=*/false,
+ nullptr);
+ web_transport_data_ =
+ std::make_unique<WebTransportDataStream>(this, session_id);
+ QUIC_DVLOG(1) << ENDPOINT << "Successfully opened WebTransport data stream "
+ << id() << " for session " << session_id;
+}
+
+QuicSpdyStream::WebTransportDataStream::WebTransportDataStream(
+ QuicSpdyStream* stream,
+ WebTransportSessionId session_id)
+ : session_id(session_id),
+ adapter(stream->spdy_session_, stream, stream->sequencer()) {}
+
#undef ENDPOINT // undef for jumbo builds
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h
index 60d5e390b20..5f96d8395cf 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h
@@ -13,6 +13,7 @@
#include <cstddef>
#include <list>
+#include <memory>
#include <string>
#include "absl/strings/string_view.h"
@@ -24,10 +25,14 @@
#include "quic/core/quic_packets.h"
#include "quic/core/quic_stream.h"
#include "quic/core/quic_stream_sequencer.h"
+#include "quic/core/quic_types.h"
+#include "quic/core/web_transport_interface.h"
+#include "quic/core/web_transport_stream_adapter.h"
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_socket_address.h"
#include "spdy/core/spdy_framer.h"
+#include "spdy/core/spdy_header_block.h"
namespace quic {
@@ -37,6 +42,7 @@ class QuicStreamPeer;
} // namespace test
class QuicSpdySession;
+class WebTransportHttp3;
// A QUIC stream that can send and receive HTTP2 (SPDY) headers.
class QUIC_EXPORT_PRIVATE QuicSpdyStream
@@ -132,9 +138,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
spdy::SpdyHeaderBlock trailer_block,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
- // Serializes |frame| and writes the encoded push promise data.
- void WritePushPromise(const PushPromiseFrame& frame);
-
// Override to report newly acked bytes via ack_listener_.
bool OnStreamFrameAcked(QuicStreamOffset offset,
QuicByteCount data_length,
@@ -165,8 +168,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
// Clears |header_list_|.
void ConsumeHeaderList();
- void SetUnblocked() { sequencer()->SetUnblocked(); }
-
// This block of functions wraps the sequencer's functions of the same
// name. These methods return uncompressed data until that has
// been fully processed. Then they simply delegate to the sequencer.
@@ -222,6 +223,27 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
// |last_sent_urgency_| is different from current priority.
void MaybeSendPriorityUpdateFrame() override;
+ // Returns the WebTransport session owned by this stream, if one exists.
+ WebTransportHttp3* web_transport() { return web_transport_.get(); }
+
+ // Returns the WebTransport data stream associated with this QUIC stream, or
+ // null if this is not a WebTransport data stream.
+ WebTransportStream* web_transport_stream() {
+ if (web_transport_data_ == nullptr) {
+ return nullptr;
+ }
+ return &web_transport_data_->adapter;
+ }
+
+ // Sends a WEBTRANSPORT_STREAM frame and sets up the appropriate metadata.
+ void ConvertToWebTransportDataStream(WebTransportSessionId session_id);
+
+ void OnCanWriteNewData() override;
+
+ // If this stream is a WebTransport data stream, closes the connection with an
+ // error, and returns false.
+ bool AssertNotWebTransportDataStream(absl::string_view operation);
+
protected:
// Called when the received headers are too large. By default this will
// reset the stream.
@@ -253,6 +275,14 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
friend class QuicStreamUtils;
class HttpDecoderVisitor;
+ struct QUIC_EXPORT_PRIVATE WebTransportDataStream {
+ WebTransportDataStream(QuicSpdyStream* stream,
+ WebTransportSessionId session_id);
+
+ WebTransportSessionId session_id;
+ WebTransportStreamAdapter adapter;
+ };
+
// Called by HttpDecoderVisitor.
bool OnDataFrameStart(QuicByteCount header_length,
QuicByteCount payload_length);
@@ -268,6 +298,8 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
QuicByteCount header_block_length);
bool OnPushPromiseFramePayload(absl::string_view payload);
bool OnPushPromiseFrameEnd();
+ void OnWebTransportStreamFrameType(QuicByteCount header_length,
+ WebTransportSessionId session_id);
bool OnUnknownFrameStart(uint64_t frame_type,
QuicByteCount header_length,
QuicByteCount payload_length);
@@ -279,6 +311,9 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
QuicByteCount GetNumFrameHeadersInInterval(QuicStreamOffset offset,
QuicByteCount data_length) const;
+ void MaybeProcessSentWebTransportHeaders(spdy::SpdyHeaderBlock& headers);
+ void MaybeProcessReceivedWebTransportHeaders();
+
QuicSpdySession* spdy_session_;
bool on_body_available_called_because_sequencer_is_closed_;
@@ -339,6 +374,14 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
// Urgency value sent in the last PRIORITY_UPDATE frame, or default urgency
// defined by the spec if no PRIORITY_UPDATE frame has been sent.
int last_sent_urgency_;
+
+ // If this stream is a WebTransport extended CONNECT stream, contains the
+ // WebTransport session associated with this stream.
+ std::unique_ptr<WebTransportHttp3> web_transport_;
+
+ // If this stream is a WebTransport data stream, |web_transport_data_|
+ // contains all of the associated metadata.
+ std::unique_ptr<WebTransportDataStream> web_transport_data_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.cc
index 1d40e03d186..2ae24d472b7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.cc
@@ -41,7 +41,7 @@ size_t QuicSpdyStreamBodyManager::OnBodyConsumed(size_t num_bytes) {
while (remaining_bytes > 0) {
if (fragments_.empty()) {
- QUIC_BUG << "Not enough available body to consume.";
+ QUIC_BUG(quic_bug_10394_1) << "Not enough available body to consume.";
return 0;
}
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 0e35c28aa4f..bb464bdb4d5 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
@@ -10,11 +10,14 @@
#include <utility>
#include "absl/base/macros.h"
+#include "absl/memory/memory.h"
#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "quic/core/crypto/null_encrypter.h"
#include "quic/core/http/http_encoder.h"
#include "quic/core/http/spdy_utils.h"
+#include "quic/core/http/web_transport_http3.h"
#include "quic/core/quic_connection.h"
#include "quic/core/quic_stream_sequencer_buffer.h"
#include "quic/core/quic_utils.h"
@@ -22,7 +25,6 @@
#include "quic/core/quic_write_blocked_list.h"
#include "quic/platform/api/quic_expect_bug.h"
#include "quic/platform/api/quic_map_util.h"
-#include "quic/platform/api/quic_ptr_util.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/qpack/qpack_test_utils.h"
#include "quic/test_tools/quic_config_peer.h"
@@ -33,7 +35,6 @@
#include "quic/test_tools/quic_spdy_stream_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"
using spdy::kV3HighestPriority;
using spdy::kV3LowestPriority;
@@ -255,7 +256,11 @@ class TestSession : public MockQuicSpdySession {
return &crypto_stream_;
}
+ bool ShouldNegotiateWebTransport() override { return enable_webtransport_; }
+ void EnableWebTransport() { enable_webtransport_ = true; }
+
private:
+ bool enable_webtransport_ = false;
StrictMock<TestCryptoStream> crypto_stream_;
};
@@ -365,11 +370,11 @@ class QuicSpdyStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
stream_ =
new StrictMock<TestStream>(GetNthClientInitiatedBidirectionalId(0),
session_.get(), stream_should_process_data);
- session_->ActivateStream(QuicWrapUnique(stream_));
+ session_->ActivateStream(absl::WrapUnique(stream_));
stream2_ =
new StrictMock<TestStream>(GetNthClientInitiatedBidirectionalId(1),
session_.get(), stream_should_process_data);
- session_->ActivateStream(QuicWrapUnique(stream2_));
+ session_->ActivateStream(absl::WrapUnique(stream2_));
QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
session_->config(), kMinimumFlowControlSendWindow);
QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesUnidirectional(
@@ -443,18 +448,30 @@ class QuicSpdyStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
}
// Construct PUSH_PROMISE frame with given payload.
+ // TODO(b/171463363): Remove.
std::string SerializePushPromiseFrame(PushId push_id,
- absl::string_view payload) {
- PushPromiseFrame frame;
- frame.push_id = push_id;
- frame.headers = payload;
- std::unique_ptr<char[]> push_promise_buffer;
- QuicByteCount push_promise_frame_header_length =
- HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
- frame, &push_promise_buffer);
- absl::string_view push_promise_frame_header(
- push_promise_buffer.get(), push_promise_frame_header_length);
- return absl::StrCat(push_promise_frame_header, payload);
+ absl::string_view headers) {
+ const QuicByteCount payload_length =
+ QuicDataWriter::GetVarInt62Len(push_id) + headers.length();
+
+ const QuicByteCount length_without_headers =
+ QuicDataWriter::GetVarInt62Len(
+ static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE)) +
+ QuicDataWriter::GetVarInt62Len(payload_length) +
+ QuicDataWriter::GetVarInt62Len(push_id);
+
+ std::string push_promise_frame(length_without_headers, '\0');
+ QuicDataWriter writer(length_without_headers, &*push_promise_frame.begin());
+
+ QUICHE_CHECK(writer.WriteVarInt62(
+ static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE)));
+ QUICHE_CHECK(writer.WriteVarInt62(payload_length));
+ QUICHE_CHECK(writer.WriteVarInt62(push_id));
+ QUICHE_CHECK_EQ(0u, writer.remaining());
+
+ absl::StrAppend(&push_promise_frame, headers);
+
+ return push_promise_frame;
}
std::string DataFrame(absl::string_view payload) {
@@ -552,6 +569,23 @@ TEST_P(QuicSpdyStreamTest, ProcessTooLargeHeaderList) {
EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_HEADERS_TOO_LARGE));
}
+TEST_P(QuicSpdyStreamTest, QpackProcessLargeHeaderListDiscountOverhead) {
+ if (!UsesHttp3()) {
+ return;
+ }
+ // Setting this flag to false causes no per-entry overhead to be included
+ // in the header size.
+ SetQuicFlag(FLAGS_quic_header_size_limit_includes_overhead, false);
+ Initialize(kShouldProcessData);
+ session_->set_max_inbound_header_list_size(40);
+ std::string headers =
+ HeadersFrame({std::make_pair("foo", "too long headers")});
+
+ QuicStreamFrame frame(stream_->id(), false, 0, headers);
+ stream_->OnStreamFrame(frame);
+ EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_STREAM_NO_ERROR));
+}
+
TEST_P(QuicSpdyStreamTest, ProcessHeaderListWithFin) {
Initialize(kShouldProcessData);
@@ -1276,8 +1310,7 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithOffset) {
trailers_block["key1"] = "value1";
trailers_block["key2"] = "value2";
trailers_block["key3"] = "value3";
- trailers_block[kFinalOffsetHeaderKey] =
- quiche::QuicheTextUtils::Uint64ToString(data.size());
+ trailers_block[kFinalOffsetHeaderKey] = absl::StrCat(data.size());
QuicHeaderList trailers = ProcessHeaders(true, trailers_block);
@@ -1578,7 +1611,7 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {
// on the headers stream.
if (!UsesHttp3()) {
expected_trailers[kFinalOffsetHeaderKey] =
- quiche::QuicheTextUtils::Uint64ToString(body.length() + header_length);
+ absl::StrCat(body.length() + header_length);
}
EXPECT_CALL(*stream_, WriteHeadersMock(true));
@@ -1761,7 +1794,7 @@ TEST_P(QuicSpdyStreamTest, SetPriorityBeforeUpdateStreamPriority) {
session->transport_version(), 0),
session.get(),
/*should_process_data=*/true);
- session->ActivateStream(QuicWrapUnique(stream));
+ session->ActivateStream(absl::WrapUnique(stream));
// QuicSpdyStream::SetPriority() should eventually call UpdateStreamPriority()
// on the session. Make sure stream->priority() returns the updated priority
@@ -2736,6 +2769,7 @@ TEST_P(QuicSpdyStreamIncrementalConsumptionTest, UnknownFramesInterleaved) {
EXPECT_EQ(unknown_frame4.size(), NewlyConsumedBytes());
}
+// TODO(b/171463363): Remove.
TEST_P(QuicSpdyStreamTest, PushPromiseOnDataStream) {
Initialize(kShouldProcessData);
if (!UsesHttp3()) {
@@ -2764,6 +2798,7 @@ TEST_P(QuicSpdyStreamTest, PushPromiseOnDataStream) {
}
// Regression test for b/152518220.
+// TODO(b/171463363): Remove.
TEST_P(QuicSpdyStreamTest,
OnStreamHeaderBlockArgumentDoesNotIncludePushedHeaderBlock) {
Initialize(kShouldProcessData);
@@ -3071,6 +3106,52 @@ TEST_P(QuicSpdyStreamTest, TwoResetStreamFrames) {
}
}
+TEST_P(QuicSpdyStreamTest, ProcessOutgoingWebTransportHeaders) {
+ if (!UsesHttp3()) {
+ return;
+ }
+
+ InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
+ session_->EnableWebTransport();
+ QuicSpdySessionPeer::EnableWebTransport(*session_);
+
+ EXPECT_CALL(*stream_, WriteHeadersMock(false));
+ EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _))
+ .Times(AnyNumber());
+
+ spdy::SpdyHeaderBlock headers;
+ headers[":method"] = "CONNECT";
+ headers[":protocol"] = "webtransport";
+ headers["datagram-flow-id"] = absl::StrCat(session_->GetNextDatagramFlowId());
+ stream_->WriteHeaders(std::move(headers), /*fin=*/false, nullptr);
+ ASSERT_TRUE(stream_->web_transport() != nullptr);
+ EXPECT_EQ(stream_->id(), stream_->web_transport()->id());
+}
+
+TEST_P(QuicSpdyStreamTest, ProcessIncomingWebTransportHeaders) {
+ if (!UsesHttp3()) {
+ return;
+ }
+
+ Initialize(kShouldProcessData);
+ session_->EnableWebTransport();
+ QuicSpdySessionPeer::EnableWebTransport(*session_);
+
+ headers_[":method"] = "CONNECT";
+ headers_[":protocol"] = "webtransport";
+ headers_["datagram-flow-id"] =
+ absl::StrCat(session_->GetNextDatagramFlowId());
+
+ stream_->OnStreamHeadersPriority(
+ spdy::SpdyStreamPrecedence(kV3HighestPriority));
+ ProcessHeaders(false, headers_);
+ EXPECT_EQ("", stream_->data());
+ EXPECT_FALSE(stream_->header_list().empty());
+ EXPECT_FALSE(stream_->IsDoneReading());
+ ASSERT_TRUE(stream_->web_transport() != nullptr);
+ EXPECT_EQ(stream_->id(), stream_->web_transport()->id());
+}
+
} // namespace
} // namespace test
} // namespace quic
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 a3d800af5d4..d3a3c92d209 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc
@@ -12,6 +12,7 @@
#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
@@ -153,4 +154,45 @@ bool SpdyUtils::PopulateHeaderBlockFromUrl(const std::string url,
return true;
}
+// static
+absl::optional<QuicDatagramFlowId> SpdyUtils::ParseDatagramFlowIdHeader(
+ const spdy::SpdyHeaderBlock& headers) {
+ auto flow_id_pair = headers.find("datagram-flow-id");
+ if (flow_id_pair == headers.end()) {
+ return absl::nullopt;
+ }
+ std::vector<absl::string_view> flow_id_strings =
+ absl::StrSplit(flow_id_pair->second, ',');
+ absl::optional<QuicDatagramFlowId> first_named_flow_id;
+ for (absl::string_view flow_id_string : flow_id_strings) {
+ std::vector<absl::string_view> flow_id_components =
+ absl::StrSplit(flow_id_string, ';');
+ if (flow_id_components.empty()) {
+ continue;
+ }
+ absl::string_view flow_id_value_string = flow_id_components[0];
+ quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(
+ &flow_id_value_string);
+ QuicDatagramFlowId flow_id;
+ if (!absl::SimpleAtoi(flow_id_value_string, &flow_id)) {
+ continue;
+ }
+ if (flow_id_components.size() == 1) {
+ // This flow ID is unnamed, return this one.
+ return flow_id;
+ }
+ // Otherwise this is a named flow ID.
+ if (!first_named_flow_id.has_value()) {
+ first_named_flow_id = flow_id;
+ }
+ }
+ return first_named_flow_id;
+}
+
+// static
+void SpdyUtils::AddDatagramFlowIdHeader(spdy::SpdyHeaderBlock* headers,
+ QuicDatagramFlowId flow_id) {
+ (*headers)["datagram-flow-id"] = absl::StrCat(flow_id);
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.h b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.h
index a3b3134fe37..e3a8a97de48 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.h
@@ -9,6 +9,7 @@
#include <cstdint>
#include <string>
+#include "absl/types/optional.h"
#include "quic/core/http/http_constants.h"
#include "quic/core/http/quic_header_list.h"
#include "quic/core/quic_packets.h"
@@ -51,6 +52,15 @@ class QUIC_EXPORT_PRIVATE SpdyUtils {
// which must be fully-qualified.
static bool PopulateHeaderBlockFromUrl(const std::string url,
spdy::SpdyHeaderBlock* headers);
+
+ // Parses the "datagram-flow-id" header, returns the flow ID on success, or
+ // returns absl::nullopt if the header was not present or failed to parse.
+ static absl::optional<QuicDatagramFlowId> ParseDatagramFlowIdHeader(
+ const spdy::SpdyHeaderBlock& headers);
+
+ // Adds the "datagram-flow-id" header.
+ static void AddDatagramFlowIdHeader(spdy::SpdyHeaderBlock* headers,
+ QuicDatagramFlowId flow_id);
};
} // namespace quic
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 5cb391dc64c..c7207f383b3 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
@@ -33,6 +33,14 @@ static std::unique_ptr<QuicHeaderList> FromList(
return headers;
}
+static void ValidateDatagramFlowId(
+ const std::string& header_value,
+ absl::optional<QuicDatagramFlowId> expected_flow_id) {
+ SpdyHeaderBlock headers;
+ headers["datagram-flow-id"] = header_value;
+ ASSERT_EQ(SpdyUtils::ParseDatagramFlowIdHeader(headers), expected_flow_id);
+}
+
} // anonymous namespace
using CopyAndValidateHeaders = QuicTest;
@@ -377,5 +385,29 @@ TEST_F(PopulateHeaderBlockFromUrl, Failure) {
SpdyUtils::PopulateHeaderBlockFromUrl("www.google.com/", &headers));
}
+using DatagramFlowIdTest = QuicTest;
+
+TEST_F(DatagramFlowIdTest, DatagramFlowId) {
+ // Test missing header.
+ SpdyHeaderBlock headers;
+ EXPECT_EQ(SpdyUtils::ParseDatagramFlowIdHeader(headers), absl::nullopt);
+ // Add header and verify it parses.
+ QuicDatagramFlowId flow_id = 123;
+ SpdyUtils::AddDatagramFlowIdHeader(&headers, flow_id);
+ EXPECT_EQ(SpdyUtils::ParseDatagramFlowIdHeader(headers), flow_id);
+ // Test empty header.
+ ValidateDatagramFlowId("", absl::nullopt);
+ // Test invalid header.
+ ValidateDatagramFlowId("M4SQU3", absl::nullopt);
+ // Test simple header.
+ ValidateDatagramFlowId("42", 42);
+ // Test with parameter.
+ ValidateDatagramFlowId("42; abc=def", 42);
+ // Test list.
+ ValidateDatagramFlowId("42, 44; ecn-ect0, 46; ecn-ect1, 48; ecn-ce", 42);
+ // Test reordered list.
+ ValidateDatagramFlowId("44; ecn-ect0, 42, 48; ecn-ce, 46; ecn-ect1", 42);
+}
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.cc b/chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.cc
new file mode 100644
index 00000000000..2a105c2e5bf
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.cc
@@ -0,0 +1,271 @@
+// 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 "quic/core/http/web_transport_http3.h"
+
+#include <memory>
+
+#include "absl/strings/string_view.h"
+#include "quic/core/http/quic_spdy_session.h"
+#include "quic/core/http/quic_spdy_stream.h"
+#include "quic/core/quic_data_reader.h"
+#include "quic/core/quic_data_writer.h"
+#include "quic/core/quic_stream.h"
+#include "quic/core/quic_types.h"
+#include "quic/core/quic_utils.h"
+#include "quic/core/quic_versions.h"
+#include "quic/platform/api/quic_bug_tracker.h"
+#include "common/platform/api/quiche_logging.h"
+
+#define ENDPOINT \
+ (session_->perspective() == Perspective::IS_SERVER ? "Server: " : "Client: ")
+
+namespace quic {
+
+namespace {
+class QUIC_NO_EXPORT NoopWebTransportVisitor : public WebTransportVisitor {
+ void OnSessionReady() override {}
+ void OnIncomingBidirectionalStreamAvailable() override {}
+ void OnIncomingUnidirectionalStreamAvailable() override {}
+ void OnDatagramReceived(absl::string_view /*datagram*/) override {}
+ void OnCanCreateNewOutgoingBidirectionalStream() override {}
+ void OnCanCreateNewOutgoingUnidirectionalStream() override {}
+};
+} // namespace
+
+WebTransportHttp3::WebTransportHttp3(QuicSpdySession* session,
+ QuicSpdyStream* connect_stream,
+ WebTransportSessionId id,
+ QuicDatagramFlowId flow_id)
+ : session_(session),
+ connect_stream_(connect_stream),
+ id_(id),
+ flow_id_(flow_id),
+ visitor_(std::make_unique<NoopWebTransportVisitor>()) {
+ QUICHE_DCHECK(session_->SupportsWebTransport());
+ QUICHE_DCHECK(IsValidWebTransportSessionId(id, session_->version()));
+ QUICHE_DCHECK_EQ(connect_stream_->id(), id);
+ session_->RegisterHttp3FlowId(flow_id, this);
+}
+
+void WebTransportHttp3::AssociateStream(QuicStreamId stream_id) {
+ streams_.insert(stream_id);
+
+ ParsedQuicVersion version = session_->version();
+ if (QuicUtils::IsOutgoingStreamId(version, stream_id,
+ session_->perspective())) {
+ return;
+ }
+ if (QuicUtils::IsBidirectionalStreamId(stream_id, version)) {
+ incoming_bidirectional_streams_.push_back(stream_id);
+ visitor_->OnIncomingBidirectionalStreamAvailable();
+ } else {
+ incoming_unidirectional_streams_.push_back(stream_id);
+ visitor_->OnIncomingUnidirectionalStreamAvailable();
+ }
+}
+
+void WebTransportHttp3::CloseAllAssociatedStreams() {
+ // Copy the stream list before iterating over it, as calls to ResetStream()
+ // can potentially mutate the |session_| list.
+ std::vector<QuicStreamId> streams(streams_.begin(), streams_.end());
+ streams_.clear();
+ for (QuicStreamId id : streams) {
+ session_->ResetStream(id, QUIC_STREAM_WEBTRANSPORT_SESSION_GONE);
+ }
+ session_->UnregisterHttp3FlowId(flow_id_);
+}
+
+void WebTransportHttp3::HeadersReceived(const spdy::SpdyHeaderBlock& headers) {
+ if (session_->perspective() == Perspective::IS_CLIENT) {
+ auto it = headers.find(":status");
+ if (it == headers.end() || it->second != "200") {
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Received WebTransport headers from server without "
+ "status 200, rejecting.";
+ return;
+ }
+ }
+
+ QUIC_DVLOG(1) << ENDPOINT << "WebTransport session " << id_ << " ready.";
+ ready_ = true;
+ visitor_->OnSessionReady();
+ session_->ProcessBufferedWebTransportStreamsForSession(this);
+}
+
+WebTransportStream* WebTransportHttp3::AcceptIncomingBidirectionalStream() {
+ while (!incoming_bidirectional_streams_.empty()) {
+ QuicStreamId id = incoming_bidirectional_streams_.front();
+ incoming_bidirectional_streams_.pop_front();
+ QuicSpdyStream* stream = session_->GetOrCreateSpdyDataStream(id);
+ if (stream == nullptr) {
+ // Skip the streams that were reset in between the time they were
+ // receieved and the time the client has polled for them.
+ continue;
+ }
+ return stream->web_transport_stream();
+ }
+ return nullptr;
+}
+
+WebTransportStream* WebTransportHttp3::AcceptIncomingUnidirectionalStream() {
+ while (!incoming_unidirectional_streams_.empty()) {
+ QuicStreamId id = incoming_unidirectional_streams_.front();
+ incoming_unidirectional_streams_.pop_front();
+ QuicStream* stream = session_->GetOrCreateStream(id);
+ if (stream == nullptr) {
+ // Skip the streams that were reset in between the time they were
+ // receieved and the time the client has polled for them.
+ continue;
+ }
+ return static_cast<WebTransportHttp3UnidirectionalStream*>(stream)
+ ->interface();
+ }
+ return nullptr;
+}
+
+bool WebTransportHttp3::CanOpenNextOutgoingBidirectionalStream() {
+ return session_->CanOpenOutgoingBidirectionalWebTransportStream(id_);
+}
+bool WebTransportHttp3::CanOpenNextOutgoingUnidirectionalStream() {
+ return session_->CanOpenOutgoingUnidirectionalWebTransportStream(id_);
+}
+WebTransportStream* WebTransportHttp3::OpenOutgoingBidirectionalStream() {
+ QuicSpdyStream* stream =
+ session_->CreateOutgoingBidirectionalWebTransportStream(this);
+ if (stream == nullptr) {
+ // If stream cannot be created due to flow control or other errors, return
+ // nullptr.
+ return nullptr;
+ }
+ return stream->web_transport_stream();
+}
+
+WebTransportStream* WebTransportHttp3::OpenOutgoingUnidirectionalStream() {
+ WebTransportHttp3UnidirectionalStream* stream =
+ session_->CreateOutgoingUnidirectionalWebTransportStream(this);
+ if (stream == nullptr) {
+ // If stream cannot be created due to flow control, return nullptr.
+ return nullptr;
+ }
+ return stream->interface();
+}
+
+MessageStatus WebTransportHttp3::SendOrQueueDatagram(QuicMemSlice datagram) {
+ return session_->SendHttp3Datagram(
+ flow_id_, absl::string_view(datagram.data(), datagram.length()));
+}
+
+void WebTransportHttp3::SetDatagramMaxTimeInQueue(
+ QuicTime::Delta max_time_in_queue) {
+ session_->SetMaxTimeInQueueForFlowId(flow_id_, max_time_in_queue);
+}
+
+void WebTransportHttp3::OnHttp3Datagram(QuicDatagramFlowId flow_id,
+ absl::string_view payload) {
+ QUICHE_DCHECK_EQ(flow_id, flow_id_);
+ visitor_->OnDatagramReceived(payload);
+}
+
+WebTransportHttp3UnidirectionalStream::WebTransportHttp3UnidirectionalStream(
+ PendingStream* pending,
+ QuicSpdySession* session)
+ : QuicStream(pending, session, READ_UNIDIRECTIONAL, /*is_static=*/false),
+ session_(session),
+ adapter_(session, this, sequencer()),
+ needs_to_send_preamble_(false) {}
+
+WebTransportHttp3UnidirectionalStream::WebTransportHttp3UnidirectionalStream(
+ QuicStreamId id,
+ QuicSpdySession* session,
+ WebTransportSessionId session_id)
+ : QuicStream(id, session, /*is_static=*/false, WRITE_UNIDIRECTIONAL),
+ session_(session),
+ adapter_(session, this, sequencer()),
+ session_id_(session_id),
+ needs_to_send_preamble_(true) {}
+
+void WebTransportHttp3UnidirectionalStream::WritePreamble() {
+ if (!needs_to_send_preamble_ || !session_id_.has_value()) {
+ QUIC_BUG(WebTransportHttp3UnidirectionalStream duplicate preamble)
+ << ENDPOINT << "Sending preamble on stream ID " << id()
+ << " at the wrong time.";
+ OnUnrecoverableError(QUIC_INTERNAL_ERROR,
+ "Attempting to send a WebTransport unidirectional "
+ "stream preamble at the wrong time.");
+ return;
+ }
+
+ QuicConnection::ScopedPacketFlusher flusher(session_->connection());
+ char buffer[sizeof(uint64_t) * 2]; // varint62, varint62
+ QuicDataWriter writer(sizeof(buffer), buffer);
+ bool success = true;
+ success = success && writer.WriteVarInt62(kWebTransportUnidirectionalStream);
+ success = success && writer.WriteVarInt62(*session_id_);
+ QUICHE_DCHECK(success);
+ WriteOrBufferData(absl::string_view(buffer, writer.length()), /*fin=*/false,
+ /*ack_listener=*/nullptr);
+ QUIC_DVLOG(1) << ENDPOINT << "Sent stream type and session ID ("
+ << *session_id_ << ") on WebTransport stream " << id();
+ needs_to_send_preamble_ = false;
+}
+
+bool WebTransportHttp3UnidirectionalStream::ReadSessionId() {
+ iovec iov;
+ if (!sequencer()->GetReadableRegion(&iov)) {
+ return false;
+ }
+ QuicDataReader reader(static_cast<const char*>(iov.iov_base), iov.iov_len);
+ WebTransportSessionId session_id;
+ uint8_t session_id_length = reader.PeekVarInt62Length();
+ if (!reader.ReadVarInt62(&session_id)) {
+ // If all of the data has been received, and we still cannot associate the
+ // stream with a session, consume all of the data so that the stream can
+ // be closed.
+ if (sequencer()->NumBytesConsumed() + sequencer()->NumBytesBuffered() >=
+ sequencer()->close_offset()) {
+ QUIC_DLOG(WARNING)
+ << ENDPOINT << "Failed to associate WebTransport stream " << id()
+ << " with a session because the stream ended prematurely.";
+ sequencer()->MarkConsumed(sequencer()->NumBytesBuffered());
+ }
+ return false;
+ }
+ sequencer()->MarkConsumed(session_id_length);
+ session_id_ = session_id;
+ session_->AssociateIncomingWebTransportStreamWithSession(session_id, id());
+ return true;
+}
+
+void WebTransportHttp3UnidirectionalStream::OnDataAvailable() {
+ if (!session_id_.has_value()) {
+ if (!ReadSessionId()) {
+ return;
+ }
+ }
+
+ adapter_.OnDataAvailable();
+}
+
+void WebTransportHttp3UnidirectionalStream::OnCanWriteNewData() {
+ adapter_.OnCanWriteNewData();
+}
+
+void WebTransportHttp3UnidirectionalStream::OnClose() {
+ QuicStream::OnClose();
+
+ if (!session_id_.has_value()) {
+ return;
+ }
+ WebTransportHttp3* session = session_->GetWebTransportSession(*session_id_);
+ if (session == nullptr) {
+ QUIC_DLOG(WARNING) << ENDPOINT << "WebTransport stream " << id()
+ << " attempted to notify parent session " << *session_id_
+ << ", but the session could not be found.";
+ return;
+ }
+ session->OnStreamClosed(id());
+}
+
+} // namespace quic
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
new file mode 100644
index 00000000000..0c91c2b32a4
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.h
@@ -0,0 +1,117 @@
+// 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_QUIC_CORE_HTTP_WEB_TRANSPORT_HTTP3_H_
+#define QUICHE_QUIC_CORE_HTTP_WEB_TRANSPORT_HTTP3_H_
+
+#include <memory>
+
+#include "absl/container/flat_hash_set.h"
+#include "absl/types/optional.h"
+#include "quic/core/http/quic_spdy_session.h"
+#include "quic/core/quic_stream.h"
+#include "quic/core/quic_types.h"
+#include "quic/core/web_transport_interface.h"
+#include "quic/core/web_transport_stream_adapter.h"
+#include "spdy/core/spdy_header_block.h"
+
+namespace quic {
+
+class QuicSpdySession;
+class QuicSpdyStream;
+
+// A session of WebTransport over HTTP/3. The session is owned by
+// QuicSpdyStream object for the CONNECT stream that established it.
+//
+// WebTransport over HTTP/3 specification:
+// <https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http3>
+class QUIC_EXPORT_PRIVATE WebTransportHttp3
+ : public WebTransportSession,
+ public QuicSpdySession::Http3DatagramVisitor {
+ public:
+ WebTransportHttp3(QuicSpdySession* session,
+ QuicSpdyStream* connect_stream,
+ WebTransportSessionId id,
+ QuicDatagramFlowId flow_id);
+
+ void HeadersReceived(const spdy::SpdyHeaderBlock& headers);
+ void SetVisitor(std::unique_ptr<WebTransportVisitor> visitor) {
+ visitor_ = std::move(visitor);
+ }
+
+ WebTransportSessionId id() { return id_; }
+ bool ready() { return ready_; }
+
+ void AssociateStream(QuicStreamId stream_id);
+ void OnStreamClosed(QuicStreamId stream_id) { streams_.erase(stream_id); }
+ void CloseAllAssociatedStreams();
+
+ size_t NumberOfAssociatedStreams() { return streams_.size(); }
+
+ // Return the earliest incoming stream that has been received by the session
+ // but has not been accepted. Returns nullptr if there are no incoming
+ // streams.
+ WebTransportStream* AcceptIncomingBidirectionalStream() override;
+ WebTransportStream* AcceptIncomingUnidirectionalStream() override;
+
+ bool CanOpenNextOutgoingBidirectionalStream() override;
+ bool CanOpenNextOutgoingUnidirectionalStream() override;
+ WebTransportStream* OpenOutgoingBidirectionalStream() override;
+ WebTransportStream* OpenOutgoingUnidirectionalStream() override;
+
+ MessageStatus SendOrQueueDatagram(QuicMemSlice datagram) override;
+ void SetDatagramMaxTimeInQueue(QuicTime::Delta max_time_in_queue) override;
+
+ void OnHttp3Datagram(QuicDatagramFlowId flow_id,
+ absl::string_view payload) override;
+
+ private:
+ QuicSpdySession* const session_; // Unowned.
+ QuicSpdyStream* const connect_stream_; // Unowned.
+ const WebTransportSessionId id_;
+ const QuicDatagramFlowId flow_id_;
+ // |ready_| is set to true when the peer has seen both sets of headers.
+ bool ready_ = false;
+ std::unique_ptr<WebTransportVisitor> visitor_;
+ absl::flat_hash_set<QuicStreamId> streams_;
+ QuicCircularDeque<QuicStreamId> incoming_bidirectional_streams_;
+ QuicCircularDeque<QuicStreamId> incoming_unidirectional_streams_;
+};
+
+class QUIC_EXPORT_PRIVATE WebTransportHttp3UnidirectionalStream
+ : public QuicStream {
+ public:
+ // Incoming stream.
+ WebTransportHttp3UnidirectionalStream(PendingStream* pending,
+ QuicSpdySession* session);
+ // Outgoing stream.
+ WebTransportHttp3UnidirectionalStream(QuicStreamId id,
+ QuicSpdySession* session,
+ WebTransportSessionId session_id);
+
+ // Sends the stream type and the session ID on the stream.
+ void WritePreamble();
+
+ // Implementation of QuicStream.
+ void OnDataAvailable() override;
+ void OnCanWriteNewData() override;
+ void OnClose() override;
+
+ WebTransportStream* interface() { return &adapter_; }
+ void SetUnblocked() { sequencer()->SetUnblocked(); }
+
+ private:
+ QuicSpdySession* session_;
+ WebTransportStreamAdapter adapter_;
+ absl::optional<WebTransportSessionId> session_id_;
+ bool needs_to_send_preamble_;
+
+ bool ReadSessionId();
+ // Closes the stream if all of the data has been received.
+ void MaybeCloseIncompleteStream();
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_HTTP_WEB_TRANSPORT_HTTP3_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc b/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc
index 07403f8de08..2ddf4b2498a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc
@@ -107,11 +107,11 @@ void LegacyQuicStreamIdManager::ActivateStream(bool is_incoming) {
void LegacyQuicStreamIdManager::OnStreamClosed(bool is_incoming) {
if (is_incoming) {
- QUIC_BUG_IF(num_open_incoming_streams_ == 0);
+ QUIC_BUG_IF(quic_bug_12720_1, num_open_incoming_streams_ == 0);
--num_open_incoming_streams_;
return;
}
- QUIC_BUG_IF(num_open_outgoing_streams_ == 0);
+ QUIC_BUG_IF(quic_bug_12720_2, num_open_outgoing_streams_ == 0);
--num_open_outgoing_streams_;
}
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 eec75dfdf0f..b83916060e9 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
@@ -147,7 +147,8 @@ template <typename... Args>
bool PacketNumberIndexedQueue<T>::Emplace(QuicPacketNumber packet_number,
Args&&... args) {
if (!packet_number.IsInitialized()) {
- QUIC_BUG << "Try to insert an uninitialized packet number";
+ QUIC_BUG(quic_bug_10359_1)
+ << "Try to insert an uninitialized packet number";
return false;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.cc
index f5ddeee36a4..9a5af7e42c3 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.cc
@@ -38,9 +38,13 @@ void QpackDecodedHeadersAccumulator::OnHeaderDecoded(absl::string_view name,
}
uncompressed_header_bytes_including_overhead_ +=
- name.size() + value.size() + QpackEntry::kSizeOverhead;
+ name.size() + value.size() + kQpackEntrySizeOverhead;
- if (uncompressed_header_bytes_including_overhead_ > max_header_list_size_) {
+ const size_t uncompressed_header_bytes =
+ GetQuicFlag(FLAGS_quic_header_size_limit_includes_overhead)
+ ? uncompressed_header_bytes_including_overhead_
+ : uncompressed_header_bytes_without_overhead_;
+ if (uncompressed_header_bytes > max_header_list_size_) {
header_list_size_limit_exceeded_ = true;
quic_header_list_.Clear();
} else {
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.cc
index c1ac28ca3d1..b9926167126 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.cc
@@ -81,11 +81,12 @@ void QpackDecoder::OnInsertWithNameReference(bool is_static,
return;
}
- entry = header_table_.InsertEntry(entry->name(), value);
- if (!entry) {
+ if (!header_table_.EntryFitsDynamicTableCapacity(entry->name(), value)) {
OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_ERROR_INSERTING_STATIC,
"Error inserting entry with name reference.");
+ return;
}
+ header_table_.InsertEntry(entry->name(), value);
return;
}
@@ -104,20 +105,22 @@ void QpackDecoder::OnInsertWithNameReference(bool is_static,
"Dynamic table entry not found.");
return;
}
- entry = header_table_.InsertEntry(entry->name(), value);
- if (!entry) {
+ if (!header_table_.EntryFitsDynamicTableCapacity(entry->name(), value)) {
OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_ERROR_INSERTING_DYNAMIC,
"Error inserting entry with name reference.");
+ return;
}
+ header_table_.InsertEntry(entry->name(), value);
}
void QpackDecoder::OnInsertWithoutNameReference(absl::string_view name,
absl::string_view value) {
- const QpackEntry* entry = header_table_.InsertEntry(name, value);
- if (!entry) {
+ if (!header_table_.EntryFitsDynamicTableCapacity(name, value)) {
OnErrorDetected(QUIC_QPACK_ENCODER_STREAM_ERROR_INSERTING_LITERAL,
"Error inserting literal entry.");
+ return;
}
+ header_table_.InsertEntry(name, value);
}
void QpackDecoder::OnDuplicate(uint64_t index) {
@@ -136,13 +139,13 @@ void QpackDecoder::OnDuplicate(uint64_t index) {
"Dynamic table entry not found.");
return;
}
- entry = header_table_.InsertEntry(entry->name(), entry->value());
- if (!entry) {
- // InsertEntry() can only fail if entry is larger then dynamic table
- // capacity, but that is impossible since entry was retrieved from the
- // dynamic table.
+ if (!header_table_.EntryFitsDynamicTableCapacity(entry->name(),
+ entry->value())) {
+ // This is impossible since entry was retrieved from the dynamic table.
OnErrorDetected(QUIC_INTERNAL_ERROR, "Error inserting duplicate entry.");
+ return;
}
+ header_table_.InsertEntry(entry->name(), entry->value());
}
void QpackDecoder::OnSetDynamicTableCapacity(uint64_t capacity) {
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 8138266b493..5e61ee7490b 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
@@ -44,7 +44,7 @@ QpackEncoder::QpackEncoder(
QpackEncoder::~QpackEncoder() {}
// static
-QpackInstructionWithValues QpackEncoder::EncodeIndexedHeaderField(
+QpackEncoder::Representation QpackEncoder::EncodeIndexedHeaderField(
bool is_static,
uint64_t index,
QpackBlockingManager::IndexSet* referred_indices) {
@@ -52,11 +52,11 @@ QpackInstructionWithValues QpackEncoder::EncodeIndexedHeaderField(
if (!is_static) {
referred_indices->insert(index);
}
- return QpackInstructionWithValues::IndexedHeaderField(is_static, index);
+ return Representation::IndexedHeaderField(is_static, index);
}
// static
-QpackInstructionWithValues
+QpackEncoder::Representation
QpackEncoder::EncodeLiteralHeaderFieldWithNameReference(
bool is_static,
uint64_t index,
@@ -66,18 +66,18 @@ QpackEncoder::EncodeLiteralHeaderFieldWithNameReference(
if (!is_static) {
referred_indices->insert(index);
}
- return QpackInstructionWithValues::LiteralHeaderFieldNameReference(
- is_static, index, value);
+ return Representation::LiteralHeaderFieldNameReference(is_static, index,
+ value);
}
// static
-QpackInstructionWithValues QpackEncoder::EncodeLiteralHeaderField(
+QpackEncoder::Representation QpackEncoder::EncodeLiteralHeaderField(
absl::string_view name,
absl::string_view value) {
- return QpackInstructionWithValues::LiteralHeaderField(name, value);
+ return Representation::LiteralHeaderField(name, value);
}
-QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
+QpackEncoder::Representations QpackEncoder::FirstPassEncode(
QuicStreamId stream_id,
const spdy::Http2HeaderBlock& header_list,
QpackBlockingManager::IndexSet* referred_indices,
@@ -87,8 +87,8 @@ QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
const QuicByteCount initial_encoder_stream_buffered_byte_count =
encoder_stream_sender_.BufferedByteCount();
- Instructions instructions;
- instructions.reserve(header_list.size());
+ Representations representations;
+ representations.reserve(header_list.size());
// The index of the oldest entry that must not be evicted.
uint64_t smallest_blocking_index =
@@ -125,7 +125,7 @@ QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
case QpackHeaderTable::MatchType::kNameAndValue:
if (is_static) {
// Refer to entry directly.
- instructions.push_back(
+ representations.push_back(
EncodeIndexedHeaderField(is_static, index, referred_indices));
break;
@@ -136,7 +136,7 @@ QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
if (!blocking_allowed && index >= known_received_count) {
blocked_stream_limit_exhausted = true;
} else {
- instructions.push_back(
+ representations.push_back(
EncodeIndexedHeaderField(is_static, index, referred_indices));
smallest_blocking_index = std::min(smallest_blocking_index, index);
header_table_.set_dynamic_table_entry_referenced();
@@ -156,9 +156,9 @@ QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
encoder_stream_sender_.SendDuplicate(
QpackAbsoluteIndexToEncoderStreamRelativeIndex(
index, header_table_.inserted_entry_count()));
- auto entry = header_table_.InsertEntry(name, value);
- instructions.push_back(EncodeIndexedHeaderField(
- is_static, entry->InsertionIndex(), referred_indices));
+ uint64_t new_index = header_table_.InsertEntry(name, value);
+ representations.push_back(EncodeIndexedHeaderField(
+ is_static, new_index, referred_indices));
smallest_blocking_index = std::min(smallest_blocking_index, index);
header_table_.set_dynamic_table_entry_referenced();
@@ -171,7 +171,7 @@ QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
// exists.
// TODO(b/112770235): Use static entry name with literal value if
// dynamic entry exists but cannot be used.
- instructions.push_back(EncodeLiteralHeaderField(name, value));
+ representations.push_back(EncodeLiteralHeaderField(name, value));
break;
@@ -184,18 +184,17 @@ QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
// If allowed, insert entry into dynamic table and refer to it.
encoder_stream_sender_.SendInsertWithNameReference(is_static, index,
value);
- auto entry = header_table_.InsertEntry(name, value);
- instructions.push_back(EncodeIndexedHeaderField(
- /* is_static = */ false, entry->InsertionIndex(),
- referred_indices));
- smallest_blocking_index = std::min<uint64_t>(
- smallest_blocking_index, entry->InsertionIndex());
+ uint64_t new_index = header_table_.InsertEntry(name, value);
+ representations.push_back(EncodeIndexedHeaderField(
+ /* is_static = */ false, new_index, referred_indices));
+ smallest_blocking_index =
+ std::min<uint64_t>(smallest_blocking_index, new_index);
break;
}
// Emit literal field with name reference.
- instructions.push_back(EncodeLiteralHeaderFieldWithNameReference(
+ representations.push_back(EncodeLiteralHeaderFieldWithNameReference(
is_static, index, value, referred_indices));
break;
@@ -214,9 +213,9 @@ QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
QpackAbsoluteIndexToEncoderStreamRelativeIndex(
index, header_table_.inserted_entry_count()),
value);
- auto entry = header_table_.InsertEntry(name, value);
- instructions.push_back(EncodeIndexedHeaderField(
- is_static, entry->InsertionIndex(), referred_indices));
+ uint64_t new_index = header_table_.InsertEntry(name, value);
+ representations.push_back(
+ EncodeIndexedHeaderField(is_static, new_index, referred_indices));
smallest_blocking_index = std::min(smallest_blocking_index, index);
header_table_.set_dynamic_table_entry_referenced();
@@ -226,7 +225,7 @@ QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
if ((blocking_allowed || index < known_received_count) &&
index >= draining_index) {
// If allowed, refer to entry name directly, with literal value.
- instructions.push_back(EncodeLiteralHeaderFieldWithNameReference(
+ representations.push_back(EncodeLiteralHeaderFieldWithNameReference(
is_static, index, value, referred_indices));
smallest_blocking_index = std::min(smallest_blocking_index, index);
header_table_.set_dynamic_table_entry_referenced();
@@ -239,7 +238,7 @@ QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
// exists.
// TODO(b/112770235): Use static entry name with literal value if
// dynamic entry exists but cannot be used.
- instructions.push_back(EncodeLiteralHeaderField(name, value));
+ representations.push_back(EncodeLiteralHeaderField(name, value));
break;
@@ -253,12 +252,11 @@ QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
dynamic_table_insertion_blocked = true;
} else {
encoder_stream_sender_.SendInsertWithoutNameReference(name, value);
- auto entry = header_table_.InsertEntry(name, value);
- instructions.push_back(EncodeIndexedHeaderField(
- /* is_static = */ false, entry->InsertionIndex(),
- referred_indices));
- smallest_blocking_index = std::min<uint64_t>(smallest_blocking_index,
- entry->InsertionIndex());
+ uint64_t new_index = header_table_.InsertEntry(name, value);
+ representations.push_back(EncodeIndexedHeaderField(
+ /* is_static = */ false, new_index, referred_indices));
+ smallest_blocking_index =
+ std::min<uint64_t>(smallest_blocking_index, new_index);
break;
}
@@ -267,7 +265,7 @@ QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
// TODO(b/112770235): Consider also adding to dynamic table to improve
// compression ratio for subsequent header blocks with peers that do not
// allow any blocked streams.
- instructions.push_back(EncodeLiteralHeaderField(name, value));
+ representations.push_back(EncodeLiteralHeaderField(name, value));
break;
}
@@ -322,34 +320,34 @@ QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
"prevent referencing unacknowledged dynamic table entries.");
}
- return instructions;
+ return representations;
}
std::string QpackEncoder::SecondPassEncode(
- QpackEncoder::Instructions instructions,
+ QpackEncoder::Representations representations,
uint64_t required_insert_count) const {
QpackInstructionEncoder instruction_encoder;
std::string encoded_headers;
// Header block prefix.
instruction_encoder.Encode(
- QpackInstructionWithValues::Prefix(QpackEncodeRequiredInsertCount(
+ Representation::Prefix(QpackEncodeRequiredInsertCount(
required_insert_count, header_table_.max_entries())),
&encoded_headers);
const uint64_t base = required_insert_count;
- for (auto& instruction : instructions) {
+ for (auto& representation : representations) {
// Dynamic table references must be transformed from absolute to relative
// indices.
- if ((instruction.instruction() == QpackIndexedHeaderFieldInstruction() ||
- instruction.instruction() ==
+ if ((representation.instruction() == QpackIndexedHeaderFieldInstruction() ||
+ representation.instruction() ==
QpackLiteralHeaderFieldNameReferenceInstruction()) &&
- !instruction.s_bit()) {
- instruction.set_varint(QpackAbsoluteIndexToRequestStreamRelativeIndex(
- instruction.varint(), base));
+ !representation.s_bit()) {
+ representation.set_varint(QpackAbsoluteIndexToRequestStreamRelativeIndex(
+ representation.varint(), base));
}
- instruction_encoder.Encode(instruction, &encoded_headers);
+ instruction_encoder.Encode(representation, &encoded_headers);
}
return encoded_headers;
@@ -363,8 +361,8 @@ std::string QpackEncoder::EncodeHeaderList(
// that it can be passed to QpackBlockingManager.
QpackBlockingManager::IndexSet referred_indices;
- // First pass: encode into |instructions|.
- Instructions instructions =
+ // First pass: encode into |representations|.
+ Representations representations =
FirstPassEncode(stream_id, header_list, &referred_indices,
encoder_stream_sent_byte_count);
@@ -377,7 +375,7 @@ std::string QpackEncoder::EncodeHeaderList(
}
// Second pass.
- return SecondPassEncode(std::move(instructions), required_insert_count);
+ return SecondPassEncode(std::move(representations), required_insert_count);
}
bool QpackEncoder::SetMaximumDynamicTableCapacity(
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 3d95f6e3249..9d024417c93 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
@@ -105,27 +105,27 @@ class QUIC_EXPORT_PRIVATE QpackEncoder
private:
friend class test::QpackEncoderPeer;
- using Instructions = std::vector<QpackInstructionWithValues>;
+ using Representation = QpackInstructionWithValues;
+ using Representations = std::vector<Representation>;
- // Generate indexed header field instruction
+ // Generate indexed header field representation
// and optionally update |*referred_indices|.
- static QpackInstructionWithValues EncodeIndexedHeaderField(
+ static Representation EncodeIndexedHeaderField(
bool is_static,
uint64_t index,
QpackBlockingManager::IndexSet* referred_indices);
- // Generate literal header field with name reference instruction
+ // Generate literal header field with name reference representation
// and optionally update |*referred_indices|.
- static QpackInstructionWithValues EncodeLiteralHeaderFieldWithNameReference(
+ static Representation EncodeLiteralHeaderFieldWithNameReference(
bool is_static,
uint64_t index,
absl::string_view value,
QpackBlockingManager::IndexSet* referred_indices);
- // Generate literal header field instruction.
- static QpackInstructionWithValues EncodeLiteralHeaderField(
- absl::string_view name,
- absl::string_view value);
+ // Generate literal header field representation.
+ static Representation EncodeLiteralHeaderField(absl::string_view name,
+ absl::string_view value);
// Performs first pass of two-pass encoding: represent each header field in
// |*header_list| as a reference to an existing entry, the name of an existing
@@ -136,17 +136,18 @@ class QUIC_EXPORT_PRIVATE QpackEncoder
// sets |*encoder_stream_sent_byte_count| to the number of bytes sent on the
// encoder stream to insert dynamic table entries. Returns list of header
// field representations, with all dynamic table entries referred to with
- // absolute indices. Returned Instructions object may have
+ // absolute indices. Returned representation objects may have
// absl::string_views pointing to strings owned by |*header_list|.
- Instructions FirstPassEncode(QuicStreamId stream_id,
- const spdy::Http2HeaderBlock& header_list,
- QpackBlockingManager::IndexSet* referred_indices,
- QuicByteCount* encoder_stream_sent_byte_count);
+ Representations FirstPassEncode(
+ QuicStreamId stream_id,
+ const spdy::Http2HeaderBlock& header_list,
+ QpackBlockingManager::IndexSet* referred_indices,
+ QuicByteCount* encoder_stream_sent_byte_count);
// Performs second pass of two-pass encoding: serializes representations
// generated in first pass, transforming absolute indices of dynamic table
// entries to relative indices.
- std::string SecondPassEncode(Instructions instructions,
+ std::string SecondPassEncode(Representations representations,
uint64_t required_insert_count) const;
DecoderStreamErrorDelegate* const decoder_stream_error_delegate_;
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 6171d8455a4..da3636db4e4 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
@@ -55,22 +55,20 @@ QpackHeaderTable::MatchType QpackHeaderTable::FindHeaderField(
absl::string_view value,
bool* is_static,
uint64_t* index) const {
- QpackEntry query(name, value);
+ QpackLookupEntry query{name, value};
// Look for exact match in static table.
- auto index_it = static_index_.find(&query);
+ auto index_it = static_index_.find(query);
if (index_it != static_index_.end()) {
- QUICHE_DCHECK((*index_it)->IsStatic());
- *index = (*index_it)->InsertionIndex();
+ *index = index_it->second;
*is_static = true;
return MatchType::kNameAndValue;
}
// Look for exact match in dynamic table.
- index_it = dynamic_index_.find(&query);
+ index_it = dynamic_index_.find(query);
if (index_it != dynamic_index_.end()) {
- QUICHE_DCHECK(!(*index_it)->IsStatic());
- *index = (*index_it)->InsertionIndex();
+ *index = index_it->second;
*is_static = false;
return MatchType::kNameAndValue;
}
@@ -78,8 +76,7 @@ QpackHeaderTable::MatchType QpackHeaderTable::FindHeaderField(
// Look for name match in static table.
auto name_index_it = static_name_index_.find(name);
if (name_index_it != static_name_index_.end()) {
- QUICHE_DCHECK(name_index_it->second->IsStatic());
- *index = name_index_it->second->InsertionIndex();
+ *index = name_index_it->second;
*is_static = true;
return MatchType::kName;
}
@@ -87,8 +84,7 @@ QpackHeaderTable::MatchType QpackHeaderTable::FindHeaderField(
// Look for name match in dynamic table.
name_index_it = dynamic_name_index_.find(name);
if (name_index_it != dynamic_name_index_.end()) {
- QUICHE_DCHECK(!name_index_it->second->IsStatic());
- *index = name_index_it->second->InsertionIndex();
+ *index = name_index_it->second;
*is_static = false;
return MatchType::kName;
}
@@ -96,43 +92,54 @@ QpackHeaderTable::MatchType QpackHeaderTable::FindHeaderField(
return MatchType::kNoMatch;
}
-const QpackEntry* QpackHeaderTable::InsertEntry(absl::string_view name,
- absl::string_view value) {
- const uint64_t entry_size = QpackEntry::Size(name, value);
- if (entry_size > dynamic_table_capacity_) {
- return nullptr;
- }
+bool QpackHeaderTable::EntryFitsDynamicTableCapacity(
+ absl::string_view name,
+ absl::string_view value) const {
+ return QpackEntry::Size(name, value) <= dynamic_table_capacity_;
+}
+
+uint64_t QpackHeaderTable::InsertEntry(absl::string_view name,
+ absl::string_view value) {
+ QUICHE_DCHECK(EntryFitsDynamicTableCapacity(name, value));
const uint64_t index = dropped_entry_count_ + dynamic_entries_.size();
- dynamic_entries_.push_back({name, value, /* is_static = */ false, index});
- QpackEntry* const new_entry = &dynamic_entries_.back();
- // Evict entries after inserting the new entry instead of before
- // in order to avoid invalidating |name| and |value|.
+ // 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;
- EvictDownToCurrentCapacity();
+ dynamic_entries_.push_back(std::move(new_entry));
+
+ // Make name and value point to the new entry.
+ name = dynamic_entries_.back().name();
+ value = dynamic_entries_.back().value();
- auto index_result = dynamic_index_.insert(new_entry);
+ 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(new_entry->InsertionIndex(),
- (*index_result.first)->InsertionIndex());
+ QUICHE_DCHECK_GT(index, index_result.first->second);
dynamic_index_.erase(index_result.first);
- auto result = dynamic_index_.insert(new_entry);
+ auto result = dynamic_index_.insert(
+ std::make_pair(QpackLookupEntry{name, value}, index));
QUICHE_CHECK(result.second);
}
- auto name_result = dynamic_name_index_.insert({new_entry->name(), new_entry});
+ 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(new_entry->InsertionIndex(),
- name_result.first->second->InsertionIndex());
+ QUICHE_DCHECK_GT(index, name_result.first->second);
dynamic_name_index_.erase(name_result.first);
- auto result = dynamic_name_index_.insert({new_entry->name(), new_entry});
+ auto result = dynamic_name_index_.insert({name, index});
QUICHE_CHECK(result.second);
}
@@ -147,7 +154,7 @@ const QpackEntry* QpackHeaderTable::InsertEntry(absl::string_view name,
observer->OnInsertCountReachedThreshold();
}
- return new_entry;
+ return index;
}
uint64_t QpackHeaderTable::MaxInsertSizeWithoutEvictingGivenEntry(
@@ -162,10 +169,12 @@ uint64_t QpackHeaderTable::MaxInsertSizeWithoutEvictingGivenEntry(
// 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.InsertionIndex() >= index) {
+ if (entry_index >= index) {
break;
}
+ ++entry_index;
max_insert_size += entry.Size();
}
@@ -178,7 +187,7 @@ bool QpackHeaderTable::SetDynamicTableCapacity(uint64_t capacity) {
}
dynamic_table_capacity_ = capacity;
- EvictDownToCurrentCapacity();
+ EvictDownToCapacity(capacity);
QUICHE_DCHECK_LE(dynamic_table_size_, dynamic_table_capacity_);
@@ -231,41 +240,42 @@ uint64_t QpackHeaderTable::draining_index(float draining_fraction) const {
}
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 it->InsertionIndex();
+ return entry_index;
}
-void QpackHeaderTable::EvictDownToCurrentCapacity() {
- while (dynamic_table_size_ > dynamic_table_capacity_) {
+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();
+ const uint64_t entry_size = entry->Size();
QUICHE_DCHECK_GE(dynamic_table_size_, entry_size);
dynamic_table_size_ -= entry_size;
- auto index_it = dynamic_index_.find(entry);
+ 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_|. Note that |dynamic_index_| has a
- // comparison function that only considers name and value, not actual
- // QpackEntry* address, so find() can return a different entry if name and
- // value match.
- if (index_it != dynamic_index_.end() && *index_it == entry) {
+ // 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 == entry) {
+ if (name_it != dynamic_name_index_.end() && name_it->second == index) {
dynamic_name_index_.erase(name_it);
}
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 4f0a1b5e032..a5d6c5d74b8 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
@@ -24,16 +24,17 @@ 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 {
public:
- using EntryTable = spdy::HpackHeaderTable::EntryTable;
- using EntryHasher = spdy::HpackHeaderTable::EntryHasher;
- using EntriesEq = spdy::HpackHeaderTable::EntriesEq;
- using UnorderedEntrySet = spdy::HpackHeaderTable::UnorderedEntrySet;
+ using StaticEntryTable = spdy::HpackHeaderTable::StaticEntryTable;
+ using DynamicEntryTable = spdy::HpackHeaderTable::DynamicEntryTable;
+ using NameValueToEntryMap = spdy::HpackHeaderTable::NameValueToEntryMap;
using NameToEntryMap = spdy::HpackHeaderTable::NameToEntryMap;
// Result of header table lookup.
@@ -75,11 +76,20 @@ class QUIC_EXPORT_PRIVATE QpackHeaderTable {
bool* is_static,
uint64_t* index) const;
- // Insert (name, value) into the dynamic table. May evict entries. Returns a
- // pointer to the inserted owned entry on success. Returns nullptr if entry
- // is larger than the capacity of the dynamic table.
- const QpackEntry* InsertEntry(absl::string_view name,
- absl::string_view value);
+ // 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
+ // table.
+ bool EntryFitsDynamicTableCapacity(absl::string_view name,
+ absl::string_view value) const;
+
+ // Inserts (name, value) into the dynamic table. Entry must not be larger
+ // than the capacity of the dynamic table. May evict entries. |name| and
+ // |value| are copied first, therefore it is safe for them to point to an
+ // entry in the dynamic table, even if it is about to be evicted, or even if
+ // 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
@@ -150,8 +160,8 @@ class QUIC_EXPORT_PRIVATE QpackHeaderTable {
friend class test::QpackHeaderTablePeer;
// Evict entries from the dynamic table until table size is less than or equal
- // to current value of |dynamic_table_capacity_|.
- void EvictDownToCurrentCapacity();
+ // to |capacity|.
+ void EvictDownToCapacity(uint64_t capacity);
// Static Table
@@ -159,10 +169,10 @@ class QUIC_EXPORT_PRIVATE QpackHeaderTable {
// QpackStaticTable singleton.
// Tracks QpackEntries by index.
- const EntryTable& static_entries_;
+ const StaticEntryTable& static_entries_;
// Tracks the unique static entry for a given header name and value.
- const UnorderedEntrySet& static_index_;
+ const NameValueToEntryMap& static_index_;
// Tracks the first static entry for a given header name.
const NameToEntryMap& static_name_index_;
@@ -171,13 +181,13 @@ class QUIC_EXPORT_PRIVATE QpackHeaderTable {
// Queue of dynamic table entries, for lookup by index.
// |dynamic_entries_| owns the entries in the dynamic table.
- EntryTable dynamic_entries_;
+ 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_|.
- UnorderedEntrySet dynamic_index_;
+ 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
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 801ab8f8062..0af250efd32 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
@@ -81,13 +81,13 @@ class QpackHeaderTableTest : public QuicTest {
<< name << ": " << value;
}
- void InsertEntry(absl::string_view name, absl::string_view value) {
- EXPECT_TRUE(table_.InsertEntry(name, value));
+ bool EntryFitsDynamicTableCapacity(absl::string_view name,
+ absl::string_view value) const {
+ return table_.EntryFitsDynamicTableCapacity(name, value);
}
- void ExpectToFailInsertingEntry(absl::string_view name,
- absl::string_view value) {
- EXPECT_FALSE(table_.InsertEntry(name, value));
+ void InsertEntry(absl::string_view name, absl::string_view value) {
+ table_.InsertEntry(name, value);
}
bool SetDynamicTableCapacity(uint64_t capacity) {
@@ -293,9 +293,6 @@ TEST_F(QpackHeaderTableTest, EvictByInsertion) {
ExpectNoMatch("foo", "bar");
ExpectMatch("baz", "qux", QpackHeaderTable::MatchType::kNameAndValue,
/* expected_is_static = */ false, 1u);
-
- // Inserting an entry that does not fit results in error.
- ExpectToFailInsertingEntry("foobar", "foobar");
}
TEST_F(QpackHeaderTableTest, EvictByUpdateTableSize) {
@@ -389,7 +386,7 @@ TEST_F(QpackHeaderTableTest, MaxInsertSizeWithoutEvictingGivenEntry) {
table.MaxInsertSizeWithoutEvictingGivenEntry(0));
const uint64_t entry_size1 = QpackEntry::Size("foo", "bar");
- EXPECT_TRUE(table.InsertEntry("foo", "bar"));
+ table.InsertEntry("foo", "bar");
EXPECT_EQ(dynamic_table_capacity - entry_size1,
table.MaxInsertSizeWithoutEvictingGivenEntry(0));
// Table can take an entry up to its capacity if all entries are allowed to be
@@ -398,7 +395,7 @@ TEST_F(QpackHeaderTableTest, MaxInsertSizeWithoutEvictingGivenEntry) {
table.MaxInsertSizeWithoutEvictingGivenEntry(1));
const uint64_t entry_size2 = QpackEntry::Size("baz", "foobar");
- EXPECT_TRUE(table.InsertEntry("baz", "foobar"));
+ table.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,
@@ -412,7 +409,7 @@ TEST_F(QpackHeaderTableTest, MaxInsertSizeWithoutEvictingGivenEntry) {
// Third entry evicts first one.
const uint64_t entry_size3 = QpackEntry::Size("last", "entry");
- EXPECT_TRUE(table.InsertEntry("last", "entry"));
+ table.InsertEntry("last", "entry");
EXPECT_EQ(1u, table.dropped_entry_count());
// Table can take an entry up to its capacity if all entries are allowed to be
// evicted.
@@ -497,14 +494,14 @@ TEST_F(QpackHeaderTableTest, DrainingIndex) {
EXPECT_EQ(0u, table.draining_index(1.0));
// Table with one entry.
- EXPECT_TRUE(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));
// 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.
- EXPECT_TRUE(table.InsertEntry("foo", "bar"));
+ 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));
@@ -513,8 +510,8 @@ TEST_F(QpackHeaderTableTest, DrainingIndex) {
EXPECT_EQ(2u, table.draining_index(1.0));
// Table with four entries is full.
- EXPECT_TRUE(table.InsertEntry("foo", "bar"));
- EXPECT_TRUE(table.InsertEntry("foo", "bar"));
+ 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
@@ -533,6 +530,14 @@ TEST_F(QpackHeaderTableTest, 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.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.cc
index bf786a44a55..495a58ffdfd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.cc
@@ -127,7 +127,7 @@ bool QpackInstructionDecoder::DoStartField() {
state_ = State::kVarintStart;
return true;
default:
- QUIC_BUG << "Invalid field type.";
+ QUIC_BUG(quic_bug_10767_1) << "Invalid field type.";
return false;
}
}
@@ -157,7 +157,7 @@ bool QpackInstructionDecoder::DoReadBit(absl::string_view data) {
return true;
}
default:
- QUIC_BUG << "Invalid field type.";
+ QUIC_BUG(quic_bug_10767_2) << "Invalid field type.";
return false;
}
}
@@ -186,7 +186,7 @@ bool QpackInstructionDecoder::DoVarintStart(absl::string_view data,
OnError(ErrorCode::INTEGER_TOO_LARGE, "Encoded integer too large.");
return false;
default:
- QUIC_BUG << "Unknown decode status " << status;
+ QUIC_BUG(quic_bug_10767_3) << "Unknown decode status " << status;
return false;
}
}
@@ -215,7 +215,7 @@ bool QpackInstructionDecoder::DoVarintResume(absl::string_view data,
OnError(ErrorCode::INTEGER_TOO_LARGE, "Encoded integer too large.");
return false;
default:
- QUIC_BUG << "Unknown decode status " << status;
+ QUIC_BUG(quic_bug_10767_4) << "Unknown decode status " << status;
return false;
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream.h
index c9d2a775e57..6c04b942e5d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream.h
@@ -33,8 +33,6 @@ class QUIC_EXPORT_PRIVATE QpackReceiveStream : public QuicStream {
// Implementation of QuicStream.
void OnDataAvailable() override;
- void SetUnblocked() { sequencer()->SetUnblocked(); }
-
private:
QpackStreamReceiver* receiver_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.cc
index 636f4b477b3..0d5d8af79ef 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.cc
@@ -17,7 +17,8 @@ QpackSendStream::QpackSendStream(QuicStreamId id,
stream_type_sent_(false) {}
void QpackSendStream::OnStreamReset(const QuicRstStreamFrame& /*frame*/) {
- QUIC_BUG << "OnStreamReset() called for write unidirectional stream.";
+ QUIC_BUG(quic_bug_10805_1)
+ << "OnStreamReset() called for write unidirectional stream.";
}
bool QpackSendStream::OnStopSending(QuicRstStreamErrorCode /* code */) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table_test.cc
index 734d25320df..53ab0f49a04 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table_test.cc
@@ -25,16 +25,17 @@ TEST(QpackStaticTableTest, Initialize) {
QpackStaticTableVector().size());
EXPECT_TRUE(table.IsInitialized());
- auto static_entries = table.GetStaticEntries();
+ const auto& static_entries = table.GetStaticEntries();
EXPECT_EQ(QpackStaticTableVector().size(), static_entries.size());
- auto static_index = table.GetStaticIndex();
+ const auto& static_index = table.GetStaticIndex();
EXPECT_EQ(QpackStaticTableVector().size(), static_index.size());
- auto static_name_index = table.GetStaticNameIndex();
+ const auto& static_name_index = table.GetStaticNameIndex();
+ // Count distinct names in static table.
std::set<absl::string_view> names;
- for (auto entry : static_index) {
- names.insert(entry->name());
+ for (const auto& entry : static_entries) {
+ names.insert(entry.name());
}
EXPECT_EQ(names.size(), static_name_index.size());
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.cc b/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.cc
index b9e3d10c69b..e4d4c971338 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.cc
@@ -87,14 +87,16 @@ EnqueuePacketResult QuicBufferedPacketStore::EnqueuePacket(
QuicSocketAddress peer_address,
bool is_chlo,
const std::vector<std::string>& alpns,
+ const absl::string_view sni,
const ParsedQuicVersion& version) {
- QUIC_BUG_IF(!GetQuicFlag(FLAGS_quic_allow_chlo_buffering))
+ QUIC_BUG_IF(quic_bug_12410_1, !GetQuicFlag(FLAGS_quic_allow_chlo_buffering))
<< "Shouldn't buffer packets if disabled via flag.";
- QUIC_BUG_IF(is_chlo && QuicContainsKey(connections_with_chlo_, connection_id))
+ QUIC_BUG_IF(quic_bug_12410_2,
+ is_chlo && QuicContainsKey(connections_with_chlo_, connection_id))
<< "Shouldn't buffer duplicated CHLO on connection " << connection_id;
- QUIC_BUG_IF(!is_chlo && !alpns.empty())
+ QUIC_BUG_IF(quic_bug_12410_3, !is_chlo && !alpns.empty())
<< "Shouldn't have an ALPN defined for a non-CHLO packet.";
- QUIC_BUG_IF(is_chlo && !version.IsKnown())
+ QUIC_BUG_IF(quic_bug_12410_4, is_chlo && !version.IsKnown())
<< "Should have version for CHLO packet.";
const bool is_first_packet =
@@ -141,6 +143,7 @@ EnqueuePacketResult QuicBufferedPacketStore::EnqueuePacket(
// first later.
queue.buffered_packets.push_front(std::move(new_entry));
queue.alpns = alpns;
+ queue.sni = std::string(sni);
connections_with_chlo_[connection_id] = false; // Dummy value.
// Set the version of buffered packets of this connection on CHLO.
queue.version = version;
@@ -153,7 +156,8 @@ EnqueuePacketResult QuicBufferedPacketStore::EnqueuePacket(
queue.tls_chlo_extractor.IngestPacket(version, packet);
// Since this is the first packet and it's not a CHLO, the
// TlsChloExtractor should not have the entire CHLO.
- QUIC_BUG_IF(queue.tls_chlo_extractor.HasParsedFullChlo())
+ QUIC_BUG_IF(quic_bug_12410_5,
+ queue.tls_chlo_extractor.HasParsedFullChlo())
<< "First packet in list should not contain full CHLO";
}
// TODO(b/154857081) Reorder CHLO packets ahead of other ones.
@@ -257,13 +261,15 @@ bool QuicBufferedPacketStore::IngestPacketForTlsChloExtraction(
const QuicConnectionId& connection_id,
const ParsedQuicVersion& version,
const QuicReceivedPacket& packet,
- std::vector<std::string>* out_alpns) {
+ std::vector<std::string>* out_alpns,
+ std::string* out_sni) {
QUICHE_DCHECK_NE(out_alpns, nullptr);
+ QUICHE_DCHECK_NE(out_sni, nullptr);
QUICHE_DCHECK_EQ(version.handshake_protocol, PROTOCOL_TLS1_3);
auto it = undecryptable_packets_.find(connection_id);
if (it == undecryptable_packets_.end()) {
- QUIC_BUG << "Cannot ingest packet for unknown connection ID "
- << connection_id;
+ QUIC_BUG(quic_bug_10838_1)
+ << "Cannot ingest packet for unknown connection ID " << connection_id;
return false;
}
it->second.tls_chlo_extractor.IngestPacket(version, packet);
@@ -271,6 +277,7 @@ bool QuicBufferedPacketStore::IngestPacketForTlsChloExtraction(
return false;
}
*out_alpns = it->second.tls_chlo_extractor.alpns();
+ *out_sni = it->second.tls_chlo_extractor.server_name();
return true;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h b/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h
index c8f6375a30e..29be2c86a42 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h
@@ -69,6 +69,7 @@ class QUIC_NO_EXPORT QuicBufferedPacketStore {
QuicTime creation_time;
// The ALPNs from the CHLO, if found.
std::vector<std::string> alpns;
+ std::string sni;
// Indicating whether this is an IETF QUIC connection.
bool ietf_quic;
// If buffered_packets contains the CHLO, it is the version of the CHLO.
@@ -110,6 +111,7 @@ class QUIC_NO_EXPORT QuicBufferedPacketStore {
QuicSocketAddress peer_address,
bool is_chlo,
const std::vector<std::string>& alpns,
+ const absl::string_view sni,
const ParsedQuicVersion& version);
// Returns true if there are any packets buffered for |connection_id|.
@@ -119,11 +121,12 @@ class QUIC_NO_EXPORT QuicBufferedPacketStore {
// only be called when HasBufferedPackets(connection_id) is true.
// Returns whether we've now parsed a full multi-packet TLS CHLO.
// When this returns true, |out_alpns| is populated with the list of ALPNs
- // extracted from the CHLO.
+ // extracted from the CHLO. |out_sni| is populated with the SNI tag in CHLO.
bool IngestPacketForTlsChloExtraction(const QuicConnectionId& connection_id,
const ParsedQuicVersion& version,
const QuicReceivedPacket& packet,
- std::vector<std::string>* out_alpns);
+ std::vector<std::string>* out_alpns,
+ std::string* out_sni);
// Returns the list of buffered packets for |connection_id| and removes them
// from the store. Returns an empty list if no early arrived packets for this
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store_test.cc
index 1d9cce7647f..c5d11f22811 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store_test.cc
@@ -70,7 +70,7 @@ class QuicBufferedPacketStoreTest : public QuicTest {
TEST_F(QuicBufferedPacketStoreTest, SimpleEnqueueAndDeliverPacket) {
QuicConnectionId connection_id = TestConnectionId(1);
store_.EnqueuePacket(connection_id, false, packet_, self_address_,
- peer_address_, false, {}, invalid_version_);
+ peer_address_, false, {}, "", invalid_version_);
EXPECT_TRUE(store_.HasBufferedPackets(connection_id));
auto packets = store_.DeliverPackets(connection_id);
const std::list<BufferedPacket>& queue = packets.buffered_packets;
@@ -93,9 +93,9 @@ TEST_F(QuicBufferedPacketStoreTest, DifferentPacketAddressOnOneConnection) {
QuicSocketAddress addr_with_new_port(QuicIpAddress::Any4(), 256);
QuicConnectionId connection_id = TestConnectionId(1);
store_.EnqueuePacket(connection_id, false, packet_, self_address_,
- peer_address_, false, {}, invalid_version_);
+ peer_address_, false, {}, "", invalid_version_);
store_.EnqueuePacket(connection_id, false, packet_, self_address_,
- addr_with_new_port, false, {}, invalid_version_);
+ addr_with_new_port, false, {}, "", invalid_version_);
std::list<BufferedPacket> queue =
store_.DeliverPackets(connection_id).buffered_packets;
ASSERT_EQ(2u, queue.size());
@@ -110,9 +110,9 @@ TEST_F(QuicBufferedPacketStoreTest,
for (uint64_t conn_id = 1; conn_id <= num_connections; ++conn_id) {
QuicConnectionId connection_id = TestConnectionId(conn_id);
store_.EnqueuePacket(connection_id, false, packet_, self_address_,
- peer_address_, false, {}, invalid_version_);
+ peer_address_, false, {}, "", invalid_version_);
store_.EnqueuePacket(connection_id, false, packet_, self_address_,
- peer_address_, false, {}, invalid_version_);
+ peer_address_, false, {}, "", invalid_version_);
}
// Deliver packets in reversed order.
@@ -134,12 +134,12 @@ TEST_F(QuicBufferedPacketStoreTest,
// keep.
EXPECT_EQ(QuicBufferedPacketStore::SUCCESS,
store_.EnqueuePacket(connection_id, false, packet_, self_address_,
- peer_address_, true, {}, valid_version_));
+ peer_address_, true, {}, "", valid_version_));
for (size_t i = 1; i <= num_packets; ++i) {
// Only first |kDefaultMaxUndecryptablePackets packets| will be buffered.
EnqueuePacketResult result =
store_.EnqueuePacket(connection_id, false, packet_, self_address_,
- peer_address_, false, {}, invalid_version_);
+ peer_address_, false, {}, "", invalid_version_);
if (i <= kDefaultMaxUndecryptablePackets) {
EXPECT_EQ(EnqueuePacketResult::SUCCESS, result);
} else {
@@ -161,7 +161,7 @@ TEST_F(QuicBufferedPacketStoreTest, ReachNonChloConnectionUpperLimit) {
QuicConnectionId connection_id = TestConnectionId(conn_id);
EnqueuePacketResult result =
store_.EnqueuePacket(connection_id, false, packet_, self_address_,
- peer_address_, false, {}, invalid_version_);
+ peer_address_, false, {}, "", invalid_version_);
if (conn_id <= kMaxConnectionsWithoutCHLO) {
EXPECT_EQ(EnqueuePacketResult::SUCCESS, result);
} else {
@@ -190,7 +190,7 @@ TEST_F(QuicBufferedPacketStoreTest,
for (uint64_t conn_id = 1; conn_id <= num_chlos; ++conn_id) {
EXPECT_EQ(EnqueuePacketResult::SUCCESS,
store_.EnqueuePacket(TestConnectionId(conn_id), false, packet_,
- self_address_, peer_address_, true, {},
+ self_address_, peer_address_, true, {}, "",
valid_version_));
}
@@ -201,7 +201,7 @@ TEST_F(QuicBufferedPacketStoreTest,
QuicConnectionId connection_id = TestConnectionId(conn_id);
EnqueuePacketResult result =
store_.EnqueuePacket(connection_id, false, packet_, self_address_,
- peer_address_, true, {}, valid_version_);
+ peer_address_, true, {}, "", valid_version_);
if (conn_id <= kDefaultMaxConnectionsInStore) {
EXPECT_EQ(EnqueuePacketResult::SUCCESS, result);
} else {
@@ -214,9 +214,10 @@ TEST_F(QuicBufferedPacketStoreTest, EnqueueChloOnTooManyDifferentConnections) {
// Buffer data packets on different connections upto limit.
for (uint64_t conn_id = 1; conn_id <= kMaxConnectionsWithoutCHLO; ++conn_id) {
QuicConnectionId connection_id = TestConnectionId(conn_id);
- EXPECT_EQ(EnqueuePacketResult::SUCCESS,
- store_.EnqueuePacket(connection_id, false, packet_, self_address_,
- peer_address_, false, {}, invalid_version_));
+ EXPECT_EQ(
+ EnqueuePacketResult::SUCCESS,
+ store_.EnqueuePacket(connection_id, false, packet_, self_address_,
+ peer_address_, false, {}, "", invalid_version_));
}
// Buffer CHLOs on other connections till store is full.
@@ -225,7 +226,7 @@ TEST_F(QuicBufferedPacketStoreTest, EnqueueChloOnTooManyDifferentConnections) {
QuicConnectionId connection_id = TestConnectionId(i);
EnqueuePacketResult rs =
store_.EnqueuePacket(connection_id, false, packet_, self_address_,
- peer_address_, true, {}, valid_version_);
+ peer_address_, true, {}, "", valid_version_);
if (i <= kDefaultMaxConnectionsInStore) {
EXPECT_EQ(EnqueuePacketResult::SUCCESS, rs);
EXPECT_TRUE(store_.HasChloForConnection(connection_id));
@@ -242,7 +243,7 @@ TEST_F(QuicBufferedPacketStoreTest, EnqueueChloOnTooManyDifferentConnections) {
EXPECT_EQ(EnqueuePacketResult::SUCCESS,
store_.EnqueuePacket(
/*connection_id=*/TestConnectionId(1), false, packet_,
- self_address_, peer_address_, true, {}, valid_version_));
+ self_address_, peer_address_, true, {}, "", valid_version_));
EXPECT_TRUE(store_.HasChloForConnection(
/*connection_id=*/TestConnectionId(1)));
@@ -270,14 +271,15 @@ TEST_F(QuicBufferedPacketStoreTest, EnqueueChloOnTooManyDifferentConnections) {
TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery) {
QuicConnectionId connection_id = TestConnectionId(1);
store_.EnqueuePacket(connection_id, false, packet_, self_address_,
- peer_address_, false, {}, invalid_version_);
+ peer_address_, false, {}, "", invalid_version_);
EXPECT_EQ(EnqueuePacketResult::SUCCESS,
store_.EnqueuePacket(connection_id, false, packet_, self_address_,
- peer_address_, true, {}, valid_version_));
+ peer_address_, true, {}, "", valid_version_));
QuicConnectionId connection_id2 = TestConnectionId(2);
- EXPECT_EQ(EnqueuePacketResult::SUCCESS,
- store_.EnqueuePacket(connection_id2, false, packet_, self_address_,
- peer_address_, false, {}, invalid_version_));
+ EXPECT_EQ(
+ EnqueuePacketResult::SUCCESS,
+ store_.EnqueuePacket(connection_id2, false, packet_, self_address_,
+ peer_address_, false, {}, "", invalid_version_));
// CHLO on connection 3 arrives 1ms later.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
@@ -286,7 +288,7 @@ TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery) {
// connections.
QuicSocketAddress another_client_address(QuicIpAddress::Any4(), 255);
store_.EnqueuePacket(connection_id3, false, packet_, self_address_,
- another_client_address, true, {}, valid_version_);
+ another_client_address, true, {}, "", valid_version_);
// Advance clock to the time when connection 1 and 2 expires.
clock_.AdvanceTime(
@@ -318,9 +320,9 @@ TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery) {
// for them to expire.
QuicConnectionId connection_id4 = TestConnectionId(4);
store_.EnqueuePacket(connection_id4, false, packet_, self_address_,
- peer_address_, false, {}, invalid_version_);
+ peer_address_, false, {}, "", invalid_version_);
store_.EnqueuePacket(connection_id4, false, packet_, self_address_,
- peer_address_, false, {}, invalid_version_);
+ peer_address_, false, {}, "", invalid_version_);
clock_.AdvanceTime(
QuicBufferedPacketStorePeer::expiration_alarm(&store_)->deadline() -
clock_.ApproximateNow());
@@ -335,9 +337,9 @@ TEST_F(QuicBufferedPacketStoreTest, SimpleDiscardPackets) {
// Enqueue some packets
store_.EnqueuePacket(connection_id, false, packet_, self_address_,
- peer_address_, false, {}, invalid_version_);
+ peer_address_, false, {}, "", invalid_version_);
store_.EnqueuePacket(connection_id, false, packet_, self_address_,
- peer_address_, false, {}, invalid_version_);
+ peer_address_, false, {}, "", invalid_version_);
EXPECT_TRUE(store_.HasBufferedPackets(connection_id));
EXPECT_FALSE(store_.HasChlosBuffered());
@@ -361,11 +363,11 @@ TEST_F(QuicBufferedPacketStoreTest, DiscardWithCHLOs) {
// Enqueue some packets, which include a CHLO
store_.EnqueuePacket(connection_id, false, packet_, self_address_,
- peer_address_, false, {}, invalid_version_);
+ peer_address_, false, {}, "", invalid_version_);
store_.EnqueuePacket(connection_id, false, packet_, self_address_,
- peer_address_, true, {}, valid_version_);
+ peer_address_, true, {}, "", valid_version_);
store_.EnqueuePacket(connection_id, false, packet_, self_address_,
- peer_address_, false, {}, invalid_version_);
+ peer_address_, false, {}, "", invalid_version_);
EXPECT_TRUE(store_.HasBufferedPackets(connection_id));
EXPECT_TRUE(store_.HasChlosBuffered());
@@ -390,11 +392,12 @@ TEST_F(QuicBufferedPacketStoreTest, MultipleDiscardPackets) {
// Enqueue some packets for two connection IDs
store_.EnqueuePacket(connection_id_1, false, packet_, self_address_,
- peer_address_, false, {}, invalid_version_);
+ peer_address_, false, {}, "", invalid_version_);
store_.EnqueuePacket(connection_id_1, false, packet_, self_address_,
- peer_address_, false, {}, invalid_version_);
+ peer_address_, false, {}, "", invalid_version_);
store_.EnqueuePacket(connection_id_2, false, packet_, self_address_,
- peer_address_, true, {"h3"}, valid_version_);
+ peer_address_, true, {"h3"}, TestHostname(),
+ valid_version_);
EXPECT_TRUE(store_.HasBufferedPackets(connection_id_1));
EXPECT_TRUE(store_.HasBufferedPackets(connection_id_2));
EXPECT_TRUE(store_.HasChlosBuffered());
@@ -413,6 +416,7 @@ TEST_F(QuicBufferedPacketStoreTest, MultipleDiscardPackets) {
EXPECT_EQ(1u, packets.buffered_packets.size());
ASSERT_EQ(1u, packets.alpns.size());
EXPECT_EQ("h3", packets.alpns[0]);
+ EXPECT_EQ(TestHostname(), packets.sni);
// Since connection_id_2's chlo arrives, verify version is set.
EXPECT_EQ(valid_version_, packets.version);
EXPECT_TRUE(store_.HasChlosBuffered());
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.cc b/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.cc
index 2ae9b41aeff..52673b61d5e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.cc
@@ -4,9 +4,9 @@
#include "quic/core/quic_coalesced_packet.h"
+#include "absl/memory/memory.h"
#include "absl/strings/str_cat.h"
#include "quic/platform/api/quic_bug_tracker.h"
-#include "quic/platform/api/quic_ptr_util.h"
namespace quic {
@@ -24,7 +24,7 @@ bool QuicCoalescedPacket::MaybeCoalescePacket(
QuicBufferAllocator* allocator,
QuicPacketLength current_max_packet_length) {
if (packet.encrypted_length == 0) {
- QUIC_BUG << "Trying to coalesce an empty packet";
+ QUIC_BUG(quic_bug_10611_1) << "Trying to coalesce an empty packet";
return true;
}
if (length_ == 0) {
@@ -47,7 +47,8 @@ bool QuicCoalescedPacket::MaybeCoalescePacket(
return false;
}
if (max_packet_length_ != current_max_packet_length) {
- QUIC_BUG << "Max packet length changes in the middle of the write path";
+ QUIC_BUG(quic_bug_10611_2)
+ << "Max packet length changes in the middle of the write path";
return false;
}
if (ContainsPacketOfEncryptionLevel(packet.encryption_level)) {
@@ -73,7 +74,7 @@ bool QuicCoalescedPacket::MaybeCoalescePacket(
if (packet.encryption_level == ENCRYPTION_INITIAL) {
// Save a copy of ENCRYPTION_INITIAL packet (excluding encrypted buffer, as
// the packet will be re-serialized later).
- initial_packet_ = QuicWrapUnique<SerializedPacket>(
+ initial_packet_ = absl::WrapUnique<SerializedPacket>(
CopySerializedPacket(packet, allocator, /*copy_buffer=*/false));
return true;
}
@@ -102,9 +103,9 @@ void QuicCoalescedPacket::NeuterInitialPacket() {
return;
}
if (length_ < initial_packet_->encrypted_length) {
- QUIC_BUG << "length_: " << length_
- << ", is less than initial packet length: "
- << initial_packet_->encrypted_length;
+ QUIC_BUG(quic_bug_10611_3)
+ << "length_: " << length_ << ", is less than initial packet length: "
+ << initial_packet_->encrypted_length;
Clear();
return;
}
@@ -145,13 +146,24 @@ bool QuicCoalescedPacket::ContainsPacketOfEncryptionLevel(
TransmissionType QuicCoalescedPacket::TransmissionTypeOfPacket(
EncryptionLevel level) const {
if (!ContainsPacketOfEncryptionLevel(level)) {
- QUIC_BUG << "Coalesced packet does not contain packet of encryption level: "
- << EncryptionLevelToString(level);
+ QUIC_BUG(quic_bug_10611_4)
+ << "Coalesced packet does not contain packet of encryption level: "
+ << EncryptionLevelToString(level);
return NOT_RETRANSMISSION;
}
return transmission_types_[level];
}
+size_t QuicCoalescedPacket::NumberOfPackets() const {
+ size_t num_of_packets = 0;
+ for (int8_t i = ENCRYPTION_INITIAL; i < NUM_ENCRYPTION_LEVELS; ++i) {
+ if (ContainsPacketOfEncryptionLevel(static_cast<EncryptionLevel>(i))) {
+ ++num_of_packets;
+ }
+ }
+ return num_of_packets;
+}
+
std::string QuicCoalescedPacket::ToString(size_t serialized_length) const {
// Total length and padding size.
std::string info = absl::StrCat(
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.h b/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.h
index e3f674e239f..e8bc2c3eb0b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.h
@@ -46,6 +46,9 @@ class QUIC_EXPORT_PRIVATE QuicCoalescedPacket {
// when this coalesced packet contains packet of |level|.
TransmissionType TransmissionTypeOfPacket(EncryptionLevel level) const;
+ // Returns number of packets contained in this coalesced packet.
+ size_t NumberOfPackets() const;
+
const SerializedPacket* initial_packet() const {
return initial_packet_.get();
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet_test.cc
index 1d629ae135a..34f6da30890 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet_test.cc
@@ -19,6 +19,7 @@ TEST(QuicCoalescedPacketTest, MaybeCoalescePacket) {
coalesced.ToString(0));
SimpleBufferAllocator allocator;
EXPECT_EQ(0u, coalesced.length());
+ EXPECT_EQ(0u, coalesced.NumberOfPackets());
char buffer[1000];
QuicSocketAddress self_address(QuicIpAddress::Loopback4(), 1);
QuicSocketAddress peer_address(QuicIpAddress::Loopback4(), 2);
@@ -35,6 +36,7 @@ TEST(QuicCoalescedPacketTest, MaybeCoalescePacket) {
coalesced.TransmissionTypeOfPacket(ENCRYPTION_INITIAL));
EXPECT_EQ(1500u, coalesced.max_packet_length());
EXPECT_EQ(500u, coalesced.length());
+ EXPECT_EQ(1u, coalesced.NumberOfPackets());
EXPECT_EQ(
"total_length: 1500 padding_size: 1000 packets: {ENCRYPTION_INITIAL}",
coalesced.ToString(1500));
@@ -54,6 +56,7 @@ TEST(QuicCoalescedPacketTest, MaybeCoalescePacket) {
&allocator, 1500));
EXPECT_EQ(1500u, coalesced.max_packet_length());
EXPECT_EQ(1000u, coalesced.length());
+ EXPECT_EQ(2u, coalesced.NumberOfPackets());
EXPECT_EQ(LOSS_RETRANSMISSION,
coalesced.TransmissionTypeOfPacket(ENCRYPTION_ZERO_RTT));
EXPECT_EQ(
@@ -77,6 +80,7 @@ TEST(QuicCoalescedPacketTest, MaybeCoalescePacket) {
peer_address, &allocator, 1500));
EXPECT_EQ(1500u, coalesced.max_packet_length());
EXPECT_EQ(1000u, coalesced.length());
+ EXPECT_EQ(2u, coalesced.NumberOfPackets());
// Max packet number length changed.
SerializedPacket packet6(QuicPacketNumber(6), PACKET_4BYTE_PACKET_NUMBER,
@@ -87,6 +91,7 @@ TEST(QuicCoalescedPacketTest, MaybeCoalescePacket) {
"Max packet length changes in the middle of the write path");
EXPECT_EQ(1500u, coalesced.max_packet_length());
EXPECT_EQ(1000u, coalesced.length());
+ EXPECT_EQ(2u, coalesced.NumberOfPackets());
}
TEST(QuicCoalescedPacketTest, CopyEncryptedBuffers) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_config.cc b/chromium/net/third_party/quiche/src/quic/core/quic_config.cc
index 893d82233f1..796c641051b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_config.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_config.cc
@@ -24,7 +24,6 @@
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_socket_address.h"
-#include "quic/platform/api/quic_uint128.h"
namespace quic {
@@ -72,7 +71,7 @@ bool QuicFixedUint32::HasSendValue() const {
}
uint32_t QuicFixedUint32::GetSendValue() const {
- QUIC_BUG_IF(!has_send_value_)
+ QUIC_BUG_IF(quic_bug_12743_1, !has_send_value_)
<< "No send value to get for tag:" << QuicTagToString(tag_);
return send_value_;
}
@@ -87,7 +86,7 @@ bool QuicFixedUint32::HasReceivedValue() const {
}
uint32_t QuicFixedUint32::GetReceivedValue() const {
- QUIC_BUG_IF(!has_receive_value_)
+ QUIC_BUG_IF(quic_bug_12743_2, !has_receive_value_)
<< "No receive value to get for tag:" << QuicTagToString(tag_);
return receive_value_;
}
@@ -99,7 +98,7 @@ void QuicFixedUint32::SetReceivedValue(uint32_t value) {
void QuicFixedUint32::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
if (tag_ == 0) {
- QUIC_BUG
+ QUIC_BUG(quic_bug_12743_3)
<< "This parameter does not support writing to CryptoHandshakeMessage";
return;
}
@@ -116,7 +115,7 @@ QuicErrorCode QuicFixedUint32::ProcessPeerHello(
if (tag_ == 0) {
*error_details =
"This parameter does not support reading from CryptoHandshakeMessage";
- QUIC_BUG << *error_details;
+ QUIC_BUG(quic_bug_10575_1) << *error_details;
return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
}
QuicErrorCode error = peer_hello.GetUint32(tag_, &receive_value_);
@@ -150,7 +149,8 @@ bool QuicFixedUint62::HasSendValue() const {
uint64_t QuicFixedUint62::GetSendValue() const {
if (!has_send_value_) {
- QUIC_BUG << "No send value to get for tag:" << QuicTagToString(tag_);
+ QUIC_BUG(quic_bug_10575_2)
+ << "No send value to get for tag:" << QuicTagToString(tag_);
return 0;
}
return send_value_;
@@ -158,7 +158,7 @@ uint64_t QuicFixedUint62::GetSendValue() const {
void QuicFixedUint62::SetSendValue(uint64_t value) {
if (value > kVarInt62MaxValue) {
- QUIC_BUG << "QuicFixedUint62 invalid value " << value;
+ QUIC_BUG(quic_bug_10575_3) << "QuicFixedUint62 invalid value " << value;
value = kVarInt62MaxValue;
}
has_send_value_ = true;
@@ -171,7 +171,8 @@ bool QuicFixedUint62::HasReceivedValue() const {
uint64_t QuicFixedUint62::GetReceivedValue() const {
if (!has_receive_value_) {
- QUIC_BUG << "No receive value to get for tag:" << QuicTagToString(tag_);
+ QUIC_BUG(quic_bug_10575_4)
+ << "No receive value to get for tag:" << QuicTagToString(tag_);
return 0;
}
return receive_value_;
@@ -188,8 +189,8 @@ void QuicFixedUint62::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
}
uint32_t send_value32;
if (send_value_ > std::numeric_limits<uint32_t>::max()) {
- QUIC_BUG << "Attempting to send " << send_value_
- << " for tag:" << QuicTagToString(tag_);
+ QUIC_BUG(quic_bug_10575_5) << "Attempting to send " << send_value_
+ << " for tag:" << QuicTagToString(tag_);
send_value32 = std::numeric_limits<uint32_t>::max();
} else {
send_value32 = static_cast<uint32_t>(send_value_);
@@ -223,54 +224,61 @@ QuicErrorCode QuicFixedUint62::ProcessPeerHello(
return error;
}
-QuicFixedUint128::QuicFixedUint128(QuicTag tag, QuicConfigPresence presence)
+QuicFixedStatelessResetToken::QuicFixedStatelessResetToken(
+ QuicTag tag,
+ QuicConfigPresence presence)
: QuicConfigValue(tag, presence),
has_send_value_(false),
has_receive_value_(false) {}
-QuicFixedUint128::~QuicFixedUint128() {}
+QuicFixedStatelessResetToken::~QuicFixedStatelessResetToken() {}
-bool QuicFixedUint128::HasSendValue() const {
+bool QuicFixedStatelessResetToken::HasSendValue() const {
return has_send_value_;
}
-QuicUint128 QuicFixedUint128::GetSendValue() const {
- QUIC_BUG_IF(!has_send_value_)
+const StatelessResetToken& QuicFixedStatelessResetToken::GetSendValue() const {
+ QUIC_BUG_IF(quic_bug_12743_4, !has_send_value_)
<< "No send value to get for tag:" << QuicTagToString(tag_);
return send_value_;
}
-void QuicFixedUint128::SetSendValue(QuicUint128 value) {
+void QuicFixedStatelessResetToken::SetSendValue(
+ const StatelessResetToken& value) {
has_send_value_ = true;
send_value_ = value;
}
-bool QuicFixedUint128::HasReceivedValue() const {
+bool QuicFixedStatelessResetToken::HasReceivedValue() const {
return has_receive_value_;
}
-QuicUint128 QuicFixedUint128::GetReceivedValue() const {
- QUIC_BUG_IF(!has_receive_value_)
+const StatelessResetToken& QuicFixedStatelessResetToken::GetReceivedValue()
+ const {
+ QUIC_BUG_IF(quic_bug_12743_5, !has_receive_value_)
<< "No receive value to get for tag:" << QuicTagToString(tag_);
return receive_value_;
}
-void QuicFixedUint128::SetReceivedValue(QuicUint128 value) {
+void QuicFixedStatelessResetToken::SetReceivedValue(
+ const StatelessResetToken& value) {
has_receive_value_ = true;
receive_value_ = value;
}
-void QuicFixedUint128::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
+void QuicFixedStatelessResetToken::ToHandshakeMessage(
+ CryptoHandshakeMessage* out) const {
if (has_send_value_) {
out->SetValue(tag_, send_value_);
}
}
-QuicErrorCode QuicFixedUint128::ProcessPeerHello(
+QuicErrorCode QuicFixedStatelessResetToken::ProcessPeerHello(
const CryptoHandshakeMessage& peer_hello,
HelloType /*hello_type*/,
std::string* error_details) {
QUICHE_DCHECK(error_details != nullptr);
- QuicErrorCode error = peer_hello.GetUint128(tag_, &receive_value_);
+ QuicErrorCode error =
+ peer_hello.GetStatelessResetToken(tag_, &receive_value_);
switch (error) {
case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
if (presence_ == PRESENCE_OPTIONAL) {
@@ -304,7 +312,7 @@ bool QuicFixedTagVector::HasSendValues() const {
}
const QuicTagVector& QuicFixedTagVector::GetSendValues() const {
- QUIC_BUG_IF(!has_send_values_)
+ QUIC_BUG_IF(quic_bug_12743_6, !has_send_values_)
<< "No send values to get for tag:" << QuicTagToString(tag_);
return send_values_;
}
@@ -319,7 +327,7 @@ bool QuicFixedTagVector::HasReceivedValues() const {
}
const QuicTagVector& QuicFixedTagVector::GetReceivedValues() const {
- QUIC_BUG_IF(!has_receive_values_)
+ QUIC_BUG_IF(quic_bug_12743_7, !has_receive_values_)
<< "No receive value to get for tag:" << QuicTagToString(tag_);
return receive_values_;
}
@@ -375,7 +383,7 @@ bool QuicFixedSocketAddress::HasSendValue() const {
}
const QuicSocketAddress& QuicFixedSocketAddress::GetSendValue() const {
- QUIC_BUG_IF(!has_send_value_)
+ QUIC_BUG_IF(quic_bug_12743_8, !has_send_value_)
<< "No send value to get for tag:" << QuicTagToString(tag_);
return send_value_;
}
@@ -390,7 +398,7 @@ bool QuicFixedSocketAddress::HasReceivedValue() const {
}
const QuicSocketAddress& QuicFixedSocketAddress::GetReceivedValue() const {
- QUIC_BUG_IF(!has_receive_value_)
+ QUIC_BUG_IF(quic_bug_12743_9, !has_receive_value_)
<< "No receive value to get for tag:" << QuicTagToString(tag_);
return receive_value_;
}
@@ -544,7 +552,8 @@ const QuicTagVector& QuicConfig::ClientRequestedIndependentOptions(
void QuicConfig::SetIdleNetworkTimeout(QuicTime::Delta idle_network_timeout) {
if (idle_network_timeout.ToMicroseconds() <= 0) {
- QUIC_BUG << "Invalid idle network timeout " << idle_network_timeout;
+ QUIC_BUG(quic_bug_10575_6)
+ << "Invalid idle network timeout " << idle_network_timeout;
return;
}
max_idle_timeout_to_send_ = idle_network_timeout;
@@ -729,9 +738,10 @@ uint64_t QuicConfig::GetInitialRoundTripTimeUsToSend() const {
void QuicConfig::SetInitialStreamFlowControlWindowToSend(
uint64_t window_bytes) {
if (window_bytes < kMinimumFlowControlSendWindow) {
- QUIC_BUG << "Initial stream flow control receive window (" << window_bytes
- << ") cannot be set lower than minimum ("
- << kMinimumFlowControlSendWindow << ").";
+ QUIC_BUG(quic_bug_10575_7)
+ << "Initial stream flow control receive window (" << window_bytes
+ << ") cannot be set lower than minimum ("
+ << kMinimumFlowControlSendWindow << ").";
window_bytes = kMinimumFlowControlSendWindow;
}
initial_stream_flow_control_window_bytes_.SetSendValue(window_bytes);
@@ -824,9 +834,10 @@ uint64_t QuicConfig::ReceivedInitialMaxStreamDataBytesUnidirectional() const {
void QuicConfig::SetInitialSessionFlowControlWindowToSend(
uint64_t window_bytes) {
if (window_bytes < kMinimumFlowControlSendWindow) {
- QUIC_BUG << "Initial session flow control receive window (" << window_bytes
- << ") cannot be set lower than default ("
- << kMinimumFlowControlSendWindow << ").";
+ QUIC_BUG(quic_bug_10575_8)
+ << "Initial session flow control receive window (" << window_bytes
+ << ") cannot be set lower than default ("
+ << kMinimumFlowControlSendWindow << ").";
window_bytes = kMinimumFlowControlSendWindow;
}
initial_session_flow_control_window_bytes_.SetSendValue(window_bytes);
@@ -871,8 +882,9 @@ bool QuicConfig::KeyUpdateSupportedRemotely() const {
void QuicConfig::SetIPv6AlternateServerAddressToSend(
const QuicSocketAddress& alternate_server_address_ipv6) {
if (!alternate_server_address_ipv6.host().IsIPv6()) {
- QUIC_BUG << "Cannot use SetIPv6AlternateServerAddressToSend with "
- << alternate_server_address_ipv6;
+ QUIC_BUG(quic_bug_10575_9)
+ << "Cannot use SetIPv6AlternateServerAddressToSend with "
+ << alternate_server_address_ipv6;
return;
}
alternate_server_address_ipv6_.SetSendValue(alternate_server_address_ipv6);
@@ -881,10 +893,11 @@ void QuicConfig::SetIPv6AlternateServerAddressToSend(
void QuicConfig::SetIPv6AlternateServerAddressToSend(
const QuicSocketAddress& alternate_server_address_ipv6,
const QuicConnectionId& connection_id,
- QuicUint128 stateless_reset_token) {
+ const StatelessResetToken& stateless_reset_token) {
if (!alternate_server_address_ipv6.host().IsIPv6()) {
- QUIC_BUG << "Cannot use SetIPv6AlternateServerAddressToSend with "
- << alternate_server_address_ipv6;
+ QUIC_BUG(quic_bug_10575_10)
+ << "Cannot use SetIPv6AlternateServerAddressToSend with "
+ << alternate_server_address_ipv6;
return;
}
alternate_server_address_ipv6_.SetSendValue(alternate_server_address_ipv6);
@@ -904,8 +917,9 @@ const QuicSocketAddress& QuicConfig::ReceivedIPv6AlternateServerAddress()
void QuicConfig::SetIPv4AlternateServerAddressToSend(
const QuicSocketAddress& alternate_server_address_ipv4) {
if (!alternate_server_address_ipv4.host().IsIPv4()) {
- QUIC_BUG << "Cannot use SetIPv4AlternateServerAddressToSend with "
- << alternate_server_address_ipv4;
+ QUIC_BUG(quic_bug_10575_11)
+ << "Cannot use SetIPv4AlternateServerAddressToSend with "
+ << alternate_server_address_ipv4;
return;
}
alternate_server_address_ipv4_.SetSendValue(alternate_server_address_ipv4);
@@ -914,10 +928,11 @@ void QuicConfig::SetIPv4AlternateServerAddressToSend(
void QuicConfig::SetIPv4AlternateServerAddressToSend(
const QuicSocketAddress& alternate_server_address_ipv4,
const QuicConnectionId& connection_id,
- QuicUint128 stateless_reset_token) {
+ const StatelessResetToken& stateless_reset_token) {
if (!alternate_server_address_ipv4.host().IsIPv4()) {
- QUIC_BUG << "Cannot use SetIPv4AlternateServerAddressToSend with "
- << alternate_server_address_ipv4;
+ QUIC_BUG(quic_bug_10575_12)
+ << "Cannot use SetIPv4AlternateServerAddressToSend with "
+ << alternate_server_address_ipv4;
return;
}
alternate_server_address_ipv4_.SetSendValue(alternate_server_address_ipv4);
@@ -940,7 +955,7 @@ bool QuicConfig::HasReceivedPreferredAddressConnectionIdAndToken() const {
preferred_address_connection_id_and_token_.has_value();
}
-const std::pair<QuicConnectionId, QuicUint128>&
+const std::pair<QuicConnectionId, StatelessResetToken>&
QuicConfig::ReceivedPreferredAddressConnectionIdAndToken() const {
QUICHE_DCHECK(HasReceivedPreferredAddressConnectionIdAndToken());
return *preferred_address_connection_id_and_token_;
@@ -958,7 +973,7 @@ bool QuicConfig::HasReceivedOriginalConnectionId() const {
QuicConnectionId QuicConfig::ReceivedOriginalConnectionId() const {
if (!HasReceivedOriginalConnectionId()) {
- QUIC_BUG << "No received original connection ID";
+ QUIC_BUG(quic_bug_10575_13) << "No received original connection ID";
return EmptyQuicConnectionId();
}
return received_original_destination_connection_id_.value();
@@ -975,7 +990,7 @@ bool QuicConfig::HasReceivedInitialSourceConnectionId() const {
QuicConnectionId QuicConfig::ReceivedInitialSourceConnectionId() const {
if (!HasReceivedInitialSourceConnectionId()) {
- QUIC_BUG << "No received initial source connection ID";
+ QUIC_BUG(quic_bug_10575_14) << "No received initial source connection ID";
return EmptyQuicConnectionId();
}
return received_initial_source_connection_id_.value();
@@ -992,14 +1007,14 @@ bool QuicConfig::HasReceivedRetrySourceConnectionId() const {
QuicConnectionId QuicConfig::ReceivedRetrySourceConnectionId() const {
if (!HasReceivedRetrySourceConnectionId()) {
- QUIC_BUG << "No received retry source connection ID";
+ QUIC_BUG(quic_bug_10575_15) << "No received retry source connection ID";
return EmptyQuicConnectionId();
}
return received_retry_source_connection_id_.value();
}
void QuicConfig::SetStatelessResetTokenToSend(
- QuicUint128 stateless_reset_token) {
+ const StatelessResetToken& stateless_reset_token) {
stateless_reset_token_.SetSendValue(stateless_reset_token);
}
@@ -1007,7 +1022,7 @@ bool QuicConfig::HasReceivedStatelessResetToken() const {
return stateless_reset_token_.HasReceivedValue();
}
-QuicUint128 QuicConfig::ReceivedStatelessResetToken() const {
+const StatelessResetToken& QuicConfig::ReceivedStatelessResetToken() const {
return stateless_reset_token_.GetReceivedValue();
}
@@ -1195,7 +1210,8 @@ bool QuicConfig::FillTransportParameters(TransportParameters* params) const {
max_idle_timeout_to_send_.ToMilliseconds());
if (stateless_reset_token_.HasSendValue()) {
- QuicUint128 stateless_reset_token = stateless_reset_token_.GetSendValue();
+ StatelessResetToken stateless_reset_token =
+ stateless_reset_token_.GetSendValue();
params->stateless_reset_token.assign(
reinterpret_cast<const char*>(&stateless_reset_token),
reinterpret_cast<const char*>(&stateless_reset_token) +
@@ -1310,10 +1326,10 @@ QuicErrorCode QuicConfig::ProcessTransportParameters(
}
if (!is_resumption && !params.stateless_reset_token.empty()) {
- QuicUint128 stateless_reset_token;
+ StatelessResetToken stateless_reset_token;
if (params.stateless_reset_token.size() != sizeof(stateless_reset_token)) {
- QUIC_BUG << "Bad stateless reset token length "
- << params.stateless_reset_token.size();
+ QUIC_BUG(quic_bug_10575_16) << "Bad stateless reset token length "
+ << params.stateless_reset_token.size();
*error_details = "Bad stateless reset token length";
return QUIC_INTERNAL_ERROR;
}
@@ -1376,7 +1392,7 @@ QuicErrorCode QuicConfig::ProcessTransportParameters(
if (!params.preferred_address->connection_id.IsEmpty()) {
preferred_address_connection_id_and_token_ = std::make_pair(
params.preferred_address->connection_id,
- *reinterpret_cast<const QuicUint128*>(
+ *reinterpret_cast<const StatelessResetToken*>(
&params.preferred_address->stateless_reset_token.front()));
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_config.h b/chromium/net/third_party/quiche/src/quic/core/quic_config.h
index d0fa2c79200..d122be7ff29 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_config.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_config.h
@@ -14,8 +14,8 @@
#include "quic/core/quic_connection_id.h"
#include "quic/core/quic_packets.h"
#include "quic/core/quic_time.h"
+#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_export.h"
-#include "quic/platform/api/quic_uint128.h"
namespace quic {
@@ -134,23 +134,25 @@ class QUIC_EXPORT_PRIVATE QuicFixedUint62 : public QuicConfigValue {
uint64_t receive_value_;
};
-// Stores uint128 from CHLO or SHLO messages that are not negotiated.
-class QUIC_EXPORT_PRIVATE QuicFixedUint128 : public QuicConfigValue {
+// Stores StatelessResetToken from CHLO or SHLO messages that are not
+// negotiated.
+class QUIC_EXPORT_PRIVATE QuicFixedStatelessResetToken
+ : public QuicConfigValue {
public:
- QuicFixedUint128(QuicTag tag, QuicConfigPresence presence);
- ~QuicFixedUint128() override;
+ QuicFixedStatelessResetToken(QuicTag tag, QuicConfigPresence presence);
+ ~QuicFixedStatelessResetToken() override;
bool HasSendValue() const;
- QuicUint128 GetSendValue() const;
+ const StatelessResetToken& GetSendValue() const;
- void SetSendValue(QuicUint128 value);
+ void SetSendValue(const StatelessResetToken& value);
bool HasReceivedValue() const;
- QuicUint128 GetReceivedValue() const;
+ const StatelessResetToken& GetReceivedValue() const;
- void SetReceivedValue(QuicUint128 value);
+ void SetReceivedValue(const StatelessResetToken& value);
// If has_send_value is true, serialises |tag_| and |send_value_| to |out|.
void ToHandshakeMessage(CryptoHandshakeMessage* out) const override;
@@ -163,8 +165,8 @@ class QUIC_EXPORT_PRIVATE QuicFixedUint128 : public QuicConfigValue {
private:
bool has_send_value_;
bool has_receive_value_;
- QuicUint128 send_value_;
- QuicUint128 receive_value_;
+ StatelessResetToken send_value_;
+ StatelessResetToken receive_value_;
};
// Stores tag from CHLO or SHLO messages that are not negotiated.
@@ -394,7 +396,7 @@ class QUIC_EXPORT_PRIVATE QuicConfig {
void SetIPv6AlternateServerAddressToSend(
const QuicSocketAddress& alternate_server_address_ipv6,
const QuicConnectionId& connection_id,
- QuicUint128 stateless_reset_token);
+ const StatelessResetToken& stateless_reset_token);
bool HasReceivedIPv6AlternateServerAddress() const;
const QuicSocketAddress& ReceivedIPv6AlternateServerAddress() const;
@@ -404,13 +406,13 @@ class QUIC_EXPORT_PRIVATE QuicConfig {
void SetIPv4AlternateServerAddressToSend(
const QuicSocketAddress& alternate_server_address_ipv4,
const QuicConnectionId& connection_id,
- QuicUint128 stateless_reset_token);
+ const StatelessResetToken& stateless_reset_token);
bool HasReceivedIPv4AlternateServerAddress() const;
const QuicSocketAddress& ReceivedIPv4AlternateServerAddress() const;
// Preferred Address Connection ID and Token.
bool HasReceivedPreferredAddressConnectionIdAndToken() const;
- const std::pair<QuicConnectionId, QuicUint128>&
+ const std::pair<QuicConnectionId, StatelessResetToken>&
ReceivedPreferredAddressConnectionIdAndToken() const;
// Original destination connection ID.
@@ -420,9 +422,10 @@ class QUIC_EXPORT_PRIVATE QuicConfig {
QuicConnectionId ReceivedOriginalConnectionId() const;
// Stateless reset token.
- void SetStatelessResetTokenToSend(QuicUint128 stateless_reset_token);
+ void SetStatelessResetTokenToSend(
+ const StatelessResetToken& stateless_reset_token);
bool HasReceivedStatelessResetToken() const;
- QuicUint128 ReceivedStatelessResetToken() const;
+ const StatelessResetToken& ReceivedStatelessResetToken() const;
// Manage the IETF QUIC Max ACK Delay transport parameter.
// The sent value is the delay that this node uses
@@ -604,12 +607,12 @@ class QUIC_EXPORT_PRIVATE QuicConfig {
QuicFixedSocketAddress alternate_server_address_ipv4_;
// Connection Id data to send from the server or receive at the client as part
// of the preferred address transport parameter.
- absl::optional<std::pair<QuicConnectionId, QuicUint128>>
+ absl::optional<std::pair<QuicConnectionId, StatelessResetToken>>
preferred_address_connection_id_and_token_;
// Stateless reset token used in IETF public reset packet.
// Uses the stateless_reset_token transport parameter in IETF QUIC.
- QuicFixedUint128 stateless_reset_token_;
+ QuicFixedStatelessResetToken stateless_reset_token_;
// List of QuicTags whose presence immediately causes the session to
// be created. This allows for CHLOs that are larger than a single
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_config_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_config_test.cc
index 2f3783510fd..5124a975bf8 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_config_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_config_test.cc
@@ -17,7 +17,6 @@
#include "quic/platform/api/quic_expect_bug.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_test.h"
-#include "quic/platform/api/quic_uint128.h"
#include "quic/test_tools/quic_config_peer.h"
#include "quic/test_tools/quic_test_utils.h"
@@ -188,7 +187,9 @@ TEST_P(QuicConfigTest, ProcessServerHello) {
QuicIpAddress host;
host.FromString("127.0.3.1");
const QuicSocketAddress kTestServerAddress = QuicSocketAddress(host, 1234);
- const QuicUint128 kTestResetToken = MakeQuicUint128(0, 10111100001);
+ const StatelessResetToken kTestStatelessResetToken{
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f};
const uint32_t kTestMaxAckDelayMs =
static_cast<uint32_t>(kDefaultDelayedAckTimeMs + 1);
QuicConfig server_config;
@@ -202,7 +203,7 @@ TEST_P(QuicConfigTest, ProcessServerHello) {
server_config.SetInitialSessionFlowControlWindowToSend(
2 * kInitialSessionFlowControlWindowForTest);
server_config.SetIPv4AlternateServerAddressToSend(kTestServerAddress);
- server_config.SetStatelessResetTokenToSend(kTestResetToken);
+ server_config.SetStatelessResetTokenToSend(kTestStatelessResetToken);
server_config.SetMaxAckDelayToSendMs(kTestMaxAckDelayMs);
CryptoHandshakeMessage msg;
server_config.ToHandshakeMessage(&msg, version_.transport_version);
@@ -222,7 +223,7 @@ TEST_P(QuicConfigTest, ProcessServerHello) {
EXPECT_EQ(kTestServerAddress, config_.ReceivedIPv4AlternateServerAddress());
EXPECT_FALSE(config_.HasReceivedIPv6AlternateServerAddress());
EXPECT_TRUE(config_.HasReceivedStatelessResetToken());
- EXPECT_EQ(kTestResetToken, config_.ReceivedStatelessResetToken());
+ EXPECT_EQ(kTestStatelessResetToken, config_.ReceivedStatelessResetToken());
EXPECT_TRUE(config_.HasReceivedMaxAckDelayMs());
EXPECT_EQ(kTestMaxAckDelayMs, config_.ReceivedMaxAckDelayMs());
@@ -481,7 +482,7 @@ TEST_P(QuicConfigTest, FillTransportParams) {
host.FromString("127.0.3.1");
QuicSocketAddress kTestServerAddress = QuicSocketAddress(host, 1234);
QuicConnectionId new_connection_id = TestConnectionId(5);
- QuicUint128 new_stateless_reset_token =
+ StatelessResetToken new_stateless_reset_token =
QuicUtils::GenerateStatelessResetToken(new_connection_id);
config_.SetIPv4AlternateServerAddressToSend(
kTestServerAddress, new_connection_id, new_stateless_reset_token);
@@ -521,8 +522,7 @@ TEST_P(QuicConfigTest, FillTransportParams) {
EXPECT_TRUE(params.key_update_not_yet_supported);
EXPECT_EQ(params.preferred_address->ipv4_socket_address, kTestServerAddress);
- EXPECT_EQ(params.preferred_address->connection_id, new_connection_id);
- EXPECT_EQ(*reinterpret_cast<QuicUint128*>(
+ EXPECT_EQ(*reinterpret_cast<StatelessResetToken*>(
&params.preferred_address->stateless_reset_token.front()),
new_stateless_reset_token);
}
@@ -775,7 +775,7 @@ TEST_P(QuicConfigTest, SendPreferredIPv4Address) {
host.FromString("::ffff:192.0.2.128");
QuicSocketAddress kTestServerAddress = QuicSocketAddress(host, 1234);
QuicConnectionId new_connection_id = TestConnectionId(5);
- QuicUint128 new_stateless_reset_token =
+ StatelessResetToken new_stateless_reset_token =
QuicUtils::GenerateStatelessResetToken(new_connection_id);
auto preferred_address =
std::make_unique<TransportParameters::PreferredAddress>();
@@ -795,7 +795,7 @@ TEST_P(QuicConfigTest, SendPreferredIPv4Address) {
EXPECT_TRUE(config_.HasReceivedIPv6AlternateServerAddress());
EXPECT_EQ(config_.ReceivedIPv6AlternateServerAddress(), kTestServerAddress);
EXPECT_TRUE(config_.HasReceivedPreferredAddressConnectionIdAndToken());
- const std::pair<QuicConnectionId, QuicUint128>&
+ const std::pair<QuicConnectionId, StatelessResetToken>&
preferred_address_connection_id_and_token =
config_.ReceivedPreferredAddressConnectionIdAndToken();
EXPECT_EQ(preferred_address_connection_id_and_token.first, new_connection_id);
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 471331b3f6d..9bd21403263 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
@@ -117,7 +117,7 @@ class SendAlarmDelegate : public QuicAlarm::Delegate {
void OnAlarm() override {
QUICHE_DCHECK(connection_->connected());
- connection_->WriteAndBundleAcksIfNotBlocked();
+ connection_->WriteIfNotBlocked();
}
private:
@@ -353,7 +353,7 @@ QuicConnection::QuicConnection(
fill_up_link_during_probing_(false),
probing_retransmission_pending_(false),
stateless_reset_token_received_(false),
- received_stateless_reset_token_(0),
+ received_stateless_reset_token_({}),
last_control_frame_id_(kInvalidControlFrameId),
is_path_degrading_(false),
processing_ack_frame_(false),
@@ -371,13 +371,9 @@ QuicConnection::QuicConnection(
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),
- validate_client_addresses_(
- framer_.version().HasIetfQuicFrames() && use_path_validator_ &&
- count_bytes_on_alternative_path_separately_ &&
- update_packet_content_returns_connected_ &&
- GetQuicReloadableFlag(quic_server_reverse_validate_new_path)) {
- QUIC_BUG_IF(!start_peer_migration_earlier_ && send_path_response_);
+ 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());
@@ -385,12 +381,22 @@ QuicConnection::QuicConnection(
if (use_encryption_level_context_) {
QUIC_RELOADABLE_FLAG_COUNT(quic_use_encryption_level_context);
}
+
+ 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);
+
QUIC_DLOG(INFO) << ENDPOINT << "Created connection with server connection ID "
<< server_connection_id
<< " and version: " << ParsedQuicVersionToString(version());
- QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(server_connection_id,
- transport_version()))
+ QUIC_BUG_IF(quic_bug_12714_2, !QuicUtils::IsConnectionIdValidForVersion(
+ server_connection_id, transport_version()))
<< "QuicConnection: attempted to use server connection ID "
<< server_connection_id << " which is invalid with version " << version();
framer_.set_visitor(this);
@@ -581,6 +587,16 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
config.max_idle_time_before_crypto_handshake());
}
+ if (support_multiple_connection_ids_ &&
+ config.HasReceivedPreferredAddressConnectionIdAndToken()) {
+ QuicNewConnectionIdFrame frame;
+ std::tie(frame.connection_id, frame.stateless_reset_token) =
+ config.ReceivedPreferredAddressConnectionIdAndToken();
+ frame.sequence_number = 1u;
+ frame.retire_prior_to = 0u;
+ OnNewConnectionIdFrameInner(frame);
+ }
+
sent_packet_manager_.SetFromConfig(config);
if (perspective_ == Perspective::IS_SERVER &&
config.HasClientSentConnectionOption(kAFF2, perspective_)) {
@@ -678,11 +694,16 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
if (config.HasClientSentConnectionOption(kEACK, perspective_)) {
bundle_retransmittable_with_pto_ack_ = true;
}
- if (GetQuicReloadableFlag(quic_dont_defer_sending) &&
- config.HasClientSentConnectionOption(kDFER, perspective_)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_dont_defer_sending);
+ if (config.HasClientSentConnectionOption(kDFER, perspective_)) {
defer_send_in_response_to_packets_ = false;
}
+ if (framer_.version().HasIetfQuicFrames() && use_path_validator_ &&
+ count_bytes_on_alternative_path_separately_ &&
+ GetQuicReloadableFlag(quic_server_reverse_validate_new_path3) &&
+ config.HasClientSentConnectionOption(kRVCM, perspective_)) {
+ QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 6, 6);
+ validate_client_addresses_ = true;
+ }
if (config.HasReceivedMaxPacketSize()) {
peer_max_packet_size_ = config.ReceivedMaxPacketSize();
MaybeUpdatePacketCreatorMaxPacketLengthAndPadding();
@@ -704,11 +725,13 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
void QuicConnection::EnableLegacyVersionEncapsulation(
const std::string& server_name) {
if (perspective_ != Perspective::IS_CLIENT) {
- QUIC_BUG << "Cannot enable Legacy Version Encapsulation on the server";
+ QUIC_BUG(quic_bug_10511_1)
+ << "Cannot enable Legacy Version Encapsulation on the server";
return;
}
if (legacy_version_encapsulation_enabled_) {
- QUIC_BUG << "Do not call EnableLegacyVersionEncapsulation twice";
+ QUIC_BUG(quic_bug_10511_2)
+ << "Do not call EnableLegacyVersionEncapsulation twice";
return;
}
if (!QuicHostnameUtils::IsValidSNI(server_name)) {
@@ -864,7 +887,7 @@ bool QuicConnection::OnProtocolVersionMismatch(
<< ParsedQuicVersionToString(received_version);
if (perspective_ == Perspective::IS_CLIENT) {
const std::string error_details = "Protocol version mismatch.";
- QUIC_BUG << ENDPOINT << error_details;
+ QUIC_BUG(quic_bug_10511_3) << ENDPOINT << error_details;
CloseConnection(QUIC_INTERNAL_ERROR, error_details,
ConnectionCloseBehavior::SILENT_CLOSE);
}
@@ -884,7 +907,7 @@ void QuicConnection::OnVersionNegotiationPacket(
if (perspective_ == Perspective::IS_SERVER) {
const std::string error_details =
"Server received version negotiation packet.";
- QUIC_BUG << error_details;
+ QUIC_BUG(quic_bug_10511_4) << error_details;
QUIC_CODE_COUNT(quic_tear_down_local_connection_on_version_negotiation);
CloseConnection(QUIC_INTERNAL_ERROR, error_details,
ConnectionCloseBehavior::SILENT_CLOSE);
@@ -957,8 +980,7 @@ void QuicConnection::OnRetryPacket(QuicConnectionId original_connection_id,
QUICHE_DCHECK(!retry_source_connection_id_.has_value())
<< retry_source_connection_id_.value();
retry_source_connection_id_ = new_connection_id;
- server_connection_id_ = new_connection_id;
- packet_creator_.SetServerConnectionId(server_connection_id_);
+ ReplaceInitialServerConnectionId(new_connection_id);
packet_creator_.SetRetryToken(retry_token);
// Reinstall initial crypters because the connection ID changed.
@@ -1007,10 +1029,16 @@ bool QuicConnection::OnUnauthenticatedPublicHeader(
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 (server_connection_id != server_connection_id_ &&
+ 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 "
@@ -1038,6 +1066,14 @@ bool QuicConnection::OnUnauthenticatedPublicHeader(
return true;
}
+ if (framer_.do_not_synthesize_source_cid_for_short_header() &&
+ 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_);
@@ -1069,7 +1105,10 @@ bool QuicConnection::OnUnauthenticatedHeader(const QuicPacketHeader& 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(GetServerConnectionIdAsRecipient(header, perspective_) ==
+ 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_)) ||
@@ -1080,7 +1119,8 @@ bool QuicConnection::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
const std::string error_details =
"Pending frames must be serialized before incoming packets are "
"processed.";
- QUIC_BUG << error_details << ", received header: " << header;
+ QUIC_BUG(quic_pending_frames_not_serialized)
+ << error_details << ", received header: " << header;
CloseConnection(QUIC_INTERNAL_ERROR, error_details,
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
@@ -1261,7 +1301,7 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
}
bool QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) {
- QUIC_BUG_IF(!connected_)
+ QUIC_BUG_IF(quic_bug_12714_3, !connected_)
<< "Processing STREAM frame when connection is closed. Last frame: "
<< most_recent_frame_type_;
@@ -1283,11 +1323,11 @@ bool QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) {
return false;
}
- QUIC_PEER_BUG << ENDPOINT
- << "Received an unencrypted data frame: closing connection"
- << " packet_number:" << last_header_.packet_number
- << " stream_id:" << frame.stream_id
- << " received_packets:" << ack_frame();
+ QUIC_PEER_BUG(quic_peer_bug_10511_6)
+ << ENDPOINT << "Received an unencrypted data frame: closing connection"
+ << " packet_number:" << last_header_.packet_number
+ << " stream_id:" << frame.stream_id
+ << " received_packets:" << ack_frame();
CloseConnection(QUIC_UNENCRYPTED_STREAM_DATA,
"Unencrypted stream data seen.",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -1301,7 +1341,7 @@ bool QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) {
}
bool QuicConnection::OnCryptoFrame(const QuicCryptoFrame& frame) {
- QUIC_BUG_IF(!connected_)
+ QUIC_BUG_IF(quic_bug_12714_4, !connected_)
<< "Processing CRYPTO frame when connection is closed. Last frame: "
<< most_recent_frame_type_;
@@ -1321,7 +1361,7 @@ bool QuicConnection::OnCryptoFrame(const QuicCryptoFrame& frame) {
bool QuicConnection::OnAckFrameStart(QuicPacketNumber largest_acked,
QuicTime::Delta ack_delay_time) {
- QUIC_BUG_IF(!connected_)
+ QUIC_BUG_IF(quic_bug_12714_5, !connected_)
<< "Processing ACK frame start when connection is closed. Last frame: "
<< most_recent_frame_type_;
@@ -1369,7 +1409,7 @@ bool QuicConnection::OnAckFrameStart(QuicPacketNumber largest_acked,
}
bool QuicConnection::OnAckRange(QuicPacketNumber start, QuicPacketNumber end) {
- QUIC_BUG_IF(!connected_)
+ QUIC_BUG_IF(quic_bug_12714_6, !connected_)
<< "Processing ACK frame range when connection is closed. Last frame: "
<< most_recent_frame_type_;
QUIC_DVLOG(1) << ENDPOINT << "OnAckRange: [" << start << ", " << end << ")";
@@ -1386,9 +1426,10 @@ bool QuicConnection::OnAckRange(QuicPacketNumber start, QuicPacketNumber end) {
bool QuicConnection::OnAckTimestamp(QuicPacketNumber packet_number,
QuicTime timestamp) {
- QUIC_BUG_IF(!connected_) << "Processing ACK frame time stamp when connection "
- "is closed. Last frame: "
- << most_recent_frame_type_;
+ QUIC_BUG_IF(quic_bug_10511_7, !connected_)
+ << "Processing ACK frame time stamp when connection "
+ "is closed. Last frame: "
+ << most_recent_frame_type_;
QUIC_DVLOG(1) << ENDPOINT << "OnAckTimestamp: [" << packet_number << ", "
<< timestamp.ToDebuggingValue() << ")";
@@ -1403,7 +1444,7 @@ bool QuicConnection::OnAckTimestamp(QuicPacketNumber packet_number,
}
bool QuicConnection::OnAckFrameEnd(QuicPacketNumber start) {
- QUIC_BUG_IF(!connected_)
+ QUIC_BUG_IF(quic_bug_12714_7, !connected_)
<< "Processing ACK frame end when connection is closed. Last frame: "
<< most_recent_frame_type_;
QUIC_DVLOG(1) << ENDPOINT << "OnAckFrameEnd, start: " << start;
@@ -1464,7 +1505,7 @@ bool QuicConnection::OnAckFrameEnd(QuicPacketNumber start) {
}
bool QuicConnection::OnStopWaitingFrame(const QuicStopWaitingFrame& frame) {
- QUIC_BUG_IF(!connected_)
+ QUIC_BUG_IF(quic_bug_12714_8, !connected_)
<< "Processing STOP_WAITING frame when connection is closed. Last frame: "
<< most_recent_frame_type_;
@@ -1502,7 +1543,7 @@ bool QuicConnection::OnStopWaitingFrame(const QuicStopWaitingFrame& frame) {
}
bool QuicConnection::OnPaddingFrame(const QuicPaddingFrame& frame) {
- QUIC_BUG_IF(!connected_)
+ QUIC_BUG_IF(quic_bug_12714_9, !connected_)
<< "Processing PADDING frame when connection is closed. Last frame: "
<< most_recent_frame_type_;
if (!UpdatePacketContent(PADDING_FRAME)) {
@@ -1516,7 +1557,7 @@ bool QuicConnection::OnPaddingFrame(const QuicPaddingFrame& frame) {
}
bool QuicConnection::OnPingFrame(const QuicPingFrame& frame) {
- QUIC_BUG_IF(!connected_)
+ QUIC_BUG_IF(quic_bug_12714_10, !connected_)
<< "Processing PING frame when connection is closed. Last frame: "
<< most_recent_frame_type_;
if (!UpdatePacketContent(PING_FRAME)) {
@@ -1560,7 +1601,7 @@ const char* QuicConnection::ValidateStopWaitingFrame(
}
bool QuicConnection::OnRstStreamFrame(const QuicRstStreamFrame& frame) {
- QUIC_BUG_IF(!connected_)
+ QUIC_BUG_IF(quic_bug_12714_11, !connected_)
<< "Processing RST_STREAM frame when connection is closed. Last frame: "
<< most_recent_frame_type_;
@@ -1583,7 +1624,7 @@ bool QuicConnection::OnRstStreamFrame(const QuicRstStreamFrame& frame) {
}
bool QuicConnection::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
- QUIC_BUG_IF(!connected_)
+ QUIC_BUG_IF(quic_bug_12714_12, !connected_)
<< "Processing STOP_SENDING frame when connection is closed. Last frame: "
<< most_recent_frame_type_;
@@ -1623,18 +1664,20 @@ class ReversePathValidationContext : public QuicPathValidationContext {
};
bool QuicConnection::OnPathChallengeFrame(const QuicPathChallengeFrame& frame) {
- QUIC_BUG_IF(!connected_) << "Processing PATH_CHALLENGE frame when connection "
- "is closed. Last frame: "
- << most_recent_frame_type_;
+ QUIC_BUG_IF(quic_bug_10511_8, !connected_)
+ << "Processing PATH_CHALLENGE frame when connection "
+ "is closed. Last frame: "
+ << most_recent_frame_type_;
if (has_path_challenge_in_current_packet_) {
QUICHE_DCHECK(send_path_response_);
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_send_path_response, 2, 5);
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_send_path_response2, 2, 5);
// Only respond to the 1st PATH_CHALLENGE in the packet.
return true;
}
if (!validate_client_addresses_) {
return OnPathChallengeFrameInternal(frame);
}
+ QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 1, 6);
{
// UpdatePacketStateAndReplyPathChallenge() may start reverse path
// validation, if so bundle the PATH_CHALLENGE together with the
@@ -1668,7 +1711,7 @@ bool QuicConnection::OnPathChallengeFrameInternal(
MaybeUpdateAckTimeout();
return true;
}
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_send_path_response, 3, 5);
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_send_path_response2, 3, 5);
has_path_challenge_in_current_packet_ = true;
MaybeUpdateAckTimeout();
// Queue or send PATH_RESPONSE. Send PATH_RESPONSE to the source address of
@@ -1688,9 +1731,10 @@ bool QuicConnection::OnPathChallengeFrameInternal(
}
bool QuicConnection::OnPathResponseFrame(const QuicPathResponseFrame& frame) {
- QUIC_BUG_IF(!connected_) << "Processing PATH_RESPONSE frame when connection "
- "is closed. Last frame: "
- << most_recent_frame_type_;
+ QUIC_BUG_IF(quic_bug_10511_9, !connected_)
+ << "Processing PATH_RESPONSE frame when connection "
+ "is closed. Last frame: "
+ << most_recent_frame_type_;
if (!UpdatePacketContent(PATH_RESPONSE_FRAME)) {
return false;
}
@@ -1699,6 +1743,7 @@ bool QuicConnection::OnPathResponseFrame(const QuicPathResponseFrame& frame) {
}
MaybeUpdateAckTimeout();
if (use_path_validator_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_pass_path_response_to_validator, 1, 4);
path_validator_.OnPathResponse(frame.data_buffer,
last_packet_destination_address_);
} else {
@@ -1715,9 +1760,10 @@ bool QuicConnection::OnPathResponseFrame(const QuicPathResponseFrame& frame) {
bool QuicConnection::OnConnectionCloseFrame(
const QuicConnectionCloseFrame& frame) {
- QUIC_BUG_IF(!connected_) << "Processing CONNECTION_CLOSE frame when "
- "connection is closed. Last frame: "
- << most_recent_frame_type_;
+ QUIC_BUG_IF(quic_bug_10511_10, !connected_)
+ << "Processing CONNECTION_CLOSE frame when "
+ "connection is closed. Last frame: "
+ << most_recent_frame_type_;
// Since a connection close frame was received, this is not a connectivity
// probe. A probe only contains a PING and full padding.
@@ -1765,7 +1811,7 @@ bool QuicConnection::OnConnectionCloseFrame(
}
bool QuicConnection::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
- QUIC_BUG_IF(!connected_)
+ QUIC_BUG_IF(quic_bug_12714_13, !connected_)
<< "Processing MAX_STREAMS frame when connection is closed. Last frame: "
<< most_recent_frame_type_;
if (!UpdatePacketContent(MAX_STREAMS_FRAME)) {
@@ -1780,9 +1826,10 @@ bool QuicConnection::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
bool QuicConnection::OnStreamsBlockedFrame(
const QuicStreamsBlockedFrame& frame) {
- QUIC_BUG_IF(!connected_) << "Processing STREAMS_BLOCKED frame when "
- "connection is closed. Last frame: "
- << most_recent_frame_type_;
+ QUIC_BUG_IF(quic_bug_10511_11, !connected_)
+ << "Processing STREAMS_BLOCKED frame when "
+ "connection is closed. Last frame: "
+ << most_recent_frame_type_;
if (!UpdatePacketContent(STREAMS_BLOCKED_FRAME)) {
return false;
}
@@ -1794,7 +1841,7 @@ bool QuicConnection::OnStreamsBlockedFrame(
}
bool QuicConnection::OnGoAwayFrame(const QuicGoAwayFrame& frame) {
- QUIC_BUG_IF(!connected_)
+ QUIC_BUG_IF(quic_bug_12714_14, !connected_)
<< "Processing GOAWAY frame when connection is closed. Last frame: "
<< most_recent_frame_type_;
@@ -1817,9 +1864,10 @@ bool QuicConnection::OnGoAwayFrame(const QuicGoAwayFrame& frame) {
}
bool QuicConnection::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
- QUIC_BUG_IF(!connected_) << "Processing WINDOW_UPDATE frame when connection "
- "is closed. Last frame: "
- << most_recent_frame_type_;
+ QUIC_BUG_IF(quic_bug_10511_12, !connected_)
+ << "Processing WINDOW_UPDATE frame when connection "
+ "is closed. Last frame: "
+ << most_recent_frame_type_;
// Since a window update frame was received, this is not a connectivity probe.
// A probe only contains a PING and full padding.
@@ -1837,11 +1885,34 @@ bool QuicConnection::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
return connected_;
}
+bool QuicConnection::OnNewConnectionIdFrameInner(
+ const QuicNewConnectionIdFrame& frame) {
+ QUICHE_DCHECK(support_multiple_connection_ids_);
+ if (peer_issued_cid_manager_ == nullptr) {
+ CloseConnection(
+ IETF_QUIC_PROTOCOL_VIOLATION,
+ "Receives NEW_CONNECTION_ID while peer uses zero length connection ID",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+ std::string error_detail;
+ QuicErrorCode error =
+ peer_issued_cid_manager_->OnNewConnectionIdFrame(frame, &error_detail);
+ if (error != QUIC_NO_ERROR) {
+ CloseConnection(error, error_detail,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_support_multiple_cids_v2, 1, 2);
+ return true;
+}
+
bool QuicConnection::OnNewConnectionIdFrame(
const QuicNewConnectionIdFrame& frame) {
- QUIC_BUG_IF(!connected_) << "Processing NEW_CONNECTION_ID frame when "
- "connection is closed. Last frame: "
- << most_recent_frame_type_;
+ QUIC_BUG_IF(quic_bug_10511_13, !connected_)
+ << "Processing NEW_CONNECTION_ID frame when "
+ "connection is closed. Last frame: "
+ << most_recent_frame_type_;
if (!UpdatePacketContent(NEW_CONNECTION_ID_FRAME)) {
return false;
}
@@ -1849,14 +1920,18 @@ bool QuicConnection::OnNewConnectionIdFrame(
if (debug_visitor_ != nullptr) {
debug_visitor_->OnNewConnectionIdFrame(frame);
}
- return true;
+ if (!support_multiple_connection_ids_) {
+ return true;
+ }
+ return OnNewConnectionIdFrameInner(frame);
}
bool QuicConnection::OnRetireConnectionIdFrame(
const QuicRetireConnectionIdFrame& frame) {
- QUIC_BUG_IF(!connected_) << "Processing RETIRE_CONNECTION_ID frame when "
- "connection is closed. Last frame: "
- << most_recent_frame_type_;
+ QUIC_BUG_IF(quic_bug_10511_14, !connected_)
+ << "Processing RETIRE_CONNECTION_ID frame when "
+ "connection is closed. Last frame: "
+ << most_recent_frame_type_;
if (!UpdatePacketContent(RETIRE_CONNECTION_ID_FRAME)) {
return false;
}
@@ -1864,11 +1939,30 @@ bool QuicConnection::OnRetireConnectionIdFrame(
if (debug_visitor_ != nullptr) {
debug_visitor_->OnRetireConnectionIdFrame(frame);
}
+ if (!support_multiple_connection_ids_) {
+ return true;
+ }
+ if (self_issued_cid_manager_ == nullptr) {
+ CloseConnection(
+ IETF_QUIC_PROTOCOL_VIOLATION,
+ "Receives RETIRE_CONNECTION_ID while new connection ID is never issued",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+ std::string error_detail;
+ QuicErrorCode error = self_issued_cid_manager_->OnRetireConnectionIdFrame(
+ frame, sent_packet_manager_.GetPtoDelay(), &error_detail);
+ if (error != QUIC_NO_ERROR) {
+ CloseConnection(error, error_detail,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_support_multiple_cids_v2, 2, 2);
return true;
}
bool QuicConnection::OnNewTokenFrame(const QuicNewTokenFrame& frame) {
- QUIC_BUG_IF(!connected_)
+ QUIC_BUG_IF(quic_bug_12714_15, !connected_)
<< "Processing NEW_TOKEN frame when connection is closed. Last frame: "
<< most_recent_frame_type_;
if (!UpdatePacketContent(NEW_TOKEN_FRAME)) {
@@ -1893,7 +1987,7 @@ bool QuicConnection::OnNewTokenFrame(const QuicNewTokenFrame& frame) {
}
bool QuicConnection::OnMessageFrame(const QuicMessageFrame& frame) {
- QUIC_BUG_IF(!connected_)
+ QUIC_BUG_IF(quic_bug_12714_16, !connected_)
<< "Processing MESSAGE frame when connection is closed. Last frame: "
<< most_recent_frame_type_;
@@ -1913,9 +2007,10 @@ bool QuicConnection::OnMessageFrame(const QuicMessageFrame& frame) {
}
bool QuicConnection::OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) {
- QUIC_BUG_IF(!connected_) << "Processing HANDSHAKE_DONE frame when connection "
- "is closed. Last frame: "
- << most_recent_frame_type_;
+ QUIC_BUG_IF(quic_bug_10511_15, !connected_)
+ << "Processing HANDSHAKE_DONE frame when connection "
+ "is closed. Last frame: "
+ << most_recent_frame_type_;
if (!version().UsesTls()) {
CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION,
"Handshake done frame is unsupported",
@@ -1945,9 +2040,10 @@ bool QuicConnection::OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) {
}
bool QuicConnection::OnAckFrequencyFrame(const QuicAckFrequencyFrame& frame) {
- QUIC_BUG_IF(!connected_) << "Processing ACK_FREQUENCY frame when connection "
- "is closed. Last frame: "
- << most_recent_frame_type_;
+ QUIC_BUG_IF(quic_bug_10511_16, !connected_)
+ << "Processing ACK_FREQUENCY frame when connection "
+ "is closed. Last frame: "
+ << most_recent_frame_type_;
if (debug_visitor_ != nullptr) {
debug_visitor_->OnAckFrequencyFrame(frame);
}
@@ -1973,7 +2069,7 @@ bool QuicConnection::OnAckFrequencyFrame(const QuicAckFrequencyFrame& frame) {
}
bool QuicConnection::OnBlockedFrame(const QuicBlockedFrame& frame) {
- QUIC_BUG_IF(!connected_)
+ QUIC_BUG_IF(quic_bug_12714_17, !connected_)
<< "Processing BLOCKED frame when connection is closed. Last frame was "
<< most_recent_frame_type_;
@@ -2098,7 +2194,8 @@ void QuicConnection::MaybeRespondToConnectivityProbingOrMigration() {
}
}
-bool QuicConnection::IsValidStatelessResetToken(QuicUint128 token) const {
+bool QuicConnection::IsValidStatelessResetToken(
+ const StatelessResetToken& token) const {
return stateless_reset_token_received_ &&
token == received_stateless_reset_token_;
}
@@ -2111,17 +2208,19 @@ void QuicConnection::OnAuthenticatedIetfStatelessResetPacket(
QUICHE_DCHECK_EQ(perspective_, Perspective::IS_CLIENT);
if (use_path_validator_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_pass_path_response_to_validator, 4, 4);
if (!IsDefaultPath(last_packet_destination_address_,
last_packet_source_address_)) {
// This packet is received on a probing path. Do not close connection.
if (IsAlternativePath(last_packet_destination_address_,
GetEffectivePeerAddressFromCurrentPacket())) {
- QUIC_BUG_IF(alternative_path_.validated)
+ QUIC_BUG_IF(quic_bug_12714_18, alternative_path_.validated)
<< "STATELESS_RESET received on alternate path after it's "
"validated.";
path_validator_.CancelPathValidation();
} else {
- QUIC_BUG << "Received Stateless Reset on unknown socket.";
+ QUIC_BUG(quic_bug_10511_17)
+ << "Received Stateless Reset on unknown socket.";
}
return;
}
@@ -2255,7 +2354,7 @@ void QuicConnection::MaybeSendInResponseToPacket() {
if (defer_send_in_response_to_packets_) {
send_alarm_->Update(clock_->ApproximateNow(), QuicTime::Delta::Zero());
} else {
- WriteAndBundleAcksIfNotBlocked();
+ WriteIfNotBlocked();
}
}
@@ -2264,9 +2363,9 @@ void QuicConnection::MaybeActivateLegacyVersionEncapsulation() {
return;
}
QUICHE_DCHECK(!legacy_version_encapsulation_in_progress_);
- QUIC_BUG_IF(!packet_creator_.CanSetMaxPacketLength())
+ QUIC_BUG_IF(quic_bug_12714_19, !packet_creator_.CanSetMaxPacketLength())
<< "Cannot activate Legacy Version Encapsulation mid-packet";
- QUIC_BUG_IF(coalesced_packet_.length() != 0u)
+ QUIC_BUG_IF(quic_bug_12714_20, coalesced_packet_.length() != 0u)
<< "Cannot activate Legacy Version Encapsulation mid-coalesced-packet";
legacy_version_encapsulation_in_progress_ = true;
MaybeUpdatePacketCreatorMaxPacketLengthAndPadding();
@@ -2286,7 +2385,7 @@ size_t QuicConnection::SendCryptoData(EncryptionLevel level,
size_t write_length,
QuicStreamOffset offset) {
if (write_length == 0) {
- QUIC_BUG << "Attempt to send empty crypto frame";
+ QUIC_BUG(quic_bug_10511_18) << "Attempt to send empty crypto frame";
return 0;
}
if (level == ENCRYPTION_INITIAL) {
@@ -2307,7 +2406,7 @@ QuicConsumedData QuicConnection::SendStreamData(QuicStreamId id,
QuicStreamOffset offset,
StreamSendingState state) {
if (state == NO_FIN && write_length == 0) {
- QUIC_BUG << "Attempt to send empty stream frame";
+ QUIC_BUG(quic_bug_10511_19) << "Attempt to send empty stream frame";
return QuicConsumedData(0, false);
}
@@ -2315,6 +2414,21 @@ QuicConsumedData QuicConnection::SendStreamData(QuicStreamId id,
QuicUtils::IsCryptoStreamId(transport_version(), id)) {
MaybeActivateLegacyVersionEncapsulation();
}
+ if (GetQuicReloadableFlag(quic_preempt_stream_data_with_handshake_packet) &&
+ perspective_ == Perspective::IS_SERVER &&
+ version().CanSendCoalescedPackets() && !IsHandshakeConfirmed()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_preempt_stream_data_with_handshake_packet,
+ 1, 2);
+ 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);
+ }
+ }
QuicConsumedData consumed_data(0, false);
{
// Opportunistically bundle an ack with every outgoing packet.
@@ -2510,9 +2624,10 @@ void QuicConnection::MaybeUpdatePacketCreatorMaxPacketLengthAndPadding() {
QuicLegacyVersionEncapsulator::GetMinimumOverhead(
legacy_version_encapsulation_sni_);
if (max_packet_length < minimum_overhead) {
- QUIC_BUG << "Cannot apply Legacy Version Encapsulation overhead because "
- << "max_packet_length " << max_packet_length
- << " < minimum_overhead " << minimum_overhead;
+ QUIC_BUG(quic_bug_10511_20)
+ << "Cannot apply Legacy Version Encapsulation overhead because "
+ << "max_packet_length " << max_packet_length << " < minimum_overhead "
+ << minimum_overhead;
legacy_version_encapsulation_in_progress_ = false;
legacy_version_encapsulation_enabled_ = false;
MaybeUpdatePacketCreatorMaxPacketLengthAndPadding();
@@ -2533,7 +2648,7 @@ void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address,
<< " bytes:" << std::endl
<< quiche::QuicheTextUtils::HexDump(
absl::string_view(packet.data(), packet.length()));
- QUIC_BUG_IF(current_packet_data_ != nullptr)
+ QUIC_BUG_IF(quic_bug_12714_21, current_packet_data_ != nullptr)
<< "ProcessUdpPacket must not be called while processing a packet.";
if (debug_visitor_ != nullptr) {
debug_visitor_->OnPacketReceived(self_address, peer_address, packet);
@@ -2581,10 +2696,10 @@ void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address,
// Ensure the time coming from the packet reader is within 2 minutes of now.
if (std::abs((packet.receipt_time() - clock_->ApproximateNow()).ToSeconds()) >
2 * 60) {
- QUIC_BUG << "Packet receipt time:"
- << packet.receipt_time().ToDebuggingValue()
- << " too far from current time:"
- << clock_->ApproximateNow().ToDebuggingValue();
+ QUIC_BUG(quic_bug_10511_21)
+ << "Packet receipt time:" << packet.receipt_time().ToDebuggingValue()
+ << " too far from current time:"
+ << clock_->ApproximateNow().ToDebuggingValue();
}
time_of_last_received_packet_ = packet.receipt_time();
QUIC_DVLOG(1) << ENDPOINT << "time of last received packet: "
@@ -2623,9 +2738,12 @@ void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address,
}
}
- MaybeProcessCoalescedPackets();
- MaybeProcessUndecryptablePackets();
- MaybeSendInResponseToPacket();
+ const bool processed = MaybeProcessCoalescedPackets();
+ if (!donot_write_mid_packet_processing_ || !processed) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_donot_write_mid_packet_processing, 3, 3);
+ MaybeProcessUndecryptablePackets();
+ MaybeSendInResponseToPacket();
+ }
SetPingAlarm();
current_packet_data_ = nullptr;
is_current_packet_connectivity_probing_ = false;
@@ -2643,13 +2761,12 @@ void QuicConnection::OnCanWrite() {
if (writer_->IsWriteBlocked()) {
const std::string error_details =
"Writer is blocked while calling OnCanWrite.";
- QUIC_BUG << ENDPOINT << error_details;
+ QUIC_BUG(quic_bug_10511_22) << ENDPOINT << error_details;
CloseConnection(QUIC_INTERNAL_ERROR, error_details,
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
- // Add a flusher to ensure the connection is marked app-limited.
ScopedPacketFlusher flusher(this);
WriteQueuedPackets();
@@ -2669,7 +2786,7 @@ void QuicConnection::OnCanWrite() {
// TODO(danzh) PATH_RESPONSE is of more interest to the peer than ACK,
// evaluate if it's worth to send them before sending ACKs.
while (!pending_path_challenge_payloads_.empty()) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_send_path_response, 4, 5);
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_send_path_response2, 4, 5);
const PendingPathChallenge& pending_path_challenge =
pending_path_challenge_payloads_.front();
if (!SendPathResponse(pending_path_challenge.received_path_challenge,
@@ -2678,48 +2795,76 @@ void QuicConnection::OnCanWrite() {
}
pending_path_challenge_payloads_.pop_front();
}
- WriteNewData();
-}
-void QuicConnection::WriteNewData() {
// Sending queued packets may have caused the socket to become write blocked,
- // or the congestion manager to prohibit sending. If we've sent everything
- // we had queued and we're still not blocked, let the visitor know it can
- // write more.
+ // or the congestion manager to prohibit sending.
if (!CanWrite(HAS_RETRANSMITTABLE_DATA)) {
return;
}
- {
- ScopedPacketFlusher flusher(this);
- visitor_->OnCanWrite();
- }
+ // Tell the session it can write.
+ visitor_->OnCanWrite();
// After the visitor writes, it may have caused the socket to become write
// blocked or the congestion manager to prohibit sending, so check again.
if (visitor_->WillingAndAbleToWrite() && !send_alarm_->IsSet() &&
CanWrite(HAS_RETRANSMITTABLE_DATA)) {
- // We're not write blocked, but some stream didn't write out all of its
- // bytes. Register for 'immediate' resumption so we'll keep writing after
- // other connections and events have had a chance to use the thread.
+ // We're not write blocked, but some data wasn't written. Register for
+ // 'immediate' resumption so we'll keep writing after other connections.
send_alarm_->Set(clock_->ApproximateNow());
}
}
void QuicConnection::WriteIfNotBlocked() {
+ if (donot_write_mid_packet_processing_ && framer().is_processing_packet()) {
+ QUIC_BUG(connection_write_mid_packet_processing)
+ << ENDPOINT << "Tried to write in mid of packet processing";
+ return;
+ }
if (!HandleWriteBlocked()) {
OnCanWrite();
}
}
-void QuicConnection::WriteAndBundleAcksIfNotBlocked() {
- if (!HandleWriteBlocked()) {
- ScopedPacketFlusher flusher(this);
- WriteIfNotBlocked();
+void QuicConnection::ReplaceInitialServerConnectionId(
+ const QuicConnectionId& new_server_connection_id) {
+ QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT);
+ if (support_multiple_connection_ids_) {
+ if (new_server_connection_id.IsEmpty()) {
+ peer_issued_cid_manager_ = nullptr;
+ } else {
+ if (peer_issued_cid_manager_ != nullptr) {
+ QUIC_BUG_IF(quic_bug_12714_22,
+ !peer_issued_cid_manager_->IsConnectionIdActive(
+ server_connection_id_))
+ << "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_,
+ new_server_connection_id);
+ } else {
+ peer_issued_cid_manager_ =
+ std::make_unique<QuicPeerIssuedConnectionIdManager>(
+ kMinNumOfActiveConnectionIds, new_server_connection_id, clock_,
+ alarm_factory_, this);
+ }
+ }
}
+ server_connection_id_ = new_server_connection_id;
+ packet_creator_.SetServerConnectionId(server_connection_id_);
}
bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
+ if (perspective_ == Perspective::IS_CLIENT && version().HasIetfQuicFrames() &&
+ direct_peer_address_.IsInitialized() &&
+ last_packet_source_address_.IsInitialized() &&
+ direct_peer_address_ != last_packet_source_address_ &&
+ !visitor_->IsKnownServerAddress(last_packet_source_address_)) {
+ // TODO(haoyuewang) Revisit this when preferred_address transport parameter
+ // is used on the client side.
+ // Discard packets received from unseen server addresses.
+ return false;
+ }
+
if (perspective_ == Perspective::IS_SERVER &&
default_path_.self_address.IsInitialized() &&
last_packet_destination_address_.IsInitialized() &&
@@ -2742,14 +2887,21 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
if (PacketCanReplaceConnectionId(header, perspective_) &&
server_connection_id_ != 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 "
+ << header.source_connection_id;
+ return false;
+ }
+ server_connection_id_replaced_by_initial_ = true;
QUIC_DLOG(INFO) << ENDPOINT << "Replacing connection ID "
<< server_connection_id_ << " with "
<< header.source_connection_id;
if (!original_destination_connection_id_.has_value()) {
original_destination_connection_id_ = server_connection_id_;
}
- server_connection_id_ = header.source_connection_id;
- packet_creator_.SetServerConnectionId(server_connection_id_);
+ ReplaceInitialServerConnectionId(header.source_connection_id);
}
if (!ValidateReceivedPacketNumber(header.packet_number)) {
@@ -2926,7 +3078,7 @@ const QuicFrames QuicConnection::MaybeBundleAckOpportunistically() {
QUIC_DVLOG(1) << ENDPOINT << "Bundle an ACK opportunistically";
QuicFrame updated_ack_frame = GetUpdatedAckFrame();
- QUIC_BUG_IF(updated_ack_frame.ack_frame->packets.Empty())
+ QUIC_BUG_IF(quic_bug_12714_23, updated_ack_frame.ack_frame->packets.Empty())
<< ENDPOINT << "Attempted to opportunistically bundle an empty "
<< encryption_level_ << " ACK, " << (has_pending_ack ? "" : "!")
<< "has_pending_ack, stop_waiting_count_ " << stop_waiting_count_;
@@ -3025,8 +3177,9 @@ QuicTime QuicConnection::CalculatePacketSentTime() {
bool QuicConnection::WritePacket(SerializedPacket* packet) {
if (sent_packet_manager_.GetLargestSentPacket().IsInitialized() &&
packet->packet_number < sent_packet_manager_.GetLargestSentPacket()) {
- QUIC_BUG << "Attempt to write packet:" << packet->packet_number
- << " after:" << sent_packet_manager_.GetLargestSentPacket();
+ QUIC_BUG(quic_bug_10511_23)
+ << "Attempt to write packet:" << packet->packet_number
+ << " after:" << sent_packet_manager_.GetLargestSentPacket();
CloseConnection(QUIC_INTERNAL_ERROR, "Packet written out of order.",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return true;
@@ -3095,7 +3248,8 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
++stats_.packets_discarded;
return true;
case COALESCE:
- QUIC_BUG_IF(!version().CanSendCoalescedPackets() || coalescing_done_);
+ QUIC_BUG_IF(quic_bug_12714_24,
+ !version().CanSendCoalescedPackets() || coalescing_done_);
if (!coalesced_packet_.MaybeCoalescePacket(
*packet, self_address(), send_to_address,
helper_->GetStreamSendBufferAllocator(),
@@ -3180,10 +3334,10 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
<< quiche::QuicheTextUtils::HexDump(absl::string_view(
packet->encrypted_buffer, encrypted_length));
} else {
- QUIC_BUG << ENDPOINT
- << "Failed to perform Legacy Version Encapsulation on "
- << packet->encryption_level << " packet number "
- << packet_number << " of length " << encrypted_length;
+ QUIC_BUG(quic_bug_10511_24)
+ << ENDPOINT << "Failed to perform Legacy Version Encapsulation on "
+ << packet->encryption_level << " packet number " << packet_number
+ << " of length " << encrypted_length;
}
if (!buffered_packets_.empty() || HandleWriteBlocked()) {
// Buffer the packet.
@@ -3239,6 +3393,7 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
return true;
}
if (use_path_validator_ && !send_on_current_path) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_pass_path_response_to_validator, 2, 4);
// Only handle MSG_TOO_BIG as error on current path.
return true;
}
@@ -3316,15 +3471,17 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
const bool in_flight = sent_packet_manager_.OnPacketSent(
packet, packet_send_time, packet->transmission_type,
IsRetransmittable(*packet), /*measure_rtt=*/send_on_current_path);
- QUIC_BUG_IF(default_enable_5rto_blackhole_detection_ &&
- blackhole_detector_.IsDetectionInProgress() &&
- !sent_packet_manager_.HasInFlightPackets())
+ QUIC_BUG_IF(quic_bug_12714_25,
+ default_enable_5rto_blackhole_detection_ &&
+ blackhole_detector_.IsDetectionInProgress() &&
+ !sent_packet_manager_.HasInFlightPackets())
<< ENDPOINT
<< "Trying to start blackhole detection without no bytes in flight";
if (debug_visitor_ != nullptr) {
if (sent_packet_manager_.unacked_packets().empty()) {
- QUIC_BUG << "Unacked map is empty right after packet is sent";
+ QUIC_BUG(quic_bug_10511_25)
+ << "Unacked map is empty right after packet is sent";
} else {
debug_visitor_->OnPacketSent(
packet->packet_number, packet->encrypted_length,
@@ -3381,13 +3538,14 @@ bool QuicConnection::MaybeHandleAeadConfidentialityLimits(
}
if (packet.encryption_level != ENCRYPTION_FORWARD_SECURE) {
- QUIC_BUG
+ QUIC_BUG(quic_bug_12714_26)
<< "MaybeHandleAeadConfidentialityLimits called on non 1-RTT packet";
return false;
}
if (!lowest_packet_sent_in_current_key_phase_.IsInitialized()) {
- QUIC_BUG << "lowest_packet_sent_in_current_key_phase_ must be initialized "
- "before calling MaybeHandleAeadConfidentialityLimits";
+ QUIC_BUG(quic_bug_10511_26)
+ << "lowest_packet_sent_in_current_key_phase_ must be initialized "
+ "before calling MaybeHandleAeadConfidentialityLimits";
return false;
}
@@ -3400,7 +3558,7 @@ bool QuicConnection::MaybeHandleAeadConfidentialityLimits(
absl::StrCat("packet_number(", packet.packet_number.ToString(),
") < lowest_packet_sent_in_current_key_phase_ (",
lowest_packet_sent_in_current_key_phase_.ToString(), ")");
- QUIC_BUG << error_details;
+ QUIC_BUG(quic_bug_10511_27) << error_details;
CloseConnection(QUIC_INTERNAL_ERROR, error_details,
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return true;
@@ -3666,6 +3824,27 @@ void QuicConnection::OnPathMtuIncreased(QuicPacketLength packet_size) {
}
}
+std::unique_ptr<QuicSelfIssuedConnectionIdManager>
+QuicConnection::MakeSelfIssuedConnectionIdManager() {
+ QUICHE_DCHECK((perspective_ == Perspective::IS_CLIENT &&
+ !client_connection_id_.IsEmpty()) ||
+ (perspective_ == Perspective::IS_SERVER &&
+ !server_connection_id_.IsEmpty()));
+ return std::make_unique<QuicSelfIssuedConnectionIdManager>(
+ kMinNumOfActiveConnectionIds,
+ perspective_ == Perspective::IS_CLIENT ? client_connection_id_
+ : server_connection_id_,
+ clock_, alarm_factory_, this);
+}
+
+void QuicConnection::MaybeSendConnectionIdToClient() {
+ if (perspective_ == Perspective::IS_CLIENT) {
+ return;
+ }
+ QUICHE_DCHECK(self_issued_cid_manager_ != nullptr);
+ self_issued_cid_manager_->MaybeSendNewConnectionIds();
+}
+
void QuicConnection::OnHandshakeComplete() {
sent_packet_manager_.SetHandshakeConfirmed();
if (send_ack_frequency_on_handshake_completion_ &&
@@ -3831,10 +4010,11 @@ void QuicConnection::OnRetransmissionTimeout() {
// When timer fires in TLP/RTO/PTO mode, ensure 1) at least one packet is
// created, or there is data to send and available credit (such that
// packets will be sent eventually).
- QUIC_BUG_IF(packet_creator_.packet_number() ==
- previous_created_packet_number &&
- (!visitor_->WillingAndAbleToWrite() ||
- sent_packet_manager_.pending_timer_transmission_count() == 0u))
+ QUIC_BUG_IF(
+ quic_bug_12714_27,
+ packet_creator_.packet_number() == previous_created_packet_number &&
+ (!visitor_->WillingAndAbleToWrite() ||
+ sent_packet_manager_.pending_timer_transmission_count() == 0u))
<< "retransmission_mode: " << retransmission_mode
<< ", packet_number: " << packet_creator_.packet_number()
<< ", session has data to write: " << visitor_->WillingAndAbleToWrite()
@@ -3878,7 +4058,7 @@ void QuicConnection::SetDefaultEncryptionLevel(EncryptionLevel level) {
}
encryption_level_ = level;
packet_creator_.set_encryption_level(level);
- QUIC_BUG_IF(!framer_.HasEncrypterOfEncryptionLevel(level))
+ QUIC_BUG_IF(quic_bug_12714_28, !framer_.HasEncrypterOfEncryptionLevel(level))
<< ENDPOINT << "Trying to set encryption level to "
<< EncryptionLevelToString(level) << " while the key is missing";
@@ -3955,7 +4135,7 @@ QuicPacketCount QuicConnection::PotentialPeerKeyUpdateAttemptCount() const {
bool QuicConnection::InitiateKeyUpdate(KeyUpdateReason reason) {
QUIC_DLOG(INFO) << ENDPOINT << "InitiateKeyUpdate";
if (!IsKeyUpdateAllowed()) {
- QUIC_BUG << "key update not allowed";
+ QUIC_BUG(quic_bug_10511_28) << "key update not allowed";
return false;
}
return framer_.DoKeyUpdate(reason);
@@ -4052,14 +4232,14 @@ void QuicConnection::QueueCoalescedPacket(const QuicEncryptedPacket& packet) {
++stats_.num_coalesced_packets_received;
}
-void QuicConnection::MaybeProcessCoalescedPackets() {
+bool QuicConnection::MaybeProcessCoalescedPackets() {
bool processed = false;
while (connected_ && !received_coalesced_packets_.empty()) {
// Making sure there are no pending frames when processing the next
// coalesced packet because the queued ack frame may change.
packet_creator_.FlushCurrentPacket();
if (!connected_) {
- return;
+ return processed;
}
std::unique_ptr<QuicEncryptedPacket> packet =
@@ -4077,7 +4257,13 @@ void QuicConnection::MaybeProcessCoalescedPackets() {
}
if (processed) {
MaybeProcessUndecryptablePackets();
+ if (donot_write_mid_packet_processing_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_donot_write_mid_packet_processing, 2,
+ 3);
+ MaybeSendInResponseToPacket();
+ }
}
+ return processed;
}
void QuicConnection::CloseConnection(
@@ -4258,8 +4444,11 @@ void QuicConnection::TearDownLocalConnectionState(
// connection is closed.
CancelAllAlarms();
if (use_path_validator_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_pass_path_response_to_validator, 3, 4);
CancelPathValidation();
}
+ peer_issued_cid_manager_.reset();
+ self_issued_cid_manager_.reset();
}
void QuicConnection::CancelAllAlarms() {
@@ -4292,7 +4481,7 @@ bool QuicConnection::HasQueuedData() const {
void QuicConnection::SetNetworkTimeouts(QuicTime::Delta handshake_timeout,
QuicTime::Delta idle_timeout) {
- QUIC_BUG_IF(idle_timeout > handshake_timeout)
+ QUIC_BUG_IF(quic_bug_12714_29, idle_timeout > handshake_timeout)
<< "idle_timeout:" << idle_timeout.ToMilliseconds()
<< " handshake_timeout:" << handshake_timeout.ToMilliseconds();
// Adjust the idle timeout on client and server to prevent clients from
@@ -4376,7 +4565,8 @@ void QuicConnection::SetPingAlarm() {
void QuicConnection::SetRetransmissionAlarm() {
if (!connected_) {
if (retransmission_alarm_->IsSet()) {
- QUIC_BUG << ENDPOINT << "Retransmission alarm is set while disconnected";
+ QUIC_BUG(quic_bug_10511_29)
+ << ENDPOINT << "Retransmission alarm is set while disconnected";
retransmission_alarm_->Cancel();
}
return;
@@ -4573,7 +4763,8 @@ void QuicConnection::SetMtuDiscoveryTarget(QuicByteCount target) {
QuicByteCount QuicConnection::GetLimitedMaxPacketSize(
QuicByteCount suggested_max_packet_size) {
if (!peer_address().IsInitialized()) {
- QUIC_BUG << "Attempted to use a connection without a valid peer address";
+ QUIC_BUG(quic_bug_10511_30)
+ << "Attempted to use a connection without a valid peer address";
return suggested_max_packet_size;
}
@@ -4622,8 +4813,9 @@ bool QuicConnection::SendGenericPathProbePacket(
bool is_response) {
QUICHE_DCHECK(peer_address.IsInitialized());
if (!connected_) {
- QUIC_BUG << "Not sending connectivity probing packet as connection is "
- << "disconnected.";
+ QUIC_BUG(quic_bug_10511_31)
+ << "Not sending connectivity probing packet as connection is "
+ << "disconnected.";
return false;
}
if (perspective_ == Perspective::IS_SERVER && probing_writer == nullptr) {
@@ -4719,7 +4911,8 @@ bool QuicConnection::WritePacketUsingWriter(
if (debug_visitor_ != nullptr) {
if (sent_packet_manager_.unacked_packets().empty()) {
- QUIC_BUG << "Unacked map is empty right after packet is sent";
+ QUIC_BUG(quic_bug_10511_32)
+ << "Unacked map is empty right after packet is sent";
} else {
debug_visitor_->OnPacketSent(
packet->packet_number, packet->encrypted_length,
@@ -4766,7 +4959,7 @@ void QuicConnection::DiscoverMtu() {
void QuicConnection::OnEffectivePeerMigrationValidated() {
if (active_effective_peer_migration_type_ == NO_CHANGE) {
- QUIC_BUG << "No migration underway.";
+ QUIC_BUG(quic_bug_10511_33) << "No migration underway.";
return;
}
highest_packet_sent_before_effective_peer_migration_.Clear();
@@ -4777,6 +4970,18 @@ void QuicConnection::OnEffectivePeerMigrationValidated() {
if (!validate_client_addresses_) {
return;
}
+ QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 2, 6);
+ if (debug_visitor_ != nullptr) {
+ const QuicTime now = clock_->ApproximateNow();
+ if (now >= stats_.handshake_completion_time) {
+ debug_visitor_->OnPeerMigrationValidated(
+ now - stats_.handshake_completion_time);
+ } else {
+ QUIC_BUG(quic_bug_10511_34)
+ << "Handshake completion time is larger than current time.";
+ }
+ }
+
// Lift anti-amplification limit.
default_path_.validated = true;
alternative_path_.Clear();
@@ -4791,14 +4996,16 @@ void QuicConnection::StartEffectivePeerMigration(AddressChangeType type) {
// determine whether |type| is allowed.
if (!validate_client_addresses_) {
if (type == NO_CHANGE) {
- QUIC_BUG << "EffectivePeerMigration started without address change.";
+ QUIC_BUG(quic_bug_10511_35)
+ << "EffectivePeerMigration started without address change.";
return;
}
- QUIC_DLOG(INFO) << ENDPOINT << "Effective peer's ip:port changed from "
- << default_path_.peer_address.ToString() << " to "
- << GetEffectivePeerAddressFromCurrentPacket().ToString()
- << ", address change type is " << type
- << ", migrating connection.";
+ QUIC_DLOG(INFO)
+ << ENDPOINT << "Effective peer's ip:port changed from "
+ << default_path_.peer_address.ToString() << " to "
+ << GetEffectivePeerAddressFromCurrentPacket().ToString()
+ << ", address change type is " << type
+ << ", migrating connection without validating new client address.";
highest_packet_sent_before_effective_peer_migration_ =
sent_packet_manager_.GetLargestSentPacket();
@@ -4809,9 +5016,11 @@ void QuicConnection::StartEffectivePeerMigration(AddressChangeType type) {
return;
}
+ QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 3, 6);
if (type == NO_CHANGE) {
UpdatePeerAddress(last_packet_source_address_);
- QUIC_BUG << "EffectivePeerMigration started without address change.";
+ QUIC_BUG(quic_bug_10511_36)
+ << "EffectivePeerMigration started without address change.";
return;
}
@@ -4855,14 +5064,7 @@ void QuicConnection::StartEffectivePeerMigration(AddressChangeType type) {
// congestion controller to initial state first and then change to the one
// on alternative path.
// TODO(danzh) combine these two steps into one after deprecating gQUIC.
- previous_default_path.send_algorithm =
- sent_packet_manager_.OnConnectionMigration(
- /*reset_send_algorithm=*/true);
- // OnConnectionMigration() might have marked in-flight packets to be
- // retransmitted if there is any.
- QUICHE_DCHECK(!sent_packet_manager_.HasInFlightPackets());
- // Stop detections in quiecense.
- blackhole_detector_.StopDetection();
+ previous_default_path.send_algorithm = OnPeerIpAddressChanged();
if (alternative_path_.peer_address.host() ==
current_effective_peer_address.host() &&
@@ -5034,8 +5236,9 @@ void QuicConnection::MaybeSendProbingRetransmissions() {
}
if (probing_retransmission_pending_) {
- QUIC_BUG << "MaybeSendProbingRetransmissions is called while another call "
- "to it is already in progress";
+ QUIC_BUG(quic_bug_10511_37)
+ << "MaybeSendProbingRetransmissions is called while another call "
+ "to it is already in progress";
return;
}
@@ -5067,24 +5270,22 @@ void QuicConnection::CheckIfApplicationLimited() {
}
bool QuicConnection::UpdatePacketContent(QuicFrameType type) {
- if (update_packet_content_returns_connected_) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_update_packet_content_returns_connected);
- }
most_recent_frame_type_ = type;
if (version().HasIetfQuicFrames()) {
if (!QuicUtils::IsProbingFrame(type)) {
MaybeStartIetfPeerMigration();
- return !update_packet_content_returns_connected_ || connected_;
+ return connected_;
}
QuicSocketAddress current_effective_peer_address =
GetEffectivePeerAddressFromCurrentPacket();
if (!count_bytes_on_alternative_path_separately_ ||
IsDefaultPath(last_packet_destination_address_,
last_packet_source_address_)) {
- return !update_packet_content_returns_connected_ || connected_;
+ return connected_;
}
QUIC_CODE_COUNT_N(quic_count_bytes_on_alternative_path_seperately, 3, 5);
- if (type == PATH_CHALLENGE_FRAME &&
+ if (perspective_ == Perspective::IS_SERVER &&
+ type == PATH_CHALLENGE_FRAME &&
!IsAlternativePath(last_packet_destination_address_,
current_effective_peer_address)) {
QUIC_DVLOG(1)
@@ -5095,6 +5296,7 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) {
alternative_path_ = PathState(last_packet_destination_address_,
current_effective_peer_address);
} 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
// completed or the connection is validating the default path. Using
// PATH_CHALLENGE to validate alternative client address before
@@ -5104,9 +5306,11 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) {
// be overridden.
QUIC_DVLOG(1) << "The connection hasn't finished handshake or is "
"validating a recent peer address change.";
- QUIC_BUG_IF(IsHandshakeConfirmed() && !alternative_path_.validated)
+ QUIC_BUG_IF(quic_bug_12714_30,
+ IsHandshakeConfirmed() && !alternative_path_.validated)
<< "No validated peer address to send after handshake comfirmed.";
} else if (!IsReceivedPeerAddressValidated()) {
+ QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 5, 6);
// 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.
@@ -5128,7 +5332,7 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) {
}
}
MaybeUpdateBytesReceivedFromAlternativeAddress(last_size_);
- return !update_packet_content_returns_connected_ || connected_;
+ return connected_;
}
// Packet content is tracked to identify connectivity probe in non-IETF
// version, where a connectivity probe is defined as
@@ -5139,13 +5343,13 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) {
// We have already learned the current packet is not a connectivity
// probing packet. Peer migration should have already been started earlier
// if needed.
- return !update_packet_content_returns_connected_ || connected_;
+ return connected_;
}
if (type == PING_FRAME) {
if (current_packet_content_ == NO_FRAMES_RECEIVED) {
current_packet_content_ = FIRST_FRAME_IS_PING;
- return !update_packet_content_returns_connected_ || connected_;
+ return connected_;
}
}
@@ -5175,7 +5379,7 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) {
<< last_packet_destination_address_
<< ", default path self_address :" << default_path_.self_address;
}
- return !update_packet_content_returns_connected_ || connected_;
+ return connected_;
}
current_packet_content_ = NOT_PADDED_PING;
@@ -5189,7 +5393,7 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) {
}
}
current_effective_peer_migration_type_ = NO_CHANGE;
- return !update_packet_content_returns_connected_ || connected_;
+ return connected_;
}
void QuicConnection::MaybeStartIetfPeerMigration() {
@@ -5305,8 +5509,8 @@ MessageStatus QuicConnection::SendMessage(QuicMessageId message_id,
QuicMemSliceSpan message,
bool flush) {
if (!VersionSupportsMessageFrames(transport_version())) {
- QUIC_BUG << "MESSAGE frame is not supported for version "
- << transport_version();
+ QUIC_BUG(quic_bug_10511_38)
+ << "MESSAGE frame is not supported for version " << transport_version();
return MESSAGE_STATUS_UNSUPPORTED;
}
if (message.total_length() > GetCurrentLargestMessagePayload()) {
@@ -5340,7 +5544,8 @@ EncryptionLevel QuicConnection::GetConnectionCloseEncryptionLevel() const {
}
if (IsHandshakeComplete()) {
// A forward secure packet has been received.
- QUIC_BUG_IF(encryption_level_ != ENCRYPTION_FORWARD_SECURE)
+ QUIC_BUG_IF(quic_bug_12714_31,
+ encryption_level_ != ENCRYPTION_FORWARD_SECURE)
<< ENDPOINT << "Unexpected connection close encryption level "
<< encryption_level_;
return ENCRYPTION_FORWARD_SECURE;
@@ -5385,9 +5590,10 @@ void QuicConnection::MaybeBundleCryptoDataWithAcks() {
}
if (!framer_.HasAnEncrypterForSpace(space)) {
- QUIC_BUG << ENDPOINT
- << "Try to bundle crypto with ACK with missing key of space "
- << PacketNumberSpaceToString(space);
+ QUIC_BUG(quic_bug_10511_39)
+ << ENDPOINT
+ << "Try to bundle crypto with ACK with missing key of space "
+ << PacketNumberSpaceToString(space);
return;
}
@@ -5400,7 +5606,7 @@ void QuicConnection::SendAllPendingAcks() {
ack_alarm_->Cancel();
QuicTime earliest_ack_timeout =
uber_received_packet_manager_.GetEarliestAckTimeout();
- QUIC_BUG_IF(!earliest_ack_timeout.IsInitialized());
+ QUIC_BUG_IF(quic_bug_12714_32, !earliest_ack_timeout.IsInitialized());
MaybeBundleCryptoDataWithAcks();
earliest_ack_timeout = uber_received_packet_manager_.GetEarliestAckTimeout();
if (!earliest_ack_timeout.IsInitialized()) {
@@ -5441,7 +5647,8 @@ void QuicConnection::SendAllPendingAcks() {
const bool flushed = packet_creator_.FlushAckFrame(frames);
if (!flushed) {
// Connection is write blocked.
- QUIC_BUG_IF(!writer_->IsWriteBlocked() && !LimitedByAmplificationFactor())
+ QUIC_BUG_IF(quic_bug_12714_33,
+ !writer_->IsWriteBlocked() && !LimitedByAmplificationFactor())
<< "Writer not blocked and not throttled by amplification factor, "
"but ACK not flushed for packet space:"
<< i;
@@ -5529,16 +5736,17 @@ bool QuicConnection::FlushCoalescedPacket() {
return false;
}
if (!version().CanSendCoalescedPackets()) {
- QUIC_BUG_IF(coalesced_packet_.length() > 0);
+ QUIC_BUG_IF(quic_bug_12714_34, coalesced_packet_.length() > 0);
return true;
}
if (coalesced_packet_.ContainsPacketOfEncryptionLevel(ENCRYPTION_INITIAL) &&
!framer_.HasEncrypterOfEncryptionLevel(ENCRYPTION_INITIAL)) {
// Initial packet will be re-serialized. Neuter it in case initial key has
// been dropped.
- QUIC_BUG << ENDPOINT
- << "Coalescer contains initial packet while initial key has "
- "been dropped.";
+ QUIC_BUG(quic_bug_10511_40)
+ << ENDPOINT
+ << "Coalescer contains initial packet while initial key has "
+ "been dropped.";
coalesced_packet_.NeuterInitialPacket();
}
if (coalesced_packet_.length() == 0) {
@@ -5656,9 +5864,10 @@ void QuicConnection::OnForwardProgressMade() {
// Stop detections in quiecense.
blackhole_detector_.StopDetection();
}
- QUIC_BUG_IF(default_enable_5rto_blackhole_detection_ &&
- blackhole_detector_.IsDetectionInProgress() &&
- !sent_packet_manager_.HasInFlightPackets())
+ QUIC_BUG_IF(quic_bug_12714_35,
+ default_enable_5rto_blackhole_detection_ &&
+ blackhole_detector_.IsDetectionInProgress() &&
+ !sent_packet_manager_.HasInFlightPackets())
<< ENDPOINT
<< "Trying to start blackhole detection without no bytes in flight";
}
@@ -5756,13 +5965,26 @@ const QuicAckFrame& QuicConnection::ack_frame() const {
void QuicConnection::set_client_connection_id(
QuicConnectionId client_connection_id) {
if (!version().SupportsClientConnectionIds()) {
- QUIC_BUG_IF(!client_connection_id.IsEmpty())
+ QUIC_BUG_IF(quic_bug_12714_36, !client_connection_id.IsEmpty())
<< ENDPOINT << "Attempted to use client connection ID "
<< client_connection_id << " with unsupported version " << version();
return;
}
client_connection_id_ = client_connection_id;
client_connection_id_is_set_ = true;
+ 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_,
+ alarm_factory_, this);
+ } else {
+ // Note in Chromium client, set_client_connection_id is not called and
+ // thus self_issued_cid_manager_ should be null.
+ self_issued_cid_manager_ = MakeSelfIssuedConnectionIdManager();
+ }
+ }
QUIC_DLOG(INFO) << ENDPOINT << "setting client connection ID to "
<< client_connection_id_
<< " for connection with server connection ID "
@@ -5779,9 +6001,10 @@ void QuicConnection::OnPathDegradingDetected() {
void QuicConnection::OnBlackholeDetected() {
if (default_enable_5rto_blackhole_detection_ &&
!sent_packet_manager_.HasInFlightPackets()) {
- QUIC_BUG << ENDPOINT
- << "Blackhole detected, but there is no bytes in flight, version: "
- << version();
+ QUIC_BUG(quic_bug_10511_41)
+ << ENDPOINT
+ << "Blackhole detected, but there is no bytes in flight, version: "
+ << version();
// Do not close connection if there is no bytes in flight.
return;
}
@@ -5843,6 +6066,62 @@ void QuicConnection::OnIdleNetworkDetected() {
idle_timeout_connection_close_behavior_);
}
+void QuicConnection::OnPeerIssuedConnectionIdRetired() {
+ QUICHE_DCHECK(peer_issued_cid_manager_ != nullptr);
+ QuicConnectionId* default_path_cid = perspective_ == Perspective::IS_CLIENT
+ ? &server_connection_id_
+ : &client_connection_id_;
+ if (!default_path_cid->IsEmpty() &&
+ !peer_issued_cid_manager_->IsConnectionIdActive(*default_path_cid)) {
+ *default_path_cid = QuicConnectionId();
+ }
+ if (default_path_cid->IsEmpty()) {
+ // Try setting a new connection ID now such that subsequent
+ // RetireConnectionId frames can be sent on the default path.
+ const QuicConnectionIdData* unused_connection_id_data =
+ 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 (perspective_ == Perspective::IS_CLIENT) {
+ packet_creator_.SetServerConnectionId(
+ unused_connection_id_data->connection_id);
+ } else {
+ packet_creator_.SetClientConnectionId(
+ unused_connection_id_data->connection_id);
+ }
+ }
+ }
+
+ 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) {
+ visitor_->SendRetireConnectionId(sequence_number);
+ }
+}
+
+bool QuicConnection::SendNewConnectionId(
+ const QuicNewConnectionIdFrame& frame) {
+ QUICHE_DCHECK(perspective_ == Perspective::IS_SERVER);
+ visitor_->SendNewConnectionId(frame);
+ return connected_;
+}
+
+void QuicConnection::OnNewConnectionIdIssued(
+ const QuicConnectionId& connection_id) {
+ QUICHE_DCHECK(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);
+}
+
void QuicConnection::MaybeUpdateAckTimeout() {
if (should_last_packet_instigate_acks_) {
return;
@@ -5921,6 +6200,7 @@ bool QuicConnection::SendPathChallenge(
const QuicSocketAddress& /*effective_peer_address*/,
QuicPacketWriter* writer) {
if (writer == writer_) {
+ ScopedPacketFlusher flusher(this);
{
// It's on current path, add the PATH_CHALLENGE the same way as other
// frames.
@@ -6042,11 +6322,17 @@ void QuicConnection::MigratePath(const QuicSocketAddress& self_address,
if (!connected_) {
return;
}
- const bool is_port_change =
- QuicUtils::DetermineAddressChangeType(default_path_.self_address,
- self_address) == PORT_CHANGE &&
- QuicUtils::DetermineAddressChangeType(default_path_.peer_address,
- peer_address) == PORT_CHANGE;
+
+ const auto self_address_change_type = QuicUtils::DetermineAddressChangeType(
+ default_path_.self_address, self_address);
+ const auto peer_address_change_type = QuicUtils::DetermineAddressChangeType(
+ default_path_.peer_address, peer_address);
+ QUICHE_DCHECK(self_address_change_type != NO_CHANGE ||
+ peer_address_change_type != NO_CHANGE);
+ const bool is_port_change = (self_address_change_type == PORT_CHANGE ||
+ self_address_change_type == NO_CHANGE) &&
+ (peer_address_change_type == PORT_CHANGE ||
+ peer_address_change_type == NO_CHANGE);
SetSelfAddress(self_address);
UpdatePeerAddress(peer_address);
SetQuicPacketWriter(writer, owns_writer);
@@ -6055,7 +6341,30 @@ void QuicConnection::MigratePath(const QuicSocketAddress& self_address,
std::vector<QuicConnectionId> QuicConnection::GetActiveServerConnectionIds()
const {
- return {server_connection_id_};
+ if (!support_multiple_connection_ids_ ||
+ self_issued_cid_manager_ == nullptr) {
+ return {server_connection_id_};
+ }
+ return self_issued_cid_manager_->GetUnretiredConnectionIds();
+}
+
+void QuicConnection::CreateConnectionIdManager() {
+ if (!support_multiple_connection_ids_) {
+ return;
+ }
+
+ if (perspective_ == Perspective::IS_CLIENT) {
+ if (!server_connection_id_.IsEmpty()) {
+ peer_issued_cid_manager_ =
+ std::make_unique<QuicPeerIssuedConnectionIdManager>(
+ kMinNumOfActiveConnectionIds, server_connection_id_, clock_,
+ alarm_factory_, this);
+ }
+ } else {
+ if (!server_connection_id_.IsEmpty()) {
+ self_issued_cid_manager_ = MakeSelfIssuedConnectionIdManager();
+ }
+ }
}
void QuicConnection::SetUnackedMapInitialCapacity() {
@@ -6241,17 +6550,15 @@ void QuicConnection::RestoreToLastValidatedPath(
}
// Revert congestion control context to old state.
- sent_packet_manager_.OnConnectionMigration(true);
- QUICHE_DCHECK(!sent_packet_manager_.HasInFlightPackets());
- // Stop detections in quiecense.
- blackhole_detector_.StopDetection();
+ OnPeerIpAddressChanged();
if (alternative_path_.send_algorithm != nullptr) {
sent_packet_manager_.SetSendAlgorithm(
alternative_path_.send_algorithm.release());
sent_packet_manager_.SetRttStats(alternative_path_.rtt_stats.value());
} else {
- QUIC_BUG << "Fail to store congestion controller before migration.";
+ QUIC_BUG(quic_bug_10511_42)
+ << "Fail to store congestion controller before migration.";
}
UpdatePeerAddress(original_direct_peer_address);
@@ -6264,5 +6571,22 @@ void QuicConnection::RestoreToLastValidatedPath(
WriteIfNotBlocked();
}
+std::unique_ptr<SendAlgorithmInterface>
+QuicConnection::OnPeerIpAddressChanged() {
+ QUICHE_DCHECK(validate_client_addresses_);
+ std::unique_ptr<SendAlgorithmInterface> old_send_algorithm =
+ sent_packet_manager_.OnConnectionMigration(
+ /*reset_send_algorithm=*/true);
+ // OnConnectionMigration() should have marked in-flight packets to be
+ // retransmitted if there is any.
+ QUICHE_DCHECK(!sent_packet_manager_.HasInFlightPackets());
+ // OnConnectionMigration() may have changed the retransmission timer, so
+ // re-arm it.
+ SetRetransmissionAlarm();
+ // Stop detections in quiecense.
+ blackhole_detector_.StopDetection();
+ return old_send_algorithm;
+}
+
#undef ENDPOINT // undef for jumbo builds
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection.h b/chromium/net/third_party/quiche/src/quic/core/quic_connection.h
index 33cf33b32c0..e2ba17bd9d8 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection.h
@@ -31,12 +31,14 @@
#include "quic/core/crypto/transport_parameters.h"
#include "quic/core/frames/quic_ack_frequency_frame.h"
#include "quic/core/frames/quic_max_streams_frame.h"
+#include "quic/core/frames/quic_new_connection_id_frame.h"
#include "quic/core/proto/cached_network_parameters_proto.h"
#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"
#include "quic/core/quic_constants.h"
#include "quic/core/quic_framer.h"
@@ -164,6 +166,20 @@ class QUIC_EXPORT_PRIVATE QuicConnectionVisitorInterface {
// Called when an AckFrequency frame need to be sent.
virtual void SendAckFrequency(const QuicAckFrequencyFrame& frame) = 0;
+ // Called to send a NEW_CONNECTION_ID frame.
+ virtual void SendNewConnectionId(const QuicNewConnectionIdFrame& frame) = 0;
+
+ // Called to send a RETIRE_CONNECTION_ID frame.
+ virtual void SendRetireConnectionId(uint64_t sequence_number) = 0;
+
+ // Called when server starts to use a server issued connection ID.
+ virtual void OnServerConnectionIdIssued(
+ const QuicConnectionId& server_connection_id) = 0;
+
+ // Called when server stops to use a server issued connection ID.
+ virtual void OnServerConnectionIdRetired(
+ const QuicConnectionId& server_connection_id) = 0;
+
// Called to ask if the visitor wants to schedule write resumption as it both
// has pending data to write, and is able to write (e.g. based on flow control
// limits).
@@ -223,6 +239,9 @@ class QUIC_EXPORT_PRIVATE QuicConnectionVisitorInterface {
// Called by the server to send another token.
// Return false if the crypto stream fail to generate one.
virtual void MaybeSendAddressToken() = 0;
+
+ // Whether the server address is known to the connection.
+ virtual bool IsKnownServerAddress(const QuicSocketAddress& address) const = 0;
};
// Interface which gets callbacks from the QuicConnection at interesting
@@ -414,6 +433,9 @@ class QUIC_EXPORT_PRIVATE QuicConnectionDebugVisitor
// Called on peer address change.
virtual void OnPeerAddressChange(AddressChangeType /*type*/,
QuicTime::Delta /*connection_time*/) {}
+
+ // Called after peer migration is validated.
+ virtual void OnPeerMigrationValidated(QuicTime::Delta /*connection_time*/) {}
};
class QUIC_EXPORT_PRIVATE QuicConnectionHelperInterface {
@@ -437,7 +459,8 @@ class QUIC_EXPORT_PRIVATE QuicConnection
public QuicSentPacketManager::NetworkChangeVisitor,
public QuicNetworkBlackholeDetector::Delegate,
public QuicIdleNetworkDetector::Delegate,
- public QuicPathValidator::SendDelegate {
+ public QuicPathValidator::SendDelegate,
+ public QuicConnectionIdManagerVisitorInterface {
public:
// Constructs a new QuicConnection for |connection_id| and
// |initial_peer_address| using |writer| to write packets. |owns_writer|
@@ -564,6 +587,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
}
// Called when the caller thinks it's worth a try to write.
+ // TODO(fayang): consider unifying this with QuicSession::OnCanWrite.
virtual void OnCanWrite();
// Called when an error occurs while attempting to write a packet to the
@@ -576,10 +600,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// If the socket is not blocked, writes queued packets.
void WriteIfNotBlocked();
- // If the socket is not blocked, writes queued packets and bundles any pending
- // ACKs.
- void WriteAndBundleAcksIfNotBlocked();
-
// Set the packet writer.
void SetQuicPacketWriter(QuicPacketWriter* writer, bool owns_writer) {
QUICHE_DCHECK(writer != nullptr);
@@ -665,7 +685,8 @@ class QUIC_EXPORT_PRIVATE QuicConnection
bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) override;
bool OnAckFrequencyFrame(const QuicAckFrequencyFrame& frame) override;
void OnPacketComplete() override;
- bool IsValidStatelessResetToken(QuicUint128 token) const override;
+ bool IsValidStatelessResetToken(
+ const StatelessResetToken& token) const override;
void OnAuthenticatedIetfStatelessResetPacket(
const QuicIetfStatelessResetPacket& packet) override;
void OnKeyUpdate(KeyUpdateReason reason) override;
@@ -699,10 +720,21 @@ class QUIC_EXPORT_PRIVATE QuicConnection
void OnHandshakeTimeout() override;
void OnIdleNetworkDetected() override;
+ // QuicConnectionIdManagerVisitorInterface
+ void OnPeerIssuedConnectionIdRetired() override;
+ bool SendNewConnectionId(const QuicNewConnectionIdFrame& frame) override;
+ void OnNewConnectionIdIssued(const QuicConnectionId& connection_id) override;
+ void OnSelfIssuedConnectionIdRetired(
+ const QuicConnectionId& connection_id) override;
+
// Please note, this is not a const function. For logging purpose, please use
// ack_frame().
const QuicFrame GetUpdatedAckFrame();
+ // Called to send a new connection ID to client if the # of connection ID has
+ // not exceeded the active connection ID limits.
+ void MaybeSendConnectionIdToClient();
+
// Called when the handshake completes. On the client side, handshake
// completes on receipt of SHLO. On the server side, handshake completes when
// SHLO gets ACKed (or a forward secure packet gets decrypted successfully).
@@ -1045,8 +1077,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Queue a coalesced packet.
void QueueCoalescedPacket(const QuicEncryptedPacket& packet);
- // Process previously queued coalesced packets.
- void MaybeProcessCoalescedPackets();
+ // Process previously queued coalesced packets. Returns true if any coalesced
+ // packets have been successfully processed.
+ bool MaybeProcessCoalescedPackets();
enum PacketContent : uint8_t {
NO_FRAMES_RECEIVED,
@@ -1195,6 +1228,13 @@ class QUIC_EXPORT_PRIVATE QuicConnection
bool validate_client_address() const { return validate_client_addresses_; }
+ // Instantiates connection ID manager.
+ void CreateConnectionIdManager();
+
+ bool donot_write_mid_packet_processing() const {
+ return donot_write_mid_packet_processing_;
+ }
+
protected:
// Calls cancel() on all the alarms owned by this connection.
void CancelAllAlarms();
@@ -1393,6 +1433,11 @@ class QUIC_EXPORT_PRIVATE QuicConnection
void TearDownLocalConnectionState(const QuicConnectionCloseFrame& frame,
ConnectionCloseSource source);
+ // Replace server connection ID on the client side from retry packet or
+ // initial packets with a different source connection ID.
+ void ReplaceInitialServerConnectionId(
+ const QuicConnectionId& new_server_connection_id);
+
// 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
@@ -1433,9 +1478,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// blocked when this is called.
void WriteQueuedPackets();
- // Writes new data if congestion control allows.
- void WriteNewData();
-
// Queues |packet| in the hopes that it can be decrypted in the
// future, when a new key is installed.
void QueueUndecryptablePacket(const QuicEncryptedPacket& packet,
@@ -1680,6 +1722,18 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Return true if framer should continue processing the packet.
bool OnPathChallengeFrameInternal(const QuicPathChallengeFrame& frame);
+ virtual std::unique_ptr<QuicSelfIssuedConnectionIdManager>
+ MakeSelfIssuedConnectionIdManager();
+
+ // Called on peer IP change or restoring to previous address to reset
+ // congestion window, RTT stats, retransmission timer, etc. Only used in IETF
+ // QUIC.
+ std::unique_ptr<SendAlgorithmInterface> OnPeerIpAddressChanged();
+
+ // Process NewConnectionIdFrame either sent from peer or synsthesized from
+ // preferred_address transport parameter.
+ bool OnNewConnectionIdFrameInner(const QuicNewConnectionIdFrame& frame);
+
QuicFramer framer_;
// Contents received in the current packet, especially used to identify
@@ -1712,6 +1766,10 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// On the server, the connection ID is set when receiving the first packet.
// This variable ensures we only set it this way once.
bool client_connection_id_is_set_;
+
+ // Whether we've already replaced our server connection ID due to receiving an
+ // INITIAL packet with a different source connection ID. Only used on client.
+ bool server_connection_id_replaced_by_initial_ = false;
// Address on the last successfully processed packet received from the
// direct peer.
@@ -1946,7 +2004,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
bool stateless_reset_token_received_;
// Stores received stateless reset token from peer. Used to verify whether a
// packet is a stateless reset packet.
- QuicUint128 received_stateless_reset_token_;
+ StatelessResetToken received_stateless_reset_token_;
// Id of latest sent control frame. 0 if no control frame has been sent.
QuicControlFrameId last_control_frame_id_;
@@ -1960,6 +2018,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// True if the writer supports release timestamp.
bool supports_release_time_;
+ std::unique_ptr<QuicPeerIssuedConnectionIdManager> peer_issued_cid_manager_;
+ std::unique_ptr<QuicSelfIssuedConnectionIdManager> self_issued_cid_manager_;
+
// Time this connection can release packets into the future.
QuicTime::Delta release_time_into_future_;
@@ -2039,7 +2100,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// 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_response);
+ GetQuicReloadableFlag(quic_send_path_response2);
bool use_path_validator_ =
send_path_response_ &&
@@ -2095,11 +2156,13 @@ class QUIC_EXPORT_PRIVATE QuicConnection
bool count_bytes_on_alternative_path_separately_ =
GetQuicReloadableFlag(quic_count_bytes_on_alternative_path_seperately);
- bool update_packet_content_returns_connected_ =
- GetQuicReloadableFlag(quic_update_packet_content_returns_connected);
-
// If true, upon seeing a new client address, validate the client address.
- const bool validate_client_addresses_;
+ bool validate_client_addresses_ = false;
+
+ bool support_multiple_connection_ids_ = false;
+
+ const bool donot_write_mid_packet_processing_ =
+ GetQuicReloadableFlag(quic_donot_write_mid_packet_processing);
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_id.h b/chromium/net/third_party/quiche/src/quic/core/quic_connection_id.h
index 771203314ad..a0669d7d642 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection_id.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection_id.h
@@ -9,7 +9,6 @@
#include <vector>
#include "quic/platform/api/quic_export.h"
-#include "quic/platform/api/quic_uint128.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 adf8ebae71f..a8e8c542f5f 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
@@ -9,14 +9,13 @@
#include "quic/core/quic_connection_id.h"
#include "quic/core/quic_error_codes.h"
#include "quic/core/quic_utils.h"
-#include "quic/platform/api/quic_uint128.h"
namespace quic {
QuicConnectionIdData::QuicConnectionIdData(
const QuicConnectionId& connection_id,
uint64_t sequence_number,
- QuicUint128 stateless_reset_token)
+ const StatelessResetToken& stateless_reset_token)
: connection_id(connection_id),
sequence_number(sequence_number),
stateless_reset_token(stateless_reset_token) {}
@@ -71,9 +70,10 @@ QuicPeerIssuedConnectionIdManager::QuicPeerIssuedConnectionIdManager(
new RetirePeerIssuedConnectionIdAlarm(visitor))) {
QUICHE_DCHECK_GE(active_connection_id_limit_, 2u);
QUICHE_DCHECK(!initial_peer_issued_connection_id.IsEmpty());
- active_connection_id_data_.emplace_back(initial_peer_issued_connection_id,
- /*sequence_number=*/0u,
- QuicUint128());
+ active_connection_id_data_.emplace_back<const QuicConnectionId&, uint64_t,
+ const StatelessResetToken&>(
+ initial_peer_issued_connection_id,
+ /*sequence_number=*/0u, {});
recent_new_connection_id_sequence_numbers_.Add(0u, 1u);
}
@@ -357,7 +357,7 @@ QuicSelfIssuedConnectionIdManager::GetUnretiredConnectionIds() const {
void QuicSelfIssuedConnectionIdManager::RetireConnectionId() {
if (to_be_retired_connection_ids_.empty()) {
- QUIC_BUG
+ QUIC_BUG(quic_bug_12420_1)
<< "retire_connection_id_alarm fired but there is no connection ID "
"to be retired.";
return;
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 3f29cd4932c..b933a69f158 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
@@ -12,6 +12,7 @@
#include <cstddef>
#include <memory>
+
#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"
@@ -19,19 +20,23 @@
#include "quic/core/quic_clock.h"
#include "quic/core/quic_connection_id.h"
#include "quic/core/quic_interval_set.h"
+#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_export.h"
-#include "quic/platform/api/quic_uint128.h"
namespace quic {
+namespace test {
+class QuicConnectionIdManagerPeer;
+} // namespace test
+
struct QUIC_EXPORT_PRIVATE QuicConnectionIdData {
QuicConnectionIdData(const QuicConnectionId& connection_id,
uint64_t sequence_number,
- QuicUint128 stateless_reset_token);
+ const StatelessResetToken& stateless_reset_token);
QuicConnectionId connection_id;
uint64_t sequence_number;
- QuicUint128 stateless_reset_token;
+ StatelessResetToken stateless_reset_token;
};
// Used by QuicSelfIssuedConnectionIdManager
@@ -83,7 +88,7 @@ class QUIC_EXPORT_PRIVATE QuicPeerIssuedConnectionIdManager {
const QuicConnectionId& new_connection_id);
private:
- friend class QuicConnectionIdManagerPeer;
+ friend class test::QuicConnectionIdManagerPeer;
bool IsConnectionIdNew(const QuicNewConnectionIdFrame& frame);
@@ -134,7 +139,7 @@ class QUIC_EXPORT_PRIVATE QuicSelfIssuedConnectionIdManager {
const QuicConnectionId& old_connection_id) const;
private:
- friend class QuicConnectionIdManagerPeer;
+ friend class test::QuicConnectionIdManagerPeer;
QuicNewConnectionIdFrame IssueNewConnectionId();
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 b9ca45f5472..9c7daf0db5e 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
@@ -9,27 +9,15 @@
#include "quic/core/quic_error_codes.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/mock_clock.h"
+#include "quic/test_tools/quic_connection_id_manager_peer.h"
#include "quic/test_tools/quic_test_utils.h"
namespace quic {
-
-class QuicConnectionIdManagerPeer {
- public:
- static QuicAlarm* GetRetirePeerIssuedConnectionIdAlarm(
- QuicPeerIssuedConnectionIdManager* manager) {
- return manager->retire_connection_id_alarm_.get();
- }
-
- static QuicAlarm* GetRetireSelfIssuedConnectionIdAlarm(
- QuicSelfIssuedConnectionIdManager* manager) {
- return manager->retire_connection_id_alarm_.get();
- }
-};
-
namespace {
using ::quic::test::IsError;
using ::quic::test::IsQuicNoError;
+using ::quic::test::QuicConnectionIdManagerPeer;
using ::quic::test::TestConnectionId;
using ::testing::_;
using ::testing::ElementsAre;
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 0cf348953b8..06b7f5868bd 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
@@ -209,6 +209,21 @@ 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;
+
+ struct QUIC_NO_EXPORT TlsServerOperationStats {
+ bool success = false;
+ // If the operation is performed asynchronously, how long did it take.
+ // Zero() for synchronous operations.
+ QuicTime::Delta async_latency = QuicTime::Delta::Zero();
+ };
+
+ // The TLS server op stats only have values when the corresponding operation
+ // is performed by TlsServerHandshaker. If an operation is done within
+ // BoringSSL, e.g. ticket decrypted without using
+ // TlsServerHandshaker::SessionTicketOpen, it will not be recorded here.
+ absl::optional<TlsServerOperationStats> tls_server_select_cert_stats;
+ absl::optional<TlsServerOperationStats> tls_server_compute_signature_stats;
+ absl::optional<TlsServerOperationStats> tls_server_decrypt_ticket_stats;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc
index 60eccb818cd..e2fba5b8325 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
@@ -53,6 +53,7 @@ using testing::_;
using testing::AnyNumber;
using testing::AtLeast;
using testing::DoAll;
+using testing::ElementsAre;
using testing::Ge;
using testing::IgnoreResult;
using testing::InSequence;
@@ -82,6 +83,10 @@ DiversificationNonce kTestDiversificationNonce = {
'a', 'b', 'a', 'b', 'a', 'b', 'a', 'b', 'a', 'b',
};
+const StatelessResetToken kTestStatelessResetToken{
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f};
+
const QuicSocketAddress kPeerAddress =
QuicSocketAddress(QuicIpAddress::Loopback6(),
/*port=*/12345);
@@ -382,6 +387,7 @@ class TestConnection : public QuicConnection {
// connection and peer creator.
void set_perspective(Perspective perspective) {
writer()->set_perspective(perspective);
+ QuicConnectionPeer::ResetPeerIssuedConnectionIdManager(this);
QuicConnectionPeer::SetPerspective(this, perspective);
QuicSentPacketManagerPeer::SetPerspective(
QuicConnectionPeer::GetSentPacketManager(this), perspective);
@@ -473,6 +479,16 @@ class TestConnection : public QuicConnection {
QuicConnectionPeer::GetBlackholeDetectorAlarm(this));
}
+ TestAlarmFactory::TestAlarm* GetRetirePeerIssuedConnectionIdAlarm() {
+ return reinterpret_cast<TestAlarmFactory::TestAlarm*>(
+ QuicConnectionPeer::GetRetirePeerIssuedConnectionIdAlarm(this));
+ }
+
+ TestAlarmFactory::TestAlarm* GetRetireSelfIssuedConnectionIdAlarm() {
+ return reinterpret_cast<TestAlarmFactory::TestAlarm*>(
+ QuicConnectionPeer::GetRetireSelfIssuedConnectionIdAlarm(this));
+ }
+
void PathDegradingTimeout() {
QUICHE_DCHECK(PathDegradingDetectionInProgress());
GetBlackholeDetectorAlarm()->Fire();
@@ -1174,9 +1190,16 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
EncryptionLevel level) {
QuicPacketHeader header = ConstructPacketHeader(number, level);
QuicFrames frames;
- frames.push_back(QuicFrame(frame1_));
- if (has_stop_waiting) {
- frames.push_back(QuicFrame(stop_waiting_));
+ if (GetQuicReloadableFlag(quic_reject_unexpected_ietf_frame_types) &&
+ VersionHasIetfQuicFrames(version().transport_version) &&
+ (level == ENCRYPTION_INITIAL || level == ENCRYPTION_HANDSHAKE)) {
+ frames.push_back(QuicFrame(QuicPingFrame()));
+ frames.push_back(QuicFrame(QuicPaddingFrame(100)));
+ } else {
+ frames.push_back(QuicFrame(frame1_));
+ if (has_stop_waiting) {
+ frames.push_back(QuicFrame(stop_waiting_));
+ }
}
return ConstructPacket(header, frames);
}
@@ -1303,6 +1326,13 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
void set_perspective(Perspective perspective) {
connection_.set_perspective(perspective);
if (perspective == Perspective::IS_SERVER) {
+ QuicConfig config;
+ QuicTagVector connection_options;
+ connection_options.push_back(kRVCM);
+ config.SetInitialReceivedConnectionOptions(connection_options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ connection_.SetFromConfig(config);
+
connection_.set_can_truncate_connection_ids(true);
QuicConnectionPeer::SetNegotiatedVersion(&connection_);
connection_.OnSuccessfulVersionNegotiation();
@@ -1431,6 +1461,8 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
bool missing_retry_id_in_config,
bool wrong_retry_id_in_config);
+ void TestReplaceConnectionIdFromInitial();
+
QuicConnectionId connection_id_;
QuicFramer framer_;
@@ -1694,10 +1726,10 @@ TEST_P(QuicConnectionTest, PeerPortChangeAtServer) {
}
TEST_P(QuicConnectionTest, PeerIpAddressChangeAtServer) {
+ set_perspective(Perspective::IS_SERVER);
if (!connection_.validate_client_address()) {
return;
}
- set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
@@ -1705,6 +1737,7 @@ TEST_P(QuicConnectionTest, PeerIpAddressChangeAtServer) {
EXPECT_CALL(visitor_, GetHandshakeState())
.WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
QuicConnectionPeer::SetAddressValidated(&connection_);
+ connection_.OnHandshakeComplete();
// Enable 5 RTO
QuicConfig config;
@@ -1750,6 +1783,7 @@ TEST_P(QuicConnectionTest, PeerIpAddressChangeAtServer) {
connection_.SendStreamData3();
EXPECT_EQ(1u, writer_->packets_write_attempts());
EXPECT_TRUE(connection_.BlackholeDetectionInProgress());
+ EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
// Process another packet with a different peer address on server side will
// start connection migration.
@@ -1771,6 +1805,7 @@ TEST_P(QuicConnectionTest, PeerIpAddressChangeAtServer) {
EXPECT_EQ(IPV6_TO_IPV4_CHANGE,
connection_.active_effective_peer_migration_type());
EXPECT_FALSE(connection_.BlackholeDetectionInProgress());
+ EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
EXPECT_EQ(2u, writer_->packets_write_attempts());
EXPECT_FALSE(writer_->path_challenge_frames().empty());
@@ -1838,6 +1873,7 @@ TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
if (version().SupportsAntiAmplificationLimit()) {
QuicConnectionPeer::SetAddressValidated(&connection_);
}
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
EXPECT_CALL(visitor_, GetHandshakeState())
.WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
@@ -1857,7 +1893,7 @@ TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
}
ProcessFramePacketWithAddresses(MakeCryptoFrame(), kSelfAddress, kPeerAddress,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_FORWARD_SECURE);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kEffectivePeerAddress, connection_.effective_peer_address());
@@ -1868,7 +1904,7 @@ TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
connection_.ReturnEffectivePeerAddressForNextPacket(kNewEffectivePeerAddress);
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(1);
ProcessFramePacketWithAddresses(MakeCryptoFrame(), kSelfAddress, kPeerAddress,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_FORWARD_SECURE);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kNewEffectivePeerAddress, connection_.effective_peer_address());
EXPECT_EQ(kPeerAddress, writer_->last_write_peer_address());
@@ -1891,7 +1927,7 @@ TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
QuicAckFrame ack_frame = InitAckFrame(1);
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _));
ProcessFramePacketWithAddresses(QuicFrame(&ack_frame), kSelfAddress,
- kNewPeerAddress, ENCRYPTION_INITIAL);
+ kNewPeerAddress, ENCRYPTION_FORWARD_SECURE);
EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
EXPECT_EQ(kNewEffectivePeerAddress, connection_.effective_peer_address());
EXPECT_EQ(NO_CHANGE, connection_.active_effective_peer_migration_type());
@@ -1907,7 +1943,7 @@ TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
kNewerEffectivePeerAddress);
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(1);
ProcessFramePacketWithAddresses(MakeCryptoFrame(), kSelfAddress,
- kFinalPeerAddress, ENCRYPTION_INITIAL);
+ kFinalPeerAddress, ENCRYPTION_FORWARD_SECURE);
EXPECT_EQ(kFinalPeerAddress, connection_.peer_address());
EXPECT_EQ(kNewerEffectivePeerAddress, connection_.effective_peer_address());
if (connection_.validate_client_address()) {
@@ -1929,7 +1965,7 @@ TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
EXPECT_CALL(*send_algorithm_, OnConnectionMigration()).Times(1);
}
ProcessFramePacketWithAddresses(MakeCryptoFrame(), kSelfAddress,
- kFinalPeerAddress, ENCRYPTION_INITIAL);
+ kFinalPeerAddress, ENCRYPTION_FORWARD_SECURE);
EXPECT_EQ(kFinalPeerAddress, connection_.peer_address());
EXPECT_EQ(kNewestEffectivePeerAddress, connection_.effective_peer_address());
EXPECT_EQ(IPV6_TO_IPV4_CHANGE,
@@ -1946,10 +1982,10 @@ TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
}
TEST_P(QuicConnectionTest, ReversePathValidationFailureAtServer) {
+ set_perspective(Perspective::IS_SERVER);
if (!connection_.validate_client_address()) {
return;
}
- set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
@@ -1957,6 +1993,7 @@ TEST_P(QuicConnectionTest, ReversePathValidationFailureAtServer) {
EXPECT_CALL(visitor_, GetHandshakeState())
.WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
QuicConnectionPeer::SetAddressValidated(&connection_);
+ connection_.OnHandshakeComplete();
// Clear direct_peer_address.
QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
@@ -1994,14 +2031,16 @@ TEST_P(QuicConnectionTest, ReversePathValidationFailureAtServer) {
QuicFrames frames2;
frames2.push_back(QuicFrame(frame2_));
+ QuicPaddingFrame padding;
+ frames2.push_back(QuicFrame(padding));
ProcessFramesPacketWithAddresses(frames2, kSelfAddress, kNewPeerAddress,
ENCRYPTION_FORWARD_SECURE);
EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
EXPECT_EQ(IPV6_TO_IPV4_CHANGE,
connection_.active_effective_peer_migration_type());
- EXPECT_EQ(1u, writer_->packets_write_attempts());
- EXPECT_FALSE(writer_->path_challenge_frames().empty());
+ EXPECT_LT(0u, writer_->packets_write_attempts());
+ EXPECT_TRUE(connection_.HasPendingPathValidation());
EXPECT_NE(connection_.sent_packet_manager().GetSendAlgorithm(),
send_algorithm_);
EXPECT_EQ(kNewPeerAddress, writer_->last_write_peer_address());
@@ -2018,6 +2057,9 @@ TEST_P(QuicConnectionTest, ReversePathValidationFailureAtServer) {
EXPECT_EQ(IPV6_TO_IPV4_CHANGE,
connection_.active_effective_peer_migration_type());
+ SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr);
+ EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
+
// Advance the time so that the reverse path validation times out.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(3 * kInitialRttMs));
static_cast<TestAlarmFactory::TestAlarm*>(
@@ -2029,6 +2071,7 @@ TEST_P(QuicConnectionTest, ReversePathValidationFailureAtServer) {
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
EXPECT_EQ(connection_.sent_packet_manager().GetSendAlgorithm(),
send_algorithm_);
+ EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
}
TEST_P(QuicConnectionTest, ReceivePathProbeWithNoAddressChangeAtServer) {
@@ -2259,8 +2302,9 @@ TEST_P(QuicConnectionTest, ReceivePathProbingAtServer) {
ENCRYPTION_FORWARD_SECURE);
EXPECT_LT(2 * received->length(),
QuicConnectionPeer::BytesReceivedOnAlternativePath(&connection_));
- EXPECT_TRUE(QuicConnectionPeer::IsAlternativePathValidated(&connection_));
-
+ if (connection_.validate_client_address()) {
+ EXPECT_TRUE(QuicConnectionPeer::IsAlternativePathValidated(&connection_));
+ }
// Receiving another probing packet from a newer address with a different
// port shouldn't trigger another reverse path validation.
QuicSocketAddress kNewerPeerAddress(QuicIpAddress::Loopback4(),
@@ -2541,8 +2585,14 @@ TEST_P(QuicConnectionTest, PeerAddressChangeAtClient) {
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
ProcessFramePacketWithAddresses(MakeCryptoFrame(), kSelfAddress,
kNewPeerAddress, ENCRYPTION_INITIAL);
- EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
- EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
+ if (connection_.version().HasIetfQuicFrames()) {
+ // IETF QUIC disallows server initiated address change.
+ EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+ } else {
+ EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
+ EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
+ }
}
TEST_P(QuicConnectionTest, MaxPacketSize) {
@@ -2785,7 +2835,9 @@ TEST_P(QuicConnectionTest, PacketsOutOfOrderWithAdditionsAndLeastAwaiting) {
TEST_P(QuicConnectionTest, RejectUnencryptedStreamData) {
// EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
- if (!IsDefaultTestConfiguration()) {
+ if (!IsDefaultTestConfiguration() ||
+ (GetQuicReloadableFlag(quic_reject_unexpected_ietf_frame_types) &&
+ VersionHasIetfQuicFrames(version().transport_version))) {
return;
}
@@ -2939,28 +2991,6 @@ TEST_P(QuicConnectionTest, AckFrequencyUpdatedFromAckFrequencyFrame) {
}
}
-TEST_P(QuicConnectionTest,
- AckFrequencyFrameOutsideApplicationDataNumberSpaceIsIgnored) {
- if (!GetParam().version.HasIetfQuicFrames()) {
- return;
- }
- connection_.set_can_receive_ack_frequency_frame();
-
- QuicAckFrequencyFrame ack_frequency_frame;
- ack_frequency_frame.packet_tolerance = 3;
- ProcessFramePacketAtLevel(1, QuicFrame(&ack_frequency_frame),
- ENCRYPTION_HANDSHAKE);
-
- // Expect 30 acks, every 2nd (instead of 3rd) packet including the first
- // packet with AckFrequencyFrame.
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(30);
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(60);
- // Receives packets 2 - 61.
- for (size_t i = 2; i <= 61; ++i) {
- ProcessDataPacket(i);
- }
-}
-
TEST_P(QuicConnectionTest, AckDecimationReducesAcks) {
const size_t kMinRttMs = 40;
RttStats* rtt_stats = const_cast<RttStats*>(manager_->GetRttStats());
@@ -6873,7 +6903,6 @@ TEST_P(QuicConnectionTest, IetfStatelessReset) {
if (!GetParam().version.HasIetfInvariantHeader()) {
return;
}
- const QuicUint128 kTestStatelessResetToken = 1010101;
QuicConfig config;
QuicConfigPeer::SetReceivedStatelessResetToken(&config,
kTestStatelessResetToken);
@@ -6881,6 +6910,7 @@ TEST_P(QuicConnectionTest, IetfStatelessReset) {
connection_.SetFromConfig(config);
std::unique_ptr<QuicEncryptedPacket> packet(
QuicFramer::BuildIetfStatelessResetPacket(connection_id_,
+ /*received_packet_length=*/100,
kTestStatelessResetToken));
std::unique_ptr<QuicReceivedPacket> received(
ConstructReceivedPacket(*packet, QuicTime::Zero()));
@@ -7757,7 +7787,13 @@ TEST_P(QuicConnectionTest, ServerReceivesChloOnNonCryptoStream) {
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
ForceProcessFramePacket(QuicFrame(frame1_));
- TestConnectionCloseQuicErrorCode(QUIC_MAYBE_CORRUPTED_MEMORY);
+ if (GetQuicReloadableFlag(quic_reject_unexpected_ietf_frame_types) &&
+ VersionHasIetfQuicFrames(version().transport_version)) {
+ // INITIAL packet should not contain STREAM frame.
+ TestConnectionCloseQuicErrorCode(IETF_QUIC_PROTOCOL_VIOLATION);
+ } else {
+ TestConnectionCloseQuicErrorCode(QUIC_MAYBE_CORRUPTED_MEMORY);
+ }
}
TEST_P(QuicConnectionTest, ClientReceivesRejOnNonCryptoStream) {
@@ -7774,7 +7810,13 @@ TEST_P(QuicConnectionTest, ClientReceivesRejOnNonCryptoStream) {
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
ForceProcessFramePacket(QuicFrame(frame1_));
- TestConnectionCloseQuicErrorCode(QUIC_MAYBE_CORRUPTED_MEMORY);
+ if (GetQuicReloadableFlag(quic_reject_unexpected_ietf_frame_types) &&
+ VersionHasIetfQuicFrames(version().transport_version)) {
+ // INITIAL packet should not contain STREAM frame.
+ TestConnectionCloseQuicErrorCode(IETF_QUIC_PROTOCOL_VIOLATION);
+ } else {
+ TestConnectionCloseQuicErrorCode(QUIC_MAYBE_CORRUPTED_MEMORY);
+ }
}
TEST_P(QuicConnectionTest, CloseConnectionOnPacketTooLarge) {
@@ -8572,8 +8614,10 @@ TEST_P(QuicConnectionTest, RetransmittableOnWirePingLimit) {
}
TEST_P(QuicConnectionTest, ValidStatelessResetToken) {
- const QuicUint128 kTestToken = 1010101;
- const QuicUint128 kWrongTestToken = 1010100;
+ const StatelessResetToken kTestToken{0, 1, 0, 1, 0, 1, 0, 1,
+ 0, 1, 0, 1, 0, 1, 0, 1};
+ const StatelessResetToken kWrongTestToken{0, 1, 0, 1, 0, 1, 0, 1,
+ 0, 1, 0, 1, 0, 1, 0, 2};
QuicConfig config;
// No token has been received.
EXPECT_FALSE(connection_.IsValidStatelessResetToken(kTestToken));
@@ -8921,23 +8965,23 @@ TEST_P(QuicConnectionTest,
EXPECT_CALL(visitor_,
OnPacketReceived(_, _, /*is_connectivity_probe=*/true))
.Times(1);
- const QuicSocketAddress kNewSelfAddress =
- QuicSocketAddress(QuicIpAddress::Loopback6(), /*port=*/23456);
+ const QuicSocketAddress kNewSelfAddress =
+ QuicSocketAddress(QuicIpAddress::Loopback6(), /*port=*/23456);
- std::unique_ptr<SerializedPacket> probing_packet = ConstructProbingPacket();
- std::unique_ptr<QuicReceivedPacket> received(ConstructReceivedPacket(
- QuicEncryptedPacket(probing_packet->encrypted_buffer,
- probing_packet->encrypted_length),
- clock_.Now()));
- uint64_t num_probing_received =
- connection_.GetStats().num_connectivity_probing_received;
- ProcessReceivedPacket(kNewSelfAddress, kPeerAddress, *received);
+ std::unique_ptr<SerializedPacket> probing_packet = ConstructProbingPacket();
+ std::unique_ptr<QuicReceivedPacket> received(ConstructReceivedPacket(
+ QuicEncryptedPacket(probing_packet->encrypted_buffer,
+ probing_packet->encrypted_length),
+ clock_.Now()));
+ uint64_t num_probing_received =
+ connection_.GetStats().num_connectivity_probing_received;
+ ProcessReceivedPacket(kNewSelfAddress, kPeerAddress, *received);
- EXPECT_EQ(num_probing_received + 1,
- connection_.GetStats().num_connectivity_probing_received);
- EXPECT_EQ(kPeerAddress, connection_.peer_address());
- EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
- EXPECT_TRUE(connection_.IsPathDegrading());
+ EXPECT_EQ(num_probing_received + 1,
+ connection_.GetStats().num_connectivity_probing_received);
+ EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+ EXPECT_TRUE(connection_.IsPathDegrading());
}
// Verify new path degrading detection is activated.
@@ -9174,23 +9218,23 @@ TEST_P(QuicConnectionTest, MultiplePacketNumberSpacesBasicReceiving) {
// Receives packet 1000 in initial data.
ProcessCryptoPacketAtLevel(1000, ENCRYPTION_INITIAL);
EXPECT_TRUE(connection_.HasPendingAcks());
- peer_framer_.SetEncrypter(ENCRYPTION_ZERO_RTT,
+ peer_framer_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
std::make_unique<TaggingEncrypter>(0x02));
- SetDecrypter(ENCRYPTION_ZERO_RTT,
+ SetDecrypter(ENCRYPTION_FORWARD_SECURE,
std::make_unique<StrictTaggingDecrypter>(0x02));
connection_.SetEncrypter(ENCRYPTION_INITIAL,
std::make_unique<TaggingEncrypter>(0x02));
// Receives packet 1000 in application data.
- ProcessDataPacketAtLevel(1000, false, ENCRYPTION_ZERO_RTT);
+ ProcessDataPacketAtLevel(1000, false, ENCRYPTION_FORWARD_SECURE);
EXPECT_TRUE(connection_.HasPendingAcks());
- connection_.SendApplicationDataAtLevel(ENCRYPTION_ZERO_RTT, 5, "data", 0,
- NO_FIN);
+ connection_.SendApplicationDataAtLevel(ENCRYPTION_FORWARD_SECURE, 5, "data",
+ 0, NO_FIN);
// Verify application data ACK gets bundled with outgoing data.
EXPECT_EQ(2u, writer_->frame_count());
// Make sure ACK alarm is still set because initial data is not ACKed.
EXPECT_TRUE(connection_.HasPendingAcks());
// Receive packet 1001 in application data.
- ProcessDataPacketAtLevel(1001, false, ENCRYPTION_ZERO_RTT);
+ ProcessDataPacketAtLevel(1001, false, ENCRYPTION_FORWARD_SECURE);
clock_.AdvanceTime(DefaultRetransmissionTime());
// Simulates ACK alarm fires and verify two ACKs are flushed.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
@@ -9199,13 +9243,9 @@ TEST_P(QuicConnectionTest, MultiplePacketNumberSpacesBasicReceiving) {
connection_.GetAckAlarm()->Fire();
EXPECT_FALSE(connection_.HasPendingAcks());
// Receives more packets in application data.
- ProcessDataPacketAtLevel(1002, false, ENCRYPTION_ZERO_RTT);
+ ProcessDataPacketAtLevel(1002, false, ENCRYPTION_FORWARD_SECURE);
EXPECT_TRUE(connection_.HasPendingAcks());
- peer_framer_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
- std::make_unique<TaggingEncrypter>(0x02));
- SetDecrypter(ENCRYPTION_FORWARD_SECURE,
- std::make_unique<StrictTaggingDecrypter>(0x02));
// Verify zero rtt and forward secure packets get acked in the same packet.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
ProcessDataPacket(1003);
@@ -9271,7 +9311,7 @@ TEST_P(QuicConnectionTest, ValidClientConnectionId) {
frames.push_back(QuicFrame(ping_frame));
frames.push_back(QuicFrame(padding_frame));
std::unique_ptr<QuicPacket> packet =
- BuildUnsizedDataPacket(&framer_, header, frames);
+ BuildUnsizedDataPacket(&peer_framer_, header, frames);
char buffer[kMaxOutgoingPacketSize];
size_t encrypted_length = peer_framer_.EncryptPayload(
ENCRYPTION_FORWARD_SECURE, QuicPacketNumber(1), *packet, buffer,
@@ -9299,7 +9339,7 @@ TEST_P(QuicConnectionTest, InvalidClientConnectionId) {
frames.push_back(QuicFrame(ping_frame));
frames.push_back(QuicFrame(padding_frame));
std::unique_ptr<QuicPacket> packet =
- BuildUnsizedDataPacket(&framer_, header, frames);
+ BuildUnsizedDataPacket(&peer_framer_, header, frames);
char buffer[kMaxOutgoingPacketSize];
size_t encrypted_length = peer_framer_.EncryptPayload(
ENCRYPTION_FORWARD_SECURE, QuicPacketNumber(1), *packet, buffer,
@@ -9327,7 +9367,7 @@ TEST_P(QuicConnectionTest, UpdateClientConnectionIdFromFirstPacket) {
frames.push_back(QuicFrame(ping_frame));
frames.push_back(QuicFrame(padding_frame));
std::unique_ptr<QuicPacket> packet =
- BuildUnsizedDataPacket(&framer_, header, frames);
+ BuildUnsizedDataPacket(&peer_framer_, header, frames);
char buffer[kMaxOutgoingPacketSize];
size_t encrypted_length =
peer_framer_.EncryptPayload(ENCRYPTION_INITIAL, QuicPacketNumber(1),
@@ -9339,6 +9379,79 @@ TEST_P(QuicConnectionTest, UpdateClientConnectionIdFromFirstPacket) {
EXPECT_EQ(0u, connection_.GetStats().packets_dropped);
EXPECT_EQ(TestConnectionId(0x33), connection_.client_connection_id());
}
+void QuicConnectionTest::TestReplaceConnectionIdFromInitial() {
+ if (!framer_.version().AllowsVariableLengthConnectionIds()) {
+ return;
+ }
+ // We start with a known connection ID.
+ EXPECT_TRUE(connection_.connected());
+ EXPECT_EQ(0u, connection_.GetStats().packets_dropped);
+ EXPECT_NE(TestConnectionId(0x33), connection_.connection_id());
+ // Receiving an initial can replace the connection ID once.
+ {
+ QuicPacketHeader header = ConstructPacketHeader(1, ENCRYPTION_INITIAL);
+ header.source_connection_id = TestConnectionId(0x33);
+ header.source_connection_id_included = CONNECTION_ID_PRESENT;
+ QuicFrames frames;
+ QuicPingFrame ping_frame;
+ QuicPaddingFrame padding_frame;
+ frames.push_back(QuicFrame(ping_frame));
+ frames.push_back(QuicFrame(padding_frame));
+ std::unique_ptr<QuicPacket> packet =
+ BuildUnsizedDataPacket(&peer_framer_, header, frames);
+ char buffer[kMaxOutgoingPacketSize];
+ size_t encrypted_length =
+ peer_framer_.EncryptPayload(ENCRYPTION_INITIAL, QuicPacketNumber(1),
+ *packet, buffer, kMaxOutgoingPacketSize);
+ QuicReceivedPacket received_packet(buffer, encrypted_length, clock_.Now(),
+ false);
+ ProcessReceivedPacket(kSelfAddress, kPeerAddress, received_packet);
+ }
+ EXPECT_TRUE(connection_.connected());
+ EXPECT_EQ(0u, connection_.GetStats().packets_dropped);
+ EXPECT_EQ(TestConnectionId(0x33), connection_.connection_id());
+ // Trying to replace the connection ID a second time drops the packet.
+ {
+ QuicPacketHeader header = ConstructPacketHeader(2, ENCRYPTION_INITIAL);
+ header.source_connection_id = TestConnectionId(0x66);
+ header.source_connection_id_included = CONNECTION_ID_PRESENT;
+ QuicFrames frames;
+ QuicPingFrame ping_frame;
+ QuicPaddingFrame padding_frame;
+ frames.push_back(QuicFrame(ping_frame));
+ frames.push_back(QuicFrame(padding_frame));
+ std::unique_ptr<QuicPacket> packet =
+ BuildUnsizedDataPacket(&peer_framer_, header, frames);
+ char buffer[kMaxOutgoingPacketSize];
+ size_t encrypted_length =
+ peer_framer_.EncryptPayload(ENCRYPTION_INITIAL, QuicPacketNumber(2),
+ *packet, buffer, kMaxOutgoingPacketSize);
+ QuicReceivedPacket received_packet(buffer, encrypted_length, clock_.Now(),
+ false);
+ ProcessReceivedPacket(kSelfAddress, kPeerAddress, received_packet);
+ }
+ EXPECT_TRUE(connection_.connected());
+ EXPECT_EQ(1u, connection_.GetStats().packets_dropped);
+ EXPECT_EQ(TestConnectionId(0x33), connection_.connection_id());
+}
+
+TEST_P(QuicConnectionTest, ReplaceServerConnectionIdFromInitial) {
+ TestReplaceConnectionIdFromInitial();
+}
+
+TEST_P(QuicConnectionTest, ReplaceServerConnectionIdFromRetryAndInitial) {
+ // First make the connection process a RETRY and replace the server connection
+ // ID a first time.
+ TestClientRetryHandling(/*invalid_retry_tag=*/false,
+ /*missing_original_id_in_config=*/false,
+ /*wrong_original_id_in_config=*/false,
+ /*missing_retry_id_in_config=*/false,
+ /*wrong_retry_id_in_config=*/false);
+ // Reset the test framer to use the right connection ID.
+ peer_framer_.SetInitialObfuscators(connection_.connection_id());
+ // Now process an INITIAL and replace the server connection ID a second time.
+ TestReplaceConnectionIdFromInitial();
+}
// Regression test for b/134416344.
TEST_P(QuicConnectionTest, CheckConnectedBeforeFlush) {
@@ -11049,7 +11162,10 @@ TEST_P(QuicConnectionTest, ProcessUndecryptablePacketsBasedOnEncryptionLevel) {
std::make_unique<TaggingEncrypter>(0x01));
connection_.SetDefaultEncryptionLevel(ENCRYPTION_HANDSHAKE);
// Verify all ENCRYPTION_HANDSHAKE packets get processed.
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(6);
+ if (!GetQuicReloadableFlag(quic_reject_unexpected_ietf_frame_types) ||
+ !VersionHasIetfQuicFrames(version().transport_version)) {
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(6);
+ }
connection_.GetProcessUndecryptablePacketsAlarm()->Fire();
EXPECT_EQ(1u, QuicConnectionPeer::NumUndecryptablePackets(&connection_));
@@ -11694,13 +11810,46 @@ TEST_P(QuicConnectionTest, NewPathValidationCancelsPreviousOne) {
EXPECT_TRUE(connection_.HasPendingPathValidation());
}
+// Regression test for b/182571515.
+TEST_P(QuicConnectionTest, PathValidationRetry) {
+ if (!VersionHasIetfQuicFrames(connection_.version().transport_version) ||
+ !connection_.use_path_validator()) {
+ return;
+ }
+ PathProbeTestInit(Perspective::IS_CLIENT);
+
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(2u)
+ .WillRepeatedly(Invoke([&]() {
+ EXPECT_EQ(1u, writer_->path_challenge_frames().size());
+ 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));
+ EXPECT_EQ(1u, writer_->packets_write_attempts());
+ EXPECT_TRUE(connection_.HasPendingPathValidation());
+
+ // Retry after time out.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(3 * kInitialRttMs));
+ static_cast<test::MockRandom*>(helper_->GetRandomGenerator())->ChangeValue();
+ static_cast<TestAlarmFactory::TestAlarm*>(
+ QuicPathValidatorPeer::retry_timer(
+ QuicConnectionPeer::path_validator(&connection_)))
+ ->Fire();
+ EXPECT_EQ(2u, writer_->packets_write_attempts());
+}
+
TEST_P(QuicConnectionTest, PathValidationReceivesStatelessReset) {
if (!VersionHasIetfQuicFrames(connection_.version().transport_version) ||
!connection_.use_path_validator()) {
return;
}
PathProbeTestInit(Perspective::IS_CLIENT);
- const QuicUint128 kTestStatelessResetToken = 1010101;
QuicConfig config;
QuicConfigPeer::SetReceivedStatelessResetToken(&config,
kTestStatelessResetToken);
@@ -11729,6 +11878,7 @@ TEST_P(QuicConnectionTest, PathValidationReceivesStatelessReset) {
std::unique_ptr<QuicEncryptedPacket> packet(
QuicFramer::BuildIetfStatelessResetPacket(connection_id_,
+ /*received_packet_length=*/100,
kTestStatelessResetToken));
std::unique_ptr<QuicReceivedPacket> received(
ConstructReceivedPacket(*packet, QuicTime::Zero()));
@@ -12375,8 +12525,10 @@ TEST_P(QuicConnectionTest, ZeroRttRejectionAndMissingInitialKeys) {
connection_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
std::make_unique<TaggingEncrypter>(0x04));
connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
- // Retransmit rejected 0-RTT packets.
- connection_.OnCanWrite();
+ if (!GetQuicReloadableFlag(quic_donot_write_mid_packet_processing)) {
+ // Retransmit rejected 0-RTT packets.
+ connection_.OnCanWrite();
+ }
// Advance INITIAL ack delay to trigger initial ACK to be sent AFTER
// the retransmission of rejected 0-RTT packets while the HANDSHAKE
// packet is still in the coalescer, such that the INITIAL key gets
@@ -13479,64 +13631,7 @@ TEST_P(QuicConnectionTest, DonotOverrideRetryTokenWithAddressToken) {
}
TEST_P(QuicConnectionTest,
- ServerReceivedZeroRttWithHigherPacketNumberThanOneRttAndFlagDisabled) {
- SetQuicReloadableFlag(
- quic_close_connection_on_0rtt_packet_number_higher_than_1rtt, false);
- if (!connection_.version().UsesTls()) {
- return;
- }
-
- // The code that checks for this error piggybacks on some book-keeping state
- // kept for key update, so enable key update for the test.
- std::string error_details;
- TransportParameters params;
- params.key_update_not_yet_supported = false;
- QuicConfig config;
- EXPECT_THAT(config.ProcessTransportParameters(
- params, /* is_resumption = */ false, &error_details),
- IsQuicNoError());
- config.SetKeyUpdateSupportedLocally();
- QuicConfigPeer::SetNegotiated(&config, true);
- QuicConfigPeer::SetReceivedOriginalConnectionId(&config,
- connection_.connection_id());
- QuicConfigPeer::SetReceivedInitialSourceConnectionId(
- &config, connection_.connection_id());
- EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
- connection_.SetFromConfig(config);
-
- set_perspective(Perspective::IS_SERVER);
- SetDecrypter(ENCRYPTION_ZERO_RTT,
- std::make_unique<NullDecrypter>(Perspective::IS_SERVER));
-
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(1, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
-
- // Finish handshake.
- connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
- notifier_.NeuterUnencryptedData();
- connection_.NeuterUnencryptedPackets();
- connection_.OnHandshakeComplete();
- EXPECT_CALL(visitor_, GetHandshakeState())
- .WillRepeatedly(Return(HANDSHAKE_COMPLETE));
-
- // Decrypt a 1-RTT packet.
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(2, !kHasStopWaiting, ENCRYPTION_FORWARD_SECURE);
- EXPECT_TRUE(connection_.GetDiscardZeroRttDecryptionKeysAlarm()->IsSet());
-
- // 0-RTT packet with higher packet number than a 1-RTT packet is invalid, but
- // accepted as the
- // quic_close_connection_on_0rtt_packet_number_higher_than_1rtt
- // flag is disabled.
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(3, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
- EXPECT_TRUE(connection_.connected());
-}
-
-TEST_P(QuicConnectionTest,
ServerReceivedZeroRttWithHigherPacketNumberThanOneRtt) {
- SetQuicReloadableFlag(
- quic_close_connection_on_0rtt_packet_number_higher_than_1rtt, true);
if (!connection_.version().UsesTls()) {
return;
}
@@ -13624,17 +13719,10 @@ TEST_P(QuicConnectionTest, PeerMigrateBeforeHandshakeConfirm) {
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0u);
- if (!GetQuicReloadableFlag(quic_update_packet_content_returns_connected)) {
- EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _));
- EXPECT_QUIC_BUG(
- ProcessFramePacketWithAddresses(QuicFrame(&frame), kSelfAddress,
- kNewPeerAddress, ENCRYPTION_INITIAL),
- "");
- } else {
- EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _)).Times(0);
- ProcessFramePacketWithAddresses(QuicFrame(&frame), kSelfAddress,
- kNewPeerAddress, ENCRYPTION_INITIAL);
- }
+
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _)).Times(0);
+ ProcessFramePacketWithAddresses(QuicFrame(&frame), kSelfAddress,
+ kNewPeerAddress, ENCRYPTION_INITIAL);
EXPECT_FALSE(connection_.connected());
}
@@ -13666,10 +13754,10 @@ TEST_P(QuicConnectionTest, TryToFlushAckWithAckQueued) {
}
TEST_P(QuicConnectionTest, PathChallengeBeforePeerIpAddressChangeAtServer) {
+ set_perspective(Perspective::IS_SERVER);
if (!connection_.validate_client_address()) {
return;
}
- set_perspective(Perspective::IS_SERVER);
PathProbeTestInit(Perspective::IS_SERVER);
const QuicSocketAddress kNewPeerAddress =
@@ -13764,10 +13852,10 @@ TEST_P(QuicConnectionTest, PathChallengeBeforePeerIpAddressChangeAtServer) {
TEST_P(QuicConnectionTest,
PathValidationSucceedsBeforePeerIpAddressChangeAtServer) {
+ set_perspective(Perspective::IS_SERVER);
if (!connection_.validate_client_address()) {
return;
}
- set_perspective(Perspective::IS_SERVER);
PathProbeTestInit(Perspective::IS_SERVER);
// Receive probing packet with new peer address.
@@ -13855,10 +13943,10 @@ TEST_P(QuicConnectionTest,
TEST_P(QuicConnectionTest,
ProbedOnAnotherPathAfterPeerIpAddressChangeAtServer) {
+ PathProbeTestInit(Perspective::IS_SERVER);
if (!connection_.validate_client_address()) {
return;
}
- PathProbeTestInit(Perspective::IS_SERVER);
const QuicSocketAddress kNewPeerAddress(QuicIpAddress::Loopback4(),
/*port=*/23456);
@@ -13916,6 +14004,280 @@ TEST_P(QuicConnectionTest,
EXPECT_TRUE(connection_.HasPendingPathValidation());
}
+TEST_P(QuicConnectionTest,
+ CloseConnectionAfterReceiveNewConnectionIdFromPeerUsingEmptyCID) {
+ if (!version().HasIetfQuicFrames()) {
+ return;
+ }
+ QuicConnectionPeer::EnableMultipleConnectionIdSupport(&connection_);
+ set_perspective(Perspective::IS_SERVER);
+ ASSERT_TRUE(connection_.client_connection_id().IsEmpty());
+
+ EXPECT_CALL(visitor_, BeforeConnectionCloseSent());
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF))
+ .WillOnce(Invoke(this, &QuicConnectionTest::SaveConnectionCloseFrame));
+ 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_FALSE(connection_.OnNewConnectionIdFrame(frame));
+
+ EXPECT_FALSE(connection_.connected());
+ EXPECT_THAT(saved_connection_close_frame_.quic_error_code,
+ IsError(IETF_QUIC_PROTOCOL_VIOLATION));
+}
+
+TEST_P(QuicConnectionTest, NewConnectionIdFrameResultsInError) {
+ if (!version().HasIetfQuicFrames()) {
+ return;
+ }
+ QuicConnectionPeer::EnableMultipleConnectionIdSupport(&connection_);
+ connection_.CreateConnectionIdManager();
+ ASSERT_FALSE(connection_.connection_id().IsEmpty());
+
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF))
+ .WillOnce(Invoke(this, &QuicConnectionTest::SaveConnectionCloseFrame));
+ QuicNewConnectionIdFrame frame;
+ frame.sequence_number = 1u;
+ frame.connection_id = connection_id_; // Reuses connection ID casuing error.
+ frame.stateless_reset_token =
+ QuicUtils::GenerateStatelessResetToken(frame.connection_id);
+ frame.retire_prior_to = 0u;
+
+ EXPECT_FALSE(connection_.OnNewConnectionIdFrame(frame));
+
+ EXPECT_FALSE(connection_.connected());
+ EXPECT_THAT(saved_connection_close_frame_.quic_error_code,
+ IsError(IETF_QUIC_PROTOCOL_VIOLATION));
+}
+
+TEST_P(QuicConnectionTest,
+ ClientRetirePeerIssuedConnectionIdTriggeredByNewConnectionIdFrame) {
+ if (!version().HasIetfQuicFrames()) {
+ return;
+ }
+ QuicConnectionPeer::EnableMultipleConnectionIdSupport(&connection_);
+ connection_.CreateConnectionIdManager();
+
+ 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_.connection_id(), connection_id_);
+
+ EXPECT_CALL(visitor_, SendRetireConnectionId(/*sequence_number=*/0u));
+ retire_peer_issued_cid_alarm->Fire();
+ EXPECT_EQ(connection_.connection_id(), TestConnectionId(2));
+ EXPECT_EQ(connection_.packet_creator().GetDestinationConnectionId(),
+ TestConnectionId(2));
+}
+
+TEST_P(QuicConnectionTest,
+ ServerRetirePeerIssuedConnectionIdTriggeredByNewConnectionIdFrame) {
+ if (!version().HasIetfQuicFrames()) {
+ return;
+ }
+ QuicConnectionPeer::EnableMultipleConnectionIdSupport(&connection_);
+ set_perspective(Perspective::IS_SERVER);
+ connection_.set_client_connection_id(TestConnectionId(0));
+
+ 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));
+}
+
+TEST_P(QuicConnectionTest,
+ CloseConnectionAfterReceiveRetireConnectionIdWhenNoCIDIssued) {
+ if (!version().HasIetfQuicFrames()) {
+ return;
+ }
+ QuicConnectionPeer::EnableMultipleConnectionIdSupport(&connection_);
+ set_perspective(Perspective::IS_SERVER);
+
+ EXPECT_CALL(visitor_, BeforeConnectionCloseSent());
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF))
+ .WillOnce(Invoke(this, &QuicConnectionTest::SaveConnectionCloseFrame));
+ QuicRetireConnectionIdFrame frame;
+ frame.sequence_number = 1u;
+
+ EXPECT_FALSE(connection_.OnRetireConnectionIdFrame(frame));
+
+ EXPECT_FALSE(connection_.connected());
+ EXPECT_THAT(saved_connection_close_frame_.quic_error_code,
+ IsError(IETF_QUIC_PROTOCOL_VIOLATION));
+}
+
+TEST_P(QuicConnectionTest, RetireConnectionIdFrameResultsInError) {
+ if (!version().HasIetfQuicFrames()) {
+ return;
+ }
+ QuicConnectionPeer::EnableMultipleConnectionIdSupport(&connection_);
+ set_perspective(Perspective::IS_SERVER);
+ connection_.CreateConnectionIdManager();
+
+ EXPECT_CALL(visitor_, OnServerConnectionIdIssued(_));
+ EXPECT_CALL(visitor_, SendNewConnectionId(_));
+ connection_.MaybeSendConnectionIdToClient();
+
+ EXPECT_CALL(visitor_, BeforeConnectionCloseSent());
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF))
+ .WillOnce(Invoke(this, &QuicConnectionTest::SaveConnectionCloseFrame));
+ QuicRetireConnectionIdFrame frame;
+ frame.sequence_number = 2u; // The corresponding ID is never issued.
+
+ EXPECT_FALSE(connection_.OnRetireConnectionIdFrame(frame));
+
+ EXPECT_FALSE(connection_.connected());
+ EXPECT_THAT(saved_connection_close_frame_.quic_error_code,
+ IsError(IETF_QUIC_PROTOCOL_VIOLATION));
+}
+
+TEST_P(QuicConnectionTest, ServerRetireSelfIssuedConnectionId) {
+ if (!version().HasIetfQuicFrames()) {
+ return;
+ }
+ QuicConnectionPeer::EnableMultipleConnectionIdSupport(&connection_);
+ set_perspective(Perspective::IS_SERVER);
+ connection_.CreateConnectionIdManager();
+ QuicConnectionId recorded_cid;
+ auto cid_recorder = [&recorded_cid](const QuicConnectionId& cid) {
+ recorded_cid = cid;
+ };
+ QuicConnectionId cid0 = connection_id_;
+ QuicConnectionId cid1;
+ QuicConnectionId cid2;
+
+ EXPECT_CALL(visitor_, OnServerConnectionIdIssued(_))
+ .WillOnce(Invoke(cid_recorder));
+ EXPECT_CALL(visitor_, SendNewConnectionId(_));
+ connection_.MaybeSendConnectionIdToClient();
+ cid1 = recorded_cid;
+
+ auto* retire_self_issued_cid_alarm =
+ connection_.GetRetireSelfIssuedConnectionIdAlarm();
+ ASSERT_FALSE(retire_self_issued_cid_alarm->IsSet());
+
+ QuicRetireConnectionIdFrame frame;
+ frame.sequence_number = 0u;
+ EXPECT_CALL(visitor_, OnServerConnectionIdIssued(_))
+ .WillOnce(Invoke(cid_recorder));
+ // RetireConnectionId trigers sending NewConnectionId immediately.
+ EXPECT_CALL(visitor_, SendNewConnectionId(_));
+ EXPECT_TRUE(connection_.OnRetireConnectionIdFrame(frame));
+ cid2 = recorded_cid;
+ // cid0 is not retired immediately.
+ EXPECT_THAT(connection_.GetActiveServerConnectionIds(),
+ ElementsAre(cid0, cid1, cid2));
+ ASSERT_TRUE(retire_self_issued_cid_alarm->IsSet());
+ // cid0 is retired when the retire CID alarm fires.
+ EXPECT_CALL(visitor_, OnServerConnectionIdRetired(cid0));
+ retire_self_issued_cid_alarm->Fire();
+ EXPECT_THAT(connection_.GetActiveServerConnectionIds(),
+ ElementsAre(cid1, cid2));
+}
+
+// Regression test for b/182571515
+TEST_P(QuicConnectionTest, LostDataThenGetAcknowledged) {
+ set_perspective(Perspective::IS_SERVER);
+ if (!connection_.validate_client_address()) {
+ return;
+ }
+
+ QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
+ if (version().SupportsAntiAmplificationLimit()) {
+ QuicConnectionPeer::SetAddressValidated(&connection_);
+ }
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ EXPECT_CALL(visitor_, GetHandshakeState())
+ .WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
+
+ QuicPacketNumber last_packet;
+ // Send packets 1 to 4.
+ SendStreamDataToPeer(3, "foo", 0, NO_FIN, &last_packet); // Packet 1
+ SendStreamDataToPeer(3, "foo", 3, NO_FIN, &last_packet); // Packet 2
+ SendStreamDataToPeer(3, "foo", 6, NO_FIN, &last_packet); // Packet 3
+ SendStreamDataToPeer(3, "foo", 9, NO_FIN, &last_packet); // Packet 4
+
+ // Process a PING packet to set peer address.
+ ProcessFramePacket(QuicFrame(QuicPingFrame()));
+
+ // Process a packet containing a STREAM_FRAME and an ACK with changed peer
+ // address.
+ QuicFrames frames;
+ frames.push_back(QuicFrame(frame1_));
+ QuicAckFrame ack = InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(5)}});
+ frames.push_back(QuicFrame(&ack));
+
+ EXPECT_CALL(visitor_, OnConnectionMigration(_)).Times(1);
+
+ // Invoke OnCanWrite.
+ EXPECT_CALL(visitor_, OnStreamFrame(_))
+ .WillOnce(
+ InvokeWithoutArgs(&notifier_, &SimpleSessionNotifier::OnCanWrite));
+ QuicIpAddress ip_address;
+ ASSERT_TRUE(ip_address.FromString("127.0.52.223"));
+ if (GetQuicReloadableFlag(quic_donot_write_mid_packet_processing)) {
+ EXPECT_QUIC_BUG(
+ ProcessFramesPacketWithAddresses(frames, kSelfAddress,
+ QuicSocketAddress(ip_address, 1000),
+ ENCRYPTION_FORWARD_SECURE),
+ "Try to write mid packet processing");
+ EXPECT_EQ(1u, writer_->path_challenge_frames().size());
+ // Verify stream frame will not be retransmitted.
+ EXPECT_TRUE(writer_->stream_frames().empty());
+ } else {
+ ProcessFramesPacketWithAddresses(frames, kSelfAddress,
+ QuicSocketAddress(ip_address, 1000),
+ ENCRYPTION_FORWARD_SECURE);
+ // In prod, this would cause FAILED_TO_SERIALIZE_PACKET since the stream
+ // data has been freed, but simple_data_producer does not free data.
+ EXPECT_EQ(1u, writer_->stream_frames().size());
+ }
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_constants.h b/chromium/net/third_party/quiche/src/quic/core/quic_constants.h
index 2de827f6227..b750abb3a4f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_constants.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_constants.h
@@ -100,6 +100,9 @@ const size_t kPublicFlagsSize = 1;
// Number of bytes reserved for version number in the packet header.
const size_t kQuicVersionSize = 4;
+// Minimum number of active connection IDs that an end point can maintain.
+const uint32_t kMinNumOfActiveConnectionIds = 2;
+
// Length of the retry integrity tag in bytes.
// https://tools.ietf.org/html/draft-ietf-quic-transport-25#section-17.2.5
const size_t kRetryIntegrityTagLength = 16;
@@ -291,6 +294,13 @@ QUIC_EXPORT_PRIVATE QuicPacketNumber FirstSendingPacketNumber();
QUIC_EXPORT_PRIVATE extern const char* const kEPIDGoogleFrontEnd;
QUIC_EXPORT_PRIVATE extern const char* const kEPIDGoogleFrontEnd0;
+// HTTP/3 Datagrams.
+enum : QuicDatagramFlowId {
+ kFirstDatagramFlowIdClient = 0,
+ kFirstDatagramFlowIdServer = 1,
+ kDatagramFlowIdIncrement = 2,
+};
+
} // namespace quic
#endif // QUICHE_QUIC_CORE_QUIC_CONSTANTS_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc
index 64e5f5d38eb..f41a3560009 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc
@@ -138,7 +138,7 @@ void QuicControlFrameManager::WriteOrBufferNewConnectionId(
const QuicConnectionId& connection_id,
uint64_t sequence_number,
uint64_t retire_prior_to,
- QuicUint128 stateless_reset_token) {
+ const StatelessResetToken& stateless_reset_token) {
QUIC_DVLOG(1) << "Writing NEW_CONNECTION_ID frame";
WriteOrBufferQuicFrame(QuicFrame(new QuicNewConnectionIdFrame(
++last_control_frame_id_, connection_id, sequence_number,
@@ -161,7 +161,7 @@ void QuicControlFrameManager::WriteOrBufferNewToken(absl::string_view token) {
void QuicControlFrameManager::OnControlFrameSent(const QuicFrame& frame) {
QuicControlFrameId id = GetControlFrameId(frame);
if (id == kInvalidControlFrameId) {
- QUIC_BUG
+ QUIC_BUG(quic_bug_12727_1)
<< "Send or retransmit a control frame with invalid control frame id";
return;
}
@@ -180,8 +180,9 @@ void QuicControlFrameManager::OnControlFrameSent(const QuicFrame& frame) {
return;
}
if (id > least_unsent_) {
- QUIC_BUG << "Try to send control frames out of order, id: " << id
- << " least_unsent: " << least_unsent_;
+ QUIC_BUG(quic_bug_10517_1)
+ << "Try to send control frames out of order, id: " << id
+ << " least_unsent: " << least_unsent_;
delegate_->OnControlFrameManagerError(
QUIC_INTERNAL_ERROR, "Try to send control frames out of order");
return;
@@ -211,7 +212,7 @@ void QuicControlFrameManager::OnControlFrameLost(const QuicFrame& frame) {
return;
}
if (id >= least_unsent_) {
- QUIC_BUG << "Try to mark unsent control frame as lost";
+ QUIC_BUG(quic_bug_10517_2) << "Try to mark unsent control frame as lost";
delegate_->OnControlFrameManagerError(
QUIC_INTERNAL_ERROR, "Try to mark unsent control frame as lost");
return;
@@ -224,7 +225,8 @@ void QuicControlFrameManager::OnControlFrameLost(const QuicFrame& frame) {
}
if (!QuicContainsKey(pending_retransmissions_, id)) {
pending_retransmissions_[id] = true;
- QUIC_BUG_IF(pending_retransmissions_.size() > control_frames_.size())
+ QUIC_BUG_IF(quic_bug_12727_2,
+ pending_retransmissions_.size() > control_frames_.size())
<< "least_unacked_: " << least_unacked_
<< ", least_unsent_: " << least_unsent_;
}
@@ -252,7 +254,7 @@ bool QuicControlFrameManager::WillingToWrite() const {
}
QuicFrame QuicControlFrameManager::NextPendingRetransmission() const {
- QUIC_BUG_IF(pending_retransmissions_.empty())
+ QUIC_BUG_IF(quic_bug_12727_3, pending_retransmissions_.empty())
<< "Unexpected call to NextPendingRetransmission() with empty pending "
<< "retransmission list.";
QuicControlFrameId id = pending_retransmissions_.begin()->first;
@@ -279,7 +281,7 @@ bool QuicControlFrameManager::RetransmitControlFrame(const QuicFrame& frame,
return true;
}
if (id >= least_unsent_) {
- QUIC_BUG << "Try to retransmit unsent control frame";
+ QUIC_BUG(quic_bug_10517_3) << "Try to retransmit unsent control frame";
delegate_->OnControlFrameManagerError(
QUIC_INTERNAL_ERROR, "Try to retransmit unsent control frame");
return false;
@@ -333,7 +335,7 @@ bool QuicControlFrameManager::OnControlFrameIdAcked(QuicControlFrameId id) {
return false;
}
if (id >= least_unsent_) {
- QUIC_BUG << "Try to ack unsent control frame";
+ QUIC_BUG(quic_bug_10517_4) << "Try to ack unsent control frame";
delegate_->OnControlFrameManagerError(QUIC_INTERNAL_ERROR,
"Try to ack unsent control frame");
return false;
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 e4a55260afe..1bb37035912 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
@@ -11,6 +11,7 @@
#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"
namespace quic {
@@ -92,10 +93,11 @@ class QUIC_EXPORT_PRIVATE QuicControlFrameManager {
// Tries to send a NEW_CONNECTION_ID frame. The frame is buffered if it cannot
// be sent immediately.
- void WriteOrBufferNewConnectionId(const QuicConnectionId& connection_id,
- uint64_t sequence_number,
- uint64_t retire_prior_to,
- QuicUint128 stateless_reset_token);
+ void WriteOrBufferNewConnectionId(
+ const QuicConnectionId& connection_id,
+ uint64_t sequence_number,
+ uint64_t retire_prior_to,
+ const StatelessResetToken& stateless_reset_token);
// Tries to send a RETIRE_CONNNECTION_ID frame. The frame is buffered if it
// cannot be sent immediately.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager_test.cc
index 5aed6e0c17f..9d6b434ef31 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager_test.cc
@@ -250,7 +250,8 @@ TEST_F(QuicControlFrameManagerTest, NewAndRetireConnectionIdFrames) {
// Send NewConnectionIdFrame as frame 6.
manager_->WriteOrBufferNewConnectionId(
TestConnectionId(3), /*sequence_number=*/2, /*retire_prior_to=*/1,
- /*stateless_reset_token=*/MakeQuicUint128(1, 1));
+ /*stateless_reset_token=*/
+ {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1});
// Send RetireConnectionIdFrame as frame 7.
manager_->WriteOrBufferRetireConnectionId(/*sequence_number=*/0);
manager_->OnCanWrite();
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.cc
index 29a4367d599..e9a99167f46 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.cc
@@ -117,14 +117,14 @@ int QuicCryptoClientHandshaker::num_sent_client_hellos() const {
}
bool QuicCryptoClientHandshaker::IsResumption() const {
- QUIC_BUG_IF(!one_rtt_keys_available_);
+ QUIC_BUG_IF(quic_bug_12522_1, !one_rtt_keys_available_);
// While 0-RTT handshakes could be considered to be like resumption, QUIC
// Crypto doesn't have the same notion of a resumption like TLS does.
return false;
}
bool QuicCryptoClientHandshaker::EarlyDataAccepted() const {
- QUIC_BUG_IF(!one_rtt_keys_available_);
+ QUIC_BUG_IF(quic_bug_12522_2, !one_rtt_keys_available_);
return num_client_hellos_ == 1;
}
@@ -133,7 +133,7 @@ ssl_early_data_reason_t QuicCryptoClientHandshaker::EarlyDataReason() const {
}
bool QuicCryptoClientHandshaker::ReceivedInchoateReject() const {
- QUIC_BUG_IF(!one_rtt_keys_available_);
+ QUIC_BUG_IF(quic_bug_12522_3, !one_rtt_keys_available_);
return num_client_hellos_ >= 3;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.cc
index 3160f583185..78d2f10a563 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.cc
@@ -49,8 +49,9 @@ QuicCryptoClientStream::QuicCryptoClientStream(
proof_handler, has_application_state);
break;
case PROTOCOL_UNSUPPORTED:
- QUIC_BUG << "Attempting to create QuicCryptoClientStream for unknown "
- "handshake protocol";
+ QUIC_BUG(quic_bug_10296_1)
+ << "Attempting to create QuicCryptoClientStream for unknown "
+ "handshake protocol";
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.cc
index b80d06dc1e5..708b1750166 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.cc
@@ -42,9 +42,9 @@ std::unique_ptr<QuicCryptoServerStreamBase> CreateCryptoServerStream(
case PROTOCOL_UNSUPPORTED:
break;
}
- QUIC_BUG << "Unknown handshake protocol: "
- << static_cast<int>(
- session->connection()->version().handshake_protocol);
+ QUIC_BUG(quic_bug_10492_1)
+ << "Unknown handshake protocol: "
+ << static_cast<int>(session->connection()->version().handshake_protocol);
return nullptr;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.cc
index 1b2f6db928f..f8f34dfb22c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.cc
@@ -71,7 +71,8 @@ QuicByteCount QuicCryptoStream::CryptoMessageFramingOverhead(
}
void QuicCryptoStream::OnCryptoFrame(const QuicCryptoFrame& frame) {
- QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(session()->transport_version()))
+ QUIC_BUG_IF(quic_bug_12573_1,
+ !QuicVersionUsesCryptoFrames(session()->transport_version()))
<< "Versions less than 47 shouldn't receive CRYPTO frames";
EncryptionLevel level = session()->connection()->last_decrypted_level();
substreams_[level].sequencer.OnCryptoFrame(frame);
@@ -85,7 +86,7 @@ void QuicCryptoStream::OnCryptoFrame(const QuicCryptoFrame& frame) {
void QuicCryptoStream::OnStreamFrame(const QuicStreamFrame& frame) {
if (QuicVersionUsesCryptoFrames(session()->transport_version())) {
- QUIC_PEER_BUG
+ QUIC_PEER_BUG(quic_peer_bug_12573_2)
<< "Crypto data received in stream frame instead of crypto frame";
OnUnrecoverableError(QUIC_INVALID_STREAM_DATA, "Unexpected stream frame");
}
@@ -155,7 +156,7 @@ void QuicCryptoStream::WriteCryptoData(EncryptionLevel level,
return;
}
if (data.empty()) {
- QUIC_BUG << "Empty crypto data being written";
+ QUIC_BUG(quic_bug_10322_1) << "Empty crypto data being written";
return;
}
const bool had_buffered_data = HasBufferedCryptoFrames();
@@ -166,7 +167,7 @@ void QuicCryptoStream::WriteCryptoData(EncryptionLevel level,
send_buffer->SaveStreamData(&iov, /*iov_count=*/1, /*iov_offset=*/0,
data.length());
if (kMaxStreamLength - offset < data.length()) {
- QUIC_BUG << "Writing too much crypto handshake data";
+ QUIC_BUG(quic_bug_10322_2) << "Writing too much crypto handshake data";
// TODO(nharper): Switch this to an IETF QUIC error code, possibly
// INTERNAL_ERROR?
OnUnrecoverableError(QUIC_STREAM_LENGTH_OVERFLOW,
@@ -231,7 +232,8 @@ void QuicCryptoStream::NeuterStreamDataOfEncryptionLevel(
void QuicCryptoStream::OnStreamDataConsumed(QuicByteCount bytes_consumed) {
if (QuicVersionUsesCryptoFrames(session()->transport_version())) {
- QUIC_BUG << "Stream data consumed when CRYPTO frames should be in use";
+ QUIC_BUG(quic_bug_10322_3)
+ << "Stream data consumed when CRYPTO frames should be in use";
}
if (bytes_consumed > 0) {
bytes_consumed_[session()->connection()->encryption_level()].Add(
@@ -263,7 +265,8 @@ bool QuicCryptoStream::HasPendingCryptoRetransmission() const {
}
void QuicCryptoStream::WritePendingCryptoRetransmission() {
- QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(session()->transport_version()))
+ QUIC_BUG_IF(quic_bug_12573_3,
+ !QuicVersionUsesCryptoFrames(session()->transport_version()))
<< "Versions less than 47 don't write CRYPTO frames";
for (EncryptionLevel level : AllEncryptionLevels()) {
QuicStreamSendBuffer* send_buffer = &substreams_[level].send_buffer;
@@ -381,14 +384,16 @@ bool QuicCryptoStream::WriteCryptoFrame(EncryptionLevel level,
QuicStreamOffset offset,
QuicByteCount data_length,
QuicDataWriter* writer) {
- QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(session()->transport_version()))
+ QUIC_BUG_IF(quic_bug_12573_4,
+ !QuicVersionUsesCryptoFrames(session()->transport_version()))
<< "Versions less than 47 don't write CRYPTO frames (2)";
return substreams_[level].send_buffer.WriteStreamData(offset, data_length,
writer);
}
void QuicCryptoStream::OnCryptoFrameLost(QuicCryptoFrame* crypto_frame) {
- QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(session()->transport_version()))
+ QUIC_BUG_IF(quic_bug_12573_5,
+ !QuicVersionUsesCryptoFrames(session()->transport_version()))
<< "Versions less than 47 don't lose CRYPTO frames";
substreams_[crypto_frame->level].send_buffer.OnStreamDataLost(
crypto_frame->offset, crypto_frame->data_length);
@@ -396,7 +401,8 @@ void QuicCryptoStream::OnCryptoFrameLost(QuicCryptoFrame* crypto_frame) {
void QuicCryptoStream::RetransmitData(QuicCryptoFrame* crypto_frame,
TransmissionType type) {
- QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(session()->transport_version()))
+ QUIC_BUG_IF(quic_bug_12573_6,
+ !QuicVersionUsesCryptoFrames(session()->transport_version()))
<< "Versions less than 47 don't retransmit CRYPTO frames";
QuicIntervalSet<QuicStreamOffset> retransmission(
crypto_frame->offset, crypto_frame->offset + crypto_frame->data_length);
@@ -421,7 +427,8 @@ void QuicCryptoStream::RetransmitData(QuicCryptoFrame* crypto_frame,
}
void QuicCryptoStream::WriteBufferedCryptoFrames() {
- QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(session()->transport_version()))
+ QUIC_BUG_IF(quic_bug_12573_7,
+ !QuicVersionUsesCryptoFrames(session()->transport_version()))
<< "Versions less than 47 don't use CRYPTO frames";
for (EncryptionLevel level : AllEncryptionLevels()) {
QuicStreamSendBuffer* send_buffer = &substreams_[level].send_buffer;
@@ -443,7 +450,8 @@ void QuicCryptoStream::WriteBufferedCryptoFrames() {
}
bool QuicCryptoStream::HasBufferedCryptoFrames() const {
- QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(session()->transport_version()))
+ QUIC_BUG_IF(quic_bug_12573_8,
+ !QuicVersionUsesCryptoFrames(session()->transport_version()))
<< "Versions less than 47 don't use CRYPTO frames";
for (EncryptionLevel level : AllEncryptionLevels()) {
const QuicStreamSendBuffer& send_buffer = substreams_[level].send_buffer;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_data_writer.cc b/chromium/net/third_party/quiche/src/quic/core/quic_data_writer.cc
index 4ed9b4584c1..ee3c861ee8c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_data_writer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_data_writer.cc
@@ -201,8 +201,8 @@ bool QuicDataWriter::WriteVarInt62(
const QuicVariableLengthIntegerLength min_length = GetVarInt62Len(value);
if (write_length < min_length) {
- QUIC_BUG << "Cannot write value " << value << " with write_length "
- << write_length;
+ QUIC_BUG(quic_bug_10347_1) << "Cannot write value " << value
+ << " with write_length " << write_length;
return false;
}
if (write_length == min_length) {
@@ -220,15 +220,16 @@ bool QuicDataWriter::WriteVarInt62(
WriteUInt32(value);
}
- QUIC_BUG << "Invalid write_length " << static_cast<int>(write_length);
+ QUIC_BUG(quic_bug_10347_2)
+ << "Invalid write_length " << static_cast<int>(write_length);
return false;
}
// static
QuicVariableLengthIntegerLength QuicDataWriter::GetVarInt62Len(uint64_t value) {
if ((value & kVarInt62ErrorMask) != 0) {
- QUIC_BUG << "Attempted to encode a value, " << value
- << ", that is too big for VarInt62";
+ QUIC_BUG(quic_bug_10347_3) << "Attempted to encode a value, " << value
+ << ", that is too big for VarInt62";
return VARIABLE_LENGTH_INTEGER_LENGTH_0;
}
if ((value & kVarInt62Mask8Bytes) != 0) {
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 d0d44b6a1ab..0ed002a6850 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
@@ -25,7 +25,6 @@
#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_ptr_util.h"
#include "quic/platform/api/quic_stack_trace.h"
#include "common/platform/api/quiche_text_utils.h"
@@ -176,7 +175,7 @@ class StatelessConnectionTerminator {
/*transport_close_frame_type=*/0);
if (!creator_.AddFrame(QuicFrame(frame), NOT_RETRANSMISSION)) {
- QUIC_BUG << "Unable to add frame to an empty packet";
+ QUIC_BUG(quic_bug_10287_1) << "Unable to add frame to an empty packet";
delete frame;
return;
}
@@ -192,8 +191,8 @@ class StatelessConnectionTerminator {
QuicTimeWaitListManager* time_wait_list_manager_;
};
-// Class which extracts the ALPN from a QUIC_CRYPTO CHLO packet.
-class ChloAlpnExtractor : public ChloExtractor::Delegate {
+// Class which extracts the ALPN and SNI from a QUIC_CRYPTO CHLO packet.
+class ChloAlpnSniExtractor : public ChloExtractor::Delegate {
public:
void OnChlo(QuicTransportVersion version,
QuicConnectionId /*server_connection_id*/,
@@ -202,6 +201,10 @@ class ChloAlpnExtractor : public ChloExtractor::Delegate {
if (chlo.GetStringPiece(kALPN, &alpn_value)) {
alpn_ = std::string(alpn_value);
}
+ absl::string_view sni;
+ if (chlo.GetStringPiece(quic::kSNI, &sni)) {
+ sni_ = std::string(sni);
+ }
if (version == LegacyVersionForEncapsulation().transport_version) {
absl::string_view qlve_value;
if (chlo.GetStringPiece(kQLVE, &qlve_value)) {
@@ -212,18 +215,21 @@ class ChloAlpnExtractor : public ChloExtractor::Delegate {
std::string&& ConsumeAlpn() { return std::move(alpn_); }
+ std::string&& ConsumeSni() { return std::move(sni_); }
+
std::string&& ConsumeLegacyVersionEncapsulationInnerPacket() {
return std::move(legacy_version_encapsulation_inner_packet_);
}
private:
std::string alpn_;
+ std::string sni_;
std::string legacy_version_encapsulation_inner_packet_;
};
bool MaybeHandleLegacyVersionEncapsulation(
QuicDispatcher* dispatcher,
- ChloAlpnExtractor* alpn_extractor,
+ ChloAlpnSniExtractor* alpn_extractor,
const ReceivedPacketInfo& packet_info) {
std::string legacy_version_encapsulation_inner_packet =
alpn_extractor->ConsumeLegacyVersionEncapsulationInnerPacket();
@@ -265,9 +271,10 @@ bool MaybeHandleLegacyVersionEncapsulation(
}
if (legacy_version_encapsulation_inner_packet.length() >=
packet_info.packet.length()) {
- QUIC_BUG << "Inner packet cannot be larger than outer "
- << legacy_version_encapsulation_inner_packet.length() << " vs "
- << packet_info.packet.length();
+ QUIC_BUG(quic_bug_10287_2)
+ << "Inner packet cannot be larger than outer "
+ << legacy_version_encapsulation_inner_packet.length() << " vs "
+ << packet_info.packet.length();
return false;
}
@@ -327,7 +334,7 @@ QuicDispatcher::QuicDispatcher(
if (use_reference_counted_session_map_) {
QUIC_RESTART_FLAG_COUNT(quic_use_reference_counted_sesssion_map);
}
- QUIC_BUG_IF(GetSupportedVersions().empty())
+ QUIC_BUG_IF(quic_bug_12724_1, GetSupportedVersions().empty())
<< "Trying to create dispatcher without any supported versions";
QUIC_DLOG(INFO) << "Created QuicDispatcher with versions: "
<< ParsedQuicVersionVectorToString(GetSupportedVersions());
@@ -515,7 +522,7 @@ bool QuicDispatcher::MaybeDispatchPacket(
packet_info.version == LegacyVersionForEncapsulation()) {
// This packet is using the Legacy Version Encapsulation version but the
// corresponding session isn't, attempt extraction of inner packet.
- ChloAlpnExtractor alpn_extractor;
+ ChloAlpnSniExtractor alpn_extractor;
if (ChloExtractor::Extract(packet_info.packet, packet_info.version,
config_->create_session_tag_indicators(),
&alpn_extractor,
@@ -541,7 +548,7 @@ bool QuicDispatcher::MaybeDispatchPacket(
packet_info.version == LegacyVersionForEncapsulation()) {
// This packet is using the Legacy Version Encapsulation version but the
// corresponding session isn't, attempt extraction of inner packet.
- ChloAlpnExtractor alpn_extractor;
+ ChloAlpnSniExtractor alpn_extractor;
if (ChloExtractor::Extract(packet_info.packet, packet_info.version,
config_->create_session_tag_indicators(),
&alpn_extractor,
@@ -608,7 +615,7 @@ bool QuicDispatcher::MaybeDispatchPacket(
time_wait_list_manager_->ProcessPacket(
packet_info.self_address, packet_info.peer_address,
packet_info.destination_connection_id, packet_info.form,
- GetPerPacketContext());
+ packet_info.packet.length(), GetPerPacketContext());
return true;
}
@@ -629,7 +636,7 @@ bool QuicDispatcher::MaybeDispatchPacket(
time_wait_list_manager()->ProcessPacket(
packet_info.self_address, packet_info.peer_address,
packet_info.destination_connection_id, packet_info.form,
- GetPerPacketContext());
+ packet_info.packet.length(), GetPerPacketContext());
OnNewConnectionRejected();
return true;
}
@@ -676,11 +683,12 @@ void QuicDispatcher::ProcessHeader(ReceivedPacketInfo* packet_info) {
packet_info->destination_connection_id;
// Packet's connection ID is unknown. Apply the validity checks.
QuicPacketFate fate = ValidityChecks(*packet_info);
- ChloAlpnExtractor alpn_extractor;
+ ChloAlpnSniExtractor alpn_extractor;
switch (fate) {
case kFateProcess: {
if (packet_info->version.handshake_protocol == PROTOCOL_TLS1_3) {
bool has_full_tls_chlo = false;
+ std::string sni;
std::vector<std::string> alpns;
if (buffered_packets_.HasBufferedPackets(
packet_info->destination_connection_id)) {
@@ -689,7 +697,7 @@ void QuicDispatcher::ProcessHeader(ReceivedPacketInfo* packet_info) {
has_full_tls_chlo =
buffered_packets_.IngestPacketForTlsChloExtraction(
packet_info->destination_connection_id, packet_info->version,
- packet_info->packet, &alpns);
+ packet_info->packet, &alpns, &sni);
} else {
// If we do not have a BufferedPacketList for this connection ID,
// create a single-use one to check whether this packet contains a
@@ -701,10 +709,11 @@ void QuicDispatcher::ProcessHeader(ReceivedPacketInfo* packet_info) {
// This packet contains a full single-packet CHLO.
has_full_tls_chlo = true;
alpns = tls_chlo_extractor.alpns();
+ sni = tls_chlo_extractor.server_name();
}
}
if (has_full_tls_chlo) {
- ProcessChlo(alpns, packet_info);
+ ProcessChlo(alpns, sni, packet_info);
} else {
// This packet does not contain a full CHLO. It could be a 0-RTT
// packet that arrived before the CHLO (due to loss or reordering),
@@ -741,7 +750,8 @@ void QuicDispatcher::ProcessHeader(ReceivedPacketInfo* packet_info) {
break;
}
- ProcessChlo({alpn_extractor.ConsumeAlpn()}, packet_info);
+ ProcessChlo({alpn_extractor.ConsumeAlpn()}, alpn_extractor.ConsumeSni(),
+ packet_info);
} break;
case kFateTimeWait:
// Add this connection_id to the time-wait state, to safely reject
@@ -759,7 +769,8 @@ void QuicDispatcher::ProcessHeader(ReceivedPacketInfo* packet_info) {
server_connection_id));
time_wait_list_manager_->ProcessPacket(
packet_info->self_address, packet_info->peer_address,
- server_connection_id, packet_info->form, GetPerPacketContext());
+ server_connection_id, packet_info->form, packet_info->packet.length(),
+ GetPerPacketContext());
buffered_packets_.DiscardPackets(server_connection_id);
break;
@@ -801,7 +812,9 @@ QuicDispatcher::QuicPacketFate QuicDispatcher::ValidityChecks(
void QuicDispatcher::CleanUpSession(QuicConnectionId server_connection_id,
QuicConnection* connection,
- ConnectionCloseSource /*source*/) {
+ QuicErrorCode error,
+ const std::string& error_details,
+ ConnectionCloseSource source) {
write_blocked_list_.erase(connection);
QuicTimeWaitListManager::TimeWaitAction action =
QuicTimeWaitListManager::SEND_STATELESS_RESET;
@@ -810,6 +823,14 @@ 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 {
@@ -818,20 +839,22 @@ void QuicDispatcher::CleanUpSession(QuicConnectionId server_connection_id,
if (support_multiple_cid_per_connection_) {
QUIC_RESTART_FLAG_COUNT_N(
quic_dispatcher_support_multiple_cid_per_connection_v2, 1, 2);
- // This serializes a connection close termination packet with error code
- // QUIC_HANDSHAKE_FAILED and adds the connection to the time wait list.
+ // This serializes a connection close termination packet and adds the
+ // connection to the time wait list.
StatelessConnectionTerminator terminator(
server_connection_id, connection->version(), helper_.get(),
time_wait_list_manager_.get());
terminator.CloseConnection(
- QUIC_HANDSHAKE_FAILED,
- "Connection is closed by server before handshake confirmed",
+ 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().HasIetfInvariantHeader(),
connection->GetActiveServerConnectionIds());
} else {
action = QuicTimeWaitListManager::SEND_TERMINATION_PACKETS;
- // This serializes a connection close termination packet with error code
- // QUIC_HANDSHAKE_FAILED and adds the connection to the time wait list.
+ // This serializes a connection close termination packet and adds the
+ // connection to the time wait list.
StatelesslyTerminateConnection(
connection->connection_id(),
connection->version().HasIetfInvariantHeader()
@@ -839,8 +862,11 @@ void QuicDispatcher::CleanUpSession(QuicConnectionId server_connection_id,
: GOOGLE_QUIC_PACKET,
/*version_flag=*/true,
connection->version().HasLengthPrefixedConnectionIds(),
- connection->version(), QUIC_HANDSHAKE_FAILED,
- "Connection is closed by server before handshake confirmed",
+ 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",
// Although it is our intention to send termination packets, the
// |action| argument is not used by this call to
// StatelesslyTerminateConnection().
@@ -915,7 +941,7 @@ void QuicDispatcher::DeleteSessions() {
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(quic_bug_12724_2)
<< "QuicConnection was in WriteBlockedList before destruction "
<< session->connection()->connection_id();
}
@@ -926,7 +952,7 @@ void QuicDispatcher::DeleteSessions() {
if (!write_blocked_list_.empty()) {
for (const std::unique_ptr<QuicSession>& session : closed_session_list_) {
if (write_blocked_list_.erase(session->connection()) != 0) {
- QUIC_BUG
+ QUIC_BUG(quic_bug_12724_3)
<< "QuicConnection was in WriteBlockedList before destruction "
<< session->connection()->connection_id();
}
@@ -1002,10 +1028,11 @@ void QuicDispatcher::OnConnectionClosed(QuicConnectionId server_connection_id,
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 << "ConnectionId " << server_connection_id
- << " does not exist in the session map. Error: "
- << QuicErrorCodeToString(error);
- QUIC_BUG << QuicStackTrace();
+ 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;
}
@@ -1024,7 +1051,7 @@ void QuicDispatcher::OnConnectionClosed(QuicConnectionId server_connection_id,
}
closed_ref_counted_session_list_.push_back(std::move(it->second));
}
- CleanUpSession(it->first, connection, source);
+ 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);
@@ -1039,10 +1066,11 @@ void QuicDispatcher::OnConnectionClosed(QuicConnectionId server_connection_id,
} else {
auto it = session_map_.find(server_connection_id);
if (it == session_map_.end()) {
- QUIC_BUG << "ConnectionId " << server_connection_id
- << " does not exist in the session map. Error: "
- << QuicErrorCodeToString(error);
- QUIC_BUG << QuicStackTrace();
+ 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;
}
@@ -1061,7 +1089,7 @@ void QuicDispatcher::OnConnectionClosed(QuicConnectionId server_connection_id,
}
closed_session_list_.push_back(std::move(it->second));
}
- CleanUpSession(it->first, connection, source);
+ CleanUpSession(it->first, connection, error, error_details, source);
session_map_.erase(it);
}
}
@@ -1071,7 +1099,7 @@ void QuicDispatcher::OnWriteBlocked(
if (!blocked_writer->IsWriterBlocked()) {
// It is a programming error if this ever happens. When we are sure it is
// not happening, replace it with a QUICHE_DCHECK.
- QUIC_BUG
+ QUIC_BUG(quic_bug_12724_4)
<< "Tried to add writer into blocked list when it shouldn't be added";
// Return without adding the connection to the blocked list, to avoid
// infinite loops in OnCanWrite.
@@ -1092,10 +1120,10 @@ void QuicDispatcher::OnNewConnectionIdSent(
QUICHE_DCHECK(support_multiple_cid_per_connection_);
auto it = reference_counted_session_map_.find(server_connection_id);
if (it == reference_counted_session_map_.end()) {
- QUIC_BUG << "Couldn't locate the session that issues the connection ID in "
- "reference_counted_session_map_. server_connection_id:"
- << server_connection_id
- << " new_connection_id: " << new_connection_id;
+ QUIC_BUG(quic_bug_10287_7)
+ << "Couldn't locate the session that issues the connection ID in "
+ "reference_counted_session_map_. server_connection_id:"
+ << server_connection_id << " new_connection_id: " << new_connection_id;
return;
}
auto insertion_result = reference_counted_session_map_.insert(
@@ -1151,6 +1179,9 @@ void QuicDispatcher::StatelesslyTerminateConnection(
terminator.CloseConnection(
error_code, error_details, format != GOOGLE_QUIC_PACKET,
/*active_connection_ids=*/{server_connection_id});
+ QUIC_CODE_COUNT(quic_dispatcher_generated_connection_close);
+ QuicSession::RecordConnectionCloseAtServer(
+ error_code, ConnectionCloseSource::FROM_SELF);
return;
}
@@ -1209,9 +1240,10 @@ void QuicDispatcher::ProcessBufferedChlos(size_t max_connections_to_create) {
server_connection_id = MaybeReplaceServerConnectionId(server_connection_id,
packet_list.version);
std::string alpn = SelectAlpn(packet_list.alpns);
- std::unique_ptr<QuicSession> session = CreateQuicSession(
- server_connection_id, packets.front().self_address,
- packets.front().peer_address, alpn, packet_list.version);
+ std::unique_ptr<QuicSession> session =
+ CreateQuicSession(server_connection_id, packets.front().self_address,
+ packets.front().peer_address, alpn,
+ packet_list.version, packet_list.sni);
if (original_connection_id != server_connection_id) {
session->connection()->SetOriginalDestinationConnectionId(
original_connection_id);
@@ -1223,7 +1255,7 @@ void QuicDispatcher::ProcessBufferedChlos(size_t max_connections_to_create) {
std::make_pair(server_connection_id,
std::shared_ptr<QuicSession>(std::move(session))));
if (!insertion_result.second) {
- QUIC_BUG
+ QUIC_BUG(quic_bug_12724_5)
<< "Tried to add a session to session_map with existing connection "
"id: "
<< server_connection_id;
@@ -1234,7 +1266,7 @@ void QuicDispatcher::ProcessBufferedChlos(size_t max_connections_to_create) {
} else {
auto insertion_result = session_map_.insert(
std::make_pair(server_connection_id, std::move(session)));
- QUIC_BUG_IF(!insertion_result.second)
+ QUIC_BUG_IF(quic_bug_12724_6, !insertion_result.second)
<< "Tried to add a session to session_map with existing connection "
"id: "
<< server_connection_id;
@@ -1283,13 +1315,14 @@ void QuicDispatcher::BufferEarlyPacket(const ReceivedPacketInfo& packet_info) {
packet_info.destination_connection_id,
packet_info.form != GOOGLE_QUIC_PACKET, packet_info.packet,
packet_info.self_address, packet_info.peer_address, /*is_chlo=*/false,
- /*alpns=*/{}, packet_info.version);
+ /*alpns=*/{}, /*sni=*/absl::string_view(), packet_info.version);
if (rs != EnqueuePacketResult::SUCCESS) {
OnBufferPacketFailure(rs, packet_info.destination_connection_id);
}
}
void QuicDispatcher::ProcessChlo(const std::vector<std::string>& alpns,
+ absl::string_view sni,
ReceivedPacketInfo* packet_info) {
if (!buffered_packets_.HasBufferedPackets(
packet_info->destination_connection_id) &&
@@ -1299,13 +1332,13 @@ void QuicDispatcher::ProcessChlo(const std::vector<std::string>& alpns,
if (GetQuicFlag(FLAGS_quic_allow_chlo_buffering) &&
new_sessions_allowed_per_event_loop_ <= 0) {
// Can't create new session any more. Wait till next event loop.
- QUIC_BUG_IF(buffered_packets_.HasChloForConnection(
- packet_info->destination_connection_id));
+ QUIC_BUG_IF(quic_bug_12724_7, buffered_packets_.HasChloForConnection(
+ packet_info->destination_connection_id));
EnqueuePacketResult rs = buffered_packets_.EnqueuePacket(
packet_info->destination_connection_id,
packet_info->form != GOOGLE_QUIC_PACKET, packet_info->packet,
packet_info->self_address, packet_info->peer_address,
- /*is_chlo=*/true, alpns, packet_info->version);
+ /*is_chlo=*/true, alpns, sni, packet_info->version);
if (rs != EnqueuePacketResult::SUCCESS) {
OnBufferPacketFailure(rs, packet_info->destination_connection_id);
}
@@ -1320,12 +1353,13 @@ void QuicDispatcher::ProcessChlo(const std::vector<std::string>& alpns,
std::string alpn = SelectAlpn(alpns);
std::unique_ptr<QuicSession> session = CreateQuicSession(
packet_info->destination_connection_id, packet_info->self_address,
- packet_info->peer_address, alpn, packet_info->version);
+ packet_info->peer_address, alpn, packet_info->version, sni);
if (QUIC_PREDICT_FALSE(session == nullptr)) {
- QUIC_BUG << "CreateQuicSession returned nullptr for "
- << packet_info->destination_connection_id << " from "
- << packet_info->peer_address << " to " << packet_info->self_address
- << " ALPN \"" << alpn << "\" version " << packet_info->version;
+ QUIC_BUG(quic_bug_10287_8)
+ << "CreateQuicSession returned nullptr for "
+ << packet_info->destination_connection_id << " from "
+ << packet_info->peer_address << " to " << packet_info->self_address
+ << " ALPN \"" << alpn << "\" version " << packet_info->version;
return;
}
if (original_connection_id != packet_info->destination_connection_id) {
@@ -1342,9 +1376,10 @@ void QuicDispatcher::ProcessChlo(const std::vector<std::string>& alpns,
packet_info->destination_connection_id,
std::shared_ptr<QuicSession>(std::move(session.release()))));
if (!insertion_result.second) {
- QUIC_BUG << "Tried to add a session to session_map with existing "
- "connection id: "
- << packet_info->destination_connection_id;
+ 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_;
}
@@ -1352,7 +1387,7 @@ void QuicDispatcher::ProcessChlo(const std::vector<std::string>& alpns,
} else {
auto insertion_result = session_map_.insert(std::make_pair(
packet_info->destination_connection_id, std::move(session)));
- QUIC_BUG_IF(!insertion_result.second)
+ QUIC_BUG_IF(quic_bug_12724_8, !insertion_result.second)
<< "Tried to add a session to session_map with existing connection id: "
<< packet_info->destination_connection_id;
session_ptr = insertion_result.first->second.get();
@@ -1414,21 +1449,32 @@ bool QuicDispatcher::IsSupportedVersion(const ParsedQuicVersion version) {
void QuicDispatcher::MaybeResetPacketsWithNoVersion(
const ReceivedPacketInfo& packet_info) {
QUICHE_DCHECK(!packet_info.version_flag);
- const size_t MinValidPacketLength =
- kPacketHeaderTypeSize + expected_server_connection_id_length_ +
- PACKET_1BYTE_PACKET_NUMBER + /*payload size=*/1 + /*tag size=*/12;
- if (packet_info.packet.length() < MinValidPacketLength) {
- // The packet size is too small.
- QUIC_CODE_COUNT(drop_too_small_packets);
- return;
+ if (GetQuicReloadableFlag(quic_fix_stateless_reset) &&
+ packet_info.form != GOOGLE_QUIC_PACKET) {
+ // Drop IETF packets smaller than the minimal stateless reset length.
+ if (packet_info.packet.length() <=
+ QuicFramer::GetMinStatelessResetPacketLength()) {
+ QUIC_CODE_COUNT(quic_drop_too_small_short_header_packets);
+ return;
+ }
+ } else {
+ const size_t MinValidPacketLength =
+ kPacketHeaderTypeSize + expected_server_connection_id_length_ +
+ PACKET_1BYTE_PACKET_NUMBER + /*payload size=*/1 + /*tag size=*/12;
+ if (packet_info.packet.length() < MinValidPacketLength) {
+ // The packet size is too small.
+ QUIC_CODE_COUNT(drop_too_small_packets);
+ return;
+ }
+ // TODO(fayang): Consider rate limiting reset packets if reset packet size >
+ // packet_length.
}
- // TODO(fayang): Consider rate limiting reset packets if reset packet size >
- // packet_length.
time_wait_list_manager()->SendPublicReset(
packet_info.self_address, packet_info.peer_address,
packet_info.destination_connection_id,
- packet_info.form != GOOGLE_QUIC_PACKET, GetPerPacketContext());
+ packet_info.form != GOOGLE_QUIC_PACKET, packet_info.packet.length(),
+ GetPerPacketContext());
}
size_t QuicDispatcher::NumSessions() const {
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 4245a5df7fd..81749543d4d 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
@@ -180,7 +180,8 @@ class QUIC_NO_EXPORT QuicDispatcher
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
absl::string_view alpn,
- const ParsedQuicVersion& version) = 0;
+ const ParsedQuicVersion& version,
+ absl::string_view sni) = 0;
// Tries to validate and dispatch packet based on available information.
// Returns true if packet is dropped or successfully dispatched (e.g.,
@@ -242,6 +243,7 @@ class QUIC_NO_EXPORT QuicDispatcher
// Called when |packet_info| is a CHLO packet. Creates a new connection and
// delivers any buffered packets for that connection id.
void ProcessChlo(const std::vector<std::string>& alpns,
+ absl::string_view sni,
ReceivedPacketInfo* packet_info);
// Return true if dispatcher wants to destroy session outside of
@@ -305,6 +307,8 @@ class QUIC_NO_EXPORT QuicDispatcher
// from the map after that.
void CleanUpSession(QuicConnectionId server_connection_id,
QuicConnection* connection,
+ QuicErrorCode error,
+ const std::string& error_details,
ConnectionCloseSource source);
// Called to terminate a connection statelessly. Depending on |format|, either
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 3f2f8cc2bb3..3df8a76965d 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
@@ -139,7 +139,8 @@ class TestDispatcher : public QuicDispatcher {
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
absl::string_view alpn,
- const quic::ParsedQuicVersion& version),
+ const quic::ParsedQuicVersion& version,
+ absl::string_view sni),
(override));
MOCK_METHOD(bool,
@@ -466,7 +467,7 @@ class QuicDispatcherTestBase : public QuicTestWithParam<ParsedQuicVersion> {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
EXPECT_CALL(*dispatcher_,
CreateQuicSession(connection_id, _, client_address,
- Eq(ExpectedAlpnForVersion(version)), _))
+ Eq(ExpectedAlpnForVersion(version)), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, connection_id, client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
@@ -487,7 +488,7 @@ class QuicDispatcherTestBase : public QuicTestWithParam<ParsedQuicVersion> {
QuicConnectionId connection_id = TestConnectionId(++connection_id_);
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
EXPECT_CALL(*dispatcher_,
- CreateQuicSession(connection_id, _, client_address, _, _))
+ CreateQuicSession(connection_id, _, client_address, _, _, _))
.Times(0);
ProcessFirstFlight(version, client_address, connection_id);
}
@@ -535,7 +536,7 @@ TEST_P(QuicDispatcherTestAllVersions, TlsClientHelloCreatesSession) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(1), _, client_address,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(1), client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
@@ -586,7 +587,7 @@ void QuicDispatcherTestBase::TestTlsMultiPacketClientHello(
// Processing the second packet should create the new session.
EXPECT_CALL(*dispatcher_,
CreateQuicSession(server_connection_id, _, client_address,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, TestHostname()))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, server_connection_id, client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
@@ -653,7 +654,7 @@ TEST_P(QuicDispatcherTestAllVersions, LegacyVersionEncapsulation) {
// Processing the packet should create a new session.
EXPECT_CALL(*dispatcher_,
CreateQuicSession(server_connection_id, _, client_address,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, server_connection_id, client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
@@ -678,7 +679,7 @@ TEST_P(QuicDispatcherTestAllVersions, ProcessPackets) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(1), _, client_address,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, TestHostname()))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(1), client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
@@ -695,7 +696,7 @@ TEST_P(QuicDispatcherTestAllVersions, ProcessPackets) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(2), _, client_address,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, TestHostname()))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(2), client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
@@ -725,7 +726,7 @@ TEST_P(QuicDispatcherTestAllVersions, DispatcherDoesNotRejectPacketNumberZero) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(1), _, client_address,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(1), client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
@@ -752,7 +753,7 @@ TEST_P(QuicDispatcherTestOneVersion, StatelessVersionNegotiation) {
CreateTimeWaitListManager();
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
SendVersionNegotiationPacket(TestConnectionId(1), _, _, _, _, _, _, _))
@@ -767,7 +768,7 @@ TEST_P(QuicDispatcherTestOneVersion,
CreateTimeWaitListManager();
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_,
SendVersionNegotiationPacket(connection_id, _, _, _, _, _, _, _))
.Times(1);
@@ -780,7 +781,7 @@ TEST_P(QuicDispatcherTestOneVersion,
CreateTimeWaitListManager();
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_,
SendVersionNegotiationPacket(
TestConnectionId(1), TestConnectionId(2), _, _, _, _, _, _))
@@ -793,7 +794,7 @@ TEST_P(QuicDispatcherTestOneVersion, NoVersionNegotiationWithSmallPacket) {
CreateTimeWaitListManager();
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_,
SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
.Times(0);
@@ -817,7 +818,7 @@ TEST_P(QuicDispatcherTestOneVersion,
CreateTimeWaitListManager();
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_,
SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
.Times(1);
@@ -836,7 +837,7 @@ TEST_P(QuicDispatcherTestAllVersions, Shutdown) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
EXPECT_CALL(*dispatcher_,
- CreateQuicSession(_, _, client_address, Eq(ExpectedAlpn()), _))
+ CreateQuicSession(_, _, client_address, Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(1), client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
@@ -865,7 +866,7 @@ TEST_P(QuicDispatcherTestAllVersions, TimeWaitListManager) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId connection_id = TestConnectionId(1);
EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, _, client_address,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, connection_id, client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
@@ -891,7 +892,7 @@ TEST_P(QuicDispatcherTestAllVersions, TimeWaitListManager) {
// Dispatcher forwards subsequent packets for this connection_id to the time
// wait list manager.
EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, _, connection_id, _, _))
+ ProcessPacket(_, _, connection_id, _, _, _))
.Times(1);
EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _))
.Times(0);
@@ -905,13 +906,13 @@ TEST_P(QuicDispatcherTestAllVersions, NoVersionPacketToTimeWaitListManager) {
QuicConnectionId connection_id = TestConnectionId(1);
// Dispatcher forwards all packets for this connection_id to the time wait
// list manager.
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, _, connection_id, _, _))
+ ProcessPacket(_, _, connection_id, _, _, _))
.Times(0);
EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _))
.Times(0);
- EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
+ EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _, _))
.Times(1);
ProcessPacket(client_address, connection_id, /*has_version_flag=*/false,
"data");
@@ -922,19 +923,20 @@ TEST_P(QuicDispatcherTestAllVersions,
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
CreateTimeWaitListManager();
- char short_packet[22] = {0x70, 0xa7, 0x02, 0x6b};
- QuicReceivedPacket packet(short_packet, 22, QuicTime::Zero());
+ char short_packet[21] = {0x70, 0xa7, 0x02, 0x6b};
+ QuicReceivedPacket packet(short_packet, 21, QuicTime::Zero());
char valid_size_packet[23] = {0x70, 0xa7, 0x02, 0x6c};
QuicReceivedPacket packet2(valid_size_packet, 23, QuicTime::Zero());
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
- EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
+ EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _, _))
+ .Times(0);
EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _))
.Times(0);
// Verify small packet is silently dropped.
- EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
+ EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _, _))
.Times(0);
dispatcher_->ProcessPacket(server_address_, client_address, packet);
- EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
+ EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _, _))
.Times(1);
dispatcher_->ProcessPacket(server_address_, client_address, packet2);
}
@@ -954,7 +956,7 @@ TEST_P(QuicDispatcherTestAllVersions, LongConnectionIdLengthReplaced) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(fixed_connection_id, _, client_address,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, fixed_connection_id, client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
@@ -991,7 +993,7 @@ TEST_P(QuicDispatcherTestAllVersions, InvalidShortConnectionIdLengthReplaced) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(fixed_connection_id, _, client_address,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, fixed_connection_id, client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
@@ -1022,7 +1024,7 @@ TEST_P(QuicDispatcherTestAllVersions, MixGoodAndBadConnectionIdLengthPackets) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(1), _, client_address,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(1), client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
@@ -1039,7 +1041,7 @@ TEST_P(QuicDispatcherTestAllVersions, MixGoodAndBadConnectionIdLengthPackets) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(fixed_connection_id, _, client_address,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, fixed_connection_id, client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
@@ -1070,10 +1072,11 @@ TEST_P(QuicDispatcherTestAllVersions, ProcessPacketWithZeroPort) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 0);
// dispatcher_ should drop this packet.
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(TestConnectionId(1), _, client_address, _, _))
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(TestConnectionId(1), _,
+ client_address, _, _, _))
+ .Times(0);
+ EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _, _))
.Times(0);
- EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _))
.Times(0);
ProcessPacket(client_address, TestConnectionId(1), /*has_version_flag=*/true,
@@ -1090,8 +1093,9 @@ TEST_P(QuicDispatcherTestAllVersions,
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
// dispatcher_ should drop this packet.
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
- EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
+ EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _, _))
+ .Times(0);
EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _))
.Times(0);
ProcessFirstFlight(client_address, EmptyQuicConnectionId());
@@ -1105,7 +1109,7 @@ void QuicDispatcherTestBase::
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_,
SendVersionNegotiationPacket(
server_connection_id, client_connection_id,
@@ -1160,7 +1164,7 @@ TEST_P(QuicDispatcherTestOneVersion,
0xC0, 0xFF, 0x00, 0x00, 28, /*destination connection ID length*/ 0x08};
QuicReceivedPacket received_packet(packet, ABSL_ARRAYSIZE(packet),
QuicTime::Zero());
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
SendVersionNegotiationPacket(_, _, /*ietf_quic=*/true,
@@ -1177,7 +1181,7 @@ TEST_P(QuicDispatcherTestOneVersion,
0xC0, 0xFF, 0x00, 0x00, 27, /*destination connection ID length*/ 0x08};
QuicReceivedPacket received_packet(packet, ABSL_ARRAYSIZE(packet),
QuicTime::Zero());
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
SendVersionNegotiationPacket(_, _, /*ietf_quic=*/true,
@@ -1194,7 +1198,7 @@ TEST_P(QuicDispatcherTestOneVersion,
0xC0, 0xFF, 0x00, 0x00, 25, /*destination connection ID length*/ 0x08};
QuicReceivedPacket received_packet(packet, ABSL_ARRAYSIZE(packet),
QuicTime::Zero());
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
SendVersionNegotiationPacket(_, _, /*ietf_quic=*/true,
@@ -1211,7 +1215,7 @@ TEST_P(QuicDispatcherTestOneVersion,
0xC0, 'T', '0', '5', '0', /*destination connection ID length*/ 0x08};
QuicReceivedPacket received_packet(packet, ABSL_ARRAYSIZE(packet),
QuicTime::Zero());
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
SendVersionNegotiationPacket(_, _, /*ietf_quic=*/true,
@@ -1228,7 +1232,7 @@ TEST_P(QuicDispatcherTestOneVersion,
0xC0, 'Q', '0', '4', '9', /*destination connection ID length*/ 0x08};
QuicReceivedPacket received_packet(packet, ABSL_ARRAYSIZE(packet),
QuicTime::Zero());
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
SendVersionNegotiationPacket(_, _, /*ietf_quic=*/true,
@@ -1245,7 +1249,7 @@ TEST_P(QuicDispatcherTestOneVersion,
0xC0, 'Q', '0', '4', '8', /*connection ID length byte*/ 0x50};
QuicReceivedPacket received_packet(packet, ABSL_ARRAYSIZE(packet),
QuicTime::Zero());
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
SendVersionNegotiationPacket(_, _, /*ietf_quic=*/true,
@@ -1262,7 +1266,7 @@ TEST_P(QuicDispatcherTestOneVersion,
0xC0, 'Q', '0', '4', '7', /*connection ID length byte*/ 0x50};
QuicReceivedPacket received_packet(packet, ABSL_ARRAYSIZE(packet),
QuicTime::Zero());
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
SendVersionNegotiationPacket(_, _, /*ietf_quic=*/true,
@@ -1279,7 +1283,7 @@ TEST_P(QuicDispatcherTestOneVersion,
0xC0, 'Q', '0', '4', '5', /*connection ID length byte*/ 0x50};
QuicReceivedPacket received_packet(packet, ABSL_ARRAYSIZE(packet),
QuicTime::Zero());
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
SendVersionNegotiationPacket(_, _, /*ietf_quic=*/true,
@@ -1296,7 +1300,7 @@ TEST_P(QuicDispatcherTestOneVersion,
0xFF, 'Q', '0', '4', '4', /*connection ID length byte*/ 0x50};
QuicReceivedPacket received_packet44(
packet44, kMinPacketSizeForVersionNegotiation, QuicTime::Zero());
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
SendVersionNegotiationPacket(_, _, /*ietf_quic=*/true,
@@ -1330,7 +1334,7 @@ TEST_P(QuicDispatcherTestOneVersion, VersionNegotiationProbe) {
server_connection_id, client_connection_id,
/*ietf_quic=*/true, /*use_length_prefix=*/true, _, _, _, _))
.Times(1);
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
}
@@ -1379,7 +1383,7 @@ TEST_P(QuicDispatcherTestOneVersion, VersionNegotiationProbeEndToEnd) {
QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
std::unique_ptr<QuicReceivedPacket> received_packet(
ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
@@ -1430,7 +1434,7 @@ TEST_P(QuicDispatcherTestOneVersion, AndroidConformanceTest) {
sizeof(packet), false);
std::unique_ptr<QuicReceivedPacket> received_packet(
ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
@@ -1481,7 +1485,7 @@ TEST_P(QuicDispatcherTestOneVersion, AndroidConformanceTestOld) {
sizeof(packet), false);
std::unique_ptr<QuicReceivedPacket> received_packet(
ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
@@ -1503,7 +1507,7 @@ TEST_P(QuicDispatcherTestAllVersions, DoNotProcessSmallPacket) {
CreateTimeWaitListManager();
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_, SendPacket(_, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _))
.Times(0);
@@ -1565,7 +1569,7 @@ TEST_P(QuicDispatcherTestAllVersions, StopAcceptingNewConnections) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(1), _, client_address,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(1), client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
@@ -1583,7 +1587,7 @@ TEST_P(QuicDispatcherTestAllVersions, StopAcceptingNewConnections) {
// No more new connections afterwards.
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(2), _, client_address,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.Times(0u);
ProcessFirstFlight(client_address, TestConnectionId(2));
@@ -1604,7 +1608,7 @@ TEST_P(QuicDispatcherTestAllVersions, StartAcceptingNewConnections) {
// No more new connections afterwards.
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(2), _, client_address,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.Times(0u);
ProcessFirstFlight(client_address, TestConnectionId(2));
@@ -1613,7 +1617,7 @@ TEST_P(QuicDispatcherTestAllVersions, StartAcceptingNewConnections) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(1), _, client_address,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(1), client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
@@ -1654,8 +1658,9 @@ TEST_P(QuicDispatcherTestStrayPacketConnectionId,
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId connection_id = TestConnectionId(1);
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _)).Times(0);
- EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
+ EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _, _))
+ .Times(0);
EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _))
.Times(0);
@@ -1694,8 +1699,8 @@ class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTestBase {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(_, _, client_address, Eq(ExpectedAlpn()), _))
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, client_address,
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(1), client_address,
&helper_, &alarm_factory_, &crypto_config_,
@@ -1710,8 +1715,8 @@ class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTestBase {
ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
ProcessFirstFlight(client_address, TestConnectionId(1));
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(_, _, client_address, Eq(ExpectedAlpn()), _))
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, client_address,
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(2), client_address,
&helper_, &alarm_factory_, &crypto_config_,
@@ -1981,8 +1986,8 @@ class QuicDispatcherSupportMultipleConnectionIdPerConnectionTest
}
void AddConnection1() {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(_, _, client_address, Eq(ExpectedAlpn()), _))
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, client_address,
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(1), client_address,
&helper_, &alarm_factory_, &crypto_config_,
@@ -2000,8 +2005,8 @@ class QuicDispatcherSupportMultipleConnectionIdPerConnectionTest
void AddConnection2() {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 2);
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(_, _, client_address, Eq(ExpectedAlpn()), _))
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, client_address,
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(2), client_address,
&helper_, &alarm_factory_, &crypto_config_,
@@ -2221,8 +2226,9 @@ TEST_P(BufferedPacketStoreTest, ProcessNonChloPacketBeforeChlo) {
// When CHLO arrives, a new session should be created, and all packets
// buffered should be delivered to the session.
- EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, _, client_addr_,
- Eq(ExpectedAlpn()), _))
+ EXPECT_CALL(*dispatcher_,
+ CreateQuicSession(conn_id, _, client_addr_, Eq(ExpectedAlpn()), _,
+ TestHostname()))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, conn_id, client_addr_, &mock_helper_,
&mock_alarm_factory_, &crypto_config_,
@@ -2257,7 +2263,7 @@ TEST_P(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
// When CHLO arrives, a new session should be created, and all packets
// buffered should be delivered to the session.
EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, _, client_addr_,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, conn_id, client_addr_, &mock_helper_,
&mock_alarm_factory_, &crypto_config_,
@@ -2309,7 +2315,7 @@ TEST_P(BufferedPacketStoreTest,
ReceivedPacketInfoConnectionIdEquals(conn_id)));
}
EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, _, client_address,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
&mock_alarm_factory_, &crypto_config_,
@@ -2337,7 +2343,7 @@ TEST_P(BufferedPacketStoreTest, DeliverEmptyPackets) {
EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(
ReceivedPacketInfoConnectionIdEquals(conn_id)));
EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, _, client_addr_,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, conn_id, client_addr_, &mock_helper_,
&mock_alarm_factory_, &crypto_config_,
@@ -2357,7 +2363,7 @@ TEST_P(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) {
// When CHLO arrives, a new session should be created, and all packets
// buffered should be delivered to the session.
EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, _, client_addr_,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.Times(1) // Only triggered by 1st CHLO.
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, conn_id, client_addr_, &mock_helper_,
@@ -2404,7 +2410,7 @@ TEST_P(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) {
// New arrived CHLO will be dropped because this connection is in time wait
// list.
ASSERT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
- EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, conn_id, _, _));
+ EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, conn_id, _, _, _));
ProcessFirstFlight(conn_id);
}
@@ -2426,7 +2432,7 @@ TEST_P(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
if (conn_id <= kMaxNumSessionsToCreate) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(conn_id), _, client_addr_,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, TestHostname()))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(conn_id),
client_addr_, &mock_helper_, &mock_alarm_factory_,
@@ -2461,7 +2467,7 @@ TEST_P(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
++conn_id) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(conn_id), _, client_addr_,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, TestHostname()))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(conn_id), client_addr_,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
@@ -2477,7 +2483,7 @@ TEST_P(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
}
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(kNumCHLOs), _, client_addr_,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.Times(0);
while (store->HasChlosBuffered()) {
@@ -2497,7 +2503,7 @@ TEST_P(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
if (conn_id <= kMaxNumSessionsToCreate) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(conn_id), _, client_addr_,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(conn_id),
client_addr_, &mock_helper_, &mock_alarm_factory_,
@@ -2524,7 +2530,7 @@ TEST_P(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
// Reset counter and process buffered CHLO.
EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection, _, client_addr_,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, last_connection, client_addr_,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
@@ -2550,7 +2556,7 @@ TEST_P(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
if (conn_id <= kMaxNumSessionsToCreate) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(conn_id), _, client_addr_,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(conn_id),
client_addr_, &mock_helper_, &mock_alarm_factory_,
@@ -2579,7 +2585,7 @@ TEST_P(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
// Reset counter and process buffered CHLO.
EXPECT_CALL(*dispatcher_,
CreateQuicSession(last_connection_id, _, client_addr_,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, last_connection_id, client_addr_,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
@@ -2615,7 +2621,7 @@ TEST_P(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) {
if (conn_id <= kMaxNumSessionsToCreate + 1) {
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(conn_id), _, client_addr_,
- Eq(ExpectedAlpn()), _))
+ Eq(ExpectedAlpn()), _, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(conn_id),
client_addr_, &mock_helper_, &mock_alarm_factory_,
@@ -2657,7 +2663,7 @@ TEST_P(BufferedPacketStoreTest, ProcessBufferedChloWithDifferentVersion) {
EXPECT_CALL(
*dispatcher_,
CreateQuicSession(TestConnectionId(conn_id), _, client_addr_,
- Eq(ExpectedAlpnForVersion(version)), version))
+ Eq(ExpectedAlpnForVersion(version)), version, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(conn_id),
client_addr_, &mock_helper_, &mock_alarm_factory_,
@@ -2681,9 +2687,10 @@ TEST_P(BufferedPacketStoreTest, ProcessBufferedChloWithDifferentVersion) {
conn_id <= last_connection_id; ++conn_id) {
ParsedQuicVersion version =
supported_versions[(conn_id - 1) % supported_versions.size()];
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(TestConnectionId(conn_id), _, client_addr_,
- Eq(ExpectedAlpnForVersion(version)), version))
+ EXPECT_CALL(
+ *dispatcher_,
+ CreateQuicSession(TestConnectionId(conn_id), _, client_addr_,
+ Eq(ExpectedAlpnForVersion(version)), version, _))
.WillOnce(Return(ByMove(CreateSession(
dispatcher_.get(), config_, TestConnectionId(conn_id), client_addr_,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc b/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc
index dd8be33e747..e82e7cb2eab 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc
@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "quic/core/quic_error_codes.h"
+
#include <cstdint>
#include <cstring>
#include "absl/strings/str_cat.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
-#include "quic/core/quic_error_codes.h"
#include "quic/platform/api/quic_logging.h"
namespace quic {
@@ -54,6 +55,9 @@ const char* QuicRstStreamErrorCodeToString(QuicRstStreamErrorCode error) {
RETURN_STRING_LITERAL(QUIC_STREAM_ENCODER_STREAM_ERROR);
RETURN_STRING_LITERAL(QUIC_STREAM_DECODER_STREAM_ERROR);
RETURN_STRING_LITERAL(QUIC_STREAM_UNKNOWN_APPLICATION_ERROR_CODE);
+ RETURN_STRING_LITERAL(QUIC_STREAM_WEBTRANSPORT_SESSION_GONE);
+ RETURN_STRING_LITERAL(
+ QUIC_STREAM_WEBTRANSPORT_BUFFERED_STREAMS_LIMIT_EXCEEDED);
RETURN_STRING_LITERAL(QUIC_STREAM_LAST_ERROR);
}
// Return a default value so that we return this when |error| doesn't match
@@ -874,6 +878,10 @@ uint64_t RstStreamErrorCodeToIetfResetStreamErrorCode(
QuicHttpQpackErrorCode::DECODER_STREAM_ERROR);
case QUIC_STREAM_UNKNOWN_APPLICATION_ERROR_CODE:
return static_cast<uint64_t>(QuicHttp3ErrorCode::INTERNAL_ERROR);
+ case QUIC_STREAM_WEBTRANSPORT_SESSION_GONE:
+ return static_cast<uint64_t>(QuicHttp3ErrorCode::CONNECT_ERROR);
+ case QUIC_STREAM_WEBTRANSPORT_BUFFERED_STREAMS_LIMIT_EXCEEDED:
+ return static_cast<uint64_t>(QuicHttp3ErrorCode::CONNECT_ERROR);
case QUIC_STREAM_LAST_ERROR:
return static_cast<uint64_t>(QuicHttp3ErrorCode::INTERNAL_ERROR);
}
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 3a8069675f1..32816b869cf 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
@@ -103,8 +103,14 @@ enum QuicRstStreamErrorCode {
// IETF RESET_FRAME application error code not matching any HTTP/3 or QPACK
// error codes.
QUIC_STREAM_UNKNOWN_APPLICATION_ERROR_CODE = 35,
+ // WebTransport session is going away, causing all underlying streams to be
+ // reset.
+ QUIC_STREAM_WEBTRANSPORT_SESSION_GONE = 36,
+ // There is no corresponding WebTransport session to associate this stream
+ // with, and the limit for buffered streams has been exceeded.
+ QUIC_STREAM_WEBTRANSPORT_BUFFERED_STREAMS_LIMIT_EXCEEDED = 37,
// No error. Used as bound while iterating.
- QUIC_STREAM_LAST_ERROR = 36,
+ QUIC_STREAM_LAST_ERROR = 38,
};
// QuicRstStreamErrorCode is encoded as a single octet on-the-wire.
static_assert(static_cast<int>(QUIC_STREAM_LAST_ERROR) <=
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 a3bc2251327..910db544eff 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
@@ -6,21 +6,21 @@
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, false)
+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)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_avoid_too_low_probe_bw_cwnd, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_bw_startup, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_fewer_startup_round_trips, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_reset_max_bytes_delivered, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_use_bytes_delivered, true)
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_fix_bw_lo_mode, false)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_can_send_ack_frequency, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_close_connection_on_0rtt_packet_number_higher_than_1rtt, 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, 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)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_on_pto, false)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_to_bbr, false)
@@ -33,50 +33,48 @@ QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q046, false)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q050, false)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_t051, false)
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_dont_defer_sending, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_alps_client, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_alps_server, 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)
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_on_stream_reset, false)
+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_goaway_with_max_stream_id, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_parse_accept_ch_frame, true)
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_h3_datagram, false)
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)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_require_handshake_confirmation, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_goaway_with_connection_close, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_path_response, false)
+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_path, false)
+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_stateless_reset, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_stateless_reset_faster_random, false)
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, false)
+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, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_update_packet_content_returns_connected, true)
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_unify_stop_sending, true)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_use_encryption_level_context, true)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_use_write_or_buffer_data_at_level, false)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_send_quic_fallback_server_config_on_leto_error, false)
QUIC_FLAG(FLAGS_quic_restart_flag_dont_fetch_quic_private_keys_from_leto, false)
-QUIC_FLAG(FLAGS_quic_restart_flag_http2_parse_priority_update_frame, true)
QUIC_FLAG(FLAGS_quic_restart_flag_quic_dispatcher_support_multiple_cid_per_connection_v2, true)
-QUIC_FLAG(FLAGS_quic_restart_flag_quic_enable_zero_rtt_for_tls_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_tls_prefer_server_cipher_and_curve_list, true)
QUIC_FLAG(FLAGS_quic_restart_flag_quic_use_reference_counted_sesssion_map, true)
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_flow_controller.cc b/chromium/net/third_party/quiche/src/quic/core/quic_flow_controller.cc
index 01fb72ce008..88dc3edcd44 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_flow_controller.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_flow_controller.cc
@@ -91,9 +91,10 @@ bool QuicFlowController::UpdateHighestReceivedOffset(
void QuicFlowController::AddBytesSent(QuicByteCount bytes_sent) {
if (bytes_sent_ + bytes_sent > send_window_offset_) {
- QUIC_BUG << ENDPOINT << LogLabel() << " Trying to send an extra "
- << bytes_sent << " bytes, when bytes_sent = " << bytes_sent_
- << ", and send_window_offset_ = " << send_window_offset_;
+ QUIC_BUG(quic_bug_10836_1)
+ << ENDPOINT << LogLabel() << " Trying to send an extra " << bytes_sent
+ << " bytes, when bytes_sent = " << bytes_sent_
+ << ", and send_window_offset_ = " << send_window_offset_;
bytes_sent_ = send_window_offset_;
// This is an error on our side, close the connection as soon as possible.
@@ -298,8 +299,9 @@ void QuicFlowController::UpdateReceiveWindowSize(QuicStreamOffset size) {
QUIC_DVLOG(1) << ENDPOINT << "UpdateReceiveWindowSize for " << LogLabel()
<< ": " << size;
if (receive_window_size_ != receive_window_offset_) {
- QUIC_BUG << "receive_window_size_:" << receive_window_size_
- << " != receive_window_offset:" << receive_window_offset_;
+ QUIC_BUG(quic_bug_10836_2)
+ << "receive_window_size_:" << receive_window_size_
+ << " != receive_window_offset:" << receive_window_offset_;
return;
}
receive_window_size_ = size;
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 fdccef9c72f..c5de97be541 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
@@ -166,7 +166,7 @@ QuicPacketNumberLength ReadSequenceNumberLength(uint8_t flags) {
case PACKET_FLAGS_1BYTE_PACKET:
return PACKET_1BYTE_PACKET_NUMBER;
default:
- QUIC_BUG << "Unreachable case statement.";
+ QUIC_BUG(quic_bug_10850_1) << "Unreachable case statement.";
return PACKET_6BYTE_PACKET_NUMBER;
}
}
@@ -183,7 +183,7 @@ QuicPacketNumberLength ReadAckPacketNumberLength(
case PACKET_FLAGS_1BYTE_PACKET:
return PACKET_1BYTE_PACKET_NUMBER;
default:
- QUIC_BUG << "Unreachable case statement.";
+ QUIC_BUG(quic_bug_10850_2) << "Unreachable case statement.";
return PACKET_6BYTE_PACKET_NUMBER;
}
}
@@ -211,7 +211,7 @@ uint8_t LongHeaderTypeToOnWireValue(QuicLongHeaderType type) {
case VERSION_NEGOTIATION:
return 0xF0; // Value does not matter
default:
- QUIC_BUG << "Invalid long header type: " << type;
+ QUIC_BUG(quic_bug_10850_3) << "Invalid long header type: " << type;
return 0xFF;
}
}
@@ -232,7 +232,7 @@ bool GetLongHeaderType(uint8_t type, QuicLongHeaderType* long_header_type) {
*long_header_type = RETRY;
break;
default:
- QUIC_BUG << "Unreachable statement";
+ QUIC_BUG(quic_bug_10850_4) << "Unreachable statement";
*long_header_type = INVALID_PACKET_TYPE;
return false;
}
@@ -247,7 +247,8 @@ QuicPacketNumberLength GetLongHeaderPacketNumberLength(uint8_t type) {
PacketNumberSpace GetPacketNumberSpace(const QuicPacketHeader& header) {
switch (header.form) {
case GOOGLE_QUIC_PACKET:
- QUIC_BUG << "Try to get packet number space of Google QUIC packet";
+ QUIC_BUG(quic_bug_10850_5)
+ << "Try to get packet number space of Google QUIC packet";
break;
case IETF_QUIC_SHORT_HEADER_PACKET:
return APPLICATION_DATA;
@@ -262,9 +263,9 @@ PacketNumberSpace GetPacketNumberSpace(const QuicPacketHeader& header) {
case VERSION_NEGOTIATION:
case RETRY:
case INVALID_PACKET_TYPE:
- QUIC_BUG << "Try to get packet number space of long header type: "
- << QuicUtils::QuicLongHeaderTypetoString(
- header.long_packet_type);
+ QUIC_BUG(quic_bug_10850_6)
+ << "Try to get packet number space of long header type: "
+ << QuicUtils::QuicLongHeaderTypetoString(header.long_packet_type);
break;
}
}
@@ -275,7 +276,8 @@ PacketNumberSpace GetPacketNumberSpace(const QuicPacketHeader& header) {
EncryptionLevel GetEncryptionLevel(const QuicPacketHeader& header) {
switch (header.form) {
case GOOGLE_QUIC_PACKET:
- QUIC_BUG << "Cannot determine EncryptionLevel from Google QUIC header";
+ QUIC_BUG(quic_bug_10850_7)
+ << "Cannot determine EncryptionLevel from Google QUIC header";
break;
case IETF_QUIC_SHORT_HEADER_PACKET:
return ENCRYPTION_FORWARD_SECURE;
@@ -290,9 +292,9 @@ EncryptionLevel GetEncryptionLevel(const QuicPacketHeader& header) {
case VERSION_NEGOTIATION:
case RETRY:
case INVALID_PACKET_TYPE:
- QUIC_BUG << "No encryption used with type "
- << QuicUtils::QuicLongHeaderTypetoString(
- header.long_packet_type);
+ QUIC_BUG(quic_bug_10850_8)
+ << "No encryption used with type "
+ << QuicUtils::QuicLongHeaderTypetoString(header.long_packet_type);
}
}
return NUM_ENCRYPTION_LEVELS;
@@ -433,6 +435,10 @@ 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() {}
@@ -466,7 +472,7 @@ size_t QuicFramer::GetMinCryptoFrameSize(QuicStreamOffset offset,
size_t QuicFramer::GetMessageFrameSize(QuicTransportVersion version,
bool last_frame_in_packet,
QuicByteCount length) {
- QUIC_BUG_IF(!VersionSupportsMessageFrames(version))
+ QUIC_BUG_IF(quic_bug_12975_1, !VersionSupportsMessageFrames(version))
<< "Try to serialize MESSAGE frame in " << version;
return kQuicFrameTypeSize +
(last_frame_in_packet ? 0 : QuicDataWriter::GetVarInt62Len(length)) +
@@ -586,9 +592,10 @@ size_t QuicFramer::GetWindowUpdateFrameSize(
size_t QuicFramer::GetMaxStreamsFrameSize(QuicTransportVersion version,
const QuicMaxStreamsFrame& frame) {
if (!VersionHasIetfQuicFrames(version)) {
- QUIC_BUG << "In version " << version
- << ", which does not support IETF Frames, and tried to serialize "
- "MaxStreams Frame.";
+ QUIC_BUG(quic_bug_10850_9)
+ << "In version " << version
+ << ", which does not support IETF Frames, and tried to serialize "
+ "MaxStreams Frame.";
}
return kQuicFrameTypeSize +
QuicDataWriter::GetVarInt62Len(frame.stream_count);
@@ -599,9 +606,10 @@ size_t QuicFramer::GetStreamsBlockedFrameSize(
QuicTransportVersion version,
const QuicStreamsBlockedFrame& frame) {
if (!VersionHasIetfQuicFrames(version)) {
- QUIC_BUG << "In version " << version
- << ", which does not support IETF frames, and tried to serialize "
- "StreamsBlocked Frame.";
+ QUIC_BUG(quic_bug_10850_10)
+ << "In version " << version
+ << ", which does not support IETF frames, and tried to serialize "
+ "StreamsBlocked Frame.";
}
return kQuicFrameTypeSize +
@@ -722,7 +730,7 @@ size_t QuicFramer::GetStreamIdSize(QuicStreamId stream_id) {
return i;
}
}
- QUIC_BUG << "Failed to determine StreamIDSize.";
+ QUIC_BUG(quic_bug_10850_11) << "Failed to determine StreamIDSize.";
return 4;
}
@@ -740,7 +748,7 @@ size_t QuicFramer::GetStreamOffsetSize(QuicStreamOffset offset) {
return i;
}
}
- QUIC_BUG << "Failed to determine StreamOffsetSize.";
+ QUIC_BUG(quic_bug_10850_12) << "Failed to determine StreamOffsetSize.";
return 8;
}
@@ -796,10 +804,11 @@ size_t QuicFramer::GetSerializedFrameLength(
QuicPacketNumberLength packet_number_length) {
// Prevent a rare crash reported in b/19458523.
if (frame.type == ACK_FRAME && frame.ack_frame == nullptr) {
- QUIC_BUG << "Cannot compute the length of a null ack frame. free_bytes:"
- << free_bytes << " first_frame:" << first_frame
- << " last_frame:" << last_frame
- << " seq num length:" << packet_number_length;
+ QUIC_BUG(quic_bug_10850_13)
+ << "Cannot compute the length of a null ack frame. free_bytes:"
+ << free_bytes << " first_frame:" << first_frame
+ << " last_frame:" << last_frame
+ << " seq num length:" << packet_number_length;
set_error(QUIC_INTERNAL_ERROR);
visitor_->OnError(this);
return 0;
@@ -862,7 +871,7 @@ bool QuicFramer::WriteIetfLongHeaderLength(const QuicPacketHeader& header,
writer->length() - length_field_offset <
kQuicDefaultLongHeaderLengthLength) {
set_detailed_error("Invalid length_field_offset.");
- QUIC_BUG << "Invalid length_field_offset.";
+ QUIC_BUG(quic_bug_10850_14) << "Invalid length_field_offset.";
return false;
}
size_t length_to_write = writer->length() - length_field_offset -
@@ -875,7 +884,7 @@ bool QuicFramer::WriteIetfLongHeaderLength(const QuicPacketHeader& header,
if (!length_writer.WriteVarInt62(length_to_write,
kQuicDefaultLongHeaderLengthLength)) {
set_detailed_error("Failed to overwrite long header length.");
- QUIC_BUG << "Failed to overwrite long header length.";
+ QUIC_BUG(quic_bug_10850_15) << "Failed to overwrite long header length.";
return false;
}
return true;
@@ -886,13 +895,14 @@ size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header,
char* buffer,
size_t packet_length,
EncryptionLevel level) {
- QUIC_BUG_IF(header.version_flag && version().HasIetfInvariantHeader() &&
- header.long_packet_type == RETRY && !frames.empty())
+ QUIC_BUG_IF(quic_bug_12975_2,
+ header.version_flag && version().HasIetfInvariantHeader() &&
+ header.long_packet_type == RETRY && !frames.empty())
<< "IETF RETRY packets cannot contain frames " << header;
QuicDataWriter writer(packet_length, buffer);
size_t length_field_offset = 0;
if (!AppendPacketHeader(header, &writer, &length_field_offset)) {
- QUIC_BUG << "AppendPacketHeader failed";
+ QUIC_BUG(quic_bug_10850_16) << "AppendPacketHeader failed";
return 0;
}
@@ -912,35 +922,37 @@ size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header,
// Determine if we should write stream frame length in header.
const bool last_frame_in_packet = i == frames.size() - 1;
if (!AppendTypeByte(frame, last_frame_in_packet, &writer)) {
- QUIC_BUG << "AppendTypeByte failed";
+ QUIC_BUG(quic_bug_10850_17) << "AppendTypeByte failed";
return 0;
}
switch (frame.type) {
case PADDING_FRAME:
if (!AppendPaddingFrame(frame.padding_frame, &writer)) {
- QUIC_BUG << "AppendPaddingFrame of "
- << frame.padding_frame.num_padding_bytes << " failed";
+ QUIC_BUG(quic_bug_10850_18)
+ << "AppendPaddingFrame of "
+ << frame.padding_frame.num_padding_bytes << " failed";
return 0;
}
break;
case STREAM_FRAME:
if (!AppendStreamFrame(frame.stream_frame, last_frame_in_packet,
&writer)) {
- QUIC_BUG << "AppendStreamFrame failed";
+ QUIC_BUG(quic_bug_10850_19) << "AppendStreamFrame failed";
return 0;
}
break;
case ACK_FRAME:
if (!AppendAckFrameAndTypeByte(*frame.ack_frame, &writer)) {
- QUIC_BUG << "AppendAckFrameAndTypeByte failed: " << detailed_error_;
+ QUIC_BUG(quic_bug_10850_20)
+ << "AppendAckFrameAndTypeByte failed: " << detailed_error_;
return 0;
}
break;
case STOP_WAITING_FRAME:
if (!AppendStopWaitingFrame(header, frame.stop_waiting_frame,
&writer)) {
- QUIC_BUG << "AppendStopWaitingFrame failed";
+ QUIC_BUG(quic_bug_10850_21) << "AppendStopWaitingFrame failed";
return 0;
}
break;
@@ -952,32 +964,32 @@ size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header,
break;
case RST_STREAM_FRAME:
if (!AppendRstStreamFrame(*frame.rst_stream_frame, &writer)) {
- QUIC_BUG << "AppendRstStreamFrame failed";
+ QUIC_BUG(quic_bug_10850_22) << "AppendRstStreamFrame failed";
return 0;
}
break;
case CONNECTION_CLOSE_FRAME:
if (!AppendConnectionCloseFrame(*frame.connection_close_frame,
&writer)) {
- QUIC_BUG << "AppendConnectionCloseFrame failed";
+ QUIC_BUG(quic_bug_10850_23) << "AppendConnectionCloseFrame failed";
return 0;
}
break;
case GOAWAY_FRAME:
if (!AppendGoAwayFrame(*frame.goaway_frame, &writer)) {
- QUIC_BUG << "AppendGoAwayFrame failed";
+ QUIC_BUG(quic_bug_10850_24) << "AppendGoAwayFrame failed";
return 0;
}
break;
case WINDOW_UPDATE_FRAME:
if (!AppendWindowUpdateFrame(*frame.window_update_frame, &writer)) {
- QUIC_BUG << "AppendWindowUpdateFrame failed";
+ QUIC_BUG(quic_bug_10850_25) << "AppendWindowUpdateFrame failed";
return 0;
}
break;
case BLOCKED_FRAME:
if (!AppendBlockedFrame(*frame.blocked_frame, &writer)) {
- QUIC_BUG << "AppendBlockedFrame failed";
+ QUIC_BUG(quic_bug_10850_26) << "AppendBlockedFrame failed";
return 0;
}
break;
@@ -1017,7 +1029,7 @@ size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header,
case MESSAGE_FRAME:
if (!AppendMessageFrameAndTypeByte(*frame.message_frame,
last_frame_in_packet, &writer)) {
- QUIC_BUG << "AppendMessageFrame failed";
+ QUIC_BUG(quic_bug_10850_27) << "AppendMessageFrame failed";
return 0;
}
break;
@@ -1028,7 +1040,7 @@ size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header,
return RaiseError(QUIC_INTERNAL_ERROR);
}
if (!AppendCryptoFrame(*frame.crypto_frame, &writer)) {
- QUIC_BUG << "AppendCryptoFrame failed";
+ QUIC_BUG(quic_bug_10850_28) << "AppendCryptoFrame failed";
return 0;
}
break;
@@ -1037,7 +1049,7 @@ size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header,
break;
default:
RaiseError(QUIC_INVALID_FRAME_DATA);
- QUIC_BUG << "QUIC_INVALID_FRAME_DATA";
+ QUIC_BUG(quic_bug_10850_29) << "QUIC_INVALID_FRAME_DATA";
return 0;
}
++i;
@@ -1057,30 +1069,33 @@ size_t QuicFramer::AppendIetfFrames(const QuicFrames& frames,
// Determine if we should write stream frame length in header.
const bool last_frame_in_packet = i == frames.size() - 1;
if (!AppendIetfFrameType(frame, last_frame_in_packet, writer)) {
- QUIC_BUG << "AppendIetfFrameType failed: " << detailed_error();
+ QUIC_BUG(quic_bug_10850_30)
+ << "AppendIetfFrameType failed: " << detailed_error();
return 0;
}
switch (frame.type) {
case PADDING_FRAME:
if (!AppendPaddingFrame(frame.padding_frame, writer)) {
- QUIC_BUG << "AppendPaddingFrame of "
- << frame.padding_frame.num_padding_bytes
- << " failed: " << detailed_error();
+ QUIC_BUG(quic_bug_10850_31) << "AppendPaddingFrame of "
+ << frame.padding_frame.num_padding_bytes
+ << " failed: " << detailed_error();
return 0;
}
break;
case STREAM_FRAME:
if (!AppendStreamFrame(frame.stream_frame, last_frame_in_packet,
writer)) {
- QUIC_BUG << "AppendStreamFrame failed: " << detailed_error();
+ QUIC_BUG(quic_bug_10850_32)
+ << "AppendStreamFrame " << frame.stream_frame
+ << " failed: " << detailed_error();
return 0;
}
break;
case ACK_FRAME:
if (!AppendIetfAckFrameAndTypeByte(*frame.ack_frame, writer)) {
- QUIC_BUG << "AppendIetfAckFrameAndTypeByte failed: "
- << detailed_error();
+ QUIC_BUG(quic_bug_10850_33)
+ << "AppendIetfAckFrameAndTypeByte failed: " << detailed_error();
return 0;
}
break;
@@ -1088,7 +1103,7 @@ size_t QuicFramer::AppendIetfFrames(const QuicFrames& frames,
set_detailed_error(
"Attempt to append STOP WAITING frame in IETF QUIC.");
RaiseError(QUIC_INTERNAL_ERROR);
- QUIC_BUG << detailed_error();
+ QUIC_BUG(quic_bug_10850_34) << detailed_error();
return 0;
case MTU_DISCOVERY_FRAME:
// MTU discovery frames are serialized as ping frames.
@@ -1098,22 +1113,23 @@ size_t QuicFramer::AppendIetfFrames(const QuicFrames& frames,
break;
case RST_STREAM_FRAME:
if (!AppendRstStreamFrame(*frame.rst_stream_frame, writer)) {
- QUIC_BUG << "AppendRstStreamFrame failed: " << detailed_error();
+ QUIC_BUG(quic_bug_10850_35)
+ << "AppendRstStreamFrame failed: " << detailed_error();
return 0;
}
break;
case CONNECTION_CLOSE_FRAME:
if (!AppendIetfConnectionCloseFrame(*frame.connection_close_frame,
writer)) {
- QUIC_BUG << "AppendIetfConnectionCloseFrame failed: "
- << detailed_error();
+ QUIC_BUG(quic_bug_10850_36)
+ << "AppendIetfConnectionCloseFrame failed: " << detailed_error();
return 0;
}
break;
case GOAWAY_FRAME:
set_detailed_error("Attempt to append GOAWAY frame in IETF QUIC.");
RaiseError(QUIC_INTERNAL_ERROR);
- QUIC_BUG << detailed_error();
+ QUIC_BUG(quic_bug_10850_37) << detailed_error();
return 0;
case WINDOW_UPDATE_FRAME:
// Depending on whether there is a stream ID or not, will be either a
@@ -1121,83 +1137,95 @@ size_t QuicFramer::AppendIetfFrames(const QuicFrames& frames,
if (frame.window_update_frame->stream_id ==
QuicUtils::GetInvalidStreamId(transport_version())) {
if (!AppendMaxDataFrame(*frame.window_update_frame, writer)) {
- QUIC_BUG << "AppendMaxDataFrame failed: " << detailed_error();
+ QUIC_BUG(quic_bug_10850_38)
+ << "AppendMaxDataFrame failed: " << detailed_error();
return 0;
}
} else {
if (!AppendMaxStreamDataFrame(*frame.window_update_frame, writer)) {
- QUIC_BUG << "AppendMaxStreamDataFrame failed: " << detailed_error();
+ QUIC_BUG(quic_bug_10850_39)
+ << "AppendMaxStreamDataFrame failed: " << detailed_error();
return 0;
}
}
break;
case BLOCKED_FRAME:
if (!AppendBlockedFrame(*frame.blocked_frame, writer)) {
- QUIC_BUG << "AppendBlockedFrame failed: " << detailed_error();
+ QUIC_BUG(quic_bug_10850_40)
+ << "AppendBlockedFrame failed: " << detailed_error();
return 0;
}
break;
case MAX_STREAMS_FRAME:
if (!AppendMaxStreamsFrame(frame.max_streams_frame, writer)) {
- QUIC_BUG << "AppendMaxStreamsFrame failed: " << detailed_error();
+ QUIC_BUG(quic_bug_10850_41)
+ << "AppendMaxStreamsFrame failed: " << detailed_error();
return 0;
}
break;
case STREAMS_BLOCKED_FRAME:
if (!AppendStreamsBlockedFrame(frame.streams_blocked_frame, writer)) {
- QUIC_BUG << "AppendStreamsBlockedFrame failed: " << detailed_error();
+ QUIC_BUG(quic_bug_10850_42)
+ << "AppendStreamsBlockedFrame failed: " << detailed_error();
return 0;
}
break;
case NEW_CONNECTION_ID_FRAME:
if (!AppendNewConnectionIdFrame(*frame.new_connection_id_frame,
writer)) {
- QUIC_BUG << "AppendNewConnectionIdFrame failed: " << detailed_error();
+ QUIC_BUG(quic_bug_10850_43)
+ << "AppendNewConnectionIdFrame failed: " << detailed_error();
return 0;
}
break;
case RETIRE_CONNECTION_ID_FRAME:
if (!AppendRetireConnectionIdFrame(*frame.retire_connection_id_frame,
writer)) {
- QUIC_BUG << "AppendRetireConnectionIdFrame failed: "
- << detailed_error();
+ QUIC_BUG(quic_bug_10850_44)
+ << "AppendRetireConnectionIdFrame failed: " << detailed_error();
return 0;
}
break;
case NEW_TOKEN_FRAME:
if (!AppendNewTokenFrame(*frame.new_token_frame, writer)) {
- QUIC_BUG << "AppendNewTokenFrame failed: " << detailed_error();
+ QUIC_BUG(quic_bug_10850_45)
+ << "AppendNewTokenFrame failed: " << detailed_error();
return 0;
}
break;
case STOP_SENDING_FRAME:
if (!AppendStopSendingFrame(*frame.stop_sending_frame, writer)) {
- QUIC_BUG << "AppendStopSendingFrame failed: " << detailed_error();
+ QUIC_BUG(quic_bug_10850_46)
+ << "AppendStopSendingFrame failed: " << detailed_error();
return 0;
}
break;
case PATH_CHALLENGE_FRAME:
if (!AppendPathChallengeFrame(*frame.path_challenge_frame, writer)) {
- QUIC_BUG << "AppendPathChallengeFrame failed: " << detailed_error();
+ QUIC_BUG(quic_bug_10850_47)
+ << "AppendPathChallengeFrame failed: " << detailed_error();
return 0;
}
break;
case PATH_RESPONSE_FRAME:
if (!AppendPathResponseFrame(*frame.path_response_frame, writer)) {
- QUIC_BUG << "AppendPathResponseFrame failed: " << detailed_error();
+ QUIC_BUG(quic_bug_10850_48)
+ << "AppendPathResponseFrame failed: " << detailed_error();
return 0;
}
break;
case MESSAGE_FRAME:
if (!AppendMessageFrameAndTypeByte(*frame.message_frame,
last_frame_in_packet, writer)) {
- QUIC_BUG << "AppendMessageFrame failed: " << detailed_error();
+ QUIC_BUG(quic_bug_10850_49)
+ << "AppendMessageFrame failed: " << detailed_error();
return 0;
}
break;
case CRYPTO_FRAME:
if (!AppendCryptoFrame(*frame.crypto_frame, writer)) {
- QUIC_BUG << "AppendCryptoFrame failed: " << detailed_error();
+ QUIC_BUG(quic_bug_10850_50)
+ << "AppendCryptoFrame failed: " << detailed_error();
return 0;
}
break;
@@ -1206,14 +1234,16 @@ size_t QuicFramer::AppendIetfFrames(const QuicFrames& frames,
break;
case ACK_FREQUENCY_FRAME:
if (!AppendAckFrequencyFrame(*frame.ack_frequency_frame, writer)) {
- QUIC_BUG << "AppendAckFrequencyFrame failed: " << detailed_error();
+ QUIC_BUG(quic_bug_10850_51)
+ << "AppendAckFrequencyFrame failed: " << detailed_error();
return 0;
}
break;
default:
set_detailed_error("Tried to append unknown frame type.");
RaiseError(QUIC_INVALID_FRAME_DATA);
- QUIC_BUG << "QUIC_INVALID_FRAME_DATA: " << frame.type;
+ QUIC_BUG(quic_bug_10850_52)
+ << "QUIC_INVALID_FRAME_DATA: " << frame.type;
return 0;
}
++i;
@@ -1268,10 +1298,57 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildPublicResetPacket(
}
// static
+size_t QuicFramer::GetMinStatelessResetPacketLength() {
+ // 5 bytes (40 bits) = 2 Fixed Bits (01) + 38 Unpredictable bits
+ return 5 + kStatelessResetTokenLength;
+}
+
+// static
std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildIetfStatelessResetPacket(
QuicConnectionId /*connection_id*/,
- QuicUint128 stateless_reset_token) {
+ size_t received_packet_length,
+ StatelessResetToken stateless_reset_token) {
QUIC_DVLOG(1) << "Building IETF stateless reset packet.";
+ if (GetQuicReloadableFlag(quic_fix_stateless_reset)) {
+ if (received_packet_length <= GetMinStatelessResetPacketLength()) {
+ QUIC_BUG(362045737_1)
+ << "Tried to build stateless reset packet with received packet "
+ "length "
+ << received_packet_length;
+ return nullptr;
+ }
+ // To ensure stateless reset is indistinguishable from a valid packet,
+ // include the max connection ID length.
+ size_t len = std::min(received_packet_length - 1,
+ GetMinStatelessResetPacketLength() + 1 +
+ kQuicMaxConnectionIdWithLengthPrefixLength);
+ std::unique_ptr<char[]> buffer(new char[len]);
+ QuicDataWriter writer(len, buffer.get());
+ // Append random bytes. This randomness only exists to prevent middleboxes
+ // from comparing the entire packet to a known value. Therefore it has no
+ // cryptographic use, and does not need a secure cryptographic pseudo-random
+ // number generator. It's therefore safe to use WriteInsecureRandomBytes.
+ if (!writer.WriteInsecureRandomBytes(QuicRandom::GetInstance(),
+ len - kStatelessResetTokenLength)) {
+ QUIC_BUG(362045737_2) << "Failed to append random bytes of length: "
+ << len - kStatelessResetTokenLength;
+ return nullptr;
+ }
+ // Change first 2 fixed bits to 01.
+ buffer[0] &= ~FLAGS_LONG_HEADER;
+ buffer[0] |= FLAGS_FIXED_BIT;
+
+ // Append stateless reset token.
+ if (!writer.WriteBytes(&stateless_reset_token,
+ sizeof(stateless_reset_token))) {
+ QUIC_BUG(362045737_3) << "Failed to write stateless reset token";
+ return nullptr;
+ }
+ QUIC_RELOADABLE_FLAG_COUNT(quic_fix_stateless_reset);
+ return std::make_unique<QuicEncryptedPacket>(buffer.release(), len,
+ /*owns_buffer=*/true);
+ }
+
size_t len = kPacketHeaderTypeSize + kMinRandomBytesLengthInStatelessReset +
sizeof(stateless_reset_token);
std::unique_ptr<char[]> buffer(new char[len]);
@@ -1291,18 +1368,10 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildIetfStatelessResetPacket(
// Append random bytes. This randomness only exists to prevent middleboxes
// from comparing the entire packet to a known value. Therefore it has no
// cryptographic use, and does not need a secure cryptographic pseudo-random
- // number generator. It's therefore safe to use WriteInsecureRandomBytes here.
- if (GetQuicReloadableFlag(quic_stateless_reset_faster_random)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_stateless_reset_faster_random);
- if (!writer.WriteInsecureRandomBytes(
- QuicRandom::GetInstance(), kMinRandomBytesLengthInStatelessReset)) {
- return nullptr;
- }
- } else {
- if (!writer.WriteRandomBytes(QuicRandom::GetInstance(),
- kMinRandomBytesLengthInStatelessReset)) {
- return nullptr;
- }
+ // number generator. It's therefore safe to use WriteInsecureRandomBytes.
+ if (!writer.WriteInsecureRandomBytes(QuicRandom::GetInstance(),
+ kMinRandomBytesLengthInStatelessReset)) {
+ return nullptr;
}
// Append stateless reset token.
@@ -1528,9 +1597,9 @@ bool QuicFramer::ProcessPacketInternal(const QuicEncryptedPacket& packet) {
rv = ProcessDataPacket(&reader, &header, packet, large_buffer.get(),
packet.length());
}
- QUIC_BUG_IF(rv) << "QUIC should never successfully process packets larger"
- << "than kMaxIncomingPacketSize. packet size:"
- << packet.length();
+ QUIC_BUG_IF(quic_bug_10850_53, rv)
+ << "QUIC should never successfully process packets larger"
+ << "than kMaxIncomingPacketSize. packet size:" << packet.length();
}
return rv;
}
@@ -1709,7 +1778,7 @@ bool QuicFramer::MaybeProcessIetfLength(QuicDataReader* encrypted_reader,
if (!encrypted_reader->TruncateRemaining(header->remaining_packet_length)) {
set_detailed_error("Length TruncateRemaining failed.");
- QUIC_BUG << "Length TruncateRemaining failed.";
+ QUIC_BUG(quic_bug_10850_54) << "Length TruncateRemaining failed.";
return RaiseError(QUIC_INVALID_PACKET_HEADER);
}
return true;
@@ -1899,7 +1968,7 @@ bool QuicFramer::ProcessIetfDataPacket(QuicDataReader* encrypted_reader,
// Handle the payload.
if (VersionHasIetfQuicFrames(version_.transport_version)) {
current_received_frame_type_ = 0;
- if (!ProcessIetfFrameData(&reader, *header)) {
+ if (!ProcessIetfFrameData(&reader, *header, decrypted_level)) {
current_received_frame_type_ = 0;
QUICHE_DCHECK_NE(QUIC_NO_ERROR,
error_); // ProcessIetfFrameData sets the error.
@@ -2050,8 +2119,8 @@ bool QuicFramer::ProcessPublicResetPacket(QuicDataReader* reader,
bool QuicFramer::IsIetfStatelessResetPacket(
const QuicPacketHeader& header) const {
- QUIC_BUG_IF(header.has_possible_stateless_reset_token &&
- perspective_ != Perspective::IS_CLIENT)
+ QUIC_BUG_IF(quic_bug_12975_3, header.has_possible_stateless_reset_token &&
+ perspective_ != Perspective::IS_CLIENT)
<< "has_possible_stateless_reset_token can only be true at client side.";
return header.form == IETF_QUIC_SHORT_HEADER_PACKET &&
header.has_possible_stateless_reset_token &&
@@ -2079,14 +2148,15 @@ bool QuicFramer::HasAnEncrypterForSpace(PacketNumberSpace space) const {
case NUM_PACKET_NUMBER_SPACES:
break;
}
- QUIC_BUG << ENDPOINT
- << "Try to send data of space: " << PacketNumberSpaceToString(space);
+ QUIC_BUG(quic_bug_10850_55)
+ << ENDPOINT
+ << "Try to send data of space: " << PacketNumberSpaceToString(space);
return false;
}
EncryptionLevel QuicFramer::GetEncryptionLevelToSendApplicationData() const {
if (!HasAnEncrypterForSpace(APPLICATION_DATA)) {
- QUIC_BUG
+ QUIC_BUG(quic_bug_12975_4)
<< "Tried to get encryption level to send application data with no "
"encrypter available.";
return NUM_ENCRYPTION_LEVELS;
@@ -2138,8 +2208,9 @@ bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header,
}
break;
case CONNECTION_ID_PRESENT:
- QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
- server_connection_id, transport_version()))
+ QUIC_BUG_IF(quic_bug_12975_5,
+ !QuicUtils::IsConnectionIdValidForVersion(
+ server_connection_id, transport_version()))
<< "AppendPacketHeader: attempted to use connection ID "
<< server_connection_id << " which is invalid with version "
<< version();
@@ -2202,8 +2273,8 @@ bool QuicFramer::AppendIetfPacketHeader(const QuicPacketHeader& header,
QUIC_DVLOG(1) << ENDPOINT << "Appending IETF header: " << header;
QuicConnectionId server_connection_id =
GetServerConnectionIdAsSender(header, perspective_);
- QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(server_connection_id,
- transport_version()))
+ QUIC_BUG_IF(quic_bug_12975_6, !QuicUtils::IsConnectionIdValidForVersion(
+ server_connection_id, transport_version()))
<< "AppendIetfPacketHeader: attempted to use connection ID "
<< server_connection_id << " which is invalid with version " << version();
if (!AppendIetfHeaderTypeByte(header, writer)) {
@@ -2243,7 +2314,8 @@ bool QuicFramer::AppendIetfPacketHeader(const QuicPacketHeader& header,
}
// TODO(b/141924462) Remove this QUIC_BUG once we do support sending RETRY.
- QUIC_BUG_IF(header.version_flag && header.long_packet_type == RETRY)
+ QUIC_BUG_IF(quic_bug_12975_7,
+ header.version_flag && header.long_packet_type == RETRY)
<< "Sending IETF RETRY packets is not currently supported " << header;
if (QuicVersionHasLongHeaderLengths(transport_version()) &&
@@ -2468,7 +2540,7 @@ uint8_t QuicFramer::GetPacketNumberFlags(
case PACKET_8BYTE_PACKET_NUMBER:
return PACKET_FLAGS_8BYTE_PACKET;
default:
- QUIC_BUG << "Unreachable case statement.";
+ QUIC_BUG(quic_bug_10850_56) << "Unreachable case statement.";
return PACKET_FLAGS_8BYTE_PACKET;
}
}
@@ -2701,14 +2773,28 @@ bool QuicFramer::ProcessAndValidateIetfConnectionIdLength(
}
bool QuicFramer::ValidateReceivedConnectionIds(const QuicPacketHeader& header) {
- if (!QuicUtils::IsConnectionIdValidForVersion(
+ 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 &&
+ !QuicUtils::IsConnectionIdValidForVersion(
GetServerConnectionIdAsRecipient(header, perspective_),
transport_version())) {
set_detailed_error("Received server connection ID with invalid length.");
return false;
}
- if (version_.SupportsClientConnectionIds() &&
+ 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(
GetClientConnectionIdAsRecipient(header, perspective_),
transport_version())) {
@@ -2743,7 +2829,8 @@ 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 (header->source_connection_id_included == 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_;
@@ -2838,10 +2925,12 @@ bool QuicFramer::ProcessIetfPacketHeader(QuicDataReader* reader,
set_detailed_error("Client connection ID not supported in this version.");
return false;
}
- 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 (!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_;
+ }
}
}
@@ -3098,8 +3187,33 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader,
return true;
}
+// static
+bool QuicFramer::IsIetfFrameTypeExpectedForEncryptionLevel(
+ uint64_t frame_type,
+ EncryptionLevel level) {
+ switch (level) {
+ case ENCRYPTION_INITIAL:
+ case ENCRYPTION_HANDSHAKE:
+ return frame_type == IETF_CRYPTO || frame_type == IETF_ACK ||
+ frame_type == IETF_PING || frame_type == IETF_PADDING ||
+ frame_type == IETF_CONNECTION_CLOSE;
+ case ENCRYPTION_ZERO_RTT:
+ return !(frame_type == IETF_ACK || frame_type == IETF_CRYPTO ||
+ frame_type == IETF_HANDSHAKE_DONE ||
+ frame_type == IETF_NEW_TOKEN ||
+ frame_type == IETF_PATH_RESPONSE ||
+ frame_type == IETF_RETIRE_CONNECTION_ID);
+ case ENCRYPTION_FORWARD_SECURE:
+ return true;
+ default:
+ QUIC_BUG(quic_bug_10850_57) << "Unknown encryption level: " << level;
+ }
+ return false;
+}
+
bool QuicFramer::ProcessIetfFrameData(QuicDataReader* reader,
- const QuicPacketHeader& header) {
+ const QuicPacketHeader& header,
+ EncryptionLevel decrypted_level) {
QUICHE_DCHECK(VersionHasIetfQuicFrames(version_.transport_version))
<< "Attempt to process frames as IETF frames but version ("
<< version_.transport_version << ") does not support IETF Framing.";
@@ -3118,6 +3232,21 @@ 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);
+ }
+ }
current_received_frame_type_ = frame_type;
// Is now the number of bytes into which the frame type was encoded.
@@ -4294,9 +4423,10 @@ bool QuicFramer::DoKeyUpdate(KeyUpdateReason reason) {
std::unique_ptr<QuicEncrypter> next_encrypter =
visitor_->CreateCurrentOneRttEncrypter();
if (!next_decrypter_ || !next_encrypter) {
- QUIC_BUG << "Failed to create next crypters";
+ QUIC_BUG(quic_bug_10850_58) << "Failed to create next crypters";
return false;
}
+ key_update_performed_ = true;
current_key_phase_bit_ = !current_key_phase_bit_;
QUIC_DLOG(INFO) << ENDPOINT << "DoKeyUpdate: new current_key_phase_bit_="
<< current_key_phase_bit_;
@@ -4357,9 +4487,9 @@ size_t QuicFramer::EncryptInPlace(EncryptionLevel level,
char* buffer) {
QUICHE_DCHECK(packet_number.IsInitialized());
if (encrypter_[level] == nullptr) {
- QUIC_BUG << ENDPOINT
- << "Attempted to encrypt in place without encrypter at level "
- << level;
+ QUIC_BUG(quic_bug_10850_59)
+ << ENDPOINT
+ << "Attempted to encrypt in place without encrypter at level " << level;
RaiseError(QUIC_ENCRYPTION_FAILURE);
return 0;
}
@@ -4412,14 +4542,14 @@ bool QuicFramer::ApplyHeaderProtection(EncryptionLevel level,
absl::string_view sample;
if (!sample_reader.Seek(sample_offset) ||
!sample_reader.ReadStringPiece(&sample, kHPSampleLen)) {
- QUIC_BUG << "Not enough bytes to sample: sample_offset " << sample_offset
- << ", sample len: " << kHPSampleLen
- << ", buffer len: " << buffer_len;
+ QUIC_BUG(quic_bug_10850_60)
+ << "Not enough bytes to sample: sample_offset " << sample_offset
+ << ", sample len: " << kHPSampleLen << ", buffer len: " << buffer_len;
return false;
}
if (encrypter_[level] == nullptr) {
- QUIC_BUG
+ QUIC_BUG(quic_bug_12975_8)
<< ENDPOINT
<< "Attempted to apply header protection without encrypter at level "
<< level << " using " << version_;
@@ -4428,7 +4558,7 @@ bool QuicFramer::ApplyHeaderProtection(EncryptionLevel level,
std::string mask = encrypter_[level]->GenerateHeaderProtectionMask(sample);
if (mask.empty()) {
- QUIC_BUG << "Unable to generate header protection mask.";
+ QUIC_BUG(quic_bug_10850_61) << "Unable to generate header protection mask.";
return false;
}
QuicDataReader mask_reader(mask.data(), mask.size());
@@ -4457,7 +4587,8 @@ bool QuicFramer::ApplyHeaderProtection(EncryptionLevel level,
perspective_ == Perspective::IS_SERVER &&
version_.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
if (pn_offset <= kDiversificationNonceSize) {
- QUIC_BUG << "Expected diversification nonce, but not enough bytes";
+ QUIC_BUG(quic_bug_10850_62)
+ << "Expected diversification nonce, but not enough bytes";
return false;
}
pn_offset -= kDiversificationNonceSize;
@@ -4612,8 +4743,9 @@ size_t QuicFramer::EncryptPayload(EncryptionLevel level,
size_t buffer_len) {
QUICHE_DCHECK(packet_number.IsInitialized());
if (encrypter_[level] == nullptr) {
- QUIC_BUG << ENDPOINT << "Attempted to encrypt without encrypter at level "
- << level;
+ QUIC_BUG(quic_bug_10850_63)
+ << ENDPOINT << "Attempted to encrypt without encrypter at level "
+ << level;
RaiseError(QUIC_ENCRYPTION_FAILURE);
return 0;
}
@@ -4624,10 +4756,10 @@ size_t QuicFramer::EncryptPayload(EncryptionLevel level,
// plaintext content.
const size_t ad_len = associated_data.length();
if (packet.length() < ad_len) {
- QUIC_BUG << ENDPOINT
- << "packet is shorter than associated data length. version:"
- << version() << ", packet length:" << packet.length()
- << ", associated data length:" << ad_len;
+ QUIC_BUG(quic_bug_10850_64)
+ << ENDPOINT << "packet is shorter than associated data length. version:"
+ << version() << ", packet length:" << packet.length()
+ << ", associated data length:" << ad_len;
RaiseError(QUIC_ENCRYPTION_FAILURE);
return 0;
}
@@ -4654,9 +4786,10 @@ size_t QuicFramer::EncryptPayload(EncryptionLevel level,
size_t QuicFramer::GetCiphertextSize(EncryptionLevel level,
size_t plaintext_size) const {
if (encrypter_[level] == nullptr) {
- QUIC_BUG << ENDPOINT
- << "Attempted to get ciphertext size without encrypter at level "
- << level << " using " << version_;
+ QUIC_BUG(quic_bug_10850_65)
+ << ENDPOINT
+ << "Attempted to get ciphertext size without encrypter at level "
+ << level << " using " << version_;
return plaintext_size;
}
return encrypter_[level]->GetCiphertextSize(plaintext_size);
@@ -4681,7 +4814,7 @@ size_t QuicFramer::GetMaxPlaintextSize(size_t ciphertext_size) {
QuicPacketCount QuicFramer::GetOneRttEncrypterConfidentialityLimit() const {
if (!encrypter_[ENCRYPTION_FORWARD_SECURE]) {
- QUIC_BUG << "1-RTT encrypter not set";
+ QUIC_BUG(quic_bug_10850_66) << "1-RTT encrypter not set";
return 0;
}
return encrypter_[ENCRYPTION_FORWARD_SECURE]->GetConfidentialityLimit();
@@ -4696,7 +4829,8 @@ bool QuicFramer::DecryptPayload(size_t udp_packet_length,
size_t* decrypted_length,
EncryptionLevel* decrypted_level) {
if (!EncryptionLevelIsValid(decrypter_level_)) {
- QUIC_BUG << "Attempted to decrypt with bad decrypter_level_";
+ QUIC_BUG(quic_bug_10850_67)
+ << "Attempted to decrypt with bad decrypter_level_";
return false;
}
EncryptionLevel level = decrypter_level_;
@@ -4707,13 +4841,14 @@ bool QuicFramer::DecryptPayload(size_t udp_packet_length,
bool attempt_key_update = false;
if (version().KnowsWhichDecrypterToUse()) {
if (header.form == GOOGLE_QUIC_PACKET) {
- QUIC_BUG << "Attempted to decrypt GOOGLE_QUIC_PACKET with a version that "
- "knows which decrypter to use";
+ QUIC_BUG(quic_bug_10850_68)
+ << "Attempted to decrypt GOOGLE_QUIC_PACKET with a version that "
+ "knows which decrypter to use";
return false;
}
level = GetEncryptionLevel(header);
if (!EncryptionLevelIsValid(level)) {
- QUIC_BUG << "Attempted to decrypt with bad level";
+ QUIC_BUG(quic_bug_10850_69) << "Attempted to decrypt with bad level";
return false;
}
decrypter = decrypter_[level].get();
@@ -4734,14 +4869,18 @@ bool QuicFramer::DecryptPayload(size_t udp_packet_length,
<< " received key_phase=" << key_phase
<< " current_key_phase_bit_=" << current_key_phase_bit_;
if (key_phase != current_key_phase_bit_) {
- if (current_key_phase_first_received_packet_number_.IsInitialized() &&
- header.packet_number >
- current_key_phase_first_received_packet_number_) {
+ 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() &&
+ !key_update_performed_)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_fix_key_update_on_first_packet);
if (!next_decrypter_) {
next_decrypter_ =
visitor_->AdvanceKeysAndCreateCurrentOneRttDecrypter();
if (!next_decrypter_) {
- QUIC_BUG << "Failed to create next_decrypter";
+ QUIC_BUG(quic_bug_10850_70) << "Failed to create next_decrypter";
return false;
}
}
@@ -4766,15 +4905,17 @@ bool QuicFramer::DecryptPayload(size_t udp_packet_length,
}
} else if (alternative_decrypter_level_ != NUM_ENCRYPTION_LEVELS) {
if (!EncryptionLevelIsValid(alternative_decrypter_level_)) {
- QUIC_BUG << "Attempted to decrypt with bad alternative_decrypter_level_";
+ QUIC_BUG(quic_bug_10850_71)
+ << "Attempted to decrypt with bad alternative_decrypter_level_";
return false;
}
alternative_decrypter = decrypter_[alternative_decrypter_level_].get();
}
if (decrypter == nullptr) {
- QUIC_BUG << "Attempting to decrypt without decrypter, encryption level:"
- << level << " version:" << version();
+ QUIC_BUG(quic_bug_10850_72)
+ << "Attempting to decrypt without decrypter, encryption level:" << level
+ << " version:" << version();
return false;
}
@@ -4783,21 +4924,16 @@ bool QuicFramer::DecryptPayload(size_t udp_packet_length,
decrypted_buffer, decrypted_length, buffer_length);
if (success) {
visitor_->OnDecryptedPacket(udp_packet_length, level);
- if (GetQuicReloadableFlag(
- quic_close_connection_on_0rtt_packet_number_higher_than_1rtt)) {
- QUIC_RELOADABLE_FLAG_COUNT(
- quic_close_connection_on_0rtt_packet_number_higher_than_1rtt);
- if (level == ENCRYPTION_ZERO_RTT &&
- current_key_phase_first_received_packet_number_.IsInitialized() &&
- header.packet_number >
- current_key_phase_first_received_packet_number_) {
- set_detailed_error(absl::StrCat(
- "Decrypted a 0-RTT packet with a packet number ",
- header.packet_number.ToString(),
- " which is higher than a 1-RTT packet number ",
- current_key_phase_first_received_packet_number_.ToString()));
- return RaiseError(QUIC_INVALID_0RTT_PACKET_NUMBER_OUT_OF_ORDER);
- }
+ if (level == ENCRYPTION_ZERO_RTT &&
+ current_key_phase_first_received_packet_number_.IsInitialized() &&
+ header.packet_number >
+ current_key_phase_first_received_packet_number_) {
+ set_detailed_error(absl::StrCat(
+ "Decrypted a 0-RTT packet with a packet number ",
+ header.packet_number.ToString(),
+ " which is higher than a 1-RTT packet number ",
+ current_key_phase_first_received_packet_number_.ToString()));
+ return RaiseError(QUIC_INVALID_0RTT_PACKET_NUMBER_OUT_OF_ORDER);
}
*decrypted_level = level;
potential_peer_key_update_attempt_count_ = 0;
@@ -4850,8 +4986,9 @@ bool QuicFramer::DecryptPayload(size_t udp_packet_length,
*decrypted_level = decrypter_level_;
if (alternative_decrypter_latch_) {
if (!EncryptionLevelIsValid(alternative_decrypter_level_)) {
- QUIC_BUG << "Attempted to latch alternate decrypter with bad "
- "alternative_decrypter_level_";
+ QUIC_BUG(quic_bug_10850_73)
+ << "Attempted to latch alternate decrypter with bad "
+ "alternative_decrypter_level_";
return false;
}
// Switch to the alternative decrypter and latch so that we cannot
@@ -4886,7 +5023,7 @@ size_t QuicFramer::GetIetfAckFrameSize(const QuicAckFrame& frame) {
ack_frame_size += QuicDataWriter::GetVarInt62Len(ack_delay_time_us);
if (frame.packets.Empty() || frame.packets.Max() != largest_acked) {
- QUIC_BUG << "Malformed ack frame";
+ QUIC_BUG(quic_bug_10850_74) << "Malformed ack frame";
// ACK frame serialization will fail and connection will be closed.
return ack_frame_size;
}
@@ -5169,8 +5306,9 @@ bool QuicFramer::AppendIetfFrameType(const QuicFrame& frame,
type_byte = IETF_ACK_FREQUENCY;
break;
default:
- QUIC_BUG << "Attempt to generate a frame type for an unsupported value: "
- << frame.type;
+ QUIC_BUG(quic_bug_10850_75)
+ << "Attempt to generate a frame type for an unsupported value: "
+ << frame.type;
return false;
}
return writer->WriteVarInt62(type_byte);
@@ -5182,7 +5320,8 @@ bool QuicFramer::AppendPacketNumber(QuicPacketNumberLength packet_number_length,
QuicDataWriter* writer) {
QUICHE_DCHECK(packet_number.IsInitialized());
if (!IsValidPacketNumberLength(packet_number_length)) {
- QUIC_BUG << "Invalid packet_number_length: " << packet_number_length;
+ QUIC_BUG(quic_bug_10850_76)
+ << "Invalid packet_number_length: " << packet_number_length;
return false;
}
return writer->WriteBytesToUInt64(packet_number_length,
@@ -5194,7 +5333,8 @@ bool QuicFramer::AppendStreamId(size_t stream_id_length,
QuicStreamId stream_id,
QuicDataWriter* writer) {
if (stream_id_length == 0 || stream_id_length > 4) {
- QUIC_BUG << "Invalid stream_id_length: " << stream_id_length;
+ QUIC_BUG(quic_bug_10850_77)
+ << "Invalid stream_id_length: " << stream_id_length;
return false;
}
return writer->WriteBytesToUInt64(stream_id_length, stream_id);
@@ -5205,7 +5345,8 @@ bool QuicFramer::AppendStreamOffset(size_t offset_length,
QuicStreamOffset offset,
QuicDataWriter* writer) {
if (offset_length == 1 || offset_length > 8) {
- QUIC_BUG << "Invalid stream_offset_length: " << offset_length;
+ QUIC_BUG(quic_bug_10850_78)
+ << "Invalid stream_offset_length: " << offset_length;
return false;
}
@@ -5219,7 +5360,8 @@ bool QuicFramer::AppendAckBlock(uint8_t gap,
QuicDataWriter* writer) {
if (length == 0) {
if (!IsValidPacketNumberLength(length_length)) {
- QUIC_BUG << "Invalid packet_number_length: " << length_length;
+ QUIC_BUG(quic_bug_10850_79)
+ << "Invalid packet_number_length: " << length_length;
return false;
}
return writer->WriteUInt8(gap) &&
@@ -5237,12 +5379,12 @@ bool QuicFramer::AppendStreamFrame(const QuicStreamFrame& frame,
}
if (!AppendStreamId(GetStreamIdSize(frame.stream_id), frame.stream_id,
writer)) {
- QUIC_BUG << "Writing stream id size failed.";
+ QUIC_BUG(quic_bug_10850_80) << "Writing stream id size failed.";
return false;
}
if (!AppendStreamOffset(GetStreamOffsetSize(frame.offset), frame.offset,
writer)) {
- QUIC_BUG << "Writing offset size failed.";
+ QUIC_BUG(quic_bug_10850_81) << "Writing offset size failed.";
return false;
}
if (!no_stream_frame_length) {
@@ -5252,7 +5394,7 @@ bool QuicFramer::AppendStreamFrame(const QuicStreamFrame& frame,
"If frame.data_length can hold more than a uint16_t than we need to "
"check that frame.data_length <= std::numeric_limits<uint16_t>::max()");
if (!writer->WriteUInt16(static_cast<uint16_t>(frame.data_length))) {
- QUIC_BUG << "Writing stream frame length failed";
+ QUIC_BUG(quic_bug_10850_82) << "Writing stream frame length failed";
return false;
}
}
@@ -5265,14 +5407,14 @@ bool QuicFramer::AppendStreamFrame(const QuicStreamFrame& frame,
if (data_producer_->WriteStreamData(frame.stream_id, frame.offset,
frame.data_length,
writer) != WRITE_SUCCESS) {
- QUIC_BUG << "Writing frame data failed.";
+ QUIC_BUG(quic_bug_10850_83) << "Writing frame data failed.";
return false;
}
return true;
}
if (!writer->WriteBytes(frame.data_buffer, frame.data_length)) {
- QUIC_BUG << "Writing frame data failed.";
+ QUIC_BUG(quic_bug_10850_84) << "Writing frame data failed.";
return false;
}
return true;
@@ -5352,7 +5494,7 @@ bool QuicFramer::AppendIetfStreamFrame(const QuicStreamFrame& frame,
if (data_producer_->WriteStreamData(frame.stream_id, frame.offset,
frame.data_length,
writer) != WRITE_SUCCESS) {
- set_detailed_error("Writing frame data failed.");
+ set_detailed_error("Writing frame data from producer failed.");
return false;
}
}
@@ -5524,8 +5666,9 @@ bool QuicFramer::AppendAckFrameAndTypeByte(const QuicAckFrame& frame,
}
if (num_ack_blocks_written >= num_ack_blocks) {
if (QUIC_PREDICT_FALSE(num_ack_blocks_written != num_ack_blocks)) {
- QUIC_BUG << "Wrote " << num_ack_blocks_written
- << ", expected to write " << num_ack_blocks;
+ QUIC_BUG(quic_bug_10850_85)
+ << "Wrote " << num_ack_blocks_written << ", expected to write "
+ << num_ack_blocks;
}
break;
}
@@ -5635,11 +5778,12 @@ bool QuicFramer::AppendStopWaitingFrame(const QuicPacketHeader& header,
const uint64_t length_shift = header.packet_number_length * 8;
if (least_unacked_delta >> length_shift > 0) {
- QUIC_BUG << "packet_number_length " << header.packet_number_length
- << " is too small for least_unacked_delta: " << least_unacked_delta
- << " packet_number:" << header.packet_number
- << " least_unacked:" << frame.least_unacked
- << " version:" << version_.transport_version;
+ QUIC_BUG(quic_bug_10850_86)
+ << "packet_number_length " << header.packet_number_length
+ << " is too small for least_unacked_delta: " << least_unacked_delta
+ << " packet_number:" << header.packet_number
+ << " least_unacked:" << frame.least_unacked
+ << " version:" << version_.transport_version;
return false;
}
if (least_unacked_delta == 0) {
@@ -5648,7 +5792,8 @@ bool QuicFramer::AppendStopWaitingFrame(const QuicPacketHeader& header,
}
if (!AppendPacketNumber(header.packet_number_length,
QuicPacketNumber(least_unacked_delta), writer)) {
- QUIC_BUG << " seq failed: " << header.packet_number_length;
+ QUIC_BUG(quic_bug_10850_87)
+ << " seq failed: " << header.packet_number_length;
return false;
}
@@ -5692,7 +5837,7 @@ bool QuicFramer::AppendIetfAckFrameAndTypeByte(const QuicAckFrame& frame,
}
if (frame.packets.Empty() || frame.packets.Max() != largest_acked) {
- QUIC_BUG << "Malformed ack frame: " << frame;
+ QUIC_BUG(quic_bug_10850_88) << "Malformed ack frame: " << frame;
set_detailed_error("Malformed ack frame");
return false;
}
@@ -5739,9 +5884,9 @@ bool QuicFramer::AppendIetfAckFrameAndTypeByte(const QuicAckFrame& frame,
!count_writer.WriteVarInt62(appended_ack_blocks)) {
// This should never happen as ack_block_count is limited by
// max_ack_ranges_.
- QUIC_BUG << "Ack frame truncation fails. ack_block_count: "
- << ack_block_count
- << ", appended count: " << appended_ack_blocks;
+ QUIC_BUG(quic_bug_10850_89)
+ << "Ack frame truncation fails. ack_block_count: " << ack_block_count
+ << ", appended count: " << appended_ack_blocks;
set_detailed_error("ACK frame truncation fails");
return false;
}
@@ -5854,7 +5999,7 @@ bool QuicFramer::AppendPaddingFrame(const QuicPaddingFrame& frame,
return false;
}
if (frame.num_padding_bytes < 0) {
- QUIC_BUG_IF(frame.num_padding_bytes != -1);
+ QUIC_BUG_IF(quic_bug_12975_9, frame.num_padding_bytes != -1);
writer->WritePadding();
return true;
}
@@ -5915,7 +6060,8 @@ bool QuicFramer::AppendIetfConnectionCloseFrame(
QuicDataWriter* writer) {
if (frame.close_type != IETF_QUIC_TRANSPORT_CONNECTION_CLOSE &&
frame.close_type != IETF_QUIC_APPLICATION_CONNECTION_CLOSE) {
- QUIC_BUG << "Invalid close_type for writing IETF CONNECTION CLOSE.";
+ QUIC_BUG(quic_bug_10850_90)
+ << "Invalid close_type for writing IETF CONNECTION CLOSE.";
set_detailed_error("Invalid close_type for writing IETF CONNECTION CLOSE.");
return false;
}
@@ -6406,12 +6552,14 @@ void QuicFramer::InferPacketHeaderTypeFromVersion() {
void QuicFramer::EnableMultiplePacketNumberSpacesSupport() {
if (supports_multiple_packet_number_spaces_) {
- QUIC_BUG << "Multiple packet number spaces has already been enabled";
+ QUIC_BUG(quic_bug_10850_91)
+ << "Multiple packet number spaces has already been enabled";
return;
}
if (largest_packet_number_.IsInitialized()) {
- QUIC_BUG << "Try to enable multiple packet number spaces support after any "
- "packet has been received.";
+ QUIC_BUG(quic_bug_10850_92)
+ << "Try to enable multiple packet number spaces support after any "
+ "packet has been received.";
return;
}
@@ -6701,17 +6849,17 @@ bool QuicFramer::WriteClientVersionNegotiationProbePacket(
const char* destination_connection_id_bytes,
uint8_t destination_connection_id_length) {
if (packet_bytes == nullptr) {
- QUIC_BUG << "Invalid packet_bytes";
+ QUIC_BUG(quic_bug_10850_93) << "Invalid packet_bytes";
return false;
}
if (packet_length < kMinPacketSizeForVersionNegotiation ||
packet_length > 65535) {
- QUIC_BUG << "Invalid packet_length";
+ QUIC_BUG(quic_bug_10850_94) << "Invalid packet_length";
return false;
}
if (destination_connection_id_length > kQuicMaxConnectionId4BitLength ||
destination_connection_id_length < kQuicDefaultConnectionIdLength) {
- QUIC_BUG << "Invalid connection_id_length";
+ QUIC_BUG(quic_bug_10850_95) << "Invalid connection_id_length";
return false;
}
// clang-format off
@@ -6727,7 +6875,7 @@ bool QuicFramer::WriteClientVersionNegotiationProbePacket(
static_assert(sizeof(packet_start_bytes) == 5, "bad packet_start_bytes size");
QuicDataWriter writer(packet_length, packet_bytes);
if (!writer.WriteBytes(packet_start_bytes, sizeof(packet_start_bytes))) {
- QUIC_BUG << "Failed to write packet start";
+ QUIC_BUG(quic_bug_10850_96) << "Failed to write packet start";
return false;
}
@@ -6736,7 +6884,7 @@ bool QuicFramer::WriteClientVersionNegotiationProbePacket(
if (!AppendIetfConnectionIds(
/*version_flag=*/true, /*use_length_prefix=*/true,
destination_connection_id, EmptyQuicConnectionId(), &writer)) {
- QUIC_BUG << "Failed to write connection IDs";
+ QUIC_BUG(quic_bug_10850_97) << "Failed to write connection IDs";
return false;
}
// Add 8 bytes of zeroes followed by 8 bytes of ones to ensure that this does
@@ -6746,14 +6894,14 @@ bool QuicFramer::WriteClientVersionNegotiationProbePacket(
// valid frame type.
if (!writer.WriteUInt64(0) ||
!writer.WriteUInt64(std::numeric_limits<uint64_t>::max())) {
- QUIC_BUG << "Failed to write 18 bytes";
+ QUIC_BUG(quic_bug_10850_98) << "Failed to write 18 bytes";
return false;
}
// Make sure the polite greeting below is padded to a 16-byte boundary to
// make it easier to read in tcpdump.
while (writer.length() % 16 != 0) {
if (!writer.WriteUInt8(0)) {
- QUIC_BUG << "Failed to write padding byte";
+ QUIC_BUG(quic_bug_10850_99) << "Failed to write padding byte";
return false;
}
}
@@ -6763,7 +6911,7 @@ bool QuicFramer::WriteClientVersionNegotiationProbePacket(
"Please respond with a Version Negotiation packet indicating what "
"versions you support. Thank you and have a nice day.";
if (!writer.WriteBytes(polite_greeting, sizeof(polite_greeting))) {
- QUIC_BUG << "Failed to write polite greeting";
+ QUIC_BUG(quic_bug_10850_100) << "Failed to write polite greeting";
return false;
}
// Fill the rest of the packet with zeroes.
@@ -6780,7 +6928,7 @@ bool QuicFramer::ParseServerVersionNegotiationProbeResponse(
uint8_t* source_connection_id_length_out,
std::string* detailed_error) {
if (detailed_error == nullptr) {
- QUIC_BUG << "Invalid error_details";
+ QUIC_BUG(quic_bug_10850_101) << "Invalid error_details";
return false;
}
*detailed_error = "";
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 571278deab8..e27c7f0727e 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
@@ -225,7 +225,8 @@ class QUIC_EXPORT_PRIVATE QuicFramerVisitorInterface {
virtual void OnPacketComplete() = 0;
// Called to check whether |token| is a valid stateless reset token.
- virtual bool IsValidStatelessResetToken(QuicUint128 token) const = 0;
+ virtual bool IsValidStatelessResetToken(
+ const StatelessResetToken& token) const = 0;
// Called when an IETF stateless reset packet has been parsed and validated
// with the stateless reset token.
@@ -470,10 +471,14 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
static std::unique_ptr<QuicEncryptedPacket> BuildPublicResetPacket(
const QuicPublicResetPacket& packet);
+ // Returns the minimal stateless reset packet length.
+ static size_t GetMinStatelessResetPacketLength();
+
// Returns a new IETF stateless reset packet.
static std::unique_ptr<QuicEncryptedPacket> BuildIetfStatelessResetPacket(
QuicConnectionId connection_id,
- QuicUint128 stateless_reset_token);
+ size_t received_packet_length,
+ StatelessResetToken stateless_reset_token);
// Returns a new version negotiation packet.
static std::unique_ptr<QuicEncryptedPacket> BuildVersionNegotiationPacket(
@@ -709,6 +714,10 @@ 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;
@@ -826,8 +835,13 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
QuicPacketNumber base_packet_number,
uint64_t* packet_number);
bool ProcessFrameData(QuicDataReader* reader, const QuicPacketHeader& header);
+
+ static bool IsIetfFrameTypeExpectedForEncryptionLevel(uint64_t frame_type,
+ EncryptionLevel level);
+
bool ProcessIetfFrameData(QuicDataReader* reader,
- const QuicPacketHeader& header);
+ const QuicPacketHeader& header,
+ EncryptionLevel decrypted_level);
bool ProcessStreamFrame(QuicDataReader* reader,
uint8_t frame_type,
QuicStreamFrame* frame);
@@ -1112,6 +1126,8 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
// The value of the current key phase bit, which is toggled when the keys are
// changed.
bool current_key_phase_bit_;
+ // Whether we have performed a key update at least once.
+ bool key_update_performed_ = false;
// Tracks the first packet received in the current key phase. Will be
// uninitialized before the first one-RTT packet has been received or after a
// locally initiated key update but before the first packet from the peer in
@@ -1158,6 +1174,14 @@ 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 12b779ac8f9..048a4b72ffb 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
@@ -13,6 +13,7 @@
#include <vector>
#include "absl/base/macros.h"
+#include "absl/memory/memory.h"
#include "absl/strings/escaping.h"
#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
@@ -29,7 +30,6 @@
#include "quic/platform/api/quic_expect_bug.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
-#include "quic/platform/api/quic_ptr_util.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_framer_peer.h"
#include "quic/test_tools/quic_test_utils.h"
@@ -47,7 +47,9 @@ namespace {
const uint64_t kEpoch = UINT64_C(1) << 32;
const uint64_t kMask = kEpoch - 1;
-const QuicUint128 kTestStatelessResetToken = 1010101; // 0x0F69B5
+const StatelessResetToken kTestStatelessResetToken{
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f};
// Use fields in which each byte is distinct to ensure that every byte is
// framed correctly. The values are otherwise arbitrary.
@@ -153,7 +155,7 @@ class TestDecrypter : public QuicDecrypter {
return true;
}
bool SetPreliminaryKey(absl::string_view /*key*/) override {
- QUIC_BUG << "should not be called";
+ QUIC_BUG(quic_bug_10486_1) << "should not be called";
return false;
}
bool SetDiversificationNonce(const DiversificationNonce& /*key*/) override {
@@ -319,7 +321,7 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
// Save a copy of the data so it is valid after the packet is processed.
std::string* string_data =
new std::string(frame.data_buffer, frame.data_length);
- stream_data_.push_back(QuicWrapUnique(string_data));
+ stream_data_.push_back(absl::WrapUnique(string_data));
stream_frames_.push_back(std::make_unique<QuicStreamFrame>(
frame.stream_id, frame.fin, frame.offset, *string_data));
if (VersionHasIetfQuicFrames(transport_version_)) {
@@ -336,7 +338,7 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
// Save a copy of the data so it is valid after the packet is processed.
std::string* string_data =
new std::string(frame.data_buffer, frame.data_length);
- crypto_data_.push_back(QuicWrapUnique(string_data));
+ crypto_data_.push_back(absl::WrapUnique(string_data));
crypto_frames_.push_back(std::make_unique<QuicCryptoFrame>(
frame.level, frame.offset, *string_data));
if (VersionHasIetfQuicFrames(transport_version_)) {
@@ -571,7 +573,8 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
return true;
}
- bool IsValidStatelessResetToken(QuicUint128 token) const override {
+ bool IsValidStatelessResetToken(
+ const StatelessResetToken& token) const override {
EXPECT_EQ(0u, framer_->current_received_frame_type());
return token == kTestStatelessResetToken;
}
@@ -1476,7 +1479,9 @@ TEST_P(QuicFramerTest, ClientConnectionIdFromShortHeaderToClient) {
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
- EXPECT_EQ(TestConnectionId(0x33), visitor_.header_->source_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
@@ -1510,7 +1515,9 @@ TEST_P(QuicFramerTest, ClientConnectionIdFromShortHeaderToServer) {
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
- EXPECT_EQ(TestConnectionId(0x33), visitor_.header_->source_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) {
@@ -1560,7 +1567,9 @@ TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) {
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
EXPECT_THAT(framer_.error(), IsError(QUIC_MISSING_PAYLOAD));
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_EQ(FramerTestConnectionId(), visitor_.header_->source_connection_id);
+ 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);
@@ -5746,8 +5755,8 @@ TEST_P(QuicFramerTest, IetfStatelessResetPacket) {
0x01, 0x11, 0x02, 0x22, 0x03, 0x33, 0x04, 0x44,
0x01, 0x11, 0x02, 0x22, 0x03, 0x33, 0x04, 0x44,
// stateless reset token
- 0xB5, 0x69, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
};
// clang-format on
if (!framer_.version().HasIetfInvariantHeader()) {
@@ -9239,6 +9248,59 @@ TEST_P(QuicFramerTest, BuildPublicResetPacketWithEndpointId) {
}
TEST_P(QuicFramerTest, BuildIetfStatelessResetPacket) {
+ if (GetQuicReloadableFlag(quic_fix_stateless_reset)) {
+ // clang-format off
+ unsigned char packet[] = {
+ // 1st byte 01XX XXXX
+ 0x40,
+ // At least 4 bytes of random bytes.
+ 0x00, 0x00, 0x00, 0x00,
+ // stateless reset token
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f
+ };
+ // clang-format on
+
+ // Build the minimal stateless reset packet.
+ std::unique_ptr<QuicEncryptedPacket> data(
+ framer_.BuildIetfStatelessResetPacket(
+ FramerTestConnectionId(),
+ QuicFramer::GetMinStatelessResetPacketLength() + 1,
+ kTestStatelessResetToken));
+ ASSERT_TRUE(data);
+ EXPECT_EQ(QuicFramer::GetMinStatelessResetPacketLength(), data->length());
+ // Verify the first 2 bits are 01.
+ EXPECT_FALSE(data->data()[0] & FLAGS_LONG_HEADER);
+ EXPECT_TRUE(data->data()[0] & FLAGS_FIXED_BIT);
+ // Verify stateless reset token.
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet",
+ data->data() + data->length() - kStatelessResetTokenLength,
+ kStatelessResetTokenLength,
+ AsChars(packet) + ABSL_ARRAYSIZE(packet) - kStatelessResetTokenLength,
+ kStatelessResetTokenLength);
+
+ // 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");
+
+ // Do not send stateless reset >= minimal stateless reset + 1 + max
+ // connection ID length.
+ std::unique_ptr<QuicEncryptedPacket> data3(
+ framer_.BuildIetfStatelessResetPacket(FramerTestConnectionId(), 1000,
+ kTestStatelessResetToken));
+ ASSERT_TRUE(data3);
+ EXPECT_EQ(QuicFramer::GetMinStatelessResetPacketLength() + 1 +
+ kQuicMaxConnectionIdWithLengthPrefixLength,
+ data3->length());
+ return;
+ }
// clang-format off
unsigned char packet[] = {
// type (short header, 1 byte packet number)
@@ -9246,29 +9308,28 @@ TEST_P(QuicFramerTest, BuildIetfStatelessResetPacket) {
// random packet number
0xFE,
// stateless reset token
- 0xB5, 0x69, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
};
// clang-format on
std::unique_ptr<QuicEncryptedPacket> data(
- framer_.BuildIetfStatelessResetPacket(FramerTestConnectionId(),
+ framer_.BuildIetfStatelessResetPacket(FramerTestConnectionId(), 0,
kTestStatelessResetToken));
ASSERT_TRUE(data != nullptr);
// Skip packet number byte which is random in stateless reset packet.
quiche::test::CompareCharArraysWithHexError(
"constructed packet", data->data(), 1, AsChars(packet), 1);
const size_t random_bytes_length =
- data->length() - kPacketHeaderTypeSize - sizeof(kTestStatelessResetToken);
+ data->length() - kPacketHeaderTypeSize - kStatelessResetTokenLength;
EXPECT_EQ(kMinRandomBytesLengthInStatelessReset, random_bytes_length);
// Verify stateless reset token is correct.
quiche::test::CompareCharArraysWithHexError(
"constructed packet",
- data->data() + data->length() - sizeof(kTestStatelessResetToken),
- sizeof(kTestStatelessResetToken),
- AsChars(packet) + ABSL_ARRAYSIZE(packet) -
- sizeof(kTestStatelessResetToken),
- sizeof(kTestStatelessResetToken));
+ data->data() + data->length() - kStatelessResetTokenLength,
+ kStatelessResetTokenLength,
+ AsChars(packet) + ABSL_ARRAYSIZE(packet) - kStatelessResetTokenLength,
+ kStatelessResetTokenLength);
}
TEST_P(QuicFramerTest, EncryptPacket) {
@@ -10852,8 +10913,8 @@ TEST_P(QuicFramerTest, NewConnectionIdFrame) {
{"Unable to read new connection ID frame connection id.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x11}},
{"Can not read new connection ID frame reset token.",
- {0xb5, 0x69, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}
+ {0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f}}
};
// clang-format on
@@ -10911,8 +10972,8 @@ TEST_P(QuicFramerTest, NewConnectionIdFrameVariableLength) {
{"Unable to read new connection ID frame connection id.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0x42}},
{"Can not read new connection ID frame reset token.",
- {0xb5, 0x69, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}
+ {0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f}}
};
// clang-format on
@@ -11078,8 +11139,8 @@ TEST_P(QuicFramerTest, BuildNewConnectionIdFramePacket) {
// new connection id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x11,
// stateless reset token
- 0xb5, 0x69, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
};
// clang-format on
@@ -11485,8 +11546,8 @@ TEST_P(QuicFramerTest, GetRetransmittableControlFrameSize) {
return;
}
- QuicNewConnectionIdFrame new_connection_id(5, TestConnectionId(), 1, 101111,
- 1);
+ QuicNewConnectionIdFrame new_connection_id(5, TestConnectionId(), 1,
+ kTestStatelessResetToken, 1);
EXPECT_EQ(QuicFramer::GetNewConnectionIdFrameSize(new_connection_id),
QuicFramer::GetRetransmittableControlFrameSize(
framer_.transport_version(), QuicFrame(&new_connection_id)));
@@ -15164,6 +15225,85 @@ TEST_P(QuicFramerTest, KeyUpdateLocallyInitiatedReceivedOldPacket) {
EXPECT_EQ(1, visitor_.decrypted_first_packet_in_key_phase_count_);
}
+TEST_P(QuicFramerTest, KeyUpdateOnFirstReceivedPacket) {
+ if (!framer_.version().UsesTls()) {
+ // 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.
+ framer_.InstallDecrypter(ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<StrictTaggingDecrypter>(/*key=*/0));
+ framer_.SetKeyUpdateSupportForConnection(true);
+
+ QuicPacketHeader header;
+ header.destination_connection_id = FramerTestConnectionId();
+ header.reset_flag = false;
+ header.version_flag = false;
+ header.packet_number = QuicPacketNumber(123);
+
+ QuicFrames frames = {QuicFrame(QuicPaddingFrame())};
+
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
+ std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
+ ASSERT_TRUE(data != nullptr);
+ std::unique_ptr<QuicEncryptedPacket> encrypted(
+ EncryptPacketWithTagAndPhase(*data, /*tag=*/1, /*phase=*/true));
+ ASSERT_TRUE(encrypted);
+
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
+ EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
+ // Processed valid packet with phase=1, key=1: do key update.
+ EXPECT_EQ(1u, visitor_.key_update_count());
+ EXPECT_EQ(1, visitor_.derive_next_key_count_);
+ EXPECT_EQ(1, visitor_.decrypted_first_packet_in_key_phase_count_);
+}
+
+TEST_P(QuicFramerTest, ErrorWhenUnexpectedFrameTypeEncountered) {
+ if (!GetQuicReloadableFlag(quic_reject_unexpected_ietf_frame_types) ||
+ !VersionHasIetfQuicFrames(framer_.transport_version()) ||
+ !QuicVersionHasLongHeaderLengths(framer_.transport_version()) ||
+ !framer_.version().HasLongHeaderLengths()) {
+ return;
+ }
+ SetDecrypterLevel(ENCRYPTION_ZERO_RTT);
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (long header with packet type ZERO_RTT_PROTECTED and
+ // 4-byte packet number)
+ 0xD3,
+ // version
+ QUIC_VERSION_BYTES,
+ // destination connection ID length
+ 0x08,
+ // destination connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // source connection ID length
+ 0x08,
+ // source connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x11,
+ // long header packet length
+ 0x05,
+ // packet number
+ 0x12, 0x34, 0x56, 0x00,
+ // unexpected ietf ack frame type in 0-RTT packet
+ 0x02,
+ };
+ // clang-format on
+
+ QuicEncryptedPacket encrypted(AsChars(packet), ABSL_ARRAYSIZE(packet), false);
+
+ EXPECT_FALSE(framer_.ProcessPacket(encrypted));
+
+ EXPECT_THAT(framer_.error(), IsError(IETF_QUIC_PROTOCOL_VIOLATION));
+ EXPECT_EQ(
+ "IETF frame type IETF_ACK is unexpected at encryption level "
+ "ENCRYPTION_ZERO_RTT",
+ framer_.detailed_error());
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_interval_deque.h b/chromium/net/third_party/quiche/src/quic/core/quic_interval_deque.h
index d4e82e2d1a2..ba27aa9d8f5 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
@@ -162,7 +162,7 @@ class QUIC_NO_EXPORT QuicIntervalDeque {
// Don't increment when we are at the end.
const std::size_t container_size = deque_->container_.size();
if (index_ >= container_size) {
- QUIC_BUG << "Iterator out of bounds.";
+ QUIC_BUG(quic_bug_10862_1) << "Iterator out of bounds.";
return *this;
}
index_++;
@@ -279,7 +279,7 @@ void QuicIntervalDeque<T, C>::PushBack(const T& item) {
template <class T, class C>
void QuicIntervalDeque<T, C>::PopFront() {
if (container_.size() == 0) {
- QUIC_BUG << "Trying to pop from an empty container.";
+ QUIC_BUG(quic_bug_10862_2) << "Trying to pop from an empty container.";
return;
}
container_.pop_front();
@@ -362,7 +362,8 @@ void QuicIntervalDeque<T, C>::PushBackUniversal(U&& item) {
QuicInterval<std::size_t> interval = item.interval();
// Adding an empty interval is a bug.
if (interval.Empty()) {
- QUIC_BUG << "Trying to save empty interval to QuicCircularDeque.";
+ QUIC_BUG(quic_bug_10862_3)
+ << "Trying to save empty interval to QuicCircularDeque.";
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 bfe2df2fce0..27dbb9b48a8 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
@@ -46,12 +46,12 @@ void QuicLegacyVersionEncapsulator::OnSerializedPacket(
SerializedPacket serialized_packet) {
if (encrypted_length_ != 0) {
unrecoverable_failure_encountered_ = true;
- QUIC_BUG << "OnSerializedPacket called twice";
+ QUIC_BUG(quic_bug_10615_1) << "OnSerializedPacket called twice";
return;
}
if (serialized_packet.encrypted_length == 0) {
unrecoverable_failure_encountered_ = true;
- QUIC_BUG << "OnSerializedPacket called with empty packet";
+ QUIC_BUG(quic_bug_10615_2) << "OnSerializedPacket called with empty packet";
return;
}
encrypted_length_ = serialized_packet.encrypted_length;
@@ -61,8 +61,8 @@ void QuicLegacyVersionEncapsulator::OnUnrecoverableError(
QuicErrorCode error,
const std::string& error_details) {
unrecoverable_failure_encountered_ = true;
- QUIC_BUG << "QuicLegacyVersionEncapsulator received error " << error << ": "
- << error_details;
+ QUIC_BUG(quic_bug_10615_3) << "QuicLegacyVersionEncapsulator received error "
+ << error << ": " << error_details;
}
bool QuicLegacyVersionEncapsulator::ShouldGeneratePacket(
@@ -120,23 +120,26 @@ QuicPacketLength QuicLegacyVersionEncapsulator::Encapsulate(
outer_creator.SetTransmissionType(NOT_RETRANSMISSION);
if (!outer_creator.AddPaddedSavedFrame(QuicFrame(outer_stream_frame),
NOT_RETRANSMISSION)) {
- QUIC_BUG << "Failed to add Legacy Version Encapsulation stream frame "
- "(max packet length is "
- << outer_creator.max_packet_length() << ") " << outer_stream_frame;
+ QUIC_BUG(quic_bug_10615_4)
+ << "Failed to add Legacy Version Encapsulation stream frame "
+ "(max packet length is "
+ << outer_creator.max_packet_length() << ") " << outer_stream_frame;
return 0;
}
outer_creator.FlushCurrentPacket();
const QuicPacketLength encrypted_length = creator_delegate.encrypted_length_;
if (creator_delegate.unrecoverable_failure_encountered_ ||
encrypted_length == 0) {
- QUIC_BUG << "Failed to perform Legacy Version Encapsulation of "
- << inner_packet.length() << " bytes";
+ QUIC_BUG(quic_bug_10615_5)
+ << "Failed to perform Legacy Version Encapsulation of "
+ << inner_packet.length() << " bytes";
return 0;
}
if (encrypted_length > kMaxOutgoingPacketSize) {
- QUIC_BUG << "Legacy Version Encapsulation outer creator generated a "
- "packet with unexpected length "
- << encrypted_length;
+ QUIC_BUG(quic_bug_10615_6)
+ << "Legacy Version Encapsulation outer creator generated a "
+ "packet with unexpected length "
+ << encrypted_length;
return 0;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_linux_socket_utils.cc b/chromium/net/third_party/quiche/src/quic/core/quic_linux_socket_utils.cc
index c2931afe02e..888b658eec0 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_linux_socket_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_linux_socket_utils.cc
@@ -229,7 +229,7 @@ void QuicLinuxSocketUtils::SetIpInfoInCmsgData(
in6_pktinfo* pktinfo = static_cast<in6_pktinfo*>(cmsg_data);
memcpy(&pktinfo->ipi6_addr, address_str.c_str(), address_str.length());
} else {
- QUIC_BUG << "Unrecognized IPAddress";
+ QUIC_BUG(quic_bug_10598_1) << "Unrecognized IPAddress";
}
}
@@ -259,7 +259,7 @@ size_t QuicLinuxSocketUtils::SetIpInfoInCmsg(const QuicIpAddress& self_address,
address_string.length());
return sizeof(in6_pktinfo);
} else {
- QUIC_BUG << "Unrecognized IPAddress";
+ QUIC_BUG(quic_bug_10598_2) << "Unrecognized IPAddress";
return 0;
}
}
@@ -300,8 +300,9 @@ WriteResult QuicLinuxSocketUtils::WriteMultiplePackets(int fd,
return WriteResult(WRITE_STATUS_OK, mhdr->num_bytes_sent(rc));
} else if (rc == 0) {
- QUIC_BUG << "sendmmsg returned 0, returning WRITE_STATUS_ERROR. errno: "
- << errno;
+ QUIC_BUG(quic_bug_10598_3)
+ << "sendmmsg returned 0, returning WRITE_STATUS_ERROR. errno: "
+ << errno;
errno = EIO;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.cc b/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.cc
index a79810f9aa0..5281ffb980a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.cc
@@ -36,7 +36,7 @@ QuicNetworkBlackholeDetector::QuicNetworkBlackholeDetector(
void QuicNetworkBlackholeDetector::OnAlarm() {
QuicTime next_deadline = GetEarliestDeadline();
if (!next_deadline.IsInitialized()) {
- QUIC_BUG << "BlackholeDetector alarm fired unexpectedly";
+ QUIC_BUG(quic_bug_10328_1) << "BlackholeDetector alarm fired unexpectedly";
return;
}
@@ -79,8 +79,8 @@ void QuicNetworkBlackholeDetector::RestartDetection(
blackhole_deadline_ = blackhole_deadline;
path_mtu_reduction_deadline_ = path_mtu_reduction_deadline;
- QUIC_BUG_IF(blackhole_deadline_.IsInitialized() &&
- blackhole_deadline_ != GetLastDeadline())
+ QUIC_BUG_IF(quic_bug_12708_1, blackhole_deadline_.IsInitialized() &&
+ blackhole_deadline_ != GetLastDeadline())
<< "Blackhole detection deadline should be the last deadline.";
UpdateAlarm();
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_one_block_arena.h b/chromium/net/third_party/quiche/src/quic/core/quic_one_block_arena.h
index 8311477219c..53882ead440 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_one_block_arena.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_one_block_arena.h
@@ -38,9 +38,10 @@ class QUIC_EXPORT_PRIVATE QuicOneBlockArena {
static_assert(alignof(T) > 1,
"Objects added to the arena must be at least 2B aligned.");
if (QUIC_PREDICT_FALSE(offset_ > ArenaSize - AlignedSize<T>())) {
- QUIC_BUG << "Ran out of space in QuicOneBlockArena at " << this
- << ", max size was " << ArenaSize << ", failing request was "
- << AlignedSize<T>() << ", end of arena was " << offset_;
+ QUIC_BUG(quic_bug_10593_1)
+ << "Ran out of space in QuicOneBlockArena at " << this
+ << ", max size was " << ArenaSize << ", failing request was "
+ << AlignedSize<T>() << ", end of arena was " << offset_;
return QuicArenaScopedPtr<T>(new T(std::forward<Args>(args)...));
}
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 9dabd3af78f..42aebe5ce4b 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
@@ -46,12 +46,12 @@ QuicLongHeaderType EncryptionlevelToLongHeaderType(EncryptionLevel level) {
case ENCRYPTION_ZERO_RTT:
return ZERO_RTT_PROTECTED;
case ENCRYPTION_FORWARD_SECURE:
- QUIC_BUG
+ QUIC_BUG(quic_bug_12398_1)
<< "Try to derive long header type for packet with encryption level: "
<< level;
return INVALID_PACKET_TYPE;
default:
- QUIC_BUG << level;
+ QUIC_BUG(quic_bug_10752_1) << level;
return INVALID_PACKET_TYPE;
}
}
@@ -171,8 +171,8 @@ void QuicPacketCreator::SetMaxPacketLength(QuicByteCount length) {
max_packet_length_ = length;
max_plaintext_size_ = framer_->GetMaxPlaintextSize(max_packet_length_);
- QUIC_BUG_IF(max_plaintext_size_ - PacketHeaderSize() <
- MinPlaintextPacketSize(framer_->version()))
+ QUIC_BUG_IF(quic_bug_12398_2, max_plaintext_size_ - PacketHeaderSize() <
+ MinPlaintextPacketSize(framer_->version()))
<< "Attempted to set max packet length too small";
}
@@ -194,9 +194,10 @@ void QuicPacketCreator::SetMaxDatagramFrameSize(
void QuicPacketCreator::SetSoftMaxPacketLength(QuicByteCount length) {
QUICHE_DCHECK(CanSetMaxPacketLength());
if (length > max_packet_length_) {
- QUIC_BUG << ENDPOINT
- << "Try to increase max_packet_length_ in "
- "SetSoftMaxPacketLength, use SetMaxPacketLength instead.";
+ QUIC_BUG(quic_bug_10752_2)
+ << ENDPOINT
+ << "Try to increase max_packet_length_ in "
+ "SetSoftMaxPacketLength, use SetMaxPacketLength instead.";
return;
}
if (framer_->GetMaxPlaintextSize(length) <
@@ -238,10 +239,10 @@ void QuicPacketCreator::UpdatePacketNumberLength(
QuicPacketCount max_packets_in_flight) {
if (!queued_frames_.empty()) {
// Don't change creator state if there are frames queued.
- QUIC_BUG << "Called UpdatePacketNumberLength with " << queued_frames_.size()
- << " queued_frames. First frame type:"
- << queued_frames_.front().type
- << " last frame type:" << queued_frames_.back().type;
+ QUIC_BUG(quic_bug_10752_3)
+ << "Called UpdatePacketNumberLength with " << queued_frames_.size()
+ << " queued_frames. First frame type:" << queued_frames_.front().type
+ << " last frame type:" << queued_frames_.back().type;
return;
}
@@ -271,10 +272,10 @@ void QuicPacketCreator::SkipNPacketNumbers(
QuicPacketCount max_packets_in_flight) {
if (!queued_frames_.empty()) {
// Don't change creator state if there are frames queued.
- QUIC_BUG << "Called SkipNPacketNumbers with " << queued_frames_.size()
- << " queued_frames. First frame type:"
- << queued_frames_.front().type
- << " last frame type:" << queued_frames_.back().type;
+ QUIC_BUG(quic_bug_10752_4)
+ << "Called SkipNPacketNumbers with " << queued_frames_.size()
+ << " queued_frames. First frame type:" << queued_frames_.front().type
+ << " last frame type:" << queued_frames_.back().type;
return;
}
if (packet_.packet_number > packet_.packet_number + count) {
@@ -336,9 +337,9 @@ bool QuicPacketCreator::ConsumeDataToFillCurrentPacket(
frame->stream_frame.data_length < data_size) {
const std::string error_details =
"Client hello won't fit in a single packet.";
- QUIC_BUG << error_details << " Constructed stream frame length: "
- << frame->stream_frame.data_length
- << " CHLO length: " << data_size;
+ QUIC_BUG(quic_bug_10752_5)
+ << 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;
}
@@ -423,13 +424,13 @@ void QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
GetRetryTokenLengthLength(), GetLengthLength(), offset) ||
latched_hard_max_packet_length_ > 0);
- QUIC_BUG_IF(!HasRoomForStreamFrame(id, offset, data_size))
+ QUIC_BUG_IF(quic_bug_12398_3, !HasRoomForStreamFrame(id, offset, data_size))
<< "No room for Stream frame, BytesFree: " << BytesFree()
<< " MinStreamFrameSize: "
<< QuicFramer::GetMinStreamFrameSize(framer_->transport_version(), id,
offset, true, data_size);
- QUIC_BUG_IF(data_size == 0 && !fin)
+ QUIC_BUG_IF(quic_bug_12398_4, data_size == 0 && !fin)
<< "Creating a stream frame for stream ID:" << id
<< " with no data or fin.";
size_t min_frame_size = QuicFramer::GetMinStreamFrameSize(
@@ -479,7 +480,7 @@ void QuicPacketCreator::FlushCurrentPacket() {
}
void QuicPacketCreator::OnSerializedPacket() {
- QUIC_BUG_IF(packet_.encrypted_buffer == nullptr);
+ QUIC_BUG_IF(quic_bug_12398_5, packet_.encrypted_buffer == nullptr);
SerializedPacket packet(std::move(packet_));
ClearPacket();
@@ -497,7 +498,7 @@ void QuicPacketCreator::ClearPacket() {
packet_.has_ack_frequency = false;
packet_.has_message = false;
packet_.fate = SEND_TO_WRITER;
- QUIC_BUG_IF(packet_.release_encrypted_buffer != nullptr)
+ QUIC_BUG_IF(quic_bug_12398_6, packet_.release_encrypted_buffer != nullptr)
<< "packet_.release_encrypted_buffer should be empty";
packet_.release_encrypted_buffer = nullptr;
QUICHE_DCHECK(packet_.retransmittable_frames.empty());
@@ -511,9 +512,9 @@ size_t QuicPacketCreator::ReserializeInitialPacketInCoalescedPacket(
size_t padding_size,
char* buffer,
size_t buffer_len) {
- QUIC_BUG_IF(packet.encryption_level != ENCRYPTION_INITIAL);
- QUIC_BUG_IF(packet.nonretransmittable_frames.empty() &&
- packet.retransmittable_frames.empty())
+ 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())
<< "Attempt to serialize empty ENCRYPTION_INITIAL packet in coalesced "
"packet";
ScopedPacketContextSwitcher switcher(
@@ -522,13 +523,13 @@ 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 << "Failed to serialize frame: " << frame;
+ QUIC_BUG(quic_bug_10752_6) << "Failed to serialize frame: " << frame;
return 0;
}
}
for (const QuicFrame& frame : packet.retransmittable_frames) {
if (!AddFrame(frame, packet.transmission_type)) {
- QUIC_BUG << "Failed to serialize frame: " << frame;
+ QUIC_BUG(quic_bug_10752_7) << "Failed to serialize frame: " << frame;
return 0;
}
}
@@ -537,9 +538,10 @@ size_t QuicPacketCreator::ReserializeInitialPacketInCoalescedPacket(
QUIC_DVLOG(2) << ENDPOINT << "Add padding of size: " << padding_size;
if (!AddFrame(QuicFrame(QuicPaddingFrame(padding_size)),
packet.transmission_type)) {
- QUIC_BUG << "Failed to add padding of size " << padding_size
- << " when serializing ENCRYPTION_INITIAL "
- "packet in coalesced packet";
+ QUIC_BUG(quic_bug_10752_8)
+ << "Failed to add padding of size " << padding_size
+ << " when serializing ENCRYPTION_INITIAL "
+ "packet in coalesced packet";
return 0;
}
}
@@ -588,12 +590,12 @@ void QuicPacketCreator::CreateAndSerializeStreamFrame(
QuicDataWriter writer(kMaxOutgoingPacketSize, encrypted_buffer);
size_t length_field_offset = 0;
if (!framer_->AppendPacketHeader(header, &writer, &length_field_offset)) {
- QUIC_BUG << "AppendPacketHeader failed";
+ QUIC_BUG(quic_bug_10752_9) << "AppendPacketHeader failed";
return;
}
// Create a Stream frame with the remaining space.
- QUIC_BUG_IF(iov_offset == write_length && !fin)
+ QUIC_BUG_IF(quic_bug_12398_9, iov_offset == write_length && !fin)
<< "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(
@@ -629,18 +631,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 << "AppendTypeByte failed";
+ QUIC_BUG(quic_bug_10752_10) << "AppendTypeByte failed";
return;
}
if (!framer_->AppendStreamFrame(frame, omit_frame_length, &writer)) {
- QUIC_BUG << "AppendStreamFrame failed";
+ QUIC_BUG(quic_bug_10752_11) << "AppendStreamFrame failed";
return;
}
if (needs_padding &&
plaintext_bytes_written < MinPlaintextPacketSize(framer_->version()) &&
!writer.WritePaddingBytes(MinPlaintextPacketSize(framer_->version()) -
plaintext_bytes_written)) {
- QUIC_BUG << "Unable to add padding bytes";
+ QUIC_BUG(quic_bug_10752_12) << "Unable to add padding bytes";
return;
}
@@ -659,7 +661,8 @@ void QuicPacketCreator::CreateAndSerializeStreamFrame(
GetStartOfEncryptedData(framer_->transport_version(), header),
writer.length(), kMaxOutgoingPacketSize, encrypted_buffer);
if (encrypted_length == 0) {
- QUIC_BUG << "Failed to encrypt packet number " << header.packet_number;
+ QUIC_BUG(quic_bug_10752_13)
+ << "Failed to encrypt packet number " << header.packet_number;
return;
}
// TODO(ianswett): Optimize the storage so RetransmitableFrames can be
@@ -745,7 +748,7 @@ bool QuicPacketCreator::SerializePacket(QuicOwnedPacketBuffer encrypted_buffer,
if (packet_.encrypted_buffer != nullptr) {
const std::string error_details =
"Packet's encrypted buffer is not empty before serialization";
- QUIC_BUG << error_details;
+ QUIC_BUG(quic_bug_10752_14) << error_details;
delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET,
error_details);
return false;
@@ -753,7 +756,8 @@ bool QuicPacketCreator::SerializePacket(QuicOwnedPacketBuffer encrypted_buffer,
ScopedSerializationFailureHandler handler(this);
QUICHE_DCHECK_LT(0u, encrypted_buffer_len);
- QUIC_BUG_IF(queued_frames_.empty() && pending_padding_bytes_ == 0)
+ QUIC_BUG_IF(quic_bug_12398_10,
+ queued_frames_.empty() && pending_padding_bytes_ == 0)
<< "Attempt to serialize empty packet";
QuicPacketHeader header;
// FillPacketHeader increments packet_number_.
@@ -778,10 +782,10 @@ bool QuicPacketCreator::SerializePacket(QuicOwnedPacketBuffer encrypted_buffer,
if (!framer_->HasEncrypterOfEncryptionLevel(packet_.encryption_level)) {
// TODO(fayang): Use QUIC_MISSING_WRITE_KEYS for serialization failures due
// to missing keys.
- QUIC_BUG << ENDPOINT << "Attempting to serialize " << header
- << QuicFramesToString(queued_frames_)
- << " at missing encryption_level " << packet_.encryption_level
- << " using " << framer_->version();
+ QUIC_BUG(quic_bug_10752_15)
+ << ENDPOINT << "Attempting to serialize " << header
+ << QuicFramesToString(queued_frames_) << " at missing encryption_level "
+ << packet_.encryption_level << " using " << framer_->version();
return false;
}
@@ -792,14 +796,15 @@ bool QuicPacketCreator::SerializePacket(QuicOwnedPacketBuffer encrypted_buffer,
framer_->BuildDataPacket(header, queued_frames_, encrypted_buffer.buffer,
packet_size_, packet_.encryption_level);
if (length == 0) {
- QUIC_BUG << "Failed to serialize " << QuicFramesToString(queued_frames_)
- << " at encryption_level: " << packet_.encryption_level
- << ", needs_full_padding_: " << needs_full_padding_
- << ", pending_padding_bytes_: " << pending_padding_bytes_
- << ", latched_hard_max_packet_length_: "
- << latched_hard_max_packet_length_
- << ", max_packet_length_: " << max_packet_length_
- << ", header: " << header;
+ QUIC_BUG(quic_bug_10752_16)
+ << "Failed to serialize " << QuicFramesToString(queued_frames_)
+ << " at encryption_level: " << packet_.encryption_level
+ << ", needs_full_padding_: " << needs_full_padding_
+ << ", pending_padding_bytes_: " << pending_padding_bytes_
+ << ", latched_hard_max_packet_length_: "
+ << latched_hard_max_packet_length_
+ << ", max_packet_length_: " << max_packet_length_
+ << ", header: " << header;
return false;
}
@@ -820,7 +825,8 @@ bool QuicPacketCreator::SerializePacket(QuicOwnedPacketBuffer encrypted_buffer,
GetStartOfEncryptedData(framer_->transport_version(), header), length,
encrypted_buffer_len, encrypted_buffer.buffer);
if (encrypted_length == 0) {
- QUIC_BUG << "Failed to encrypt packet number " << packet_.packet_number;
+ QUIC_BUG(quic_bug_10752_17)
+ << "Failed to encrypt packet number " << packet_.packet_number;
return false;
}
@@ -835,7 +841,8 @@ bool QuicPacketCreator::SerializePacket(QuicOwnedPacketBuffer encrypted_buffer,
std::unique_ptr<SerializedPacket>
QuicPacketCreator::SerializeConnectivityProbingPacket() {
- QUIC_BUG_IF(VersionHasIetfQuicFrames(framer_->transport_version()))
+ QUIC_BUG_IF(quic_bug_12398_11,
+ VersionHasIetfQuicFrames(framer_->transport_version()))
<< "Must not be version 99 to serialize padded ping connectivity probe";
RemoveSoftMaxPacketLength();
QuicPacketHeader header;
@@ -873,7 +880,8 @@ QuicPacketCreator::SerializeConnectivityProbingPacket() {
std::unique_ptr<SerializedPacket>
QuicPacketCreator::SerializePathChallengeConnectivityProbingPacket(
const QuicPathFrameBuffer& payload) {
- QUIC_BUG_IF(!VersionHasIetfQuicFrames(framer_->transport_version()))
+ QUIC_BUG_IF(quic_bug_12398_12,
+ !VersionHasIetfQuicFrames(framer_->transport_version()))
<< "Must be version 99 to serialize path challenge connectivity probe, "
"is version "
<< framer_->transport_version();
@@ -915,7 +923,8 @@ std::unique_ptr<SerializedPacket>
QuicPacketCreator::SerializePathResponseConnectivityProbingPacket(
const QuicCircularDeque<QuicPathFrameBuffer>& payloads,
const bool is_padded) {
- QUIC_BUG_IF(!VersionHasIetfQuicFrames(framer_->transport_version()))
+ QUIC_BUG_IF(quic_bug_12398_13,
+ !VersionHasIetfQuicFrames(framer_->transport_version()))
<< "Must be version 99 to serialize path response connectivity probe, is "
"version "
<< framer_->transport_version();
@@ -986,7 +995,7 @@ size_t QuicPacketCreator::BuildPathResponsePacket(
const bool is_padded,
EncryptionLevel level) {
if (payloads.empty()) {
- QUIC_BUG
+ QUIC_BUG(quic_bug_12398_14)
<< "Attempt to generate connectivity response with no request payloads";
return 0;
}
@@ -1042,11 +1051,12 @@ size_t QuicPacketCreator::SerializeCoalescedPacket(
char* buffer,
size_t buffer_len) {
if (HasPendingFrames()) {
- QUIC_BUG << "Try to serialize coalesced packet with pending frames";
+ QUIC_BUG(quic_bug_10752_18)
+ << "Try to serialize coalesced packet with pending frames";
return 0;
}
RemoveSoftMaxPacketLength();
- QUIC_BUG_IF(coalesced.length() == 0)
+ QUIC_BUG_IF(quic_bug_12398_15, coalesced.length() == 0)
<< "Attempt to serialize empty coalesced packet";
size_t packet_length = 0;
if (coalesced.initial_packet() != nullptr) {
@@ -1062,8 +1072,9 @@ size_t QuicPacketCreator::SerializeCoalescedPacket(
size_t initial_length = ReserializeInitialPacketInCoalescedPacket(
*coalesced.initial_packet(), padding_size, buffer, buffer_len);
if (initial_length == 0) {
- QUIC_BUG << "Failed to reserialize ENCRYPTION_INITIAL packet in "
- "coalesced packet";
+ QUIC_BUG(quic_bug_10752_19)
+ << "Failed to reserialize ENCRYPTION_INITIAL packet in "
+ "coalesced packet";
return 0;
}
buffer += initial_length;
@@ -1187,8 +1198,9 @@ void QuicPacketCreator::SetRetryToken(absl::string_view retry_token) {
bool QuicPacketCreator::ConsumeRetransmittableControlFrame(
const QuicFrame& frame) {
- QUIC_BUG_IF(IsControlFrame(frame.type) && !GetControlFrameId(frame) &&
- frame.type != PING_FRAME)
+ QUIC_BUG_IF(quic_bug_12398_16, IsControlFrame(frame.type) &&
+ !GetControlFrameId(frame) &&
+ frame.type != PING_FRAME)
<< "Adding a control frame with no control frame id: " << frame;
QUICHE_DCHECK(QuicUtils::IsRetransmittableFrame(frame.type)) << frame;
MaybeBundleAckOpportunistically();
@@ -1206,8 +1218,9 @@ bool QuicPacketCreator::ConsumeRetransmittableControlFrame(
return false;
}
const bool success = AddFrame(frame, next_transmission_type_);
- QUIC_BUG_IF(!success) << "Failed to add frame:" << frame
- << " transmission_type:" << next_transmission_type_;
+ QUIC_BUG_IF(quic_bug_10752_20, !success)
+ << "Failed to add frame:" << frame
+ << " transmission_type:" << next_transmission_type_;
return success;
}
@@ -1215,12 +1228,13 @@ QuicConsumedData QuicPacketCreator::ConsumeData(QuicStreamId id,
size_t write_length,
QuicStreamOffset offset,
StreamSendingState state) {
- QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
- "generator tries to write stream data.";
+ QUIC_BUG_IF(quic_bug_10752_21, !flusher_attached_)
+ << "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(has_handshake && fin)
+ QUIC_BUG_IF(quic_bug_12398_17, has_handshake && fin)
<< "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.
@@ -1236,7 +1250,7 @@ QuicConsumedData QuicPacketCreator::ConsumeData(QuicStreamId id,
}
if (!fin && (write_length == 0)) {
- QUIC_BUG << "Attempt to consume empty data without FIN.";
+ QUIC_BUG(quic_bug_10752_22) << "Attempt to consume empty data without FIN.";
return QuicConsumedData(0, false);
}
// We determine if we can enter the fast path before executing
@@ -1259,7 +1273,7 @@ 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 << "Failed to ConsumeData, stream:" << id;
+ QUIC_BUG(quic_bug_10752_23) << "Failed to ConsumeData, stream:" << id;
return QuicConsumedData(0, false);
}
@@ -1323,7 +1337,7 @@ QuicConsumedData QuicPacketCreator::ConsumeDataFastPath(
if (bytes_consumed == 0) {
const std::string error_details =
"Failed in CreateAndSerializeStreamFrame.";
- QUIC_BUG << error_details;
+ QUIC_BUG(quic_bug_10752_24) << error_details;
delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET,
error_details);
break;
@@ -1340,8 +1354,9 @@ size_t QuicPacketCreator::ConsumeCryptoData(EncryptionLevel level,
QuicStreamOffset offset) {
QUIC_DVLOG(2) << "ConsumeCryptoData " << level << " write_length "
<< write_length << " offset " << offset;
- QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
- "generator tries to write crypto data.";
+ QUIC_BUG_IF(quic_bug_10752_25, !flusher_attached_)
+ << "Packet flusher is not attached when "
+ "generator tries to write crypto data.";
MaybeBundleAckOpportunistically();
// To make reasoning about crypto frames easier, we don't combine them with
// other retransmittable frames in a single packet.
@@ -1365,7 +1380,8 @@ size_t QuicPacketCreator::ConsumeCryptoData(EncryptionLevel level,
// The only pending data in the packet is non-retransmittable frames. I'm
// assuming here that they won't occupy so much of the packet that a
// CRYPTO frame won't fit.
- QUIC_BUG << "Failed to ConsumeCryptoData at level " << level;
+ QUIC_BUG(quic_bug_10752_26)
+ << "Failed to ConsumeCryptoData at level " << level;
return 0;
}
total_bytes_consumed += frame.crypto_frame->data_length;
@@ -1381,8 +1397,9 @@ size_t QuicPacketCreator::ConsumeCryptoData(EncryptionLevel level,
void QuicPacketCreator::GenerateMtuDiscoveryPacket(QuicByteCount target_mtu) {
// MTU discovery frames must be sent by themselves.
if (!CanSetMaxPacketLength()) {
- QUIC_BUG << "MTU discovery packets should only be sent when no other "
- << "frames needs to be sent.";
+ QUIC_BUG(quic_bug_10752_27)
+ << "MTU discovery packets should only be sent when no other "
+ << "frames needs to be sent.";
return;
}
const QuicByteCount current_mtu = max_packet_length();
@@ -1398,8 +1415,9 @@ void QuicPacketCreator::GenerateMtuDiscoveryPacket(QuicByteCount target_mtu) {
FlushCurrentPacket();
// 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(!success) << "Failed to send path MTU target_mtu:" << target_mtu
- << " transmission_type:" << next_transmission_type_;
+ QUIC_BUG_IF(quic_bug_10752_28, !success)
+ << "Failed to send path MTU target_mtu:" << target_mtu
+ << " transmission_type:" << next_transmission_type_;
// Reset the packet length back.
SetMaxPacketLength(current_mtu);
@@ -1416,17 +1434,20 @@ void QuicPacketCreator::MaybeBundleAckOpportunistically() {
}
const bool flushed =
FlushAckFrame(delegate_->MaybeBundleAckOpportunistically());
- QUIC_BUG_IF(!flushed) << "Failed to flush ACK frame. encryption_level:"
- << packet_.encryption_level;
+ QUIC_BUG_IF(quic_bug_10752_29, !flushed)
+ << "Failed to flush ACK frame. encryption_level:"
+ << packet_.encryption_level;
}
bool QuicPacketCreator::FlushAckFrame(const QuicFrames& frames) {
- QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
- "generator tries to send ACK frame.";
+ QUIC_BUG_IF(quic_bug_10752_30, !flusher_attached_)
+ << "Packet flusher is not attached when "
+ "generator tries to send ACK frame.";
// MaybeBundleAckOpportunistically could be called nestedly when sending a
// control frame causing another control frame to be sent.
- QUIC_BUG_IF(GetQuicReloadableFlag(quic_single_ack_in_packet2) &&
- !frames.empty() && has_ack())
+ 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";
for (const auto& frame : frames) {
QUICHE_DCHECK(frame.type == ACK_FRAME || frame.type == STOP_WAITING_FRAME);
@@ -1444,7 +1465,7 @@ bool QuicPacketCreator::FlushAckFrame(const QuicFrames& frames) {
return false;
}
const bool success = AddFrame(frame, next_transmission_type_);
- QUIC_BUG_IF(!success) << "Failed to flush " << frame;
+ QUIC_BUG_IF(quic_bug_10752_31, !success) << "Failed to flush " << frame;
}
return true;
}
@@ -1466,7 +1487,8 @@ void QuicPacketCreator::Flush() {
flusher_attached_ = false;
if (GetQuicFlag(FLAGS_quic_export_write_path_stats_at_server)) {
if (!write_start_packet_number_.IsInitialized()) {
- QUIC_BUG << "write_start_packet_number is not initialized";
+ QUIC_BUG(quic_bug_10752_32)
+ << "write_start_packet_number is not initialized";
return;
}
QUIC_SERVER_HISTOGRAM_COUNTS(
@@ -1499,8 +1521,9 @@ void QuicPacketCreator::SetTransmissionType(TransmissionType type) {
MessageStatus QuicPacketCreator::AddMessageFrame(QuicMessageId message_id,
QuicMemSliceSpan message) {
- QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
- "generator tries to add message frame.";
+ QUIC_BUG_IF(quic_bug_10752_33, !flusher_attached_)
+ << "Packet flusher is not attached when "
+ "generator tries to add message frame.";
MaybeBundleAckOpportunistically();
const QuicByteCount message_length = message.total_length();
if (message_length > GetCurrentLargestMessagePayload()) {
@@ -1512,7 +1535,7 @@ 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 << "Failed to send message " << message_id;
+ QUIC_BUG(quic_bug_10752_34) << "Failed to send message " << message_id;
delete frame;
return MESSAGE_STATUS_INTERNAL_ERROR;
}
@@ -1576,7 +1599,7 @@ size_t QuicPacketCreator::GetSerializedFrameLength(const QuicFrame& frame) {
return serialized_frame_length;
}
if (BytesFree() < serialized_frame_length) {
- QUIC_BUG << ENDPOINT << "Frame does not fit: " << frame;
+ QUIC_BUG(quic_bug_10752_35) << ENDPOINT << "Frame does not fit: " << frame;
return 0;
}
// Please note bytes_free does not take |frame|'s expansion into account.
@@ -1604,6 +1627,21 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
return false;
}
+ // Sanity check to ensure we don't send frames at the wrong encryption level.
+ QUICHE_DCHECK(
+ packet_.encryption_level == ENCRYPTION_ZERO_RTT ||
+ packet_.encryption_level == ENCRYPTION_FORWARD_SECURE ||
+ (frame.type != GOAWAY_FRAME && frame.type != WINDOW_UPDATE_FRAME &&
+ frame.type != HANDSHAKE_DONE_FRAME &&
+ frame.type != NEW_CONNECTION_ID_FRAME &&
+ frame.type != MAX_STREAMS_FRAME && frame.type != STREAMS_BLOCKED_FRAME &&
+ frame.type != PATH_RESPONSE_FRAME &&
+ frame.type != PATH_CHALLENGE_FRAME && frame.type != STOP_SENDING_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;
+
if (frame.type == STREAM_FRAME) {
if (MaybeCoalesceStreamFrame(frame.stream_frame)) {
LogCoalesceStreamFrameStatus(true);
@@ -1775,8 +1813,9 @@ void QuicPacketCreator::MaybeAddPadding() {
bool success = AddFrame(QuicFrame(QuicPaddingFrame(padding_bytes)),
packet_.transmission_type);
- QUIC_BUG_IF(!success) << "Failed to add padding_bytes: " << padding_bytes
- << " transmission_type: " << packet_.transmission_type;
+ QUIC_BUG_IF(quic_bug_10752_36, !success)
+ << "Failed to add padding_bytes: " << padding_bytes
+ << " transmission_type: " << packet_.transmission_type;
}
bool QuicPacketCreator::IncludeNonceInPublicHeader() const {
@@ -1901,7 +1940,7 @@ bool QuicPacketCreator::AttemptingToSendUnencryptedStreamData() {
const std::string error_details =
absl::StrCat("Cannot send stream data with level: ",
EncryptionLevelToString(packet_.encryption_level));
- QUIC_BUG << error_details;
+ QUIC_BUG(quic_bug_10752_37) << error_details;
delegate_->OnUnrecoverableError(QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA,
error_details);
return true;
@@ -1970,7 +2009,8 @@ QuicPacketCreator::ScopedPeerAddressContext::ScopedPeerAddressContext(
QuicPacketCreator* creator,
QuicSocketAddress address)
: creator_(creator), old_peer_address_(creator_->packet_.peer_address) {
- QUIC_BUG_IF(!creator_->packet_.peer_address.IsInitialized())
+ QUIC_BUG_IF(quic_bug_12398_19,
+ !creator_->packet_.peer_address.IsInitialized())
<< "Context is used before seralized packet's peer address is "
"initialized.";
creator_->SetDefaultPeerAddress(address);
@@ -1994,7 +2034,7 @@ QuicPacketCreator::ScopedSerializationFailureHandler::
if (creator_->packet_.encrypted_buffer == nullptr) {
const std::string error_details = "Failed to SerializePacket.";
- QUIC_BUG << error_details;
+ QUIC_BUG(quic_bug_10752_38) << error_details;
creator_->delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET,
error_details);
}
@@ -2010,6 +2050,12 @@ void QuicPacketCreator::set_encryption_level(EncryptionLevel level) {
void QuicPacketCreator::AddPathChallengeFrame(
const QuicPathFrameBuffer& payload) {
+ // TODO(danzh) Unify similar checks at several entry points into one in
+ // AddFrame(). Sort out test helper functions and peer class that don't
+ // enforce this check.
+ QUIC_BUG_IF(quic_bug_10752_39, !flusher_attached_)
+ << "Packet flusher is not attached when "
+ "generator tries to write stream data.";
// Write a PATH_CHALLENGE frame, which has a random 8-byte payload.
auto path_challenge_frame = new QuicPathChallengeFrame(0, payload);
QuicFrame frame(path_challenge_frame);
@@ -2035,7 +2081,7 @@ bool QuicPacketCreator::AddPathResponseFrame(
}
QUIC_DVLOG(1) << ENDPOINT << "Can't send PATH_RESPONSE now";
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_send_path_response, 5, 5);
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_send_path_response2, 5, 5);
delete path_response;
return false;
}
@@ -2054,7 +2100,7 @@ bool QuicPacketCreator::AddPaddedFrameWithRetry(const QuicFrame& frame) {
return false;
}
bool success = AddPaddedSavedFrame(frame, NOT_RETRANSMISSION);
- QUIC_BUG_IF(!success);
+ QUIC_BUG_IF(quic_bug_12398_20, !success);
return true;
}
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 8ff44c1f96f..5986bd2890f 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
@@ -25,7 +25,6 @@
#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_ptr_util.h"
#include "quic/platform/api/quic_socket_address.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_framer_peer.h"
@@ -299,7 +298,9 @@ TEST_P(QuicPacketCreatorTest, SerializeFrames) {
for (int i = ENCRYPTION_INITIAL; i < NUM_ENCRYPTION_LEVELS; ++i) {
EncryptionLevel level = static_cast<EncryptionLevel>(i);
creator_.set_encryption_level(level);
- frames_.push_back(QuicFrame(new QuicAckFrame(InitAckFrame(1))));
+ if (level != ENCRYPTION_ZERO_RTT) {
+ frames_.push_back(QuicFrame(new QuicAckFrame(InitAckFrame(1))));
+ }
QuicStreamId stream_id = QuicUtils::GetFirstBidirectionalStreamId(
client_framer_.transport_version(), Perspective::IS_CLIENT);
if (level != ENCRYPTION_INITIAL && level != ENCRYPTION_HANDSHAKE) {
@@ -308,7 +309,9 @@ TEST_P(QuicPacketCreatorTest, SerializeFrames) {
}
SerializedPacket serialized = SerializeAllFrames(frames_);
EXPECT_EQ(level, serialized.encryption_level);
- delete frames_[0].ack_frame;
+ if (level != ENCRYPTION_ZERO_RTT) {
+ delete frames_[0].ack_frame;
+ }
frames_.clear();
{
@@ -318,13 +321,15 @@ TEST_P(QuicPacketCreatorTest, SerializeFrames) {
EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_, _));
EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnAckFrameStart(_, _))
- .WillOnce(Return(true));
- EXPECT_CALL(framer_visitor_,
- OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)))
- .WillOnce(Return(true));
- EXPECT_CALL(framer_visitor_, OnAckFrameEnd(QuicPacketNumber(1)))
- .WillOnce(Return(true));
+ if (level != ENCRYPTION_ZERO_RTT) {
+ EXPECT_CALL(framer_visitor_, OnAckFrameStart(_, _))
+ .WillOnce(Return(true));
+ EXPECT_CALL(framer_visitor_,
+ OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)))
+ .WillOnce(Return(true));
+ EXPECT_CALL(framer_visitor_, OnAckFrameEnd(QuicPacketNumber(1)))
+ .WillOnce(Return(true));
+ }
if (level != ENCRYPTION_INITIAL && level != ENCRYPTION_HANDSHAKE) {
EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
}
@@ -2118,7 +2123,9 @@ TEST_P(QuicPacketCreatorTest, SerializeCoalescedPacket) {
EncryptionLevel level = static_cast<EncryptionLevel>(i);
creator_.set_encryption_level(level);
QuicAckFrame ack_frame(InitAckFrame(1));
- frames_.push_back(QuicFrame(&ack_frame));
+ if (level != ENCRYPTION_ZERO_RTT) {
+ frames_.push_back(QuicFrame(&ack_frame));
+ }
if (level != ENCRYPTION_INITIAL && level != ENCRYPTION_HANDSHAKE) {
frames_.push_back(
QuicFrame(QuicStreamFrame(1, false, 0u, absl::string_view())));
@@ -2156,20 +2163,26 @@ TEST_P(QuicPacketCreatorTest, SerializeCoalescedPacket) {
EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_, _));
EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnAckFrameStart(_, _)).WillOnce(Return(true));
- EXPECT_CALL(framer_visitor_,
- OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)))
- .WillOnce(Return(true));
- EXPECT_CALL(framer_visitor_, OnAckFrameEnd(_)).WillOnce(Return(true));
+ if (i != ENCRYPTION_ZERO_RTT) {
+ EXPECT_CALL(framer_visitor_, OnAckFrameStart(_, _))
+ .WillOnce(Return(true));
+ EXPECT_CALL(framer_visitor_,
+ OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)))
+ .WillOnce(Return(true));
+ EXPECT_CALL(framer_visitor_, OnAckFrameEnd(_)).WillOnce(Return(true));
+ }
if (i == ENCRYPTION_INITIAL) {
// Verify padding is added.
EXPECT_CALL(framer_visitor_, OnPaddingFrame(_));
- } else {
+ } else if (i != ENCRYPTION_ZERO_RTT) {
EXPECT_CALL(framer_visitor_, OnPaddingFrame(_)).Times(testing::AtMost(1));
}
if (i != ENCRYPTION_INITIAL && i != ENCRYPTION_HANDSHAKE) {
EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
}
+ if (i == ENCRYPTION_ZERO_RTT) {
+ EXPECT_CALL(framer_visitor_, OnPaddingFrame(_));
+ }
EXPECT_CALL(framer_visitor_, OnPacketComplete());
server_framer_.ProcessPacket(*packets[i]);
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_number.cc b/chromium/net/third_party/quiche/src/quic/core/quic_packet_number.cc
index ba1c509360b..b2821b454d7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_number.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packet_number.cc
@@ -2,10 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "quic/core/quic_packet_number.h"
+
#include <algorithm>
+#include <limits>
-#include "quic/core/quic_packet_number.h"
-#include "common/platform/api/quiche_text_utils.h"
+#include "absl/strings/str_cat.h"
namespace quic {
@@ -98,7 +100,7 @@ std::string QuicPacketNumber::ToString() const {
if (!IsInitialized()) {
return "uninitialized";
}
- return quiche::QuicheTextUtils::Uint64ToString(ToUint64());
+ return absl::StrCat(ToUint64());
}
std::ostream& operator<<(std::ostream& os, const QuicPacketNumber& p) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_number.h b/chromium/net/third_party/quiche/src/quic/core/quic_packet_number.h
index a1ea62fbec1..affd714336e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_number.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packet_number.h
@@ -11,7 +11,6 @@
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_logging.h"
-#include "quic/platform/api/quic_uint128.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.cc b/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.cc
index 4b0eb4b12ee..3a8a9b4fe3d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.cc
@@ -67,7 +67,7 @@ bool QuicPacketReader::ReadAndDispatchPackets(
}
if (!result.packet_info.HasValue(QuicUdpPacketInfoBit::PEER_ADDRESS)) {
- QUIC_BUG << "Unable to get peer socket address.";
+ QUIC_BUG(quic_bug_10329_1) << "Unable to get peer socket address.";
continue;
}
@@ -77,7 +77,7 @@ bool QuicPacketReader::ReadAndDispatchPackets(
QuicIpAddress self_ip = GetSelfIpFromPacketInfo(
result.packet_info, peer_address.host().IsIPv6());
if (!self_ip.IsInitialized()) {
- QUIC_BUG << "Unable to get self IP address.";
+ QUIC_BUG(quic_bug_10329_2) << "Unable to get self IP address.";
continue;
}
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 5f3e5a2697f..5cc593f41bf 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
@@ -183,7 +183,7 @@ QuicPacketHeader::QuicPacketHeader()
nonce(nullptr),
form(GOOGLE_QUIC_PACKET),
long_packet_type(INITIAL),
- possible_stateless_reset_token(0),
+ possible_stateless_reset_token({}),
retry_token_length_length(VARIABLE_LENGTH_INTEGER_LENGTH_0),
retry_token(absl::string_view()),
length_length(VARIABLE_LENGTH_INTEGER_LENGTH_0),
@@ -215,11 +215,11 @@ QuicVersionNegotiationPacket::QuicVersionNegotiationPacket(
QuicVersionNegotiationPacket::~QuicVersionNegotiationPacket() {}
QuicIetfStatelessResetPacket::QuicIetfStatelessResetPacket()
- : stateless_reset_token(0) {}
+ : stateless_reset_token({}) {}
QuicIetfStatelessResetPacket::QuicIetfStatelessResetPacket(
const QuicPacketHeader& header,
- QuicUint128 token)
+ StatelessResetToken token)
: header(header), stateless_reset_token(token) {}
QuicIetfStatelessResetPacket::QuicIetfStatelessResetPacket(
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packets.h b/chromium/net/third_party/quiche/src/quic/core/quic_packets.h
index 4643ebcba6e..a3fc59dbd7d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packets.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packets.h
@@ -7,12 +7,10 @@
#include <cstddef>
#include <cstdint>
-#include <limits>
-#include <list>
#include <memory>
#include <ostream>
+#include <string>
#include <utility>
-#include <vector>
#include "absl/strings/string_view.h"
#include "quic/core/frames/quic_frame.h"
@@ -25,7 +23,6 @@
#include "quic/core/quic_versions.h"
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_socket_address.h"
-#include "quic/platform/api/quic_uint128.h"
namespace quic {
@@ -155,7 +152,7 @@ struct QUIC_EXPORT_PRIVATE QuicPacketHeader {
// Only valid if |has_possible_stateless_reset_token| is true.
// Stores last 16 bytes of a this packet, used to check whether this packet is
// a stateless reset packet on decryption failure.
- QuicUint128 possible_stateless_reset_token;
+ StatelessResetToken possible_stateless_reset_token;
// Length of the retry token length variable length integer field,
// carried only by v99 IETF Initial packets.
QuicVariableLengthIntegerLength retry_token_length_length;
@@ -196,12 +193,12 @@ struct QUIC_EXPORT_PRIVATE QuicVersionNegotiationPacket {
struct QUIC_EXPORT_PRIVATE QuicIetfStatelessResetPacket {
QuicIetfStatelessResetPacket();
QuicIetfStatelessResetPacket(const QuicPacketHeader& header,
- QuicUint128 token);
+ StatelessResetToken token);
QuicIetfStatelessResetPacket(const QuicIetfStatelessResetPacket& other);
~QuicIetfStatelessResetPacket();
QuicPacketHeader header;
- QuicUint128 stateless_reset_token;
+ StatelessResetToken stateless_reset_token;
};
class QUIC_EXPORT_PRIVATE QuicData {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packets_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_packets_test.cc
index 5e206f46827..a07e289cb71 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packets_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packets_test.cc
@@ -4,7 +4,7 @@
#include "quic/core/quic_packets.h"
-#include "quic/platform/api/quic_ptr_util.h"
+#include "absl/memory/memory.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_test_utils.h"
#include "common/test_tools/quiche_test_utils.h"
@@ -86,7 +86,7 @@ TEST_F(QuicPacketsTest, CopySerializedPacket) {
packet.nonretransmittable_frames.push_back(QuicFrame(&ack_frame));
packet.nonretransmittable_frames.push_back(QuicFrame(QuicPaddingFrame(-1)));
- std::unique_ptr<SerializedPacket> copy = QuicWrapUnique<SerializedPacket>(
+ std::unique_ptr<SerializedPacket> copy = absl::WrapUnique<SerializedPacket>(
CopySerializedPacket(packet, &allocator, /*copy_buffer=*/true));
EXPECT_EQ(quic::QuicPacketNumber(1), copy->packet_number);
EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, copy->packet_number_length);
@@ -102,7 +102,7 @@ TEST_F(QuicPacketsTest, CopySerializedPacket) {
"encrypted_buffer", copy->encrypted_buffer, copy->encrypted_length,
packet.encrypted_buffer, packet.encrypted_length);
- std::unique_ptr<SerializedPacket> copy2 = QuicWrapUnique<SerializedPacket>(
+ std::unique_ptr<SerializedPacket> copy2 = absl::WrapUnique<SerializedPacket>(
CopySerializedPacket(packet, &allocator, /*copy_buffer=*/false));
EXPECT_EQ(packet.encrypted_buffer, copy2->encrypted_buffer);
EXPECT_EQ(1000u, copy2->encrypted_length);
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_path_validator.cc b/chromium/net/third_party/quiche/src/quic/core/quic_path_validator.cc
index f2abef0543f..bb83e9472f7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_path_validator.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_path_validator.cc
@@ -47,7 +47,7 @@ void QuicPathValidator::OnPathResponse(const QuicPathFrameBuffer& probing_data,
}
QUIC_DVLOG(1) << "Match PATH_RESPONSE received on " << self_address;
- QUIC_BUG_IF(!path_context_->self_address().IsInitialized())
+ QUIC_BUG_IF(quic_bug_12402_1, !path_context_->self_address().IsInitialized())
<< "Self address should have been known by now";
if (self_address != path_context_->self_address()) {
QUIC_DVLOG(1) << "Expect the response to be received on "
@@ -72,7 +72,8 @@ void QuicPathValidator::StartPathValidation(
QUIC_DLOG(INFO) << "Start validating path " << *context
<< " via writer: " << context->WriterToUse();
if (path_context_ != nullptr) {
- QUIC_BUG << "There is an on-going validation on path " << *path_context_;
+ QUIC_BUG(quic_bug_10876_1)
+ << "There is an on-going validation on path " << *path_context_;
ResetPathValidation();
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_path_validator_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_path_validator_test.cc
index e433f0c07be..1dfafc3b77a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_path_validator_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_path_validator_test.cc
@@ -42,7 +42,7 @@ class MockSendDelegate : public QuicPathValidator::SendDelegate {
MOCK_METHOD(QuicTime,
GetRetryTimeout,
(const QuicSocketAddress&, QuicPacketWriter*),
- (const override));
+ (const, override));
};
class QuicPathValidatorTest : public QuicTest {
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 14ed8cd6931..5187c61def4 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
@@ -116,12 +116,6 @@ QUIC_PROTOCOL_FLAG(
"descendents) will be automatically converted to lower case.")
QUIC_PROTOCOL_FLAG(
- bool,
- quic_enable_http3_server_push,
- false,
- "If true, server push will be allowed in QUIC versions that use HTTP/3.")
-
-QUIC_PROTOCOL_FLAG(
int32_t,
quic_bbr2_default_probe_bw_base_duration_ms,
2000,
@@ -248,4 +242,11 @@ QUIC_PROTOCOL_FLAG(bool,
true,
"If true, QUIC servers will defer sending in response to "
"incoming packets by default.")
+
+QUIC_PROTOCOL_FLAG(
+ bool,
+ quic_header_size_limit_includes_overhead,
+ true,
+ "If true, QUIC QPACK decoder includes 32-bytes overheader per entry while "
+ "comparing request/response header size against its upper limit.")
#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 2b434424833..a1b78a4fb86 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
@@ -309,7 +309,7 @@ QuicPacketNumber QuicReceivedPacketManager::GetLargestObserved() const {
QuicPacketNumber QuicReceivedPacketManager::PeerFirstSendingPacketNumber()
const {
if (!least_received_packet_number_.IsInitialized()) {
- QUIC_BUG << "No packets have been received yet";
+ QUIC_BUG(quic_bug_10849_1) << "No packets have been received yet";
return QuicPacketNumber(1);
}
return least_received_packet_number_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc
index 97c7c250aa3..53d9f0eca22 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc
@@ -179,7 +179,7 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
if (config.HasClientSentConnectionOption(kPTOS, perspective)) {
if (!pto_enabled_) {
- QUIC_PEER_BUG
+ QUIC_PEER_BUG(quic_peer_bug_12552_1)
<< "PTO is not enabled when receiving PTOS connection option.";
pto_enabled_ = true;
max_probe_packets_per_pto_ = 1;
@@ -339,6 +339,21 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
void QuicSentPacketManager::ApplyConnectionOptions(
const QuicTagVector& connection_options) {
+ absl::optional<CongestionControlType> cc_type;
+ if (ContainsQuicTag(connection_options, kB2ON)) {
+ cc_type = kBBRv2;
+ } else if (ContainsQuicTag(connection_options, kTBBR)) {
+ cc_type = kBBR;
+ } else if (ContainsQuicTag(connection_options, kRENO)) {
+ cc_type = kRenoBytes;
+ } else if (ContainsQuicTag(connection_options, kQBIC)) {
+ cc_type = kCubicBytes;
+ }
+
+ if (cc_type.has_value()) {
+ SetSendAlgorithm(*cc_type);
+ }
+
send_algorithm_->ApplyConnectionOptions(connection_options);
}
@@ -624,9 +639,10 @@ void QuicSentPacketManager::MarkForRetransmission(
unacked_packets_.GetMutableTransmissionInfo(packet_number);
// A previous RTO retransmission may cause connection close; packets without
// retransmittable frames can be marked for loss retransmissions.
- QUIC_BUG_IF(transmission_type != LOSS_RETRANSMISSION &&
- transmission_type != RTO_RETRANSMISSION &&
- !unacked_packets_.HasRetransmittableFrames(*transmission_info))
+ QUIC_BUG_IF(quic_bug_12552_2, transmission_type != LOSS_RETRANSMISSION &&
+ transmission_type != RTO_RETRANSMISSION &&
+ !unacked_packets_.HasRetransmittableFrames(
+ *transmission_info))
<< "packet number " << packet_number
<< " transmission_type: " << transmission_type << " transmission_info "
<< transmission_info->DebugString();
@@ -761,7 +777,8 @@ QuicAckFrequencyFrame QuicSentPacketManager::GetUpdatedAckFrequencyFrame()
const {
QuicAckFrequencyFrame frame;
if (!CanSendAckFrequency()) {
- QUIC_BUG << "New AckFrequencyFrame is created while it shouldn't.";
+ QUIC_BUG(quic_bug_10750_1)
+ << "New AckFrequencyFrame is created while it shouldn't.";
return frame;
}
@@ -789,7 +806,8 @@ bool QuicSentPacketManager::OnPacketSent(
QuicPacketNumber packet_number = packet.packet_number;
QUICHE_DCHECK_LE(FirstSendingPacketNumber(), packet_number);
QUICHE_DCHECK(!unacked_packets_.IsUnacked(packet_number));
- QUIC_BUG_IF(packet.encrypted_length == 0) << "Cannot send empty packets.";
+ QUIC_BUG_IF(quic_bug_10750_2, packet.encrypted_length == 0)
+ << "Cannot send empty packets.";
if (pending_timer_transmission_count_ > 0) {
--pending_timer_transmission_count_;
}
@@ -880,7 +898,8 @@ QuicSentPacketManager::OnRetransmissionTimeout() {
pending_timer_transmission_count_ = max_probe_packets_per_pto_;
return PTO_MODE;
}
- QUIC_BUG << "Unknown retransmission mode " << GetRetransmissionMode();
+ QUIC_BUG(quic_bug_10750_3)
+ << "Unknown retransmission mode " << GetRetransmissionMode();
return GetRetransmissionMode();
}
@@ -953,7 +972,7 @@ bool QuicSentPacketManager::MaybeRetransmitOldestPacket(TransmissionType type) {
void QuicSentPacketManager::RetransmitRtoPackets() {
QUICHE_DCHECK(!pto_enabled_);
- QUIC_BUG_IF(pending_timer_transmission_count_ > 0)
+ QUIC_BUG_IF(quic_bug_12552_3, pending_timer_transmission_count_ > 0)
<< "Retransmissions already queued:" << pending_timer_transmission_count_;
// Mark two packets for retransmission.
std::vector<QuicPacketNumber> retransmissions;
@@ -983,7 +1002,7 @@ void QuicSentPacketManager::RetransmitRtoPackets() {
MarkForRetransmission(retransmission, RTO_RETRANSMISSION);
}
if (retransmissions.empty()) {
- QUIC_BUG_IF(pending_timer_transmission_count_ != 0);
+ QUIC_BUG_IF(quic_bug_12552_4, pending_timer_transmission_count_ != 0);
// No packets to be RTO retransmitted, raise up a credit to allow
// connection to send.
QUIC_CODE_COUNT(no_packets_to_be_rto_retransmitted);
@@ -1000,8 +1019,9 @@ void QuicSentPacketManager::MaybeSendProbePackets() {
// Find out the packet number space to send probe packets.
if (!GetEarliestPacketSentTimeForPto(&packet_number_space)
.IsInitialized()) {
- QUIC_BUG_IF(unacked_packets_.perspective() == Perspective::IS_SERVER)
- << "earlist_sent_time not initialized when trying to send PTO "
+ QUIC_BUG_IF(quic_earliest_sent_time_not_initialized,
+ unacked_packets_.perspective() == Perspective::IS_SERVER)
+ << "earliest_sent_time not initialized when trying to send PTO "
"retransmissions";
return;
}
@@ -1173,8 +1193,8 @@ bool QuicSentPacketManager::MaybeUpdateRTT(QuicPacketNumber largest_acked,
unacked_packets_.GetTransmissionInfo(largest_acked);
// Ensure the packet has a valid sent time.
if (transmission_info.sent_time == QuicTime::Zero()) {
- QUIC_BUG << "Acked packet has zero sent time, largest_acked:"
- << largest_acked;
+ QUIC_BUG(quic_bug_10750_4)
+ << "Acked packet has zero sent time, largest_acked:" << largest_acked;
return false;
}
if (transmission_info.state == NOT_CONTRIBUTING_RTT) {
@@ -1401,7 +1421,7 @@ const QuicTime::Delta QuicSentPacketManager::GetProbeTimeoutDelay(
QUICHE_DCHECK(pto_enabled_);
if (rtt_stats_.smoothed_rtt().IsZero()) {
// Respect kMinHandshakeTimeoutMs to avoid a potential amplification attack.
- QUIC_BUG_IF(rtt_stats_.initial_rtt().IsZero());
+ QUIC_BUG_IF(quic_bug_12552_6, rtt_stats_.initial_rtt().IsZero());
return std::max(
pto_multiplier_without_rtt_samples_ * rtt_stats_.initial_rtt(),
QuicTime::Delta::FromMilliseconds(kMinHandshakeTimeoutMs)) *
@@ -1576,16 +1596,18 @@ AckResult QuicSentPacketManager::OnAckFrameEnd(
unacked_packets_.GetMutableTransmissionInfo(acked_packet.packet_number);
if (!QuicUtils::IsAckable(info->state)) {
if (info->state == ACKED) {
- QUIC_BUG << "Trying to ack an already acked packet: "
- << acked_packet.packet_number
- << ", last_ack_frame_: " << last_ack_frame_
- << ", least_unacked: " << unacked_packets_.GetLeastUnacked()
- << ", packets_acked_: " << packets_acked_;
+ QUIC_BUG(quic_bug_10750_5)
+ << "Trying to ack an already acked packet: "
+ << acked_packet.packet_number
+ << ", last_ack_frame_: " << last_ack_frame_
+ << ", least_unacked: " << unacked_packets_.GetLeastUnacked()
+ << ", packets_acked_: " << packets_acked_;
} else {
- QUIC_PEER_BUG << "Received " << ack_decrypted_level
- << " ack for unackable packet: "
- << acked_packet.packet_number << " with state: "
- << QuicUtils::SentPacketStateToString(info->state);
+ QUIC_PEER_BUG(quic_peer_bug_10750_6)
+ << "Received " << ack_decrypted_level
+ << " ack for unackable packet: " << acked_packet.packet_number
+ << " with state: "
+ << QuicUtils::SentPacketStateToString(info->state);
if (supports_multiple_packet_number_spaces()) {
if (info->state == NEVER_SENT) {
return UNSENT_PACKETS_ACKED;
@@ -1789,7 +1811,7 @@ void QuicSentPacketManager::OnAckFrequencyFrameAcked(
in_use_sent_ack_delays_.pop_front_n(stale_entry_count);
}
if (in_use_sent_ack_delays_.empty()) {
- QUIC_BUG << "in_use_sent_ack_delays_ is empty.";
+ QUIC_BUG(quic_bug_10750_7) << "in_use_sent_ack_delays_ is empty.";
return;
}
peer_max_ack_delay_ = std::max_element(in_use_sent_ack_delays_.cbegin(),
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 8cd0a57a366..7c7aa4d077f 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
@@ -8,6 +8,7 @@
#include <string>
#include <utility>
+#include "absl/memory/memory.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "quic/core/frames/quic_ack_frequency_frame.h"
@@ -22,9 +23,9 @@
#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_ptr_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"
using spdy::SpdyPriority;
@@ -115,7 +116,7 @@ QuicSession::QuicSession(
was_zero_rtt_rejected_(false),
liveness_testing_in_progress_(false) {
closed_streams_clean_up_alarm_ =
- QuicWrapUnique<QuicAlarm>(connection_->alarm_factory()->CreateAlarm(
+ absl::WrapUnique<QuicAlarm>(connection_->alarm_factory()->CreateAlarm(
new ClosedStreamsCleanUpDelegate(this)));
if (perspective() == Perspective::IS_SERVER &&
connection_->version().handshake_protocol == PROTOCOL_TLS1_3) {
@@ -141,6 +142,8 @@ void QuicSession::Initialize() {
config_.SetMinAckDelayMs(kDefaultMinAckDelayTimeMs);
}
+ connection_->CreateConnectionIdManager();
+
// On the server side, version negotiation has been done by the dispatcher,
// and the server session is created with the right version.
if (perspective() == Perspective::IS_SERVER) {
@@ -179,11 +182,13 @@ void QuicSession::PendingStreamOnStreamFrame(const QuicStreamFrame& frame) {
if (!connection()->connected()) {
return;
}
- if (ProcessPendingStream(pending)) {
+ QuicStream* stream = ProcessPendingStream(pending);
+ if (stream != nullptr) {
// The pending stream should now be in the scope of normal streams.
QUICHE_DCHECK(IsClosedStream(stream_id) || IsOpenStream(stream_id))
<< "Stream " << stream_id << " not created";
pending_stream_map_.erase(stream_id);
+ stream->OnStreamCreatedFromPendingStream();
return;
}
if (pending->sequencer()->IsClosed()) {
@@ -361,15 +366,18 @@ void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) {
}
void QuicSession::OnGoAway(const QuicGoAwayFrame& /*frame*/) {
- QUIC_BUG_IF(version().UsesHttp3())
+ QUIC_BUG_IF(quic_bug_12435_1, version().UsesHttp3())
<< "gQUIC GOAWAY received on version " << version();
transport_goaway_received_ = true;
}
void QuicSession::OnMessageReceived(absl::string_view message) {
- QUIC_DVLOG(1) << ENDPOINT << "Received message, length: " << message.length()
- << ", " << message;
+ QUIC_DVLOG(1) << ENDPOINT << "Received message of length "
+ << message.length();
+ QUIC_DVLOG(2) << ENDPOINT << "Contents of message of length "
+ << message.length() << ":" << std::endl
+ << quiche::QuicheTextUtils::HexDump(message);
}
void QuicSession::OnHandshakeDoneReceived() {
@@ -417,7 +425,7 @@ void QuicSession::OnConnectionClosed(const QuicConnectionCloseFrame& frame,
stream->OnConnectionClosed(frame.quic_error_code, source);
auto it = stream_map_.find(id);
if (it != stream_map_.end()) {
- QUIC_BUG_IF(!it->second->IsZombie())
+ QUIC_BUG_IF(quic_bug_12435_2, !it->second->IsZombie())
<< ENDPOINT << "Non-zombie stream " << id
<< " failed to close under OnConnectionClosed";
}
@@ -555,6 +563,18 @@ bool QuicSession::CheckStreamWriteBlocked(QuicStream* stream) const {
}
void QuicSession::OnCanWrite() {
+ if (connection_->donot_write_mid_packet_processing()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_donot_write_mid_packet_processing, 1, 3);
+ if (connection_->framer().is_processing_packet()) {
+ // Do not write data in the middle of packet processing because rest
+ // frames in the packet may change the data to write. For example, lost
+ // data could be acknowledged. Also, connection is going to emit
+ // OnCanWrite signal post packet processing.
+ QUIC_BUG(session_write_mid_packet_processing)
+ << ENDPOINT << "Try to write mid packet processing.";
+ return;
+ }
+ }
if (!RetransmitLostData()) {
// Cannot finish retransmitting lost data, connection is write blocked.
QUIC_DVLOG(1) << ENDPOINT
@@ -608,11 +628,12 @@ void QuicSession::OnCanWrite() {
if (!(write_blocked_streams_.HasWriteBlockedSpecialStream() ||
write_blocked_streams_.HasWriteBlockedDataStreams())) {
// Writing one stream removed another!? Something's broken.
- QUIC_BUG << "WriteBlockedStream is missing, num_writes: " << num_writes
- << ", finished_writes: " << i
- << ", connected: " << connection_->connected()
- << ", connection level flow control blocked: "
- << flow_controller_.IsBlocked();
+ QUIC_BUG(quic_bug_10866_1)
+ << "WriteBlockedStream is missing, num_writes: " << num_writes
+ << ", finished_writes: " << i
+ << ", connected: " << connection_->connected()
+ << ", connection level flow control blocked: "
+ << flow_controller_.IsBlocked();
for (QuicStreamId id : last_writing_stream_ids) {
QUIC_LOG(WARNING) << "last_writing_stream_id: " << id;
}
@@ -750,12 +771,12 @@ QuicConsumedData QuicSession::WritevData(
if (was_zero_rtt_rejected_ && !OneRttKeysAvailable()) {
QUICHE_DCHECK(version().UsesTls() &&
perspective() == Perspective::IS_CLIENT);
- QUIC_BUG_IF(type == NOT_RETRANSMISSION)
+ 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.";
} else {
- QUIC_BUG << ENDPOINT << "Try to send data of stream " << id
- << " before encryption is established.";
+ QUIC_BUG(quic_bug_10866_2) << ENDPOINT << "Try to send data of stream "
+ << id << " before encryption is established.";
}
return QuicConsumedData(0, false);
}
@@ -798,7 +819,7 @@ size_t QuicSession::SendCryptoData(EncryptionLevel level,
const std::string error_details = absl::StrCat(
"Try to send crypto data with missing keys of encryption level: ",
EncryptionLevelToString(level));
- QUIC_BUG << ENDPOINT << error_details;
+ QUIC_BUG(quic_bug_10866_3) << ENDPOINT << error_details;
connection()->CloseConnection(
QUIC_MISSING_WRITE_KEYS, error_details,
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -834,8 +855,10 @@ bool QuicSession::WriteControlFrame(const QuicFrame& frame,
if (connection_->encrypted_control_frames()) {
QUIC_RELOADABLE_FLAG_COUNT(quic_encrypted_control_frames);
if (!IsEncryptionEstablished()) {
- QUIC_BUG << ENDPOINT << "Tried to send control frame " << frame
- << " before encryption is established.";
+ QUIC_BUG(quic_bug_10866_4)
+ << ENDPOINT << "Tried to send control frame " << frame
+ << " before encryption is established. Last decrypted level: "
+ << EncryptionLevelToString(connection_->last_decrypted_level());
return false;
}
}
@@ -911,19 +934,13 @@ void QuicSession::SendGoAway(QuicErrorCode error_code,
return;
}
transport_goaway_sent_ = true;
- if (GetQuicReloadableFlag(quic_goaway_with_max_stream_id)) {
- QUICHE_DCHECK_EQ(perspective(), Perspective::IS_SERVER);
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_goaway_with_max_stream_id, 2, 2);
- control_frame_manager_.WriteOrBufferGoAway(
- error_code,
- QuicUtils::GetMaxClientInitiatedBidirectionalStreamId(
- transport_version()),
- reason);
- } else {
- control_frame_manager_.WriteOrBufferGoAway(
- error_code, stream_id_manager_.largest_peer_created_stream_id(),
- reason);
- }
+
+ QUICHE_DCHECK_EQ(perspective(), Perspective::IS_SERVER);
+ control_frame_manager_.WriteOrBufferGoAway(
+ error_code,
+ QuicUtils::GetMaxClientInitiatedBidirectionalStreamId(
+ transport_version()),
+ reason);
}
void QuicSession::SendBlocked(QuicStreamId id) {
@@ -953,7 +970,8 @@ void QuicSession::OnStreamError(QuicErrorCode error_code,
void QuicSession::SendMaxStreams(QuicStreamCount stream_count,
bool unidirectional) {
if (!is_configured_) {
- QUIC_BUG << "Try to send max streams before config negotiated.";
+ QUIC_BUG(quic_bug_10866_5)
+ << "Try to send max streams before config negotiated.";
return;
}
control_frame_manager_.WriteOrBufferMaxStreams(stream_count, unidirectional);
@@ -969,7 +987,8 @@ void QuicSession::OnStreamClosed(QuicStreamId stream_id) {
QUIC_DVLOG(1) << ENDPOINT << "Closing stream: " << stream_id;
StreamMap::iterator it = stream_map_.find(stream_id);
if (it == stream_map_.end()) {
- QUIC_BUG << ENDPOINT << "Stream is already closed: " << stream_id;
+ QUIC_BUG(quic_bug_10866_6)
+ << ENDPOINT << "Stream is already closed: " << stream_id;
return;
}
QuicStream* stream = it->second.get();
@@ -988,6 +1007,11 @@ void QuicSession::OnStreamClosed(QuicStreamId stream_id) {
closed_streams_clean_up_alarm_->Set(
connection_->clock()->ApproximateNow());
}
+ QUIC_BUG_IF(
+ 364846171_1,
+ connection_->packet_creator().HasPendingStreamFramesOfStream(stream_id))
+ << "Stream " << stream_id
+ << " gets closed while there are pending frames.";
}
if (!stream->HasReceivedFinalOffset()) {
@@ -1006,10 +1030,10 @@ void QuicSession::OnStreamClosed(QuicStreamId stream_id) {
QUIC_DVLOG_IF(1, stream_was_draining)
<< ENDPOINT << "Stream " << stream_id << " was draining";
if (stream_was_draining) {
- QUIC_BUG_IF(num_draining_streams_ == 0);
+ QUIC_BUG_IF(quic_bug_12435_4, num_draining_streams_ == 0);
--num_draining_streams_;
if (!IsIncomingStream(stream_id)) {
- QUIC_BUG_IF(num_outgoing_draining_streams_ == 0);
+ QUIC_BUG_IF(quic_bug_12435_5, num_outgoing_draining_streams_ == 0);
--num_outgoing_draining_streams_;
}
// Stream Id manager has been informed with draining streams.
@@ -1098,10 +1122,9 @@ bool QuicSession::OneRttKeysAvailable() const {
void QuicSession::OnConfigNegotiated() {
// In versions with TLS, the configs will be set twice if 0-RTT is available.
// In the second config setting, 1-RTT keys are guaranteed to be available.
- if (GetQuicRestartFlag(quic_enable_zero_rtt_for_tls_v2) &&
- version().UsesTls() && is_configured_ &&
+ if (version().UsesTls() && is_configured_ &&
connection_->encryption_level() != ENCRYPTION_FORWARD_SECURE) {
- QUIC_BUG
+ QUIC_BUG(quic_bug_12435_6)
<< ENDPOINT
<< "1-RTT keys missing when config is negotiated for the second time.";
connection_->CloseConnection(
@@ -1297,9 +1320,12 @@ void QuicSession::OnConfigNegotiated() {
// Ask flow controllers to try again since the config could have unblocked us.
// Or if this session is configured on TLS enabled QUIC versions,
// attempt to retransmit 0-RTT data if there's any.
- if (connection_->version().AllowsLowFlowControlLimits() ||
- (GetQuicRestartFlag(quic_enable_zero_rtt_for_tls_v2) &&
+ // TODO(fayang): consider removing this OnCanWrite call.
+ if ((!connection_->donot_write_mid_packet_processing() ||
+ !connection_->framer().is_processing_packet()) &&
+ (connection_->version().AllowsLowFlowControlLimits() ||
version().UsesTls())) {
+ QUIC_CODE_COUNT(quic_session_on_can_write_on_config_negotiated);
OnCanWrite();
}
}
@@ -1581,9 +1607,10 @@ void QuicSession::OnNewEncryptionKeyAvailable(
if (reset_encryption_level) {
connection()->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
}
- QUIC_BUG_IF(IsEncryptionEstablished() &&
- (connection()->encryption_level() == ENCRYPTION_INITIAL ||
- connection()->encryption_level() == ENCRYPTION_HANDSHAKE))
+ QUIC_BUG_IF(quic_bug_12435_7,
+ IsEncryptionEstablished() &&
+ (connection()->encryption_level() == ENCRYPTION_INITIAL ||
+ connection()->encryption_level() == ENCRYPTION_HANDSHAKE))
<< "Encryption is established, but the encryption level " << level
<< " does not support sending stream data";
}
@@ -1602,28 +1629,35 @@ void QuicSession::SetDefaultEncryptionLevel(EncryptionLevel level) {
// Retransmit old 0-RTT data (if any) with the new 0-RTT keys, since
// they can't be decrypted by the server.
connection_->MarkZeroRttPacketsForRetransmission(0);
- // Given any streams blocked by encryption a chance to write.
- OnCanWrite();
+ if (!connection_->donot_write_mid_packet_processing() ||
+ !connection_->framer().is_processing_packet()) {
+ // TODO(fayang): consider removing this OnCanWrite call.
+ // Given any streams blocked by encryption a chance to write.
+ QUIC_CODE_COUNT(
+ quic_session_on_can_write_set_default_encryption_level);
+ OnCanWrite();
+ }
}
break;
case ENCRYPTION_HANDSHAKE:
break;
case ENCRYPTION_FORWARD_SECURE:
- QUIC_BUG_IF(!config_.negotiated())
+ QUIC_BUG_IF(quic_bug_12435_8, !config_.negotiated())
<< ENDPOINT << "Handshake confirmed without parameter negotiation.";
connection()->mutable_stats().handshake_completion_time =
connection()->clock()->ApproximateNow();
break;
default:
- QUIC_BUG << "Unknown encryption level: " << level;
+ QUIC_BUG(quic_bug_10866_7) << "Unknown encryption level: " << level;
}
}
void QuicSession::OnTlsHandshakeComplete() {
QUICHE_DCHECK_EQ(PROTOCOL_TLS1_3, connection_->version().handshake_protocol);
- QUIC_BUG_IF(!GetCryptoStream()->crypto_negotiated_params().cipher_suite)
+ QUIC_BUG_IF(quic_bug_12435_9,
+ !GetCryptoStream()->crypto_negotiated_params().cipher_suite)
<< ENDPOINT << "Handshake completes without cipher suite negotiation.";
- QUIC_BUG_IF(!config_.negotiated())
+ QUIC_BUG_IF(quic_bug_12435_10, !config_.negotiated())
<< ENDPOINT << "Handshake completes without parameter negotiation.";
connection()->mutable_stats().handshake_completion_time =
connection()->clock()->ApproximateNow();
@@ -1680,11 +1714,13 @@ void QuicSession::DiscardOldEncryptionKey(EncryptionLevel level) {
case ENCRYPTION_ZERO_RTT:
break;
case ENCRYPTION_FORWARD_SECURE:
- QUIC_BUG << ENDPOINT << "Discarding 1-RTT keys is not allowed";
+ QUIC_BUG(quic_bug_10866_8)
+ << ENDPOINT << "Discarding 1-RTT keys is not allowed";
break;
default:
- QUIC_BUG << ENDPOINT
- << "Cannot discard keys for unknown encryption level: " << level;
+ QUIC_BUG(quic_bug_10866_9)
+ << ENDPOINT
+ << "Cannot discard keys for unknown encryption level: " << level;
}
}
@@ -1698,7 +1734,8 @@ void QuicSession::OnZeroRttRejected(int reason) {
was_zero_rtt_rejected_ = true;
connection_->MarkZeroRttPacketsForRetransmission(reason);
if (connection_->encryption_level() == ENCRYPTION_FORWARD_SECURE) {
- QUIC_BUG << "1-RTT keys already available when 0-RTT is rejected.";
+ QUIC_BUG(quic_bug_10866_10)
+ << "1-RTT keys already available when 0-RTT is rejected.";
connection_->CloseConnection(
QUIC_INTERNAL_ERROR,
"1-RTT keys already available when 0-RTT is rejected.",
@@ -2031,7 +2068,8 @@ size_t QuicSession::GetNumActiveStreams() const {
void QuicSession::MarkConnectionLevelWriteBlocked(QuicStreamId id) {
if (GetOrCreateStream(id) == nullptr) {
- QUIC_BUG << "Marking unknown stream " << id << " blocked.";
+ QUIC_BUG(quic_bug_10866_11)
+ << "Marking unknown stream " << id << " blocked.";
QUIC_LOG_FIRST_N(ERROR, 2) << QuicStackTrace();
}
@@ -2057,6 +2095,27 @@ void QuicSession::SendAckFrequency(const QuicAckFrequencyFrame& frame) {
control_frame_manager_.WriteOrBufferAckFrequency(frame);
}
+void QuicSession::SendNewConnectionId(const QuicNewConnectionIdFrame& frame) {
+ 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) {
+ control_frame_manager_.WriteOrBufferRetireConnectionId(sequence_number);
+}
+
+void QuicSession::OnServerConnectionIdIssued(
+ const QuicConnectionId& server_connection_id) {
+ visitor_->OnNewConnectionIdSent(connection_->connection_id(),
+ server_connection_id);
+}
+
+void QuicSession::OnServerConnectionIdRetired(
+ const QuicConnectionId& server_connection_id) {
+ visitor_->OnConnectionIdRetired(server_connection_id);
+}
+
bool QuicSession::IsConnectionFlowControlBlocked() const {
return flow_controller_.IsBlocked();
}
@@ -2109,6 +2168,9 @@ void QuicSession::MaybeCloseZombieStream(QuicStreamId id) {
}
// Do not retransmit data of a closed stream.
streams_with_pending_retransmission_.erase(id);
+ QUIC_BUG_IF(364846171_2,
+ connection_->packet_creator().HasPendingStreamFramesOfStream(id))
+ << "Stream " << id << " gets closed while there are pending frames.";
}
QuicStream* QuicSession::GetStream(QuicStreamId id) const {
@@ -2165,8 +2227,9 @@ bool QuicSession::OnFrameAcked(const QuicFrame& frame,
void QuicSession::OnStreamFrameRetransmitted(const QuicStreamFrame& frame) {
QuicStream* stream = GetStream(frame.stream_id);
if (stream == nullptr) {
- QUIC_BUG << "Stream: " << frame.stream_id << " is closed when " << frame
- << " is retransmitted.";
+ QUIC_BUG(quic_bug_10866_12)
+ << "Stream: " << frame.stream_id << " is closed when " << frame
+ << " is retransmitted.";
connection()->CloseConnection(
QUIC_INTERNAL_ERROR, "Attempt to retransmit frame of a closed stream",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -2277,8 +2340,9 @@ WriteStreamDataResult QuicSession::WriteStreamData(QuicStreamId id,
if (stream == nullptr) {
// This causes the connection to be closed because of failed to serialize
// packet.
- QUIC_BUG << "Stream " << id << " does not exist when trying to write data."
- << " version:" << transport_version();
+ QUIC_BUG(quic_bug_10866_13)
+ << "Stream " << id << " does not exist when trying to write data."
+ << " version:" << transport_version();
return STREAM_MISSING;
}
if (stream->WriteStreamData(offset, data_length, writer)) {
@@ -2295,7 +2359,7 @@ bool QuicSession::WriteCryptoData(EncryptionLevel level,
writer);
}
-QuicUint128 QuicSession::GetStatelessResetToken() const {
+StatelessResetToken QuicSession::GetStatelessResetToken() const {
return QuicUtils::GenerateStatelessResetToken(connection_->connection_id());
}
@@ -2363,7 +2427,8 @@ bool QuicSession::RetransmitLostData() {
streams_with_pending_retransmission_.pop_front();
}
} else {
- QUIC_BUG << "Try to retransmit data of a closed stream";
+ QUIC_BUG(quic_bug_10866_14)
+ << "Try to retransmit data of a closed stream";
streams_with_pending_retransmission_.pop_front();
}
}
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 cf7f9f725b4..cf366cf5654 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
@@ -145,6 +145,12 @@ class QUIC_EXPORT_PRIVATE QuicSession
// Adds a connection level WINDOW_UPDATE frame.
void OnAckNeedsRetransmittableFrame() override;
void SendAckFrequency(const QuicAckFrequencyFrame& frame) override;
+ void SendNewConnectionId(const QuicNewConnectionIdFrame& frame) override;
+ void SendRetireConnectionId(uint64_t sequence_number) override;
+ void OnServerConnectionIdIssued(
+ const QuicConnectionId& server_connection_id) override;
+ void OnServerConnectionIdRetired(
+ const QuicConnectionId& server_connection_id) override;
bool WillingAndAbleToWrite() const override;
std::string GetStreamsInfoForLogging() const override;
void OnPathDegrading() override;
@@ -164,6 +170,10 @@ class QUIC_EXPORT_PRIVATE QuicSession
void BeforeConnectionCloseSent() override {}
bool ValidateToken(absl::string_view token) const override;
void MaybeSendAddressToken() override;
+ bool IsKnownServerAddress(
+ const QuicSocketAddress& /*address*/) const override {
+ return false;
+ }
// QuicStreamFrameDataProducer
WriteStreamDataResult WriteStreamData(QuicStreamId id,
@@ -710,7 +720,7 @@ class QUIC_EXPORT_PRIVATE QuicSession
// Returns a stateless reset token which will be included in the public reset
// packet.
- virtual QuicUint128 GetStatelessResetToken() const;
+ virtual StatelessResetToken GetStatelessResetToken() const;
QuicControlFrameManager& control_frame_manager() {
return control_frame_manager_;
@@ -735,10 +745,11 @@ class QUIC_EXPORT_PRIVATE QuicSession
size_t num_draining_streams() const { return num_draining_streams_; }
// Processes the stream type information of |pending| depending on
- // different kinds of sessions' own rules. Returns true if the pending stream
- // is converted into a normal stream.
- virtual bool ProcessPendingStream(PendingStream* /*pending*/) {
- return false;
+ // different kinds of sessions' own rules. If the pending stream has been
+ // converted to a normal stream, returns a pointer to the new stream;
+ // otherwise, returns nullptr.
+ virtual QuicStream* ProcessPendingStream(PendingStream* /*pending*/) {
+ return nullptr;
}
// Called by applications to perform |action| on active streams.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc
index 7daec2bbe00..81282fe9eeb 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc
@@ -10,6 +10,7 @@
#include <utility>
#include "absl/base/macros.h"
+#include "absl/memory/memory.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
@@ -28,7 +29,6 @@
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_map_util.h"
#include "quic/platform/api/quic_mem_slice_storage.h"
-#include "quic/platform/api/quic_ptr_util.h"
#include "quic/platform/api/quic_test.h"
#include "quic/platform/api/quic_test_mem_slice_vector.h"
#include "quic/test_tools/mock_quic_session_visitor.h"
@@ -246,14 +246,14 @@ class TestSession : public QuicSession {
return nullptr;
}
TestStream* stream = new TestStream(id, this, BIDIRECTIONAL);
- ActivateStream(QuicWrapUnique(stream));
+ ActivateStream(absl::WrapUnique(stream));
return stream;
}
TestStream* CreateOutgoingUnidirectionalStream() {
TestStream* stream = new TestStream(GetNextOutgoingUnidirectionalStreamId(),
this, WRITE_UNIDIRECTIONAL);
- ActivateStream(QuicWrapUnique(stream));
+ ActivateStream(absl::WrapUnique(stream));
return stream;
}
@@ -274,7 +274,7 @@ class TestSession : public QuicSession {
id, this,
DetermineStreamType(id, connection()->version(), perspective(),
/*is_incoming=*/true, BIDIRECTIONAL));
- ActivateStream(QuicWrapUnique(stream));
+ ActivateStream(absl::WrapUnique(stream));
++num_incoming_streams_created_;
return stream;
}
@@ -285,7 +285,7 @@ class TestSession : public QuicSession {
pending, this,
DetermineStreamType(id, connection()->version(), perspective(),
/*is_incoming=*/true, BIDIRECTIONAL));
- ActivateStream(QuicWrapUnique(stream));
+ ActivateStream(absl::WrapUnique(stream));
++num_incoming_streams_created_;
return stream;
}
@@ -293,14 +293,13 @@ class TestSession : public QuicSession {
// QuicSession doesn't do anything in this method. So it's overridden here to
// test that the session handles pending streams correctly in terms of
// receiving stream frames.
- bool ProcessPendingStream(PendingStream* pending) override {
+ QuicStream* ProcessPendingStream(PendingStream* pending) override {
struct iovec iov;
if (pending->sequencer()->GetReadableRegion(&iov)) {
// Create TestStream once the first byte is received.
- CreateIncomingStream(pending);
- return true;
+ return CreateIncomingStream(pending);
}
- return false;
+ return nullptr;
}
bool IsClosedStream(QuicStreamId id) {
@@ -2552,7 +2551,7 @@ TEST_P(QuicSessionTestServer, WriteUnidirectionalStream) {
session_.set_writev_consumes_all_data(true);
TestStream* stream4 = new TestStream(GetNthServerInitiatedUnidirectionalId(1),
&session_, WRITE_UNIDIRECTIONAL);
- session_.ActivateStream(QuicWrapUnique(stream4));
+ session_.ActivateStream(absl::WrapUnique(stream4));
std::string body(100, '.');
stream4->WriteOrBufferData(body, false, nullptr);
stream4->WriteOrBufferData(body, true, nullptr);
@@ -2565,7 +2564,7 @@ TEST_P(QuicSessionTestServer, WriteUnidirectionalStream) {
TEST_P(QuicSessionTestServer, ReceivedDataOnWriteUnidirectionalStream) {
TestStream* stream4 = new TestStream(GetNthServerInitiatedUnidirectionalId(1),
&session_, WRITE_UNIDIRECTIONAL);
- session_.ActivateStream(QuicWrapUnique(stream4));
+ session_.ActivateStream(absl::WrapUnique(stream4));
EXPECT_CALL(
*connection_,
@@ -2579,7 +2578,7 @@ TEST_P(QuicSessionTestServer, ReceivedDataOnWriteUnidirectionalStream) {
TEST_P(QuicSessionTestServer, ReadUnidirectionalStream) {
TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
&session_, READ_UNIDIRECTIONAL);
- session_.ActivateStream(QuicWrapUnique(stream4));
+ session_.ActivateStream(absl::WrapUnique(stream4));
EXPECT_FALSE(stream4->IsWaitingForAcks());
// Discard all incoming data.
stream4->StopReading();
@@ -2599,7 +2598,7 @@ TEST_P(QuicSessionTestServer, ReadUnidirectionalStream) {
TEST_P(QuicSessionTestServer, WriteOrBufferDataOnReadUnidirectionalStream) {
TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
&session_, READ_UNIDIRECTIONAL);
- session_.ActivateStream(QuicWrapUnique(stream4));
+ session_.ActivateStream(absl::WrapUnique(stream4));
EXPECT_CALL(*connection_,
CloseConnection(
@@ -2612,7 +2611,7 @@ TEST_P(QuicSessionTestServer, WriteOrBufferDataOnReadUnidirectionalStream) {
TEST_P(QuicSessionTestServer, WritevDataOnReadUnidirectionalStream) {
TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
&session_, READ_UNIDIRECTIONAL);
- session_.ActivateStream(QuicWrapUnique(stream4));
+ session_.ActivateStream(absl::WrapUnique(stream4));
EXPECT_CALL(*connection_,
CloseConnection(
@@ -2629,7 +2628,7 @@ TEST_P(QuicSessionTestServer, WritevDataOnReadUnidirectionalStream) {
TEST_P(QuicSessionTestServer, WriteMemSlicesOnReadUnidirectionalStream) {
TestStream* stream4 = new TestStream(GetNthClientInitiatedUnidirectionalId(1),
&session_, READ_UNIDIRECTIONAL);
- session_.ActivateStream(QuicWrapUnique(stream4));
+ session_.ActivateStream(absl::WrapUnique(stream4));
EXPECT_CALL(*connection_,
CloseConnection(
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream.cc
index b8ac8ccccae..3f1b7d94e18 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream.cc
@@ -176,7 +176,7 @@ void PendingStream::OnStreamFrame(const QuicStreamFrame& frame) {
(kMaxStreamLength - frame.offset < frame.data_length);
if (is_stream_too_long) {
// Close connection if stream becomes too long.
- QUIC_PEER_BUG
+ QUIC_PEER_BUG(quic_peer_bug_12570_1)
<< "Receive stream frame reaches max stream length. frame offset "
<< frame.offset << " length " << frame.data_length;
OnUnrecoverableError(QUIC_STREAM_LENGTH_OVERFLOW,
@@ -424,10 +424,10 @@ void QuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
(kMaxStreamLength - frame.offset < frame.data_length);
if (is_stream_too_long) {
// Close connection if stream becomes too long.
- QUIC_PEER_BUG << "Receive stream frame on stream " << id_
- << " reaches max stream length. frame offset " << frame.offset
- << " length " << frame.data_length << ". "
- << sequencer_.DebugString();
+ QUIC_PEER_BUG(quic_peer_bug_10586_1)
+ << "Receive stream frame on stream " << id_
+ << " reaches max stream length. frame offset " << frame.offset
+ << " length " << frame.data_length << ". " << sequencer_.DebugString();
OnUnrecoverableError(
QUIC_STREAM_LENGTH_OVERFLOW,
absl::StrCat("Peer sends more data than allowed on stream ", id_,
@@ -474,7 +474,7 @@ void QuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
MaybeIncreaseHighestReceivedOffset(frame.offset + frame_payload_size)) {
// As the highest received offset has changed, check to see if this is a
// violation of flow control.
- QUIC_BUG_IF(!flow_controller_.has_value())
+ QUIC_BUG_IF(quic_bug_12570_2, !flow_controller_.has_value())
<< ENDPOINT << "OnStreamFrame called on stream without flow control";
if ((flow_controller_.has_value() &&
flow_controller_->FlowControlViolation()) ||
@@ -542,7 +542,7 @@ void QuicStream::OnStreamReset(const QuicRstStreamFrame& frame) {
}
MaybeIncreaseHighestReceivedOffset(frame.byte_offset);
- QUIC_BUG_IF(!flow_controller_.has_value())
+ QUIC_BUG_IF(quic_bug_12570_3, !flow_controller_.has_value())
<< ENDPOINT << "OnStreamReset called on stream without flow control";
if ((flow_controller_.has_value() &&
flow_controller_->FlowControlViolation()) ||
@@ -631,7 +631,8 @@ void QuicStream::WriteOrBufferData(
bool fin,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
if (session()->use_write_or_buffer_data_at_level()) {
- QUIC_BUG_IF(QuicUtils::IsCryptoStreamId(transport_version(), id_))
+ QUIC_BUG_IF(quic_bug_12570_4,
+ QuicUtils::IsCryptoStreamId(transport_version(), id_))
<< ENDPOINT
<< "WriteOrBufferData is used to send application data, use "
"WriteOrBufferDataAtLevel to send crypto data.";
@@ -648,12 +649,12 @@ void QuicStream::WriteOrBufferDataInner(
absl::optional<EncryptionLevel> level,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
if (data.empty() && !fin) {
- QUIC_BUG << "data.empty() && !fin";
+ QUIC_BUG(quic_bug_10586_2) << "data.empty() && !fin";
return;
}
if (fin_buffered_) {
- QUIC_BUG << "Fin already buffered";
+ QUIC_BUG(quic_bug_10586_3) << "Fin already buffered";
return;
}
if (write_side_closed_) {
@@ -675,7 +676,7 @@ void QuicStream::WriteOrBufferDataInner(
struct iovec iov(QuicUtils::MakeIovec(data));
QuicStreamOffset offset = send_buffer_.stream_offset();
if (kMaxStreamLength - offset < data.length()) {
- QUIC_BUG << "Write too many data via stream " << id_;
+ QUIC_BUG(quic_bug_10586_4) << "Write too many data via stream " << id_;
OnUnrecoverableError(
QUIC_STREAM_LENGTH_OVERFLOW,
absl::StrCat("Write too many data via stream ", id_));
@@ -734,8 +735,8 @@ void QuicStream::OnCanWrite() {
void QuicStream::MaybeSendBlocked() {
if (!flow_controller_.has_value()) {
- QUIC_BUG << ENDPOINT
- << "MaybeSendBlocked called on stream without flow control";
+ QUIC_BUG(quic_bug_10586_5)
+ << ENDPOINT << "MaybeSendBlocked called on stream without flow control";
return;
}
if (flow_controller_->ShouldSendBlocked()) {
@@ -760,12 +761,12 @@ void QuicStream::MaybeSendBlocked() {
QuicConsumedData QuicStream::WriteMemSlices(QuicMemSliceSpan span, bool fin) {
QuicConsumedData consumed_data(0, false);
if (span.empty() && !fin) {
- QUIC_BUG << "span.empty() && !fin";
+ QUIC_BUG(quic_bug_10586_6) << "span.empty() && !fin";
return consumed_data;
}
if (fin_buffered_) {
- QUIC_BUG << "Fin already buffered";
+ QUIC_BUG(quic_bug_10586_7) << "Fin already buffered";
return consumed_data;
}
@@ -788,7 +789,7 @@ QuicConsumedData QuicStream::WriteMemSlices(QuicMemSliceSpan span, bool fin) {
consumed_data.bytes_consumed = send_buffer_.SaveMemSliceSpan(span);
if (offset > send_buffer_.stream_offset() ||
kMaxStreamLength < send_buffer_.stream_offset()) {
- QUIC_BUG << "Write too many data via stream " << id_;
+ QUIC_BUG(quic_bug_10586_8) << "Write too many data via stream " << id_;
OnUnrecoverableError(
QUIC_STREAM_LENGTH_OVERFLOW,
absl::StrCat("Write too many data via stream ", id_));
@@ -879,7 +880,7 @@ void QuicStream::MaybeSendRstStream(QuicRstStreamErrorCode error) {
}
if (!session()->version().UsesHttp3()) {
- QUIC_BUG_IF(error == QUIC_STREAM_NO_ERROR);
+ QUIC_BUG_IF(quic_bug_12570_5, error == QUIC_STREAM_NO_ERROR);
stop_sending_sent_ = true;
CloseReadSide();
}
@@ -914,8 +915,8 @@ void QuicStream::OnClose() {
QUICHE_DCHECK(read_side_closed_ && write_side_closed_);
if (!fin_sent_ && !rst_sent_) {
- QUIC_BUG_IF(session()->connection()->connected() &&
- session()->version().UsesHttp3())
+ QUIC_BUG_IF(quic_bug_12570_6, session()->connection()->connected() &&
+ session()->version().UsesHttp3())
<< "The stream should've already sent RST in response to "
"STOP_SENDING";
// For flow control accounting, tell the peer how many bytes have been
@@ -949,8 +950,9 @@ void QuicStream::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
}
if (!flow_controller_.has_value()) {
- QUIC_BUG << ENDPOINT
- << "OnWindowUpdateFrame called on stream without flow control";
+ QUIC_BUG(quic_bug_10586_9)
+ << ENDPOINT
+ << "OnWindowUpdateFrame called on stream without flow control";
return;
}
@@ -963,9 +965,10 @@ void QuicStream::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
bool QuicStream::MaybeIncreaseHighestReceivedOffset(
QuicStreamOffset new_offset) {
if (!flow_controller_.has_value()) {
- QUIC_BUG << ENDPOINT
- << "MaybeIncreaseHighestReceivedOffset called on stream without "
- "flow control";
+ QUIC_BUG(quic_bug_10586_10)
+ << ENDPOINT
+ << "MaybeIncreaseHighestReceivedOffset called on stream without "
+ "flow control";
return false;
}
uint64_t increment =
@@ -987,8 +990,8 @@ bool QuicStream::MaybeIncreaseHighestReceivedOffset(
void QuicStream::AddBytesSent(QuicByteCount bytes) {
if (!flow_controller_.has_value()) {
- QUIC_BUG << ENDPOINT
- << "AddBytesSent called on stream without flow control";
+ QUIC_BUG(quic_bug_10586_11)
+ << ENDPOINT << "AddBytesSent called on stream without flow control";
return;
}
flow_controller_->AddBytesSent(bytes);
@@ -1005,7 +1008,7 @@ void QuicStream::AddBytesConsumed(QuicByteCount bytes) {
return;
}
if (!flow_controller_.has_value()) {
- QUIC_BUG
+ QUIC_BUG(quic_bug_12570_7)
<< ENDPOINT
<< "AddBytesConsumed called on non-crypto stream without flow control";
return;
@@ -1023,8 +1026,9 @@ void QuicStream::AddBytesConsumed(QuicByteCount bytes) {
bool QuicStream::MaybeConfigSendWindowOffset(QuicStreamOffset new_offset,
bool was_zero_rtt_rejected) {
if (!flow_controller_.has_value()) {
- QUIC_BUG << ENDPOINT
- << "ConfigSendWindowOffset called on stream without flow control";
+ QUIC_BUG(quic_bug_10586_12)
+ << ENDPOINT
+ << "ConfigSendWindowOffset called on stream without flow control";
return false;
}
@@ -1034,7 +1038,7 @@ bool QuicStream::MaybeConfigSendWindowOffset(QuicStreamOffset new_offset,
if (was_zero_rtt_rejected && new_offset < flow_controller_->bytes_sent()) {
// The client is given flow control window lower than what's written in
// 0-RTT. This QUIC implementation is unable to retransmit them.
- QUIC_BUG_IF(perspective_ == Perspective::IS_SERVER)
+ QUIC_BUG_IF(quic_bug_12570_8, perspective_ == Perspective::IS_SERVER)
<< "Server streams' flow control should never be configured twice.";
OnUnrecoverableError(
QUIC_ZERO_RTT_UNRETRANSMITTABLE,
@@ -1047,7 +1051,7 @@ bool QuicStream::MaybeConfigSendWindowOffset(QuicStreamOffset new_offset,
// In IETF QUIC, if the client receives flow control limit lower than what
// was resumed from 0-RTT, depending on 0-RTT status, it's either the
// peer's fault or our implementation's fault.
- QUIC_BUG_IF(perspective_ == Perspective::IS_SERVER)
+ QUIC_BUG_IF(quic_bug_12570_9, perspective_ == Perspective::IS_SERVER)
<< "Server streams' flow control should never be configured twice.";
OnUnrecoverableError(
was_zero_rtt_rejected ? QUIC_ZERO_RTT_REJECTION_LIMIT_REDUCED
@@ -1227,8 +1231,9 @@ void QuicStream::WriteBufferedData(absl::optional<EncryptionLevel> level) {
send_window = flow_controller_->SendWindowSize();
} else {
send_window = std::numeric_limits<QuicByteCount>::max();
- QUIC_BUG << ENDPOINT
- << "WriteBufferedData called on stream without flow control";
+ QUIC_BUG(quic_bug_10586_13)
+ << ENDPOINT
+ << "WriteBufferedData called on stream without flow control";
}
if (stream_contributes_to_connection_flow_control_) {
send_window =
@@ -1370,7 +1375,7 @@ void QuicStream::WritePendingRetransmission() {
bool QuicStream::MaybeSetTtl(QuicTime::Delta ttl) {
if (is_static_) {
- QUIC_BUG << "Cannot set TTL of a static stream.";
+ QUIC_BUG(quic_bug_10586_14) << "Cannot set TTL of a static stream.";
return false;
}
if (deadline_.IsInitialized()) {
@@ -1402,7 +1407,8 @@ void QuicStream::OnDeadlinePassed() {
bool QuicStream::IsFlowControlBlocked() const {
if (!flow_controller_.has_value()) {
- QUIC_BUG << "Trying to access non-existent flow controller.";
+ QUIC_BUG(quic_bug_10586_15)
+ << "Trying to access non-existent flow controller.";
return false;
}
return flow_controller_->IsBlocked();
@@ -1410,7 +1416,8 @@ bool QuicStream::IsFlowControlBlocked() const {
QuicStreamOffset QuicStream::highest_received_byte_offset() const {
if (!flow_controller_.has_value()) {
- QUIC_BUG << "Trying to access non-existent flow controller.";
+ QUIC_BUG(quic_bug_10586_16)
+ << "Trying to access non-existent flow controller.";
return 0;
}
return flow_controller_->highest_received_byte_offset();
@@ -1418,7 +1425,8 @@ QuicStreamOffset QuicStream::highest_received_byte_offset() const {
void QuicStream::UpdateReceiveWindowSize(QuicStreamOffset size) {
if (!flow_controller_.has_value()) {
- QUIC_BUG << "Trying to access non-existent flow controller.";
+ QUIC_BUG(quic_bug_10586_17)
+ << "Trying to access non-existent flow controller.";
return;
}
flow_controller_->UpdateReceiveWindowSize(size);
@@ -1446,4 +1454,8 @@ absl::optional<QuicByteCount> QuicStream::GetReceiveWindow() const {
: absl::nullopt;
}
+void QuicStream::OnStreamCreatedFromPendingStream() {
+ sequencer()->SetUnblocked();
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream.h b/chromium/net/third_party/quiche/src/quic/core/quic_stream.h
index d89e4602909..6e6e623b9f2 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream.h
@@ -376,6 +376,13 @@ class QUIC_EXPORT_PRIVATE QuicStream
bool fin_buffered() const { return fin_buffered_; }
+ // True if buffered data in send buffer is below buffered_data_threshold_.
+ bool CanWriteNewData() const;
+
+ // Called immediately after the stream is created from a pending stream,
+ // indicating it can start processing data.
+ void OnStreamCreatedFromPendingStream();
+
protected:
// Called when data of [offset, offset + data_length] is buffered in send
// buffer.
@@ -391,9 +398,6 @@ class QUIC_EXPORT_PRIVATE QuicStream
// a RST_STREAM has been sent.
virtual void OnClose();
- // True if buffered data in send buffer is below buffered_data_threshold_.
- bool CanWriteNewData() const;
-
// True if buffered data in send buffer is still below
// buffered_data_threshold_ even after writing |length| bytes.
bool CanWriteNewDataAfterData(QuicByteCount length) const;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc
index 397eb71269b..05562125557 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc
@@ -86,7 +86,7 @@ bool QuicStreamIdManager::MaybeAllowNewOutgoingStreams(
void QuicStreamIdManager::SetMaxOpenIncomingStreams(
QuicStreamCount max_open_streams) {
- QUIC_BUG_IF(incoming_stream_count_ > 0)
+ QUIC_BUG_IF(quic_bug_12413_1, incoming_stream_count_ > 0)
<< "non-zero incoming stream count " << incoming_stream_count_
<< " when setting max incoming stream to " << max_open_streams;
QUIC_DLOG_IF(WARNING, incoming_initial_max_open_streams_ != max_open_streams)
@@ -113,7 +113,8 @@ void QuicStreamIdManager::MaybeSendMaxStreamsFrame() {
}
void QuicStreamIdManager::SendMaxStreamsFrame() {
- QUIC_BUG_IF(incoming_advertised_max_streams_ >= incoming_actual_max_streams_);
+ QUIC_BUG_IF(quic_bug_12413_2,
+ incoming_advertised_max_streams_ >= incoming_actual_max_streams_);
incoming_advertised_max_streams_ = incoming_actual_max_streams_;
delegate_->SendMaxStreams(incoming_advertised_max_streams_, unidirectional_);
}
@@ -138,7 +139,7 @@ void QuicStreamIdManager::OnStreamClosed(QuicStreamId stream_id) {
}
QuicStreamId QuicStreamIdManager::GetNextOutgoingStreamId() {
- QUIC_BUG_IF(outgoing_stream_count_ >= outgoing_max_streams_)
+ QUIC_BUG_IF(quic_bug_12413_3, outgoing_stream_count_ >= outgoing_max_streams_)
<< "Attempt to allocate a new outgoing stream that would exceed the "
"limit ("
<< outgoing_max_streams_ << ")";
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.cc
index 219eacdbd60..3b1b37bd1f3 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.cc
@@ -77,7 +77,7 @@ void QuicStreamSendBuffer::SaveMemSlice(QuicMemSlice slice) {
QUIC_DVLOG(2) << "Save slice offset " << stream_offset_ << " length "
<< slice.length();
if (slice.empty()) {
- QUIC_BUG << "Try to save empty MemSlice to send buffer.";
+ QUIC_BUG(quic_bug_10853_1) << "Try to save empty MemSlice to send buffer.";
return;
}
size_t length = slice.length();
@@ -104,7 +104,7 @@ void QuicStreamSendBuffer::OnStreamDataConsumed(size_t bytes_consumed) {
bool QuicStreamSendBuffer::WriteStreamData(QuicStreamOffset offset,
QuicByteCount data_length,
QuicDataWriter* writer) {
- QUIC_BUG_IF(current_end_offset_ < offset)
+ QUIC_BUG_IF(quic_bug_12823_1, current_end_offset_ < offset)
<< "Tried to write data out of sequence. last_offset_end:"
<< current_end_offset_ << ", offset:" << offset;
// The iterator returned from |interval_deque_| will automatically advance
@@ -122,7 +122,7 @@ bool QuicStreamSendBuffer::WriteStreamData(QuicStreamOffset offset,
QuicByteCount copy_length = std::min(data_length, available_bytes_in_slice);
if (!writer->WriteBytes(slice_it->slice.data() + slice_offset,
copy_length)) {
- QUIC_BUG << "Writer fails to write.";
+ QUIC_BUG(quic_bug_10853_2) << "Writer fails to write.";
return false;
}
offset += copy_length;
@@ -219,8 +219,9 @@ StreamPendingRetransmission QuicStreamSendBuffer::NextPendingRetransmission()
const auto pending = pending_retransmissions_.begin();
return {pending->min(), pending->max() - pending->min()};
}
- QUIC_BUG << "NextPendingRetransmission is called unexpected with no "
- "pending retransmissions.";
+ QUIC_BUG(quic_bug_10853_3)
+ << "NextPendingRetransmission is called unexpected with no "
+ "pending retransmissions.";
return {0, 0};
}
@@ -228,10 +229,11 @@ bool QuicStreamSendBuffer::FreeMemSlices(QuicStreamOffset start,
QuicStreamOffset end) {
auto it = interval_deque_.DataBegin();
if (it == interval_deque_.DataEnd() || it->slice.empty()) {
- QUIC_BUG << "Trying to ack stream data [" << start << ", " << end << "), "
- << (it == interval_deque_.DataEnd()
- ? "and there is no outstanding data."
- : "and the first slice is empty.");
+ QUIC_BUG(quic_bug_10853_4)
+ << "Trying to ack stream data [" << start << ", " << end << "), "
+ << (it == interval_deque_.DataEnd()
+ ? "and there is no outstanding data."
+ : "and the first slice is empty.");
return false;
}
if (!it->interval().Contains(start)) {
@@ -240,9 +242,10 @@ bool QuicStreamSendBuffer::FreeMemSlices(QuicStreamOffset start,
interval_deque_.DataEnd(), start, CompareOffset());
}
if (it == interval_deque_.DataEnd() || it->slice.empty()) {
- QUIC_BUG << "Offset " << start << " with iterator offset: " << it->offset
- << (it == interval_deque_.DataEnd() ? " does not exist."
- : " has already been acked.");
+ QUIC_BUG(quic_bug_10853_5)
+ << "Offset " << start << " with iterator offset: " << it->offset
+ << (it == interval_deque_.DataEnd() ? " does not exist."
+ : " has already been acked.");
return false;
}
for (; it != interval_deque_.DataEnd(); ++it) {
@@ -260,7 +263,8 @@ bool QuicStreamSendBuffer::FreeMemSlices(QuicStreamOffset start,
void QuicStreamSendBuffer::CleanUpBufferedSlices() {
while (!interval_deque_.Empty() &&
interval_deque_.DataBegin()->slice.empty()) {
- QUIC_BUG_IF(interval_deque_.DataBegin()->offset > current_end_offset_)
+ QUIC_BUG_IF(quic_bug_12823_2,
+ interval_deque_.DataBegin()->offset > current_end_offset_)
<< "Fail to pop front from interval_deque_. Front element contained "
"a slice whose data has not all be written. Front offset "
<< interval_deque_.DataBegin()->offset << " length "
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 e702f714747..cf7340bdb65 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
@@ -40,8 +40,8 @@ QuicStreamSequencer::QuicStreamSequencer(StreamInterface* quic_stream)
QuicStreamSequencer::~QuicStreamSequencer() {
if (stream_ == nullptr) {
- QUIC_BUG << "Double free'ing QuicStreamSequencer at " << this << ". "
- << QuicStackTrace();
+ QUIC_BUG(quic_bug_10858_1) << "Double free'ing QuicStreamSequencer at "
+ << this << ". " << QuicStackTrace();
}
stream_ = nullptr;
}
@@ -235,9 +235,10 @@ void QuicStreamSequencer::MarkConsumed(size_t num_bytes_consumed) {
QUICHE_DCHECK(!blocked_);
bool result = buffered_frames_.MarkConsumed(num_bytes_consumed);
if (!result) {
- QUIC_BUG << "Invalid argument to MarkConsumed."
- << " expect to consume: " << num_bytes_consumed
- << ", but not enough bytes available. " << DebugString();
+ QUIC_BUG(quic_bug_10858_2)
+ << "Invalid argument to MarkConsumed."
+ << " expect to consume: " << num_bytes_consumed
+ << ", but not enough bytes available. " << DebugString();
stream_->Reset(QUIC_ERROR_PROCESSING_STREAM);
return;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.cc
index 5c85a6e7baa..871b832b168 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.cc
@@ -73,7 +73,7 @@ void QuicStreamSequencerBuffer::Clear() {
bool QuicStreamSequencerBuffer::RetireBlock(size_t index) {
if (blocks_[index] == nullptr) {
- QUIC_BUG << "Try to retire block twice";
+ QUIC_BUG(quic_bug_10610_1) << "Try to retire block twice";
return false;
}
delete blocks_[index];
@@ -516,7 +516,7 @@ bool QuicStreamSequencerBuffer::RetireBlockIfEmpty(size_t block_index) {
return true;
}
} else {
- QUIC_BUG << "Read stopped at where it shouldn't.";
+ QUIC_BUG(quic_bug_10610_2) << "Read stopped at where it shouldn't.";
return false;
}
}
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 46c4b4af3f6..739113a9147 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
@@ -9,6 +9,7 @@
#include <utility>
#include "absl/base/macros.h"
+#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "quic/core/crypto/null_encrypter.h"
@@ -24,7 +25,6 @@
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_mem_slice_storage.h"
-#include "quic/platform/api/quic_ptr_util.h"
#include "quic/platform/api/quic_test.h"
#include "quic/platform/api/quic_test_mem_slice_vector.h"
#include "quic/test_tools/quic_config_peer.h"
@@ -114,7 +114,7 @@ class QuicStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
BIDIRECTIONAL);
EXPECT_NE(nullptr, stream_);
// session_ now owns stream_.
- session_->ActivateStream(QuicWrapUnique(stream_));
+ session_->ActivateStream(absl::WrapUnique(stream_));
// Ignore resetting when session_ is terminated.
EXPECT_CALL(*session_, MaybeSendStopSendingFrame(kTestStreamId, _))
.Times(AnyNumber());
@@ -264,7 +264,7 @@ TEST_P(QuicStreamTest, FromPendingStreamThenData) {
auto stream = new TestStream(&pending, session_.get(),
StreamType::READ_UNIDIRECTIONAL, false);
- session_->ActivateStream(QuicWrapUnique(stream));
+ session_->ActivateStream(absl::WrapUnique(stream));
QuicStreamFrame frame2(kTestStreamId + 2, true, 3, ".");
stream->OnStreamFrame(frame2);
@@ -1437,7 +1437,7 @@ TEST_P(QuicStreamTest, MarkConnectionLevelWriteBlockedOnWindowUpdateFrame) {
auto stream = new TestStream(GetNthClientInitiatedBidirectionalStreamId(
GetParam().transport_version, 2),
session_.get(), BIDIRECTIONAL);
- session_->ActivateStream(QuicWrapUnique(stream));
+ session_->ActivateStream(absl::WrapUnique(stream));
EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData));
@@ -1470,7 +1470,7 @@ TEST_P(QuicStreamTest,
auto stream = new TestStream(GetNthClientInitiatedBidirectionalStreamId(
GetParam().transport_version, 2),
session_.get(), BIDIRECTIONAL);
- session_->ActivateStream(QuicWrapUnique(stream));
+ session_->ActivateStream(absl::WrapUnique(stream));
std::string data(100, '.');
EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
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 641f5c90c03..d6fa2da7a10 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
@@ -192,6 +192,7 @@ void QuicTimeWaitListManager::ProcessPacket(
const QuicSocketAddress& peer_address,
QuicConnectionId connection_id,
PacketHeaderFormat header_format,
+ size_t received_packet_length,
std::unique_ptr<QuicPerPacketContext> packet_context) {
QUICHE_DCHECK(IsConnectionIdInTimeWait(connection_id));
// TODO(satyamshekhar): Think about handling packets from different peer
@@ -224,7 +225,7 @@ void QuicTimeWaitListManager::ProcessPacket(
switch (connection_data->action) {
case SEND_TERMINATION_PACKETS:
if (connection_data->info.termination_packets.empty()) {
- QUIC_BUG << "There are no termination packets.";
+ QUIC_BUG(quic_bug_10608_1) << "There are no termination packets.";
return;
}
switch (header_format) {
@@ -240,7 +241,7 @@ void QuicTimeWaitListManager::ProcessPacket(
// Send stateless reset in response to short header packets.
SendPublicReset(self_address, peer_address, connection_id,
connection_data->info.ietf_quic,
- std::move(packet_context));
+ received_packet_length, std::move(packet_context));
return;
case GOOGLE_QUIC_PACKET:
if (connection_data->info.ietf_quic) {
@@ -258,7 +259,7 @@ void QuicTimeWaitListManager::ProcessPacket(
case SEND_CONNECTION_CLOSE_PACKETS:
if (connection_data->info.termination_packets.empty()) {
- QUIC_BUG << "There are no termination packets.";
+ QUIC_BUG(quic_bug_10608_2) << "There are no termination packets.";
return;
}
for (const auto& packet : connection_data->info.termination_packets) {
@@ -273,7 +274,7 @@ void QuicTimeWaitListManager::ProcessPacket(
QUIC_CODE_COUNT(quic_stateless_reset_long_header_packet);
}
SendPublicReset(self_address, peer_address, connection_id,
- connection_data->info.ietf_quic,
+ connection_data->info.ietf_quic, received_packet_length,
std::move(packet_context));
return;
case DO_NOTHING:
@@ -318,10 +319,11 @@ void QuicTimeWaitListManager::SendPublicReset(
const QuicSocketAddress& peer_address,
QuicConnectionId connection_id,
bool ietf_quic,
+ size_t received_packet_length,
std::unique_ptr<QuicPerPacketContext> packet_context) {
if (ietf_quic) {
std::unique_ptr<QuicEncryptedPacket> ietf_reset_packet =
- BuildIetfStatelessResetPacket(connection_id);
+ BuildIetfStatelessResetPacket(connection_id, received_packet_length);
QUIC_DVLOG(2) << "Dispatcher sending IETF reset packet for "
<< connection_id << std::endl
<< quiche::QuicheTextUtils::HexDump(
@@ -333,6 +335,7 @@ void QuicTimeWaitListManager::SendPublicReset(
packet_context.get());
return;
}
+ // Google QUIC public resets donot elicit resets in response.
QuicPublicResetPacket packet;
packet.connection_id = connection_id;
// TODO(satyamshekhar): generate a valid nonce for this connection_id.
@@ -366,9 +369,11 @@ std::unique_ptr<QuicEncryptedPacket> QuicTimeWaitListManager::BuildPublicReset(
std::unique_ptr<QuicEncryptedPacket>
QuicTimeWaitListManager::BuildIetfStatelessResetPacket(
- QuicConnectionId connection_id) {
+ QuicConnectionId connection_id,
+ size_t received_packet_length) {
return QuicFramer::BuildIetfStatelessResetPacket(
- connection_id, GetStatelessResetToken(connection_id));
+ connection_id, received_packet_length,
+ GetStatelessResetToken(connection_id));
}
// Either sends the packet and deletes it or makes pending queue the
@@ -495,7 +500,7 @@ QuicTimeWaitListManager::ConnectionIdData::ConnectionIdData(
QuicTimeWaitListManager::ConnectionIdData::~ConnectionIdData() = default;
-QuicUint128 QuicTimeWaitListManager::GetStatelessResetToken(
+StatelessResetToken QuicTimeWaitListManager::GetStatelessResetToken(
QuicConnectionId connection_id) const {
return QuicUtils::GenerateStatelessResetToken(connection_id);
}
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 9b3739b958c..2018f723306 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
@@ -18,6 +18,7 @@
#include "quic/core/quic_packet_writer.h"
#include "quic/core/quic_packets.h"
#include "quic/core/quic_session.h"
+#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_containers.h"
#include "quic/platform/api/quic_flags.h"
@@ -118,11 +119,14 @@ class QUIC_NO_EXPORT QuicTimeWaitListManager
// connection_id. Sending of the public reset packet is throttled by using
// exponential back off. QUICHE_DCHECKs for the connection_id to be in time
// wait state. virtual to override in tests.
+ // TODO(fayang): change ProcessPacket and SendPublicReset to take
+ // ReceivedPacketInfo.
virtual void ProcessPacket(
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
QuicConnectionId connection_id,
PacketHeaderFormat header_format,
+ size_t received_packet_length,
std::unique_ptr<QuicPerPacketContext> packet_context);
// Called by the dispatcher when the underlying socket becomes writable again,
@@ -164,6 +168,7 @@ class QUIC_NO_EXPORT QuicTimeWaitListManager
const QuicSocketAddress& peer_address,
QuicConnectionId connection_id,
bool ietf_quic,
+ size_t received_packet_length,
std::unique_ptr<QuicPerPacketContext> packet_context);
// Called to send |packet|.
@@ -182,7 +187,7 @@ class QUIC_NO_EXPORT QuicTimeWaitListManager
// Returns a stateless reset token which will be included in the public reset
// packet.
- virtual QuicUint128 GetStatelessResetToken(
+ virtual StatelessResetToken GetStatelessResetToken(
QuicConnectionId connection_id) const;
// Internal structure to store pending termination packets.
@@ -257,7 +262,8 @@ class QUIC_NO_EXPORT QuicTimeWaitListManager
QuicTime::Delta /*srtt*/) const {}
std::unique_ptr<QuicEncryptedPacket> BuildIetfStatelessResetPacket(
- QuicConnectionId connection_id);
+ QuicConnectionId connection_id,
+ size_t received_packet_length);
// A map from a recently closed connection_id to the number of packets
// received after the termination of the connection bound to the
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 189d3f09b21..d33e992e372 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
@@ -21,7 +21,6 @@
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_test.h"
-#include "quic/platform/api/quic_uint128.h"
#include "quic/test_tools/mock_quic_session_visitor.h"
#include "quic/test_tools/quic_test_utils.h"
#include "quic/test_tools/quic_time_wait_list_manager_peer.h"
@@ -41,6 +40,8 @@ namespace quic {
namespace test {
namespace {
+const size_t kTestPacketSize = 100;
+
class FramerVisitorCapturingPublicReset : public NoOpFramerVisitor {
public:
FramerVisitorCapturingPublicReset(QuicConnectionId connection_id)
@@ -55,7 +56,8 @@ class FramerVisitorCapturingPublicReset : public NoOpFramerVisitor {
return public_reset_packet_;
}
- bool IsValidStatelessResetToken(QuicUint128 token) const override {
+ bool IsValidStatelessResetToken(
+ const StatelessResetToken& token) const override {
return token == QuicUtils::GenerateStatelessResetToken(connection_id_);
}
@@ -176,7 +178,7 @@ class QuicTimeWaitListManagerTest : public QuicTest {
void ProcessPacket(QuicConnectionId connection_id) {
time_wait_list_manager_.ProcessPacket(
self_address_, peer_address_, connection_id, GOOGLE_QUIC_PACKET,
- std::make_unique<QuicPerPacketContext>());
+ kTestPacketSize, std::make_unique<QuicPerPacketContext>());
}
QuicEncryptedPacket* ConstructEncryptedPacket(
@@ -218,7 +220,7 @@ bool ValidPublicResetPacketPredicate(
QuicIetfStatelessResetPacket stateless_reset =
visitor.stateless_reset_packet();
- QuicUint128 expected_stateless_reset_token =
+ StatelessResetToken expected_stateless_reset_token =
QuicUtils::GenerateStatelessResetToken(expected_connection_id);
bool stateless_reset_is_valid =
@@ -684,7 +686,8 @@ TEST_F(QuicTimeWaitListManagerTest,
// Processes IETF short header packet.
time_wait_list_manager_.ProcessPacket(
self_address_, peer_address_, connection_id_,
- IETF_QUIC_SHORT_HEADER_PACKET, std::make_unique<QuicPerPacketContext>());
+ IETF_QUIC_SHORT_HEADER_PACKET, kTestPacketSize,
+ std::make_unique<QuicPerPacketContext>());
}
TEST_F(QuicTimeWaitListManagerTest,
@@ -707,7 +710,8 @@ TEST_F(QuicTimeWaitListManagerTest,
// Processes IETF short header packet.
time_wait_list_manager_.ProcessPacket(
self_address_, peer_address_, connection_id_,
- IETF_QUIC_SHORT_HEADER_PACKET, std::make_unique<QuicPerPacketContext>());
+ IETF_QUIC_SHORT_HEADER_PACKET, kTestPacketSize,
+ std::make_unique<QuicPerPacketContext>());
}
TEST_F(QuicTimeWaitListManagerTest,
@@ -741,7 +745,7 @@ TEST_F(QuicTimeWaitListManagerTest,
for (auto const& cid : active_connection_ids) {
time_wait_list_manager_.ProcessPacket(
self_address_, peer_address_, cid, IETF_QUIC_SHORT_HEADER_PACKET,
- std::make_unique<QuicPerPacketContext>());
+ kTestPacketSize, std::make_unique<QuicPerPacketContext>());
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.cc b/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.cc
index 381d29bd5e3..f603f583e2d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.cc
@@ -22,7 +22,7 @@ quic_trace::EncryptionLevel EncryptionLevelToProto(EncryptionLevel level) {
case ENCRYPTION_FORWARD_SECURE:
return quic_trace::ENCRYPTION_1RTT;
case NUM_ENCRYPTION_LEVELS:
- QUIC_BUG << "Invalid encryption level specified";
+ QUIC_BUG(quic_bug_10284_1) << "Invalid encryption level specified";
return quic_trace::ENCRYPTION_UNKNOWN;
}
}
@@ -77,7 +77,7 @@ void QuicTraceVisitor::OnPacketSent(
case MTU_DISCOVERY_FRAME:
case STOP_WAITING_FRAME:
case ACK_FRAME:
- QUIC_BUG
+ QUIC_BUG(quic_bug_12732_1)
<< "Frames of type are not retransmittable and are not supposed "
"to be in retransmittable_frames";
break;
@@ -100,7 +100,7 @@ void QuicTraceVisitor::OnPacketSent(
break;
case NUM_FRAME_TYPES:
- QUIC_BUG << "Unknown frame type encountered";
+ QUIC_BUG(quic_bug_10284_2) << "Unknown frame type encountered";
break;
}
}
@@ -228,7 +228,7 @@ void QuicTraceVisitor::PopulateFrameInfo(const QuicFrame& frame,
break;
case NUM_FRAME_TYPES:
- QUIC_BUG << "Unknown frame type encountered";
+ QUIC_BUG(quic_bug_10284_3) << "Unknown frame type encountered";
break;
}
}
@@ -314,7 +314,8 @@ void QuicTraceVisitor::OnAdjustNetworkParameters(QuicBandwidth bandwidth,
uint64_t QuicTraceVisitor::ConvertTimestampToRecordedFormat(
QuicTime timestamp) {
if (timestamp < start_time_) {
- QUIC_BUG << "Timestamp went back in time while recording a trace";
+ QUIC_BUG(quic_bug_10284_4)
+ << "Timestamp went back in time while recording a trace";
return 0;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_types.cc b/chromium/net/third_party/quiche/src/quic/core/quic_types.cc
index f8182684e7f..57163abbe42 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_types.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_types.cc
@@ -11,6 +11,9 @@
namespace quic {
+static_assert(sizeof(StatelessResetToken) == kStatelessResetTokenLength,
+ "bad size");
+
std::ostream& operator<<(std::ostream& os, const QuicConsumedData& s) {
os << "bytes_consumed: " << s.bytes_consumed
<< " fin_consumed: " << s.fin_consumed;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_types.h b/chromium/net/third_party/quiche/src/quic/core/quic_types.h
index 7344cea6de3..2e65e5f12a4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_types.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_types.h
@@ -7,6 +7,7 @@
#include <array>
#include <cstddef>
+#include <cstdint>
#include <map>
#include <ostream>
#include <vector>
@@ -43,6 +44,12 @@ using QuicStreamOffset = uint64_t;
using DiversificationNonce = std::array<char, 32>;
using PacketTimeVector = std::vector<std::pair<QuicPacketNumber, QuicTime>>;
+enum : size_t { kStatelessResetTokenLength = 16 };
+using StatelessResetToken = std::array<char, kStatelessResetTokenLength>;
+
+// WebTransport session IDs are stream IDs.
+using WebTransportSessionId = uint64_t;
+
enum : size_t { kQuicPathFrameBufferSize = 8 };
using QuicPathFrameBuffer = std::array<uint8_t, kQuicPathFrameBufferSize>;
@@ -278,7 +285,7 @@ QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
// byte, with the two most significant bits being 0. Thus, the following
// enumerations are valid as both the numeric values of frame types AND their
// encodings.
-enum QuicIetfFrameType : uint8_t {
+enum QuicIetfFrameType : uint64_t {
IETF_PADDING = 0x00,
IETF_PING = 0x01,
IETF_ACK = 0x02,
@@ -708,10 +715,10 @@ enum AckResult {
// Indicates the fate of a serialized packet in WritePacket().
enum SerializedPacketFate : uint8_t {
- DISCARD, // Discard the packet.
- COALESCE, // Try to coalesce packet.
- BUFFER, // Buffer packet in buffered_packets_.
- SEND_TO_WRITER, // Send packet to writer.
+ DISCARD, // Discard the packet.
+ COALESCE, // Try to coalesce packet.
+ BUFFER, // Buffer packet in buffered_packets_.
+ SEND_TO_WRITER, // Send packet to writer.
LEGACY_VERSION_ENCAPSULATE, // Perform Legacy Version Encapsulation on this
// packet.
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_udp_socket_posix.cc b/chromium/net/third_party/quiche/src/quic/core/quic_udp_socket_posix.cc
index e410635cef5..eef582b99f1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_udp_socket_posix.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_udp_socket_posix.cc
@@ -157,7 +157,7 @@ void PopulatePacketInfoFromControlMessage(struct cmsghdr* cmsg,
if (self_v6_ip.FromPackedString(addr_data, addr_len)) {
packet_info->SetSelfV6Ip(self_v6_ip);
} else {
- QUIC_BUG << "QuicIpAddress::FromPackedString failed";
+ QUIC_BUG(quic_bug_10751_1) << "QuicIpAddress::FromPackedString failed";
}
}
return;
@@ -172,7 +172,7 @@ void PopulatePacketInfoFromControlMessage(struct cmsghdr* cmsg,
if (self_v4_ip.FromPackedString(addr_data, addr_len)) {
packet_info->SetSelfV4Ip(self_v4_ip);
} else {
- QUIC_BUG << "QuicIpAddress::FromPackedString failed";
+ QUIC_BUG(quic_bug_10751_2) << "QuicIpAddress::FromPackedString failed";
}
}
return;
@@ -421,7 +421,8 @@ void QuicUdpSocketApi::ReadPacket(QuicUdpSocketFd fd,
}
if (QUIC_PREDICT_FALSE(hdr.msg_flags & MSG_CTRUNC)) {
- QUIC_BUG << "Control buffer too small. size:" << control_buffer.buffer_len;
+ QUIC_BUG(quic_bug_10751_3)
+ << "Control buffer too small. size:" << control_buffer.buffer_len;
return;
}
@@ -509,9 +510,9 @@ size_t QuicUdpSocketApi::ReadMultiplePackets(QuicUdpSocketFd fd,
msghdr& hdr = hdrs[i].msg_hdr;
if (QUIC_PREDICT_FALSE(hdr.msg_flags & MSG_CTRUNC)) {
- QUIC_BUG << "Control buffer too small. size:"
- << (*results)[i].control_buffer.buffer_len
- << ", need:" << hdr.msg_controllen;
+ QUIC_BUG(quic_bug_10751_4) << "Control buffer too small. size:"
+ << (*results)[i].control_buffer.buffer_len
+ << ", need:" << hdr.msg_controllen;
continue;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_udp_socket_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_udp_socket_test.cc
deleted file mode 100644
index 400c38e6fda..00000000000
--- a/chromium/net/third_party/quiche/src/quic/core/quic_udp_socket_test.cc
+++ /dev/null
@@ -1,439 +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.
-
-#include "quic/core/quic_udp_socket.h"
-#include <sys/socket.h>
-
-#ifdef __APPLE__
-#include <TargetConditionals.h>
-#endif
-
-#include "quic/core/quic_constants.h"
-#include "quic/platform/api/quic_test.h"
-
-namespace quic {
-namespace test {
-namespace {
-// Used by ReadMultiplePackets tests.
-struct ReadBuffers {
- char control_buffer[512];
- char packet_buffer[1536];
-};
-
-// Allows IPv6-specific testing.
-struct TestParameters {
- // If true, the test will only use IPv6. If false, IPv4 will be used if
- // possible, with IPv6 used as a fallback.
- bool force_ipv6;
- // The value of ipv6_only to be used in QuicUdpSocketApi::Create calls.
- bool ipv6_only;
-};
-} // namespace
-
-class QuicUdpSocketTest : public QuicTestWithParam<TestParameters> {
- protected:
- void SetUp() override {
- const TestParameters& parameters = GetParam();
- if (!parameters.force_ipv6) {
- // Try creating AF_INET socket, if it fails because of unsupported address
- // family then tests are being run under IPv6-only environment, initialize
- // address family to use for running the test under as AF_INET6 otherwise
- // initialize it as AF_INET.
- address_family_ = AF_INET;
- fd_client_ =
- api_.Create(address_family_,
- /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
- /*send_buffer_size =*/kDefaultSocketReceiveBuffer,
- /*ipv6_only =*/parameters.ipv6_only);
- }
- if (fd_client_ == kQuicInvalidSocketFd) {
- // Either AF_INET is unsupported, or force_ipv6 is true.
- address_family_ = AF_INET6;
- fd_client_ =
- api_.Create(address_family_,
- /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
- /*send_buffer_size =*/kDefaultSocketReceiveBuffer,
- /*ipv6_only =*/parameters.ipv6_only);
- }
- ASSERT_NE(fd_client_, kQuicInvalidSocketFd);
-
- fd_server_ =
- api_.Create(address_family_,
- /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
- /*send_buffer_size =*/kDefaultSocketReceiveBuffer,
- /*ipv6_only =*/parameters.ipv6_only);
- ASSERT_NE(fd_server_, kQuicInvalidSocketFd);
-
- ASSERT_TRUE(
- api_.Bind(fd_server_, QuicSocketAddress(Loopback(), /*port=*/0)));
-
- ASSERT_EQ(0, server_address_.FromSocket(fd_server_));
-
- QUIC_LOG(INFO) << "Testing under IP"
- << std::string((address_family_ == AF_INET) ? "v4" : "v6");
- }
-
- ~QuicUdpSocketTest() {
- api_.Destroy(fd_client_);
- api_.Destroy(fd_server_);
- }
-
- QuicIpAddress Loopback() const {
- return (address_family_ == AF_INET) ? QuicIpAddress::Loopback4()
- : QuicIpAddress::Loopback6();
- }
-
- // Client sends the first |packet_size| bytes in |client_packet_buffer_| to
- // server.
- WriteResult SendPacketFromClient(size_t packet_size) {
- EXPECT_LE(packet_size, sizeof(client_packet_buffer_));
- QuicUdpPacketInfo packet_info;
- packet_info.SetPeerAddress(server_address_);
- return api_.WritePacket(fd_client_, client_packet_buffer_, packet_size,
- packet_info);
- }
-
- WriteResult SendPacketFromClientWithTtl(size_t packet_size, int ttl) {
- EXPECT_LE(packet_size, sizeof(client_packet_buffer_));
- QuicUdpPacketInfo packet_info;
- packet_info.SetPeerAddress(server_address_);
- packet_info.SetTtl(ttl);
- return api_.WritePacket(fd_client_, client_packet_buffer_, packet_size,
- packet_info);
- }
-
- // Server waits for an incoming packet and reads it into
- // |server_packet_buffer_|.
- QuicUdpSocketApi::ReadPacketResult ReadPacketFromServer(
- BitMask64 packet_info_interested) {
- EXPECT_TRUE(
- api_.WaitUntilReadable(fd_server_, QuicTime::Delta::FromSeconds(5)));
- memset(server_packet_buffer_, 0, sizeof(server_packet_buffer_));
- QuicUdpSocketApi::ReadPacketResult result;
- result.packet_buffer = {server_packet_buffer_,
- sizeof(server_packet_buffer_)};
- result.control_buffer = {server_control_buffer_,
- sizeof(server_control_buffer_)};
- api_.ReadPacket(fd_server_, packet_info_interested, &result);
- return result;
- }
-
- int ComparePacketBuffers(size_t packet_size) {
- return memcmp(client_packet_buffer_, server_packet_buffer_, packet_size);
- }
-
- bool VerifyBufferIsFilledWith(const char* buffer,
- size_t buffer_length,
- char c) {
- for (size_t i = 0; i < buffer_length; ++i) {
- if (buffer[i] != c) {
- return false;
- }
- }
- return true;
- }
-
- QuicUdpSocketApi api_;
- QuicUdpSocketFd fd_client_ = kQuicInvalidSocketFd;
- QuicUdpSocketFd fd_server_ = kQuicInvalidSocketFd;
- QuicSocketAddress server_address_;
- int address_family_;
- char client_packet_buffer_[kEthernetMTU] = {0};
- char server_packet_buffer_[kDefaultMaxPacketSize] = {0};
- char server_control_buffer_[512] = {0};
-};
-
-INSTANTIATE_TEST_SUITE_P(
- PlatformIndependent,
- QuicUdpSocketTest,
- testing::Values(TestParameters{/*force_ipv6 =*/false, /*ipv6_only =*/false},
- TestParameters{/*force_ipv6 =*/false, /*ipv6_only =*/true},
- TestParameters{/*force_ipv6 =*/true, /*ipv6_only =*/true}));
-
-#ifndef TARGET_OS_IPHONE
-// IPv6 on iOS is known to fail without ipv6_only, so should not be tested.
-INSTANTIATE_TEST_SUITE_P(NonIos,
- QuicUdpSocketTest,
- testing::Values(TestParameters{/*force_ipv6 =*/true,
- /*ipv6_only =*/false}));
-#endif
-
-TEST_P(QuicUdpSocketTest, ReadPacketResultReset) {
- QuicUdpSocketApi::ReadPacketResult result;
- result.packet_info.SetDroppedPackets(100);
- result.packet_buffer.buffer_len = 100;
- result.ok = true;
-
- result.Reset(/*packet_buffer_length=*/200);
-
- EXPECT_FALSE(result.ok);
- EXPECT_FALSE(
- result.packet_info.HasValue(QuicUdpPacketInfoBit::DROPPED_PACKETS));
- EXPECT_EQ(200u, result.packet_buffer.buffer_len);
-}
-
-TEST_P(QuicUdpSocketTest, ReadPacketOnly) {
- const size_t kPacketSize = 512;
- memset(client_packet_buffer_, '-', kPacketSize);
- ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
- SendPacketFromClient(kPacketSize));
-
- QuicUdpSocketApi::ReadPacketResult read_result =
- ReadPacketFromServer(/*packet_info_interested=*/BitMask64());
- ASSERT_TRUE(read_result.ok);
- ASSERT_EQ(kPacketSize, read_result.packet_buffer.buffer_len);
- ASSERT_EQ(0, ComparePacketBuffers(kPacketSize));
-}
-
-TEST_P(QuicUdpSocketTest, ReadTruncated) {
- const size_t kPacketSize = kDefaultMaxPacketSize + 1;
- memset(client_packet_buffer_, '*', kPacketSize);
- ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
- SendPacketFromClient(kPacketSize));
-
- QuicUdpSocketApi::ReadPacketResult read_result =
- ReadPacketFromServer(/*packet_info_interested=*/BitMask64());
- ASSERT_FALSE(read_result.ok);
-}
-
-TEST_P(QuicUdpSocketTest, ReadDroppedPackets) {
- const size_t kPacketSize = kDefaultMaxPacketSize;
- memset(client_packet_buffer_, '-', kPacketSize);
- ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
- SendPacketFromClient(kPacketSize));
- ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
- SendPacketFromClient(kPacketSize));
-
- // Read the first packet without enabling DROPPED_PACKETS.
- QuicUdpSocketApi::ReadPacketResult read_result =
- ReadPacketFromServer(BitMask64(QuicUdpPacketInfoBit::DROPPED_PACKETS));
- ASSERT_TRUE(read_result.ok);
- ASSERT_EQ(kPacketSize, read_result.packet_buffer.buffer_len);
- ASSERT_EQ(0, ComparePacketBuffers(kPacketSize));
- ASSERT_FALSE(
- read_result.packet_info.HasValue(QuicUdpPacketInfoBit::DROPPED_PACKETS));
-
- // Enable DROPPED_PACKETS and read the second packet.
- if (!api_.EnableDroppedPacketCount(fd_server_)) {
- QUIC_LOG(INFO) << "DROPPED_PACKETS is not supported";
- return;
- }
- read_result =
- ReadPacketFromServer(BitMask64(QuicUdpPacketInfoBit::DROPPED_PACKETS));
- ASSERT_TRUE(read_result.ok);
- ASSERT_EQ(kPacketSize, read_result.packet_buffer.buffer_len);
- ASSERT_EQ(0, ComparePacketBuffers(kPacketSize));
- if (read_result.packet_info.HasValue(QuicUdpPacketInfoBit::DROPPED_PACKETS)) {
- EXPECT_EQ(0u, read_result.packet_info.dropped_packets());
- }
-}
-
-TEST_P(QuicUdpSocketTest, ReadSelfIp) {
- const QuicUdpPacketInfoBit self_ip_bit =
- (address_family_ == AF_INET) ? QuicUdpPacketInfoBit::V4_SELF_IP
- : QuicUdpPacketInfoBit::V6_SELF_IP;
-
- const size_t kPacketSize = 512;
- memset(client_packet_buffer_, '&', kPacketSize);
- ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
- SendPacketFromClient(kPacketSize));
-
- QuicUdpSocketApi::ReadPacketResult read_result =
- ReadPacketFromServer(BitMask64(self_ip_bit));
- ASSERT_TRUE(read_result.ok);
- ASSERT_EQ(kPacketSize, read_result.packet_buffer.buffer_len);
- ASSERT_EQ(0, ComparePacketBuffers(kPacketSize));
- ASSERT_TRUE(read_result.packet_info.HasValue(self_ip_bit));
- EXPECT_EQ(Loopback(), (address_family_ == AF_INET)
- ? read_result.packet_info.self_v4_ip()
- : read_result.packet_info.self_v6_ip());
-}
-
-TEST_P(QuicUdpSocketTest, ReadReceiveTimestamp) {
- const size_t kPacketSize = kDefaultMaxPacketSize;
- memset(client_packet_buffer_, '-', kPacketSize);
- ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
- SendPacketFromClient(kPacketSize));
- ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
- SendPacketFromClient(kPacketSize));
-
- // Read the first packet without enabling RECV_TIMESTAMP.
- QuicUdpSocketApi::ReadPacketResult read_result =
- ReadPacketFromServer(BitMask64(QuicUdpPacketInfoBit::RECV_TIMESTAMP));
- ASSERT_TRUE(read_result.ok);
- ASSERT_EQ(kPacketSize, read_result.packet_buffer.buffer_len);
- ASSERT_EQ(0, ComparePacketBuffers(kPacketSize));
- ASSERT_FALSE(
- read_result.packet_info.HasValue(QuicUdpPacketInfoBit::RECV_TIMESTAMP));
-
- // Enable RECV_TIMESTAMP and read the second packet.
- if (!api_.EnableReceiveTimestamp(fd_server_)) {
- QUIC_LOG(INFO) << "RECV_TIMESTAMP is not supported";
- return;
- }
- read_result =
- ReadPacketFromServer(BitMask64(QuicUdpPacketInfoBit::RECV_TIMESTAMP));
- ASSERT_TRUE(read_result.ok);
- ASSERT_EQ(kPacketSize, read_result.packet_buffer.buffer_len);
- ASSERT_EQ(0, ComparePacketBuffers(kPacketSize));
- ASSERT_TRUE(
- read_result.packet_info.HasValue(QuicUdpPacketInfoBit::RECV_TIMESTAMP));
- QuicWallTime recv_timestamp = read_result.packet_info.receive_timestamp();
- // 1577836800 is the unix seconds for 2020-01-01
- EXPECT_TRUE(
- QuicWallTime::FromUNIXSeconds(1577836800).IsBefore(recv_timestamp));
-}
-
-TEST_P(QuicUdpSocketTest, Ttl) {
- const size_t kPacketSize = 512;
- memset(client_packet_buffer_, '$', kPacketSize);
- ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
- SendPacketFromClientWithTtl(kPacketSize, 13));
- ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
- SendPacketFromClientWithTtl(kPacketSize, 13));
-
- // Read the first packet without enabling ttl reporting.
- QuicUdpSocketApi::ReadPacketResult read_result =
- ReadPacketFromServer(BitMask64(QuicUdpPacketInfoBit::TTL));
- ASSERT_TRUE(read_result.ok);
- ASSERT_EQ(kPacketSize, read_result.packet_buffer.buffer_len);
- ASSERT_EQ(0, ComparePacketBuffers(kPacketSize));
- ASSERT_FALSE(read_result.packet_info.HasValue(QuicUdpPacketInfoBit::TTL));
-
- // Enable ttl reporting and read the second packet.
- if (!((address_family_ == AF_INET)
- ? api_.EnableReceiveTtlForV4(fd_server_)
- : api_.EnableReceiveTtlForV6(fd_server_))) {
- QUIC_LOG(INFO) << "TTL is not supported for address family "
- << address_family_;
- return;
- }
-
- read_result = ReadPacketFromServer(BitMask64(QuicUdpPacketInfoBit::TTL));
- ASSERT_TRUE(read_result.ok);
- ASSERT_EQ(kPacketSize, read_result.packet_buffer.buffer_len);
- ASSERT_EQ(0, ComparePacketBuffers(kPacketSize));
- ASSERT_TRUE(read_result.packet_info.HasValue(QuicUdpPacketInfoBit::TTL));
- EXPECT_EQ(13, read_result.packet_info.ttl());
-}
-
-TEST_P(QuicUdpSocketTest, ReadMultiplePackets) {
- const QuicUdpPacketInfoBit self_ip_bit =
- (address_family_ == AF_INET) ? QuicUdpPacketInfoBit::V4_SELF_IP
- : QuicUdpPacketInfoBit::V6_SELF_IP;
- const size_t kPacketSize = kDefaultMaxPacketSize;
- const size_t kNumPackets = 90;
- for (size_t i = 0; i < kNumPackets; ++i) {
- memset(client_packet_buffer_, ' ' + i, kPacketSize);
- ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
- SendPacketFromClient(kPacketSize));
- }
-
- const size_t kNumPacketsPerRead = 16;
- size_t total_packets_read = 0;
- while (total_packets_read < kNumPackets) {
- std::unique_ptr<ReadBuffers[]> read_buffers =
- std::make_unique<ReadBuffers[]>(kNumPacketsPerRead);
- QuicUdpSocketApi::ReadPacketResults results(kNumPacketsPerRead);
- for (size_t i = 0; i < kNumPacketsPerRead; ++i) {
- results[i].packet_buffer.buffer = read_buffers[i].packet_buffer;
- results[i].packet_buffer.buffer_len =
- sizeof(read_buffers[i].packet_buffer);
-
- results[i].control_buffer.buffer = read_buffers[i].control_buffer;
- results[i].control_buffer.buffer_len =
- sizeof(read_buffers[i].control_buffer);
- }
- size_t packets_read =
- api_.ReadMultiplePackets(fd_server_, BitMask64(self_ip_bit), &results);
- if (packets_read == 0) {
- ASSERT_TRUE(
- api_.WaitUntilReadable(fd_server_, QuicTime::Delta::FromSeconds(5)));
- packets_read = api_.ReadMultiplePackets(fd_server_,
- BitMask64(self_ip_bit), &results);
- ASSERT_GT(packets_read, 0u);
- }
-
- for (size_t i = 0; i < packets_read; ++i) {
- const auto& result = results[i];
- ASSERT_TRUE(result.ok);
- ASSERT_EQ(kPacketSize, result.packet_buffer.buffer_len);
- ASSERT_TRUE(VerifyBufferIsFilledWith(result.packet_buffer.buffer,
- result.packet_buffer.buffer_len,
- ' ' + total_packets_read));
- ASSERT_TRUE(result.packet_info.HasValue(self_ip_bit));
- EXPECT_EQ(Loopback(), (address_family_ == AF_INET)
- ? result.packet_info.self_v4_ip()
- : result.packet_info.self_v6_ip());
- total_packets_read++;
- }
- }
-}
-
-TEST_P(QuicUdpSocketTest, ReadMultiplePacketsSomeTruncated) {
- const QuicUdpPacketInfoBit self_ip_bit =
- (address_family_ == AF_INET) ? QuicUdpPacketInfoBit::V4_SELF_IP
- : QuicUdpPacketInfoBit::V6_SELF_IP;
- const size_t kPacketSize = kDefaultMaxPacketSize;
- const size_t kNumPackets = 90;
- for (size_t i = 0; i < kNumPackets; ++i) {
- memset(client_packet_buffer_, ' ' + i, kPacketSize);
- ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
- SendPacketFromClient(kPacketSize));
- }
-
- const size_t kNumPacketsPerRead = 16;
- size_t total_packets_read = 0; // Including truncated packets.
- while (total_packets_read < kNumPackets) {
- std::unique_ptr<ReadBuffers[]> read_buffers =
- std::make_unique<ReadBuffers[]>(kNumPacketsPerRead);
- QuicUdpSocketApi::ReadPacketResults results(kNumPacketsPerRead);
- // Use small packet buffer for all even-numbered packets and expect them to
- // be truncated.
- auto is_truncated = [total_packets_read](size_t i) {
- return ((total_packets_read + i) % 2) == 1;
- };
-
- for (size_t i = 0; i < kNumPacketsPerRead; ++i) {
- results[i].packet_buffer.buffer = read_buffers[i].packet_buffer;
- results[i].packet_buffer.buffer_len =
- is_truncated(i) ? kPacketSize - 1
- : sizeof(read_buffers[i].packet_buffer);
-
- results[i].control_buffer.buffer = read_buffers[i].control_buffer;
- results[i].control_buffer.buffer_len =
- sizeof(read_buffers[i].control_buffer);
- }
- size_t packets_read =
- api_.ReadMultiplePackets(fd_server_, BitMask64(self_ip_bit), &results);
- if (packets_read == 0) {
- ASSERT_TRUE(
- api_.WaitUntilReadable(fd_server_, QuicTime::Delta::FromSeconds(5)));
- packets_read = api_.ReadMultiplePackets(fd_server_,
- BitMask64(self_ip_bit), &results);
- ASSERT_GT(packets_read, 0u);
- }
-
- for (size_t i = 0; i < packets_read; ++i) {
- const auto& result = results[i];
- if (is_truncated(i)) {
- ASSERT_FALSE(result.ok);
- } else {
- ASSERT_TRUE(result.ok);
- ASSERT_EQ(kPacketSize, result.packet_buffer.buffer_len);
- ASSERT_TRUE(VerifyBufferIsFilledWith(result.packet_buffer.buffer,
- result.packet_buffer.buffer_len,
- ' ' + total_packets_read));
- ASSERT_TRUE(result.packet_info.HasValue(self_ip_bit));
- EXPECT_EQ(Loopback(), (address_family_ == AF_INET)
- ? result.packet_info.self_v4_ip()
- : result.packet_info.self_v6_ip());
- }
- total_packets_read++;
- }
- }
-}
-
-} // namespace test
-} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.cc b/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.cc
index eeda2159092..fbdcd3eeb8a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.cc
@@ -102,10 +102,10 @@ QuicFrameTypeBitfield GetFrameTypeBitfield(QuicFrameType type) {
case ACK_FREQUENCY_FRAME:
return kAckFrequencyFrameBitfield;
case NUM_FRAME_TYPES:
- QUIC_BUG << "Unexpected frame type";
+ QUIC_BUG(quic_bug_10518_1) << "Unexpected frame type";
return kInvalidFrameBitfield;
}
- QUIC_BUG << "Unexpected frame type";
+ QUIC_BUG(quic_bug_10518_2) << "Unexpected frame type";
return kInvalidFrameBitfield;
}
@@ -140,8 +140,8 @@ void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* mutable_packet,
const SerializedPacket& packet = *mutable_packet;
QuicPacketNumber packet_number = packet.packet_number;
QuicPacketLength bytes_sent = packet.encrypted_length;
- QUIC_BUG_IF(largest_sent_packet_.IsInitialized() &&
- largest_sent_packet_ >= packet_number)
+ QUIC_BUG_IF(quic_bug_12645_1, largest_sent_packet_.IsInitialized() &&
+ largest_sent_packet_ >= packet_number)
<< "largest_sent_packet_: " << largest_sent_packet_
<< ", packet_number: " << packet_number;
QUICHE_DCHECK_GE(packet_number, least_unacked_ + unacked_packets_.size());
@@ -158,7 +158,7 @@ void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* mutable_packet,
largest_sent_largest_acked_.UpdateMax(packet.largest_acked);
if (!measure_rtt) {
- QUIC_BUG_IF(set_in_flight);
+ QUIC_BUG_IF(quic_bug_12645_2, set_in_flight);
info.state = NOT_CONTRIBUTING_RTT;
}
@@ -289,8 +289,8 @@ bool QuicUnackedPacketMap::IsUnacked(QuicPacketNumber packet_number) const {
void QuicUnackedPacketMap::RemoveFromInFlight(QuicTransmissionInfo* info) {
if (info->in_flight) {
- QUIC_BUG_IF(bytes_in_flight_ < info->bytes_sent);
- QUIC_BUG_IF(packets_in_flight_ == 0);
+ QUIC_BUG_IF(quic_bug_12645_3, bytes_in_flight_ < info->bytes_sent);
+ QUIC_BUG_IF(quic_bug_12645_4, packets_in_flight_ == 0);
bytes_in_flight_ -= info->bytes_sent;
--packets_in_flight_;
@@ -298,11 +298,12 @@ void QuicUnackedPacketMap::RemoveFromInFlight(QuicTransmissionInfo* info) {
GetPacketNumberSpace(info->encryption_level);
if (bytes_in_flight_per_packet_number_space_[packet_number_space] <
info->bytes_sent) {
- QUIC_BUG << "bytes_in_flight: "
- << bytes_in_flight_per_packet_number_space_[packet_number_space]
- << " is smaller than bytes_sent: " << info->bytes_sent
- << " for packet number space: "
- << PacketNumberSpaceToString(packet_number_space);
+ QUIC_BUG(quic_bug_10518_3)
+ << "bytes_in_flight: "
+ << bytes_in_flight_per_packet_number_space_[packet_number_space]
+ << " is smaller than bytes_sent: " << info->bytes_sent
+ << " for packet number space: "
+ << PacketNumberSpaceToString(packet_number_space);
bytes_in_flight_per_packet_number_space_[packet_number_space] = 0;
} else {
bytes_in_flight_per_packet_number_space_[packet_number_space] -=
@@ -560,7 +561,8 @@ PacketNumberSpace QuicUnackedPacketMap::GetPacketNumberSpace(
QuicPacketNumber QuicUnackedPacketMap::GetLargestAckedOfPacketNumberSpace(
PacketNumberSpace packet_number_space) const {
if (packet_number_space >= NUM_PACKET_NUMBER_SPACES) {
- QUIC_BUG << "Invalid packet number space: " << packet_number_space;
+ QUIC_BUG(quic_bug_10518_4)
+ << "Invalid packet number space: " << packet_number_space;
return QuicPacketNumber();
}
return largest_acked_packets_[packet_number_space];
@@ -569,7 +571,8 @@ QuicPacketNumber QuicUnackedPacketMap::GetLargestAckedOfPacketNumberSpace(
QuicTime QuicUnackedPacketMap::GetLastInFlightPacketSentTime(
PacketNumberSpace packet_number_space) const {
if (packet_number_space >= NUM_PACKET_NUMBER_SPACES) {
- QUIC_BUG << "Invalid packet number space: " << packet_number_space;
+ QUIC_BUG(quic_bug_10518_5)
+ << "Invalid packet number space: " << packet_number_space;
return QuicTime::Zero();
}
return last_inflight_packets_sent_time_[packet_number_space];
@@ -579,7 +582,8 @@ QuicPacketNumber
QuicUnackedPacketMap::GetLargestSentRetransmittableOfPacketNumberSpace(
PacketNumberSpace packet_number_space) const {
if (packet_number_space >= NUM_PACKET_NUMBER_SPACES) {
- QUIC_BUG << "Invalid packet number space: " << packet_number_space;
+ QUIC_BUG(quic_bug_10518_6)
+ << "Invalid packet number space: " << packet_number_space;
return QuicPacketNumber();
}
return largest_sent_retransmittable_packets_[packet_number_space];
@@ -613,12 +617,14 @@ QuicUnackedPacketMap::GetFirstInFlightTransmissionInfoOfSpace(
void QuicUnackedPacketMap::EnableMultiplePacketNumberSpacesSupport() {
if (supports_multiple_packet_number_spaces_) {
- QUIC_BUG << "Multiple packet number spaces has already been enabled";
+ QUIC_BUG(quic_bug_10518_7)
+ << "Multiple packet number spaces has already been enabled";
return;
}
if (largest_sent_packet_.IsInitialized()) {
- QUIC_BUG << "Try to enable multiple packet number spaces support after any "
- "packet has been sent.";
+ QUIC_BUG(quic_bug_10518_8)
+ << "Try to enable multiple packet number spaces support after any "
+ "packet has been sent.";
return;
}
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 7eff759077e..27b74bb9430 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
@@ -7,10 +7,12 @@
#include <algorithm>
#include <cstdint>
#include <cstring>
+#include <limits>
#include <string>
#include "absl/base/macros.h"
#include "absl/base/optimization.h"
+#include "absl/numeric/int128.h"
#include "absl/strings/string_view.h"
#include "quic/core/quic_connection_id.h"
#include "quic/core/quic_constants.h"
@@ -20,7 +22,7 @@
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_prefetch.h"
-#include "quic/platform/api/quic_uint128.h"
+#include "common/platform/api/quiche_logging.h"
#include "common/quiche_endian.h"
namespace quic {
@@ -36,42 +38,43 @@ namespace {
#endif
#ifdef QUIC_UTIL_HAS_UINT128
-QuicUint128 IncrementalHashFast(QuicUint128 uhash, absl::string_view data) {
+absl::uint128 IncrementalHashFast(absl::uint128 uhash, absl::string_view data) {
// This code ends up faster than the naive implementation for 2 reasons:
- // 1. QuicUint128 is sufficiently complicated that the compiler
+ // 1. absl::uint128 is sufficiently complicated that the compiler
// cannot transform the multiplication by kPrime into a shift-multiply-add;
// it has go through all of the instructions for a 128-bit multiply.
// 2. Because there are so fewer instructions (around 13), the hot loop fits
// nicely in the instruction queue of many Intel CPUs.
// kPrime = 309485009821345068724781371
- static const QuicUint128 kPrime =
- (static_cast<QuicUint128>(16777216) << 64) + 315;
- auto hi = QuicUint128High64(uhash);
- auto lo = QuicUint128Low64(uhash);
- QuicUint128 xhash = (static_cast<QuicUint128>(hi) << 64) + lo;
+ static const absl::uint128 kPrime =
+ (static_cast<absl::uint128>(16777216) << 64) + 315;
+ auto hi = absl::Uint128High64(uhash);
+ auto lo = absl::Uint128Low64(uhash);
+ absl::uint128 xhash = (static_cast<absl::uint128>(hi) << 64) + lo;
const uint8_t* octets = reinterpret_cast<const uint8_t*>(data.data());
for (size_t i = 0; i < data.length(); ++i) {
xhash = (xhash ^ static_cast<uint32_t>(octets[i])) * kPrime;
}
- return MakeQuicUint128(QuicUint128High64(xhash), QuicUint128Low64(xhash));
+ return absl::MakeUint128(absl::Uint128High64(xhash),
+ absl::Uint128Low64(xhash));
}
#endif
#ifndef QUIC_UTIL_HAS_UINT128
// Slow implementation of IncrementalHash. In practice, only used by Chromium.
-QuicUint128 IncrementalHashSlow(QuicUint128 hash, absl::string_view data) {
+absl::uint128 IncrementalHashSlow(absl::uint128 hash, absl::string_view data) {
// kPrime = 309485009821345068724781371
- static const QuicUint128 kPrime = MakeQuicUint128(16777216, 315);
+ static const absl::uint128 kPrime = absl::MakeUint128(16777216, 315);
const uint8_t* octets = reinterpret_cast<const uint8_t*>(data.data());
for (size_t i = 0; i < data.length(); ++i) {
- hash = hash ^ MakeQuicUint128(0, octets[i]);
+ hash = hash ^ absl::MakeUint128(0, octets[i]);
hash = hash * kPrime;
}
return hash;
}
#endif
-QuicUint128 IncrementalHash(QuicUint128 hash, absl::string_view data) {
+absl::uint128 IncrementalHash(absl::uint128 hash, absl::string_view data) {
#ifdef QUIC_UTIL_HAS_UINT128
return IncrementalHashFast(hash, data);
#else
@@ -99,27 +102,27 @@ uint64_t QuicUtils::FNV1a_64_Hash(absl::string_view data) {
}
// static
-QuicUint128 QuicUtils::FNV1a_128_Hash(absl::string_view data) {
+absl::uint128 QuicUtils::FNV1a_128_Hash(absl::string_view data) {
return FNV1a_128_Hash_Three(data, absl::string_view(), absl::string_view());
}
// static
-QuicUint128 QuicUtils::FNV1a_128_Hash_Two(absl::string_view data1,
- absl::string_view data2) {
+absl::uint128 QuicUtils::FNV1a_128_Hash_Two(absl::string_view data1,
+ absl::string_view data2) {
return FNV1a_128_Hash_Three(data1, data2, absl::string_view());
}
// static
-QuicUint128 QuicUtils::FNV1a_128_Hash_Three(absl::string_view data1,
- absl::string_view data2,
- absl::string_view data3) {
+absl::uint128 QuicUtils::FNV1a_128_Hash_Three(absl::string_view data1,
+ absl::string_view data2,
+ absl::string_view data3) {
// The two constants are defined as part of the hash algorithm.
// see http://www.isthe.com/chongo/tech/comp/fnv/
// kOffset = 144066263297769815596495629667062367629
- const QuicUint128 kOffset = MakeQuicUint128(UINT64_C(7809847782465536322),
- UINT64_C(7113472399480571277));
+ const absl::uint128 kOffset = absl::MakeUint128(
+ UINT64_C(7809847782465536322), UINT64_C(7113472399480571277));
- QuicUint128 hash = IncrementalHash(kOffset, data1);
+ absl::uint128 hash = IncrementalHash(kOffset, data1);
if (data2.empty()) {
return hash;
}
@@ -132,9 +135,9 @@ QuicUint128 QuicUtils::FNV1a_128_Hash_Three(absl::string_view data1,
}
// static
-void QuicUtils::SerializeUint128Short(QuicUint128 v, uint8_t* out) {
- const uint64_t lo = QuicUint128Low64(v);
- const uint64_t hi = QuicUint128High64(v);
+void QuicUtils::SerializeUint128Short(absl::uint128 v, uint8_t* out) {
+ const uint64_t lo = absl::Uint128Low64(v);
+ const uint64_t hi = absl::Uint128High64(v);
// This assumes that the system is little-endian.
memcpy(out, &lo, sizeof(lo));
memcpy(out + sizeof(lo), &hi, sizeof(hi) / 2);
@@ -280,7 +283,8 @@ void QuicUtils::CopyToBuffer(const struct iovec* iov,
src = static_cast<char*>(iov[iovnum].iov_base);
copy_len = std::min(buffer_length, iov[iovnum].iov_len);
}
- QUIC_BUG_IF(buffer_length > 0) << "Failed to copy entire length to buffer.";
+ QUIC_BUG_IF(quic_bug_10839_1, buffer_length > 0)
+ << "Failed to copy entire length to buffer.";
}
// static
@@ -356,7 +360,8 @@ SentPacketState QuicUtils::RetransmissionTypeToPacketState(
case ALL_INITIAL_RETRANSMISSION:
return UNACKABLE;
default:
- QUIC_BUG << retransmission_type << " is not a retransmission_type";
+ QUIC_BUG(quic_bug_10839_2)
+ << retransmission_type << " is not a retransmission_type";
return UNACKABLE;
}
}
@@ -381,7 +386,7 @@ QuicStreamId QuicUtils::GetInvalidStreamId(QuicTransportVersion version) {
// static
QuicStreamId QuicUtils::GetCryptoStreamId(QuicTransportVersion version) {
- QUIC_BUG_IF(QuicVersionUsesCryptoFrames(version))
+ QUIC_BUG_IF(quic_bug_12982_1, QuicVersionUsesCryptoFrames(version))
<< "CRYPTO data aren't in stream frames; they have no stream ID.";
return QuicVersionUsesCryptoFrames(version) ? GetInvalidStreamId(version) : 1;
}
@@ -531,7 +536,7 @@ QuicConnectionId QuicUtils::CreateReplacementConnectionId(
expected_connection_id_length);
}
char new_connection_id_data[255] = {};
- const QuicUint128 connection_id_hash128 = FNV1a_128_Hash(
+ const absl::uint128 connection_id_hash128 = FNV1a_128_Hash(
absl::string_view(connection_id.data(), connection_id.length()));
static_assert(sizeof(connection_id_hash64) + sizeof(connection_id_hash128) <=
sizeof(new_connection_id_data),
@@ -625,10 +630,15 @@ bool QuicUtils::IsConnectionIdValidForVersion(
transport_version);
}
-QuicUint128 QuicUtils::GenerateStatelessResetToken(
+StatelessResetToken QuicUtils::GenerateStatelessResetToken(
QuicConnectionId connection_id) {
- return FNV1a_128_Hash(
+ static_assert(sizeof(absl::uint128) == sizeof(StatelessResetToken),
+ "bad size");
+ static_assert(alignof(absl::uint128) >= alignof(StatelessResetToken),
+ "bad alignment");
+ absl::uint128 hash = FNV1a_128_Hash(
absl::string_view(connection_id.data(), connection_id.length()));
+ return *reinterpret_cast<StatelessResetToken*>(&hash);
}
// static
@@ -648,8 +658,9 @@ PacketNumberSpace QuicUtils::GetPacketNumberSpace(
case ENCRYPTION_FORWARD_SECURE:
return APPLICATION_DATA;
default:
- QUIC_BUG << "Try to get packet number space of encryption level: "
- << encryption_level;
+ QUIC_BUG(quic_bug_10839_3)
+ << "Try to get packet number space of encryption level: "
+ << encryption_level;
return NUM_PACKET_NUMBER_SPACES;
}
}
@@ -683,5 +694,13 @@ bool QuicUtils::IsProbingFrame(QuicFrameType type) {
}
}
+bool IsValidWebTransportSessionId(WebTransportSessionId id,
+ ParsedQuicVersion version) {
+ QUICHE_DCHECK(version.UsesHttp3());
+ return (id <= std::numeric_limits<QuicStreamId>::max()) &&
+ QuicUtils::IsBidirectionalStreamId(id, version) &&
+ QuicUtils::IsClientInitiatedStreamId(version.transport_version, id);
+}
+
#undef RETURN_STRING_LITERAL // undef for jumbo builds
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_utils.h b/chromium/net/third_party/quiche/src/quic/core/quic_utils.h
index 91751175a3b..0b089b4bad6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_utils.h
@@ -11,6 +11,7 @@
#include <string>
#include <type_traits>
+#include "absl/numeric/int128.h"
#include "absl/strings/string_view.h"
#include "quic/core/crypto/quic_random.h"
#include "quic/core/frames/quic_frame.h"
@@ -21,7 +22,6 @@
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_iovec.h"
#include "quic/platform/api/quic_socket_address.h"
-#include "quic/platform/api/quic_uint128.h"
namespace quic {
@@ -35,22 +35,22 @@ class QUIC_EXPORT_PRIVATE QuicUtils {
// Returns the 128 bit FNV1a hash of the data. See
// http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
- static QuicUint128 FNV1a_128_Hash(absl::string_view data);
+ static absl::uint128 FNV1a_128_Hash(absl::string_view data);
// Returns the 128 bit FNV1a hash of the two sequences of data. See
// http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
- static QuicUint128 FNV1a_128_Hash_Two(absl::string_view data1,
- absl::string_view data2);
+ static absl::uint128 FNV1a_128_Hash_Two(absl::string_view data1,
+ absl::string_view data2);
// Returns the 128 bit FNV1a hash of the three sequences of data. See
// http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
- static QuicUint128 FNV1a_128_Hash_Three(absl::string_view data1,
- absl::string_view data2,
- absl::string_view data3);
+ static absl::uint128 FNV1a_128_Hash_Three(absl::string_view data1,
+ absl::string_view data2,
+ absl::string_view data3);
// SerializeUint128 writes the first 96 bits of |v| in little-endian form
// to |out|.
- static void SerializeUint128Short(QuicUint128 v, uint8_t* out);
+ static void SerializeUint128Short(absl::uint128 v, uint8_t* out);
// Returns AddressChangeType as a string.
static std::string AddressChangeTypeToString(AddressChangeType type);
@@ -219,7 +219,7 @@ class QUIC_EXPORT_PRIVATE QuicUtils {
static QuicConnectionId CreateZeroConnectionId(QuicTransportVersion version);
// Generates a 128bit stateless reset token based on a connection ID.
- static QuicUint128 GenerateStatelessResetToken(
+ static StatelessResetToken GenerateStatelessResetToken(
QuicConnectionId connection_id);
// Determines packet number space from |encryption_level|.
@@ -239,6 +239,11 @@ class QUIC_EXPORT_PRIVATE QuicUtils {
static bool IsProbingFrame(QuicFrameType type);
};
+// Returns true if the specific ID is a valid WebTransport session ID that our
+// implementation can process.
+bool IsValidWebTransportSessionId(WebTransportSessionId id,
+ ParsedQuicVersion transport_version);
+
template <typename Mask>
class QUIC_EXPORT_PRIVATE BitMask {
public:
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_utils_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_utils_test.cc
index a5249d7cf48..dc1165242f5 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_utils_test.cc
@@ -7,6 +7,7 @@
#include <string>
#include "absl/base/macros.h"
+#include "absl/numeric/int128.h"
#include "absl/strings/string_view.h"
#include "quic/core/crypto/crypto_protocol.h"
#include "quic/core/quic_connection_id.h"
@@ -79,17 +80,17 @@ TEST_F(QuicUtilsTest, DetermineAddressChangeType) {
QuicUtils::DetermineAddressChangeType(old_address, new_address));
}
-QuicUint128 IncrementalHashReference(const void* data, size_t len) {
+absl::uint128 IncrementalHashReference(const void* data, size_t len) {
// The two constants are defined as part of the hash algorithm.
// see http://www.isthe.com/chongo/tech/comp/fnv/
// hash = 144066263297769815596495629667062367629
- QuicUint128 hash = MakeQuicUint128(UINT64_C(7809847782465536322),
- UINT64_C(7113472399480571277));
+ absl::uint128 hash = absl::MakeUint128(UINT64_C(7809847782465536322),
+ UINT64_C(7113472399480571277));
// kPrime = 309485009821345068724781371
- const QuicUint128 kPrime = MakeQuicUint128(16777216, 315);
+ const absl::uint128 kPrime = absl::MakeUint128(16777216, 315);
const uint8_t* octets = reinterpret_cast<const uint8_t*>(data);
for (size_t i = 0; i < len; ++i) {
- hash = hash ^ MakeQuicUint128(0, octets[i]);
+ hash = hash ^ absl::MakeUint128(0, octets[i]);
hash = hash * kPrime;
}
return hash;
@@ -311,9 +312,12 @@ TEST_F(QuicUtilsTest, StatelessResetToken) {
QuicConnectionId connection_id1a = test::TestConnectionId(1);
QuicConnectionId connection_id1b = test::TestConnectionId(1);
QuicConnectionId connection_id2 = test::TestConnectionId(2);
- QuicUint128 token1a = QuicUtils::GenerateStatelessResetToken(connection_id1a);
- QuicUint128 token1b = QuicUtils::GenerateStatelessResetToken(connection_id1b);
- QuicUint128 token2 = QuicUtils::GenerateStatelessResetToken(connection_id2);
+ StatelessResetToken token1a =
+ QuicUtils::GenerateStatelessResetToken(connection_id1a);
+ StatelessResetToken token1b =
+ QuicUtils::GenerateStatelessResetToken(connection_id1b);
+ StatelessResetToken token2 =
+ QuicUtils::GenerateStatelessResetToken(connection_id2);
EXPECT_EQ(token1a, token1b);
EXPECT_NE(token1a, token2);
}
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 a189e263b94..ab68ddd57d1 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
@@ -59,8 +59,8 @@ void SetVersionFlag(const ParsedQuicVersion& version, bool should_enable) {
} else if (version == ParsedQuicVersion::Q043()) {
SetQuicReloadableFlag(quic_disable_version_q043, disable);
} else {
- QUIC_BUG << "Cannot " << (enable ? "en" : "dis") << "able version "
- << version;
+ QUIC_BUG(quic_bug_10589_1)
+ << "Cannot " << (enable ? "en" : "dis") << "able version " << version;
}
}
@@ -232,9 +232,10 @@ QuicVersionLabel CreateQuicVersionLabel(ParsedQuicVersion parsed_version) {
} else if (parsed_version == ParsedQuicVersion::ReservedForNegotiation()) {
return CreateRandomVersionLabelForNegotiation();
}
- QUIC_BUG << "Unsupported version "
- << QuicVersionToString(parsed_version.transport_version) << " "
- << HandshakeProtocolToString(parsed_version.handshake_protocol);
+ QUIC_BUG(quic_bug_10589_2)
+ << "Unsupported version "
+ << QuicVersionToString(parsed_version.transport_version) << " "
+ << HandshakeProtocolToString(parsed_version.handshake_protocol);
return 0;
}
@@ -255,7 +256,8 @@ ParsedQuicVersionVector AllSupportedVersionsWithQuicCrypto() {
versions.push_back(version);
}
}
- QUIC_BUG_IF(versions.empty()) << "No version with QUIC crypto found.";
+ QUIC_BUG_IF(quic_bug_10589_3, versions.empty())
+ << "No version with QUIC crypto found.";
return versions;
}
@@ -266,7 +268,8 @@ ParsedQuicVersionVector CurrentSupportedVersionsWithQuicCrypto() {
versions.push_back(version);
}
}
- QUIC_BUG_IF(versions.empty()) << "No version with QUIC crypto found.";
+ QUIC_BUG_IF(quic_bug_10589_4, versions.empty())
+ << "No version with QUIC crypto found.";
return versions;
}
@@ -277,7 +280,8 @@ ParsedQuicVersionVector AllSupportedVersionsWithTls() {
versions.push_back(version);
}
}
- QUIC_BUG_IF(versions.empty()) << "No version with TLS handshake found.";
+ QUIC_BUG_IF(quic_bug_10589_5, versions.empty())
+ << "No version with TLS handshake found.";
return versions;
}
@@ -288,7 +292,8 @@ ParsedQuicVersionVector CurrentSupportedVersionsWithTls() {
versions.push_back(version);
}
}
- QUIC_BUG_IF(versions.empty()) << "No version with TLS handshake found.";
+ QUIC_BUG_IF(quic_bug_10589_6, versions.empty())
+ << "No version with TLS handshake found.";
return versions;
}
@@ -414,7 +419,8 @@ ParsedQuicVersionVector FilterSupportedVersions(
filtered_versions.push_back(version);
}
} else {
- QUIC_BUG << "QUIC version " << version << " has no flag protection";
+ QUIC_BUG(quic_bug_10589_7)
+ << "QUIC version " << version << " has no flag protection";
filtered_versions.push_back(version);
}
}
@@ -593,7 +599,7 @@ std::string AlpnForVersion(ParsedQuicVersion parsed_version) {
void QuicVersionInitializeSupportForIetfDraft() {
// Enable necessary flags.
- SetQuicRestartFlag(quic_enable_zero_rtt_for_tls_v2, true);
+ 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/tls_chlo_extractor.cc b/chromium/net/third_party/quiche/src/quic/core/tls_chlo_extractor.cc
index ca9eb5b9865..ae85b07c251 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
@@ -129,8 +129,8 @@ bool TlsChloExtractor::OnUnauthenticatedPublicHeader(
bool TlsChloExtractor::OnProtocolVersionMismatch(ParsedQuicVersion version) {
// This should never be called because we already check versions in
// IngestPacket.
- QUIC_BUG << "Unexpected version mismatch, expected " << framer_->version()
- << ", got " << version;
+ QUIC_BUG(quic_bug_10855_1) << "Unexpected version mismatch, expected "
+ << framer_->version() << ", got " << version;
return false;
}
@@ -156,7 +156,7 @@ bool TlsChloExtractor::OnCryptoFrame(const QuicCryptoFrame& frame) {
if (frame.level != ENCRYPTION_INITIAL) {
// Since we drop non-INITIAL packets in OnUnauthenticatedPublicHeader,
// we should never receive any CRYPTO frames at other encryption levels.
- QUIC_BUG << "Parsed bad-level CRYPTO frame " << frame;
+ QUIC_BUG(quic_bug_10855_2) << "Parsed bad-level CRYPTO frame " << frame;
return false;
}
// parsed_crypto_frame_in_this_packet_ is checked in IngestPacket to allow
@@ -242,7 +242,7 @@ void TlsChloExtractor::HandleUnexpectedCallback(
const std::string& callback_name) {
std::string error_details =
absl::StrCat("Unexpected callback ", callback_name);
- QUIC_BUG << error_details;
+ QUIC_BUG(quic_bug_10855_3) << error_details;
HandleUnrecoverableError(error_details);
}
@@ -311,8 +311,8 @@ void TlsChloExtractor::HandleParsedChlo(const SSL_CLIENT_HELLO* client_hello) {
} else if (state_ == State::kParsedPartialChloFragment) {
state_ = State::kParsedFullMultiPacketChlo;
} else {
- QUIC_BUG << "Unexpected state on successful parse "
- << StateToString(state_);
+ QUIC_BUG(quic_bug_10855_4)
+ << "Unexpected state on successful parse " << StateToString(state_);
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_chlo_extractor.h b/chromium/net/third_party/quiche/src/quic/core/tls_chlo_extractor.h
index f7392a5817f..c6d04552f43 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_chlo_extractor.h
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_chlo_extractor.h
@@ -13,6 +13,7 @@
#include "quic/core/quic_framer.h"
#include "quic/core/quic_packets.h"
#include "quic/core/quic_stream_sequencer.h"
+#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_export.h"
namespace quic {
@@ -156,7 +157,8 @@ class QUIC_NO_EXPORT TlsChloExtractor
return true;
}
void OnPacketComplete() override {}
- bool IsValidStatelessResetToken(QuicUint128 /*token*/) const override {
+ bool IsValidStatelessResetToken(
+ const StatelessResetToken& /*token*/) const override {
return true;
}
void OnAuthenticatedIetfStatelessResetPacket(
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 448136f8013..f8e321663ca 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
@@ -58,7 +58,7 @@ bool TlsClientHandshaker::CryptoConnect() {
// TODO(b/154162689) add PSK support to QUIC+TLS.
std::string error_details =
"QUIC client pre-shared keys not yet supported with TLS";
- QUIC_BUG << error_details;
+ QUIC_BUG(quic_bug_10576_1) << error_details;
CloseConnection(QUIC_HANDSHAKE_FAILED, error_details);
return false;
}
@@ -116,7 +116,8 @@ bool TlsClientHandshaker::PrepareZeroRttConfig(
handshaker_delegate()->ProcessTransportParameters(
*(cached_state->transport_params),
/*is_resumption = */ true, &error_details) != QUIC_NO_ERROR) {
- QUIC_BUG << "Unable to parse cached transport parameters.";
+ QUIC_BUG(quic_bug_10576_2)
+ << "Unable to parse cached transport parameters.";
CloseConnection(QUIC_HANDSHAKE_FAILED,
"Client failed to parse cached Transport Parameters.");
return false;
@@ -130,7 +131,7 @@ bool TlsClientHandshaker::PrepareZeroRttConfig(
if (!cached_state->application_state ||
!session()->ResumeApplicationState(
cached_state->application_state.get())) {
- QUIC_BUG << "Unable to parse cached application state.";
+ QUIC_BUG(quic_bug_10576_3) << "Unable to parse cached application state.";
CloseConnection(QUIC_HANDSHAKE_FAILED,
"Client failed to parse cached application state.");
return false;
@@ -150,11 +151,11 @@ bool TlsClientHandshaker::SetAlpn() {
return true;
}
- QUIC_BUG << "ALPN missing";
+ QUIC_BUG(quic_bug_10576_4) << "ALPN missing";
return false;
}
if (!std::all_of(alpns.begin(), alpns.end(), IsValidAlpn)) {
- QUIC_BUG << "ALPN too long";
+ QUIC_BUG(quic_bug_10576_5) << "ALPN too long";
return false;
}
@@ -170,19 +171,24 @@ bool TlsClientHandshaker::SetAlpn() {
success =
success && (SSL_set_alpn_protos(ssl(), alpn, alpn_writer.length()) == 0);
if (!success) {
- QUIC_BUG << "Failed to set ALPN: "
- << quiche::QuicheTextUtils::HexDump(absl::string_view(
- alpn_writer.data(), alpn_writer.length()));
+ QUIC_BUG(quic_bug_10576_6)
+ << "Failed to set ALPN: "
+ << quiche::QuicheTextUtils::HexDump(
+ absl::string_view(alpn_writer.data(), alpn_writer.length()));
return false;
}
- // Enable ALPS.
+ // 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 << "Failed to enable ALPS.";
+ QUIC_BUG(quic_bug_10576_7) << "Failed to enable ALPS.";
return false;
}
}
@@ -281,12 +287,12 @@ int TlsClientHandshaker::num_sent_client_hellos() const {
}
bool TlsClientHandshaker::IsResumption() const {
- QUIC_BUG_IF(!one_rtt_keys_available());
+ QUIC_BUG_IF(quic_bug_12736_1, !one_rtt_keys_available());
return SSL_session_reused(ssl()) == 1;
}
bool TlsClientHandshaker::EarlyDataAccepted() const {
- QUIC_BUG_IF(!one_rtt_keys_available());
+ QUIC_BUG_IF(quic_bug_12736_2, !one_rtt_keys_available());
return SSL_early_data_accepted(ssl()) == 1;
}
@@ -295,7 +301,7 @@ ssl_early_data_reason_t TlsClientHandshaker::EarlyDataReason() const {
}
bool TlsClientHandshaker::ReceivedInchoateReject() const {
- QUIC_BUG_IF(!one_rtt_keys_available());
+ QUIC_BUG_IF(quic_bug_12736_3, !one_rtt_keys_available());
// REJ messages are a QUIC crypto feature, so TLS always returns false.
return false;
}
@@ -440,25 +446,23 @@ void TlsClientHandshaker::OnProofVerifyDetailsAvailable(
}
void TlsClientHandshaker::FinishHandshake() {
- // Fill crypto_negotiated_params_:
- const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
- if (cipher) {
- crypto_negotiated_params_->cipher_suite = SSL_CIPHER_get_value(cipher);
- }
- crypto_negotiated_params_->key_exchange_group = SSL_get_curve_id(ssl());
- crypto_negotiated_params_->peer_signature_algorithm =
- SSL_get_peer_signature_algorithm(ssl());
- if (SSL_in_early_data(ssl())) {
- // SSL_do_handshake returns after sending the ClientHello if the session is
- // 0-RTT-capable, which means that FinishHandshake will get called twice -
- // the first time after sending the ClientHello, and the second time after
- // the handshake is complete. If we're in the first time FinishHandshake is
- // called, we can't do any end-of-handshake processing.
-
- // If we're attempting a 0-RTT handshake, then we need to let the transport
- // and application know what state to apply to early data.
- PrepareZeroRttConfig(cached_state_.get());
- return;
+ FillNegotiatedParams();
+
+ if (retry_handshake_on_early_data_) {
+ QUICHE_CHECK(!SSL_in_early_data(ssl()));
+ } else {
+ if (SSL_in_early_data(ssl())) {
+ // SSL_do_handshake returns after sending the ClientHello if the session
+ // is 0-RTT-capable, which means that FinishHandshake will get called
+ // twice - the first time after sending the ClientHello, and the second
+ // time after the handshake is complete. If we're in the first time
+ // FinishHandshake is called, we can't do any end-of-handshake processing.
+
+ // If we're attempting a 0-RTT handshake, then we need to let the
+ // transport and application know what state to apply to early data.
+ PrepareZeroRttConfig(cached_state_.get());
+ return;
+ }
}
QUIC_LOG(INFO) << "Client: handshake finished";
@@ -505,6 +509,8 @@ void TlsClientHandshaker::FinishHandshake() {
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()));
@@ -517,6 +523,30 @@ void TlsClientHandshaker::FinishHandshake() {
handshaker_delegate()->OnTlsHandshakeComplete();
}
+void TlsClientHandshaker::OnEnterEarlyData() {
+ QUICHE_DCHECK(retry_handshake_on_early_data_);
+ QUICHE_DCHECK(SSL_in_early_data(ssl()));
+
+ // TODO(wub): It might be unnecessary to FillNegotiatedParams() at this time,
+ // because we fill it again when handshake completes.
+ FillNegotiatedParams();
+
+ // If we're attempting a 0-RTT handshake, then we need to let the transport
+ // and application know what state to apply to early data.
+ PrepareZeroRttConfig(cached_state_.get());
+}
+
+void TlsClientHandshaker::FillNegotiatedParams() {
+ const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
+ if (cipher) {
+ crypto_negotiated_params_->cipher_suite =
+ SSL_CIPHER_get_protocol_id(cipher);
+ }
+ crypto_negotiated_params_->key_exchange_group = SSL_get_curve_id(ssl());
+ crypto_negotiated_params_->peer_signature_algorithm =
+ SSL_get_peer_signature_algorithm(ssl());
+}
+
void TlsClientHandshaker::ProcessPostHandshakeMessage() {
int rv = SSL_process_quic_post_handshake(ssl());
if (rv != 1) {
@@ -546,7 +576,7 @@ void TlsClientHandshaker::HandleZeroRttReject() {
void TlsClientHandshaker::InsertSession(bssl::UniquePtr<SSL_SESSION> session) {
if (!received_transport_params_) {
- QUIC_BUG << "Transport parameters isn't received";
+ QUIC_BUG(quic_bug_10576_8) << "Transport parameters isn't received";
return;
}
if (session_cache_ == nullptr) {
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 42d587fdbcc..8fb6da69d2c 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
@@ -90,6 +90,8 @@ class QUIC_EXPORT_PRIVATE TlsClientHandshaker
}
void FinishHandshake() override;
+ void OnEnterEarlyData() override;
+ void FillNegotiatedParams();
void ProcessPostHandshakeMessage() override;
bool ShouldCloseConnectionOnUnexpectedError(int ssl_error) override;
QuicAsyncStatus VerifyCertChain(
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 19fdab5db04..e498acb9a43 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
@@ -178,7 +178,6 @@ class TlsClientHandshakerTest : public QuicTestWithParam<ParsedQuicVersion> {
server_id_(kServerHostname, kServerPort, false),
server_compressed_certs_cache_(
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {
- SetQuicRestartFlag(quic_enable_zero_rtt_for_tls_v2, true);
crypto_config_ = std::make_unique<QuicCryptoClientConfig>(
std::make_unique<TestProofVerifier>(),
std::make_unique<test::SimpleSessionCache>());
@@ -424,6 +423,62 @@ TEST_P(TlsClientHandshakerTest, ZeroRttResumption) {
EXPECT_EQ(stream()->EarlyDataReason(), ssl_early_data_accepted);
}
+// Regression test for b/186438140.
+TEST_P(TlsClientHandshakerTest, ZeroRttResumptionWithAyncProofVerifier) {
+ // Finish establishing the first connection, so the second connection can
+ // resume.
+ CompleteCryptoHandshake();
+
+ EXPECT_EQ(PROTOCOL_TLS1_3, stream()->handshake_protocol());
+ EXPECT_TRUE(stream()->encryption_established());
+ EXPECT_TRUE(stream()->one_rtt_keys_available());
+ EXPECT_FALSE(stream()->IsResumption());
+
+ // Create a second connection.
+ CreateConnection();
+ InitializeFakeServer();
+ EXPECT_CALL(*session_, OnConfigNegotiated());
+ EXPECT_CALL(*connection_, SendCryptoData(_, _, _))
+ .Times(testing::AnyNumber());
+ // Enable TestProofVerifier to capture the call to VerifyCertChain and run it
+ // asynchronously.
+ TestProofVerifier* proof_verifier =
+ static_cast<TestProofVerifier*>(crypto_config_->proof_verifier());
+ proof_verifier->Activate();
+ // Start the second handshake.
+ stream()->CryptoConnect();
+
+ ASSERT_EQ(proof_verifier->NumPendingCallbacks(), 1u);
+
+ // Advance the handshake with the server. Since cert verification has not
+ // finished yet, client cannot derive HANDSHAKE and 1-RTT keys.
+ crypto_test_utils::AdvanceHandshake(connection_, stream(), 0,
+ server_connection_, server_stream(), 0);
+
+ EXPECT_FALSE(stream()->one_rtt_keys_available());
+ EXPECT_FALSE(server_stream()->one_rtt_keys_available());
+
+ // Finish cert verification after receiving packets from server.
+ proof_verifier->InvokePendingCallback(0);
+
+ QuicFramer* framer = QuicConnectionPeer::GetFramer(connection_);
+ if (!GetQuicReloadableFlag(quic_tls_retry_handshake_on_early_data)) {
+ // Client does not have HANDSHAKE key due to b/186438140.
+ EXPECT_EQ(nullptr,
+ QuicFramerPeer::GetEncrypter(framer, ENCRYPTION_HANDSHAKE));
+ return;
+ }
+
+ // Verify client has derived HANDSHAKE key.
+ EXPECT_NE(nullptr,
+ QuicFramerPeer::GetEncrypter(framer, ENCRYPTION_HANDSHAKE));
+
+ // Ideally, we should also verify that the process_undecryptable_packets_alarm
+ // is set and processing the undecryptable packets can advance the handshake
+ // to completion. Unfortunately, the test facilities used in this test does
+ // not support queuing and processing undecryptable packets.
+}
+
TEST_P(TlsClientHandshakerTest, ZeroRttRejection) {
// Finish establishing the first connection:
CompleteCryptoHandshake();
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 133c85c4a27..bc8e0b48d4d 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
@@ -12,9 +12,12 @@
#include "quic/core/quic_crypto_stream.h"
#include "quic/core/tls_client_handshaker.h"
#include "quic/platform/api/quic_bug_tracker.h"
+#include "quic/platform/api/quic_stack_trace.h"
namespace quic {
+#define ENDPOINT (SSL_is_server(ssl()) ? "TlsServer: " : "TlsClient: ")
+
TlsHandshaker::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl(
TlsHandshaker* parent)
: parent_(parent) {}
@@ -93,8 +96,38 @@ void TlsHandshaker::AdvanceHandshake() {
return;
}
- QUIC_VLOG(1) << "TlsHandshaker: continuing handshake";
+ QUIC_VLOG(1) << ENDPOINT << "Continuing handshake";
int rv = SSL_do_handshake(ssl());
+
+ // If SSL_do_handshake return success(1) and we are in early data, it is
+ // possible that we have provided ServerHello to BoringSSL but it hasn't been
+ // processed. Retry SSL_do_handshake once will advance the handshake more in
+ // 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())) {
+ OnEnterEarlyData();
+ rv = SSL_do_handshake(ssl());
+ QUIC_VLOG(1) << ENDPOINT
+ << "SSL_do_handshake returned when entering early data. After "
+ << "retry, rv=" << rv
+ << ", SSL_in_early_data=" << SSL_in_early_data(ssl());
+ // The retry should either
+ // - Return <= 0 if the handshake is still pending, likely still in early
+ // data.
+ // - Return 1 if the handshake has _actually_ finished. i.e.
+ // SSL_in_early_data should be false.
+ //
+ // In either case, it should not both return 1 and stay in early data.
+ if (rv == 1 && SSL_in_early_data(ssl()) && !is_connection_closed_) {
+ QUIC_BUG(quic_handshaker_stay_in_early_data)
+ << "The original and the retry of SSL_do_handshake both returned "
+ "success and in early data";
+ CloseConnection(QUIC_HANDSHAKE_FAILED,
+ "TLS handshake failed: Still in early data after retry");
+ return;
+ }
+ }
+
if (rv == 1) {
FinishHandshake();
return;
@@ -200,7 +233,7 @@ enum ssl_verify_result_t TlsHandshaker::VerifyCert(uint8_t* out_alert) {
void TlsHandshaker::SetWriteSecret(EncryptionLevel level,
const SSL_CIPHER* cipher,
const std::vector<uint8_t>& write_secret) {
- QUIC_DVLOG(1) << "SetWriteSecret level=" << level;
+ QUIC_DVLOG(1) << ENDPOINT << "SetWriteSecret level=" << level;
std::unique_ptr<QuicEncrypter> encrypter =
QuicEncrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher));
const EVP_MD* prf = Prf(cipher);
@@ -223,7 +256,7 @@ void TlsHandshaker::SetWriteSecret(EncryptionLevel level,
bool TlsHandshaker::SetReadSecret(EncryptionLevel level,
const SSL_CIPHER* cipher,
const std::vector<uint8_t>& read_secret) {
- QUIC_DVLOG(1) << "SetReadSecret level=" << level;
+ QUIC_DVLOG(1) << ENDPOINT << "SetReadSecret level=" << level;
std::unique_ptr<QuicDecrypter> decrypter =
QuicDecrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher));
const EVP_MD* prf = Prf(cipher);
@@ -251,7 +284,7 @@ TlsHandshaker::AdvanceKeysAndCreateCurrentOneRttDecrypter() {
one_rtt_read_header_protection_key_.empty() ||
one_rtt_write_header_protection_key_.empty()) {
std::string error_details = "1-RTT secret(s) not set yet.";
- QUIC_BUG << error_details;
+ QUIC_BUG(quic_bug_10312_1) << error_details;
CloseConnection(QUIC_INTERNAL_ERROR, error_details);
return nullptr;
}
@@ -276,7 +309,7 @@ std::unique_ptr<QuicEncrypter> TlsHandshaker::CreateCurrentOneRttEncrypter() {
if (latest_write_secret_.empty() ||
one_rtt_write_header_protection_key_.empty()) {
std::string error_details = "1-RTT write secret not set yet.";
- QUIC_BUG << error_details;
+ QUIC_BUG(quic_bug_10312_2) << error_details;
CloseConnection(QUIC_INTERNAL_ERROR, error_details);
return nullptr;
}
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 4f8bf47d20f..6bf48b548c4 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
@@ -73,8 +73,20 @@ class QUIC_EXPORT_PRIVATE TlsHandshaker : public TlsConnection::Delegate,
// finished. Note that due to 0-RTT, the handshake may "finish" twice;
// |SSL_in_early_data| can be used to determine whether the handshake is truly
// done.
+ // TODO(wub): When --quic_tls_retry_handshake_on_early_data is true, this
+ // function will only be called once when the handshake actually finishes.
+ // Update comment when deprecating the flag.
virtual void FinishHandshake() = 0;
+ // Called when |SSL_do_handshake| returns 1 and the connection is in early
+ // data. In that case, |AdvanceHandshake| will call |OnEnterEarlyData| and
+ // retry |SSL_do_handshake| once.
+ virtual void OnEnterEarlyData() {
+ // By default, do nothing but check the preconditions.
+ QUICHE_DCHECK(retry_handshake_on_early_data_);
+ QUICHE_DCHECK(SSL_in_early_data(ssl()));
+ }
+
// Called when a handshake message is received after the handshake is
// complete.
virtual void ProcessPostHandshakeMessage() = 0;
@@ -155,6 +167,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 retry_handshake_on_early_data_ =
+ GetQuicReloadableFlag(quic_tls_retry_handshake_on_early_data);
+
private:
// ProofVerifierCallbackImpl handles the result of an asynchronous certificate
// verification operation.
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 81c7559489b..b628db1744a 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
@@ -21,8 +21,17 @@
#include "quic/platform/api/quic_flags.h"
#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 { \
+ const int64_t latency_in_us = (latency).ToMicroseconds(); \
+ QUIC_DVLOG(1) << "Recording " stat_name ": " << latency_in_us; \
+ QUIC_SERVER_HISTOGRAM_COUNTS(stat_name, latency_in_us, 1, 10000000, 50, \
+ comment); \
+ } while (0)
+
namespace quic {
TlsServerHandshaker::DefaultProofSourceHandle::DefaultProofSourceHandle(
@@ -55,7 +64,8 @@ TlsServerHandshaker::DefaultProofSourceHandle::SelectCertificate(
const std::vector<uint8_t>& /*quic_transport_params*/,
const absl::optional<std::vector<uint8_t>>& /*early_data_context*/) {
if (!handshaker_ || !proof_source_) {
- QUIC_BUG << "SelectCertificate called on a detached handle";
+ QUIC_BUG(quic_bug_10341_1)
+ << "SelectCertificate called on a detached handle";
return QUIC_FAILURE;
}
@@ -65,7 +75,7 @@ TlsServerHandshaker::DefaultProofSourceHandle::SelectCertificate(
handshaker_->OnSelectCertificateDone(
/*ok=*/true, /*is_sync=*/true, chain.get());
if (!handshaker_->select_cert_status().has_value()) {
- QUIC_BUG
+ QUIC_BUG(quic_bug_12423_1)
<< "select_cert_status() has no value after a synchronous select cert";
// Return success to continue the handshake.
return QUIC_SUCCESS;
@@ -81,12 +91,13 @@ QuicAsyncStatus TlsServerHandshaker::DefaultProofSourceHandle::ComputeSignature(
absl::string_view in,
size_t max_signature_size) {
if (!handshaker_ || !proof_source_) {
- QUIC_BUG << "ComputeSignature called on a detached handle";
+ QUIC_BUG(quic_bug_10341_2)
+ << "ComputeSignature called on a detached handle";
return QUIC_FAILURE;
}
if (signature_callback_) {
- QUIC_BUG << "ComputeSignature called while pending";
+ QUIC_BUG(quic_bug_10341_3) << "ComputeSignature called while pending";
return QUIC_FAILURE;
}
@@ -489,7 +500,8 @@ TlsServerHandshaker::SetTransportParameters() {
std::vector<uint8_t> early_data_context;
if (!SerializeTransportParametersForTicket(
server_params, *application_state_, &early_data_context)) {
- QUIC_BUG << "Failed to serialize Transport Parameters for ticket.";
+ QUIC_BUG(quic_bug_10341_4)
+ << "Failed to serialize Transport Parameters for ticket.";
result.early_data_context = std::vector<uint8_t>();
return result;
}
@@ -514,7 +526,8 @@ void TlsServerHandshaker::SetWriteSecret(
// Fill crypto_negotiated_params_:
const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
if (cipher) {
- crypto_negotiated_params_->cipher_suite = SSL_CIPHER_get_value(cipher);
+ crypto_negotiated_params_->cipher_suite =
+ SSL_CIPHER_get_protocol_id(cipher);
}
crypto_negotiated_params_->key_exchange_group = SSL_get_curve_id(ssl());
}
@@ -527,16 +540,19 @@ std::string TlsServerHandshaker::GetAcceptChValueForOrigin(
}
void TlsServerHandshaker::FinishHandshake() {
- if (SSL_in_early_data(ssl())) {
- // If the server accepts early data, SSL_do_handshake returns success twice:
- // once after processing the ClientHello and sending the server's first
- // flight, and then again after the handshake is complete. This results in
- // FinishHandshake getting called twice. On the first call to
- // FinishHandshake, we don't have any confirmation that the client is live,
- // so all end of handshake processing is deferred until the handshake is
- // actually complete.
- QUIC_RESTART_FLAG_COUNT(quic_enable_zero_rtt_for_tls_v2);
- return;
+ if (retry_handshake_on_early_data_) {
+ QUICHE_DCHECK(!SSL_in_early_data(ssl()));
+ } else {
+ if (SSL_in_early_data(ssl())) {
+ // If the server accepts early data, SSL_do_handshake returns success
+ // twice: once after processing the ClientHello and sending the server's
+ // first flight, and then again after the handshake is complete. This
+ // results in FinishHandshake getting called twice. On the first call to
+ // FinishHandshake, we don't have any confirmation that the client is
+ // live, so all end of handshake processing is deferred until the
+ // handshake is actually complete.
+ return;
+ }
}
if (!valid_alpn_received_) {
QUIC_DLOG(ERROR)
@@ -570,7 +586,8 @@ QuicAsyncStatus TlsServerHandshaker::VerifyCertChain(
std::unique_ptr<ProofVerifyDetails>* /*details*/,
uint8_t* /*out_alert*/,
std::unique_ptr<ProofVerifierCallback> /*callback*/) {
- QUIC_BUG << "Client certificates are not yet supported on the server";
+ QUIC_BUG(quic_bug_10341_5)
+ << "Client certificates are not yet supported on the server";
return QUIC_FAILURE;
}
@@ -593,6 +610,12 @@ ssl_private_key_result_t TlsServerHandshaker::PrivateKeySign(
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);
}
@@ -616,7 +639,23 @@ ssl_private_key_result_t TlsServerHandshaker::PrivateKeyComplete(
if (expected_ssl_error() == SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) {
return ssl_private_key_retry;
}
- if (!HasValidSignature(max_out)) {
+
+ const bool success = HasValidSignature(max_out);
+ QuicConnectionStats::TlsServerOperationStats compute_signature_stats;
+ compute_signature_stats.success = success;
+ if (async_op_timer_.has_value()) {
+ async_op_timer_->Stop(now());
+ compute_signature_stats.async_latency =
+ async_op_timer_->GetTotalElapsedTime();
+ async_op_timer_.reset();
+ RECORD_LATENCY_IN_US("tls_server_async_compute_signature_latency_us",
+ compute_signature_stats.async_latency,
+ "Async compute signature latency in microseconds");
+ }
+ connection_stats().tls_server_compute_signature_stats =
+ std::move(compute_signature_stats);
+
+ if (!success) {
return ssl_private_key_failure;
}
*out_len = cert_verify_sig_.size();
@@ -665,7 +704,7 @@ int TlsServerHandshaker::SessionTicketSeal(uint8_t* out,
QUICHE_DCHECK(proof_source_->GetTicketCrypter());
std::vector<uint8_t> ticket = proof_source_->GetTicketCrypter()->Encrypt(in);
if (max_out_len < ticket.size()) {
- QUIC_BUG
+ QUIC_BUG(quic_bug_12423_2)
<< "TicketCrypter returned " << ticket.size()
<< " bytes of ciphertext, which is larger than its max overhead of "
<< max_out_len;
@@ -673,6 +712,7 @@ int TlsServerHandshaker::SessionTicketSeal(uint8_t* out,
}
*out_len = ticket.size();
memcpy(out, ticket.data(), ticket.size());
+ QUIC_CODE_COUNT(quic_tls_server_handshaker_tickets_sealed);
return 1; // success
}
@@ -693,19 +733,50 @@ ssl_ticket_aead_result_t TlsServerHandshaker::SessionTicketOpen(
// returning ssl_ticket_aead_retry, we should continue processing to return
// the decrypted ticket.
//
- // If the callback is not run asynchronously, return ssl_ticket_aead_retry
+ // If the callback is not run synchronously, return ssl_ticket_aead_retry
// and when the callback is complete this function will be run again to
// return the result.
if (ticket_decryption_callback_) {
set_expected_ssl_error(SSL_ERROR_PENDING_TICKET);
+ if (async_op_timer_.has_value()) {
+ QUIC_CODE_COUNT(
+ quic_tls_server_decrypting_ticket_while_another_op_pending);
+ }
+ async_op_timer_ = QuicTimeAccumulator();
+ async_op_timer_->Start(now());
return ssl_ticket_aead_retry;
}
}
+
+ ssl_ticket_aead_result_t result =
+ FinalizeSessionTicketOpen(out, out_len, max_out_len);
+
+ QuicConnectionStats::TlsServerOperationStats decrypt_ticket_stats;
+ decrypt_ticket_stats.success = (result == ssl_ticket_aead_success);
+ if (async_op_timer_.has_value()) {
+ async_op_timer_->Stop(now());
+ decrypt_ticket_stats.async_latency = async_op_timer_->GetTotalElapsedTime();
+ async_op_timer_.reset();
+ RECORD_LATENCY_IN_US("tls_server_async_decrypt_ticket_latency_us",
+ decrypt_ticket_stats.async_latency,
+ "Async decrypt ticket latency in microseconds");
+ }
+ connection_stats().tls_server_decrypt_ticket_stats =
+ std::move(decrypt_ticket_stats);
+
+ return result;
+}
+
+ssl_ticket_aead_result_t TlsServerHandshaker::FinalizeSessionTicketOpen(
+ uint8_t* out,
+ size_t* out_len,
+ size_t max_out_len) {
ticket_decryption_callback_ = nullptr;
set_expected_ssl_error(SSL_ERROR_WANT_READ);
if (decrypted_session_ticket_.empty()) {
QUIC_DLOG(ERROR) << "Session ticket decryption failed; ignoring ticket";
// Ticket decryption failed. Ignore the ticket.
+ QUIC_CODE_COUNT(quic_tls_server_handshaker_tickets_ignored);
return ssl_ticket_aead_ignore_ticket;
}
if (max_out_len < decrypted_session_ticket_.size()) {
@@ -715,6 +786,7 @@ ssl_ticket_aead_result_t TlsServerHandshaker::SessionTicketOpen(
decrypted_session_ticket_.size());
*out_len = decrypted_session_ticket_.size();
+ QUIC_CODE_COUNT(quic_tls_server_handshaker_tickets_opened);
return ssl_ticket_aead_success;
}
@@ -743,7 +815,8 @@ ssl_select_cert_result_t TlsServerHandshaker::EarlySelectCertCallback(
if (!pre_shared_key_.empty()) {
// TODO(b/154162689) add PSK support to QUIC+TLS.
- QUIC_BUG << "QUIC server pre-shared keys not yet supported with TLS";
+ QUIC_BUG(quic_bug_10341_6)
+ << "QUIC server pre-shared keys not yet supported with TLS";
return ssl_select_cert_error;
}
@@ -799,6 +872,12 @@ ssl_select_cert_result_t TlsServerHandshaker::EarlySelectCertCallback(
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;
}
@@ -857,6 +936,21 @@ void TlsServerHandshaker::OnSelectCertificateDone(
QUIC_LOG(ERROR) << "No certs provided for host '" << hostname_ << "'";
}
}
+
+ QuicConnectionStats::TlsServerOperationStats select_cert_stats;
+ select_cert_stats.success = (select_cert_status_ == QUIC_SUCCESS);
+ QUICHE_DCHECK_NE(is_sync, async_op_timer_.has_value());
+ if (async_op_timer_.has_value()) {
+ async_op_timer_->Stop(now());
+ select_cert_stats.async_latency = async_op_timer_->GetTotalElapsedTime();
+ async_op_timer_.reset();
+ RECORD_LATENCY_IN_US("tls_server_async_select_cert_latency_us",
+ select_cert_stats.async_latency,
+ "Async select cert latency in microseconds");
+ }
+ connection_stats().tls_server_select_cert_stats =
+ std::move(select_cert_stats);
+
const int last_expected_ssl_error = expected_ssl_error();
set_expected_ssl_error(SSL_ERROR_WANT_READ);
if (!is_sync) {
@@ -928,10 +1022,18 @@ int TlsServerHandshaker::SelectAlpn(const uint8_t** out,
size_t alps_length = 0;
std::unique_ptr<char[]> buffer;
- const std::string& origin = crypto_negotiated_params_->sni;
- std::string accept_ch_value = GetAcceptChValueForOrigin(origin);
+ 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{{{origin, std::move(accept_ch_value)}}};
+ 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());
}
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 16707cd2938..7850d3519a8 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
@@ -15,6 +15,7 @@
#include "quic/core/proto/cached_network_parameters_proto.h"
#include "quic/core/quic_crypto_server_stream_base.h"
#include "quic/core/quic_crypto_stream.h"
+#include "quic/core/quic_time_accumulator.h"
#include "quic/core/quic_types.h"
#include "quic/core/tls_handshaker.h"
#include "quic/platform/api/quic_export.h"
@@ -155,6 +156,11 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
size_t* out_len,
size_t max_out_len,
absl::string_view in) override;
+ // Called when ticket_decryption_callback_ is done to determine a final
+ // decryption result.
+ ssl_ticket_aead_result_t FinalizeSessionTicketOpen(uint8_t* out,
+ size_t* out_len,
+ size_t max_out_len);
TlsConnection::Delegate* ConnectionDelegate() override { return this; }
// The status of cert selection. nullopt means it hasn't started.
@@ -296,6 +302,11 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
bool ProcessTransportParameters(const SSL_CLIENT_HELLO* client_hello,
std::string* error_details);
+ QuicConnectionStats& connection_stats() {
+ return session()->connection()->mutable_stats();
+ }
+ QuicTime now() const { return session()->GetClock()->Now(); }
+
std::unique_ptr<ProofSourceHandle> proof_source_handle_;
ProofSource* proof_source_;
SignatureCallback* signature_callback_ = nullptr;
@@ -321,6 +332,9 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
std::string cert_verify_sig_;
std::unique_ptr<ProofSource::Details> proof_source_details_;
+ // Count the duration of the current async operation, if any.
+ absl::optional<QuicTimeAccumulator> async_op_timer_;
+
std::unique_ptr<ApplicationState> application_state_;
// Pre-shared key used during the handshake.
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 66cdd7984d3..fbec2551227 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
@@ -138,7 +138,6 @@ class TlsServerHandshakerTest : public QuicTestWithParam<TestParams> {
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
server_id_(kServerHostname, kServerPort, false),
supported_versions_({GetParam().version}) {
- SetQuicRestartFlag(quic_enable_zero_rtt_for_tls_v2, true);
SetQuicFlag(FLAGS_quic_disable_server_tls_resumption,
GetParam().disable_resumption);
client_crypto_config_ = std::make_unique<QuicCryptoClientConfig>(
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 7235edf192e..5ed0e08777a 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
@@ -108,12 +108,14 @@ void UberReceivedPacketManager::ResetAckStates(
void UberReceivedPacketManager::EnableMultiplePacketNumberSpacesSupport(
Perspective perspective) {
if (supports_multiple_packet_number_spaces_) {
- QUIC_BUG << "Multiple packet number spaces has already been enabled";
+ QUIC_BUG(quic_bug_10495_1)
+ << "Multiple packet number spaces has already been enabled";
return;
}
if (received_packet_managers_[0].GetLargestObserved().IsInitialized()) {
- QUIC_BUG << "Try to enable multiple packet number spaces support after any "
- "packet has been received.";
+ QUIC_BUG(quic_bug_10495_2)
+ << "Try to enable multiple packet number spaces support after any "
+ "packet has been received.";
return;
}
// In IETF QUIC, the peer is expected to acknowledge packets in Initial and
@@ -236,8 +238,9 @@ void UberReceivedPacketManager::set_save_timestamps(bool save_timestamps) {
void UberReceivedPacketManager::OnAckFrequencyFrame(
const QuicAckFrequencyFrame& frame) {
if (!supports_multiple_packet_number_spaces_) {
- QUIC_BUG << "Received AckFrequencyFrame when multiple packet number spaces "
- "is not supported";
+ QUIC_BUG(quic_bug_10495_3)
+ << "Received AckFrequencyFrame when multiple packet number spaces "
+ "is not supported";
return;
}
received_packet_managers_[APPLICATION_DATA].OnAckFrequencyFrame(frame);
diff --git a/chromium/net/third_party/quiche/src/quic/core/web_transport_interface.h b/chromium/net/third_party/quiche/src/quic/core/web_transport_interface.h
new file mode 100644
index 00000000000..154d242b1e8
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/web_transport_interface.h
@@ -0,0 +1,130 @@
+// 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.
+
+// This header contains interfaces that abstract away different backing
+// protocols for WebTransport.
+
+#ifndef QUICHE_QUIC_CORE_WEB_TRANSPORT_INTERFACE_H_
+#define QUICHE_QUIC_CORE_WEB_TRANSPORT_INTERFACE_H_
+
+#include <cstddef>
+#include <memory>
+
+#include "absl/base/attributes.h"
+#include "absl/strings/string_view.h"
+#include "quic/core/quic_datagram_queue.h"
+#include "quic/core/quic_types.h"
+#include "quic/platform/api/quic_export.h"
+
+namespace quic {
+
+// Visitor that gets notified about events related to a WebTransport stream.
+class QUIC_EXPORT_PRIVATE WebTransportStreamVisitor {
+ public:
+ virtual ~WebTransportStreamVisitor() {}
+
+ // Called whenever the stream has readable data available.
+ virtual void OnCanRead() = 0;
+ // Called whenever the stream is not write-blocked and can accept new data.
+ virtual void OnCanWrite() = 0;
+};
+
+// A stream (either bidirectional or unidirectional) that is contained within a
+// WebTransport session.
+class QUIC_EXPORT_PRIVATE WebTransportStream {
+ public:
+ struct QUIC_EXPORT_PRIVATE ReadResult {
+ // Number of bytes actually read.
+ size_t bytes_read;
+ // Whether the FIN has been received; if true, no further data will arrive
+ // on the stream, and the stream object can be soon potentially garbage
+ // collected.
+ bool fin;
+ };
+
+ virtual ~WebTransportStream() {}
+
+ // Reads at most |buffer_size| bytes into |buffer|.
+ ABSL_MUST_USE_RESULT virtual ReadResult Read(char* buffer,
+ size_t buffer_size) = 0;
+ // Reads all available data and appends it to the end of |output|.
+ ABSL_MUST_USE_RESULT virtual ReadResult Read(std::string* output) = 0;
+ // Writes |data| into the stream. Returns true on success.
+ ABSL_MUST_USE_RESULT virtual bool Write(absl::string_view data) = 0;
+ // Sends the FIN on the stream. Returns true on success.
+ ABSL_MUST_USE_RESULT virtual bool SendFin() = 0;
+
+ // Indicates whether it is possible to write into stream right now.
+ virtual bool CanWrite() const = 0;
+ // Indicates the number of bytes that can be read from the stream.
+ virtual size_t ReadableBytes() const = 0;
+
+ // An ID that is unique within the session. Those are not exposed to the user
+ // via the web API, but can be used internally for bookkeeping and
+ // diagnostics.
+ virtual QuicStreamId GetStreamId() const = 0;
+
+ // Resets the stream with the specified error code.
+ // TODO(b/184048994): change the error code type based on IETF consensus.
+ virtual void ResetWithUserCode(QuicRstStreamErrorCode error) = 0;
+ virtual void ResetDueToInternalError() = 0;
+ // Called when the owning object has been garbage-collected.
+ virtual void MaybeResetDueToStreamObjectGone() = 0;
+
+ virtual WebTransportStreamVisitor* visitor() = 0;
+ virtual void SetVisitor(
+ std::unique_ptr<WebTransportStreamVisitor> visitor) = 0;
+};
+
+// Visitor that gets notified about events related to a WebTransport session.
+class QUIC_EXPORT_PRIVATE WebTransportVisitor {
+ public:
+ virtual ~WebTransportVisitor() {}
+
+ // Notifies the visitor when the session is ready to exchange application
+ // data.
+ virtual void OnSessionReady() = 0;
+
+ // Notifies the visitor when a new stream has been received. The stream in
+ // question can be retrieved using AcceptIncomingBidirectionalStream() or
+ // AcceptIncomingUnidirectionalStream().
+ virtual void OnIncomingBidirectionalStreamAvailable() = 0;
+ virtual void OnIncomingUnidirectionalStreamAvailable() = 0;
+
+ // Notifies the visitor when a new datagram has been received.
+ virtual void OnDatagramReceived(absl::string_view datagram) = 0;
+
+ // Notifies the visitor that a new outgoing stream can now be created.
+ virtual void OnCanCreateNewOutgoingBidirectionalStream() = 0;
+ virtual void OnCanCreateNewOutgoingUnidirectionalStream() = 0;
+};
+
+// An abstract interface for a WebTransport session.
+class QUIC_EXPORT_PRIVATE WebTransportSession {
+ public:
+ virtual ~WebTransportSession() {}
+
+ // Return the earliest incoming stream that has been received by the session
+ // but has not been accepted. Returns nullptr if there are no incoming
+ // streams.
+ virtual WebTransportStream* AcceptIncomingBidirectionalStream() = 0;
+ virtual WebTransportStream* AcceptIncomingUnidirectionalStream() = 0;
+
+ // Returns true if flow control allows opening a new stream.
+ virtual bool CanOpenNextOutgoingBidirectionalStream() = 0;
+ virtual bool CanOpenNextOutgoingUnidirectionalStream() = 0;
+ // Opens a new WebTransport stream, or returns nullptr if that is not possible
+ // due to flow control.
+ virtual WebTransportStream* OpenOutgoingBidirectionalStream() = 0;
+ virtual WebTransportStream* OpenOutgoingUnidirectionalStream() = 0;
+
+ virtual MessageStatus SendOrQueueDatagram(QuicMemSlice datagram) = 0;
+ // Sets the largest duration that a datagram can spend in the queue before
+ // being silently dropped.
+ virtual void SetDatagramMaxTimeInQueue(QuicTime::Delta max_time_in_queue) = 0;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_WEB_TRANSPORT_INTERFACE_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/web_transport_stream_adapter.cc b/chromium/net/third_party/quiche/src/quic/core/web_transport_stream_adapter.cc
new file mode 100644
index 00000000000..78227049dbd
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/web_transport_stream_adapter.cc
@@ -0,0 +1,116 @@
+// 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 "quic/core/web_transport_stream_adapter.h"
+
+namespace quic {
+
+WebTransportStreamAdapter::WebTransportStreamAdapter(
+ QuicSession* session,
+ QuicStream* stream,
+ QuicStreamSequencer* sequencer)
+ : session_(session), stream_(stream), sequencer_(sequencer) {}
+
+WebTransportStream::ReadResult WebTransportStreamAdapter::Read(
+ char* buffer,
+ size_t buffer_size) {
+ iovec iov;
+ iov.iov_base = buffer;
+ iov.iov_len = buffer_size;
+ const size_t result = sequencer_->Readv(&iov, 1);
+ if (!fin_read_ && sequencer_->IsClosed()) {
+ fin_read_ = true;
+ stream_->OnFinRead();
+ }
+ return ReadResult{result, sequencer_->IsClosed()};
+}
+
+WebTransportStream::ReadResult WebTransportStreamAdapter::Read(
+ std::string* output) {
+ const size_t old_size = output->size();
+ const size_t bytes_to_read = ReadableBytes();
+ output->resize(old_size + bytes_to_read);
+ ReadResult result = Read(&(*output)[old_size], bytes_to_read);
+ QUICHE_DCHECK_EQ(bytes_to_read, result.bytes_read);
+ output->resize(old_size + result.bytes_read);
+ return result;
+}
+
+bool WebTransportStreamAdapter::Write(absl::string_view data) {
+ if (!CanWrite()) {
+ return false;
+ }
+
+ QuicUniqueBufferPtr buffer = MakeUniqueBuffer(
+ session_->connection()->helper()->GetStreamSendBufferAllocator(),
+ data.size());
+ memcpy(buffer.get(), data.data(), data.size());
+ QuicMemSlice memslice(std::move(buffer), data.size());
+ QuicConsumedData consumed =
+ stream_->WriteMemSlices(QuicMemSliceSpan(&memslice), /*fin=*/false);
+
+ if (consumed.bytes_consumed == data.size()) {
+ return true;
+ }
+ if (consumed.bytes_consumed == 0) {
+ return false;
+ }
+ // WebTransportStream::Write() is an all-or-nothing write API. To achieve
+ // that property, it relies on WriteMemSlices() being an all-or-nothing API.
+ // If WriteMemSlices() fails to provide that guarantee, we have no way to
+ // communicate a partial write to the caller, and thus it's safer to just
+ // close the connection.
+ QUIC_BUG(WebTransportStreamAdapter partial write)
+ << "WriteMemSlices() unexpectedly partially consumed the input "
+ "data, provided: "
+ << data.size() << ", written: " << consumed.bytes_consumed;
+ stream_->OnUnrecoverableError(
+ QUIC_INTERNAL_ERROR,
+ "WriteMemSlices() unexpectedly partially consumed the input data");
+ return false;
+}
+
+bool WebTransportStreamAdapter::SendFin() {
+ if (!CanWrite()) {
+ return false;
+ }
+
+ QuicMemSlice empty;
+ QuicConsumedData consumed =
+ stream_->WriteMemSlices(QuicMemSliceSpan(&empty), /*fin=*/true);
+ QUICHE_DCHECK_EQ(consumed.bytes_consumed, 0u);
+ return consumed.fin_consumed;
+}
+
+bool WebTransportStreamAdapter::CanWrite() const {
+ return stream_->CanWriteNewData() && !stream_->write_side_closed();
+}
+
+size_t WebTransportStreamAdapter::ReadableBytes() const {
+ return sequencer_->ReadableBytes();
+}
+
+void WebTransportStreamAdapter::OnDataAvailable() {
+ if (visitor_ == nullptr) {
+ return;
+ }
+ const bool fin_readable = sequencer_->IsClosed() && !fin_read_;
+ if (ReadableBytes() == 0 && !fin_readable) {
+ return;
+ }
+ visitor_->OnCanRead();
+}
+
+void WebTransportStreamAdapter::OnCanWriteNewData() {
+ // Ensure the origin check has been completed, as the stream can be notified
+ // about being writable before that.
+ if (!CanWrite()) {
+ return;
+ }
+ if (visitor_ != nullptr) {
+ visitor_->OnCanWrite();
+ }
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/web_transport_stream_adapter.h b/chromium/net/third_party/quiche/src/quic/core/web_transport_stream_adapter.h
new file mode 100644
index 00000000000..2e4704ba3e4
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/web_transport_stream_adapter.h
@@ -0,0 +1,66 @@
+// 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_QUIC_CORE_WEB_TRANSPORT_STREAM_ADAPTER_H_
+#define QUICHE_QUIC_CORE_WEB_TRANSPORT_STREAM_ADAPTER_H_
+
+#include "quic/core/quic_session.h"
+#include "quic/core/quic_stream.h"
+#include "quic/core/quic_stream_sequencer.h"
+#include "quic/core/web_transport_interface.h"
+
+namespace quic {
+
+// Converts WebTransportStream API calls into QuicStream API calls. The users
+// of this class can either subclass it, or wrap around it.
+class QUIC_EXPORT_PRIVATE WebTransportStreamAdapter
+ : public WebTransportStream {
+ public:
+ WebTransportStreamAdapter(QuicSession* session,
+ QuicStream* stream,
+ QuicStreamSequencer* sequencer);
+
+ // WebTransportStream implementation.
+ ABSL_MUST_USE_RESULT ReadResult Read(char* buffer,
+ size_t buffer_size) override;
+ ABSL_MUST_USE_RESULT ReadResult Read(std::string* output) override;
+ ABSL_MUST_USE_RESULT bool Write(absl::string_view data) override;
+ ABSL_MUST_USE_RESULT bool SendFin() override;
+ bool CanWrite() const override;
+ size_t ReadableBytes() const override;
+ void SetVisitor(std::unique_ptr<WebTransportStreamVisitor> visitor) override {
+ visitor_ = std::move(visitor);
+ }
+ QuicStreamId GetStreamId() const override { return stream_->id(); }
+
+ void ResetWithUserCode(QuicRstStreamErrorCode error) override {
+ stream_->Reset(error);
+ }
+ void ResetDueToInternalError() override {
+ stream_->Reset(QUIC_STREAM_INTERNAL_ERROR);
+ }
+ void MaybeResetDueToStreamObjectGone() override {
+ if (stream_->write_side_closed() && stream_->read_side_closed()) {
+ return;
+ }
+ stream_->Reset(QUIC_STREAM_CANCELLED);
+ }
+
+ WebTransportStreamVisitor* visitor() override { return visitor_.get(); }
+
+ // Calls that need to be passed from the corresponding QuicStream methods.
+ void OnDataAvailable();
+ void OnCanWriteNewData();
+
+ private:
+ QuicSession* session_; // Unowned.
+ QuicStream* stream_; // Unowned.
+ QuicStreamSequencer* sequencer_; // Unowned.
+ std::unique_ptr<WebTransportStreamVisitor> visitor_;
+ bool fin_read_ = false;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_WEB_TRANSPORT_STREAM_ADAPTER_H_
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 8e09a12b27c..4d0523f5177 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
@@ -29,6 +29,12 @@ DEFINE_QUIC_COMMAND_LINE_FLAG(bool,
false,
"If true, don't verify the server certificate.");
+DEFINE_QUIC_COMMAND_LINE_FLAG(std::string,
+ masque_mode,
+ "",
+ "Allows setting MASQUE mode, valid values are "
+ "open and legacy. Defaults to open.");
+
namespace quic {
namespace {
@@ -45,6 +51,8 @@ int RunMasqueClient(int argc, char* argv[]) {
return 1;
}
+ SetQuicReloadableFlag(quic_h3_datagram, true);
+
const bool disable_certificate_verification =
GetQuicFlag(FLAGS_disable_certificate_verification);
QuicEpollServer epoll_server;
@@ -54,7 +62,8 @@ int RunMasqueClient(int argc, char* argv[]) {
masque_url = QuicUrl(absl::StrCat("https://", urls[0]), "https");
}
if (masque_url.host().empty()) {
- QUIC_LOG(ERROR) << "Failed to parse MASQUE server address " << urls[0];
+ std::cerr << "Failed to parse MASQUE server address \"" << urls[0] << "\""
+ << std::endl;
return 1;
}
std::unique_ptr<ProofVerifier> proof_verifier;
@@ -63,15 +72,23 @@ int RunMasqueClient(int argc, char* argv[]) {
} else {
proof_verifier = CreateDefaultProofVerifier(masque_url.host());
}
- std::unique_ptr<MasqueEpollClient> masque_client =
- MasqueEpollClient::Create(masque_url.host(), masque_url.port(),
- &epoll_server, std::move(proof_verifier));
+ MasqueMode masque_mode = MasqueMode::kOpen;
+ std::string mode_string = GetQuicFlag(FLAGS_masque_mode);
+ if (mode_string == "legacy") {
+ masque_mode = MasqueMode::kLegacy;
+ } else if (!mode_string.empty() && mode_string != "open") {
+ std::cerr << "Invalid masque_mode \"" << mode_string << "\"" << std::endl;
+ return 1;
+ }
+ std::unique_ptr<MasqueEpollClient> masque_client = MasqueEpollClient::Create(
+ masque_url.host(), masque_url.port(), masque_mode, &epoll_server,
+ std::move(proof_verifier));
if (masque_client == nullptr) {
return 1;
}
std::cerr << "MASQUE is connected " << masque_client->connection_id()
- << std::endl;
+ << " in " << masque_mode << " mode" << std::endl;
for (size_t i = 1; i < urls.size(); ++i) {
if (!tools::SendEncapsulatedMasqueRequest(
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 eeedccfd0d5..8793d5319f2 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
@@ -3,10 +3,16 @@
// found in the LICENSE file.
#include "quic/masque/masque_client_session.h"
+#include "absl/algorithm/container.h"
+#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 {
MasqueClientSession::MasqueClientSession(
+ MasqueMode masque_mode,
const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
QuicConnection* connection,
@@ -20,36 +26,42 @@ MasqueClientSession::MasqueClientSession(
server_id,
crypto_config,
push_promise_index),
+ masque_mode_(masque_mode),
owner_(owner),
compression_engine_(this) {}
void MasqueClientSession::OnMessageReceived(absl::string_view message) {
- QUIC_DVLOG(1) << "Received DATAGRAM frame of length " << message.length();
-
- QuicConnectionId client_connection_id, server_connection_id;
- QuicSocketAddress server_address;
- std::vector<char> packet;
- bool version_present;
- if (!compression_engine_.DecompressDatagram(
- message, &client_connection_id, &server_connection_id,
- &server_address, &packet, &version_present)) {
- return;
- }
+ if (masque_mode_ == MasqueMode::kLegacy) {
+ QUIC_DVLOG(1) << "Received DATAGRAM frame of length " << message.length();
+ QuicConnectionId client_connection_id, server_connection_id;
+ QuicSocketAddress target_server_address;
+ std::vector<char> packet;
+ bool version_present;
+ if (!compression_engine_.DecompressDatagram(
+ message, &client_connection_id, &server_connection_id,
+ &target_server_address, &packet, &version_present)) {
+ return;
+ }
+
+ auto connection_id_registration =
+ client_connection_id_registrations_.find(client_connection_id);
+ if (connection_id_registration ==
+ client_connection_id_registrations_.end()) {
+ QUIC_DLOG(ERROR) << "MasqueClientSession failed to dispatch "
+ << client_connection_id;
+ return;
+ }
+ EncapsulatedClientSession* encapsulated_client_session =
+ connection_id_registration->second;
+ encapsulated_client_session->ProcessPacket(
+ absl::string_view(packet.data(), packet.size()), target_server_address);
- auto connection_id_registration =
- client_connection_id_registrations_.find(client_connection_id);
- if (connection_id_registration == client_connection_id_registrations_.end()) {
- QUIC_DLOG(ERROR) << "MasqueClientSession failed to dispatch "
- << client_connection_id;
+ QUIC_DVLOG(1) << "Sent " << packet.size() << " bytes to connection for "
+ << client_connection_id;
return;
}
- EncapsulatedClientSession* encapsulated_client_session =
- connection_id_registration->second;
- encapsulated_client_session->ProcessPacket(
- absl::string_view(packet.data(), packet.size()), server_address);
-
- QUIC_DVLOG(1) << "Sent " << packet.size() << " bytes to connection for "
- << client_connection_id;
+ QUICHE_DCHECK_EQ(masque_mode_, MasqueMode::kOpen);
+ QuicSpdySession::OnMessageReceived(message);
}
void MasqueClientSession::OnMessageAcked(QuicMessageId message_id,
@@ -61,12 +73,79 @@ void MasqueClientSession::OnMessageLost(QuicMessageId message_id) {
QUIC_DVLOG(1) << "We believe DATAGRAM frame " << message_id << " was lost";
}
-void MasqueClientSession::SendPacket(QuicConnectionId client_connection_id,
- QuicConnectionId server_connection_id,
- absl::string_view packet,
- const QuicSocketAddress& server_address) {
- compression_engine_.CompressAndSendPacket(
- packet, client_connection_id, server_connection_id, server_address);
+const MasqueClientSession::ConnectUdpClientState*
+MasqueClientSession::GetOrCreateConnectUdpClientState(
+ const QuicSocketAddress& target_server_address,
+ EncapsulatedClientSession* encapsulated_client_session) {
+ for (const ConnectUdpClientState& client_state : connect_udp_client_states_) {
+ if (client_state.target_server_address() == target_server_address &&
+ client_state.encapsulated_client_session() ==
+ encapsulated_client_session) {
+ // Found existing CONNECT-UDP request.
+ return &client_state;
+ }
+ }
+ // No CONNECT-UDP request found, create a new one.
+ QuicSpdyClientStream* stream = CreateOutgoingBidirectionalStream();
+ if (stream == nullptr) {
+ // Stream flow control limits prevented us from opening a new stream.
+ QUIC_DLOG(ERROR) << "Failed to open CONNECT-UDP stream";
+ return nullptr;
+ }
+
+ QuicDatagramFlowId flow_id = GetNextDatagramFlowId();
+
+ QUIC_DLOG(INFO) << "Sending CONNECT-UDP request for " << target_server_address
+ << " using flow ID " << flow_id << " on stream "
+ << stream->id();
+
+ // Send the request.
+ spdy::Http2HeaderBlock headers;
+ headers[":method"] = "CONNECT-UDP";
+ headers[":scheme"] = "masque";
+ headers[":path"] = "/";
+ headers[":authority"] = target_server_address.ToString();
+ SpdyUtils::AddDatagramFlowIdHeader(&headers, flow_id);
+ size_t bytes_sent =
+ stream->SendRequest(std::move(headers), /*body=*/"", /*fin=*/false);
+ if (bytes_sent == 0) {
+ QUIC_DLOG(ERROR) << "Failed to send CONNECT-UDP request";
+ return nullptr;
+ }
+
+ connect_udp_client_states_.push_back(
+ ConnectUdpClientState(stream, encapsulated_client_session, this, flow_id,
+ target_server_address));
+ return &connect_udp_client_states_.back();
+}
+
+void MasqueClientSession::SendPacket(
+ QuicConnectionId client_connection_id,
+ QuicConnectionId server_connection_id,
+ absl::string_view packet,
+ const QuicSocketAddress& target_server_address,
+ EncapsulatedClientSession* encapsulated_client_session) {
+ if (masque_mode_ == MasqueMode::kLegacy) {
+ compression_engine_.CompressAndSendPacket(packet, client_connection_id,
+ server_connection_id,
+ target_server_address);
+ return;
+ }
+ const ConnectUdpClientState* connect_udp = GetOrCreateConnectUdpClientState(
+ target_server_address, encapsulated_client_session);
+ if (connect_udp == nullptr) {
+ QUIC_DLOG(ERROR) << "Failed to create CONNECT-UDP request";
+ return;
+ }
+
+ QuicDatagramFlowId flow_id = connect_udp->flow_id();
+ MessageStatus message_status =
+ SendHttp3Datagram(connect_udp->flow_id(), packet);
+
+ QUIC_DVLOG(1) << "Sent packet to " << target_server_address
+ << " compressed with flow ID " << flow_id
+ << " and got message status "
+ << MessageStatusToString(message_status);
}
void MasqueClientSession::RegisterConnectionId(
@@ -84,14 +163,126 @@ void MasqueClientSession::RegisterConnectionId(
}
void MasqueClientSession::UnregisterConnectionId(
- QuicConnectionId client_connection_id) {
+ QuicConnectionId client_connection_id,
+ EncapsulatedClientSession* encapsulated_client_session) {
QUIC_DLOG(INFO) << "Unregistering " << client_connection_id;
- if (client_connection_id_registrations_.find(client_connection_id) !=
- client_connection_id_registrations_.end()) {
- client_connection_id_registrations_.erase(client_connection_id);
- owner_->UnregisterClientConnectionId(client_connection_id);
- compression_engine_.UnregisterClientConnectionId(client_connection_id);
+ if (masque_mode_ == MasqueMode::kLegacy) {
+ if (client_connection_id_registrations_.find(client_connection_id) !=
+ client_connection_id_registrations_.end()) {
+ client_connection_id_registrations_.erase(client_connection_id);
+ owner_->UnregisterClientConnectionId(client_connection_id);
+ compression_engine_.UnregisterClientConnectionId(client_connection_id);
+ }
+ return;
+ }
+
+ for (auto it = connect_udp_client_states_.begin();
+ it != connect_udp_client_states_.end();) {
+ if (it->encapsulated_client_session() == encapsulated_client_session) {
+ QUIC_DLOG(INFO) << "Removing state for flow_id " << it->flow_id();
+ auto* stream = it->stream();
+ it = connect_udp_client_states_.erase(it);
+ if (!stream->write_side_closed()) {
+ stream->Reset(QUIC_STREAM_CANCELLED);
+ }
+ } else {
+ ++it;
+ }
+ }
+}
+
+void MasqueClientSession::OnConnectionClosed(
+ const QuicConnectionCloseFrame& frame,
+ ConnectionCloseSource source) {
+ QuicSpdyClientSession::OnConnectionClosed(frame, source);
+ // Close all encapsulated sessions.
+ for (const auto& client_state : connect_udp_client_states_) {
+ client_state.encapsulated_client_session()->CloseConnection(
+ QUIC_CONNECTION_CANCELLED, "Underlying MASQUE connection was closed",
+ ConnectionCloseBehavior::SILENT_CLOSE);
}
}
+void MasqueClientSession::OnStreamClosed(QuicStreamId stream_id) {
+ if (QuicUtils::IsBidirectionalStreamId(stream_id, version()) &&
+ QuicUtils::IsClientInitiatedStreamId(transport_version(), stream_id)) {
+ QuicSpdyClientStream* stream =
+ reinterpret_cast<QuicSpdyClientStream*>(GetActiveStream(stream_id));
+ if (stream != nullptr) {
+ QUIC_DLOG(INFO) << "Stream " << stream_id
+ << " closed, got response headers:"
+ << stream->response_headers().DebugString();
+ }
+ }
+ for (auto it = connect_udp_client_states_.begin();
+ it != connect_udp_client_states_.end();) {
+ if (it->stream()->id() == stream_id) {
+ QUIC_DLOG(INFO) << "Stream " << stream_id
+ << " was closed, removing state for flow_id "
+ << it->flow_id();
+ auto* encapsulated_client_session = it->encapsulated_client_session();
+ it = connect_udp_client_states_.erase(it);
+ encapsulated_client_session->CloseConnection(
+ QUIC_CONNECTION_CANCELLED,
+ "Underlying MASQUE CONNECT-UDP stream was closed",
+ ConnectionCloseBehavior::SILENT_CLOSE);
+ } else {
+ ++it;
+ }
+ }
+
+ QuicSpdyClientSession::OnStreamClosed(stream_id);
+}
+
+MasqueClientSession::ConnectUdpClientState::ConnectUdpClientState(
+ QuicSpdyClientStream* stream,
+ EncapsulatedClientSession* encapsulated_client_session,
+ MasqueClientSession* masque_session,
+ QuicDatagramFlowId flow_id,
+ const QuicSocketAddress& target_server_address)
+ : stream_(stream),
+ encapsulated_client_session_(encapsulated_client_session),
+ masque_session_(masque_session),
+ flow_id_(flow_id),
+ target_server_address_(target_server_address) {
+ QUICHE_DCHECK_NE(masque_session_, nullptr);
+ masque_session_->RegisterHttp3FlowId(this->flow_id(), this);
+}
+
+MasqueClientSession::ConnectUdpClientState::~ConnectUdpClientState() {
+ if (flow_id_.has_value()) {
+ masque_session_->UnregisterHttp3FlowId(flow_id());
+ }
+}
+
+MasqueClientSession::ConnectUdpClientState::ConnectUdpClientState(
+ MasqueClientSession::ConnectUdpClientState&& other) {
+ *this = std::move(other);
+}
+
+MasqueClientSession::ConnectUdpClientState&
+MasqueClientSession::ConnectUdpClientState::operator=(
+ MasqueClientSession::ConnectUdpClientState&& other) {
+ stream_ = other.stream_;
+ encapsulated_client_session_ = other.encapsulated_client_session_;
+ masque_session_ = other.masque_session_;
+ flow_id_ = other.flow_id_;
+ target_server_address_ = other.target_server_address_;
+ other.flow_id_.reset();
+ if (flow_id_.has_value()) {
+ masque_session_->UnregisterHttp3FlowId(flow_id());
+ masque_session_->RegisterHttp3FlowId(flow_id(), this);
+ }
+ return *this;
+}
+
+void MasqueClientSession::ConnectUdpClientState::OnHttp3Datagram(
+ QuicDatagramFlowId flow_id,
+ absl::string_view payload) {
+ QUICHE_DCHECK_EQ(flow_id, this->flow_id());
+ encapsulated_client_session_->ProcessPacket(payload, target_server_address_);
+ QUIC_DVLOG(1) << "Sent " << payload.size()
+ << " bytes to connection for flow_id " << flow_id;
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_client_session.h b/chromium/net/third_party/quiche/src/quic/masque/masque_client_session.h
index 0eab5b22c20..e055a7699be 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_client_session.h
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_client_session.h
@@ -9,6 +9,7 @@
#include "absl/strings/string_view.h"
#include "quic/core/http/quic_spdy_client_session.h"
#include "quic/masque/masque_compression_engine.h"
+#include "quic/masque/masque_utils.h"
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_socket_address.h"
@@ -39,14 +40,21 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession {
// Process packet that was just decapsulated.
virtual void ProcessPacket(absl::string_view packet,
- QuicSocketAddress server_address) = 0;
+ QuicSocketAddress target_server_address) = 0;
+
+ // Close the encapsulated connection.
+ virtual void CloseConnection(
+ QuicErrorCode error,
+ const std::string& details,
+ ConnectionCloseBehavior connection_close_behavior) = 0;
};
// Takes ownership of |connection|, but not of |crypto_config| or
// |push_promise_index| or |owner|. All pointers must be non-null. Caller
// must ensure that |push_promise_index| and |owner| stay valid for the
// lifetime of the newly created MasqueClientSession.
- MasqueClientSession(const QuicConfig& config,
+ MasqueClientSession(MasqueMode masque_mode,
+ const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
QuicConnection* connection,
const QuicServerId& server_id,
@@ -60,17 +68,19 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession {
// From QuicSession.
void OnMessageReceived(absl::string_view message) override;
-
void OnMessageAcked(QuicMessageId message_id,
QuicTime receive_timestamp) override;
-
void OnMessageLost(QuicMessageId message_id) override;
+ void OnConnectionClosed(const QuicConnectionCloseFrame& frame,
+ ConnectionCloseSource source) override;
+ void OnStreamClosed(QuicStreamId stream_id) override;
// Send encapsulated packet.
void SendPacket(QuicConnectionId client_connection_id,
QuicConnectionId server_connection_id,
absl::string_view packet,
- const QuicSocketAddress& server_address);
+ const QuicSocketAddress& target_server_address,
+ EncapsulatedClientSession* encapsulated_client_session);
// Register encapsulated client. This allows clients that are encapsulated
// within this MASQUE session to indicate they own a given client connection
@@ -84,9 +94,62 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession {
// Unregister encapsulated client. |client_connection_id| must match a
// value previously passed to RegisterConnectionId.
- void UnregisterConnectionId(QuicConnectionId client_connection_id);
+ void UnregisterConnectionId(
+ QuicConnectionId client_connection_id,
+ EncapsulatedClientSession* encapsulated_client_session);
private:
+ // State that the MasqueClientSession keeps for each CONNECT-UDP request.
+ class QUIC_NO_EXPORT ConnectUdpClientState
+ : public QuicSpdySession::Http3DatagramVisitor {
+ public:
+ // |stream| and |encapsulated_client_session| must be valid for the lifetime
+ // of the ConnectUdpClientState.
+ explicit ConnectUdpClientState(
+ QuicSpdyClientStream* stream,
+ EncapsulatedClientSession* encapsulated_client_session,
+ MasqueClientSession* masque_session,
+ QuicDatagramFlowId flow_id,
+ const QuicSocketAddress& target_server_address);
+
+ ~ConnectUdpClientState();
+
+ // Disallow copy but allow move.
+ ConnectUdpClientState(const ConnectUdpClientState&) = delete;
+ ConnectUdpClientState(ConnectUdpClientState&&);
+ ConnectUdpClientState& operator=(const ConnectUdpClientState&) = delete;
+ ConnectUdpClientState& operator=(ConnectUdpClientState&&);
+
+ QuicSpdyClientStream* stream() const { return stream_; }
+ EncapsulatedClientSession* encapsulated_client_session() const {
+ return encapsulated_client_session_;
+ }
+ QuicDatagramFlowId flow_id() const {
+ QUICHE_DCHECK(flow_id_.has_value());
+ return *flow_id_;
+ }
+ const QuicSocketAddress& target_server_address() const {
+ return target_server_address_;
+ }
+
+ // From QuicSpdySession::Http3DatagramVisitor.
+ void OnHttp3Datagram(QuicDatagramFlowId flow_id,
+ absl::string_view payload) override;
+
+ private:
+ QuicSpdyClientStream* stream_; // Unowned.
+ EncapsulatedClientSession* encapsulated_client_session_; // Unowned.
+ MasqueClientSession* masque_session_; // Unowned.
+ absl::optional<QuicDatagramFlowId> flow_id_;
+ QuicSocketAddress target_server_address_;
+ };
+
+ const ConnectUdpClientState* GetOrCreateConnectUdpClientState(
+ const QuicSocketAddress& target_server_address,
+ EncapsulatedClientSession* encapsulated_client_session);
+
+ MasqueMode masque_mode_;
+ std::list<ConnectUdpClientState> connect_udp_client_states_;
absl::flat_hash_map<QuicConnectionId,
EncapsulatedClientSession*,
QuicConnectionIdHash>
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 af6758af58a..8413e0d974b 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
@@ -30,14 +30,9 @@ enum MasqueAddressFamily : uint8_t {
} // namespace
-MasqueCompressionEngine::MasqueCompressionEngine(QuicSession* masque_session)
- : masque_session_(masque_session) {
- if (masque_session_->perspective() == Perspective::IS_SERVER) {
- next_flow_id_ = 1;
- } else {
- next_flow_id_ = 2;
- }
-}
+MasqueCompressionEngine::MasqueCompressionEngine(
+ QuicSpdySession* masque_session)
+ : masque_session_(masque_session) {}
QuicDatagramFlowId MasqueCompressionEngine::FindOrCreateCompressionContext(
QuicConnectionId client_connection_id,
@@ -79,7 +74,11 @@ QuicDatagramFlowId MasqueCompressionEngine::FindOrCreateCompressionContext(
}
// Create new compression context.
- flow_id = GetNextFlowId();
+ flow_id = masque_session_->GetNextDatagramFlowId();
+ if (flow_id == kFlowId0) {
+ // Do not use value zero which is reserved in this mode.
+ flow_id = masque_session_->GetNextDatagramFlowId();
+ }
QUIC_DVLOG(1) << "Compression assigning new flow_id " << flow_id << " to "
<< server_address << " client " << client_connection_id
<< " server " << server_connection_id;
@@ -107,29 +106,29 @@ bool MasqueCompressionEngine::WriteCompressedPacketToSlice(
if (validated) {
QUIC_DVLOG(1) << "Compressing using validated flow_id " << flow_id;
if (!writer->WriteVarInt62(flow_id)) {
- QUIC_BUG << "Failed to write flow_id";
+ QUIC_BUG(quic_bug_10981_1) << "Failed to write flow_id";
return false;
}
} else {
QUIC_DVLOG(1) << "Compressing using unvalidated flow_id " << flow_id;
if (!writer->WriteVarInt62(kFlowId0)) {
- QUIC_BUG << "Failed to write kFlowId0";
+ QUIC_BUG(quic_bug_10981_2) << "Failed to write kFlowId0";
return false;
}
if (!writer->WriteVarInt62(flow_id)) {
- QUIC_BUG << "Failed to write flow_id";
+ QUIC_BUG(quic_bug_10981_3) << "Failed to write flow_id";
return false;
}
if (!writer->WriteLengthPrefixedConnectionId(client_connection_id)) {
- QUIC_BUG << "Failed to write client_connection_id";
+ QUIC_BUG(quic_bug_10981_4) << "Failed to write client_connection_id";
return false;
}
if (!writer->WriteLengthPrefixedConnectionId(server_connection_id)) {
- QUIC_BUG << "Failed to write server_connection_id";
+ QUIC_BUG(quic_bug_10981_5) << "Failed to write server_connection_id";
return false;
}
if (!writer->WriteUInt16(server_address.port())) {
- QUIC_BUG << "Failed to write port";
+ QUIC_BUG(quic_bug_10981_6) << "Failed to write port";
return false;
}
QuicIpAddress peer_ip = server_address.host();
@@ -140,30 +139,31 @@ bool MasqueCompressionEngine::WriteCompressedPacketToSlice(
if (peer_ip.address_family() == IpAddressFamily::IP_V6) {
address_id = MasqueAddressFamilyIPv6;
if (peer_ip_bytes.length() != QuicIpAddress::kIPv6AddressSize) {
- QUIC_BUG << "Bad IPv6 length " << server_address;
+ QUIC_BUG(quic_bug_10981_7) << "Bad IPv6 length " << server_address;
return false;
}
} else if (peer_ip.address_family() == IpAddressFamily::IP_V4) {
address_id = MasqueAddressFamilyIPv4;
if (peer_ip_bytes.length() != QuicIpAddress::kIPv4AddressSize) {
- QUIC_BUG << "Bad IPv4 length " << server_address;
+ QUIC_BUG(quic_bug_10981_8) << "Bad IPv4 length " << server_address;
return false;
}
} else {
- QUIC_BUG << "Unexpected server_address " << server_address;
+ QUIC_BUG(quic_bug_10981_9)
+ << "Unexpected server_address " << server_address;
return false;
}
if (!writer->WriteUInt8(address_id)) {
- QUIC_BUG << "Failed to write address_id";
+ QUIC_BUG(quic_bug_10981_10) << "Failed to write address_id";
return false;
}
if (!writer->WriteStringPiece(peer_ip_bytes)) {
- QUIC_BUG << "Failed to write IP address";
+ QUIC_BUG(quic_bug_10981_11) << "Failed to write IP address";
return false;
}
}
if (!writer->WriteUInt8(first_byte)) {
- QUIC_BUG << "Failed to write first_byte";
+ QUIC_BUG(quic_bug_10981_12) << "Failed to write first_byte";
return false;
}
if (long_header) {
@@ -173,7 +173,7 @@ bool MasqueCompressionEngine::WriteCompressedPacketToSlice(
return false;
}
if (!writer->WriteUInt32(version_label)) {
- QUIC_BUG << "Failed to write version";
+ QUIC_BUG(quic_bug_10981_13) << "Failed to write version";
return false;
}
QuicConnectionId packet_destination_connection_id,
@@ -215,7 +215,7 @@ bool MasqueCompressionEngine::WriteCompressedPacketToSlice(
}
absl::string_view packet_payload = reader->ReadRemainingPayload();
if (!writer->WriteStringPiece(packet_payload)) {
- QUIC_BUG << "Failed to write packet_payload";
+ QUIC_BUG(quic_bug_10981_14) << "Failed to write packet_payload";
return false;
}
return true;
@@ -231,13 +231,13 @@ void MasqueCompressionEngine::CompressAndSendPacket(
<< quiche::QuicheTextUtils::HexDump(packet);
QUICHE_DCHECK(server_address.IsInitialized());
if (packet.empty()) {
- QUIC_BUG << "Tried to send empty packet";
+ QUIC_BUG(quic_bug_10981_15) << "Tried to send empty packet";
return;
}
QuicDataReader reader(packet.data(), packet.length());
uint8_t first_byte;
if (!reader.ReadUInt8(&first_byte)) {
- QUIC_BUG << "Failed to read first_byte";
+ QUIC_BUG(quic_bug_10981_16) << "Failed to read first_byte";
return;
}
const bool long_header = (first_byte & FLAGS_LONG_HEADER) != 0;
@@ -341,7 +341,7 @@ bool MasqueCompressionEngine::ParseCompressionContext(
QuicIpAddress ip_address;
ip_address.FromPackedString(ip_bytes, ip_bytes_length);
if (!ip_address.IsInitialized()) {
- QUIC_BUG << "Failed to parse IP address";
+ QUIC_BUG(quic_bug_10981_17) << "Failed to parse IP address";
return false;
}
QuicSocketAddress new_server_address = QuicSocketAddress(ip_address, port);
@@ -425,7 +425,7 @@ bool MasqueCompressionEngine::WriteDecompressedPacket(
*packet = std::vector<char>(packet_length);
QuicDataWriter writer(packet->size(), packet->data());
if (!writer.WriteUInt8(first_byte)) {
- QUIC_BUG << "Failed to write first_byte";
+ QUIC_BUG(quic_bug_10981_18) << "Failed to write first_byte";
return false;
}
if (*version_present) {
@@ -435,26 +435,29 @@ bool MasqueCompressionEngine::WriteDecompressedPacket(
return false;
}
if (!writer.WriteUInt32(version_label)) {
- QUIC_BUG << "Failed to write version";
+ QUIC_BUG(quic_bug_10981_19) << "Failed to write version";
return false;
}
if (!writer.WriteLengthPrefixedConnectionId(destination_connection_id)) {
- QUIC_BUG << "Failed to write long header destination_connection_id";
+ QUIC_BUG(quic_bug_10981_20)
+ << "Failed to write long header destination_connection_id";
return false;
}
if (!writer.WriteLengthPrefixedConnectionId(source_connection_id)) {
- QUIC_BUG << "Failed to write long header source_connection_id";
+ QUIC_BUG(quic_bug_10981_21)
+ << "Failed to write long header source_connection_id";
return false;
}
} else {
if (!writer.WriteConnectionId(destination_connection_id)) {
- QUIC_BUG << "Failed to write short header destination_connection_id";
+ QUIC_BUG(quic_bug_10981_22)
+ << "Failed to write short header destination_connection_id";
return false;
}
}
absl::string_view payload = reader->ReadRemainingPayload();
if (!writer.WriteStringPiece(payload)) {
- QUIC_BUG << "Failed to write payload";
+ QUIC_BUG(quic_bug_10981_23) << "Failed to write payload";
return false;
}
return true;
@@ -520,12 +523,6 @@ bool MasqueCompressionEngine::DecompressDatagram(
return true;
}
-QuicDatagramFlowId MasqueCompressionEngine::GetNextFlowId() {
- const QuicDatagramFlowId next_flow_id = next_flow_id_;
- next_flow_id_ += 2;
- return next_flow_id;
-}
-
void MasqueCompressionEngine::UnregisterClientConnectionId(
QuicConnectionId client_connection_id) {
std::vector<QuicDatagramFlowId> flow_ids_to_remove;
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.h b/chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.h
index 96c59482b52..9bea618ae76 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.h
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.h
@@ -7,8 +7,8 @@
#include "absl/container/flat_hash_map.h"
#include "absl/strings/string_view.h"
+#include "quic/core/http/quic_spdy_session.h"
#include "quic/core/quic_connection_id.h"
-#include "quic/core/quic_session.h"
#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_containers.h"
#include "quic/platform/api/quic_export.h"
@@ -35,7 +35,7 @@ class QUIC_NO_EXPORT MasqueCompressionEngine {
public:
// Caller must ensure that |masque_session| has a lifetime longer than the
// newly constructed MasqueCompressionEngine.
- explicit MasqueCompressionEngine(QuicSession* masque_session);
+ explicit MasqueCompressionEngine(QuicSpdySession* masque_session);
// Disallow copy and assign.
MasqueCompressionEngine(const MasqueCompressionEngine&) = delete;
@@ -78,9 +78,6 @@ class QUIC_NO_EXPORT MasqueCompressionEngine {
bool validated = false;
};
- // Generates a new datagram flow ID.
- QuicDatagramFlowId GetNextFlowId();
-
// Finds or creates a new compression context to use during compression.
// |client_connection_id_present| and |server_connection_id_present| indicate
// whether the corresponding connection ID is present in the current packet.
@@ -117,9 +114,8 @@ class QUIC_NO_EXPORT MasqueCompressionEngine {
std::vector<char>* packet,
bool* version_present);
- QuicSession* masque_session_; // Unowned.
+ QuicSpdySession* masque_session_; // Unowned.
absl::flat_hash_map<QuicDatagramFlowId, MasqueCompressionContext> contexts_;
- QuicDatagramFlowId next_flow_id_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_dispatcher.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_dispatcher.cc
index 6edca628f4f..5729d5427f7 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_dispatcher.cc
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_dispatcher.cc
@@ -8,9 +8,11 @@
namespace quic {
MasqueDispatcher::MasqueDispatcher(
+ MasqueMode masque_mode,
const QuicConfig* config,
const QuicCryptoServerConfig* crypto_config,
QuicVersionManager* version_manager,
+ QuicEpollServer* epoll_server,
std::unique_ptr<QuicConnectionHelperInterface> helper,
std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
@@ -24,6 +26,8 @@ MasqueDispatcher::MasqueDispatcher(
std::move(alarm_factory),
masque_server_backend,
expected_server_connection_id_length),
+ masque_mode_(masque_mode),
+ epoll_server_(epoll_server),
masque_server_backend_(masque_server_backend) {}
std::unique_ptr<QuicSession> MasqueDispatcher::CreateQuicSession(
@@ -31,7 +35,8 @@ std::unique_ptr<QuicSession> MasqueDispatcher::CreateQuicSession(
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
absl::string_view /*alpn*/,
- const ParsedQuicVersion& version) {
+ const ParsedQuicVersion& version,
+ absl::string_view /*sni*/) {
// The MasqueServerSession takes ownership of |connection| below.
QuicConnection* connection =
new QuicConnection(connection_id, self_address, peer_address, helper(),
@@ -40,9 +45,9 @@ std::unique_ptr<QuicSession> MasqueDispatcher::CreateQuicSession(
ParsedQuicVersionVector{version});
auto session = std::make_unique<MasqueServerSession>(
- config(), GetSupportedVersions(), connection, this, this,
- session_helper(), crypto_config(), compressed_certs_cache(),
- masque_server_backend_);
+ masque_mode_, config(), GetSupportedVersions(), connection, this, this,
+ epoll_server_, session_helper(), crypto_config(),
+ compressed_certs_cache(), masque_server_backend_);
session->Initialize();
return session;
}
@@ -70,10 +75,11 @@ void MasqueDispatcher::RegisterClientConnectionId(
// Make sure we don't try to overwrite an existing registration with a
// different session.
- QUIC_BUG_IF(client_connection_id_registrations_.find(client_connection_id) !=
- client_connection_id_registrations_.end() &&
- client_connection_id_registrations_[client_connection_id] !=
- masque_server_session)
+ QUIC_BUG_IF(quic_bug_12013_1,
+ client_connection_id_registrations_.find(client_connection_id) !=
+ client_connection_id_registrations_.end() &&
+ client_connection_id_registrations_[client_connection_id] !=
+ masque_server_session)
<< "Overwriting existing registration for " << client_connection_id;
client_connection_id_registrations_[client_connection_id] =
masque_server_session;
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_dispatcher.h b/chromium/net/third_party/quiche/src/quic/masque/masque_dispatcher.h
index 2e0186c9a3d..368219e031a 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_dispatcher.h
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_dispatcher.h
@@ -8,6 +8,8 @@
#include "absl/container/flat_hash_map.h"
#include "quic/masque/masque_server_backend.h"
#include "quic/masque/masque_server_session.h"
+#include "quic/masque/masque_utils.h"
+#include "quic/platform/api/quic_epoll.h"
#include "quic/platform/api/quic_export.h"
#include "quic/tools/quic_simple_dispatcher.h"
@@ -19,9 +21,11 @@ class QUIC_NO_EXPORT MasqueDispatcher : public QuicSimpleDispatcher,
public MasqueServerSession::Visitor {
public:
explicit MasqueDispatcher(
+ MasqueMode masque_mode,
const QuicConfig* config,
const QuicCryptoServerConfig* crypto_config,
QuicVersionManager* version_manager,
+ QuicEpollServer* epoll_server,
std::unique_ptr<QuicConnectionHelperInterface> helper,
std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
@@ -38,7 +42,8 @@ class QUIC_NO_EXPORT MasqueDispatcher : public QuicSimpleDispatcher,
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
absl::string_view alpn,
- const ParsedQuicVersion& version) override;
+ const ParsedQuicVersion& version,
+ absl::string_view sni) override;
bool OnFailedToDispatchPacket(const ReceivedPacketInfo& packet_info) override;
@@ -51,6 +56,8 @@ class QUIC_NO_EXPORT MasqueDispatcher : public QuicSimpleDispatcher,
QuicConnectionId client_connection_id) override;
private:
+ MasqueMode masque_mode_;
+ QuicEpollServer* epoll_server_; // Unowned.
MasqueServerBackend* masque_server_backend_; // Unowned.
// Mapping from client connection IDs to server sessions, allows routing
// incoming packets to the right MASQUE connection.
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.cc
index 983a094f30a..3d557c3a073 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.cc
@@ -31,11 +31,19 @@ void MasqueEncapsulatedClientSession::ProcessPacket(
received_packet);
}
+void MasqueEncapsulatedClientSession::CloseConnection(
+ QuicErrorCode error,
+ const std::string& details,
+ ConnectionCloseBehavior connection_close_behavior) {
+ connection()->CloseConnection(error, details, connection_close_behavior);
+}
+
void MasqueEncapsulatedClientSession::OnConnectionClosed(
- const QuicConnectionCloseFrame& /*frame*/,
- ConnectionCloseSource /*source*/) {
+ const QuicConnectionCloseFrame& frame,
+ ConnectionCloseSource source) {
+ QuicSpdyClientSession::OnConnectionClosed(frame, source);
masque_client_session_->UnregisterConnectionId(
- connection()->client_connection_id());
+ connection()->client_connection_id(), this);
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.h b/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.h
index 570ccdb84d3..09521591898 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.h
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_client_session.h
@@ -44,6 +44,10 @@ class QUIC_NO_EXPORT MasqueEncapsulatedClientSession
// From MasqueClientSession::EncapsulatedClientSession.
void ProcessPacket(absl::string_view packet,
QuicSocketAddress server_address) override;
+ void CloseConnection(
+ QuicErrorCode error,
+ const std::string& details,
+ ConnectionCloseBehavior connection_close_behavior) override;
// From QuicSession.
void OnConnectionClosed(const QuicConnectionCloseFrame& frame,
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_epoll_client.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_epoll_client.cc
index 8fb938dbdc7..8891e4a0e41 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_epoll_client.cc
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_encapsulated_epoll_client.cc
@@ -30,8 +30,8 @@ class MasquePacketWriter : public QuicPacketWriter {
absl::string_view packet(buffer, buf_len);
client_->masque_client()->masque_client_session()->SendPacket(
client_->session()->connection()->client_connection_id(),
- client_->session()->connection()->connection_id(), packet,
- peer_address);
+ client_->session()->connection()->connection_id(), packet, peer_address,
+ client_->masque_encapsulated_client_session());
return WriteResult(WRITE_STATUS_OK, buf_len);
}
@@ -94,7 +94,7 @@ MasqueEncapsulatedEpollClient::MasqueEncapsulatedEpollClient(
MasqueEncapsulatedEpollClient::~MasqueEncapsulatedEpollClient() {
masque_client_->masque_client_session()->UnregisterConnectionId(
- client_connection_id_);
+ client_connection_id_, masque_encapsulated_client_session());
}
std::unique_ptr<QuicSession>
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.cc
index 1d77e557a64..5ad91cfd9ad 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.cc
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.cc
@@ -3,15 +3,16 @@
// found in the LICENSE file.
#include "quic/masque/masque_epoll_client.h"
+#include "absl/memory/memory.h"
#include "quic/masque/masque_client_session.h"
#include "quic/masque/masque_utils.h"
-#include "quic/platform/api/quic_ptr_util.h"
namespace quic {
MasqueEpollClient::MasqueEpollClient(
QuicSocketAddress server_address,
const QuicServerId& server_id,
+ MasqueMode masque_mode,
QuicEpollServer* epoll_server,
std::unique_ptr<ProofVerifier> proof_verifier,
const std::string& authority)
@@ -20,6 +21,7 @@ MasqueEpollClient::MasqueEpollClient(
MasqueSupportedVersions(),
epoll_server,
std::move(proof_verifier)),
+ masque_mode_(masque_mode),
authority_(authority) {}
std::unique_ptr<QuicSession> MasqueEpollClient::CreateQuicClientSession(
@@ -28,8 +30,8 @@ std::unique_ptr<QuicSession> MasqueEpollClient::CreateQuicClientSession(
QUIC_DLOG(INFO) << "Creating MASQUE session for "
<< connection->connection_id();
return std::make_unique<MasqueClientSession>(
- *config(), supported_versions, connection, server_id(), crypto_config(),
- push_promise_index(), this);
+ masque_mode_, *config(), supported_versions, connection, server_id(),
+ crypto_config(), push_promise_index(), this);
}
MasqueClientSession* MasqueEpollClient::masque_client_session() {
@@ -44,6 +46,7 @@ QuicConnectionId MasqueEpollClient::connection_id() {
std::unique_ptr<MasqueEpollClient> MasqueEpollClient::Create(
const std::string& host,
int port,
+ MasqueMode masque_mode,
QuicEpollServer* epoll_server,
std::unique_ptr<ProofVerifier> proof_verifier) {
// Build the masque_client, and try to connect.
@@ -53,11 +56,11 @@ std::unique_ptr<MasqueEpollClient> MasqueEpollClient::Create(
return nullptr;
}
QuicServerId server_id(host, port);
- // Use QuicWrapUnique(new MasqueEpollClient(...)) instead of
+ // Use absl::WrapUnique(new MasqueEpollClient(...)) instead of
// std::make_unique<MasqueEpollClient>(...) because the constructor for
// MasqueEpollClient is private and therefore not accessible from make_unique.
- auto masque_client = QuicWrapUnique(new MasqueEpollClient(
- addr, server_id, epoll_server, std::move(proof_verifier),
+ auto masque_client = absl::WrapUnique(new MasqueEpollClient(
+ addr, server_id, masque_mode, epoll_server, std::move(proof_verifier),
absl::StrCat(host, ":", port)));
if (masque_client == nullptr) {
@@ -78,33 +81,35 @@ std::unique_ptr<MasqueEpollClient> MasqueEpollClient::Create(
return nullptr;
}
- std::string body = "foo";
-
- // Construct a GET or POST request for supplied URL.
- spdy::Http2HeaderBlock header_block;
- header_block[":method"] = "POST";
- header_block[":scheme"] = "https";
- header_block[":authority"] = masque_client->authority_;
- header_block[":path"] = "/.well-known/masque/init";
-
- // Make sure to store the response, for later output.
- masque_client->set_store_response(true);
-
- // Send the MASQUE init command.
- masque_client->SendRequestAndWaitForResponse(header_block, body,
- /*fin=*/true);
-
- if (!masque_client->connected()) {
- QUIC_LOG(ERROR) << "MASQUE init request caused connection failure. Error: "
- << QuicErrorCodeToString(masque_client->session()->error());
- return nullptr;
- }
-
- const int response_code = masque_client->latest_response_code();
- if (response_code != 200) {
- QUIC_LOG(ERROR) << "MASQUE init request failed with HTTP response code "
- << response_code;
- return nullptr;
+ if (masque_client->masque_mode() == MasqueMode::kLegacy) {
+ // Construct the legacy mode init request.
+ spdy::Http2HeaderBlock header_block;
+ header_block[":method"] = "POST";
+ header_block[":scheme"] = "https";
+ header_block[":authority"] = masque_client->authority_;
+ header_block[":path"] = "/.well-known/masque/init";
+ std::string body = "foo";
+
+ // Make sure to store the response, for later output.
+ masque_client->set_store_response(true);
+
+ // Send the MASQUE init command.
+ masque_client->SendRequestAndWaitForResponse(header_block, body,
+ /*fin=*/true);
+
+ if (!masque_client->connected()) {
+ QUIC_LOG(ERROR)
+ << "MASQUE init request caused connection failure. Error: "
+ << QuicErrorCodeToString(masque_client->session()->error());
+ return nullptr;
+ }
+
+ const int response_code = masque_client->latest_response_code();
+ if (response_code != 200) {
+ QUIC_LOG(ERROR) << "MASQUE init request failed with HTTP response code "
+ << response_code;
+ return nullptr;
+ }
}
return masque_client;
}
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.h b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.h
index 345c18c7dee..1db161f5aaa 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.h
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.h
@@ -6,6 +6,7 @@
#define QUICHE_QUIC_MASQUE_MASQUE_EPOLL_CLIENT_H_
#include "quic/masque/masque_client_session.h"
+#include "quic/masque/masque_utils.h"
#include "quic/platform/api/quic_export.h"
#include "quic/tools/quic_client.h"
@@ -19,6 +20,7 @@ class QUIC_NO_EXPORT MasqueEpollClient : public QuicClient,
static std::unique_ptr<MasqueEpollClient> Create(
const std::string& host,
int port,
+ MasqueMode masque_mode,
QuicEpollServer* epoll_server,
std::unique_ptr<ProofVerifier> proof_verifier);
@@ -37,10 +39,13 @@ class QUIC_NO_EXPORT MasqueEpollClient : public QuicClient,
void UnregisterClientConnectionId(
QuicConnectionId client_connection_id) override;
+ MasqueMode masque_mode() const { return masque_mode_; }
+
private:
// Constructor is private, use Create() instead.
MasqueEpollClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
+ MasqueMode masque_mode,
QuicEpollServer* epoll_server,
std::unique_ptr<ProofVerifier> proof_verifier,
const std::string& authority);
@@ -49,6 +54,7 @@ class QUIC_NO_EXPORT MasqueEpollClient : public QuicClient,
MasqueEpollClient(const MasqueEpollClient&) = delete;
MasqueEpollClient& operator=(const MasqueEpollClient&) = delete;
+ MasqueMode masque_mode_;
std::string authority_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_server.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_server.cc
index 34769a37bf7..e8a0850f0d8 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_server.cc
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_server.cc
@@ -11,15 +11,18 @@
namespace quic {
-MasqueEpollServer::MasqueEpollServer(MasqueServerBackend* masque_server_backend)
+MasqueEpollServer::MasqueEpollServer(MasqueMode masque_mode,
+ MasqueServerBackend* masque_server_backend)
: QuicServer(CreateDefaultProofSource(),
masque_server_backend,
MasqueSupportedVersions()),
+ masque_mode_(masque_mode),
masque_server_backend_(masque_server_backend) {}
QuicDispatcher* MasqueEpollServer::CreateQuicDispatcher() {
return new MasqueDispatcher(
- &config(), &crypto_config(), version_manager(),
+ masque_mode_, &config(), &crypto_config(), version_manager(),
+ epoll_server(),
std::make_unique<QuicEpollConnectionHelper>(epoll_server(),
QuicAllocator::BUFFER_POOL),
std::make_unique<QuicSimpleCryptoServerStreamHelper>(),
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_server.h b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_server.h
index 57eab6a1f84..88161ee37cf 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_server.h
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_server.h
@@ -6,6 +6,7 @@
#define QUICHE_QUIC_MASQUE_MASQUE_EPOLL_SERVER_H_
#include "quic/masque/masque_server_backend.h"
+#include "quic/masque/masque_utils.h"
#include "quic/platform/api/quic_export.h"
#include "quic/tools/quic_server.h"
@@ -14,7 +15,8 @@ namespace quic {
// QUIC server that implements MASQUE.
class QUIC_NO_EXPORT MasqueEpollServer : public QuicServer {
public:
- explicit MasqueEpollServer(MasqueServerBackend* masque_server_backend);
+ explicit MasqueEpollServer(MasqueMode masque_mode,
+ MasqueServerBackend* masque_server_backend);
// Disallow copy and assign.
MasqueEpollServer(const MasqueEpollServer&) = delete;
@@ -24,6 +26,7 @@ class QUIC_NO_EXPORT MasqueEpollServer : public QuicServer {
QuicDispatcher* CreateQuicDispatcher() override;
private:
+ MasqueMode masque_mode_;
MasqueServerBackend* masque_server_backend_; // Unowned.
};
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 19948198f33..112f3053180 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
@@ -8,20 +8,10 @@
namespace quic {
-namespace {
-
-std::string GetRequestHandlerKey(
- const QuicSimpleServerBackend::RequestHandler* request_handler) {
- return absl::StrCat(request_handler->connection_id().ToString(), "_",
- request_handler->stream_id(), "_",
- request_handler->peer_host());
-}
-
-} // namespace
-
-MasqueServerBackend::MasqueServerBackend(const std::string& server_authority,
+MasqueServerBackend::MasqueServerBackend(MasqueMode masque_mode,
+ const std::string& server_authority,
const std::string& cache_directory)
- : server_authority_(server_authority) {
+ : masque_mode_(masque_mode), server_authority_(server_authority) {
if (!cache_directory.empty()) {
QuicMemoryCacheBackend::InitializeBackend(cache_directory);
}
@@ -31,28 +21,40 @@ bool MasqueServerBackend::MaybeHandleMasqueRequest(
const spdy::Http2HeaderBlock& request_headers,
const std::string& request_body,
QuicSimpleServerBackend::RequestHandler* request_handler) {
- auto path_pair = request_headers.find(":path");
auto method_pair = request_headers.find(":method");
- auto scheme_pair = request_headers.find(":scheme");
- if (path_pair == request_headers.end() ||
- method_pair == request_headers.end() ||
- scheme_pair == request_headers.end()) {
- // This request is missing required headers.
+ if (method_pair == request_headers.end()) {
+ // Request is missing a method.
return false;
}
- absl::string_view path = path_pair->second;
- absl::string_view scheme = scheme_pair->second;
absl::string_view method = method_pair->second;
- if (scheme != "https" || method != "POST" || request_body.empty()) {
- // MASQUE requests MUST be a non-empty https POST.
- return false;
- }
+ std::string masque_path = "";
+ if (masque_mode_ == MasqueMode::kLegacy) {
+ auto path_pair = request_headers.find(":path");
+ auto scheme_pair = request_headers.find(":scheme");
+ if (path_pair == request_headers.end() ||
+ scheme_pair == request_headers.end()) {
+ // This request is missing required headers.
+ return false;
+ }
+ absl::string_view path = path_pair->second;
+ absl::string_view scheme = scheme_pair->second;
+ if (scheme != "https" || method != "POST" || request_body.empty()) {
+ // MASQUE requests MUST be a non-empty https POST.
+ return false;
+ }
- if (path.rfind("/.well-known/masque/", 0) != 0) {
- // This request is not a MASQUE path.
- return false;
+ if (path.rfind("/.well-known/masque/", 0) != 0) {
+ // This request is not a MASQUE path.
+ return false;
+ }
+ masque_path = std::string(path.substr(sizeof("/.well-known/masque/") - 1));
+ } else {
+ QUICHE_DCHECK_EQ(masque_mode_, MasqueMode::kOpen);
+ if (method != "CONNECT-UDP") {
+ // This is not a MASQUE request.
+ return false;
+ }
}
- std::string masque_path(path.substr(sizeof("/.well-known/masque/") - 1));
if (!server_authority_.empty()) {
auto authority_pair = request_headers.find(":authority");
@@ -67,34 +69,29 @@ bool MasqueServerBackend::MaybeHandleMasqueRequest(
}
}
- auto backend_client_pair =
- backend_clients_.find(request_handler->connection_id());
- if (backend_client_pair == backend_clients_.end()) {
+ auto it = backend_client_states_.find(request_handler->connection_id());
+ if (it == backend_client_states_.end()) {
QUIC_LOG(ERROR) << "Could not find backend client for "
- << GetRequestHandlerKey(request_handler) << " "
<< masque_path << request_headers.DebugString();
return false;
}
- BackendClient* backend_client = backend_client_pair->second;
+ BackendClient* backend_client = it->second.backend_client;
std::unique_ptr<QuicBackendResponse> response =
backend_client->HandleMasqueRequest(masque_path, request_headers,
request_body, request_handler);
if (response == nullptr) {
QUIC_LOG(ERROR) << "Backend client did not process request for "
- << GetRequestHandlerKey(request_handler) << " "
<< masque_path << request_headers.DebugString();
return false;
}
QUIC_DLOG(INFO) << "Sending MASQUE response for "
- << GetRequestHandlerKey(request_handler) << " " << masque_path
<< request_headers.DebugString();
request_handler->OnResponseBackendComplete(response.get(), {});
- active_response_map_[GetRequestHandlerKey(request_handler)] =
- std::move(response);
+ it->second.responses.emplace_back(std::move(response));
return true;
}
@@ -109,7 +106,6 @@ void MasqueServerBackend::FetchResponseFromBackend(
return;
}
QUIC_DLOG(INFO) << "Fetching non-MASQUE response for "
- << GetRequestHandlerKey(request_handler)
<< request_headers.DebugString();
QuicMemoryCacheBackend::FetchResponseFromBackend(
request_headers, request_body, request_handler);
@@ -117,23 +113,23 @@ void MasqueServerBackend::FetchResponseFromBackend(
void MasqueServerBackend::CloseBackendResponseStream(
QuicSimpleServerBackend::RequestHandler* request_handler) {
- QUIC_DLOG(INFO) << "Closing response stream for "
- << GetRequestHandlerKey(request_handler);
- active_response_map_.erase(GetRequestHandlerKey(request_handler));
+ QUIC_DLOG(INFO) << "Closing response stream";
QuicMemoryCacheBackend::CloseBackendResponseStream(request_handler);
}
void MasqueServerBackend::RegisterBackendClient(QuicConnectionId connection_id,
BackendClient* backend_client) {
- QUIC_BUG_IF(backend_clients_.find(connection_id) != backend_clients_.end())
- << connection_id << " already in backend clients map";
- backend_clients_[connection_id] = backend_client;
QUIC_DLOG(INFO) << "Registering backend client for " << connection_id;
+ QUIC_BUG_IF(quic_bug_12005_1, backend_client_states_.find(connection_id) !=
+ backend_client_states_.end())
+ << connection_id << " already in backend clients map";
+ backend_client_states_[connection_id] =
+ BackendClientState{backend_client, {}};
}
void MasqueServerBackend::RemoveBackendClient(QuicConnectionId connection_id) {
- backend_clients_.erase(connection_id);
QUIC_DLOG(INFO) << "Removing backend client for " << connection_id;
+ backend_client_states_.erase(connection_id);
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_server_backend.h b/chromium/net/third_party/quiche/src/quic/masque/masque_server_backend.h
index 180935917e5..4f0e10d7421 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_server_backend.h
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_server_backend.h
@@ -6,6 +6,7 @@
#define QUICHE_QUIC_MASQUE_MASQUE_SERVER_BACKEND_H_
#include "absl/container/flat_hash_map.h"
+#include "quic/masque/masque_utils.h"
#include "quic/platform/api/quic_export.h"
#include "quic/tools/quic_memory_cache_backend.h"
@@ -27,7 +28,8 @@ class QUIC_NO_EXPORT MasqueServerBackend : public QuicMemoryCacheBackend {
virtual ~BackendClient() = default;
};
- explicit MasqueServerBackend(const std::string& server_authority,
+ explicit MasqueServerBackend(MasqueMode masque_mode,
+ const std::string& server_authority,
const std::string& cache_directory);
// Disallow copy and assign.
@@ -57,11 +59,16 @@ class QUIC_NO_EXPORT MasqueServerBackend : public QuicMemoryCacheBackend {
const std::string& request_body,
QuicSimpleServerBackend::RequestHandler* request_handler);
+ MasqueMode masque_mode_;
std::string server_authority_;
- absl::flat_hash_map<std::string, std::unique_ptr<QuicBackendResponse>>
- active_response_map_;
- absl::flat_hash_map<QuicConnectionId, BackendClient*, QuicConnectionIdHash>
- backend_clients_;
+
+ struct QUIC_NO_EXPORT BackendClientState {
+ BackendClient* backend_client;
+ std::vector<std::unique_ptr<QuicBackendResponse>> responses;
+ };
+ absl::
+ flat_hash_map<QuicConnectionId, BackendClientState, QuicConnectionIdHash>
+ backend_client_states_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_server_bin.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_server_bin.cc
index b25bf834ed3..d5a5d9f7d36 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_server_bin.cc
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_server_bin.cc
@@ -14,6 +14,7 @@
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_socket_address.h"
+#include "quic/platform/api/quic_system_event_loop.h"
DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t,
port,
@@ -35,7 +36,14 @@ DEFINE_QUIC_COMMAND_LINE_FLAG(
"Specifies the authority over which the server will accept MASQUE "
"requests. Defaults to empty which allows all authorities.");
+DEFINE_QUIC_COMMAND_LINE_FLAG(std::string,
+ masque_mode,
+ "",
+ "Allows setting MASQUE mode, valid values are "
+ "open and legacy. Defaults to open.");
+
int main(int argc, char* argv[]) {
+ QuicSystemEventLoop event_loop("masque_server");
const char* usage = "Usage: masque_server [options]";
std::vector<std::string> non_option_args =
quic::QuicParseCommandLineFlags(usage, argc, argv);
@@ -44,17 +52,30 @@ int main(int argc, char* argv[]) {
return 0;
}
+ SetQuicReloadableFlag(quic_h3_datagram, true);
+
+ quic::MasqueMode masque_mode = quic::MasqueMode::kOpen;
+ std::string mode_string = GetQuicFlag(FLAGS_masque_mode);
+ if (mode_string == "legacy") {
+ masque_mode = quic::MasqueMode::kLegacy;
+ } else if (!mode_string.empty() && mode_string != "open") {
+ std::cerr << "Invalid masque_mode \"" << mode_string << "\"" << std::endl;
+ return 1;
+ }
+
auto backend = std::make_unique<quic::MasqueServerBackend>(
- GetQuicFlag(FLAGS_server_authority), GetQuicFlag(FLAGS_cache_dir));
+ masque_mode, GetQuicFlag(FLAGS_server_authority),
+ GetQuicFlag(FLAGS_cache_dir));
- auto server = std::make_unique<quic::MasqueEpollServer>(backend.get());
+ auto server =
+ std::make_unique<quic::MasqueEpollServer>(masque_mode, backend.get());
if (!server->CreateUDPSocketAndListen(quic::QuicSocketAddress(
quic::QuicIpAddress::Any6(), GetQuicFlag(FLAGS_port)))) {
return 1;
}
- std::cerr << "Started MASQUE server" << std::endl;
+ std::cerr << "Started " << masque_mode << " MASQUE server" << std::endl;
server->HandleEventsForever();
return 0;
}
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.cc
index 228444aacbb..036c75fb95c 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
@@ -4,14 +4,82 @@
#include "quic/masque/masque_server_session.h"
+#include <netdb.h>
+
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "quic/core/http/spdy_utils.h"
+#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 {
+namespace {
+// RAII wrapper for QuicUdpSocketFd.
+class FdWrapper {
+ public:
+ // Takes ownership of |fd| and closes the file descriptor on destruction.
+ explicit FdWrapper(int address_family) {
+ QuicUdpSocketApi socket_api;
+ fd_ =
+ socket_api.Create(address_family,
+ /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
+ /*send_buffer_size =*/kDefaultSocketReceiveBuffer);
+ }
+
+ ~FdWrapper() {
+ if (fd_ == kQuicInvalidSocketFd) {
+ return;
+ }
+ QuicUdpSocketApi socket_api;
+ socket_api.Destroy(fd_);
+ }
+
+ // Hands ownership of the file descriptor to the caller.
+ QuicUdpSocketFd extract_fd() {
+ QuicUdpSocketFd fd = fd_;
+ fd_ = kQuicInvalidSocketFd;
+ return fd;
+ }
+
+ // Keeps ownership of the file descriptor.
+ QuicUdpSocketFd fd() { return fd_; }
+
+ // Disallow copy and move.
+ FdWrapper(const FdWrapper&) = delete;
+ FdWrapper(FdWrapper&&) = delete;
+ FdWrapper& operator=(const FdWrapper&) = delete;
+ FdWrapper& operator=(FdWrapper&&) = delete;
+
+ private:
+ QuicUdpSocketFd fd_;
+};
+
+std::unique_ptr<QuicBackendResponse> CreateBackendErrorResponse(
+ absl::string_view status,
+ absl::string_view error_details) {
+ spdy::Http2HeaderBlock response_headers;
+ response_headers[":status"] = status;
+ response_headers["masque-debug-info"] = error_details;
+ auto response = std::make_unique<QuicBackendResponse>();
+ response->set_response_type(QuicBackendResponse::REGULAR_RESPONSE);
+ response->set_headers(std::move(response_headers));
+ return response;
+}
+
+} // namespace
+
MasqueServerSession::MasqueServerSession(
+ MasqueMode masque_mode,
const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
QuicConnection* connection,
QuicSession::Visitor* visitor,
Visitor* owner,
+ QuicEpollServer* epoll_server,
QuicCryptoServerStreamBase::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
@@ -26,41 +94,54 @@ MasqueServerSession::MasqueServerSession(
masque_server_backend),
masque_server_backend_(masque_server_backend),
owner_(owner),
- compression_engine_(this) {
+ epoll_server_(epoll_server),
+ compression_engine_(this),
+ masque_mode_(masque_mode) {
+ // Artificially increase the max packet length to 1350 to ensure we can fit
+ // QUIC packets inside DATAGRAM frames.
+ // TODO(b/181606597) Remove this workaround once we use PMTUD.
+ connection->SetMaxPacketLength(kDefaultMaxPacketSize);
+
masque_server_backend_->RegisterBackendClient(connection_id(), this);
+ QUICHE_DCHECK_NE(epoll_server_, nullptr);
}
void MasqueServerSession::OnMessageReceived(absl::string_view message) {
- QUIC_DVLOG(1) << "Received DATAGRAM frame of length " << message.length();
-
- QuicConnectionId client_connection_id, server_connection_id;
- QuicSocketAddress server_address;
- std::vector<char> packet;
- bool version_present;
- if (!compression_engine_.DecompressDatagram(
- message, &client_connection_id, &server_connection_id,
- &server_address, &packet, &version_present)) {
- return;
- }
+ if (masque_mode_ == MasqueMode::kLegacy) {
+ QUIC_DVLOG(1) << "Received DATAGRAM frame of length " << message.length();
+ QuicConnectionId client_connection_id, server_connection_id;
+ QuicSocketAddress target_server_address;
+ std::vector<char> packet;
+ bool version_present;
+ if (!compression_engine_.DecompressDatagram(
+ message, &client_connection_id, &server_connection_id,
+ &target_server_address, &packet, &version_present)) {
+ return;
+ }
- QUIC_DVLOG(1) << "Received packet of length " << packet.size() << " for "
- << server_address << " client " << client_connection_id;
+ QUIC_DVLOG(1) << "Received packet of length " << packet.size() << " for "
+ << target_server_address << " client "
+ << client_connection_id;
- if (version_present) {
- if (client_connection_id.length() != kQuicDefaultConnectionIdLength) {
- QUIC_DLOG(ERROR)
- << "Dropping long header with invalid client_connection_id "
- << client_connection_id;
- return;
+ if (version_present) {
+ if (client_connection_id.length() != kQuicDefaultConnectionIdLength) {
+ QUIC_DLOG(ERROR)
+ << "Dropping long header with invalid client_connection_id "
+ << client_connection_id;
+ return;
+ }
+ owner_->RegisterClientConnectionId(client_connection_id, this);
}
- owner_->RegisterClientConnectionId(client_connection_id, this);
- }
- WriteResult write_result = connection()->writer()->WritePacket(
- packet.data(), packet.size(), connection()->self_address().host(),
- server_address, nullptr);
- QUIC_DVLOG(1) << "Got " << write_result << " for " << packet.size()
- << " bytes to " << server_address;
+ WriteResult write_result = connection()->writer()->WritePacket(
+ packet.data(), packet.size(), connection()->self_address().host(),
+ target_server_address, nullptr);
+ QUIC_DVLOG(1) << "Got " << write_result << " for " << packet.size()
+ << " bytes to " << target_server_address;
+ return;
+ }
+ QUICHE_DCHECK_EQ(masque_mode_, MasqueMode::kOpen);
+ QuicSpdySession::OnMessageReceived(message);
}
void MasqueServerSession::OnMessageAcked(QuicMessageId message_id,
@@ -73,17 +154,131 @@ void MasqueServerSession::OnMessageLost(QuicMessageId message_id) {
}
void MasqueServerSession::OnConnectionClosed(
- const QuicConnectionCloseFrame& /*frame*/,
- ConnectionCloseSource /*source*/) {
+ const QuicConnectionCloseFrame& frame,
+ ConnectionCloseSource source) {
+ QuicSimpleServerSession::OnConnectionClosed(frame, source);
QUIC_DLOG(INFO) << "Closing connection for " << connection_id();
masque_server_backend_->RemoveBackendClient(connection_id());
+ // Clearing this state will close all sockets.
+ connect_udp_server_states_.clear();
+}
+
+void MasqueServerSession::OnStreamClosed(QuicStreamId stream_id) {
+ connect_udp_server_states_.remove_if(
+ [stream_id](const ConnectUdpServerState& connect_udp) {
+ return connect_udp.stream_id() == stream_id;
+ });
+
+ QuicSimpleServerSession::OnStreamClosed(stream_id);
}
std::unique_ptr<QuicBackendResponse> MasqueServerSession::HandleMasqueRequest(
const std::string& masque_path,
- const spdy::Http2HeaderBlock& /*request_headers*/,
+ const spdy::Http2HeaderBlock& request_headers,
const std::string& request_body,
- QuicSimpleServerBackend::RequestHandler* /*request_handler*/) {
+ QuicSimpleServerBackend::RequestHandler* request_handler) {
+ if (masque_mode_ != MasqueMode::kLegacy) {
+ auto path_pair = request_headers.find(":path");
+ auto scheme_pair = request_headers.find(":scheme");
+ auto method_pair = request_headers.find(":method");
+ auto authority_pair = request_headers.find(":authority");
+ if (path_pair == request_headers.end()) {
+ QUIC_DLOG(ERROR) << "MASQUE request is missing :path";
+ return CreateBackendErrorResponse("400", "Missing :path");
+ }
+ if (scheme_pair == request_headers.end()) {
+ QUIC_DLOG(ERROR) << "MASQUE request is missing :scheme";
+ return CreateBackendErrorResponse("400", "Missing :scheme");
+ }
+ if (method_pair == request_headers.end()) {
+ QUIC_DLOG(ERROR) << "MASQUE request is missing :method";
+ return CreateBackendErrorResponse("400", "Missing :method");
+ }
+ if (authority_pair == request_headers.end()) {
+ QUIC_DLOG(ERROR) << "MASQUE request is missing :authority";
+ return CreateBackendErrorResponse("400", "Missing :authority");
+ }
+ absl::string_view path = path_pair->second;
+ absl::string_view scheme = scheme_pair->second;
+ absl::string_view method = method_pair->second;
+ absl::string_view authority = authority_pair->second;
+ if (path.empty()) {
+ QUIC_DLOG(ERROR) << "MASQUE request with empty path";
+ return CreateBackendErrorResponse("400", "Empty path");
+ }
+ if (scheme.empty()) {
+ return CreateBackendErrorResponse("400", "Empty scheme");
+ return nullptr;
+ }
+ if (method != "CONNECT-UDP") {
+ QUIC_DLOG(ERROR) << "MASQUE request with bad method \"" << method << "\"";
+ return CreateBackendErrorResponse("400", "Bad method");
+ }
+ absl::optional<QuicDatagramFlowId> flow_id =
+ SpdyUtils::ParseDatagramFlowIdHeader(request_headers);
+ if (!flow_id.has_value()) {
+ QUIC_DLOG(ERROR)
+ << "MASQUE request with bad or missing DatagramFlowId header";
+ return CreateBackendErrorResponse("400",
+ "Bad or missing DatagramFlowId header");
+ }
+ QuicUrl url(absl::StrCat("https://", authority));
+ if (!url.IsValid() || url.PathParamsQuery() != "/") {
+ QUIC_DLOG(ERROR) << "MASQUE request with bad authority \"" << authority
+ << "\"";
+ return CreateBackendErrorResponse("400", "Bad authority");
+ }
+
+ std::string port = absl::StrCat(url.port());
+ addrinfo hint = {};
+ hint.ai_protocol = IPPROTO_UDP;
+
+ addrinfo* info_list = nullptr;
+ int result =
+ getaddrinfo(url.host().c_str(), port.c_str(), &hint, &info_list);
+ if (result != 0) {
+ QUIC_DLOG(ERROR) << "Failed to resolve " << authority << ": "
+ << gai_strerror(result);
+ return CreateBackendErrorResponse("500", "DNS resolution failed");
+ }
+
+ QUICHE_CHECK_NE(info_list, nullptr);
+ std::unique_ptr<addrinfo, void (*)(addrinfo*)> info_list_owned(
+ info_list, freeaddrinfo);
+ QuicSocketAddress target_server_address(info_list->ai_addr,
+ info_list->ai_addrlen);
+ QUIC_DLOG(INFO) << "Got CONNECT_UDP request flow_id=" << *flow_id
+ << " target_server_address=\"" << target_server_address
+ << "\"";
+
+ FdWrapper fd_wrapper(target_server_address.host().AddressFamilyToInt());
+ if (fd_wrapper.fd() == kQuicInvalidSocketFd) {
+ QUIC_DLOG(ERROR) << "Socket creation failed";
+ return CreateBackendErrorResponse("500", "Socket creation failed");
+ }
+ QuicSocketAddress any_v6_address(QuicIpAddress::Any6(), 0);
+ QuicUdpSocketApi socket_api;
+ if (!socket_api.Bind(fd_wrapper.fd(), any_v6_address)) {
+ QUIC_DLOG(ERROR) << "Socket bind failed";
+ return CreateBackendErrorResponse("500", "Socket bind failed");
+ }
+ epoll_server_->RegisterFDForRead(fd_wrapper.fd(), this);
+
+ connect_udp_server_states_.emplace_back(ConnectUdpServerState(
+ *flow_id, request_handler->stream_id(), target_server_address,
+ fd_wrapper.extract_fd(), this));
+
+ spdy::Http2HeaderBlock response_headers;
+ response_headers[":status"] = "200";
+ SpdyUtils::AddDatagramFlowIdHeader(&response_headers, *flow_id);
+ auto response = std::make_unique<QuicBackendResponse>();
+ response->set_response_type(QuicBackendResponse::INCOMPLETE_RESPONSE);
+ response->set_headers(std::move(response_headers));
+ response->set_body("");
+
+ return response;
+ }
+
QUIC_DLOG(INFO) << "MasqueServerSession handling MASQUE request";
if (masque_path == "init") {
@@ -120,9 +315,177 @@ std::unique_ptr<QuicBackendResponse> MasqueServerSession::HandleMasqueRequest(
void MasqueServerSession::HandlePacketFromServer(
const ReceivedPacketInfo& packet_info) {
QUIC_DVLOG(1) << "MasqueServerSession received " << packet_info;
- compression_engine_.CompressAndSendPacket(
- packet_info.packet.AsStringPiece(), packet_info.destination_connection_id,
- packet_info.source_connection_id, packet_info.peer_address);
+ if (masque_mode_ == MasqueMode::kLegacy) {
+ compression_engine_.CompressAndSendPacket(
+ packet_info.packet.AsStringPiece(),
+ packet_info.destination_connection_id, packet_info.source_connection_id,
+ packet_info.peer_address);
+ return;
+ }
+ QUIC_LOG(ERROR) << "Ignoring packet from server in " << masque_mode_
+ << " mode";
+}
+
+void MasqueServerSession::OnRegistration(QuicEpollServer* /*eps*/,
+ QuicUdpSocketFd fd,
+ int event_mask) {
+ QUIC_DVLOG(1) << "OnRegistration " << fd << " event_mask " << event_mask;
+}
+
+void MasqueServerSession::OnModification(QuicUdpSocketFd fd, int event_mask) {
+ QUIC_DVLOG(1) << "OnModification " << fd << " event_mask " << event_mask;
+}
+
+void MasqueServerSession::OnEvent(QuicUdpSocketFd fd, QuicEpollEvent* event) {
+ if ((event->in_events & EPOLLIN) == 0) {
+ QUIC_DVLOG(1) << "Ignoring OnEvent fd " << fd << " event mask "
+ << event->in_events;
+ return;
+ }
+ auto it = absl::c_find_if(connect_udp_server_states_,
+ [fd](const ConnectUdpServerState& connect_udp) {
+ return connect_udp.fd() == fd;
+ });
+ if (it == connect_udp_server_states_.end()) {
+ QUIC_BUG(quic_bug_10974_1) << "Got unexpected event mask "
+ << event->in_events << " on unknown fd " << fd;
+ return;
+ }
+ QuicDatagramFlowId flow_id = it->flow_id();
+ QuicSocketAddress expected_target_server_address =
+ it->target_server_address();
+ QUICHE_DCHECK(expected_target_server_address.IsInitialized());
+ QUIC_DVLOG(1) << "Received readable event on fd " << fd << " (mask "
+ << event->in_events << ") flow_id " << flow_id << " server "
+ << expected_target_server_address;
+ QuicUdpSocketApi socket_api;
+ BitMask64 packet_info_interested(QuicUdpPacketInfoBit::PEER_ADDRESS);
+ char packet_buffer[kMaxIncomingPacketSize];
+ char control_buffer[kDefaultUdpPacketControlBufferSize];
+ while (true) {
+ QuicUdpSocketApi::ReadPacketResult read_result;
+ read_result.packet_buffer = {packet_buffer, sizeof(packet_buffer)};
+ read_result.control_buffer = {control_buffer, sizeof(control_buffer)};
+ socket_api.ReadPacket(fd, packet_info_interested, &read_result);
+ if (!read_result.ok) {
+ // Most likely there is nothing left to read, break out of read loop.
+ break;
+ }
+ if (!read_result.packet_info.HasValue(QuicUdpPacketInfoBit::PEER_ADDRESS)) {
+ QUIC_BUG(quic_bug_10974_2)
+ << "Missing peer address when reading from fd " << fd;
+ continue;
+ }
+ if (read_result.packet_info.peer_address() !=
+ expected_target_server_address) {
+ QUIC_DLOG(ERROR) << "Ignoring UDP packet on fd " << fd
+ << " from unexpected server address "
+ << read_result.packet_info.peer_address()
+ << " (expected " << expected_target_server_address
+ << ")";
+ continue;
+ }
+ if (!connection()->connected()) {
+ QUIC_BUG(quic_bug_10974_3)
+ << "Unexpected incoming UDP packet on fd " << fd << " from "
+ << expected_target_server_address
+ << " because MASQUE connection is closed";
+ return;
+ }
+ // The packet is valid, send it to the client in a DATAGRAM frame.
+ MessageStatus message_status = SendHttp3Datagram(
+ flow_id, absl::string_view(read_result.packet_buffer.buffer,
+ read_result.packet_buffer.buffer_len));
+ QUIC_DVLOG(1) << "Sent UDP packet from " << expected_target_server_address
+ << " of length " << read_result.packet_buffer.buffer_len
+ << " with flow ID " << flow_id << " and got message status "
+ << MessageStatusToString(message_status);
+ }
+}
+
+void MasqueServerSession::OnUnregistration(QuicUdpSocketFd fd, bool replaced) {
+ QUIC_DVLOG(1) << "OnUnregistration " << fd << " " << (replaced ? "" : "!")
+ << " replaced";
+}
+
+void MasqueServerSession::OnShutdown(QuicEpollServer* /*eps*/,
+ QuicUdpSocketFd fd) {
+ QUIC_DVLOG(1) << "OnShutdown " << fd;
+}
+
+std::string MasqueServerSession::Name() const {
+ return std::string("MasqueServerSession-") + connection_id().ToString();
+}
+
+MasqueServerSession::ConnectUdpServerState::ConnectUdpServerState(
+ QuicDatagramFlowId flow_id,
+ QuicStreamId stream_id,
+ const QuicSocketAddress& target_server_address,
+ QuicUdpSocketFd fd,
+ MasqueServerSession* masque_session)
+ : flow_id_(flow_id),
+ stream_id_(stream_id),
+ target_server_address_(target_server_address),
+ fd_(fd),
+ masque_session_(masque_session) {
+ QUICHE_DCHECK_NE(fd_, kQuicInvalidSocketFd);
+ QUICHE_DCHECK_NE(masque_session_, nullptr);
+ masque_session_->RegisterHttp3FlowId(this->flow_id(), this);
+}
+
+MasqueServerSession::ConnectUdpServerState::~ConnectUdpServerState() {
+ if (flow_id_.has_value()) {
+ masque_session_->UnregisterHttp3FlowId(flow_id());
+ }
+ if (fd_ == kQuicInvalidSocketFd) {
+ return;
+ }
+ QuicUdpSocketApi socket_api;
+ QUIC_DLOG(INFO) << "Closing fd " << fd_;
+ masque_session_->epoll_server()->UnregisterFD(fd_);
+ socket_api.Destroy(fd_);
+}
+
+MasqueServerSession::ConnectUdpServerState::ConnectUdpServerState(
+ MasqueServerSession::ConnectUdpServerState&& other) {
+ fd_ = kQuicInvalidSocketFd;
+ *this = std::move(other);
+}
+
+MasqueServerSession::ConnectUdpServerState&
+MasqueServerSession::ConnectUdpServerState::operator=(
+ MasqueServerSession::ConnectUdpServerState&& other) {
+ if (fd_ != kQuicInvalidSocketFd) {
+ QuicUdpSocketApi socket_api;
+ QUIC_DLOG(INFO) << "Closing fd " << fd_;
+ masque_session_->epoll_server()->UnregisterFD(fd_);
+ socket_api.Destroy(fd_);
+ }
+ flow_id_ = other.flow_id_;
+ stream_id_ = other.stream_id_;
+ target_server_address_ = other.target_server_address_;
+ fd_ = other.fd_;
+ masque_session_ = other.masque_session_;
+ other.fd_ = kQuicInvalidSocketFd;
+ other.flow_id_.reset();
+ if (flow_id_.has_value()) {
+ masque_session_->UnregisterHttp3FlowId(flow_id());
+ masque_session_->RegisterHttp3FlowId(flow_id(), this);
+ }
+ return *this;
+}
+
+void MasqueServerSession::ConnectUdpServerState::OnHttp3Datagram(
+ QuicDatagramFlowId flow_id,
+ absl::string_view payload) {
+ QUICHE_DCHECK_EQ(flow_id, this->flow_id());
+ QuicUdpSocketApi socket_api;
+ QuicUdpPacketInfo packet_info;
+ packet_info.SetPeerAddress(target_server_address_);
+ WriteResult write_result = socket_api.WritePacket(
+ fd_, payload.data(), payload.length(), packet_info);
+ QUIC_DVLOG(1) << "Wrote packet of length " << payload.length() << " to "
+ << target_server_address_ << " with result " << write_result;
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.h b/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.h
index 9e43b63ccbc..14b8293e9b1 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.h
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.h
@@ -5,8 +5,12 @@
#ifndef QUICHE_QUIC_MASQUE_MASQUE_SERVER_SESSION_H_
#define QUICHE_QUIC_MASQUE_MASQUE_SERVER_SESSION_H_
+#include "quic/core/quic_types.h"
+#include "quic/core/quic_udp_socket.h"
#include "quic/masque/masque_compression_engine.h"
#include "quic/masque/masque_server_backend.h"
+#include "quic/masque/masque_utils.h"
+#include "quic/platform/api/quic_epoll.h"
#include "quic/platform/api/quic_export.h"
#include "quic/tools/quic_simple_server_session.h"
@@ -15,7 +19,8 @@ namespace quic {
// QUIC server session for connection to MASQUE proxy.
class QUIC_NO_EXPORT MasqueServerSession
: public QuicSimpleServerSession,
- public MasqueServerBackend::BackendClient {
+ public MasqueServerBackend::BackendClient,
+ public QuicEpollCallbackInterface {
public:
// Interface meant to be implemented by owner of this MasqueServerSession
// instance.
@@ -33,11 +38,13 @@ class QUIC_NO_EXPORT MasqueServerSession
};
explicit MasqueServerSession(
+ MasqueMode masque_mode,
const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
QuicConnection* connection,
QuicSession::Visitor* visitor,
Visitor* owner,
+ QuicEpollServer* epoll_server,
QuicCryptoServerStreamBase::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
@@ -54,6 +61,7 @@ class QUIC_NO_EXPORT MasqueServerSession
void OnMessageLost(QuicMessageId message_id) override;
void OnConnectionClosed(const QuicConnectionCloseFrame& frame,
ConnectionCloseSource source) override;
+ void OnStreamClosed(QuicStreamId stream_id) override;
// From MasqueServerBackend::BackendClient.
std::unique_ptr<QuicBackendResponse> HandleMasqueRequest(
@@ -62,13 +70,71 @@ class QUIC_NO_EXPORT MasqueServerSession
const std::string& request_body,
QuicSimpleServerBackend::RequestHandler* request_handler) override;
+ // From QuicEpollCallbackInterface.
+ void OnRegistration(QuicEpollServer* eps,
+ QuicUdpSocketFd fd,
+ int event_mask) override;
+ void OnModification(QuicUdpSocketFd fd, int event_mask) override;
+ void OnEvent(QuicUdpSocketFd fd, QuicEpollEvent* event) override;
+ void OnUnregistration(QuicUdpSocketFd fd, bool replaced) override;
+ void OnShutdown(QuicEpollServer* eps, QuicUdpSocketFd fd) override;
+ std::string Name() const override;
+
// Handle packet for client, meant to be called by MasqueDispatcher.
void HandlePacketFromServer(const ReceivedPacketInfo& packet_info);
+ QuicEpollServer* epoll_server() const { return epoll_server_; }
+
private:
+ // State that the MasqueServerSession keeps for each CONNECT-UDP request.
+ class QUIC_NO_EXPORT ConnectUdpServerState
+ : public QuicSpdySession::Http3DatagramVisitor {
+ public:
+ // ConnectUdpServerState takes ownership of |fd|. It will unregister it
+ // from |epoll_server| and close the file descriptor when destructed.
+ explicit ConnectUdpServerState(
+ QuicDatagramFlowId flow_id,
+ QuicStreamId stream_id,
+ const QuicSocketAddress& target_server_address,
+ QuicUdpSocketFd fd,
+ MasqueServerSession* masque_session);
+
+ ~ConnectUdpServerState();
+
+ // Disallow copy but allow move.
+ ConnectUdpServerState(const ConnectUdpServerState&) = delete;
+ ConnectUdpServerState(ConnectUdpServerState&&);
+ ConnectUdpServerState& operator=(const ConnectUdpServerState&) = delete;
+ ConnectUdpServerState& operator=(ConnectUdpServerState&&);
+
+ QuicDatagramFlowId flow_id() const {
+ QUICHE_DCHECK(flow_id_.has_value());
+ return *flow_id_;
+ }
+ QuicStreamId stream_id() const { return stream_id_; }
+ const QuicSocketAddress& target_server_address() const {
+ return target_server_address_;
+ }
+ QuicUdpSocketFd fd() const { return fd_; }
+
+ // From QuicSpdySession::Http3DatagramVisitor.
+ void OnHttp3Datagram(QuicDatagramFlowId flow_id,
+ absl::string_view payload) override;
+
+ private:
+ absl::optional<QuicDatagramFlowId> flow_id_;
+ QuicStreamId stream_id_;
+ QuicSocketAddress target_server_address_;
+ QuicUdpSocketFd fd_; // Owned.
+ MasqueServerSession* masque_session_; // Unowned.
+ };
+
MasqueServerBackend* masque_server_backend_; // Unowned.
Visitor* owner_; // Unowned.
+ QuicEpollServer* epoll_server_; // Unowned.
MasqueCompressionEngine compression_engine_;
+ MasqueMode masque_mode_;
+ std::list<ConnectUdpServerState> connect_udp_server_states_;
bool masque_initialized_ = false;
};
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_utils.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_utils.cc
index f4f77f5faa2..cd196029c6b 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_utils.cc
@@ -8,17 +8,16 @@ namespace quic {
ParsedQuicVersionVector MasqueSupportedVersions() {
QuicVersionInitializeSupportForIetfDraft();
- ParsedQuicVersion version = UnsupportedQuicVersion();
- for (const ParsedQuicVersion& vers : AllSupportedVersions()) {
- // Find the first version that supports IETF QUIC.
- if (vers.HasIetfQuicFrames() && vers.UsesTls()) {
- version = vers;
- break;
+ ParsedQuicVersionVector versions;
+ for (const ParsedQuicVersion& version : AllSupportedVersions()) {
+ // Use all versions that support IETF QUIC.
+ if (version.UsesHttp3()) {
+ QuicEnableVersion(version);
+ versions.push_back(version);
}
}
- QUICHE_CHECK(version.IsKnown());
- QuicEnableVersion(version);
- return {version};
+ QUICHE_CHECK(!versions.empty());
+ return versions;
}
QuicConfig MasqueEncapsulatedConfig() {
@@ -27,4 +26,21 @@ QuicConfig MasqueEncapsulatedConfig() {
return config;
}
+std::string MasqueModeToString(MasqueMode masque_mode) {
+ switch (masque_mode) {
+ case MasqueMode::kInvalid:
+ return "Invalid";
+ case MasqueMode::kLegacy:
+ return "Legacy";
+ case MasqueMode::kOpen:
+ return "Open";
+ }
+ return absl::StrCat("Unknown(", static_cast<int>(masque_mode), ")");
+}
+
+std::ostream& operator<<(std::ostream& os, const MasqueMode& masque_mode) {
+ os << MasqueModeToString(masque_mode);
+ return os;
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_utils.h b/chromium/net/third_party/quiche/src/quic/masque/masque_utils.h
index f151f5508cd..8113047768c 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_utils.h
@@ -18,7 +18,24 @@ QUIC_NO_EXPORT ParsedQuicVersionVector MasqueSupportedVersions();
QUIC_NO_EXPORT QuicConfig MasqueEncapsulatedConfig();
// Maximum packet size for encapsulated connections.
-const QuicByteCount kMasqueMaxEncapsulatedPacketSize = 1300;
+enum : QuicByteCount { kMasqueMaxEncapsulatedPacketSize = 1300 };
+
+// Mode that MASQUE is operating in.
+enum class MasqueMode : uint8_t {
+ kInvalid = 0, // Should never be used.
+ kLegacy = 1, // Legacy mode uses the legacy MASQUE protocol as documented in
+ // <https://tools.ietf.org/html/draft-schinazi-masque-protocol>. That version
+ // of MASQUE uses a custom application-protocol over HTTP/3, and also allows
+ // unauthenticated clients.
+ kOpen = 2, // Open mode uses the MASQUE HTTP CONNECT-UDP method as documented
+ // in <https://tools.ietf.org/html/draft-ietf-masque-connect-udp>. This mode
+ // allows unauthenticated clients (a more restricted mode will be added to
+ // this enum at a later date).
+};
+
+QUIC_NO_EXPORT std::string MasqueModeToString(MasqueMode masque_mode);
+QUIC_NO_EXPORT std::ostream& operator<<(std::ostream& os,
+ const MasqueMode& masque_mode);
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h
index 23bcb7b14ac..cffa6e52533 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h
@@ -5,11 +5,11 @@
#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_BUG_TRACKER_H_
#define QUICHE_QUIC_PLATFORM_API_QUIC_BUG_TRACKER_H_
-#include "net/quic/platform/impl/quic_bug_tracker_impl.h"
+#include "common/platform/api/quiche_bug_tracker.h"
-#define QUIC_BUG QUIC_BUG_IMPL
-#define QUIC_BUG_IF QUIC_BUG_IF_IMPL
-#define QUIC_PEER_BUG QUIC_PEER_BUG_IMPL
-#define QUIC_PEER_BUG_IF QUIC_PEER_BUG_IF_IMPL
+#define QUIC_BUG QUICHE_BUG
+#define QUIC_BUG_IF QUICHE_BUG_IF
+#define QUIC_PEER_BUG QUICHE_PEER_BUG
+#define QUIC_PEER_BUG_IF QUICHE_PEER_BUG_IF
#endif // QUICHE_QUIC_PLATFORM_API_QUIC_BUG_TRACKER_H_
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils_test.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils_test.cc
index 7049715f74e..788cb2d5425 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils_test.cc
@@ -19,6 +19,9 @@ TEST_F(QuicHostnameUtilsTest, IsValidSNI) {
// IP as SNI.
EXPECT_FALSE(QuicHostnameUtils::IsValidSNI("192.168.0.1"));
// SNI without any dot.
+ SetQuicReloadableFlag(quic_and_tls_allow_sni_without_dots, true);
+ EXPECT_TRUE(QuicHostnameUtils::IsValidSNI("somedomain"));
+ SetQuicReloadableFlag(quic_and_tls_allow_sni_without_dots, false);
EXPECT_FALSE(QuicHostnameUtils::IsValidSNI("somedomain"));
// Invalid by RFC2396 but unfortunately domains of this form exist.
EXPECT_TRUE(QuicHostnameUtils::IsValidSNI("some_domain.com"));
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address.cc
index 95877f4c8e7..b2cb649f5f9 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address.cc
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address.cc
@@ -23,7 +23,8 @@ static int ToPlatformAddressFamily(IpAddressFamily family) {
case IpAddressFamily::IP_UNSPEC:
return AF_UNSPEC;
}
- QUIC_BUG << "Invalid IpAddressFamily " << static_cast<int32_t>(family);
+ QUIC_BUG(quic_bug_10126_1)
+ << "Invalid IpAddressFamily " << static_cast<int32_t>(family);
return AF_UNSPEC;
}
@@ -85,7 +86,8 @@ bool operator==(QuicIpAddress lhs, QuicIpAddress rhs) {
case IpAddressFamily::IP_UNSPEC:
return true;
}
- QUIC_BUG << "Invalid IpAddressFamily " << static_cast<int32_t>(lhs.family_);
+ QUIC_BUG(quic_bug_10126_2)
+ << "Invalid IpAddressFamily " << static_cast<int32_t>(lhs.family_);
return false;
}
@@ -114,7 +116,8 @@ std::string QuicIpAddress::ToPackedString() const {
case IpAddressFamily::IP_UNSPEC:
return "";
}
- QUIC_BUG << "Invalid IpAddressFamily " << static_cast<int32_t>(family_);
+ QUIC_BUG(quic_bug_10126_3)
+ << "Invalid IpAddressFamily " << static_cast<int32_t>(family_);
return "";
}
@@ -126,7 +129,8 @@ std::string QuicIpAddress::ToString() const {
char buffer[INET6_ADDRSTRLEN] = {0};
const char* result =
inet_ntop(AddressFamilyToInt(), address_.bytes, buffer, sizeof(buffer));
- QUIC_BUG_IF(result == nullptr) << "Failed to convert an IP address to string";
+ QUIC_BUG_IF(quic_bug_10126_4, result == nullptr)
+ << "Failed to convert an IP address to string";
return buffer;
}
@@ -200,11 +204,12 @@ bool QuicIpAddress::IsIPv6() const {
bool QuicIpAddress::InSameSubnet(const QuicIpAddress& other,
int subnet_length) {
if (!IsInitialized()) {
- QUIC_BUG << "Attempting to do subnet matching on undefined address";
+ QUIC_BUG(quic_bug_10126_5)
+ << "Attempting to do subnet matching on undefined address";
return false;
}
if ((IsIPv4() && subnet_length > 32) || (IsIPv6() && subnet_length > 128)) {
- QUIC_BUG << "Subnet mask is out of bounds";
+ QUIC_BUG(quic_bug_10126_6) << "Subnet mask is out of bounds";
return false;
}
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h
deleted file mode 100644
index 71045e1c30e..00000000000
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_PTR_UTIL_H_
-#define QUICHE_QUIC_PLATFORM_API_QUIC_PTR_UTIL_H_
-
-#include <memory>
-#include <utility>
-
-#include "net/quic/platform/impl/quic_ptr_util_impl.h"
-
-namespace quic {
-
-template <typename T>
-std::unique_ptr<T> QuicWrapUnique(T* ptr) {
- return QuicWrapUniqueImpl<T>(ptr);
-}
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_PLATFORM_API_QUIC_PTR_UTIL_H_
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.cc
index 38179e9fcf6..4c60c1e6da1 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.cc
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.cc
@@ -33,7 +33,8 @@ QuicSocketAddress::QuicSocketAddress(const struct sockaddr_storage& saddr) {
break;
}
default:
- QUIC_BUG << "Unknown address family passed: " << saddr.ss_family;
+ QUIC_BUG(quic_bug_10075_1)
+ << "Unknown address family passed: " << saddr.ss_family;
break;
}
}
@@ -48,7 +49,7 @@ QuicSocketAddress::QuicSocketAddress(const sockaddr* saddr, socklen_t len) {
(saddr->sa_family == AF_INET6 &&
len < static_cast<socklen_t>(sizeof(sockaddr_in6))) ||
len > static_cast<socklen_t>(sizeof(storage))) {
- QUIC_BUG << "Socket address of invalid length provided";
+ QUIC_BUG(quic_bug_10075_2) << "Socket address of invalid length provided";
return;
}
memcpy(&storage, saddr, len);
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_uint128.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_uint128.h
deleted file mode 100644
index 4f333ae131a..00000000000
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_uint128.h
+++ /dev/null
@@ -1,19 +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_QUIC_PLATFORM_API_QUIC_UINT128_H_
-#define QUICHE_QUIC_PLATFORM_API_QUIC_UINT128_H_
-
-#include "net/quic/platform/impl/quic_uint128_impl.h"
-
-namespace quic {
-
-using QuicUint128 = QuicUint128Impl;
-#define MakeQuicUint128(hi, lo) MakeQuicUint128Impl(hi, lo)
-#define QuicUint128Low64(x) QuicUint128Low64Impl(x)
-#define QuicUint128High64(x) QuicUint128High64Impl(x)
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_PLATFORM_API_QUIC_UINT128_H_
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/qbone_tunnel_info.cc b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/qbone_tunnel_info.cc
new file mode 100644
index 00000000000..372cd2b2510
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/qbone_tunnel_info.cc
@@ -0,0 +1,37 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "quic/qbone/bonnet/qbone_tunnel_info.h"
+
+namespace quic {
+
+QuicIpAddress QboneTunnelInfo::GetAddress() {
+ QuicIpAddress no_address;
+
+ NetlinkInterface::LinkInfo link_info{};
+ if (!netlink_->GetLinkInfo(ifname_, &link_info)) {
+ return no_address;
+ }
+
+ std::vector<NetlinkInterface::AddressInfo> addresses;
+ if (!netlink_->GetAddresses(link_info.index, 0, &addresses, nullptr)) {
+ return no_address;
+ }
+
+ quic::QuicIpAddress link_local_subnet;
+ if (!link_local_subnet.FromString("FE80::")) {
+ return no_address;
+ }
+
+ for (const auto& address : addresses) {
+ if (address.interface_address.IsInitialized() &&
+ !link_local_subnet.InSameSubnet(address.interface_address, 10)) {
+ return address.interface_address;
+ }
+ }
+
+ return no_address;
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/qbone_tunnel_info.h b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/qbone_tunnel_info.h
new file mode 100644
index 00000000000..6ca6ae8bff6
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/qbone_tunnel_info.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_QBONE_BONNET_QBONE_TUNNEL_INFO_H_
+#define QUICHE_QUIC_QBONE_BONNET_QBONE_TUNNEL_INFO_H_
+
+#include "quic/platform/api/quic_ip_address.h"
+#include "quic/qbone/platform/netlink_interface.h"
+
+namespace quic {
+
+class QboneTunnelInfo {
+ public:
+ QboneTunnelInfo(std::string ifname, NetlinkInterface* netlink)
+ : ifname_(std::move(ifname)), netlink_(netlink) {}
+
+ // Returns the current QBONE tunnel address. Callers must use IsInitialized()
+ // to ensure the returned address is valid.
+ QuicIpAddress GetAddress();
+
+ private:
+ const std::string ifname_;
+ NetlinkInterface* netlink_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_QBONE_BONNET_QBONE_TUNNEL_INFO_H_
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 3ee066a1b7b..3ca52e8d6d6 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
@@ -14,9 +14,13 @@
#include "quic/platform/api/quic_logging.h"
#include "quic/qbone/platform/kernel_interface.h"
+ABSL_FLAG(std::string,
+ qbone_client_tun_device_path,
+ "/dev/net/tun",
+ "The path to the QBONE client's TUN device.");
+
namespace quic {
-const char kTapTunDevicePath[] = "/dev/net/tun";
const int kInvalidFd = -1;
TunDevice::TunDevice(const std::string& interface_name,
@@ -40,7 +44,8 @@ TunDevice::~TunDevice() {
bool TunDevice::Init() {
if (interface_name_.empty() || interface_name_.size() >= IFNAMSIZ) {
- QUIC_BUG << "interface_name must be nonempty and shorter than " << IFNAMSIZ;
+ QUIC_BUG(quic_bug_10995_1)
+ << "interface_name must be nonempty and shorter than " << IFNAMSIZ;
return false;
}
@@ -115,9 +120,11 @@ bool TunDevice::OpenDevice() {
// 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.
- int fd = kernel_.open(kTapTunDevicePath, O_RDWR);
+ 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 " << kTapTunDevicePath;
+ QUIC_PLOG(WARNING) << "Failed to open " << tun_device_path;
CleanUpFileDescriptor();
return false;
}
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_interface.h b/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_interface.h
index eabfe078665..0794b1d5e4c 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_interface.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_interface.h
@@ -5,6 +5,8 @@
#ifndef QUICHE_QUIC_QBONE_PLATFORM_NETLINK_INTERFACE_H_
#define QUICHE_QUIC_QBONE_PLATFORM_NETLINK_INTERFACE_H_
+#include <linux/rtnetlink.h>
+
#include "quic/platform/api/quic_ip_address.h"
#include "quic/qbone/platform/ip_range.h"
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_test.cc
index 58b03d38838..16d2a19dc60 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_test.cc
@@ -196,8 +196,8 @@ void CreateIfaddrmsg(struct nlmsghdr* nlm,
family = AF_INET6;
break;
default:
- QUIC_BUG << absl::StrCat("unexpected address family: ",
- ip.address_family());
+ QUIC_BUG(quic_bug_11034_1)
+ << absl::StrCat("unexpected address family: ", ip.address_family());
family = AF_UNSPEC;
}
auto* msg = reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(nlm));
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client.cc
index 464c0532589..d0daf95c419 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client.cc
@@ -11,6 +11,7 @@
#include "quic/core/quic_epoll_connection_helper.h"
#include "quic/platform/api/quic_epoll.h"
#include "quic/platform/api/quic_exported_stats.h"
+#include "quic/platform/api/quic_testvalue.h"
#include "quic/qbone/qbone_stream.h"
namespace quic {
@@ -20,7 +21,7 @@ std::unique_ptr<QuicClientBase::NetworkHelper> CreateNetworkHelper(
QboneClient* client) {
std::unique_ptr<QuicClientBase::NetworkHelper> helper =
std::make_unique<QuicClientEpollNetworkHelper>(epoll_server, client);
- testing::testvalue::Adjust("QboneClient/network_helper", &helper);
+ quic::AdjustTestValue("QboneClient/network_helper", &helper);
return helper;
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.cc
index f3b62904d6b..1f8ca0ab788 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_session.cc
@@ -72,7 +72,8 @@ int QboneClientSession::GetNumReceivedServerConfigUpdates() const {
bool QboneClientSession::SendServerRequest(const QboneServerRequest& request) {
if (!control_stream_) {
- QUIC_BUG << "Cannot send server request before control stream is created.";
+ QUIC_BUG(quic_bug_11056_1)
+ << "Cannot send server request before control stream is created.";
return false;
}
return control_stream_->SendRequest(request);
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_test.cc
index 75a3a1e9216..91bb82d7449 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_client_test.cc
@@ -127,7 +127,8 @@ class QuicQboneDispatcher : public QuicDispatcher {
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
absl::string_view alpn,
- const quic::ParsedQuicVersion& version) override {
+ const quic::ParsedQuicVersion& version,
+ absl::string_view sni) override {
QUICHE_CHECK_EQ(alpn, "qbone");
QuicConnection* connection = new QuicConnection(
id, self_address, peer_address, helper(), alarm_factory(), writer(),
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc
index 132ecb7a232..944257f7af2 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc
@@ -48,12 +48,13 @@ void QboneControlStreamBase::OnDataAvailable() {
bool QboneControlStreamBase::SendMessage(const proto2::Message& proto) {
std::string tmp;
if (!proto.SerializeToString(&tmp)) {
- QUIC_BUG << "Failed to serialize QboneControlRequest";
+ QUIC_BUG(quic_bug_11023_1) << "Failed to serialize QboneControlRequest";
return false;
}
if (tmp.size() > kuint16max) {
- QUIC_BUG << "QboneControlRequest too large: " << tmp.size() << " > "
- << kuint16max;
+ QUIC_BUG(quic_bug_11023_2)
+ << "QboneControlRequest too large: " << tmp.size() << " > "
+ << kuint16max;
return false;
}
uint16_t size = tmp.size();
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.cc
index c9935577a86..7b45ed1050b 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.cc
@@ -62,7 +62,8 @@ QbonePacketProcessor::Filter::FilterPacket(Direction direction,
void QbonePacketProcessor::ProcessPacket(std::string* packet,
Direction direction) {
if (QUIC_PREDICT_FALSE(!IsValid())) {
- QUIC_BUG << "QuicPacketProcessor is invoked in an invalid state.";
+ QUIC_BUG(quic_bug_11024_1)
+ << "QuicPacketProcessor is invoked in an invalid state.";
stats_->OnPacketDroppedSilently(direction);
return;
}
@@ -120,8 +121,9 @@ QbonePacketProcessor::ProcessIPv6HeaderAndFilter(std::string* packet,
// Sanity-check the bounds.
if (packet_data >= *transport_data || header_size > packet->size() ||
header_size < kIPv6HeaderSize) {
- QUIC_BUG << "Invalid pointers encountered in "
- "QbonePacketProcessor::ProcessPacket. Dropping the packet";
+ QUIC_BUG(quic_bug_11024_2)
+ << "Invalid pointers encountered in "
+ "QbonePacketProcessor::ProcessPacket. Dropping the packet";
return ProcessingResult::SILENT_DROP;
}
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.cc
index 76a460c99d1..3b80dab9d48 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_server_session.cc
@@ -66,7 +66,8 @@ void QboneServerSession::Initialize() {
bool QboneServerSession::SendClientRequest(const QboneClientRequest& request) {
if (!control_stream_) {
- QUIC_BUG << "Cannot send client request before control stream is created.";
+ QUIC_BUG(quic_bug_11026_1)
+ << "Cannot send client request before control stream is created.";
return false;
}
return control_stream_->SendRequest(request);
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc
index 607c542591f..e984196faf0 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc
@@ -15,10 +15,11 @@
#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_exported_stats.h"
#include "quic/platform/api/quic_logging.h"
+#include "quic/platform/api/quic_testvalue.h"
#include "quic/qbone/platform/icmp_packet.h"
#include "quic/qbone/qbone_constants.h"
-ABSL_FLAG(
+DEFINE_QUIC_COMMAND_LINE_FLAG(
bool,
qbone_close_ephemeral_frames,
true,
@@ -133,7 +134,8 @@ QuicStream* QboneSessionBase::ActivateDataStream(
void QboneSessionBase::SendPacketToPeer(absl::string_view packet) {
if (crypto_stream_ == nullptr) {
- QUIC_BUG << "Attempting to send packet before encryption established";
+ QUIC_BUG(quic_bug_10987_1)
+ << "Attempting to send packet before encryption established";
return;
}
@@ -147,7 +149,8 @@ void QboneSessionBase::SendPacketToPeer(absl::string_view packet) {
break;
case MESSAGE_STATUS_TOO_LARGE: {
if (packet.size() < sizeof(ip6_hdr)) {
- QUIC_BUG << "Dropped malformed packet: IPv6 header too short";
+ QUIC_BUG(quic_bug_10987_2)
+ << "Dropped malformed packet: IPv6 header too short";
break;
}
auto* header = reinterpret_cast<const ip6_hdr*>(packet.begin());
@@ -164,16 +167,17 @@ void QboneSessionBase::SendPacketToPeer(absl::string_view packet) {
break;
}
case MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED:
- QUIC_BUG << "MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED";
+ QUIC_BUG(quic_bug_10987_3)
+ << "MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED";
break;
case MESSAGE_STATUS_UNSUPPORTED:
- QUIC_BUG << "MESSAGE_STATUS_UNSUPPORTED";
+ QUIC_BUG(quic_bug_10987_4) << "MESSAGE_STATUS_UNSUPPORTED";
break;
case MESSAGE_STATUS_BLOCKED:
- QUIC_BUG << "MESSAGE_STATUS_BLOCKED";
+ QUIC_BUG(quic_bug_10987_5) << "MESSAGE_STATUS_BLOCKED";
break;
case MESSAGE_STATUS_INTERNAL_ERROR:
- QUIC_BUG << "MESSAGE_STATUS_INTERNAL_ERROR";
+ QUIC_BUG(quic_bug_10987_6) << "MESSAGE_STATUS_INTERNAL_ERROR";
break;
}
return;
@@ -182,7 +186,7 @@ void QboneSessionBase::SendPacketToPeer(absl::string_view packet) {
// QBONE streams are ephemeral.
QuicStream* stream = CreateOutgoingStream();
if (!stream) {
- QUIC_BUG << "Failed to create an outgoing QBONE stream.";
+ QUIC_BUG(quic_bug_10987_7) << "Failed to create an outgoing QBONE stream.";
return;
}
@@ -209,7 +213,7 @@ uint64_t QboneSessionBase::GetNumFallbackToStream() const {
void QboneSessionBase::set_writer(QbonePacketWriter* writer) {
writer_ = writer;
- testing::testvalue::Adjust("quic_QbonePacketWriter", &writer_);
+ quic::AdjustTestValue("quic_QbonePacketWriter", &writer_);
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.cc
index 43aab4d001b..5aac3e73ada 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream.cc
@@ -11,7 +11,10 @@
#include "quic/qbone/qbone_constants.h"
#include "quic/qbone/qbone_session_base.h"
-ABSL_FLAG(int, qbone_stream_ttl_secs, 3, "The QBONE Stream TTL in seconds.");
+DEFINE_QUIC_COMMAND_LINE_FLAG(int,
+ qbone_stream_ttl_secs,
+ 3,
+ "The QBONE Stream TTL in seconds.");
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.cc b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.cc
index cf7032103b9..17f9194abfe 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.cc
@@ -34,7 +34,7 @@ QuicTransportClientSession::QuicTransportClientSession(
const GURL& url,
QuicCryptoClientConfig* crypto_config,
url::Origin origin,
- ClientVisitor* visitor,
+ WebTransportVisitor* visitor,
std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer)
: QuicSession(connection,
owner,
@@ -46,7 +46,7 @@ QuicTransportClientSession::QuicTransportClientSession(
origin_(origin),
visitor_(visitor) {
for (const ParsedQuicVersion& version : supported_versions) {
- QUIC_BUG_IF(version.handshake_protocol != PROTOCOL_TLS1_3)
+ QUIC_BUG_IF(quic_bug_12035_1, version.handshake_protocol != PROTOCOL_TLS1_3)
<< "QuicTransport requires TLS 1.3 handshake";
}
crypto_stream_ = std::make_unique<QuicCryptoClientStream>(
@@ -58,7 +58,8 @@ QuicTransportClientSession::QuicTransportClientSession(
void QuicTransportClientSession::OnAlpnSelected(absl::string_view alpn) {
// Defense in-depth: ensure the ALPN selected is the desired one.
if (alpn != QuicTransportAlpn()) {
- QUIC_BUG << "QuicTransport negotiated non-QuicTransport ALPN: " << alpn;
+ QUIC_BUG(quic_bug_10881_1)
+ << "QuicTransport negotiated non-QuicTransport ALPN: " << alpn;
connection()->CloseConnection(
QUIC_INTERNAL_ERROR, "QuicTransport negotiated non-QuicTransport ALPN",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -117,7 +118,8 @@ QuicTransportClientSession::AcceptIncomingUnidirectionalStream() {
QuicTransportStream*
QuicTransportClientSession::OpenOutgoingBidirectionalStream() {
if (!CanOpenNextOutgoingBidirectionalStream()) {
- QUIC_BUG << "Attempted to open a stream in violation of flow control";
+ QUIC_BUG(quic_bug_10881_2)
+ << "Attempted to open a stream in violation of flow control";
return nullptr;
}
return CreateStream(GetNextOutgoingBidirectionalStreamId());
@@ -126,7 +128,8 @@ QuicTransportClientSession::OpenOutgoingBidirectionalStream() {
QuicTransportStream*
QuicTransportClientSession::OpenOutgoingUnidirectionalStream() {
if (!CanOpenNextOutgoingUnidirectionalStream()) {
- QUIC_BUG << "Attempted to open a stream in violation of flow control";
+ QUIC_BUG(quic_bug_10881_3)
+ << "Attempted to open a stream in violation of flow control";
return nullptr;
}
return CreateStream(GetNextOutgoingUnidirectionalStreamId());
@@ -142,7 +145,7 @@ QuicTransportStream* QuicTransportClientSession::CreateStream(QuicStreamId id) {
std::string QuicTransportClientSession::SerializeClientIndication() {
std::string serialized_origin = origin_.Serialize();
if (serialized_origin.size() > std::numeric_limits<uint16_t>::max()) {
- QUIC_BUG << "Client origin too long";
+ QUIC_BUG(quic_bug_10881_4) << "Client origin too long";
connection()->CloseConnection(
QUIC_INTERNAL_ERROR, "Client origin too long",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -182,23 +185,25 @@ std::string QuicTransportClientSession::SerializeClientIndication() {
writer.WriteUInt16(
static_cast<uint16_t>(QuicTransportClientIndicationKeys::kPath)) &&
writer.WriteUInt16(path.size()) && writer.WriteStringPiece(path);
- QUIC_BUG_IF(!success) << "Failed to serialize client indication";
- QUIC_BUG_IF(writer.length() != buffer.length())
+ QUIC_BUG_IF(quic_bug_10881_5, !success)
+ << "Failed to serialize client indication";
+ QUIC_BUG_IF(quic_bug_12035_2, writer.length() != buffer.length())
<< "Serialized client indication has length different from expected";
return buffer;
}
void QuicTransportClientSession::SendClientIndication() {
if (!crypto_stream_->encryption_established()) {
- QUIC_BUG << "Client indication may only be sent once the encryption is "
- "established.";
+ QUIC_BUG(quic_bug_10881_6)
+ << "Client indication may only be sent once the encryption is "
+ "established.";
connection()->CloseConnection(
QUIC_INTERNAL_ERROR, "Attempted to send client indication unencrypted",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
if (ready_) {
- QUIC_BUG << "Client indication may only be sent once.";
+ QUIC_BUG(quic_bug_10881_7) << "Client indication may only be sent once.";
connection()->CloseConnection(
QUIC_INTERNAL_ERROR, "Attempted to send client indication twice",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -208,7 +213,8 @@ void QuicTransportClientSession::SendClientIndication() {
auto client_indication_owned = std::make_unique<ClientIndication>(
/*stream_id=*/GetNextOutgoingUnidirectionalStreamId(), this,
/*is_static=*/false, WRITE_UNIDIRECTIONAL);
- QUIC_BUG_IF(client_indication_owned->id() != ClientIndicationStream())
+ QUIC_BUG_IF(quic_bug_12035_3,
+ client_indication_owned->id() != ClientIndicationStream())
<< "Client indication stream is " << client_indication_owned->id()
<< " instead of expected " << ClientIndicationStream();
ClientIndication* client_indication = client_indication_owned.get();
@@ -220,7 +226,8 @@ void QuicTransportClientSession::SendClientIndication() {
// Defense in depth: never set the ready bit unless ALPN has been confirmed.
if (!alpn_received_) {
- QUIC_BUG << "ALPN confirmation missing after handshake complete";
+ QUIC_BUG(quic_bug_10881_8)
+ << "ALPN confirmation missing after handshake complete";
connection()->CloseConnection(
QUIC_INTERNAL_ERROR,
"ALPN confirmation missing after handshake complete",
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 d01903c388d..6f6d091d71a 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.h
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.h
@@ -21,6 +21,7 @@
#include "quic/core/quic_session.h"
#include "quic/core/quic_stream.h"
#include "quic/core/quic_versions.h"
+#include "quic/core/web_transport_interface.h"
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_containers.h"
#include "quic/quic_transport/quic_transport_protocol.h"
@@ -32,31 +33,10 @@ namespace quic {
// A client session for the QuicTransport protocol.
class QUIC_EXPORT_PRIVATE QuicTransportClientSession
: public QuicSession,
+ public WebTransportSession,
public QuicTransportSessionInterface,
public QuicCryptoClientStream::ProofHandler {
public:
- class QUIC_EXPORT_PRIVATE ClientVisitor {
- public:
- virtual ~ClientVisitor() {}
-
- // Notifies the visitor when the client indication has been sent and the
- // connection is ready to exchange application data.
- virtual void OnSessionReady() = 0;
-
- // Notifies the visitor when a new stream has been received. The stream in
- // question can be retrieved using AcceptIncomingBidirectionalStream() or
- // AcceptIncomingUnidirectionalStream().
- virtual void OnIncomingBidirectionalStreamAvailable() = 0;
- virtual void OnIncomingUnidirectionalStreamAvailable() = 0;
-
- // Notifies the visitor when a new datagram has been received.
- virtual void OnDatagramReceived(absl::string_view datagram) = 0;
-
- // Notifies the visitor that a new outgoing stream can now be created.
- virtual void OnCanCreateNewOutgoingBidirectionalStream() = 0;
- virtual void OnCanCreateNewOutgoingUnidirectionalStream() = 0;
- };
-
QuicTransportClientSession(
QuicConnection* connection,
Visitor* owner,
@@ -65,7 +45,7 @@ class QUIC_EXPORT_PRIVATE QuicTransportClientSession
const GURL& url,
QuicCryptoClientConfig* crypto_config,
url::Origin origin,
- ClientVisitor* visitor,
+ WebTransportVisitor* visitor,
std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer);
std::vector<std::string> GetAlpnsToOffer() const override {
@@ -93,8 +73,9 @@ class QUIC_EXPORT_PRIVATE QuicTransportClientSession
QuicStream* CreateIncomingStream(QuicStreamId id) override;
QuicStream* CreateIncomingStream(PendingStream* /*pending*/) override {
- QUIC_BUG << "QuicTransportClientSession::CreateIncomingStream("
- "PendingStream) not implemented";
+ QUIC_BUG(quic_bug_10890_1)
+ << "QuicTransportClientSession::CreateIncomingStream("
+ "PendingStream) not implemented";
return nullptr;
}
@@ -105,14 +86,26 @@ class QUIC_EXPORT_PRIVATE QuicTransportClientSession
// Return the earliest incoming stream that has been received by the session
// but has not been accepted. Returns nullptr if there are no incoming
// streams.
- QuicTransportStream* AcceptIncomingBidirectionalStream();
- QuicTransportStream* AcceptIncomingUnidirectionalStream();
+ QuicTransportStream* AcceptIncomingBidirectionalStream() override;
+ QuicTransportStream* AcceptIncomingUnidirectionalStream() override;
+
+ bool CanOpenNextOutgoingBidirectionalStream() override {
+ return QuicSession::CanOpenNextOutgoingBidirectionalStream();
+ }
+ bool CanOpenNextOutgoingUnidirectionalStream() override {
+ return QuicSession::CanOpenNextOutgoingUnidirectionalStream();
+ }
+ QuicTransportStream* OpenOutgoingBidirectionalStream() override;
+ QuicTransportStream* OpenOutgoingUnidirectionalStream() override;
- using QuicSession::CanOpenNextOutgoingBidirectionalStream;
- using QuicSession::CanOpenNextOutgoingUnidirectionalStream;
- QuicTransportStream* OpenOutgoingBidirectionalStream();
- QuicTransportStream* OpenOutgoingUnidirectionalStream();
+ MessageStatus SendOrQueueDatagram(QuicMemSlice datagram) override {
+ return datagram_queue()->SendOrQueueDatagram(std::move(datagram));
+ }
+ void SetDatagramMaxTimeInQueue(QuicTime::Delta max_time_in_queue) override {
+ datagram_queue()->SetMaxTimeInQueue(max_time_in_queue);
+ }
+ // For unit tests.
using QuicSession::datagram_queue;
// QuicCryptoClientStream::ProofHandler implementation.
@@ -128,7 +121,7 @@ class QUIC_EXPORT_PRIVATE QuicTransportClientSession
// This method should never be called, since the stream is client-initiated
// unidirectional.
void OnDataAvailable() override {
- QUIC_BUG << "Received data on a write-only stream";
+ QUIC_BUG(quic_bug_10890_2) << "Received data on a write-only stream";
}
};
@@ -146,7 +139,7 @@ class QUIC_EXPORT_PRIVATE QuicTransportClientSession
std::unique_ptr<QuicCryptoClientStream> crypto_stream_;
GURL url_;
url::Origin origin_;
- ClientVisitor* visitor_; // not owned
+ WebTransportVisitor* visitor_; // not owned
bool client_indication_sent_ = false;
bool alpn_received_ = false;
bool ready_ = false;
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_integration_test.cc b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_integration_test.cc
index 1b42020d535..36607b3918e 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_integration_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_integration_test.cc
@@ -140,12 +140,6 @@ class QuicTransportServerEndpoint : public QuicTransportEndpointBase {
QuicTransportSimpleServerSession session_;
};
-std::unique_ptr<MockStreamVisitor> VisitorExpectingFin() {
- auto visitor = std::make_unique<MockStreamVisitor>();
- EXPECT_CALL(*visitor, OnFinRead());
- return visitor;
-}
-
constexpr QuicBandwidth kClientBandwidth =
QuicBandwidth::FromKBitsPerSecond(10000);
constexpr QuicTime::Delta kClientPropagationDelay =
@@ -286,7 +280,9 @@ TEST_F(QuicTransportIntegrationTest, EchoBidirectionalStreams) {
[stream]() { return stream->ReadableBytes() == strlen("Hello!"); },
kDefaultTimeout));
std::string received;
- EXPECT_EQ(stream->Read(&received), strlen("Hello!"));
+ WebTransportStream::ReadResult result = stream->Read(&received);
+ EXPECT_EQ(result.bytes_read, strlen("Hello!"));
+ EXPECT_FALSE(result.fin);
EXPECT_EQ(received, "Hello!");
EXPECT_TRUE(stream->SendFin());
@@ -325,8 +321,9 @@ TEST_F(QuicTransportIntegrationTest, EchoUnidirectionalStreams) {
client_->session()->AcceptIncomingUnidirectionalStream();
ASSERT_TRUE(reply != nullptr);
std::string buffer;
- reply->set_visitor(VisitorExpectingFin());
- EXPECT_GT(reply->Read(&buffer), 0u);
+ WebTransportStream::ReadResult result = reply->Read(&buffer);
+ EXPECT_GT(result.bytes_read, 0u);
+ EXPECT_TRUE(result.fin);
EXPECT_EQ(buffer, "Stream Two");
// Reset reply-related variables.
@@ -339,8 +336,9 @@ TEST_F(QuicTransportIntegrationTest, EchoUnidirectionalStreams) {
[&stream_received]() { return stream_received; }, kDefaultTimeout));
reply = client_->session()->AcceptIncomingUnidirectionalStream();
ASSERT_TRUE(reply != nullptr);
- reply->set_visitor(VisitorExpectingFin());
- EXPECT_GT(reply->Read(&buffer), 0u);
+ result = reply->Read(&buffer);
+ EXPECT_GT(result.bytes_read, 0u);
+ EXPECT_TRUE(result.fin);
EXPECT_EQ(buffer, "Stream One");
}
@@ -349,8 +347,7 @@ TEST_F(QuicTransportIntegrationTest, EchoDatagram) {
WireUpEndpoints();
RunHandshake();
- client_->session()->datagram_queue()->SendOrQueueDatagram(
- MemSliceFromString("test"));
+ client_->session()->SendOrQueueDatagram(MemSliceFromString("test"));
bool datagram_received = false;
EXPECT_CALL(*client_->visitor(), OnDatagramReceived(Eq("test")))
@@ -368,11 +365,10 @@ TEST_F(QuicTransportIntegrationTest, EchoALotOfDatagrams) {
RunHandshake();
// Set the datagrams to effectively never expire.
- client_->session()->datagram_queue()->SetMaxTimeInQueue(10000 * kRtt);
+ client_->session()->SetDatagramMaxTimeInQueue(10000 * kRtt);
for (int i = 0; i < 1000; i++) {
- client_->session()->datagram_queue()->SendOrQueueDatagram(
- MemSliceFromString(std::string(
- client_->session()->GetGuaranteedLargestMessagePayload(), 'a')));
+ client_->session()->SendOrQueueDatagram(MemSliceFromString(std::string(
+ client_->session()->GetGuaranteedLargestMessagePayload(), 'a')));
}
size_t received = 0;
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.cc b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.cc
index e2cc59dc2a1..f7c8c0f949d 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.cc
@@ -50,7 +50,7 @@ QuicTransportServerSession::QuicTransportServerSession(
/*num_expected_unidirectional_static_streams*/ 0),
visitor_(visitor) {
for (const ParsedQuicVersion& version : supported_versions) {
- QUIC_BUG_IF(version.handshake_protocol != PROTOCOL_TLS1_3)
+ QUIC_BUG_IF(quic_bug_12025_1, version.handshake_protocol != PROTOCOL_TLS1_3)
<< "QuicTransport requires TLS 1.3 handshake";
}
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h
index 485f3268b2b..070cfdd5511 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h
@@ -66,8 +66,9 @@ class QUIC_EXPORT_PRIVATE QuicTransportServerSession
QuicStream* CreateIncomingStream(QuicStreamId id) override;
QuicStream* CreateIncomingStream(PendingStream* /*pending*/) override {
- QUIC_BUG << "QuicTransportServerSession::CreateIncomingStream("
- "PendingStream) not implemented";
+ QUIC_BUG(quic_bug_10884_1)
+ << "QuicTransportServerSession::CreateIncomingStream("
+ "PendingStream) not implemented";
return nullptr;
}
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc
index e27f4692f9d..4def1dead0f 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc
@@ -25,31 +25,24 @@ QuicTransportStream::QuicTransportStream(
session->connection()->perspective(),
session->IsIncomingStream(id),
session->version())),
+ adapter_(session, this, sequencer()),
session_interface_(session_interface) {}
-size_t QuicTransportStream::Read(char* buffer, size_t buffer_size) {
+WebTransportStream::ReadResult QuicTransportStream::Read(char* buffer,
+ size_t buffer_size) {
if (!session_interface_->IsSessionReady()) {
- return 0;
+ return ReadResult{0, false};
}
- iovec iov;
- iov.iov_base = buffer;
- iov.iov_len = buffer_size;
- const size_t result = sequencer()->Readv(&iov, 1);
- if (sequencer()->IsClosed()) {
- MaybeNotifyFinRead();
- }
- return result;
+ return adapter_.Read(buffer, buffer_size);
}
-size_t QuicTransportStream::Read(std::string* output) {
- const size_t old_size = output->size();
- const size_t bytes_to_read = ReadableBytes();
- output->resize(old_size + bytes_to_read);
- size_t bytes_read = Read(&(*output)[old_size], bytes_to_read);
- QUICHE_DCHECK_EQ(bytes_to_read, bytes_read);
- output->resize(old_size + bytes_read);
- return bytes_read;
+WebTransportStream::ReadResult QuicTransportStream::Read(std::string* output) {
+ if (!session_interface_->IsSessionReady()) {
+ return ReadResult{0, false};
+ }
+
+ return adapter_.Read(output);
}
bool QuicTransportStream::Write(absl::string_view data) {
@@ -57,32 +50,7 @@ bool QuicTransportStream::Write(absl::string_view data) {
return false;
}
- QuicUniqueBufferPtr buffer = MakeUniqueBuffer(
- session()->connection()->helper()->GetStreamSendBufferAllocator(),
- data.size());
- memcpy(buffer.get(), data.data(), data.size());
- QuicMemSlice memslice(std::move(buffer), data.size());
- QuicConsumedData consumed =
- WriteMemSlices(QuicMemSliceSpan(&memslice), /*fin=*/false);
-
- if (consumed.bytes_consumed == data.size()) {
- return true;
- }
- if (consumed.bytes_consumed == 0) {
- return false;
- }
- // QuicTransportStream::Write() is an all-or-nothing write API. To achieve
- // that property, it relies on WriteMemSlices() being an all-or-nothing API.
- // If WriteMemSlices() fails to provide that guarantee, we have no way to
- // communicate a partial write to the caller, and thus it's safer to just
- // close the connection.
- QUIC_BUG << "WriteMemSlices() unexpectedly partially consumed the input "
- "data, provided: "
- << data.size() << ", written: " << consumed.bytes_consumed;
- OnUnrecoverableError(
- QUIC_INTERNAL_ERROR,
- "WriteMemSlices() unexpectedly partially consumed the input data");
- return false;
+ return adapter_.Write(data);
}
bool QuicTransportStream::SendFin() {
@@ -90,16 +58,11 @@ bool QuicTransportStream::SendFin() {
return false;
}
- QuicMemSlice empty;
- QuicConsumedData consumed =
- WriteMemSlices(QuicMemSliceSpan(&empty), /*fin=*/true);
- QUICHE_DCHECK_EQ(consumed.bytes_consumed, 0u);
- return consumed.fin_consumed;
+ return adapter_.SendFin();
}
bool QuicTransportStream::CanWrite() const {
- return session_interface_->IsSessionReady() && CanWriteNewData() &&
- !write_side_closed();
+ return session_interface_->IsSessionReady() && adapter_.CanWrite();
}
size_t QuicTransportStream::ReadableBytes() const {
@@ -107,22 +70,11 @@ size_t QuicTransportStream::ReadableBytes() const {
return 0;
}
- return sequencer()->ReadableBytes();
+ return adapter_.ReadableBytes();
}
void QuicTransportStream::OnDataAvailable() {
- if (sequencer()->IsClosed()) {
- MaybeNotifyFinRead();
- return;
- }
-
- if (visitor_ == nullptr) {
- return;
- }
- if (ReadableBytes() == 0) {
- return;
- }
- visitor_->OnCanRead();
+ adapter_.OnDataAvailable();
}
void QuicTransportStream::OnCanWriteNewData() {
@@ -131,18 +83,7 @@ void QuicTransportStream::OnCanWriteNewData() {
if (!CanWrite()) {
return;
}
- if (visitor_ != nullptr) {
- visitor_->OnCanWrite();
- }
-}
-
-void QuicTransportStream::MaybeNotifyFinRead() {
- if (visitor_ == nullptr || fin_read_notified_) {
- return;
- }
- fin_read_notified_ = true;
- visitor_->OnFinRead();
- OnFinRead();
+ adapter_.OnCanWriteNewData();
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h
index 70f947c544d..87ef5fb3b83 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h
@@ -13,6 +13,8 @@
#include "quic/core/quic_session.h"
#include "quic/core/quic_stream.h"
#include "quic/core/quic_types.h"
+#include "quic/core/web_transport_interface.h"
+#include "quic/core/web_transport_stream_adapter.h"
#include "quic/quic_transport/quic_transport_session_interface.h"
namespace quic {
@@ -20,42 +22,47 @@ namespace quic {
// QuicTransportStream is an extension of QuicStream that provides I/O interface
// that is safe to use in the QuicTransport context. The interface ensures no
// application data is processed before the client indication is processed.
-class QUIC_EXPORT_PRIVATE QuicTransportStream : public QuicStream {
+class QUIC_EXPORT_PRIVATE QuicTransportStream : public QuicStream,
+ public WebTransportStream {
public:
- class QUIC_EXPORT_PRIVATE Visitor {
- public:
- virtual ~Visitor() {}
- virtual void OnCanRead() = 0;
- virtual void OnFinRead() = 0;
- virtual void OnCanWrite() = 0;
- };
-
QuicTransportStream(QuicStreamId id,
QuicSession* session,
QuicTransportSessionInterface* session_interface);
// Reads at most |buffer_size| bytes into |buffer| and returns the number of
// bytes actually read.
- size_t Read(char* buffer, size_t buffer_size);
+ ReadResult Read(char* buffer, size_t buffer_size) override;
// Reads all available data and appends it to the end of |output|.
- size_t Read(std::string* output);
+ ReadResult Read(std::string* output) override;
// Writes |data| into the stream. Returns true on success.
- ABSL_MUST_USE_RESULT bool Write(absl::string_view data);
+ ABSL_MUST_USE_RESULT bool Write(absl::string_view data) override;
// Sends the FIN on the stream. Returns true on success.
- ABSL_MUST_USE_RESULT bool SendFin();
+ ABSL_MUST_USE_RESULT bool SendFin() override;
// Indicates whether it is possible to write into stream right now.
- bool CanWrite() const;
+ bool CanWrite() const override;
// Indicates the number of bytes that can be read from the stream.
- size_t ReadableBytes() const;
+ size_t ReadableBytes() const override;
// QuicSession method implementations.
void OnDataAvailable() override;
void OnCanWriteNewData() override;
- Visitor* visitor() { return visitor_.get(); }
- void set_visitor(std::unique_ptr<Visitor> visitor) {
- visitor_ = std::move(visitor);
+ QuicStreamId GetStreamId() const override { return id(); }
+
+ void ResetWithUserCode(QuicRstStreamErrorCode error) override {
+ adapter_.ResetWithUserCode(error);
+ }
+ void ResetDueToInternalError() override {
+ adapter_.ResetDueToInternalError();
+ }
+ void MaybeResetDueToStreamObjectGone() override {
+ adapter_.MaybeResetDueToStreamObjectGone();
+ }
+
+ WebTransportStreamVisitor* visitor() override { return adapter_.visitor(); }
+ void SetVisitor(std::unique_ptr<WebTransportStreamVisitor> visitor) override {
+ adapter_.SetVisitor(std::move(visitor));
}
protected:
@@ -65,9 +72,8 @@ class QUIC_EXPORT_PRIVATE QuicTransportStream : public QuicStream {
void MaybeNotifyFinRead();
+ WebTransportStreamAdapter adapter_;
QuicTransportSessionInterface* session_interface_;
- std::unique_ptr<Visitor> visitor_ = nullptr;
- bool fin_read_notified_ = false;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream_test.cc b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream_test.cc
index 75446eb30c7..b93e0eb430a 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream_test.cc
@@ -6,11 +6,11 @@
#include <memory>
+#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "quic/core/crypto/null_encrypter.h"
#include "quic/core/frames/quic_window_update_frame.h"
#include "quic/platform/api/quic_expect_bug.h"
-#include "quic/platform/api/quic_ptr_util.h"
#include "quic/platform/api/quic_test.h"
#include "quic/quic_transport/quic_transport_session_interface.h"
#include "quic/test_tools/quic_config_peer.h"
@@ -47,11 +47,11 @@ class QuicTransportStreamTest : public QuicTest {
ENCRYPTION_FORWARD_SECURE,
std::make_unique<NullEncrypter>(connection_->perspective()));
stream_ = new QuicTransportStream(0, &session_, &interface_);
- session_.ActivateStream(QuicWrapUnique(stream_));
+ session_.ActivateStream(absl::WrapUnique(stream_));
auto visitor = std::make_unique<MockStreamVisitor>();
visitor_ = visitor.get();
- stream_->set_visitor(std::move(visitor));
+ stream_->SetVisitor(std::move(visitor));
}
void ReceiveStreamData(absl::string_view data, QuicStreamOffset offset) {
@@ -81,8 +81,9 @@ TEST_F(QuicTransportStreamTest, ReadWhenNotReady) {
EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(false));
ReceiveStreamData("test", 0);
char buffer[4];
- QuicByteCount bytes_read = stream_->Read(buffer, sizeof(buffer));
- EXPECT_EQ(bytes_read, 0u);
+ WebTransportStream::ReadResult result = stream_->Read(buffer, sizeof(buffer));
+ EXPECT_EQ(result.bytes_read, 0u);
+ EXPECT_FALSE(result.fin);
}
TEST_F(QuicTransportStreamTest, WriteWhenNotReady) {
@@ -102,26 +103,47 @@ TEST_F(QuicTransportStreamTest, ReceiveData) {
EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(true));
EXPECT_CALL(*visitor_, OnCanRead());
ReceiveStreamData("test", 0);
+
+ std::string buffer;
+ WebTransportStream::ReadResult result = stream_->Read(&buffer);
+ EXPECT_EQ(result.bytes_read, 4u);
+ EXPECT_FALSE(result.fin);
+ EXPECT_EQ(buffer, "test");
}
TEST_F(QuicTransportStreamTest, FinReadWithNoDataPending) {
EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(true));
- EXPECT_CALL(*visitor_, OnFinRead());
+ EXPECT_CALL(*visitor_, OnCanRead());
+
QuicStreamFrame frame(0, true, 0, "");
stream_->OnStreamFrame(frame);
+
+ std::string buffer;
+ WebTransportStream::ReadResult result = stream_->Read(&buffer);
+ EXPECT_EQ(result.bytes_read, 0u);
+ EXPECT_TRUE(result.fin);
+ EXPECT_EQ(buffer, "");
}
TEST_F(QuicTransportStreamTest, FinReadWithDataPending) {
EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(true));
EXPECT_CALL(*visitor_, OnCanRead());
- EXPECT_CALL(*visitor_, OnFinRead()).Times(0);
QuicStreamFrame frame(0, true, 0, "test");
stream_->OnStreamFrame(frame);
- EXPECT_CALL(*visitor_, OnFinRead()).Times(1);
- std::string buffer;
- ASSERT_EQ(stream_->Read(&buffer), 4u);
+ char buffer[2];
+ WebTransportStream::ReadResult result = stream_->Read(buffer, sizeof(buffer));
+ EXPECT_EQ(result.bytes_read, 2u);
+ EXPECT_FALSE(result.fin);
+ EXPECT_EQ(buffer[0], 't');
+ EXPECT_EQ(buffer[1], 'e');
+
+ result = stream_->Read(buffer, sizeof(buffer));
+ EXPECT_EQ(result.bytes_read, 2u);
+ EXPECT_TRUE(result.fin);
+ EXPECT_EQ(buffer[0], 's');
+ EXPECT_EQ(buffer[1], 't');
}
TEST_F(QuicTransportStreamTest, WritingTooMuchData) {
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 974d25a588c..cbe55453af2 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
@@ -125,7 +125,7 @@ QuicAsyncStatus WebTransportFingerprintProofVerifier::VerifyProof(
*error_details =
"QUIC crypto certificate verification is not supported in "
"WebTransportFingerprintProofVerifier";
- QUIC_BUG << *error_details;
+ QUIC_BUG(quic_bug_10879_1) << *error_details;
*details = std::make_unique<Details>(Status::kInternalError);
return QUIC_FAILURE;
}
@@ -191,7 +191,7 @@ bool WebTransportFingerprintProofVerifier::HasKnownFingerprint(
const std::string fingerprint = ComputeSha256Fingerprint(der_certificate);
for (const CertificateFingerprint& reference : fingerprints_) {
if (reference.algorithm != CertificateFingerprint::kSha256) {
- QUIC_BUG << "Unexpected non-SHA-256 hash";
+ QUIC_BUG(quic_bug_10879_2) << "Unexpected non-SHA-256 hash";
continue;
}
if (fingerprint == reference.fingerprint) {
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 23f24d67cde..968b4140451 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
@@ -472,7 +472,7 @@ class MockCommonCertSets : public CommonCertSets {
: cert_(cert), hash_(hash), index_(index) {}
absl::string_view GetCommonHashes() const override {
- QUIC_BUG << "not implemented";
+ QUIC_BUG(quic_bug_10142_1) << "not implemented";
return absl::string_view();
}
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 5bba0728949..b239f7d140c 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
@@ -176,7 +176,8 @@ void FakeProofSourceHandle::SelectCertOperation::Run() {
bool ok = chain && !chain->certs.empty();
callback_->OnSelectCertificateDone(ok, /*is_sync=*/false, chain.get());
} else {
- QUIC_BUG << "Unexpected action: " << static_cast<int>(action_);
+ QUIC_BUG(quic_bug_10139_1)
+ << "Unexpected action: " << static_cast<int>(action_);
}
}
@@ -200,7 +201,8 @@ void FakeProofSourceHandle::ComputeSignatureOperation::Run() {
result.signature,
std::move(result.details));
} else {
- QUIC_BUG << "Unexpected action: " << static_cast<int>(action_);
+ QUIC_BUG(quic_bug_10139_2)
+ << "Unexpected action: " << static_cast<int>(action_);
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_time_wait_list_manager.h b/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_time_wait_list_manager.h
index aadba941939..12bf0801082 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_time_wait_list_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_time_wait_list_manager.h
@@ -36,11 +36,12 @@ class MockTimeWaitListManager : public QuicTimeWaitListManager {
MOCK_METHOD(void,
ProcessPacket,
- (const QuicSocketAddress& server_address,
- const QuicSocketAddress& client_address,
- QuicConnectionId connection_id,
- PacketHeaderFormat header_format,
- std::unique_ptr<QuicPerPacketContext> packet_context),
+ (const QuicSocketAddress&,
+ const QuicSocketAddress&,
+ QuicConnectionId,
+ PacketHeaderFormat,
+ size_t,
+ std::unique_ptr<QuicPerPacketContext>),
(override));
MOCK_METHOD(void,
@@ -61,6 +62,7 @@ class MockTimeWaitListManager : public QuicTimeWaitListManager {
const QuicSocketAddress&,
QuicConnectionId,
bool,
+ size_t,
std::unique_ptr<QuicPerPacketContext>),
(override));
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.cc b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.cc
index 6cd3bf0bcf1..a4535040df7 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.cc
@@ -18,7 +18,8 @@ FragmentSizeGenerator FragmentModeToFragmentSizeGenerator(
case FragmentMode::kOctetByOctet:
return []() { return 1; };
}
- QUIC_BUG << "Unknown FragmentMode " << static_cast<int>(fragment_mode);
+ QUIC_BUG(quic_bug_10259_1)
+ << "Unknown FragmentMode " << static_cast<int>(fragment_mode);
return []() { return 0; };
}
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.cc
index 9bd5dd3bbbf..243216bb2e1 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.cc
@@ -87,8 +87,9 @@ void QuicConfigPeer::SetConnectionOptionsToSend(QuicConfig* config,
}
// static
-void QuicConfigPeer::SetReceivedStatelessResetToken(QuicConfig* config,
- QuicUint128 token) {
+void QuicConfigPeer::SetReceivedStatelessResetToken(
+ QuicConfig* config,
+ const StatelessResetToken& token) {
config->stateless_reset_token_.SetReceivedValue(token);
}
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.h
index 7491e7ff834..6ffc5aeef2d 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.h
@@ -8,7 +8,7 @@
#include "quic/core/quic_config.h"
#include "quic/core/quic_connection_id.h"
#include "quic/core/quic_packets.h"
-#include "quic/platform/api/quic_uint128.h"
+#include "quic/core/quic_types.h"
namespace quic {
@@ -55,7 +55,7 @@ class QuicConfigPeer {
const QuicTagVector& options);
static void SetReceivedStatelessResetToken(QuicConfig* config,
- QuicUint128 token);
+ const StatelessResetToken& token);
static void SetReceivedMaxPacketSize(QuicConfig* config,
uint32_t max_udp_payload_size);
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_id_manager_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_id_manager_peer.h
new file mode 100644
index 00000000000..ab749ed440c
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_id_manager_peer.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_TEST_TOOLS_QUIC_CONNECTION_ID_MANAGER_PEER_H_
+#define QUICHE_QUIC_TEST_TOOLS_QUIC_CONNECTION_ID_MANAGER_PEER_H_
+
+#include "quic/core/quic_connection_id_manager.h"
+
+namespace quic {
+namespace test {
+
+class QuicConnectionIdManagerPeer {
+ public:
+ static QuicAlarm* GetRetirePeerIssuedConnectionIdAlarm(
+ QuicPeerIssuedConnectionIdManager* manager) {
+ return manager->retire_connection_id_alarm_.get();
+ }
+
+ static QuicAlarm* GetRetireSelfIssuedConnectionIdAlarm(
+ QuicSelfIssuedConnectionIdManager* manager) {
+ return manager->retire_connection_id_alarm_.get();
+ }
+};
+
+} // namespace test
+} // namespace quic
+
+#endif // QUICHE_QUIC_TEST_TOOLS_QUIC_CONNECTION_ID_MANAGER_PEER_H_
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 8d4186e4312..3f1eaeb16bd 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc
@@ -10,6 +10,7 @@
#include "quic/core/quic_received_packet_manager.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_socket_address.h"
+#include "quic/test_tools/quic_connection_id_manager_peer.h"
#include "quic/test_tools/quic_framer_peer.h"
#include "quic/test_tools/quic_sent_packet_manager_peer.h"
@@ -164,6 +165,25 @@ QuicAlarm* QuicConnectionPeer::GetDiscardZeroRttDecryptionKeysAlarm(
}
// static
+QuicAlarm* QuicConnectionPeer::GetRetirePeerIssuedConnectionIdAlarm(
+ QuicConnection* connection) {
+ if (connection->peer_issued_cid_manager_ == nullptr) {
+ return nullptr;
+ }
+ return QuicConnectionIdManagerPeer::GetRetirePeerIssuedConnectionIdAlarm(
+ connection->peer_issued_cid_manager_.get());
+}
+// static
+QuicAlarm* QuicConnectionPeer::GetRetireSelfIssuedConnectionIdAlarm(
+ QuicConnection* connection) {
+ if (connection->self_issued_cid_manager_ == nullptr) {
+ return nullptr;
+ }
+ return QuicConnectionIdManagerPeer::GetRetireSelfIssuedConnectionIdAlarm(
+ connection->self_issued_cid_manager_.get());
+}
+
+// static
QuicPacketWriter* QuicConnectionPeer::GetWriter(QuicConnection* connection) {
return connection->writer_;
}
@@ -447,5 +467,16 @@ QuicByteCount QuicConnectionPeer::BytesReceivedBeforeAddressValidation(
return connection->default_path_.bytes_received_before_address_validation;
}
+// static
+void QuicConnectionPeer::EnableMultipleConnectionIdSupport(
+ QuicConnection* connection) {
+ connection->support_multiple_connection_ids_ = true;
+}
+
+// static
+void QuicConnectionPeer::ResetPeerIssuedConnectionIdManager(
+ QuicConnection* connection) {
+ connection->peer_issued_cid_manager_ = nullptr;
+}
} // 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 e76b5b4212b..1de3ae72f0b 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
@@ -8,6 +8,7 @@
#include <cstddef>
#include "absl/strings/string_view.h"
#include "quic/core/quic_connection.h"
+#include "quic/core/quic_connection_id.h"
#include "quic/core/quic_connection_stats.h"
#include "quic/core/quic_packets.h"
#include "quic/core/quic_types.h"
@@ -88,6 +89,10 @@ class QuicConnectionPeer {
QuicConnection* connection);
static QuicAlarm* GetDiscardZeroRttDecryptionKeysAlarm(
QuicConnection* connection);
+ static QuicAlarm* GetRetirePeerIssuedConnectionIdAlarm(
+ QuicConnection* connection);
+ static QuicAlarm* GetRetireSelfIssuedConnectionIdAlarm(
+ QuicConnection* connection);
static QuicPacketWriter* GetWriter(QuicConnection* connection);
// If |owns_writer| is true, takes ownership of |writer|.
@@ -185,6 +190,10 @@ class QuicConnectionPeer {
static QuicByteCount BytesReceivedBeforeAddressValidation(
QuicConnection* connection);
+
+ static void EnableMultipleConnectionIdSupport(QuicConnection* connection);
+
+ static void ResetPeerIssuedConnectionIdManager(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 57367737d52..3a553ce0838 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
@@ -87,10 +87,11 @@ void QuicDispatcherPeer::SendPublicReset(
const QuicSocketAddress& peer_address,
QuicConnectionId connection_id,
bool ietf_quic,
+ size_t received_packet_length,
std::unique_ptr<QuicPerPacketContext> packet_context) {
dispatcher->time_wait_list_manager()->SendPublicReset(
self_address, peer_address, connection_id, ietf_quic,
- std::move(packet_context));
+ received_packet_length, std::move(packet_context));
}
// static
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.h
index f3be472126b..fc8ab2014ae 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.h
@@ -57,6 +57,7 @@ class QuicDispatcherPeer {
const QuicSocketAddress& peer_address,
QuicConnectionId connection_id,
bool ietf_quic,
+ size_t received_packet_length,
std::unique_ptr<QuicPerPacketContext> packet_context);
static std::unique_ptr<QuicPerPacketContext> GetPerPacketContext(
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.cc
index 4a8c8ca4094..a3dbf843e58 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.cc
@@ -40,7 +40,8 @@ void QuicSessionPeer::SetNextOutgoingBidirectionalStreamId(QuicSession* session,
void QuicSessionPeer::SetMaxOpenIncomingStreams(QuicSession* session,
uint32_t max_streams) {
if (VersionHasIetfQuicFrames(session->transport_version())) {
- QUIC_BUG << "SetmaxOpenIncomingStreams deprecated for IETF QUIC";
+ QUIC_BUG(quic_bug_10193_1)
+ << "SetmaxOpenIncomingStreams deprecated for IETF QUIC";
session->ietf_streamid_manager_.SetMaxOpenIncomingUnidirectionalStreams(
max_streams);
session->ietf_streamid_manager_.SetMaxOpenIncomingBidirectionalStreams(
@@ -75,7 +76,8 @@ void QuicSessionPeer::SetMaxOpenIncomingUnidirectionalStreams(
void QuicSessionPeer::SetMaxOpenOutgoingStreams(QuicSession* session,
uint32_t max_streams) {
if (VersionHasIetfQuicFrames(session->transport_version())) {
- QUIC_BUG << "SetmaxOpenOutgoingStreams deprecated for IETF QUIC";
+ QUIC_BUG(quic_bug_10193_2)
+ << "SetmaxOpenOutgoingStreams deprecated for IETF QUIC";
return;
}
session->stream_id_manager_.set_max_open_outgoing_streams(max_streams);
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc
index 58eedcc0106..c547ac22610 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc
@@ -7,7 +7,9 @@
#include "quic/core/http/quic_spdy_session.h"
#include "quic/core/qpack/qpack_receive_stream.h"
#include "quic/core/quic_utils.h"
+#include "quic/platform/api/quic_flags.h"
#include "quic/test_tools/quic_session_peer.h"
+#include "common/platform/api/quiche_logging.h"
namespace quic {
namespace test {
@@ -37,18 +39,6 @@ spdy::SpdyFramer* QuicSpdySessionPeer::GetSpdyFramer(QuicSpdySession* session) {
return &session->spdy_framer_;
}
-void QuicSpdySessionPeer::SetHpackEncoderDebugVisitor(
- QuicSpdySession* session,
- std::unique_ptr<QuicHpackDebugVisitor> visitor) {
- session->SetHpackEncoderDebugVisitor(std::move(visitor));
-}
-
-void QuicSpdySessionPeer::SetHpackDecoderDebugVisitor(
- QuicSpdySession* session,
- std::unique_ptr<QuicHpackDebugVisitor> visitor) {
- session->SetHpackDecoderDebugVisitor(std::move(visitor));
-}
-
void QuicSpdySessionPeer::SetMaxInboundHeaderListSize(
QuicSpdySession* session,
size_t max_inbound_header_size) {
@@ -109,5 +99,19 @@ QpackReceiveStream* QuicSpdySessionPeer::GetQpackEncoderReceiveStream(
return session->qpack_encoder_receive_stream_;
}
+// static
+void QuicSpdySessionPeer::SetH3DatagramSupported(QuicSpdySession* session,
+ bool h3_datagram_supported) {
+ session->h3_datagram_supported_ = h3_datagram_supported;
+}
+
+// static
+void QuicSpdySessionPeer::EnableWebTransport(QuicSpdySession& session) {
+ SetQuicReloadableFlag(quic_h3_datagram, true);
+ QUICHE_DCHECK(session.WillNegotiateWebTransport());
+ session.h3_datagram_supported_ = true;
+ session.peer_supports_webtransport_ = true;
+}
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h
index c0413c6a1b7..9ba54979e9a 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h
@@ -17,7 +17,6 @@ namespace quic {
class QuicHeadersStream;
class QuicSpdySession;
-class QuicHpackDebugVisitor;
namespace test {
@@ -29,12 +28,6 @@ class QuicSpdySessionPeer {
static void SetHeadersStream(QuicSpdySession* session,
QuicHeadersStream* headers_stream);
static spdy::SpdyFramer* GetSpdyFramer(QuicSpdySession* session);
- static void SetHpackEncoderDebugVisitor(
- QuicSpdySession* session,
- std::unique_ptr<QuicHpackDebugVisitor> visitor);
- static void SetHpackDecoderDebugVisitor(
- QuicSpdySession* session,
- std::unique_ptr<QuicHpackDebugVisitor> visitor);
// Must be called before Initialize().
static void SetMaxInboundHeaderListSize(QuicSpdySession* session,
size_t max_inbound_header_size);
@@ -57,6 +50,9 @@ class QuicSpdySessionPeer {
QuicSpdySession* session);
static QpackReceiveStream* GetQpackEncoderReceiveStream(
QuicSpdySession* session);
+ static void SetH3DatagramSupported(QuicSpdySession* session,
+ bool h3_datagram_supported);
+ static void EnableWebTransport(QuicSpdySession& session);
};
} // 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
new file mode 100644
index 00000000000..9623d752027
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_backend.cc
@@ -0,0 +1,139 @@
+// 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/test_tools/quic_test_backend.h"
+
+#include <cstring>
+#include <memory>
+
+#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"
+#include "quic/tools/web_transport_test_visitors.h"
+
+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,
+ 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<EchoWebTransportServer>(session);
+ return response;
+ }
+
+ WebTransportResponse response;
+ response.response_headers[":status"] = "404";
+ return response;
+}
+
+} // namespace test
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_backend.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_backend.h
new file mode 100644
index 00000000000..66e1213641c
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_backend.h
@@ -0,0 +1,34 @@
+// 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_TEST_TOOLS_QUIC_TEST_BACKEND_H_
+#define QUICHE_QUIC_TEST_TOOLS_QUIC_TEST_BACKEND_H_
+
+#include "quic/tools/quic_memory_cache_backend.h"
+
+namespace quic {
+namespace test {
+
+// QuicTestBackend is a QuicSimpleServer backend usable in tests. It has extra
+// WebTransport endpoints on top of what QuicMemoryCacheBackend already
+// provides.
+class QuicTestBackend : public QuicMemoryCacheBackend {
+ public:
+ WebTransportResponse ProcessWebTransportRequest(
+ const spdy::Http2HeaderBlock& request_headers,
+ WebTransportSession* session) override;
+ bool SupportsWebTransport() override { return enable_webtransport_; }
+
+ void set_enable_webtransport(bool enable_webtransport) {
+ enable_webtransport_ = enable_webtransport;
+ }
+
+ private:
+ bool enable_webtransport_ = false;
+};
+
+} // namespace test
+} // namespace quic
+
+#endif // QUICHE_QUIC_TEST_TOOLS_QUIC_TEST_BACKEND_H_
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 41339508501..ed823b1e156 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.cc
@@ -20,7 +20,6 @@
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
-#include "quic/platform/api/quic_ptr_util.h"
#include "quic/platform/api/quic_stack_trace.h"
#include "quic/test_tools/crypto_test_utils.h"
#include "quic/test_tools/quic_client_peer.h"
@@ -236,7 +235,7 @@ MockableQuicClient::MockableQuicClient(
epoll_server,
std::make_unique<MockableQuicClientEpollNetworkHelper>(epoll_server,
this),
- QuicWrapUnique(new RecordingProofVerifier(std::move(proof_verifier))),
+ std::make_unique<RecordingProofVerifier>(std::move(proof_verifier)),
std::move(session_cache)),
override_server_connection_id_(EmptyQuicConnectionId()),
server_connection_id_overridden_(false),
@@ -311,6 +310,9 @@ void MockableQuicClient::UseWriter(QuicPacketWriterWrapper* writer) {
void MockableQuicClient::set_peer_address(const QuicSocketAddress& address) {
mockable_network_helper()->set_peer_address(address);
+ if (client_session() != nullptr) {
+ client_session()->AddKnownServerAddress(address);
+ }
}
const QuicReceivedPacket* MockableQuicClient::last_incoming_packet() {
@@ -634,7 +636,7 @@ bool QuicTestClient::connected() const {
void QuicTestClient::Connect() {
if (connected()) {
- QUIC_BUG << "Cannot connect already-connected client";
+ QUIC_BUG(quic_bug_10133_1) << "Cannot connect already-connected client";
return;
}
if (!connect_attempted_) {
@@ -796,7 +798,8 @@ void QuicTestClient::OnClose(QuicSpdyStream* stream) {
closed_stream_states_.insert(std::make_pair(
id,
PerStreamState(
- client_stream->stream_error(), true,
+ // Set response_complete to true iff stream is closed while connected.
+ client_stream->stream_error(), connected(),
client_stream->headers_decompressed(),
client_stream->response_headers(),
client_stream->preliminary_headers(),
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.cc
index 55170b20d6d..f6e2c34a9b2 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.cc
@@ -6,10 +6,10 @@
#include <utility>
+#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "quic/core/quic_epoll_alarm_factory.h"
#include "quic/core/quic_epoll_connection_helper.h"
-#include "quic/platform/api/quic_ptr_util.h"
#include "quic/tools/quic_simple_crypto_server_stream_helper.h"
#include "quic/tools/quic_simple_dispatcher.h"
#include "quic/tools/quic_simple_server_session.h"
@@ -49,7 +49,7 @@ class CustomStreamSession : public QuicSimpleServerSession {
if (stream_factory_) {
QuicSpdyStream* stream =
stream_factory_->CreateStream(id, this, server_backend());
- ActivateStream(QuicWrapUnique(stream));
+ ActivateStream(absl::WrapUnique(stream));
return stream;
}
return QuicSimpleServerSession::CreateIncomingStream(id);
@@ -98,12 +98,13 @@ class QuicTestDispatcher : public QuicSimpleDispatcher {
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
absl::string_view alpn,
- const ParsedQuicVersion& version) override {
+ const ParsedQuicVersion& version,
+ absl::string_view sni) override {
QuicReaderMutexLock lock(&factory_lock_);
if (session_factory_ == nullptr && stream_factory_ == nullptr &&
crypto_stream_factory_ == nullptr) {
return QuicSimpleDispatcher::CreateQuicSession(
- id, self_address, peer_address, alpn, version);
+ id, self_address, peer_address, alpn, version, sni);
}
QuicConnection* connection = new QuicConnection(
id, self_address, peer_address, helper(), alarm_factory(), writer(),
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.cc
index 035680cf602..5feb6462321 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.cc
@@ -449,7 +449,7 @@ bool NoOpFramerVisitor::OnAckFrequencyFrame(
}
bool NoOpFramerVisitor::IsValidStatelessResetToken(
- QuicUint128 /*token*/) const {
+ const StatelessResetToken& /*token*/) const {
return false;
}
@@ -1535,11 +1535,11 @@ bool WriteServerVersionNegotiationProbeResponse(
const char* source_connection_id_bytes,
uint8_t source_connection_id_length) {
if (packet_bytes == nullptr) {
- QUIC_BUG << "Invalid packet_bytes";
+ QUIC_BUG(quic_bug_10256_1) << "Invalid packet_bytes";
return false;
}
if (packet_length_out == nullptr) {
- QUIC_BUG << "Invalid packet_length_out";
+ QUIC_BUG(quic_bug_10256_2) << "Invalid packet_length_out";
return false;
}
QuicConnectionId source_connection_id(source_connection_id_bytes,
@@ -1550,12 +1550,13 @@ bool WriteServerVersionNegotiationProbeResponse(
/*ietf_quic=*/true, /*use_length_prefix=*/true,
ParsedQuicVersionVector{});
if (!encrypted_packet) {
- QUIC_BUG << "Failed to create version negotiation packet";
+ QUIC_BUG(quic_bug_10256_3) << "Failed to create version negotiation packet";
return false;
}
if (*packet_length_out < encrypted_packet->length()) {
- QUIC_BUG << "Invalid *packet_length_out " << *packet_length_out << " < "
- << encrypted_packet->length();
+ QUIC_BUG(quic_bug_10256_4)
+ << "Invalid *packet_length_out " << *packet_length_out << " < "
+ << encrypted_packet->length();
return false;
}
*packet_length_out = encrypted_packet->length();
@@ -1569,20 +1570,21 @@ bool ParseClientVersionNegotiationProbePacket(
char* destination_connection_id_bytes,
uint8_t* destination_connection_id_length_out) {
if (packet_bytes == nullptr) {
- QUIC_BUG << "Invalid packet_bytes";
+ QUIC_BUG(quic_bug_10256_5) << "Invalid packet_bytes";
return false;
}
if (packet_length < kMinPacketSizeForVersionNegotiation ||
packet_length > 65535) {
- QUIC_BUG << "Invalid packet_length";
+ QUIC_BUG(quic_bug_10256_6) << "Invalid packet_length";
return false;
}
if (destination_connection_id_bytes == nullptr) {
- QUIC_BUG << "Invalid destination_connection_id_bytes";
+ QUIC_BUG(quic_bug_10256_7) << "Invalid destination_connection_id_bytes";
return false;
}
if (destination_connection_id_length_out == nullptr) {
- QUIC_BUG << "Invalid destination_connection_id_length_out";
+ QUIC_BUG(quic_bug_10256_8)
+ << "Invalid destination_connection_id_length_out";
return false;
}
@@ -1602,16 +1604,17 @@ bool ParseClientVersionNegotiationProbePacket(
&parsed_version, &destination_connection_id, &source_connection_id,
&retry_token_present, &retry_token, &detailed_error);
if (error != QUIC_NO_ERROR) {
- QUIC_BUG << "Failed to parse packet: " << detailed_error;
+ QUIC_BUG(quic_bug_10256_9) << "Failed to parse packet: " << detailed_error;
return false;
}
if (!version_present) {
- QUIC_BUG << "Packet is not a long header";
+ QUIC_BUG(quic_bug_10256_10) << "Packet is not a long header";
return false;
}
if (*destination_connection_id_length_out <
destination_connection_id.length()) {
- QUIC_BUG << "destination_connection_id_length_out too small";
+ QUIC_BUG(quic_bug_10256_11)
+ << "destination_connection_id_length_out too small";
return false;
}
*destination_connection_id_length_out = destination_connection_id.length();
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 fe255b45d4f..2f16b1e072b 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
@@ -33,6 +33,7 @@
#include "quic/core/quic_types.h"
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_mem_slice_storage.h"
+#include "quic/platform/api/quic_socket_address.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/mock_clock.h"
#include "quic/test_tools/mock_quic_session_visitor.h"
@@ -430,7 +431,7 @@ class MockFramerVisitor : public QuicFramerVisitorInterface {
MOCK_METHOD(void, OnPacketComplete, (), (override));
MOCK_METHOD(bool,
IsValidStatelessResetToken,
- (QuicUint128),
+ (const StatelessResetToken&),
(const, override));
MOCK_METHOD(void,
OnAuthenticatedIetfStatelessResetPacket,
@@ -503,7 +504,8 @@ class NoOpFramerVisitor : public QuicFramerVisitorInterface {
bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) override;
bool OnAckFrequencyFrame(const QuicAckFrequencyFrame& frame) override;
void OnPacketComplete() override {}
- bool IsValidStatelessResetToken(QuicUint128 token) const override;
+ bool IsValidStatelessResetToken(
+ const StatelessResetToken& token) const override;
void OnAuthenticatedIetfStatelessResetPacket(
const QuicIetfStatelessResetPacket& /*packet*/) override {}
void OnKeyUpdate(KeyUpdateReason /*reason*/) override {}
@@ -577,6 +579,22 @@ class MockQuicConnectionVisitor : public QuicConnectionVisitorInterface {
SendAckFrequency,
(const QuicAckFrequencyFrame& frame),
(override));
+ MOCK_METHOD(void,
+ SendNewConnectionId,
+ (const QuicNewConnectionIdFrame& frame),
+ (override));
+ MOCK_METHOD(void,
+ SendRetireConnectionId,
+ (uint64_t sequence_number),
+ (override));
+ MOCK_METHOD(void,
+ OnServerConnectionIdIssued,
+ (const QuicConnectionId& server_connection_id),
+ (override));
+ MOCK_METHOD(void,
+ OnServerConnectionIdRetired,
+ (const QuicConnectionId& server_connection_id),
+ (override));
MOCK_METHOD(bool, AllowSelfAddressChange, (), (const, override));
MOCK_METHOD(HandshakeState, GetHandshakeState, (), (const, override));
MOCK_METHOD(bool,
@@ -606,6 +624,11 @@ class MockQuicConnectionVisitor : public QuicConnectionVisitorInterface {
MOCK_METHOD(void, BeforeConnectionCloseSent, (), (override));
MOCK_METHOD(bool, ValidateToken, (absl::string_view), (const, override));
MOCK_METHOD(void, MaybeSendAddressToken, (), (override));
+
+ bool IsKnownServerAddress(
+ const QuicSocketAddress& /*address*/) const override {
+ return false;
+ }
};
class MockQuicConnectionHelper : public QuicConnectionHelperInterface {
@@ -771,6 +794,15 @@ class MockQuicConnection : public QuicConnection {
connection_close_behavior);
}
+ void ReallyCloseConnection4(
+ QuicErrorCode error,
+ QuicIetfTransportErrorCodes ietf_error,
+ const std::string& details,
+ ConnectionCloseBehavior connection_close_behavior) {
+ QuicConnection::CloseConnection(error, ietf_error, details,
+ connection_close_behavior);
+ }
+
void ReallySendConnectionClosePacket(QuicErrorCode error,
QuicIetfTransportErrorCodes ietf_error,
const std::string& details) {
@@ -1094,6 +1126,11 @@ class MockHttp3DebugVisitor : public Http3DebugVisitor {
(override));
MOCK_METHOD(void,
+ OnSettingsFrameReceivedViaAlps,
+ (const SettingsFrame&),
+ (override));
+
+ MOCK_METHOD(void,
OnAcceptChFrameReceivedViaAlps,
(const AcceptChFrame&),
(override));
@@ -1958,7 +1995,7 @@ class TaggingDecrypter : public QuicDecrypter {
}
bool SetPreliminaryKey(absl::string_view /*key*/) override {
- QUIC_BUG << "should not be called";
+ QUIC_BUG(quic_bug_10230_1) << "should not be called";
return false;
}
@@ -2284,6 +2321,32 @@ bool WriteServerVersionNegotiationProbeResponse(
const char* source_connection_id_bytes,
uint8_t source_connection_id_length);
+// Implementation of Http3DatagramVisitor which saves all received datagrams.
+class SavingHttp3DatagramVisitor
+ : public QuicSpdySession::Http3DatagramVisitor {
+ public:
+ struct SavedHttp3Datagram {
+ QuicDatagramFlowId flow_id;
+ std::string payload;
+ bool operator==(const SavedHttp3Datagram& o) const {
+ return flow_id == o.flow_id && payload == o.payload;
+ }
+ };
+ const std::vector<SavedHttp3Datagram>& received_h3_datagrams() const {
+ return received_h3_datagrams_;
+ }
+
+ // Override from QuicSpdySession::Http3DatagramVisitor.
+ void OnHttp3Datagram(QuicDatagramFlowId flow_id,
+ absl::string_view payload) override {
+ received_h3_datagrams_.push_back(
+ SavedHttp3Datagram{flow_id, std::string(payload)});
+ }
+
+ private:
+ std::vector<SavedHttp3Datagram> received_h3_datagrams_;
+};
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h
index e0fcebc6ebd..df52093e05a 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h
@@ -5,14 +5,14 @@
#ifndef QUICHE_QUIC_TEST_TOOLS_QUIC_TRANSPORT_TEST_TOOLS_H_
#define QUICHE_QUIC_TEST_TOOLS_QUIC_TRANSPORT_TEST_TOOLS_H_
+#include "quic/core/web_transport_interface.h"
#include "quic/platform/api/quic_test.h"
-#include "quic/quic_transport/quic_transport_client_session.h"
#include "quic/quic_transport/quic_transport_server_session.h"
namespace quic {
namespace test {
-class MockClientVisitor : public QuicTransportClientSession::ClientVisitor {
+class MockClientVisitor : public WebTransportVisitor {
public:
MOCK_METHOD(void, OnSessionReady, (), (override));
MOCK_METHOD(void, OnIncomingBidirectionalStreamAvailable, (), (override));
@@ -28,10 +28,9 @@ class MockServerVisitor : public QuicTransportServerSession::ServerVisitor {
MOCK_METHOD(bool, ProcessPath, (const GURL&), (override));
};
-class MockStreamVisitor : public QuicTransportStream::Visitor {
+class MockStreamVisitor : public WebTransportStreamVisitor {
public:
MOCK_METHOD(void, OnCanRead, (), (override));
- MOCK_METHOD(void, OnFinRead, (), (override));
MOCK_METHOD(void, OnCanWrite, (), (override));
};
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simple_quic_framer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simple_quic_framer.cc
index 96b131877fb..92363ec8eea 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simple_quic_framer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simple_quic_framer.cc
@@ -7,10 +7,11 @@
#include <memory>
#include <utility>
+#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "quic/core/crypto/quic_decrypter.h"
#include "quic/core/crypto/quic_encrypter.h"
-#include "quic/platform/api/quic_ptr_util.h"
+#include "quic/core/quic_types.h"
namespace quic {
namespace test {
@@ -73,7 +74,7 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
// Save a copy of the data so it is valid after the packet is processed.
std::string* string_data =
new std::string(frame.data_buffer, frame.data_length);
- stream_data_.push_back(QuicWrapUnique(string_data));
+ stream_data_.push_back(absl::WrapUnique(string_data));
// TODO(ianswett): A pointer isn't necessary with emplace_back.
stream_frames_.push_back(std::make_unique<QuicStreamFrame>(
frame.stream_id, frame.fin, frame.offset,
@@ -85,7 +86,7 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
// Save a copy of the data so it is valid after the packet is processed.
std::string* string_data =
new std::string(frame.data_buffer, frame.data_length);
- crypto_data_.push_back(QuicWrapUnique(string_data));
+ crypto_data_.push_back(absl::WrapUnique(string_data));
crypto_frames_.push_back(std::make_unique<QuicCryptoFrame>(
frame.level, frame.offset, absl::string_view(*string_data)));
return true;
@@ -210,7 +211,8 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
void OnPacketComplete() override {}
- bool IsValidStatelessResetToken(QuicUint128 /*token*/) const override {
+ bool IsValidStatelessResetToken(
+ const StatelessResetToken& /*token*/) const override {
return false;
}
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.cc
index 415332ad274..51d4017948f 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.cc
@@ -163,6 +163,17 @@ void SimpleSessionNotifier::NeuterUnencryptedData() {
}
void SimpleSessionNotifier::OnCanWrite() {
+ if (connection_->donot_write_mid_packet_processing()) {
+ if (connection_->framer().is_processing_packet()) {
+ // Do not write data in the middle of packet processing because rest
+ // frames in the packet may change the data to write. For example, lost
+ // data could be acknowledged. Also, connection is going to emit
+ // OnCanWrite signal post packet processing.
+ QUIC_BUG(simple_notifier_write_mid_packet_processing)
+ << "Try to write mid packet processing.";
+ return;
+ }
+ }
if (!RetransmitLostCryptoData() || !RetransmitLostControlFrames() ||
!RetransmitLostStreamData()) {
return;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/queue.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/queue.cc
index 5113cf79791..c286bf6e853 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/queue.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/queue.cc
@@ -43,7 +43,7 @@ void Queue::AcceptPacket(std::unique_ptr<Packet> packet) {
}
bytes_queued_ += packet->size;
- queue_.emplace(std::move(packet), current_bundle_);
+ queue_.emplace_back(std::move(packet), current_bundle_);
if (IsAggregationEnabled()) {
current_bundle_bytes_ += queue_.front().packet->size;
@@ -65,7 +65,7 @@ void Queue::Act() {
bytes_queued_ -= queue_.front().packet->size;
tx_port_->AcceptPacket(std::move(queue_.front().packet));
- queue_.pop();
+ queue_.pop_front();
if (listener_ != nullptr) {
listener_->OnPacketDequeued();
}
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 a291f48eeab..943b8b069a0 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,6 +6,7 @@
#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"
namespace quic {
@@ -109,7 +110,7 @@ class Queue : public Actor, public UnconstrainedPortInterface {
std::unique_ptr<QuicAlarm> aggregation_timeout_alarm_;
ConstrainedPortInterface* tx_port_;
- QuicQueue<EnqueuedPacket> queue_;
+ QuicCircularDeque<EnqueuedPacket> queue_;
ListenerInterface* listener_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.cc
index cb0b58e9db5..fd5c5b7a4a4 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.cc
@@ -228,7 +228,8 @@ bool QuicEndpoint::DataProducer::WriteCryptoData(EncryptionLevel /*level*/,
QuicStreamOffset /*offset*/,
QuicByteCount /*data_length*/,
QuicDataWriter* /*writer*/) {
- QUIC_BUG << "QuicEndpoint::DataProducer::WriteCryptoData is unimplemented";
+ QUIC_BUG(quic_bug_10157_1)
+ << "QuicEndpoint::DataProducer::WriteCryptoData is unimplemented";
return false;
}
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h
index 3d81c706550..01d35d3a589 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h
@@ -81,6 +81,13 @@ class QuicEndpoint : public QuicEndpointBase,
void OnForwardProgressMadeAfterPathDegrading() override {}
void OnAckNeedsRetransmittableFrame() override {}
void SendAckFrequency(const QuicAckFrequencyFrame& /*frame*/) override {}
+ void SendNewConnectionId(const QuicNewConnectionIdFrame& /*frame*/) override {
+ }
+ void SendRetireConnectionId(uint64_t /*sequence_number*/) override {}
+ void OnServerConnectionIdIssued(
+ const QuicConnectionId& /*server_connection_id*/) override {}
+ void OnServerConnectionIdRetired(
+ const QuicConnectionId& /*server_connection_id*/) override {}
bool AllowSelfAddressChange() const override;
HandshakeState GetHandshakeState() const override;
bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& /*frame*/) override {
@@ -107,6 +114,10 @@ class QuicEndpoint : public QuicEndpointBase,
return true;
}
void MaybeSendAddressToken() override {}
+ bool IsKnownServerAddress(
+ const QuicSocketAddress& /*address*/) const override {
+ return false;
+ }
// End QuicConnectionVisitorInterface implementation.
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator.cc
index 8d68ee4145b..a9835e85d0a 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator.cc
@@ -155,10 +155,11 @@ void Simulator::HandleNextScheduledActor() {
Unschedule(actor);
if (clock_.Now() > event_time) {
- QUIC_BUG << "Error: event registered by [" << actor->name()
- << "] requires travelling back in time. Current time: "
- << clock_.Now().ToDebuggingValue()
- << ", scheduled time: " << event_time.ToDebuggingValue();
+ QUIC_BUG(quic_bug_10150_1)
+ << "Error: event registered by [" << actor->name()
+ << "] requires travelling back in time. Current time: "
+ << clock_.Now().ToDebuggingValue()
+ << ", scheduled time: " << event_time.ToDebuggingValue();
}
clock_.now_ = event_time;
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 a7edd78e6f8..1c5cad87112 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
@@ -50,11 +50,20 @@ class QuicBackendResponse {
~QuicBackendResponse();
+ const std::vector<spdy::Http2HeaderBlock>& early_hints() const {
+ return early_hints_;
+ }
SpecialResponseType response_type() const { return response_type_; }
const spdy::Http2HeaderBlock& headers() const { return headers_; }
const spdy::Http2HeaderBlock& trailers() const { return trailers_; }
const absl::string_view body() const { return absl::string_view(body_); }
+ void AddEarlyHints(const spdy::Http2HeaderBlock& headers) {
+ spdy::Http2HeaderBlock hints = headers.Clone();
+ hints[":status"] = "103";
+ early_hints_.push_back(std::move(hints));
+ }
+
void set_response_type(SpecialResponseType response_type) {
response_type_ = response_type;
}
@@ -70,6 +79,7 @@ class QuicBackendResponse {
}
private:
+ std::vector<spdy::Http2HeaderBlock> early_hints_;
SpecialResponseType response_type_;
spdy::Http2HeaderBlock headers_;
spdy::Http2HeaderBlock trailers_;
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_client.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_client.cc
index f8375ab3b13..e659b4a7b84 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_client.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_client.cc
@@ -24,7 +24,6 @@
#include "quic/core/quic_server_id.h"
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_logging.h"
-#include "quic/platform/api/quic_ptr_util.h"
#include "quic/platform/api/quic_socket_address.h"
#include "quic/tools/quic_simple_client_session.h"
@@ -67,7 +66,7 @@ QuicClient::QuicClient(QuicSocketAddress server_address,
supported_versions,
QuicConfig(),
epoll_server,
- QuicWrapUnique(new QuicClientEpollNetworkHelper(epoll_server, this)),
+ std::make_unique<QuicClientEpollNetworkHelper>(epoll_server, this),
std::move(proof_verifier),
nullptr) {}
@@ -83,7 +82,7 @@ QuicClient::QuicClient(QuicSocketAddress server_address,
supported_versions,
QuicConfig(),
epoll_server,
- QuicWrapUnique(new QuicClientEpollNetworkHelper(epoll_server, this)),
+ std::make_unique<QuicClientEpollNetworkHelper>(epoll_server, this),
std::move(proof_verifier),
std::move(session_cache)) {}
@@ -100,7 +99,7 @@ QuicClient::QuicClient(QuicSocketAddress server_address,
supported_versions,
config,
epoll_server,
- QuicWrapUnique(new QuicClientEpollNetworkHelper(epoll_server, this)),
+ std::make_unique<QuicClientEpollNetworkHelper>(epoll_server, this),
std::move(proof_verifier),
std::move(session_cache)) {}
@@ -165,7 +164,7 @@ std::unique_ptr<QuicSession> QuicClient::CreateQuicClientSession(
QuicConnection* connection) {
return std::make_unique<QuicSimpleClientSession>(
*config(), supported_versions, connection, server_id(), crypto_config(),
- push_promise_index(), drop_response_body());
+ push_promise_index(), drop_response_body(), enable_web_transport());
}
QuicClientEpollNetworkHelper* QuicClient::epoll_network_helper() {
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 1737f8cb549..7077f16506e 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
@@ -147,7 +147,7 @@ bool QuicClientBase::Connect() {
num_attempts++;
}
if (session() == nullptr) {
- QUIC_BUG << "Missing session after Connect";
+ QUIC_BUG(quic_bug_10906_1) << "Missing session after Connect";
return false;
}
return session()->connection()->connected();
@@ -230,7 +230,8 @@ bool QuicClientBase::EncryptionBeingEstablished() {
bool QuicClientBase::WaitForEvents() {
if (!connected()) {
- QUIC_BUG << "Cannot call WaitForEvents on non-connected client";
+ QUIC_BUG(quic_bug_10906_2)
+ << "Cannot call WaitForEvents on non-connected client";
return false;
}
@@ -335,7 +336,8 @@ const QuicClientBase::NetworkHelper* QuicClientBase::network_helper() const {
void QuicClientBase::WaitForStreamToClose(QuicStreamId id) {
if (!connected()) {
- QUIC_BUG << "Cannot WaitForStreamToClose on non-connected client";
+ QUIC_BUG(quic_bug_10906_3)
+ << "Cannot WaitForStreamToClose on non-connected client";
return;
}
@@ -346,7 +348,8 @@ void QuicClientBase::WaitForStreamToClose(QuicStreamId id) {
bool QuicClientBase::WaitForOneRttKeysAvailable() {
if (!connected()) {
- QUIC_BUG << "Cannot WaitForOneRttKeysAvailable on non-connected client";
+ QUIC_BUG(quic_bug_10906_4)
+ << "Cannot WaitForOneRttKeysAvailable on non-connected client";
return false;
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_client_interop_test_bin.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_client_interop_test_bin.cc
index f67a338b09c..eee0ae7f891 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_client_interop_test_bin.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_client_interop_test_bin.cc
@@ -25,6 +25,12 @@ DEFINE_QUIC_COMMAND_LINE_FLAG(std::string,
"",
"The IP or hostname to connect to.");
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ std::string,
+ quic_version,
+ "",
+ "The QUIC version to use. Defaults to most recent IETF QUIC version.");
+
DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t, port, 0, "The port to connect to.");
namespace quic {
@@ -366,21 +372,8 @@ void QuicClientInteropRunner::SendRequest(
std::set<Feature> ServerSupport(std::string dns_host,
std::string url_host,
- int port) {
- // Enable IETF version support.
- QuicVersionInitializeSupportForIetfDraft();
- ParsedQuicVersion version = UnsupportedQuicVersion();
- for (const ParsedQuicVersion& vers : AllSupportedVersions()) {
- // Find the first version that supports IETF QUIC.
- if (vers.HasIetfQuicFrames() &&
- vers.handshake_protocol == quic::PROTOCOL_TLS1_3) {
- version = vers;
- break;
- }
- }
- QUICHE_CHECK(version.IsKnown());
- QuicEnableVersion(version);
-
+ int port,
+ ParsedQuicVersion version) {
std::cout << "Attempting interop with version " << version << std::endl;
// Build the client, and try to connect.
@@ -440,7 +433,26 @@ int main(int argc, char* argv[]) {
url_host = dns_host;
}
- auto supported_features = quic::ServerSupport(dns_host, url_host, port);
+ // Pick QUIC version to use.
+ quic::QuicVersionInitializeSupportForIetfDraft();
+ quic::ParsedQuicVersion version = quic::UnsupportedQuicVersion();
+ std::string quic_version_string = GetQuicFlag(FLAGS_quic_version);
+ if (!quic_version_string.empty()) {
+ version = quic::ParseQuicVersionString(quic_version_string);
+ } else {
+ for (const quic::ParsedQuicVersion& vers : quic::AllSupportedVersions()) {
+ // Use the most recent IETF QUIC version.
+ if (vers.HasIetfQuicFrames() && vers.UsesHttp3() && vers.UsesTls()) {
+ version = vers;
+ break;
+ }
+ }
+ }
+ QUICHE_CHECK(version.IsKnown());
+ QuicEnableVersion(version);
+
+ auto supported_features =
+ quic::ServerSupport(dns_host, url_host, port, version);
std::cout << "Results for " << url_host << ":" << port << std::endl;
int current_row = 1;
for (auto feature : supported_features) {
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 c67e5b35be8..e76a6cffb3c 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
@@ -8,6 +8,7 @@
#include "absl/strings/match.h"
#include "absl/strings/numbers.h"
+#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "quic/core/http/spdy_utils.h"
#include "quic/platform/api/quic_bug_tracker.h"
@@ -171,10 +172,8 @@ void QuicMemoryCacheBackend::AddSimpleResponse(absl::string_view host,
int response_code,
absl::string_view body) {
Http2HeaderBlock response_headers;
- response_headers[":status"] =
- quiche::QuicheTextUtils::Uint64ToString(response_code);
- response_headers["content-length"] =
- quiche::QuicheTextUtils::Uint64ToString(body.length());
+ response_headers[":status"] = absl::StrCat(response_code);
+ response_headers["content-length"] = absl::StrCat(body.length());
AddResponse(host, path, std::move(response_headers), body);
}
@@ -199,7 +198,7 @@ void QuicMemoryCacheBackend::AddResponse(absl::string_view host,
absl::string_view response_body) {
AddResponseImpl(host, path, QuicBackendResponse::REGULAR_RESPONSE,
std::move(response_headers), response_body,
- Http2HeaderBlock());
+ Http2HeaderBlock(), std::vector<spdy::Http2HeaderBlock>());
}
void QuicMemoryCacheBackend::AddResponse(absl::string_view host,
@@ -209,7 +208,19 @@ void QuicMemoryCacheBackend::AddResponse(absl::string_view host,
Http2HeaderBlock response_trailers) {
AddResponseImpl(host, path, QuicBackendResponse::REGULAR_RESPONSE,
std::move(response_headers), response_body,
- std::move(response_trailers));
+ std::move(response_trailers),
+ std::vector<spdy::Http2HeaderBlock>());
+}
+
+void QuicMemoryCacheBackend::AddResponseWithEarlyHints(
+ absl::string_view host,
+ absl::string_view path,
+ spdy::Http2HeaderBlock response_headers,
+ absl::string_view response_body,
+ const std::vector<spdy::Http2HeaderBlock>& early_hints) {
+ AddResponseImpl(host, path, QuicBackendResponse::REGULAR_RESPONSE,
+ std::move(response_headers), response_body,
+ Http2HeaderBlock(), early_hints);
}
void QuicMemoryCacheBackend::AddSpecialResponse(
@@ -217,7 +228,7 @@ void QuicMemoryCacheBackend::AddSpecialResponse(
absl::string_view path,
SpecialResponseType response_type) {
AddResponseImpl(host, path, response_type, Http2HeaderBlock(), "",
- Http2HeaderBlock());
+ Http2HeaderBlock(), std::vector<spdy::Http2HeaderBlock>());
}
void QuicMemoryCacheBackend::AddSpecialResponse(
@@ -227,7 +238,8 @@ void QuicMemoryCacheBackend::AddSpecialResponse(
absl::string_view response_body,
SpecialResponseType response_type) {
AddResponseImpl(host, path, response_type, std::move(response_headers),
- response_body, Http2HeaderBlock());
+ response_body, Http2HeaderBlock(),
+ std::vector<spdy::Http2HeaderBlock>());
}
QuicMemoryCacheBackend::QuicMemoryCacheBackend() : cache_initialized_(false) {}
@@ -235,7 +247,7 @@ QuicMemoryCacheBackend::QuicMemoryCacheBackend() : cache_initialized_(false) {}
bool QuicMemoryCacheBackend::InitializeBackend(
const std::string& cache_directory) {
if (cache_directory.empty()) {
- QUIC_BUG << "cache_directory must not be empty.";
+ QUIC_BUG(quic_bug_10932_1) << "cache_directory must not be empty.";
return false;
}
QUIC_LOG(INFO)
@@ -274,7 +286,8 @@ bool QuicMemoryCacheBackend::InitializeBackend(
QuicUrl url(push_url);
const QuicBackendResponse* response = GetResponse(url.host(), url.path());
if (!response) {
- QUIC_BUG << "Push URL '" << push_url << "' not found.";
+ QUIC_BUG(quic_bug_10932_2)
+ << "Push URL '" << push_url << "' not found.";
return false;
}
push_resources.push_back(ServerPushInfo(url, response->headers().Clone(),
@@ -316,8 +329,13 @@ void QuicMemoryCacheBackend::FetchResponseFromBackend(
quic_response = GetResponse(authority->second, path->second);
}
- std::string request_url =
- std::string(authority->second) + std::string(path->second);
+ std::string request_url;
+ if (authority != request_headers.end()) {
+ request_url = std::string(authority->second);
+ }
+ 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 "
@@ -356,14 +374,16 @@ void QuicMemoryCacheBackend::AddResponseImpl(
SpecialResponseType response_type,
Http2HeaderBlock response_headers,
absl::string_view response_body,
- Http2HeaderBlock response_trailers) {
+ Http2HeaderBlock response_trailers,
+ const std::vector<spdy::Http2HeaderBlock>& early_hints) {
QuicWriterMutexLock lock(&response_mutex_);
QUICHE_DCHECK(!host.empty())
<< "Host must be populated, e.g. \"www.google.com\"";
std::string key = GetKey(host, path);
if (QuicContainsKey(responses_, key)) {
- QUIC_BUG << "Response for '" << key << "' already exists!";
+ QUIC_BUG(quic_bug_10932_3)
+ << "Response for '" << key << "' already exists!";
return;
}
auto new_response = std::make_unique<QuicBackendResponse>();
@@ -371,6 +391,9 @@ void QuicMemoryCacheBackend::AddResponseImpl(
new_response->set_headers(std::move(response_headers));
new_response->set_body(response_body);
new_response->set_trailers(std::move(response_trailers));
+ for (auto& headers : early_hints) {
+ new_response->AddEarlyHints(headers);
+ }
QUIC_DVLOG(1) << "Add response with key " << key;
responses_[key] = std::move(new_response);
}
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 5e4b2674dd9..8ba6d605218 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
@@ -110,6 +110,14 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend {
absl::string_view response_body,
spdy::Http2HeaderBlock response_trailers);
+ // Add a response, with 103 Early Hints, to the cache.
+ void AddResponseWithEarlyHints(
+ absl::string_view host,
+ absl::string_view path,
+ spdy::Http2HeaderBlock response_headers,
+ absl::string_view response_body,
+ const std::vector<spdy::Http2HeaderBlock>& early_hints);
+
// Simulate a special behavior at a particular path.
void AddSpecialResponse(
absl::string_view host,
@@ -152,7 +160,8 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend {
QuicBackendResponse::SpecialResponseType response_type,
spdy::Http2HeaderBlock response_headers,
absl::string_view response_body,
- spdy::Http2HeaderBlock response_trailers);
+ spdy::Http2HeaderBlock response_trailers,
+ const std::vector<spdy::Http2HeaderBlock>& early_hints);
std::string GetKey(absl::string_view host, absl::string_view path) const;
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend_test.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend_test.cc
index e86bb872b47..d0383e19b6e 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend_test.cc
@@ -10,7 +10,6 @@
#include "quic/platform/api/quic_map_util.h"
#include "quic/platform/api/quic_test.h"
#include "quic/tools/quic_backend_response.h"
-#include "common/platform/api/quiche_text_utils.h"
namespace quic {
namespace test {
@@ -62,8 +61,7 @@ TEST_F(QuicMemoryCacheBackendTest, AddResponse) {
spdy::Http2HeaderBlock response_headers;
response_headers[":status"] = "200";
- response_headers["content-length"] =
- quiche::QuicheTextUtils::Uint64ToString(kResponseBody.size());
+ response_headers["content-length"] = absl::StrCat(kResponseBody.size());
spdy::Http2HeaderBlock response_trailers;
response_trailers["key-1"] = "value-1";
@@ -184,16 +182,14 @@ TEST_F(QuicMemoryCacheBackendTest, AddSimpleResponseWithServerPushResources) {
std::list<ServerPushInfo> push_resources;
std::string scheme = "http";
for (int i = 0; i < NumResources; ++i) {
- std::string path =
- "/server_push_src" + quiche::QuicheTextUtils::Uint64ToString(i);
+ std::string path = absl::StrCat("/server_push_src", i);
std::string url = scheme + "://" + request_host + path;
QuicUrl resource_url(url);
std::string body =
absl::StrCat("This is server push response body for ", path);
spdy::Http2HeaderBlock response_headers;
response_headers[":status"] = "200";
- response_headers["content-length"] =
- quiche::QuicheTextUtils::Uint64ToString(body.size());
+ response_headers["content-length"] = absl::StrCat(body.size());
push_resources.push_back(
ServerPushInfo(resource_url, response_headers.Clone(), i, body));
}
@@ -224,15 +220,13 @@ TEST_F(QuicMemoryCacheBackendTest, GetServerPushResourcesAndPushResponses) {
"404"};
std::list<ServerPushInfo> push_resources;
for (int i = 0; i < NumResources; ++i) {
- std::string path =
- "/server_push_src" + quiche::QuicheTextUtils::Uint64ToString(i);
+ std::string path = absl::StrCat("/server_push_src", i);
std::string url = scheme + "://" + request_host + path;
QuicUrl resource_url(url);
std::string body = "This is server push response body for " + path;
spdy::Http2HeaderBlock response_headers;
response_headers[":status"] = push_response_status[i];
- response_headers["content-length"] =
- quiche::QuicheTextUtils::Uint64ToString(body.size());
+ response_headers["content-length"] = absl::StrCat(body.size());
push_resources.push_back(
ServerPushInfo(resource_url, response_headers.Clone(), i, body));
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc
index 9d67b09e5e8..97ca71e9c6f 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
@@ -28,12 +28,13 @@
#include <iostream>
+#include "absl/strings/escaping.h"
+#include "absl/strings/string_view.h"
#include "quic/core/quic_framer.h"
+#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 "absl/strings/string_view.h"
-#include "absl/strings/escaping.h"
DEFINE_QUIC_COMMAND_LINE_FLAG(std::string,
quic_version,
@@ -213,7 +214,8 @@ class QuicPacketPrinter : public QuicFramerVisitorInterface {
return true;
}
void OnPacketComplete() override { std::cerr << "OnPacketComplete\n"; }
- bool IsValidStatelessResetToken(QuicUint128 /*token*/) const override {
+ bool IsValidStatelessResetToken(
+ const StatelessResetToken& /*token*/) const override {
std::cerr << "IsValidStatelessResetToken\n";
return false;
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_server_bin.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_server_bin.cc
index 6ed8e994bea..c9713670a9c 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_server_bin.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_server_bin.cc
@@ -9,10 +9,12 @@
#include "quic/core/quic_versions.h"
#include "quic/platform/api/quic_flags.h"
+#include "quic/platform/api/quic_system_event_loop.h"
#include "quic/tools/quic_epoll_server_factory.h"
#include "quic/tools/quic_toy_server.h"
int main(int argc, char* argv[]) {
+ QuicSystemEventLoop event_loop("quic_server");
const char* usage = "Usage: quic_server [options]";
std::vector<std::string> non_option_args =
quic::QuicParseCommandLineFlags(usage, argc, argv);
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.cc
index 7f64495f0fd..d1efcba4fe0 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.cc
@@ -16,13 +16,32 @@ QuicSimpleClientSession::QuicSimpleClientSession(
QuicCryptoClientConfig* crypto_config,
QuicClientPushPromiseIndex* push_promise_index,
bool drop_response_body)
+ : QuicSimpleClientSession(config,
+ supported_versions,
+ connection,
+ server_id,
+ crypto_config,
+ push_promise_index,
+ drop_response_body,
+ /*enable_web_transport=*/false) {}
+
+QuicSimpleClientSession::QuicSimpleClientSession(
+ const QuicConfig& config,
+ const ParsedQuicVersionVector& supported_versions,
+ QuicConnection* connection,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config,
+ QuicClientPushPromiseIndex* push_promise_index,
+ bool drop_response_body,
+ bool enable_web_transport)
: QuicSpdyClientSession(config,
supported_versions,
connection,
server_id,
crypto_config,
push_promise_index),
- drop_response_body_(drop_response_body) {}
+ drop_response_body_(drop_response_body),
+ enable_web_transport_(enable_web_transport) {}
std::unique_ptr<QuicSpdyClientStream>
QuicSimpleClientSession::CreateClientStream() {
@@ -31,4 +50,8 @@ QuicSimpleClientSession::CreateClientStream() {
drop_response_body_);
}
+bool QuicSimpleClientSession::ShouldNegotiateWebTransport() {
+ return enable_web_transport_;
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.h b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.h
index 5b5314183f8..aa86d9a83c9 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.h
@@ -19,11 +19,21 @@ class QuicSimpleClientSession : public QuicSpdyClientSession {
QuicCryptoClientConfig* crypto_config,
QuicClientPushPromiseIndex* push_promise_index,
bool drop_response_body);
+ QuicSimpleClientSession(const QuicConfig& config,
+ const ParsedQuicVersionVector& supported_versions,
+ QuicConnection* connection,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config,
+ QuicClientPushPromiseIndex* push_promise_index,
+ bool drop_response_body,
+ bool enable_web_transport);
std::unique_ptr<QuicSpdyClientStream> CreateClientStream() override;
+ bool ShouldNegotiateWebTransport() override;
private:
const bool drop_response_body_;
+ const bool enable_web_transport_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.cc
index 736c061a2db..aa9a9c1e616 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.cc
@@ -53,7 +53,8 @@ std::unique_ptr<QuicSession> QuicSimpleDispatcher::CreateQuicSession(
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
absl::string_view /*alpn*/,
- const ParsedQuicVersion& version) {
+ const ParsedQuicVersion& version,
+ absl::string_view /*sni*/) {
// The QuicServerSessionBase takes ownership of |connection| below.
QuicConnection* connection =
new QuicConnection(connection_id, self_address, peer_address, helper(),
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h
index a629d3cd299..c790f21a140 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h
@@ -36,7 +36,8 @@ class QuicSimpleDispatcher : public QuicDispatcher {
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
absl::string_view alpn,
- const ParsedQuicVersion& version) override;
+ const ParsedQuicVersion& version,
+ absl::string_view sni) override;
QuicSimpleServerBackend* server_backend() {
return quic_simple_server_backend_;
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 9e16d4e9a88..43ced4bcefb 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
@@ -5,7 +5,10 @@
#ifndef QUICHE_QUIC_TOOLS_QUIC_SIMPLE_SERVER_BACKEND_H_
#define QUICHE_QUIC_TOOLS_QUIC_SIMPLE_SERVER_BACKEND_H_
+#include <memory>
+
#include "quic/core/quic_types.h"
+#include "quic/core/web_transport_interface.h"
#include "quic/tools/quic_backend_response.h"
#include "spdy/core/spdy_header_block.h"
@@ -33,6 +36,11 @@ class QuicSimpleServerBackend {
std::list<QuicBackendResponse::ServerPushInfo> resources) = 0;
};
+ struct WebTransportResponse {
+ spdy::Http2HeaderBlock response_headers;
+ std::unique_ptr<WebTransportVisitor> visitor;
+ };
+
virtual ~QuicSimpleServerBackend() = default;
// This method initializes the backend instance to fetch responses
// from a backend server, in-memory cache etc.
@@ -51,6 +59,15 @@ class QuicSimpleServerBackend {
RequestHandler* request_handler) = 0;
// Clears the state of the backend instance
virtual void CloseBackendResponseStream(RequestHandler* request_handler) = 0;
+
+ virtual WebTransportResponse ProcessWebTransportRequest(
+ const spdy::Http2HeaderBlock& /*request_headers*/,
+ WebTransportSession* /*session*/) {
+ WebTransportResponse response;
+ response.response_headers[":status"] = "400";
+ return response;
+ }
+ virtual bool SupportsWebTransport() { return false; }
};
} // namespace quic
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 044998c9e16..4075d3ff417 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
@@ -6,12 +6,13 @@
#include <utility>
+#include "absl/memory/memory.h"
+#include "quic/core/http/quic_server_initiated_spdy_stream.h"
#include "quic/core/http/quic_spdy_session.h"
#include "quic/core/quic_connection.h"
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
-#include "quic/platform/api/quic_ptr_util.h"
#include "quic/tools/quic_simple_server_stream.h"
namespace quic {
@@ -51,7 +52,7 @@ QuicSimpleServerSession::CreateQuicCryptoServerStream(
}
void QuicSimpleServerSession::OnStreamFrame(const QuicStreamFrame& frame) {
- if (!IsIncomingStream(frame.stream_id)) {
+ if (!IsIncomingStream(frame.stream_id) && !WillNegotiateWebTransport()) {
QUIC_LOG(WARNING) << "Client shouldn't send data on server push stream";
connection()->CloseConnection(
QUIC_INVALID_STREAM_ID, "Client sent data on server push stream",
@@ -101,7 +102,7 @@ QuicSpdyStream* QuicSimpleServerSession::CreateIncomingStream(QuicStreamId id) {
QuicSpdyStream* stream = new QuicSimpleServerStream(
id, this, BIDIRECTIONAL, quic_simple_server_backend_);
- ActivateStream(QuicWrapUnique(stream));
+ ActivateStream(absl::WrapUnique(stream));
return stream;
}
@@ -109,14 +110,26 @@ QuicSpdyStream* QuicSimpleServerSession::CreateIncomingStream(
PendingStream* pending) {
QuicSpdyStream* stream = new QuicSimpleServerStream(
pending, this, BIDIRECTIONAL, quic_simple_server_backend_);
- ActivateStream(QuicWrapUnique(stream));
+ ActivateStream(absl::WrapUnique(stream));
return stream;
}
-QuicSimpleServerStream*
-QuicSimpleServerSession::CreateOutgoingBidirectionalStream() {
- QUICHE_DCHECK(false);
- return nullptr;
+QuicSpdyStream* QuicSimpleServerSession::CreateOutgoingBidirectionalStream() {
+ if (!WillNegotiateWebTransport()) {
+ QUIC_BUG(QuicSimpleServerSession CreateOutgoingBidirectionalStream without
+ WebTransport support)
+ << "QuicSimpleServerSession::CreateOutgoingBidirectionalStream called "
+ "in a session without WebTransport support.";
+ return nullptr;
+ }
+ if (!ShouldCreateOutgoingBidirectionalStream()) {
+ return nullptr;
+ }
+
+ QuicServerInitiatedSpdyStream* stream = new QuicServerInitiatedSpdyStream(
+ GetNextOutgoingBidirectionalStreamId(), this, BIDIRECTIONAL);
+ ActivateStream(absl::WrapUnique(stream));
+ return stream;
}
QuicSimpleServerStream*
@@ -128,7 +141,7 @@ QuicSimpleServerSession::CreateOutgoingUnidirectionalStream() {
QuicSimpleServerStream* stream = new QuicSimpleServerStream(
GetNextOutgoingUnidirectionalStreamId(), this, WRITE_UNIDIRECTIONAL,
quic_simple_server_backend_);
- ActivateStream(QuicWrapUnique(stream));
+ ActivateStream(absl::WrapUnique(stream));
return stream;
}
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 49aaae56b37..b91966da722 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
@@ -85,7 +85,7 @@ class QuicSimpleServerSession : public QuicServerSessionBase {
// QuicSession methods:
QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override;
QuicSpdyStream* CreateIncomingStream(PendingStream* pending) override;
- QuicSimpleServerStream* CreateOutgoingBidirectionalStream() override;
+ QuicSpdyStream* CreateOutgoingBidirectionalStream() override;
QuicSimpleServerStream* CreateOutgoingUnidirectionalStream() override;
// Override to return true for locally preserved server push stream.
void HandleFrameOnNonexistentOutgoingStream(QuicStreamId stream_id) override;
@@ -104,6 +104,14 @@ class QuicSimpleServerSession : public QuicServerSessionBase {
void MaybeInitializeHttp3UnidirectionalStreams() override;
+ bool ShouldNegotiateWebTransport() override {
+ return quic_simple_server_backend_->SupportsWebTransport();
+ }
+ bool ShouldNegotiateHttp3Datagram() override {
+ return QuicServerSessionBase::ShouldNegotiateHttp3Datagram() ||
+ ShouldNegotiateWebTransport();
+ }
+
private:
friend class test::QuicSimpleServerSessionPeer;
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 80d3a930349..62bbae949d5 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
@@ -8,6 +8,7 @@
#include <memory>
#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"
@@ -37,7 +38,6 @@
#include "quic/tools/quic_backend_response.h"
#include "quic/tools/quic_memory_cache_backend.h"
#include "quic/tools/quic_simple_server_stream.h"
-#include "common/platform/api/quiche_text_utils.h"
using testing::_;
using testing::AnyNumber;
@@ -135,9 +135,9 @@ QuicCryptoServerStreamBase* CreateMockCryptoServerStream(
case PROTOCOL_UNSUPPORTED:
break;
}
- QUIC_BUG << "Unknown handshake protocol: "
- << static_cast<int>(
- session->connection()->version().handshake_protocol);
+ QUIC_BUG(quic_bug_10933_1)
+ << "Unknown handshake protocol: "
+ << static_cast<int>(session->connection()->version().handshake_protocol);
return nullptr;
}
@@ -699,8 +699,7 @@ class QuicSimpleServerSessionServerPushTest
} else {
stream_id = GetNthServerInitiatedUnidirectionalId(i - 1);
}
- std::string path = partial_push_resource_path +
- quiche::QuicheTextUtils::Uint64ToString(i);
+ 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');
@@ -774,19 +773,26 @@ class QuicSimpleServerSessionServerPushTest
}
};
+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(AllSupportedVersions()));
+ ::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();
- if (VersionUsesHttp3(transport_version())) {
- session_->EnableServerPush();
- session_->OnMaxPushIdFrame(kMaxQuicStreamId);
- }
size_t num_resources = kMaxStreamsForTest + 5;
PromisePushResources(num_resources);
EXPECT_EQ(kMaxStreamsForTest,
@@ -798,10 +804,6 @@ TEST_P(QuicSimpleServerSessionServerPushTest, TestPromisePushResources) {
TEST_P(QuicSimpleServerSessionServerPushTest,
HandlePromisedPushRequestsAfterStreamDraining) {
MaybeConsumeHeadersStreamData();
- if (VersionUsesHttp3(transport_version())) {
- session_->EnableServerPush();
- session_->OnMaxPushIdFrame(kMaxQuicStreamId);
- }
size_t num_resources = kMaxStreamsForTest + 1;
QuicByteCount data_frame_header_length = PromisePushResources(num_resources);
QuicStreamId next_out_going_stream_id;
@@ -879,10 +881,6 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
return;
}
MaybeConsumeHeadersStreamData();
- if (VersionUsesHttp3(transport_version())) {
- session_->EnableServerPush();
- session_->OnMaxPushIdFrame(kMaxQuicStreamId);
- }
// Having two extra resources to be send later. One of them will be reset, so
// when opened stream become close, only one will become open.
@@ -969,10 +967,6 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
TEST_P(QuicSimpleServerSessionServerPushTest,
CloseStreamToHandleMorePromisedStream) {
MaybeConsumeHeadersStreamData();
- if (VersionUsesHttp3(transport_version())) {
- session_->EnableServerPush();
- session_->OnMaxPushIdFrame(kMaxQuicStreamId);
- }
size_t num_resources = kMaxStreamsForTest + 1;
if (VersionHasIetfQuicFrames(transport_version())) {
// V99 will send out a stream-id-blocked frame when the we desired to exceed
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 800608bf0ba..f4afeb241c0 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
@@ -9,16 +9,17 @@
#include "absl/strings/match.h"
#include "absl/strings/numbers.h"
+#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "quic/core/http/quic_spdy_stream.h"
#include "quic/core/http/spdy_utils.h"
+#include "quic/core/http/web_transport_http3.h"
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_bug_tracker.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/tools/quic_simple_server_session.h"
-#include "common/platform/api/quiche_text_utils.h"
#include "spdy/core/spdy_protocol.h"
using spdy::Http2HeaderBlock;
@@ -64,7 +65,7 @@ void QuicSimpleServerStream::OnInitialHeadersComplete(
SendErrorResponse();
}
ConsumeHeaderList();
- if (!fin) {
+ if (!fin && !response_sent_) {
// CONNECT and other CONNECT-like methods (such as CONNECT-UDP) require
// sending the response right after parsing the headers even though the FIN
// bit has not been received on the request stream.
@@ -80,7 +81,7 @@ void QuicSimpleServerStream::OnTrailingHeadersComplete(
bool /*fin*/,
size_t /*frame_len*/,
const QuicHeaderList& /*header_list*/) {
- QUIC_BUG << "Server does not support receiving Trailers.";
+ QUIC_BUG(quic_bug_10962_1) << "Server does not support receiving Trailers.";
SendErrorResponse();
}
@@ -124,7 +125,8 @@ void QuicSimpleServerStream::PushResponse(
Http2HeaderBlock push_request_headers) {
if (QuicUtils::IsClientInitiatedStreamId(session()->transport_version(),
id())) {
- QUIC_BUG << "Client initiated stream shouldn't be used as promised stream.";
+ QUIC_BUG(quic_bug_10962_2)
+ << "Client initiated stream shouldn't be used as promised stream.";
return;
}
// Change the stream state to emulate a client request.
@@ -153,19 +155,46 @@ void QuicSimpleServerStream::SendResponse() {
return;
}
- if (!QuicContainsKey(request_headers_, ":authority") ||
- !QuicContainsKey(request_headers_, ":path")) {
- QUIC_DVLOG(1) << "Request headers do not contain :authority or :path.";
+ if (!QuicContainsKey(request_headers_, ":authority")) {
+ QUIC_DVLOG(1) << "Request headers do not contain :authority.";
SendErrorResponse();
return;
}
+ if (!QuicContainsKey(request_headers_, ":path")) {
+ // CONNECT and other CONNECT-like methods (such as CONNECT-UDP) do not all
+ // require :path to be present.
+ auto it = request_headers_.find(":method");
+ if (it == request_headers_.end() ||
+ !absl::StartsWith(it->second, "CONNECT")) {
+ QUIC_DVLOG(1) << "Request headers do not contain :path.";
+ SendErrorResponse();
+ return;
+ }
+ }
+
if (quic_simple_server_backend_ == nullptr) {
QUIC_DVLOG(1) << "Backend is missing.";
SendErrorResponse();
return;
}
+ if (web_transport() != nullptr) {
+ QuicSimpleServerBackend::WebTransportResponse response =
+ quic_simple_server_backend_->ProcessWebTransportRequest(
+ request_headers_, web_transport());
+ if (response.response_headers[":status"] == "200") {
+ WriteHeaders(std::move(response.response_headers), false, nullptr);
+ if (response.visitor != nullptr) {
+ web_transport()->SetVisitor(std::move(response.visitor));
+ }
+ web_transport()->HeadersReceived(request_headers_);
+ } else {
+ WriteHeaders(std::move(response.response_headers), true, nullptr);
+ }
+ return;
+ }
+
// Fetch the response from the backend interface and wait for callback once
// response is ready
quic_simple_server_backend_->FetchResponseFromBackend(request_headers_, body_,
@@ -193,6 +222,13 @@ void QuicSimpleServerStream::OnResponseBackendComplete(
return;
}
+ // Send Early Hints first.
+ for (const auto& headers : response->early_hints()) {
+ QUIC_DVLOG(1) << "Stream " << id() << " sending an Early Hints response: "
+ << headers.DebugString();
+ WriteHeaders(headers.Clone(), false, nullptr);
+ }
+
if (response->response_type() == QuicBackendResponse::CLOSE_CONNECTION) {
QUIC_DVLOG(1) << "Special response: closing connection.";
OnUnrecoverableError(QUIC_NO_ERROR, "Toy server forcing close");
@@ -275,10 +311,11 @@ void QuicSimpleServerStream::OnResponseBackendComplete(
return;
}
Http2HeaderBlock headers = response->headers().Clone();
- headers["content-length"] =
- quiche::QuicheTextUtils::Uint64ToString(generate_bytes_length_);
+ headers["content-length"] = absl::StrCat(generate_bytes_length_);
WriteHeaders(std::move(headers), false, nullptr);
+ QUICHE_DCHECK(!response_sent_);
+ response_sent_ = true;
WriteGeneratedBytes();
@@ -310,8 +347,7 @@ void QuicSimpleServerStream::SendNotFoundResponse() {
QUIC_DVLOG(1) << "Stream " << id() << " sending not found response.";
Http2HeaderBlock headers;
headers[":status"] = "404";
- headers["content-length"] =
- quiche::QuicheTextUtils::Uint64ToString(strlen(kNotFoundResponseBody));
+ headers["content-length"] = absl::StrCat(strlen(kNotFoundResponseBody));
SendHeadersAndBody(std::move(headers), kNotFoundResponseBody);
}
@@ -325,10 +361,9 @@ void QuicSimpleServerStream::SendErrorResponse(int resp_code) {
if (resp_code <= 0) {
headers[":status"] = "500";
} else {
- headers[":status"] = quiche::QuicheTextUtils::Uint64ToString(resp_code);
+ headers[":status"] = absl::StrCat(resp_code);
}
- headers["content-length"] =
- quiche::QuicheTextUtils::Uint64ToString(strlen(kErrorResponseBody));
+ headers["content-length"] = absl::StrCat(strlen(kErrorResponseBody));
SendHeadersAndBody(std::move(headers), kErrorResponseBody);
}
@@ -338,6 +373,8 @@ void QuicSimpleServerStream::SendIncompleteResponse(
QUIC_DLOG(INFO) << "Stream " << id() << " writing headers (fin = false) : "
<< response_headers.DebugString();
WriteHeaders(std::move(response_headers), /*fin=*/false, nullptr);
+ QUICHE_DCHECK(!response_sent_);
+ response_sent_ = true;
QUIC_DLOG(INFO) << "Stream " << id()
<< " writing body (fin = false) with size: " << body.size();
@@ -362,6 +399,8 @@ void QuicSimpleServerStream::SendHeadersAndBodyAndTrailers(
QUIC_DLOG(INFO) << "Stream " << id() << " writing headers (fin = " << send_fin
<< ") : " << response_headers.DebugString();
WriteHeaders(std::move(response_headers), send_fin, nullptr);
+ QUICHE_DCHECK(!response_sent_);
+ response_sent_ = true;
if (send_fin) {
// Nothing else to send.
return;
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 bbed95a2bcd..2dd59f9fc91 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
@@ -99,6 +99,8 @@ class QuicSimpleServerStream : public QuicSpdyServerStreamBase,
private:
uint64_t generate_bytes_length_;
+ // Whether response headers have already been sent.
+ bool response_sent_ = false;
QuicSimpleServerBackend* quic_simple_server_backend_; // Not owned.
};
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 5806ad72de1..bf80d476020 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
@@ -9,6 +9,7 @@
#include <utility>
#include "absl/base/macros.h"
+#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "quic/core/crypto/null_encrypter.h"
@@ -18,7 +19,6 @@
#include "quic/core/quic_types.h"
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_expect_bug.h"
-#include "quic/platform/api/quic_ptr_util.h"
#include "quic/platform/api/quic_socket_address.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/crypto_test_utils.h"
@@ -59,12 +59,17 @@ class TestStream : public QuicSimpleServerStream {
~TestStream() override = default;
MOCK_METHOD(void, WriteHeadersMock, (bool fin), ());
+ MOCK_METHOD(void, WriteEarlyHintsHeadersMock, (bool fin), ());
- size_t WriteHeaders(spdy::Http2HeaderBlock /*header_block*/,
+ size_t WriteHeaders(spdy::Http2HeaderBlock header_block,
bool fin,
QuicReferenceCountedPointer<QuicAckListenerInterface>
/*ack_listener*/) override {
- WriteHeadersMock(fin);
+ if (header_block[":status"] == "103") {
+ WriteEarlyHintsHeadersMock(fin);
+ } else {
+ WriteHeadersMock(fin);
+ }
return 0;
}
@@ -77,6 +82,9 @@ class TestStream : public QuicSimpleServerStream {
const std::string& body() const { return body_; }
int content_length() const { return content_length_; }
bool send_response_was_called() const { return send_response_was_called_; }
+ bool send_error_response_was_called() const {
+ return send_error_response_was_called_;
+ }
absl::string_view GetHeader(absl::string_view key) const {
auto it = request_headers_.find(key);
@@ -90,8 +98,14 @@ class TestStream : public QuicSimpleServerStream {
QuicSimpleServerStream::SendResponse();
}
+ void SendErrorResponse() override {
+ send_error_response_was_called_ = true;
+ QuicSimpleServerStream::SendErrorResponse();
+ }
+
private:
bool send_response_was_called_ = false;
+ bool send_error_response_was_called_ = false;
};
namespace {
@@ -266,7 +280,7 @@ class QuicSimpleServerStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
connection_->transport_version(), 0),
&session_, BIDIRECTIONAL, &memory_cache_backend_);
// Register stream_ in dynamic_stream_map_ and pass ownership to session_.
- session_.ActivateStream(QuicWrapUnique(stream_));
+ session_.ActivateStream(absl::WrapUnique(stream_));
QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
session_.config(), kMinimumFlowControlSendWindow);
QuicConfigPeer::SetReceivedInitialMaxStreamDataBytesUnidirectional(
@@ -474,7 +488,7 @@ TEST_P(QuicSimpleServerStreamTest, SendPushResponseWith404Response) {
GetNthServerInitiatedUnidirectionalStreamId(
connection_->transport_version(), 3),
&session_, WRITE_UNIDIRECTIONAL, &memory_cache_backend_);
- session_.ActivateStream(QuicWrapUnique(promised_stream));
+ session_.ActivateStream(absl::WrapUnique(promised_stream));
// Send a push response with response status 404, which will be regarded as
// invalid server push response.
@@ -572,6 +586,50 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithPushResources) {
EXPECT_EQ(*request_headers, session_.original_request_headers_);
}
+TEST_P(QuicSimpleServerStreamTest, SendResponseWithEarlyHints) {
+ std::string host = "www.google.com";
+ std::string request_path = "/foo";
+ std::string body = "Yummm";
+
+ // Add a request and response with early hints.
+ spdy::Http2HeaderBlock* request_headers = stream_->mutable_headers();
+ (*request_headers)[":path"] = request_path;
+ (*request_headers)[":authority"] = host;
+ (*request_headers)[":method"] = "GET";
+
+ std::unique_ptr<char[]> buffer;
+ QuicByteCount header_length =
+ HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
+ std::vector<spdy::Http2HeaderBlock> early_hints;
+ // Add two Early Hints.
+ const size_t kNumEarlyHintsResponses = 2;
+ for (size_t i = 0; i < kNumEarlyHintsResponses; ++i) {
+ spdy::Http2HeaderBlock hints;
+ hints["link"] = "</image.png>; rel=preload; as=image";
+ early_hints.push_back(std::move(hints));
+ }
+
+ response_headers_[":status"] = "200";
+ response_headers_["content-length"] = "5";
+ memory_cache_backend_.AddResponseWithEarlyHints(
+ host, request_path, std::move(response_headers_), body, early_hints);
+ QuicStreamPeer::SetFinReceived(stream_);
+
+ InSequence s;
+ for (size_t i = 0; i < kNumEarlyHintsResponses; ++i) {
+ EXPECT_CALL(*stream_, WriteEarlyHintsHeadersMock(false));
+ }
+ 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_FALSE(QuicStreamPeer::read_side_closed(stream_));
+ EXPECT_TRUE(stream_->write_side_closed());
+}
+
TEST_P(QuicSimpleServerStreamTest, PushResponseOnClientInitiatedStream) {
// EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
if (GetParam() != AllSupportedVersions()[0]) {
@@ -597,7 +655,7 @@ TEST_P(QuicSimpleServerStreamTest, PushResponseOnServerInitiatedStream) {
auto server_initiated_stream =
new StrictMock<TestStream>(kServerInitiatedStreamId, &session_,
WRITE_UNIDIRECTIONAL, &memory_cache_backend_);
- session_.ActivateStream(QuicWrapUnique(server_initiated_stream));
+ session_.ActivateStream(absl::WrapUnique(server_initiated_stream));
const std::string kHost = "www.foo.com";
const std::string kPath = "/bar";
@@ -778,6 +836,33 @@ TEST_P(QuicSimpleServerStreamTest, ConnectSendsResponseBeforeFinReceived) {
EXPECT_EQ("CONNECT-SILLY", StreamHeadersValue(":method"));
EXPECT_EQ(body_, StreamBody());
EXPECT_TRUE(stream_->send_response_was_called());
+ EXPECT_FALSE(stream_->send_error_response_was_called());
+}
+
+TEST_P(QuicSimpleServerStreamTest, ConnectWithInvalidHeader) {
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
+ .WillRepeatedly(
+ Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
+ QuicHeaderList header_list;
+ header_list.OnHeaderBlockStart();
+ header_list.OnHeader(":authority", "www.google.com:4433");
+ header_list.OnHeader(":method", "CONNECT-SILLY");
+ // QUIC requires lower-case header names.
+ header_list.OnHeader("InVaLiD-HeAdEr", "Well that's just wrong!");
+ header_list.OnHeaderBlockEnd(128, 128);
+ EXPECT_CALL(*stream_, WriteHeadersMock(/*fin=*/false));
+ stream_->OnStreamHeaderList(/*fin=*/false, kFakeFrameLen, header_list);
+ std::unique_ptr<char[]> buffer;
+ QuicByteCount header_length =
+ HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
+ std::string header = std::string(buffer.get(), header_length);
+ std::string data = UsesHttp3() ? header + body_ : body_;
+ stream_->OnStreamFrame(
+ QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
+ EXPECT_EQ("CONNECT-SILLY", StreamHeadersValue(":method"));
+ EXPECT_EQ(body_, StreamBody());
+ EXPECT_FALSE(stream_->send_response_was_called());
+ EXPECT_TRUE(stream_->send_error_response_was_called());
}
} // namespace
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 d28eb771a7d..974344ed4aa 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
@@ -50,8 +50,7 @@ QuicSpdyClientBase::QuicSpdyClientBase(
std::move(proof_verifier),
std::move(session_cache)),
store_response_(false),
- latest_response_code_(-1),
- max_allowed_push_id_(0) {}
+ latest_response_code_(-1) {}
QuicSpdyClientBase::~QuicSpdyClientBase() {
// We own the push promise index. We need to explicitly kill
@@ -70,10 +69,6 @@ const QuicSpdyClientSession* QuicSpdyClientBase::client_session() const {
void QuicSpdyClientBase::InitializeSession() {
client_session()->Initialize();
client_session()->CryptoConnect();
- if (max_allowed_push_id_ > 0 &&
- VersionUsesHttp3(client_session()->transport_version())) {
- client_session()->SetMaxPushId(max_allowed_push_id_);
- }
}
void QuicSpdyClientBase::OnClose(QuicSpdyStream* stream) {
@@ -146,7 +141,7 @@ void QuicSpdyClientBase::SendRequestInternal(Http2HeaderBlock sanitized_headers,
QuicSpdyClientStream* stream = CreateClientStream();
if (stream == nullptr) {
- QUIC_BUG << "stream creation failed!";
+ QUIC_BUG(quic_bug_10949_1) << "stream creation failed!";
return;
}
stream->SendRequest(std::move(sanitized_headers), body, fin);
@@ -166,7 +161,7 @@ void QuicSpdyClientBase::SendRequestsAndWaitForResponse(
for (size_t i = 0; i < url_list.size(); ++i) {
Http2HeaderBlock headers;
if (!SpdyUtils::PopulateHeaderBlockFromUrl(url_list[i], &headers)) {
- QUIC_BUG << "Unable to create request";
+ QUIC_BUG(quic_bug_10949_2) << "Unable to create request";
continue;
}
SendRequest(headers, "", true);
@@ -260,33 +255,33 @@ void QuicSpdyClientBase::OnRendezvousResult(QuicSpdyStream* stream) {
}
int QuicSpdyClientBase::latest_response_code() const {
- QUIC_BUG_IF(!store_response_) << "Response not stored!";
+ QUIC_BUG_IF(quic_bug_10949_3, !store_response_) << "Response not stored!";
return latest_response_code_;
}
const std::string& QuicSpdyClientBase::latest_response_headers() const {
- QUIC_BUG_IF(!store_response_) << "Response not stored!";
+ QUIC_BUG_IF(quic_bug_10949_4, !store_response_) << "Response not stored!";
return latest_response_headers_;
}
const std::string& QuicSpdyClientBase::preliminary_response_headers() const {
- QUIC_BUG_IF(!store_response_) << "Response not stored!";
+ QUIC_BUG_IF(quic_bug_10949_5, !store_response_) << "Response not stored!";
return preliminary_response_headers_;
}
const Http2HeaderBlock& QuicSpdyClientBase::latest_response_header_block()
const {
- QUIC_BUG_IF(!store_response_) << "Response not stored!";
+ QUIC_BUG_IF(quic_bug_10949_6, !store_response_) << "Response not stored!";
return latest_response_header_block_;
}
const std::string& QuicSpdyClientBase::latest_response_body() const {
- QUIC_BUG_IF(!store_response_) << "Response not stored!";
+ QUIC_BUG_IF(quic_bug_10949_7, !store_response_) << "Response not stored!";
return latest_response_body_;
}
const std::string& QuicSpdyClientBase::latest_response_trailers() const {
- QUIC_BUG_IF(!store_response_) << "Response not stored!";
+ QUIC_BUG_IF(quic_bug_10949_8, !store_response_) << "Response not stored!";
return latest_response_trailers_;
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h b/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h
index 54c73f780cf..2ba55f11693 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h
@@ -139,9 +139,10 @@ class QuicSpdyClientBase : public QuicClientBase,
}
bool drop_response_body() const { return drop_response_body_; }
- // Set the max promise id for the client session.
- // TODO(b/151641466): Rename this method.
- void SetMaxAllowedPushId(PushId max) { max_allowed_push_id_ = max; }
+ void set_enable_web_transport(bool enable_web_transport) {
+ enable_web_transport_ = enable_web_transport;
+ }
+ bool enable_web_transport() const { return enable_web_transport_; }
// QuicClientBase methods.
bool goaway_received() const override;
@@ -221,9 +222,7 @@ class QuicSpdyClientBase : public QuicClientBase,
std::unique_ptr<ClientQuicDataToResend> push_promise_data_to_resend_;
bool drop_response_body_ = false;
-
- // The max promise id to set on the client session when created.
- PushId max_allowed_push_id_;
+ bool enable_web_transport_ = false;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_tcp_like_trace_converter.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_tcp_like_trace_converter.cc
index 37e23b60c76..22e873185b6 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_tcp_like_trace_converter.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_tcp_like_trace_converter.cc
@@ -30,7 +30,7 @@ QuicIntervalSet<uint64_t> QuicTcpLikeTraceConverter::OnCryptoFrameSent(
QuicStreamOffset offset,
QuicByteCount data_length) {
if (level >= NUM_ENCRYPTION_LEVELS) {
- QUIC_BUG << "Invalid encryption level";
+ QUIC_BUG(quic_bug_10907_1) << "Invalid encryption level";
return {};
}
return OnFrameSent(offset, data_length, /*fin=*/false,
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.cc
index 7029cf70be9..25730eda818 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.cc
@@ -39,7 +39,8 @@ QuicTransportSimpleServerDispatcher::CreateQuicSession(
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
absl::string_view /*alpn*/,
- const ParsedQuicVersion& version) {
+ const ParsedQuicVersion& version,
+ absl::string_view /*sni*/) {
auto connection = std::make_unique<QuicConnection>(
server_connection_id, self_address, peer_address, helper(),
alarm_factory(), writer(),
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.h b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.h
index 500b02d55fb..bb38596bf19 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.h
@@ -32,7 +32,8 @@ class QuicTransportSimpleServerDispatcher : public QuicDispatcher {
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
absl::string_view alpn,
- const ParsedQuicVersion& version) override;
+ const ParsedQuicVersion& version,
+ absl::string_view sni) override;
std::vector<url::Origin> accepted_origins_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.cc
index ad93115705f..bc7ef192860 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.cc
@@ -15,115 +15,10 @@
#include "quic/platform/api/quic_logging.h"
#include "quic/quic_transport/quic_transport_protocol.h"
#include "quic/quic_transport/quic_transport_stream.h"
+#include "quic/tools/web_transport_test_visitors.h"
namespace quic {
-namespace {
-
-// Discards any incoming data.
-class DiscardVisitor : public QuicTransportStream::Visitor {
- public:
- DiscardVisitor(QuicTransportStream* stream) : stream_(stream) {}
-
- void OnCanRead() override {
- std::string buffer;
- size_t bytes_read = stream_->Read(&buffer);
- QUIC_DVLOG(2) << "Read " << bytes_read << " bytes from stream "
- << stream_->id();
- }
-
- void OnFinRead() override {}
- void OnCanWrite() override {}
-
- private:
- QuicTransportStream* stream_;
-};
-
-// Echoes any incoming data back on the same stream.
-class BidirectionalEchoVisitor : public QuicTransportStream::Visitor {
- public:
- BidirectionalEchoVisitor(QuicTransportStream* stream) : stream_(stream) {}
-
- void OnCanRead() override {
- stream_->Read(&buffer_);
- OnCanWrite();
- }
-
- void OnFinRead() override {
- bool success = stream_->SendFin();
- QUICHE_DCHECK(success);
- }
-
- void OnCanWrite() override {
- if (buffer_.empty()) {
- return;
- }
-
- bool success = stream_->Write(buffer_);
- if (success) {
- buffer_ = "";
- }
- }
-
- private:
- QuicTransportStream* stream_;
- std::string buffer_;
-};
-
-// Buffers all of the data and calls EchoStreamBack() on the parent session.
-class UnidirectionalEchoReadVisitor : public QuicTransportStream::Visitor {
- public:
- UnidirectionalEchoReadVisitor(QuicTransportSimpleServerSession* session,
- QuicTransportStream* stream)
- : session_(session), stream_(stream) {}
-
- void OnCanRead() override {
- bool success = stream_->Read(&buffer_);
- QUICHE_DCHECK(success);
- }
-
- void OnFinRead() override {
- QUIC_DVLOG(1) << "Finished receiving data on stream " << stream_->id()
- << ", queueing up the echo";
- session_->EchoStreamBack(buffer_);
- }
-
- void OnCanWrite() override { QUIC_NOTREACHED(); }
-
- private:
- QuicTransportSimpleServerSession* session_;
- QuicTransportStream* stream_;
- std::string buffer_;
-};
-
-// Sends supplied data.
-class UnidirectionalEchoWriteVisitor : public QuicTransportStream::Visitor {
- public:
- UnidirectionalEchoWriteVisitor(QuicTransportStream* stream,
- const std::string& data)
- : stream_(stream), data_(data) {}
-
- void OnCanRead() override { QUIC_NOTREACHED(); }
- void OnFinRead() override { QUIC_NOTREACHED(); }
- void OnCanWrite() override {
- if (data_.empty()) {
- return;
- }
- if (!stream_->Write(data_)) {
- return;
- }
- data_ = "";
- bool fin_sent = stream_->SendFin();
- QUICHE_DCHECK(fin_sent);
- }
-
- private:
- QuicTransportStream* stream_;
- std::string data_;
-};
-
-} // namespace
-
QuicTransportSimpleServerSession::QuicTransportSimpleServerSession(
QuicConnection* connection,
bool owns_connection,
@@ -154,22 +49,24 @@ void QuicTransportSimpleServerSession::OnIncomingDataStream(
QuicTransportStream* stream) {
switch (mode_) {
case DISCARD:
- stream->set_visitor(std::make_unique<DiscardVisitor>(stream));
+ stream->SetVisitor(std::make_unique<WebTransportDiscardVisitor>(stream));
break;
case ECHO:
switch (stream->type()) {
case BIDIRECTIONAL:
QUIC_DVLOG(1) << "Opening bidirectional echo stream " << stream->id();
- stream->set_visitor(
- std::make_unique<BidirectionalEchoVisitor>(stream));
+ stream->SetVisitor(
+ std::make_unique<WebTransportBidirectionalEchoVisitor>(stream));
break;
case READ_UNIDIRECTIONAL:
QUIC_DVLOG(1)
<< "Started receiving data on unidirectional echo stream "
<< stream->id();
- stream->set_visitor(
- std::make_unique<UnidirectionalEchoReadVisitor>(this, stream));
+ stream->SetVisitor(
+ std::make_unique<WebTransportUnidirectionalEchoReadVisitor>(
+ stream,
+ [this](const std::string& s) { this->EchoStreamBack(s); }));
break;
default:
QUIC_NOTREACHED();
@@ -178,7 +75,7 @@ void QuicTransportSimpleServerSession::OnIncomingDataStream(
break;
case OUTGOING_BIDIRECTIONAL:
- stream->set_visitor(std::make_unique<DiscardVisitor>(stream));
+ stream->SetVisitor(std::make_unique<WebTransportDiscardVisitor>(stream));
++pending_outgoing_bidirectional_streams_;
MaybeCreateOutgoingBidirectionalStream();
break;
@@ -252,8 +149,9 @@ void QuicTransportSimpleServerSession::MaybeEchoStreamsBack() {
ActivateStream(std::move(stream_owned));
QUIC_DVLOG(1) << "Opened echo response stream " << stream->id();
- stream->set_visitor(
- std::make_unique<UnidirectionalEchoWriteVisitor>(stream, data));
+ stream->SetVisitor(
+ std::make_unique<WebTransportUnidirectionalEchoWriteVisitor>(stream,
+ data));
stream->visitor()->OnCanWrite();
}
}
@@ -267,7 +165,8 @@ void QuicTransportSimpleServerSession::
QuicTransportStream* stream = stream_owned.get();
ActivateStream(std::move(stream_owned));
QUIC_DVLOG(1) << "Opened outgoing bidirectional stream " << stream->id();
- stream->set_visitor(std::make_unique<BidirectionalEchoVisitor>(stream));
+ stream->SetVisitor(
+ std::make_unique<WebTransportBidirectionalEchoVisitor>(stream));
if (!stream->Write("hello")) {
QUIC_DVLOG(1) << "Write failed.";
}
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
new file mode 100644
index 00000000000..9bf6e6bca84
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/tools/web_transport_test_visitors.h
@@ -0,0 +1,137 @@
+// 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_TOOLS_WEB_TRANSPORT_TEST_VISITORS_H_
+#define QUICHE_QUIC_TOOLS_WEB_TRANSPORT_TEST_VISITORS_H_
+
+#include <string>
+
+#include "quic/core/web_transport_interface.h"
+#include "quic/platform/api/quic_logging.h"
+
+namespace quic {
+
+// Discards any incoming data.
+class WebTransportDiscardVisitor : public WebTransportStreamVisitor {
+ public:
+ WebTransportDiscardVisitor(WebTransportStream* stream) : stream_(stream) {}
+
+ void OnCanRead() override {
+ std::string buffer;
+ WebTransportStream::ReadResult result = stream_->Read(&buffer);
+ QUIC_DVLOG(2) << "Read " << result.bytes_read
+ << " bytes from WebTransport stream "
+ << stream_->GetStreamId() << ", fin: " << result.fin;
+ }
+
+ void OnCanWrite() override {}
+
+ private:
+ WebTransportStream* stream_;
+};
+
+// Echoes any incoming data back on the same stream.
+class WebTransportBidirectionalEchoVisitor : public WebTransportStreamVisitor {
+ public:
+ WebTransportBidirectionalEchoVisitor(WebTransportStream* stream)
+ : stream_(stream) {}
+
+ void OnCanRead() override {
+ WebTransportStream::ReadResult result = stream_->Read(&buffer_);
+ QUIC_DVLOG(1) << "Attempted reading on WebTransport bidirectional stream "
+ << stream_->GetStreamId()
+ << ", bytes read: " << result.bytes_read;
+ if (result.fin) {
+ send_fin_ = true;
+ }
+ OnCanWrite();
+ }
+
+ void OnCanWrite() override {
+ if (!buffer_.empty()) {
+ bool success = stream_->Write(buffer_);
+ QUIC_DVLOG(1) << "Attempted writing on WebTransport bidirectional stream "
+ << stream_->GetStreamId()
+ << ", success: " << (success ? "yes" : "no");
+ if (!success) {
+ return;
+ }
+
+ buffer_ = "";
+ }
+
+ if (send_fin_) {
+ bool success = stream_->SendFin();
+ QUICHE_DCHECK(success);
+ }
+ }
+
+ private:
+ WebTransportStream* stream_;
+ std::string buffer_;
+ bool send_fin_ = false;
+};
+
+// Buffers all of the data and calls |callback| with the entirety of the stream
+// data.
+class WebTransportUnidirectionalEchoReadVisitor
+ : public WebTransportStreamVisitor {
+ public:
+ using Callback = std::function<void(const std::string&)>;
+
+ WebTransportUnidirectionalEchoReadVisitor(WebTransportStream* stream,
+ Callback callback)
+ : stream_(stream), callback_(std::move(callback)) {}
+
+ void OnCanRead() override {
+ WebTransportStream::ReadResult result = stream_->Read(&buffer_);
+ QUIC_DVLOG(1) << "Attempted reading on WebTransport unidirectional stream "
+ << stream_->GetStreamId()
+ << ", bytes read: " << result.bytes_read;
+ if (result.fin) {
+ QUIC_DVLOG(1) << "Finished receiving data on a WebTransport stream "
+ << stream_->GetStreamId() << ", queueing up the echo";
+ callback_(buffer_);
+ }
+ }
+
+ void OnCanWrite() override { QUIC_NOTREACHED(); }
+
+ private:
+ WebTransportStream* stream_;
+ std::string buffer_;
+ Callback callback_;
+};
+
+// Sends supplied data.
+class WebTransportUnidirectionalEchoWriteVisitor
+ : public WebTransportStreamVisitor {
+ public:
+ WebTransportUnidirectionalEchoWriteVisitor(WebTransportStream* stream,
+ const std::string& data)
+ : stream_(stream), data_(data) {}
+
+ void OnCanRead() override { QUIC_NOTREACHED(); }
+ void OnCanWrite() override {
+ if (data_.empty()) {
+ return;
+ }
+ if (!stream_->Write(data_)) {
+ return;
+ }
+ data_ = "";
+ bool fin_sent = stream_->SendFin();
+ QUICHE_DVLOG(1)
+ << "WebTransportUnidirectionalEchoWriteVisitor finished sending data.";
+ QUICHE_DCHECK(fin_sent);
+ }
+
+ private:
+ WebTransportStream* stream_;
+ std::string data_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_TOOLS_WEB_TRANSPORT_TEST_VISITORS_H_
diff --git a/chromium/net/third_party/quiche/src/spdy/core/fifo_write_scheduler.h b/chromium/net/third_party/quiche/src/spdy/core/fifo_write_scheduler.h
deleted file mode 100644
index 7bf8c4ed475..00000000000
--- a/chromium/net/third_party/quiche/src/spdy/core/fifo_write_scheduler.h
+++ /dev/null
@@ -1,242 +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_CORE_FIFO_WRITE_SCHEDULER_H_
-#define QUICHE_SPDY_CORE_FIFO_WRITE_SCHEDULER_H_
-
-#include <map>
-#include <set>
-#include <string>
-
-#include "absl/strings/str_cat.h"
-#include "spdy/core/write_scheduler.h"
-#include "spdy/platform/api/spdy_string_utils.h"
-
-namespace spdy {
-
-// A write scheduler where the stream with the smallest stream ID will have the
-// highest priority.
-template <typename StreamIdType>
-class FifoWriteScheduler : public WriteScheduler<StreamIdType> {
- public:
- using typename WriteScheduler<StreamIdType>::StreamPrecedenceType;
-
- FifoWriteScheduler() = default;
-
- // WriteScheduler methods
- void RegisterStream(StreamIdType stream_id,
- const StreamPrecedenceType& precedence) override;
- void UnregisterStream(StreamIdType stream_id) override;
- bool StreamRegistered(StreamIdType stream_id) const override;
- // Stream precedence is available but note that it is not used for scheduling
- // in this scheduler.
- StreamPrecedenceType GetStreamPrecedence(
- StreamIdType stream_id) const override;
- void UpdateStreamPrecedence(StreamIdType stream_id,
- const StreamPrecedenceType& precedence) override;
- std::vector<StreamIdType> GetStreamChildren(
- StreamIdType stream_id) const override;
- void RecordStreamEventTime(StreamIdType stream_id,
- int64_t now_in_usec) override;
- int64_t GetLatestEventWithPrecedence(StreamIdType stream_id) const override;
- bool ShouldYield(StreamIdType stream_id) const override;
- void MarkStreamReady(StreamIdType stream_id, bool add_to_front) override;
- void MarkStreamNotReady(StreamIdType stream_id) override;
- bool HasReadyStreams() const override;
- StreamIdType PopNextReadyStream() override;
- std::tuple<StreamIdType, StreamPrecedenceType>
- PopNextReadyStreamAndPrecedence() override;
- size_t NumReadyStreams() const override;
- bool IsStreamReady(StreamIdType stream_id) const override;
- size_t NumRegisteredStreams() const override;
- std::string DebugString() const override;
-
- private:
- struct StreamInfo {
- SpdyPriority priority;
- int64_t event_time; // read/write event time (us since Unix epoch).
- };
-
- std::set<StreamIdType> ready_streams_;
- std::map<StreamIdType, StreamInfo> registered_streams_;
-};
-
-template <typename StreamIdType>
-void FifoWriteScheduler<StreamIdType>::RegisterStream(
- StreamIdType stream_id,
- const StreamPrecedenceType& precedence) {
- if (StreamRegistered(stream_id)) {
- SPDY_BUG << "Stream " << stream_id << " already registered";
- return;
- }
- registered_streams_.emplace_hint(
- registered_streams_.end(), stream_id,
- StreamInfo{/*priority=*/precedence.spdy3_priority(), /*event_time=*/0});
-}
-
-template <typename StreamIdType>
-void FifoWriteScheduler<StreamIdType>::UnregisterStream(
- StreamIdType stream_id) {
- if (!StreamRegistered(stream_id)) {
- SPDY_BUG << "Stream " << stream_id << " is not registered";
- return;
- }
- registered_streams_.erase(stream_id);
- ready_streams_.erase(stream_id);
-}
-
-template <typename StreamIdType>
-bool FifoWriteScheduler<StreamIdType>::StreamRegistered(
- StreamIdType stream_id) const {
- return registered_streams_.find(stream_id) != registered_streams_.end();
-}
-
-// Stream precedence is not supported by this scheduler.
-template <typename StreamIdType>
-typename FifoWriteScheduler<StreamIdType>::StreamPrecedenceType
-FifoWriteScheduler<StreamIdType>::GetStreamPrecedence(
- StreamIdType stream_id) const {
- auto it = registered_streams_.find(stream_id);
- if (it == registered_streams_.end()) {
- SPDY_DVLOG(1) << "Stream " << stream_id << " not registered";
- return StreamPrecedenceType(kV3LowestPriority);
- }
- return StreamPrecedenceType(it->second.priority);
-}
-
-template <typename StreamIdType>
-void FifoWriteScheduler<StreamIdType>::UpdateStreamPrecedence(
- StreamIdType stream_id,
- const StreamPrecedenceType& precedence) {
- auto it = registered_streams_.find(stream_id);
- if (it == registered_streams_.end()) {
- SPDY_DVLOG(1) << "Stream " << stream_id << " not registered";
- return;
- }
- it->second.priority = precedence.spdy3_priority();
-}
-
-template <typename StreamIdType>
-std::vector<StreamIdType> FifoWriteScheduler<StreamIdType>::GetStreamChildren(
- StreamIdType /*stream_id*/) const {
- return std::vector<StreamIdType>();
-}
-
-template <typename StreamIdType>
-void FifoWriteScheduler<StreamIdType>::RecordStreamEventTime(
- StreamIdType stream_id,
- int64_t now_in_usec) {
- auto it = registered_streams_.find(stream_id);
- if (it != registered_streams_.end()) {
- it->second.event_time = now_in_usec;
- } else {
- SPDY_BUG << "Stream " << stream_id << " is not registered";
- }
-}
-
-template <typename StreamIdType>
-int64_t FifoWriteScheduler<StreamIdType>::GetLatestEventWithPrecedence(
- StreamIdType stream_id) const {
- if (!StreamRegistered(stream_id)) {
- SPDY_BUG << "Stream " << stream_id << " is not registered";
- return 0;
- }
- int64_t latest_event_time_us = 0;
- for (auto it = registered_streams_.begin(); it != registered_streams_.end();
- ++it) {
- if (stream_id <= it->first) {
- break;
- }
- latest_event_time_us =
- std::max(latest_event_time_us, it->second.event_time);
- }
- return latest_event_time_us;
-}
-
-template <typename StreamIdType>
-bool FifoWriteScheduler<StreamIdType>::ShouldYield(
- StreamIdType stream_id) const {
- return !ready_streams_.empty() && stream_id > *ready_streams_.begin();
-}
-
-template <typename StreamIdType>
-void FifoWriteScheduler<StreamIdType>::MarkStreamReady(StreamIdType stream_id,
- bool /*add_to_front*/) {
- if (!StreamRegistered(stream_id)) {
- SPDY_BUG << "Stream " << stream_id << " is not registered";
- return;
- }
- if (ready_streams_.find(stream_id) != ready_streams_.end()) {
- SPDY_DVLOG(1) << "Stream already exists in the list";
- return;
- }
- ready_streams_.insert(stream_id);
-}
-
-template <typename StreamIdType>
-void FifoWriteScheduler<StreamIdType>::MarkStreamNotReady(
- StreamIdType stream_id) {
- auto it = ready_streams_.find(stream_id);
- if (it == ready_streams_.end()) {
- SPDY_DVLOG(1) << "Try to remove a stream that is not on list";
- return;
- }
- ready_streams_.erase(it);
-}
-
-template <typename StreamIdType>
-bool FifoWriteScheduler<StreamIdType>::HasReadyStreams() const {
- return !ready_streams_.empty();
-}
-
-template <typename StreamIdType>
-StreamIdType FifoWriteScheduler<StreamIdType>::PopNextReadyStream() {
- if (ready_streams_.empty()) {
- SPDY_BUG << "No ready streams available";
- return 0;
- }
- auto it = ready_streams_.begin();
- StreamIdType id = *it;
- ready_streams_.erase(it);
- return id;
-}
-
-template <typename StreamIdType>
-std::tuple<StreamIdType,
- typename FifoWriteScheduler<StreamIdType>::StreamPrecedenceType>
-FifoWriteScheduler<StreamIdType>::PopNextReadyStreamAndPrecedence() {
- return std::make_tuple(PopNextReadyStream(),
- StreamPrecedenceType(kV3LowestPriority));
-}
-
-template <typename StreamIdType>
-size_t FifoWriteScheduler<StreamIdType>::NumReadyStreams() const {
- return ready_streams_.size();
-}
-
-template <typename StreamIdType>
-bool FifoWriteScheduler<StreamIdType>::IsStreamReady(
- StreamIdType stream_id) const {
- if (!StreamRegistered(stream_id)) {
- SPDY_BUG << "Stream " << stream_id << " is not registered";
- return false;
- }
- return ready_streams_.find(stream_id) != ready_streams_.end();
-}
-
-template <typename StreamIdType>
-size_t FifoWriteScheduler<StreamIdType>::NumRegisteredStreams() const {
- return registered_streams_.size();
-}
-
-template <typename StreamIdType>
-std::string FifoWriteScheduler<StreamIdType>::DebugString() const {
- return absl::StrCat(
- "FifoWriteScheduler {num_streams=", registered_streams_.size(),
- " num_ready_streams=", NumReadyStreams(), "}");
-}
-
-} // namespace spdy
-
-#endif // QUICHE_SPDY_CORE_FIFO_WRITE_SCHEDULER_H_
diff --git a/chromium/net/third_party/quiche/src/spdy/core/fifo_write_scheduler_test.cc b/chromium/net/third_party/quiche/src/spdy/core/fifo_write_scheduler_test.cc
deleted file mode 100644
index c2b1d7eb84a..00000000000
--- a/chromium/net/third_party/quiche/src/spdy/core/fifo_write_scheduler_test.cc
+++ /dev/null
@@ -1,103 +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 "spdy/core/fifo_write_scheduler.h"
-
-#include "common/platform/api/quiche_test.h"
-#include "spdy/platform/api/spdy_test_helpers.h"
-
-namespace spdy {
-
-namespace test {
-
-TEST(FifoWriteSchedulerTest, BasicTest) {
- FifoWriteScheduler<SpdyStreamId> fifo;
- EXPECT_FALSE(fifo.HasReadyStreams());
- EXPECT_SPDY_BUG(
- EXPECT_EQ(0u, std::get<0>(fifo.PopNextReadyStreamAndPrecedence())),
- "No ready streams available");
- EXPECT_SPDY_BUG(fifo.MarkStreamReady(9, true), "Stream 9 is not registered");
- EXPECT_SPDY_BUG(fifo.IsStreamReady(9), "Stream 9 is not registered");
-
- SpdyStreamPrecedence precedence(1);
- fifo.RegisterStream(3, precedence);
- EXPECT_FALSE(fifo.IsStreamReady(3));
- fifo.RegisterStream(9, precedence);
- fifo.RegisterStream(7, precedence);
- fifo.RegisterStream(11, precedence);
- fifo.RegisterStream(13, precedence);
- fifo.RegisterStream(15, precedence);
- fifo.RegisterStream(17, precedence);
- EXPECT_EQ(7u, fifo.NumRegisteredStreams());
- EXPECT_FALSE(fifo.HasReadyStreams());
-
- fifo.MarkStreamReady(9, true);
- EXPECT_TRUE(fifo.IsStreamReady(9));
- EXPECT_TRUE(fifo.HasReadyStreams());
- fifo.MarkStreamReady(15, true);
- fifo.MarkStreamReady(7, true);
- fifo.MarkStreamReady(13, true);
- fifo.MarkStreamReady(11, true);
- fifo.MarkStreamReady(3, true);
- fifo.MarkStreamReady(17, true);
- EXPECT_EQ(7u, fifo.NumReadyStreams());
-
- EXPECT_EQ(3u, fifo.PopNextReadyStream());
- EXPECT_EQ(7u, std::get<0>(fifo.PopNextReadyStreamAndPrecedence()));
- EXPECT_EQ(5u, fifo.NumReadyStreams());
-
- EXPECT_FALSE(fifo.ShouldYield(3));
- EXPECT_FALSE(fifo.ShouldYield(9));
- EXPECT_TRUE(fifo.ShouldYield(13));
- EXPECT_TRUE(fifo.ShouldYield(10));
-
- fifo.MarkStreamNotReady(9);
- EXPECT_EQ(4u, fifo.NumReadyStreams());
- EXPECT_FALSE(fifo.ShouldYield(10));
- EXPECT_TRUE(fifo.ShouldYield(12));
-}
-
-TEST(FifoWriteSchedulerTest, GetLatestEventTest) {
- FifoWriteScheduler<SpdyStreamId> fifo;
-
- SpdyStreamPrecedence precedence(1);
- fifo.RegisterStream(1, precedence);
- fifo.RegisterStream(3, precedence);
- fifo.RegisterStream(5, precedence);
- fifo.RegisterStream(7, precedence);
- fifo.RegisterStream(9, precedence);
- fifo.RecordStreamEventTime(1, 3);
- fifo.RecordStreamEventTime(3, 2);
- fifo.RecordStreamEventTime(5, 4);
- fifo.RecordStreamEventTime(7, 8);
- fifo.RecordStreamEventTime(9, 1);
-
- EXPECT_EQ(8, fifo.GetLatestEventWithPrecedence(9));
- EXPECT_EQ(4, fifo.GetLatestEventWithPrecedence(7));
- EXPECT_EQ(3, fifo.GetLatestEventWithPrecedence(5));
- EXPECT_EQ(3, fifo.GetLatestEventWithPrecedence(3));
- EXPECT_EQ(0, fifo.GetLatestEventWithPrecedence(1));
-}
-
-TEST(FifoWriteSchedulerTest, GetStreamPrecedence) {
- FifoWriteScheduler<SpdyStreamId> fifo;
- // Return lowest priority for unknown stream.
- EXPECT_EQ(kV3LowestPriority, fifo.GetStreamPrecedence(1).spdy3_priority());
-
- fifo.RegisterStream(1, SpdyStreamPrecedence(3));
- EXPECT_TRUE(fifo.GetStreamPrecedence(1).is_spdy3_priority());
- EXPECT_EQ(3, fifo.GetStreamPrecedence(1).spdy3_priority());
-
- // Redundant registration shouldn't change stream priority.
- EXPECT_SPDY_BUG(fifo.RegisterStream(1, SpdyStreamPrecedence(4)),
- "Stream 1 already registered");
- EXPECT_EQ(3, fifo.GetStreamPrecedence(1).spdy3_priority());
-
- fifo.UpdateStreamPrecedence(1, SpdyStreamPrecedence(5));
- EXPECT_EQ(5, fifo.GetStreamPrecedence(1).spdy3_priority());
-}
-
-} // namespace test
-
-} // 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 59ba669b6a9..4d03cc50018 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
@@ -11,7 +11,6 @@
#include "spdy/platform/api/spdy_logging.h"
using ::http2::DecodeBuffer;
-using ::http2::HpackString;
namespace spdy {
namespace {
@@ -108,18 +107,6 @@ const SpdyHeaderBlock& HpackDecoderAdapter::decoded_block() const {
return listener_adapter_.decoded_block();
}
-void HpackDecoderAdapter::SetHeaderTableDebugVisitor(
- std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) {
- SPDY_DVLOG(2) << "HpackDecoderAdapter::SetHeaderTableDebugVisitor";
- if (visitor != nullptr) {
- listener_adapter_.SetHeaderTableDebugVisitor(std::move(visitor));
- hpack_decoder_.set_tables_debug_listener(&listener_adapter_);
- } else {
- hpack_decoder_.set_tables_debug_listener(nullptr);
- listener_adapter_.SetHeaderTableDebugVisitor(nullptr);
- }
-}
-
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";
@@ -144,11 +131,6 @@ void HpackDecoderAdapter::ListenerAdapter::set_handler(
handler_ = handler;
}
-void HpackDecoderAdapter::ListenerAdapter::SetHeaderTableDebugVisitor(
- std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) {
- visitor_ = std::move(visitor);
-}
-
void HpackDecoderAdapter::ListenerAdapter::OnHeaderListStart() {
SPDY_DVLOG(2) << "HpackDecoderAdapter::ListenerAdapter::OnHeaderListStart";
total_hpack_bytes_ = 0;
@@ -159,18 +141,17 @@ void HpackDecoderAdapter::ListenerAdapter::OnHeaderListStart() {
}
}
-void HpackDecoderAdapter::ListenerAdapter::OnHeader(const HpackString& name,
- const HpackString& value) {
+void HpackDecoderAdapter::ListenerAdapter::OnHeader(const std::string& name,
+ const std::string& value) {
SPDY_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";
- decoded_block_.AppendValueOrAddHeader(name.ToStringPiece(),
- value.ToStringPiece());
+ decoded_block_.AppendValueOrAddHeader(name, value);
} else {
SPDY_DVLOG(3) << "Passing to handler";
- handler_->OnHeader(name.ToStringPiece(), value.ToStringPiece());
+ handler_->OnHeader(name, value);
}
}
@@ -189,38 +170,4 @@ void HpackDecoderAdapter::ListenerAdapter::OnHeaderErrorDetected(
SPDY_VLOG(1) << error_message;
}
-int64_t HpackDecoderAdapter::ListenerAdapter::OnEntryInserted(
- const http2::HpackStringPair& entry,
- size_t insert_count) {
- SPDY_DVLOG(2) << "HpackDecoderAdapter::ListenerAdapter::OnEntryInserted: "
- << entry << ", insert_count=" << insert_count;
- if (visitor_ == nullptr) {
- return 0;
- }
- HpackEntry hpack_entry(entry.name.ToStringPiece(),
- entry.value.ToStringPiece(),
- /*is_static*/ false, insert_count);
- int64_t time_added = visitor_->OnNewEntry(hpack_entry);
- SPDY_DVLOG(2)
- << "HpackDecoderAdapter::ListenerAdapter::OnEntryInserted: time_added="
- << time_added;
- return time_added;
-}
-
-void HpackDecoderAdapter::ListenerAdapter::OnUseEntry(
- const http2::HpackStringPair& entry,
- size_t insert_count,
- int64_t time_added) {
- SPDY_DVLOG(2) << "HpackDecoderAdapter::ListenerAdapter::OnUseEntry: " << entry
- << ", insert_count=" << insert_count
- << ", time_added=" << time_added;
- if (visitor_ != nullptr) {
- HpackEntry hpack_entry(entry.name.ToStringPiece(),
- entry.value.ToStringPiece(), /*is_static*/ false,
- insert_count);
- hpack_entry.set_time_added(time_added);
- visitor_->OnUseEntry(hpack_entry);
- }
-}
-
} // namespace spdy
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h
index 5ec7046d2c2..98d10fe2c9a 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h
@@ -17,7 +17,6 @@
#include "http2/hpack/decoder/hpack_decoder.h"
#include "http2/hpack/decoder/hpack_decoder_listener.h"
#include "http2/hpack/decoder/hpack_decoder_tables.h"
-#include "http2/hpack/hpack_string.h"
#include "http2/hpack/http2_hpack_constants.h"
#include "common/platform/api/quiche_export.h"
#include "spdy/core/hpack/hpack_header_table.h"
@@ -68,9 +67,6 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderAdapter {
// a SpdyHeadersHandlerInterface.
const SpdyHeaderBlock& decoded_block() const;
- void SetHeaderTableDebugVisitor(
- std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor);
-
// Set how much encoded data this decoder is willing to buffer.
// TODO(jamessynge): Resolve definition of this value, as it is currently
// too tied to a single implementation. We probably want to limit one or more
@@ -92,8 +88,7 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderAdapter {
private:
class QUICHE_EXPORT_PRIVATE ListenerAdapter
- : public http2::HpackDecoderListener,
- public http2::HpackDecoderTablesDebugListener {
+ : public http2::HpackDecoderListener {
public:
ListenerAdapter();
~ListenerAdapter() override;
@@ -105,23 +100,12 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderAdapter {
void set_handler(SpdyHeadersHandlerInterface* handler);
const SpdyHeaderBlock& decoded_block() const { return decoded_block_; }
- void SetHeaderTableDebugVisitor(
- std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor);
-
// Override the HpackDecoderListener methods:
void OnHeaderListStart() override;
- void OnHeader(const http2::HpackString& name,
- const http2::HpackString& value) override;
+ void OnHeader(const std::string& name, const std::string& value) override;
void OnHeaderListEnd() override;
void OnHeaderErrorDetected(absl::string_view error_message) override;
- // Override the HpackDecoderTablesDebugListener methods:
- int64_t OnEntryInserted(const http2::HpackStringPair& entry,
- size_t insert_count) override;
- void OnUseEntry(const http2::HpackStringPair& entry,
- size_t insert_count,
- int64_t time_added) override;
-
void AddToTotalHpackBytes(size_t delta) { total_hpack_bytes_ += delta; }
size_t total_hpack_bytes() const { return total_hpack_bytes_; }
@@ -139,10 +123,6 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderAdapter {
// Total bytes of the name and value strings in the current HPACK block.
size_t total_uncompressed_bytes_;
-
- // visitor_ is used by a QUIC experiment regarding HPACK; remove
- // when the experiment is done.
- std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor_;
};
// Converts calls to HpackDecoderListener into calls to
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 c768755dbb7..0a12fe49a21 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
@@ -28,7 +28,6 @@
#include "spdy/platform/api/spdy_string_utils.h"
using ::http2::HpackEntryType;
-using ::http2::HpackString;
using ::http2::HpackStringPair;
using ::http2::test::HpackBlockBuilder;
using ::http2::test::HpackDecoderPeer;
@@ -66,9 +65,9 @@ class HpackDecoderAdapterPeer {
explicit HpackDecoderAdapterPeer(HpackDecoderAdapter* decoder)
: decoder_(decoder) {}
- void HandleHeaderRepresentation(absl::string_view name,
- absl::string_view value) {
- decoder_->listener_adapter_.OnHeader(HpackString(name), HpackString(value));
+ void HandleHeaderRepresentation(const std::string& name,
+ const std::string& value) {
+ decoder_->listener_adapter_.OnHeader(name, value);
}
http2::HpackDecoderTables* GetDecoderTables() {
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 7e924afea43..6dc27b9ca7f 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
@@ -137,10 +137,10 @@ void HpackEncoder::EncodeRepresentations(RepresentationIterator* iter,
const auto header = iter->Next();
listener_(header.first, header.second);
if (enable_compression_) {
- const HpackEntry* entry =
+ size_t index =
header_table_.GetByNameAndValue(header.first, header.second);
- if (entry != nullptr) {
- EmitIndex(entry);
+ if (index != kHpackEntryNotFound) {
+ EmitIndex(index);
} else if (should_index_(header.first, header.second)) {
EmitIndexedLiteral(header);
} else {
@@ -154,10 +154,10 @@ void HpackEncoder::EncodeRepresentations(RepresentationIterator* iter,
output_stream_.TakeString(output);
}
-void HpackEncoder::EmitIndex(const HpackEntry* entry) {
- SPDY_DVLOG(2) << "Emitting index " << header_table_.IndexOf(entry);
+void HpackEncoder::EmitIndex(size_t index) {
+ SPDY_DVLOG(2) << "Emitting index " << index;
output_stream_.AppendPrefix(kIndexedOpcode);
- output_stream_.AppendUint32(header_table_.IndexOf(entry));
+ output_stream_.AppendUint32(index);
}
void HpackEncoder::EmitIndexedLiteral(const Representation& representation) {
@@ -173,9 +173,9 @@ void HpackEncoder::EmitNonIndexedLiteral(const Representation& representation,
SPDY_DVLOG(2) << "Emitting nonindexed literal: (" << representation.first
<< ", " << representation.second << ")";
output_stream_.AppendPrefix(kLiteralNoIndexOpcode);
- const HpackEntry* name_entry = header_table_.GetByName(representation.first);
- if (enable_compression && name_entry != nullptr) {
- output_stream_.AppendUint32(header_table_.IndexOf(name_entry));
+ size_t name_index = header_table_.GetByName(representation.first);
+ if (enable_compression && name_index != kHpackEntryNotFound) {
+ output_stream_.AppendUint32(name_index);
} else {
output_stream_.AppendUint32(0);
EmitString(representation.first);
@@ -184,9 +184,9 @@ void HpackEncoder::EmitNonIndexedLiteral(const Representation& representation,
}
void HpackEncoder::EmitLiteral(const Representation& representation) {
- const HpackEntry* name_entry = header_table_.GetByName(representation.first);
- if (name_entry != nullptr) {
- output_stream_.AppendUint32(header_table_.IndexOf(name_entry));
+ size_t name_index = header_table_.GetByName(representation.first);
+ if (name_index != kHpackEntryNotFound) {
+ output_stream_.AppendUint32(name_index);
} else {
output_stream_.AppendUint32(0);
EmitString(representation.first);
@@ -347,7 +347,7 @@ HpackEncoder::Encoderator::Encoderator(const Representations& representations,
void HpackEncoder::Encoderator::Next(size_t max_encoded_bytes,
std::string* output) {
- SPDY_BUG_IF(!has_next_)
+ SPDY_BUG_IF(spdy_bug_61_1, !has_next_)
<< "Encoderator::Next called with nothing left to encode.";
const bool enable_compression = encoder_->enable_compression_;
@@ -357,10 +357,10 @@ void HpackEncoder::Encoderator::Next(size_t max_encoded_bytes,
const Representation header = header_it_->Next();
encoder_->listener_(header.first, header.second);
if (enable_compression) {
- const HpackEntry* entry = encoder_->header_table_.GetByNameAndValue(
- header.first, header.second);
- if (entry != nullptr) {
- encoder_->EmitIndex(entry);
+ size_t index = encoder_->header_table_.GetByNameAndValue(header.first,
+ header.second);
+ if (index != kHpackEntryNotFound) {
+ encoder_->EmitIndex(index);
} else if (encoder_->should_index_(header.first, header.second)) {
encoder_->EmitIndexedLiteral(header);
} else {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h
index b1b7741deba..d85b98ede0b 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h
@@ -93,11 +93,6 @@ class QUICHE_EXPORT_PRIVATE HpackEncoder {
// this encoder.
void SetHeaderListener(HeaderListener listener) { listener_ = listener; }
- void SetHeaderTableDebugVisitor(
- std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) {
- header_table_.set_debug_visitor(std::move(visitor));
- }
-
void DisableCompression() { enable_compression_ = false; }
// Returns the estimate of dynamically allocated memory in bytes.
@@ -113,7 +108,7 @@ class QUICHE_EXPORT_PRIVATE HpackEncoder {
void EncodeRepresentations(RepresentationIterator* iter, std::string* output);
// Emits a static/dynamic indexed representation (Section 7.1).
- void EmitIndex(const HpackEntry* entry);
+ void EmitIndex(size_t index);
// Emits a literal representation (Section 7.2).
void EmitIndexedLiteral(const Representation& representation);
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 0257aa6afec..85fa4fbc321 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
@@ -10,6 +10,7 @@
#include "http2/hpack/huffman/hpack_huffman_encoder.h"
#include "http2/test_tools/http2_random.h"
#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"
@@ -21,7 +22,11 @@ class HpackHeaderTablePeer {
public:
explicit HpackHeaderTablePeer(HpackHeaderTable* table) : table_(table) {}
- HpackHeaderTable::EntryTable* dynamic_entries() {
+ const HpackEntry* GetFirstStaticEntry() const {
+ return &table_->static_entries_.front();
+ }
+
+ HpackHeaderTable::DynamicEntryTable* dynamic_entries() {
return &table_->dynamic_entries_;
}
@@ -118,6 +123,8 @@ namespace {
using testing::ElementsAre;
using testing::Pair;
+const size_t kStaticEntryIndex = 1;
+
enum EncodeStrategy {
kDefault,
kIncremental,
@@ -130,7 +137,8 @@ class HpackEncoderTest : public QuicheTestWithParam<EncodeStrategy> {
HpackEncoderTest()
: peer_(&encoder_),
- static_(peer_.table()->GetByIndex(1)),
+ static_(peer_.table_peer().GetFirstStaticEntry()),
+ dynamic_table_insertions_(0),
headers_storage_(1024 /* block size */),
strategy_(GetParam()) {}
@@ -138,9 +146,13 @@ class HpackEncoderTest : public QuicheTestWithParam<EncodeStrategy> {
// Populate dynamic entries into the table fixture. For simplicity each
// entry has name.size() + value.size() == 10.
key_1_ = peer_.table()->TryAddEntry("key1", "value1");
+ key_1_index_ = dynamic_table_insertions_++;
key_2_ = peer_.table()->TryAddEntry("key2", "value2");
+ key_2_index_ = dynamic_table_insertions_++;
cookie_a_ = peer_.table()->TryAddEntry("cookie", "a=bb");
+ cookie_a_index_ = dynamic_table_insertions_++;
cookie_c_ = peer_.table()->TryAddEntry("cookie", "c=dd");
+ cookie_c_index_ = dynamic_table_insertions_++;
// No further insertions may occur without evictions.
peer_.table()->SetMaxSize(peer_.table()->size());
@@ -158,10 +170,9 @@ class HpackEncoderTest : public QuicheTestWithParam<EncodeStrategy> {
expected_.AppendPrefix(kIndexedOpcode);
expected_.AppendUint32(index);
}
- void ExpectIndexedLiteral(const HpackEntry* key_entry,
- absl::string_view value) {
+ void ExpectIndexedLiteral(size_t key_index, absl::string_view value) {
expected_.AppendPrefix(kLiteralIncrementalIndexOpcode);
- expected_.AppendUint32(IndexOf(key_entry));
+ expected_.AppendUint32(key_index);
ExpectString(&expected_, value);
}
void ExpectIndexedLiteral(absl::string_view name, absl::string_view value) {
@@ -177,10 +188,10 @@ class HpackEncoderTest : public QuicheTestWithParam<EncodeStrategy> {
ExpectString(&expected_, name);
ExpectString(&expected_, value);
}
- void ExpectNonIndexedLiteralWithNameIndex(const HpackEntry* key_entry,
+ void ExpectNonIndexedLiteralWithNameIndex(size_t key_index,
absl::string_view value) {
expected_.AppendPrefix(kLiteralNoIndexOpcode);
- expected_.AppendUint32(IndexOf(key_entry));
+ expected_.AppendUint32(key_index);
ExpectString(&expected_, value);
}
void ExpectString(HpackOutputStream* stream, absl::string_view str) {
@@ -233,8 +244,12 @@ class HpackEncoderTest : public QuicheTestWithParam<EncodeStrategy> {
&encoder_, representations, &actual_out));
EXPECT_EQ(expected_out, actual_out);
}
- size_t IndexOf(const HpackEntry* entry) {
- return peer_.table()->IndexOf(entry);
+ // Converts the index of a dynamic table entry to the HPACK index.
+ // In these test, dynamic table entries are indexed sequentially, starting
+ // with 0. The HPACK indexing scheme is defined at
+ // https://httpwg.org/specs/rfc7541.html#index.address.space.
+ size_t DynamicIndexToWireIndex(size_t index) {
+ return dynamic_table_insertions_ - index + kStaticTableSize;
}
HpackEncoder encoder_;
@@ -245,6 +260,11 @@ class HpackEncoderTest : public QuicheTestWithParam<EncodeStrategy> {
const HpackEntry* key_2_;
const HpackEntry* cookie_a_;
const HpackEntry* cookie_c_;
+ size_t key_1_index_;
+ size_t key_2_index_;
+ size_t cookie_a_index_;
+ size_t cookie_c_index_;
+ size_t dynamic_table_insertions_;
SpdySimpleArena headers_storage_;
std::vector<std::pair<absl::string_view, absl::string_view>>
@@ -303,7 +323,7 @@ TEST_P(HpackEncoderTest, SingleDynamicIndex) {
this->SaveHeaders(name, value);
});
- ExpectIndex(IndexOf(key_2_));
+ ExpectIndex(DynamicIndexToWireIndex(key_2_index_));
SpdyHeaderBlock headers;
headers[key_2_->name()] = key_2_->value();
@@ -313,7 +333,7 @@ TEST_P(HpackEncoderTest, SingleDynamicIndex) {
}
TEST_P(HpackEncoderTest, SingleStaticIndex) {
- ExpectIndex(IndexOf(static_));
+ ExpectIndex(kStaticEntryIndex);
SpdyHeaderBlock headers;
headers[static_->name()] = static_->value();
@@ -322,7 +342,7 @@ TEST_P(HpackEncoderTest, SingleStaticIndex) {
TEST_P(HpackEncoderTest, SingleStaticIndexTooLarge) {
peer_.table()->SetMaxSize(1); // Also evicts all fixtures.
- ExpectIndex(IndexOf(static_));
+ ExpectIndex(kStaticEntryIndex);
SpdyHeaderBlock headers;
headers[static_->name()] = static_->value();
@@ -332,7 +352,7 @@ TEST_P(HpackEncoderTest, SingleStaticIndexTooLarge) {
}
TEST_P(HpackEncoderTest, SingleLiteralWithIndexName) {
- ExpectIndexedLiteral(key_2_, "value3");
+ ExpectIndexedLiteral(DynamicIndexToWireIndex(key_2_index_), "value3");
SpdyHeaderBlock headers;
headers[key_2_->name()] = "value3";
@@ -373,7 +393,7 @@ TEST_P(HpackEncoderTest, SingleLiteralTooLarge) {
TEST_P(HpackEncoderTest, EmitThanEvict) {
// |key_1_| is toggled and placed into the reference set,
// and then immediately evicted by "key3".
- ExpectIndex(IndexOf(key_1_));
+ ExpectIndex(DynamicIndexToWireIndex(key_1_index_));
ExpectIndexedLiteral("key3", "value3");
SpdyHeaderBlock headers;
@@ -383,8 +403,8 @@ TEST_P(HpackEncoderTest, EmitThanEvict) {
}
TEST_P(HpackEncoderTest, CookieHeaderIsCrumbled) {
- ExpectIndex(IndexOf(cookie_a_));
- ExpectIndex(IndexOf(cookie_c_));
+ ExpectIndex(DynamicIndexToWireIndex(cookie_a_index_));
+ ExpectIndex(DynamicIndexToWireIndex(cookie_c_index_));
ExpectIndexedLiteral(peer_.table()->GetByName("cookie"), "e=ff");
SpdyHeaderBlock headers;
@@ -474,8 +494,8 @@ TEST_P(HpackEncoderTest, MultipleEncodingPasses) {
headers["key1"] = "value1";
headers["cookie"] = "a=bb";
- ExpectIndex(IndexOf(key_1_));
- ExpectIndex(IndexOf(cookie_a_));
+ ExpectIndex(DynamicIndexToWireIndex(key_1_index_));
+ ExpectIndex(DynamicIndexToWireIndex(cookie_a_index_));
CompareWithExpectedEncoding(headers);
}
// Header table is:
@@ -490,11 +510,12 @@ TEST_P(HpackEncoderTest, MultipleEncodingPasses) {
headers["cookie"] = "c=dd; e=ff";
// "key2: value2"
- ExpectIndex(64);
+ ExpectIndex(DynamicIndexToWireIndex(key_2_index_));
// "cookie: c=dd"
- ExpectIndex(62);
+ ExpectIndex(DynamicIndexToWireIndex(cookie_c_index_));
// This cookie evicts |key1| from the dynamic table.
ExpectIndexedLiteral(peer_.table()->GetByName("cookie"), "e=ff");
+ dynamic_table_insertions_++;
CompareWithExpectedEncoding(headers);
}
@@ -510,13 +531,16 @@ TEST_P(HpackEncoderTest, MultipleEncodingPasses) {
headers["cookie"] = "a=bb; b=cc; c=dd";
// "key2: value2"
- ExpectIndex(65);
+ EXPECT_EQ(65u, DynamicIndexToWireIndex(key_2_index_));
+ ExpectIndex(DynamicIndexToWireIndex(key_2_index_));
// "cookie: a=bb"
- ExpectIndex(64);
+ EXPECT_EQ(64u, DynamicIndexToWireIndex(cookie_a_index_));
+ ExpectIndex(DynamicIndexToWireIndex(cookie_a_index_));
// This cookie evicts |key2| from the dynamic table.
ExpectIndexedLiteral(peer_.table()->GetByName("cookie"), "b=cc");
+ dynamic_table_insertions_++;
// "cookie: c=dd"
- ExpectIndex(64);
+ ExpectIndex(DynamicIndexToWireIndex(cookie_c_index_));
CompareWithExpectedEncoding(headers);
}
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 e8db1d779da..b8350df4ff4 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
@@ -10,76 +10,19 @@
namespace spdy {
-const size_t HpackEntry::kSizeOverhead = 32;
-
-HpackEntry::HpackEntry(absl::string_view name,
- absl::string_view value,
- bool is_static,
- size_t insertion_index)
- : name_(name.data(), name.size()),
- value_(value.data(), value.size()),
- name_ref_(name_),
- value_ref_(value_),
- insertion_index_(insertion_index),
- type_(is_static ? STATIC : DYNAMIC),
- time_added_(0) {}
-
-HpackEntry::HpackEntry(absl::string_view name, absl::string_view value)
- : name_ref_(name),
- value_ref_(value),
- insertion_index_(0),
- type_(LOOKUP),
- time_added_(0) {}
-
-HpackEntry::HpackEntry() : insertion_index_(0), type_(LOOKUP), time_added_(0) {}
-
-HpackEntry::HpackEntry(const HpackEntry& other)
- : insertion_index_(other.insertion_index_),
- type_(other.type_),
- time_added_(0) {
- if (type_ == LOOKUP) {
- name_ref_ = other.name_ref_;
- value_ref_ = other.value_ref_;
- } else {
- name_ = other.name_;
- value_ = other.value_;
- name_ref_ = absl::string_view(name_.data(), name_.size());
- value_ref_ = absl::string_view(value_.data(), value_.size());
- }
-}
-
-HpackEntry& HpackEntry::operator=(const HpackEntry& other) {
- insertion_index_ = other.insertion_index_;
- type_ = other.type_;
- if (type_ == LOOKUP) {
- name_.clear();
- value_.clear();
- name_ref_ = other.name_ref_;
- value_ref_ = other.value_ref_;
- return *this;
- }
- name_ = other.name_;
- value_ = other.value_;
- name_ref_ = absl::string_view(name_.data(), name_.size());
- value_ref_ = absl::string_view(value_.data(), value_.size());
- return *this;
-}
-
-HpackEntry::~HpackEntry() = default;
+HpackEntry::HpackEntry(std::string name, std::string value)
+ : name_(std::move(name)), value_(std::move(value)) {}
// static
size_t HpackEntry::Size(absl::string_view name, absl::string_view value) {
- return name.size() + value.size() + kSizeOverhead;
+ return name.size() + value.size() + kHpackEntrySizeOverhead;
}
size_t HpackEntry::Size() const {
return Size(name(), value());
}
std::string HpackEntry::GetDebugString() const {
- return absl::StrCat(
- "{ name: \"", name_ref_, "\", value: \"", value_ref_,
- "\", index: ", insertion_index_, " ",
- (IsStatic() ? " static" : (IsLookup() ? " lookup" : " dynamic")), " }");
+ return absl::StrCat("{ name: \"", name_, "\", value: \"", value_, "\" }");
}
size_t HpackEntry::EstimateMemoryUsage() const {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.h b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.h
index 6141a421075..0c263584f66 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.h
@@ -8,6 +8,7 @@
#include <cstddef>
#include <cstdint>
#include <string>
+#include <utility>
#include "absl/strings/string_view.h"
#include "common/platform/api/quiche_export.h"
@@ -17,54 +18,52 @@
namespace spdy {
+// The constant amount added to name().size() and value().size() to
+// get the size of an HpackEntry as defined in 5.1.
+constexpr size_t kHpackEntrySizeOverhead = 32;
+
+// A structure for looking up entries in the static and dynamic tables.
+struct QUICHE_EXPORT_PRIVATE HpackLookupEntry {
+ absl::string_view name;
+ absl::string_view value;
+
+ bool operator==(const HpackLookupEntry& other) const {
+ return name == other.name && value == other.value;
+ }
+
+ // Abseil hashing framework extension according to absl/hash/hash.h:
+ template <typename H>
+ friend H AbslHashValue(H h, const HpackLookupEntry& entry) {
+ return H::combine(std::move(h), entry.name, entry.value);
+ }
+};
+
// A structure for an entry in the static table (3.3.1)
// and the header table (3.3.2).
class QUICHE_EXPORT_PRIVATE HpackEntry {
public:
- // The constant amount added to name().size() and value().size() to
- // get the size of an HpackEntry as defined in 5.1.
- static const size_t kSizeOverhead;
-
- // Creates an entry. Preconditions:
- // - |is_static| captures whether this entry is a member of the static
- // or dynamic header table.
- // - |insertion_index| is this entry's index in the total set of entries ever
- // inserted into the header table (including static entries).
- //
- // The combination of |is_static| and |insertion_index| allows an
- // HpackEntryTable to determine the index of an HpackEntry in O(1) time.
- // Copies |name| and |value|.
- HpackEntry(absl::string_view name,
- absl::string_view value,
- bool is_static,
- size_t insertion_index);
-
- // Create a 'lookup' entry (only) suitable for querying a HpackEntrySet. The
- // instance InsertionIndex() always returns 0 and IsLookup() returns true.
- // The memory backing |name| and |value| must outlive this object.
- HpackEntry(absl::string_view name, absl::string_view value);
-
- HpackEntry(const HpackEntry& other);
- HpackEntry& operator=(const HpackEntry& other);
-
- // Creates an entry with empty name and value. Only defined so that
- // entries can be stored in STL containers.
- HpackEntry();
-
- ~HpackEntry();
-
- absl::string_view name() const { return name_ref_; }
- absl::string_view value() const { return value_ref_; }
-
- // Returns whether this entry is a member of the static (as opposed to
- // dynamic) table.
- bool IsStatic() const { return type_ == STATIC; }
-
- // Returns whether this entry is a lookup-only entry.
- bool IsLookup() const { return type_ == LOOKUP; }
-
- // Used to compute the entry's index in the header table.
- size_t InsertionIndex() const { return insertion_index_; }
+ HpackEntry(std::string name, std::string value);
+
+ // Make HpackEntry non-copyable to make sure it is always moved.
+ HpackEntry(const HpackEntry&) = delete;
+ HpackEntry& operator=(const HpackEntry&) = delete;
+
+ HpackEntry(HpackEntry&&) = default;
+ HpackEntry& operator=(HpackEntry&&) = default;
+
+ // Getters for std::string members traditionally return const std::string&.
+ // However, HpackHeaderTable uses string_view as keys in the maps
+ // static_name_index_ and dynamic_name_index_. If HpackEntry::name() returned
+ // const std::string&, then
+ // dynamic_name_index_.insert(std::make_pair(entry.name(), index));
+ // would silently create a dangling reference: make_pair infers type from the
+ // return type of entry.name() and silently creates a temporary string copy.
+ // Insert creates a string_view that points to this copy, which then
+ // immediately goes out of scope and gets destroyed. While this is quite easy
+ // to avoid, for example, by explicitly specifying type as a template
+ // parameter to make_pair, returning string_view here is less error-prone.
+ absl::string_view name() const { return name_; }
+ absl::string_view value() const { return value_; }
// Returns the size of an entry as defined in 5.1.
static size_t Size(absl::string_view name, absl::string_view value);
@@ -72,36 +71,12 @@ class QUICHE_EXPORT_PRIVATE HpackEntry {
std::string GetDebugString() const;
- int64_t time_added() const { return time_added_; }
- void set_time_added(int64_t now) { time_added_ = now; }
-
// Returns the estimate of dynamically allocated memory in bytes.
size_t EstimateMemoryUsage() const;
private:
- enum EntryType {
- LOOKUP,
- DYNAMIC,
- STATIC,
- };
-
- // These members are not used for LOOKUP entries.
std::string name_;
std::string value_;
-
- // These members are always valid. For DYNAMIC and STATIC entries, they
- // always point to |name_| and |value_|.
- absl::string_view name_ref_;
- absl::string_view value_ref_;
-
- // The entry's index in the total set of entries ever inserted into the header
- // table.
- size_t insertion_index_;
-
- EntryType type_;
-
- // For HpackHeaderTable::DebugVisitorInterface
- int64_t time_added_;
};
} // namespace spdy
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry_test.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry_test.cc
index ced22a533b2..81acd9a4b30 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry_test.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry_test.cc
@@ -4,117 +4,48 @@
#include "spdy/core/hpack/hpack_entry.h"
+#include "absl/hash/hash.h"
#include "common/platform/api/quiche_test.h"
namespace spdy {
namespace {
-class HpackEntryTest : public QuicheTest {
- protected:
- HpackEntryTest()
- : name_("header-name"),
- value_("header value"),
- total_insertions_(0),
- table_size_(0) {}
+TEST(HpackLookupEntryTest, EntryNamesDiffer) {
+ HpackLookupEntry entry1{"header", "value"};
+ HpackLookupEntry entry2{"HEADER", "value"};
- // These builders maintain the same external table invariants that a "real"
- // table (ie HpackHeaderTable) would.
- HpackEntry StaticEntry() {
- return HpackEntry(name_, value_, true, total_insertions_++);
- }
- HpackEntry DynamicEntry() {
- ++table_size_;
- size_t index = total_insertions_++;
- return HpackEntry(name_, value_, false, index);
- }
- void DropEntry() { --table_size_; }
-
- size_t IndexOf(const HpackEntry& entry) const {
- if (entry.IsStatic()) {
- return 1 + entry.InsertionIndex() + table_size_;
- } else {
- return total_insertions_ - entry.InsertionIndex();
- }
- }
-
- size_t Size() {
- return name_.size() + value_.size() + HpackEntry::kSizeOverhead;
- }
-
- std::string name_, value_;
-
- private:
- // Referenced by HpackEntry instances.
- size_t total_insertions_;
- size_t table_size_;
-};
-
-TEST_F(HpackEntryTest, StaticConstructor) {
- HpackEntry entry(StaticEntry());
-
- EXPECT_EQ(name_, entry.name());
- EXPECT_EQ(value_, entry.value());
- EXPECT_TRUE(entry.IsStatic());
- EXPECT_EQ(1u, IndexOf(entry));
- EXPECT_EQ(Size(), entry.Size());
-}
-
-TEST_F(HpackEntryTest, DynamicConstructor) {
- HpackEntry entry(DynamicEntry());
-
- EXPECT_EQ(name_, entry.name());
- EXPECT_EQ(value_, entry.value());
- EXPECT_FALSE(entry.IsStatic());
- EXPECT_EQ(1u, IndexOf(entry));
- EXPECT_EQ(Size(), entry.Size());
+ EXPECT_FALSE(entry1 == entry2);
+ EXPECT_NE(absl::Hash<HpackLookupEntry>()(entry1),
+ absl::Hash<HpackLookupEntry>()(entry2));
}
-TEST_F(HpackEntryTest, LookupConstructor) {
- HpackEntry entry(name_, value_);
+TEST(HpackLookupEntryTest, EntryValuesDiffer) {
+ HpackLookupEntry entry1{"header", "value"};
+ HpackLookupEntry entry2{"header", "VALUE"};
- EXPECT_EQ(name_, entry.name());
- EXPECT_EQ(value_, entry.value());
- EXPECT_FALSE(entry.IsStatic());
- EXPECT_EQ(0u, IndexOf(entry));
- EXPECT_EQ(Size(), entry.Size());
+ EXPECT_FALSE(entry1 == entry2);
+ EXPECT_NE(absl::Hash<HpackLookupEntry>()(entry1),
+ absl::Hash<HpackLookupEntry>()(entry2));
}
-TEST_F(HpackEntryTest, DefaultConstructor) {
- HpackEntry entry;
+TEST(HpackLookupEntryTest, EntriesEqual) {
+ HpackLookupEntry entry1{"name", "value"};
+ HpackLookupEntry entry2{"name", "value"};
- EXPECT_TRUE(entry.name().empty());
- EXPECT_TRUE(entry.value().empty());
- EXPECT_EQ(HpackEntry::kSizeOverhead, entry.Size());
+ EXPECT_TRUE(entry1 == entry2);
+ EXPECT_EQ(absl::Hash<HpackLookupEntry>()(entry1),
+ absl::Hash<HpackLookupEntry>()(entry2));
}
-TEST_F(HpackEntryTest, IndexUpdate) {
- HpackEntry static1(StaticEntry());
- HpackEntry static2(StaticEntry());
-
- EXPECT_EQ(1u, IndexOf(static1));
- EXPECT_EQ(2u, IndexOf(static2));
-
- HpackEntry dynamic1(DynamicEntry());
- HpackEntry dynamic2(DynamicEntry());
-
- EXPECT_EQ(1u, IndexOf(dynamic2));
- EXPECT_EQ(2u, IndexOf(dynamic1));
- EXPECT_EQ(3u, IndexOf(static1));
- EXPECT_EQ(4u, IndexOf(static2));
-
- DropEntry(); // Drops |dynamic1|.
-
- EXPECT_EQ(1u, IndexOf(dynamic2));
- EXPECT_EQ(2u, IndexOf(static1));
- EXPECT_EQ(3u, IndexOf(static2));
+TEST(HpackEntryTest, BasicEntry) {
+ HpackEntry entry("header-name", "header value");
- HpackEntry dynamic3(DynamicEntry());
+ EXPECT_EQ("header-name", entry.name());
+ EXPECT_EQ("header value", entry.value());
- EXPECT_EQ(1u, IndexOf(dynamic3));
- EXPECT_EQ(2u, IndexOf(dynamic2));
- EXPECT_EQ(3u, IndexOf(static1));
- EXPECT_EQ(4u, IndexOf(static2));
+ EXPECT_EQ(55u, entry.Size());
+ EXPECT_EQ(55u, HpackEntry::Size("header-name", "header value"));
}
} // namespace
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 4dac492d034..ec69d47b6ae 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,31 +6,13 @@
#include <algorithm>
-#include "common/platform/api/quiche_string_piece.h"
#include "spdy/core/hpack/hpack_constants.h"
#include "spdy/core/hpack/hpack_static_table.h"
-#include "spdy/platform/api/spdy_containers.h"
#include "spdy/platform/api/spdy_estimate_memory_usage.h"
#include "spdy/platform/api/spdy_logging.h"
namespace spdy {
-size_t HpackHeaderTable::EntryHasher::operator()(
- const HpackEntry* entry) const {
- return quiche::QuicheHashStringPair(entry->name(), entry->value());
-}
-
-bool HpackHeaderTable::EntriesEq::operator()(const HpackEntry* lhs,
- const HpackEntry* rhs) const {
- if (lhs == nullptr) {
- return rhs == nullptr;
- }
- if (rhs == nullptr) {
- return false;
- }
- return lhs->name() == rhs->name() && lhs->value() == rhs->value();
-}
-
HpackHeaderTable::HpackHeaderTable()
: static_entries_(ObtainHpackStaticTable().GetStaticEntries()),
static_index_(ObtainHpackStaticTable().GetStaticIndex()),
@@ -38,79 +20,42 @@ HpackHeaderTable::HpackHeaderTable()
settings_size_bound_(kDefaultHeaderTableSizeSetting),
size_(0),
max_size_(kDefaultHeaderTableSizeSetting),
- total_insertions_(static_entries_.size()) {}
+ dynamic_table_insertions_(0) {}
HpackHeaderTable::~HpackHeaderTable() = default;
-const HpackEntry* HpackHeaderTable::GetByIndex(size_t index) {
- if (index == 0) {
- return nullptr;
- }
- index -= 1;
- if (index < static_entries_.size()) {
- return &static_entries_[index];
- }
- index -= static_entries_.size();
- if (index < dynamic_entries_.size()) {
- const HpackEntry* result = &dynamic_entries_[index];
- if (debug_visitor_ != nullptr) {
- debug_visitor_->OnUseEntry(*result);
- }
- return result;
- }
- return nullptr;
-}
-
-const HpackEntry* HpackHeaderTable::GetByName(absl::string_view name) {
+size_t HpackHeaderTable::GetByName(absl::string_view name) {
{
auto it = static_name_index_.find(name);
if (it != static_name_index_.end()) {
- return it->second;
+ return 1 + it->second;
}
}
{
NameToEntryMap::const_iterator it = dynamic_name_index_.find(name);
if (it != dynamic_name_index_.end()) {
- const HpackEntry* result = it->second;
- if (debug_visitor_ != nullptr) {
- debug_visitor_->OnUseEntry(*result);
- }
- return result;
+ return dynamic_table_insertions_ - it->second + kStaticTableSize;
}
}
- return nullptr;
+ return kHpackEntryNotFound;
}
-const HpackEntry* HpackHeaderTable::GetByNameAndValue(absl::string_view name,
- absl::string_view value) {
- HpackEntry query(name, value);
+size_t HpackHeaderTable::GetByNameAndValue(absl::string_view name,
+ absl::string_view value) {
+ HpackLookupEntry query{name, value};
{
- auto it = static_index_.find(&query);
+ auto it = static_index_.find(query);
if (it != static_index_.end()) {
- return *it;
+ return 1 + it->second;
}
}
{
- auto it = dynamic_index_.find(&query);
+ auto it = dynamic_index_.find(query);
if (it != dynamic_index_.end()) {
- const HpackEntry* result = *it;
- if (debug_visitor_ != nullptr) {
- debug_visitor_->OnUseEntry(*result);
- }
- return result;
+ return dynamic_table_insertions_ - it->second + kStaticTableSize;
}
}
- return nullptr;
-}
-
-size_t HpackHeaderTable::IndexOf(const HpackEntry* entry) const {
- if (entry->IsLookup()) {
- return 0;
- } else if (entry->IsStatic()) {
- return 1 + entry->InsertionIndex();
- } else {
- return total_insertions_ - entry->InsertionIndex() + static_entries_.size();
- }
+ return kHpackEntryNotFound;
}
void HpackHeaderTable::SetMaxSize(size_t max_size) {
@@ -130,8 +75,8 @@ void HpackHeaderTable::SetSettingsHeaderTableSize(size_t settings_size) {
void HpackHeaderTable::EvictionSet(absl::string_view name,
absl::string_view value,
- EntryTable::iterator* begin_out,
- EntryTable::iterator* end_out) {
+ DynamicEntryTable::iterator* begin_out,
+ DynamicEntryTable::iterator* end_out) {
size_t eviction_count = EvictionCountForEntry(name, value);
*begin_out = dynamic_entries_.end() - eviction_count;
*end_out = dynamic_entries_.end();
@@ -161,15 +106,17 @@ size_t HpackHeaderTable::EvictionCountToReclaim(size_t reclaim_size) const {
void HpackHeaderTable::Evict(size_t count) {
for (size_t i = 0; i != count; ++i) {
QUICHE_CHECK(!dynamic_entries_.empty());
+
HpackEntry* entry = &dynamic_entries_.back();
+ const size_t index = dynamic_table_insertions_ - dynamic_entries_.size();
size_ -= entry->Size();
- auto it = dynamic_index_.find(entry);
+ auto it = dynamic_index_.find({entry->name(), entry->value()});
QUICHE_DCHECK(it != dynamic_index_.end());
// Only remove an entry from the index if its insertion index matches;
// otherwise, the index refers to another entry with the same name and
// value.
- if ((*it)->InsertionIndex() == entry->InsertionIndex()) {
+ if (it->second == index) {
dynamic_index_.erase(it);
}
auto name_it = dynamic_name_index_.find(entry->name());
@@ -177,7 +124,7 @@ void HpackHeaderTable::Evict(size_t count) {
// Only remove an entry from the literal index if its insertion index
/// matches; otherwise, the index refers to another entry with the same
// name.
- if (name_it->second->InsertionIndex() == entry->InsertionIndex()) {
+ if (name_it->second == index) {
dynamic_name_index_.erase(name_it);
}
dynamic_entries_.pop_back();
@@ -186,6 +133,9 @@ void HpackHeaderTable::Evict(size_t count) {
const HpackEntry* HpackHeaderTable::TryAddEntry(absl::string_view name,
absl::string_view value) {
+ // Since |dynamic_entries_| has iterator stability, |name| and |value| are
+ // valid even after evicting other entries and push_front() making room for
+ // the new one.
Evict(EvictionCountForEntry(name, value));
size_t entry_size = HpackEntry::Size(name, value);
@@ -195,77 +145,47 @@ const HpackEntry* HpackHeaderTable::TryAddEntry(absl::string_view name,
QUICHE_DCHECK_EQ(0u, size_);
return nullptr;
}
- dynamic_entries_.push_front(HpackEntry(name, value,
- false, // is_static
- total_insertions_));
+
+ const size_t index = dynamic_table_insertions_;
+ dynamic_entries_.push_front(
+ HpackEntry(std::string(name), std::string(value)));
HpackEntry* new_entry = &dynamic_entries_.front();
- auto index_result = dynamic_index_.insert(new_entry);
+ auto index_result = dynamic_index_.insert(std::make_pair(
+ HpackLookupEntry{new_entry->name(), new_entry->value()}, index));
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: "
- << (*index_result.first)->GetDebugString()
- << " replacing with: " << new_entry->GetDebugString();
- QUICHE_DCHECK_GT(new_entry->InsertionIndex(),
- (*index_result.first)->InsertionIndex());
+ SPDY_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);
- QUICHE_CHECK(dynamic_index_.insert(new_entry).second);
+ auto insert_result = dynamic_index_.insert(std::make_pair(
+ HpackLookupEntry{new_entry->name(), new_entry->value()}, index));
+ QUICHE_CHECK(insert_result.second);
}
auto name_result =
- dynamic_name_index_.insert(std::make_pair(new_entry->name(), new_entry));
+ dynamic_name_index_.insert(std::make_pair(new_entry->name(), index));
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: "
- << name_result.first->second->GetDebugString()
- << " replacing with: " << new_entry->GetDebugString();
- QUICHE_DCHECK_GT(new_entry->InsertionIndex(),
- name_result.first->second->InsertionIndex());
+ SPDY_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 = dynamic_name_index_.insert(
- std::make_pair(new_entry->name(), new_entry));
+ auto insert_result =
+ dynamic_name_index_.insert(std::make_pair(new_entry->name(), index));
QUICHE_CHECK(insert_result.second);
}
size_ += entry_size;
- ++total_insertions_;
- if (debug_visitor_ != nullptr) {
- // Call |debug_visitor_->OnNewEntry()| to get the current time.
- HpackEntry& entry = dynamic_entries_.front();
- entry.set_time_added(debug_visitor_->OnNewEntry(entry));
- SPDY_DVLOG(2) << "HpackHeaderTable::OnNewEntry: name=" << entry.name()
- << ", value=" << entry.value()
- << ", insert_index=" << entry.InsertionIndex()
- << ", time_added=" << entry.time_added();
- }
+ ++dynamic_table_insertions_;
return &dynamic_entries_.front();
}
-void HpackHeaderTable::DebugLogTableState() const {
- SPDY_DVLOG(2) << "Dynamic table:";
- for (auto it = dynamic_entries_.begin(); it != dynamic_entries_.end(); ++it) {
- SPDY_DVLOG(2) << " " << it->GetDebugString();
- }
- SPDY_DVLOG(2) << "Full Static Index:";
- for (const auto* entry : static_index_) {
- SPDY_DVLOG(2) << " " << entry->GetDebugString();
- }
- SPDY_DVLOG(2) << "Full Static Name Index:";
- for (const auto& it : static_name_index_) {
- SPDY_DVLOG(2) << " " << it.first << ": " << it.second->GetDebugString();
- }
- SPDY_DVLOG(2) << "Full Dynamic Index:";
- for (const auto* entry : dynamic_index_) {
- SPDY_DVLOG(2) << " " << entry->GetDebugString();
- }
- SPDY_DVLOG(2) << "Full Dynamic Name Index:";
- for (const auto& it : dynamic_name_index_) {
- SPDY_DVLOG(2) << " " << it.first << ": " << it.second->GetDebugString();
- }
-}
-
size_t HpackHeaderTable::EstimateMemoryUsage() const {
return SpdyEstimateMemoryUsage(dynamic_entries_) +
SpdyEstimateMemoryUsage(dynamic_index_) +
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 02a438c57c8..893aaa7bb21 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
@@ -11,11 +11,12 @@
#include <memory>
#include "absl/base/attributes.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
#include "absl/hash/hash.h"
#include "absl/strings/string_view.h"
#include "common/platform/api/quiche_export.h"
#include "spdy/core/hpack/hpack_entry.h"
-#include "spdy/platform/api/spdy_containers.h"
// All section references below are to http://tools.ietf.org/html/rfc7541.
@@ -25,32 +26,19 @@ namespace test {
class HpackHeaderTablePeer;
} // namespace test
+// Return value of GetByName() and GetByNameAndValue() if matching entry is not
+// found. This value is never used in HPACK for indexing entries, see
+// https://httpwg.org/specs/rfc7541.html#index.address.space.
+constexpr size_t kHpackEntryNotFound = 0;
+
// A data structure for the static table (2.3.1) and the dynamic table (2.3.2).
class QUICHE_EXPORT_PRIVATE HpackHeaderTable {
public:
friend class test::HpackHeaderTablePeer;
- // Debug visitor my be used to extract debug/internal information
- // about the HpackHeaderTable as it operates.
- //
- // Most HpackHeaderTable implementations do not need to bother with
- // this interface at all.
- class DebugVisitorInterface {
- public:
- virtual ~DebugVisitorInterface() {}
-
- // |OnNewEntry()| and |OnUseEntry()| can be used together to
- // gather data about the distribution of time intervals between
- // creation and reference of entries in the dynamic table. The
- // data is desired to sanity check a proposed extension to HPACK
- // for QUIC that would eliminate inter-stream head of line
- // blocking (due to standard HPACK). The visitor should return
- // the current time from |OnNewEntry()|, which will be passed
- // to |OnUseEntry()| each time that particular entry is used to
- // emit an indexed representation.
- virtual int64_t OnNewEntry(const HpackEntry& entry) = 0;
- virtual void OnUseEntry(const HpackEntry& entry) = 0;
- };
+ // Use a lightweight, memory efficient container for the static table, which
+ // is initialized once and never changed after.
+ using StaticEntryTable = std::vector<HpackEntry>;
// HpackHeaderTable takes advantage of the deque property that references
// remain valid, so long as insertions & deletions are at the head & tail.
@@ -59,18 +47,12 @@ class QUICHE_EXPORT_PRIVATE HpackHeaderTable {
// 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.
- using EntryTable = std::deque<HpackEntry>;
-
- struct QUICHE_EXPORT_PRIVATE EntryHasher {
- size_t operator()(const HpackEntry* entry) const;
- };
- struct QUICHE_EXPORT_PRIVATE EntriesEq {
- bool operator()(const HpackEntry* lhs, const HpackEntry* rhs) const;
- };
- using UnorderedEntrySet = SpdyHashSet<HpackEntry*, EntryHasher, EntriesEq>;
- using NameToEntryMap = SpdyHashMap<absl::string_view,
- const HpackEntry*,
- absl::Hash<absl::string_view>>;
+ //
+ // TODO(b/182349990): Change to a more memory efficient container.
+ using DynamicEntryTable = std::deque<HpackEntry>;
+
+ using NameValueToEntryMap = absl::flat_hash_map<HpackLookupEntry, size_t>;
+ using NameToEntryMap = absl::flat_hash_map<absl::string_view, size_t>;
HpackHeaderTable();
HpackHeaderTable(const HpackHeaderTable&) = delete;
@@ -86,18 +68,16 @@ class QUICHE_EXPORT_PRIVATE HpackHeaderTable {
size_t size() const { return size_; }
size_t max_size() const { return max_size_; }
- // Returns the entry matching the index, or NULL.
- const HpackEntry* GetByIndex(size_t index);
+ // The HPACK indexing scheme used by GetByName() and GetByNameAndValue() is
+ // defined at https://httpwg.org/specs/rfc7541.html#index.address.space.
- // Returns the lowest-value entry having |name|, or NULL.
- const HpackEntry* GetByName(absl::string_view name);
+ // Returns the index of the lowest-index entry matching |name|,
+ // or kHpackEntryNotFound if no matching entry is found.
+ size_t GetByName(absl::string_view name);
- // Returns the lowest-index matching entry, or NULL.
- const HpackEntry* GetByNameAndValue(absl::string_view name,
- absl::string_view value);
-
- // Returns the index of an entry within this header table.
- size_t IndexOf(const HpackEntry* entry) const;
+ // Returns the index of the lowest-index entry matching |name| and |value|,
+ // or kHpackEntryNotFound if no matching entry is found.
+ size_t GetByNameAndValue(absl::string_view name, absl::string_view value);
// Sets the maximum size of the header table, evicting entries if
// necessary as described in 5.2.
@@ -112,22 +92,17 @@ class QUICHE_EXPORT_PRIVATE HpackHeaderTable {
// actually occurs. The set is returned via range [begin_out, end_out).
void EvictionSet(absl::string_view name,
absl::string_view value,
- EntryTable::iterator* begin_out,
- EntryTable::iterator* end_out);
+ DynamicEntryTable::iterator* begin_out,
+ DynamicEntryTable::iterator* end_out);
// Adds an entry for the representation, evicting entries as needed. |name|
- // and |value| must not be owned by an entry which could be evicted. The
- // added HpackEntry is returned, or NULL is returned if all entries were
+ // and |value| must not point to an entry in |dynamic_entries_| which is about
+ // to be evicted, but they may point to an entry which is not.
+ // The added HpackEntry is returned, or NULL is returned if all entries were
// evicted and the empty table is of insufficent size for the representation.
const HpackEntry* TryAddEntry(absl::string_view name,
absl::string_view value);
- void DebugLogTableState() const ABSL_ATTRIBUTE_UNUSED;
-
- void set_debug_visitor(std::unique_ptr<DebugVisitorInterface> visitor) {
- debug_visitor_ = std::move(visitor);
- }
-
// Returns the estimate of dynamically allocated memory in bytes.
size_t EstimateMemoryUsage() const;
@@ -145,21 +120,28 @@ class QUICHE_EXPORT_PRIVATE HpackHeaderTable {
// |static_entries_|, |static_index_|, and |static_name_index_| are owned by
// HpackStaticTable singleton.
- // Tracks HpackEntries by index.
- const EntryTable& static_entries_;
- EntryTable dynamic_entries_;
+ // Stores HpackEntries.
+ const StaticEntryTable& static_entries_;
+ DynamicEntryTable dynamic_entries_;
- // Tracks the unique HpackEntry for a given header name and value.
- const UnorderedEntrySet& static_index_;
+ // Tracks the index of the unique HpackEntry for a given header name and
+ // value. Keys consist of string_views that point to strings stored in
+ // |static_entries_|.
+ const NameValueToEntryMap& static_index_;
- // Tracks the first static entry for each name in the static table.
+ // Tracks the index of the first static entry for each name in the static
+ // table. Each key is a string_view that points to a name string stored in
+ // |static_entries_|.
const NameToEntryMap& static_name_index_;
- // Tracks the most recently inserted HpackEntry for a given header name and
- // value.
- UnorderedEntrySet dynamic_index_;
+ // Tracks the index of the most recently inserted HpackEntry for a given
+ // header name and value. Keys consist of string_views that point to strings
+ // stored in |dynamic_entries_|.
+ NameValueToEntryMap dynamic_index_;
- // Tracks the most recently inserted HpackEntry for a given header name.
+ // Tracks the index of the most recently inserted HpackEntry for a given
+ // header name. Each key is a string_view that points to a name string stored
+ // in |dynamic_entries_|.
NameToEntryMap dynamic_name_index_;
// Last acknowledged value for SETTINGS_HEADER_TABLE_SIZE.
@@ -170,11 +152,9 @@ class QUICHE_EXPORT_PRIVATE HpackHeaderTable {
size_t size_;
size_t max_size_;
- // Total number of table insertions which have occurred. Referenced by
- // IndexOf() for determination of an HpackEntry's table index.
- size_t total_insertions_;
-
- std::unique_ptr<DebugVisitorInterface> debug_visitor_;
+ // Total number of dynamic table insertions so far
+ // (including entries that have been evicted).
+ size_t dynamic_table_insertions_;
};
} // namespace spdy
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table_test.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table_test.cc
index 2fd7c12696e..23b551648d2 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table_test.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table_test.cc
@@ -13,6 +13,7 @@
#include "common/platform/api/quiche_test.h"
#include "spdy/core/hpack/hpack_constants.h"
#include "spdy/core/hpack/hpack_entry.h"
+#include "spdy/core/hpack/hpack_static_table.h"
namespace spdy {
@@ -24,18 +25,21 @@ class HpackHeaderTablePeer {
public:
explicit HpackHeaderTablePeer(HpackHeaderTable* table) : table_(table) {}
- const HpackHeaderTable::EntryTable& dynamic_entries() {
+ const HpackHeaderTable::DynamicEntryTable& dynamic_entries() {
return table_->dynamic_entries_;
}
- const HpackHeaderTable::EntryTable& static_entries() {
+ const HpackHeaderTable::StaticEntryTable& static_entries() {
return table_->static_entries_;
}
- size_t index_size() {
- return table_->static_index_.size() + table_->dynamic_index_.size();
+ const HpackEntry* GetFirstStaticEntry() {
+ return &table_->static_entries_.front();
+ }
+ const HpackEntry* GetLastStaticEntry() {
+ return &table_->static_entries_.back();
}
std::vector<HpackEntry*> EvictionSet(absl::string_view name,
absl::string_view value) {
- HpackHeaderTable::EntryTable::iterator begin, end;
+ HpackHeaderTable::DynamicEntryTable::iterator begin, end;
table_->EvictionSet(name, value, &begin, &end);
std::vector<HpackEntry*> result;
for (; begin != end; ++begin) {
@@ -43,8 +47,9 @@ class HpackHeaderTablePeer {
}
return result;
}
- size_t total_insertions() { return table_->total_insertions_; }
- size_t dynamic_entries_count() { return table_->dynamic_entries_.size(); }
+ size_t dynamic_table_insertions() {
+ return table_->dynamic_table_insertions_;
+ }
size_t EvictionCountForEntry(absl::string_view name,
absl::string_view value) {
return table_->EvictionCountForEntry(name, value);
@@ -54,11 +59,6 @@ class HpackHeaderTablePeer {
}
void Evict(size_t count) { return table_->Evict(count); }
- void AddDynamicEntry(absl::string_view name, absl::string_view value) {
- table_->dynamic_entries_.push_back(
- HpackEntry(name, value, false, table_->total_insertions_++));
- }
-
private:
HpackHeaderTable* table_;
};
@@ -75,10 +75,10 @@ class HpackHeaderTableTest : public QuicheTest {
// Returns an entry whose Size() is equal to the given one.
static HpackEntry MakeEntryOfSize(uint32_t size) {
- EXPECT_GE(size, HpackEntry::kSizeOverhead);
- std::string name((size - HpackEntry::kSizeOverhead) / 2, 'n');
- std::string value(size - HpackEntry::kSizeOverhead - name.size(), 'v');
- HpackEntry entry(name, value, false, 0);
+ EXPECT_GE(size, kHpackEntrySizeOverhead);
+ std::string name((size - kHpackEntrySizeOverhead) / 2, 'n');
+ std::string value(size - kHpackEntrySizeOverhead - name.size(), 'v');
+ HpackEntry entry(name, value);
EXPECT_EQ(size, entry.Size());
return entry;
}
@@ -86,8 +86,8 @@ class HpackHeaderTableTest : public QuicheTest {
// Returns a vector of entries whose total size is equal to the given
// one.
static HpackEntryVector MakeEntriesOfTotalSize(uint32_t total_size) {
- EXPECT_GE(total_size, HpackEntry::kSizeOverhead);
- uint32_t entry_size = HpackEntry::kSizeOverhead;
+ EXPECT_GE(total_size, kHpackEntrySizeOverhead);
+ uint32_t entry_size = kHpackEntrySizeOverhead;
uint32_t remaining_size = total_size;
HpackEntryVector entries;
while (remaining_size > 0) {
@@ -103,7 +103,7 @@ class HpackHeaderTableTest : public QuicheTest {
// expecting no eviction to happen.
void AddEntriesExpectNoEviction(const HpackEntryVector& entries) {
for (auto it = entries.begin(); it != entries.end(); ++it) {
- HpackHeaderTable::EntryTable::iterator begin, end;
+ HpackHeaderTable::DynamicEntryTable::iterator begin, end;
table_.EvictionSet(it->name(), it->value(), &begin, &end);
EXPECT_EQ(0, distance(begin, end));
@@ -111,20 +111,6 @@ class HpackHeaderTableTest : public QuicheTest {
const HpackEntry* entry = table_.TryAddEntry(it->name(), it->value());
EXPECT_NE(entry, static_cast<HpackEntry*>(nullptr));
}
-
- for (size_t i = 0; i != entries.size(); ++i) {
- // Static table has 61 entries, dynamic entries follow those.
- size_t index = 61 + entries.size() - i;
- const HpackEntry* entry = table_.GetByIndex(index);
- EXPECT_EQ(entries[i].name(), entry->name());
- EXPECT_EQ(entries[i].value(), entry->value());
- EXPECT_EQ(index, table_.IndexOf(entry));
- }
- }
-
- HpackEntry DynamicEntry(const std::string& name, const std::string& value) {
- peer_.AddDynamicEntry(name, value);
- return peer_.dynamic_entries().back();
}
HpackHeaderTable table_;
@@ -136,124 +122,126 @@ TEST_F(HpackHeaderTableTest, StaticTableInitialization) {
EXPECT_EQ(kDefaultHeaderTableSizeSetting, table_.max_size());
EXPECT_EQ(kDefaultHeaderTableSizeSetting, table_.settings_size_bound());
- EXPECT_EQ(0u, peer_.dynamic_entries_count());
- EXPECT_EQ(peer_.static_entries().size(), peer_.total_insertions());
+ EXPECT_EQ(0u, peer_.dynamic_entries().size());
+ EXPECT_EQ(0u, peer_.dynamic_table_insertions());
// Static entries have been populated and inserted into the table & index.
- EXPECT_NE(0u, peer_.static_entries().size());
- EXPECT_EQ(peer_.index_size(), peer_.static_entries().size());
- for (size_t i = 0; i != peer_.static_entries().size(); ++i) {
- const HpackEntry* entry = &peer_.static_entries()[i];
-
- EXPECT_TRUE(entry->IsStatic());
- EXPECT_EQ(entry, table_.GetByIndex(i + 1));
- EXPECT_EQ(entry, table_.GetByNameAndValue(entry->name(), entry->value()));
+ const HpackHeaderTable::StaticEntryTable& static_entries =
+ peer_.static_entries();
+ EXPECT_EQ(kStaticTableSize, static_entries.size());
+ // HPACK indexing scheme is 1-based.
+ size_t index = 1;
+ for (const HpackEntry& entry : static_entries) {
+ EXPECT_EQ(index, table_.GetByNameAndValue(entry.name(), entry.value()));
+ index++;
}
}
TEST_F(HpackHeaderTableTest, BasicDynamicEntryInsertionAndEviction) {
- size_t static_count = peer_.total_insertions();
- const HpackEntry* first_static_entry = table_.GetByIndex(1);
+ EXPECT_EQ(kStaticTableSize, peer_.static_entries().size());
- EXPECT_EQ(1u, table_.IndexOf(first_static_entry));
+ const HpackEntry* first_static_entry = peer_.GetFirstStaticEntry();
+ const HpackEntry* last_static_entry = peer_.GetLastStaticEntry();
const HpackEntry* entry = table_.TryAddEntry("header-key", "Header Value");
EXPECT_EQ("header-key", entry->name());
EXPECT_EQ("Header Value", entry->value());
- EXPECT_FALSE(entry->IsStatic());
// Table counts were updated appropriately.
EXPECT_EQ(entry->Size(), table_.size());
- EXPECT_EQ(1u, peer_.dynamic_entries_count());
- EXPECT_EQ(peer_.dynamic_entries().size(), peer_.dynamic_entries_count());
- EXPECT_EQ(static_count + 1, peer_.total_insertions());
- EXPECT_EQ(static_count + 1, peer_.index_size());
-
- // Index() of entries reflects the insertion.
- EXPECT_EQ(1u, table_.IndexOf(first_static_entry));
- // Static table has 61 entries.
- EXPECT_EQ(62u, table_.IndexOf(entry));
- EXPECT_EQ(first_static_entry, table_.GetByIndex(1));
- EXPECT_EQ(entry, table_.GetByIndex(62));
+ EXPECT_EQ(1u, peer_.dynamic_entries().size());
+ EXPECT_EQ(kStaticTableSize, peer_.static_entries().size());
+
+ EXPECT_EQ(62u, table_.GetByNameAndValue("header-key", "Header Value"));
+
+ // Index of static entries does not change.
+ EXPECT_EQ(first_static_entry, peer_.GetFirstStaticEntry());
+ EXPECT_EQ(last_static_entry, peer_.GetLastStaticEntry());
// Evict |entry|. Table counts are again updated appropriately.
peer_.Evict(1);
EXPECT_EQ(0u, table_.size());
- EXPECT_EQ(0u, peer_.dynamic_entries_count());
- EXPECT_EQ(peer_.dynamic_entries().size(), peer_.dynamic_entries_count());
- EXPECT_EQ(static_count + 1, peer_.total_insertions());
- EXPECT_EQ(static_count, peer_.index_size());
-
- // Index() of |first_static_entry| reflects the eviction.
- EXPECT_EQ(1u, table_.IndexOf(first_static_entry));
- EXPECT_EQ(first_static_entry, table_.GetByIndex(1));
+ EXPECT_EQ(0u, peer_.dynamic_entries().size());
+ EXPECT_EQ(kStaticTableSize, peer_.static_entries().size());
+
+ // Index of static entries does not change.
+ EXPECT_EQ(first_static_entry, peer_.GetFirstStaticEntry());
+ EXPECT_EQ(last_static_entry, peer_.GetLastStaticEntry());
}
TEST_F(HpackHeaderTableTest, EntryIndexing) {
- const HpackEntry* first_static_entry = table_.GetByIndex(1);
+ const HpackEntry* first_static_entry = peer_.GetFirstStaticEntry();
+ const HpackEntry* last_static_entry = peer_.GetLastStaticEntry();
// Static entries are queryable by name & value.
- EXPECT_EQ(first_static_entry, table_.GetByName(first_static_entry->name()));
- EXPECT_EQ(first_static_entry,
- table_.GetByNameAndValue(first_static_entry->name(),
- first_static_entry->value()));
+ EXPECT_EQ(1u, table_.GetByName(first_static_entry->name()));
+ EXPECT_EQ(1u, table_.GetByNameAndValue(first_static_entry->name(),
+ first_static_entry->value()));
// Create a mix of entries which duplicate names, and names & values of both
// dynamic and static entries.
- const HpackEntry* entry1 = table_.TryAddEntry(first_static_entry->name(),
- first_static_entry->value());
- const HpackEntry* entry2 =
- table_.TryAddEntry(first_static_entry->name(), "Value Four");
- const HpackEntry* entry3 = table_.TryAddEntry("key-1", "Value One");
- const HpackEntry* entry4 = table_.TryAddEntry("key-2", "Value Three");
- const HpackEntry* entry5 = table_.TryAddEntry("key-1", "Value Two");
- const HpackEntry* entry6 = table_.TryAddEntry("key-2", "Value Three");
- const HpackEntry* entry7 = table_.TryAddEntry("key-2", "Value Four");
-
- // Entries are queryable under their current index.
- EXPECT_EQ(entry7, table_.GetByIndex(62));
- EXPECT_EQ(entry6, table_.GetByIndex(63));
- EXPECT_EQ(entry5, table_.GetByIndex(64));
- EXPECT_EQ(entry4, table_.GetByIndex(65));
- EXPECT_EQ(entry3, table_.GetByIndex(66));
- EXPECT_EQ(entry2, table_.GetByIndex(67));
- EXPECT_EQ(entry1, table_.GetByIndex(68));
- EXPECT_EQ(first_static_entry, table_.GetByIndex(1));
+ table_.TryAddEntry(first_static_entry->name(), first_static_entry->value());
+ table_.TryAddEntry(first_static_entry->name(), "Value Four");
+ table_.TryAddEntry("key-1", "Value One");
+ table_.TryAddEntry("key-2", "Value Three");
+ table_.TryAddEntry("key-1", "Value Two");
+ table_.TryAddEntry("key-2", "Value Three");
+ table_.TryAddEntry("key-2", "Value Four");
+
+ // The following entry is identical to the one at index 68. The smaller index
+ // is returned by GetByNameAndValue().
+ EXPECT_EQ(1u, table_.GetByNameAndValue(first_static_entry->name(),
+ first_static_entry->value()));
+ EXPECT_EQ(67u,
+ table_.GetByNameAndValue(first_static_entry->name(), "Value Four"));
+ EXPECT_EQ(66u, table_.GetByNameAndValue("key-1", "Value One"));
+ EXPECT_EQ(64u, table_.GetByNameAndValue("key-1", "Value Two"));
+ // The following entry is identical to the one at index 65. The smaller index
+ // is returned by GetByNameAndValue().
+ EXPECT_EQ(63u, table_.GetByNameAndValue("key-2", "Value Three"));
+ EXPECT_EQ(62u, table_.GetByNameAndValue("key-2", "Value Four"));
+
+ // Index of static entries does not change.
+ EXPECT_EQ(first_static_entry, peer_.GetFirstStaticEntry());
+ EXPECT_EQ(last_static_entry, peer_.GetLastStaticEntry());
// Querying by name returns the most recently added matching entry.
- EXPECT_EQ(entry5, table_.GetByName("key-1"));
- EXPECT_EQ(entry7, table_.GetByName("key-2"));
- EXPECT_EQ(entry2->name(),
- table_.GetByName(first_static_entry->name())->name());
- EXPECT_EQ(nullptr, table_.GetByName("not-present"));
+ EXPECT_EQ(64u, table_.GetByName("key-1"));
+ EXPECT_EQ(62u, table_.GetByName("key-2"));
+ EXPECT_EQ(1u, table_.GetByName(first_static_entry->name()));
+ EXPECT_EQ(kHpackEntryNotFound, table_.GetByName("not-present"));
// Querying by name & value returns the lowest-index matching entry among
// static entries, and the highest-index one among dynamic entries.
- EXPECT_EQ(entry3, table_.GetByNameAndValue("key-1", "Value One"));
- EXPECT_EQ(entry5, table_.GetByNameAndValue("key-1", "Value Two"));
- EXPECT_EQ(entry6, table_.GetByNameAndValue("key-2", "Value Three"));
- EXPECT_EQ(entry7, table_.GetByNameAndValue("key-2", "Value Four"));
- EXPECT_EQ(first_static_entry,
- table_.GetByNameAndValue(first_static_entry->name(),
- first_static_entry->value()));
- EXPECT_EQ(entry2,
+ EXPECT_EQ(66u, table_.GetByNameAndValue("key-1", "Value One"));
+ EXPECT_EQ(64u, table_.GetByNameAndValue("key-1", "Value Two"));
+ EXPECT_EQ(63u, table_.GetByNameAndValue("key-2", "Value Three"));
+ EXPECT_EQ(62u, table_.GetByNameAndValue("key-2", "Value Four"));
+ EXPECT_EQ(1u, table_.GetByNameAndValue(first_static_entry->name(),
+ first_static_entry->value()));
+ EXPECT_EQ(67u,
table_.GetByNameAndValue(first_static_entry->name(), "Value Four"));
- EXPECT_EQ(nullptr, table_.GetByNameAndValue("key-1", "Not Present"));
- EXPECT_EQ(nullptr, table_.GetByNameAndValue("not-present", "Value One"));
+ EXPECT_EQ(kHpackEntryNotFound,
+ table_.GetByNameAndValue("key-1", "Not Present"));
+ EXPECT_EQ(kHpackEntryNotFound,
+ table_.GetByNameAndValue("not-present", "Value One"));
// Evict |entry1|. Queries for its name & value now return the static entry.
// |entry2| remains queryable.
peer_.Evict(1);
- EXPECT_EQ(first_static_entry,
- table_.GetByNameAndValue(first_static_entry->name(),
- first_static_entry->value()));
- EXPECT_EQ(entry2,
+ EXPECT_EQ(1u, table_.GetByNameAndValue(first_static_entry->name(),
+ first_static_entry->value()));
+ EXPECT_EQ(67u,
table_.GetByNameAndValue(first_static_entry->name(), "Value Four"));
// Evict |entry2|. Queries by its name & value are not found.
peer_.Evict(1);
- EXPECT_EQ(nullptr,
+ EXPECT_EQ(kHpackEntryNotFound,
table_.GetByNameAndValue(first_static_entry->name(), "Value Four"));
+
+ // Index of static entries does not change.
+ EXPECT_EQ(first_static_entry, peer_.GetFirstStaticEntry());
+ EXPECT_EQ(last_static_entry, peer_.GetLastStaticEntry());
}
TEST_F(HpackHeaderTableTest, SetSizes) {
@@ -363,7 +351,9 @@ TEST_F(HpackHeaderTableTest, TryAddEntryEviction) {
HpackEntryVector entries = MakeEntriesOfTotalSize(table_.max_size());
AddEntriesExpectNoEviction(entries);
- const HpackEntry* survivor_entry = table_.GetByIndex(61 + 1);
+ // The first entry in the dynamic table.
+ const HpackEntry* survivor_entry = &peer_.dynamic_entries().front();
+
HpackEntry long_entry =
MakeEntryOfSize(table_.max_size() - survivor_entry->Size());
@@ -371,12 +361,12 @@ TEST_F(HpackHeaderTableTest, TryAddEntryEviction) {
EXPECT_EQ(peer_.dynamic_entries().size() - 1,
peer_.EvictionSet(long_entry.name(), long_entry.value()).size());
- const HpackEntry* new_entry =
- table_.TryAddEntry(long_entry.name(), long_entry.value());
- EXPECT_EQ(62u, table_.IndexOf(new_entry));
+ table_.TryAddEntry(long_entry.name(), long_entry.value());
EXPECT_EQ(2u, peer_.dynamic_entries().size());
- EXPECT_EQ(table_.GetByIndex(63), survivor_entry);
- EXPECT_EQ(table_.GetByIndex(62), new_entry);
+ EXPECT_EQ(63u, table_.GetByNameAndValue(survivor_entry->name(),
+ survivor_entry->value()));
+ EXPECT_EQ(62u,
+ table_.GetByNameAndValue(long_entry.name(), long_entry.value()));
}
// Fill a header table with entries, and then add an entry bigger than
@@ -397,50 +387,6 @@ TEST_F(HpackHeaderTableTest, TryAddTooLargeEntry) {
EXPECT_EQ(0u, peer_.dynamic_entries().size());
}
-TEST_F(HpackHeaderTableTest, EntryNamesDiffer) {
- HpackEntry entry1("header", "value");
- HpackEntry entry2("HEADER", "value");
-
- HpackHeaderTable::EntryHasher hasher;
- EXPECT_NE(hasher(&entry1), hasher(&entry2));
-
- HpackHeaderTable::EntriesEq eq;
- EXPECT_FALSE(eq(&entry1, &entry2));
-}
-
-TEST_F(HpackHeaderTableTest, EntryValuesDiffer) {
- HpackEntry entry1("header", "value");
- HpackEntry entry2("header", "VALUE");
-
- HpackHeaderTable::EntryHasher hasher;
- EXPECT_NE(hasher(&entry1), hasher(&entry2));
-
- HpackHeaderTable::EntriesEq eq;
- EXPECT_FALSE(eq(&entry1, &entry2));
-}
-
-TEST_F(HpackHeaderTableTest, EntriesEqual) {
- HpackEntry entry1(DynamicEntry("name", "value"));
- HpackEntry entry2(DynamicEntry("name", "value"));
-
- HpackHeaderTable::EntryHasher hasher;
- EXPECT_EQ(hasher(&entry1), hasher(&entry2));
-
- HpackHeaderTable::EntriesEq eq;
- EXPECT_TRUE(eq(&entry1, &entry2));
-}
-
-TEST_F(HpackHeaderTableTest, StaticAndDynamicEntriesEqual) {
- HpackEntry entry1("name", "value");
- HpackEntry entry2(DynamicEntry("name", "value"));
-
- HpackHeaderTable::EntryHasher hasher;
- EXPECT_EQ(hasher(&entry1), hasher(&entry2));
-
- HpackHeaderTable::EntriesEq eq;
- EXPECT_TRUE(eq(&entry1, &entry2));
-}
-
} // namespace
} // 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 809bc82890b..8c8248c2343 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
@@ -20,20 +20,27 @@ void HpackStaticTable::Initialize(const HpackStaticEntry* static_entry_table,
size_t static_entry_count) {
QUICHE_CHECK(!IsInitialized());
- int total_insertions = 0;
+ static_entries_.reserve(static_entry_count);
+
for (const HpackStaticEntry* it = static_entry_table;
it != static_entry_table + static_entry_count; ++it) {
- static_entries_.push_back(
- HpackEntry(absl::string_view(it->name, it->name_len),
- absl::string_view(it->value, it->value_len),
- true, // is_static
- total_insertions));
- HpackEntry* entry = &static_entries_.back();
- QUICHE_CHECK(static_index_.insert(entry).second);
+ std::string name(it->name, it->name_len);
+ std::string value(it->value, it->value_len);
+ static_entries_.push_back(HpackEntry(std::move(name), std::move(value)));
+ }
+
+ // |static_entries_| will not be mutated any more. Therefore its entries will
+ // remain stable even if the container does not have iterator stability.
+ int insertion_count = 0;
+ for (const auto& entry : static_entries_) {
+ auto result = static_index_.insert(std::make_pair(
+ HpackLookupEntry{entry.name(), entry.value()}, insertion_count));
+ QUICHE_CHECK(result.second);
+
// Multiple static entries may have the same name, so inserts may fail.
- static_name_index_.insert(std::make_pair(entry->name(), entry));
+ static_name_index_.insert(std::make_pair(entry.name(), insertion_count));
- ++total_insertions;
+ ++insertion_count;
}
}
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.h b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.h
index 436ae593c0b..346332e4134 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.h
@@ -12,6 +12,9 @@ namespace spdy {
struct HpackStaticEntry;
+// Number of entries in the HPACK static table.
+constexpr size_t kStaticTableSize = 61;
+
// HpackStaticTable provides |static_entries_| and |static_index_| for HPACK
// encoding and decoding contexts. Once initialized, an instance is read only
// and may be accessed only through its const interface. Such an instance may
@@ -30,10 +33,10 @@ class QUICHE_EXPORT_PRIVATE HpackStaticTable {
bool IsInitialized() const;
// Accessors.
- const HpackHeaderTable::EntryTable& GetStaticEntries() const {
+ const HpackHeaderTable::StaticEntryTable& GetStaticEntries() const {
return static_entries_;
}
- const HpackHeaderTable::UnorderedEntrySet& GetStaticIndex() const {
+ const HpackHeaderTable::NameValueToEntryMap& GetStaticIndex() const {
return static_index_;
}
const HpackHeaderTable::NameToEntryMap& GetStaticNameIndex() const {
@@ -44,8 +47,10 @@ class QUICHE_EXPORT_PRIVATE HpackStaticTable {
size_t EstimateMemoryUsage() const;
private:
- HpackHeaderTable::EntryTable static_entries_;
- HpackHeaderTable::UnorderedEntrySet static_index_;
+ HpackHeaderTable::StaticEntryTable static_entries_;
+ // The following two members have string_views that point to strings stored in
+ // |static_entries_|.
+ HpackHeaderTable::NameValueToEntryMap static_index_;
HpackHeaderTable::NameToEntryMap static_name_index_;
};
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table_test.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table_test.cc
index ad868b16c80..f7506daf474 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table_test.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table_test.cc
@@ -31,17 +31,20 @@ TEST_F(HpackStaticTableTest, Initialize) {
HpackStaticTableVector().size());
EXPECT_TRUE(table_.IsInitialized());
- HpackHeaderTable::EntryTable static_entries = table_.GetStaticEntries();
- EXPECT_EQ(HpackStaticTableVector().size(), static_entries.size());
+ const HpackHeaderTable::StaticEntryTable& static_entries =
+ table_.GetStaticEntries();
+ EXPECT_EQ(kStaticTableSize, static_entries.size());
- HpackHeaderTable::UnorderedEntrySet static_index = table_.GetStaticIndex();
- EXPECT_EQ(HpackStaticTableVector().size(), static_index.size());
+ const HpackHeaderTable::NameValueToEntryMap& static_index =
+ table_.GetStaticIndex();
+ EXPECT_EQ(kStaticTableSize, static_index.size());
- HpackHeaderTable::NameToEntryMap static_name_index =
+ const HpackHeaderTable::NameToEntryMap& static_name_index =
table_.GetStaticNameIndex();
+ // Count distinct names in static table.
std::set<absl::string_view> names;
- for (auto* entry : static_index) {
- names.insert(entry->name());
+ for (const auto& entry : static_entries) {
+ names.insert(entry.name());
}
EXPECT_EQ(names.size(), static_name_index.size());
}
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 b9989c83cc8..cb9c176090a 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
@@ -277,12 +277,6 @@ void Http2DecoderAdapter::set_extension_visitor(
extension_ = visitor;
}
-// Passes the call on to the HPACK decoder.
-void Http2DecoderAdapter::SetDecoderHeaderTableDebugVisitor(
- std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) {
- GetHpackDecoder()->SetHeaderTableDebugVisitor(std::move(visitor));
-}
-
size_t Http2DecoderAdapter::ProcessInput(const char* data, size_t len) {
size_t limit = recv_frame_size_limit_;
frame_decoder_->set_maximum_payload_size(limit);
@@ -476,8 +470,9 @@ void Http2DecoderAdapter::OnHeadersPriority(
on_headers_called_ = true;
ReportReceiveCompressedFrame(frame_header_);
if (!visitor()) {
- SPDY_BUG << "Visitor is nullptr, handling priority in headers failed."
- << " priority:" << priority << " frame_header:" << frame_header_;
+ SPDY_BUG(spdy_bug_1_1)
+ << "Visitor is nullptr, handling priority in headers failed."
+ << " priority:" << priority << " frame_header:" << frame_header_;
return;
}
visitor()->OnHeaders(frame_header_.stream_id, kHasPriorityFields,
@@ -827,9 +822,10 @@ size_t Http2DecoderAdapter::ProcessInputFrame(const char* data, size_t len) {
<< " total remaining in the frame's payload.";
db.AdvanceCursor(avail);
} else {
- SPDY_BUG << "Total remaining (" << total
- << ") should not be greater than the payload length; "
- << frame_header();
+ SPDY_BUG(spdy_bug_1_2)
+ << "Total remaining (" << total
+ << ") should not be greater than the payload length; "
+ << frame_header();
}
}
}
@@ -877,12 +873,13 @@ void Http2DecoderAdapter::DetermineSpdyState(DecodeStatus status) {
DecodeBuffer tmp("", 0);
DecodeStatus status = frame_decoder_->DecodeFrame(&tmp);
if (status != DecodeStatus::kDecodeDone) {
- SPDY_BUG << "Expected to be done decoding the frame, not "
- << status;
+ SPDY_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 << "Expected to have no error, not "
- << SpdyFramerErrorToString(spdy_framer_error_);
+ SPDY_BUG(spdy_bug_1_4)
+ << "Expected to have no error, not "
+ << SpdyFramerErrorToString(spdy_framer_error_);
} else {
ResetBetweenFrames();
}
@@ -1077,7 +1074,7 @@ void Http2DecoderAdapter::CommonStartHpackBlock() {
SpdyHeadersHandlerInterface* handler =
visitor()->OnHeaderFrameStart(stream_id());
if (handler == nullptr) {
- SPDY_BUG << "visitor_->OnHeaderFrameStart returned nullptr";
+ SPDY_BUG(spdy_bug_1_5) << "visitor_->OnHeaderFrameStart returned nullptr";
SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INTERNAL_FRAMER_ERROR, "");
return;
}
diff --git a/chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h b/chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h
index eec6958fa2c..f05152b6468 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h
@@ -127,14 +127,16 @@ class QUICHE_EXPORT_PRIVATE Http2DecoderAdapter
return debug_visitor_;
}
- // Set debug callbacks to be called from the HPACK decoder.
- void SetDecoderHeaderTableDebugVisitor(
- std::unique_ptr<spdy::HpackHeaderTable::DebugVisitorInterface> visitor);
-
// Decode the |len| bytes of encoded HTTP/2 starting at |*data|. Returns
// the number of bytes consumed. It is safe to pass more bytes in than
// may be consumed. Should process (or otherwise buffer) as much as
// available.
+ //
+ // If the input contains the entirety of a DATA frame payload, GOAWAY frame
+ // Additional Debug Data field, or unknown frame payload, then the
+ // corresponding SpdyFramerVisitorInterface::OnStreamFrameData(),
+ // OnGoAwayFrameData(), or ExtensionVisitorInterface::OnFramePayload() method
+ // is guaranteed to be called exactly once, with the entire payload or field.
size_t ProcessInput(const char* data, size_t len);
// Reset the decoder (used just for tests at this time).
diff --git a/chromium/net/third_party/quiche/src/spdy/core/http2_priority_write_scheduler.h b/chromium/net/third_party/quiche/src/spdy/core/http2_priority_write_scheduler.h
index 2486453b251..5820145aac4 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/http2_priority_write_scheduler.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/http2_priority_write_scheduler.h
@@ -82,7 +82,7 @@ class Http2PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
friend class test::Http2PriorityWriteSchedulerPeer<StreamIdType>;
struct StreamInfo;
- typedef SpdyInlinedVector<StreamInfo*, 4> StreamInfoVector;
+ using StreamInfoVector = absl::InlinedVector<StreamInfo*, 4>;
struct StreamInfo : public SpdyIntrusiveLink<StreamInfo> {
// ID for this stream.
@@ -221,11 +221,11 @@ void Http2PriorityWriteScheduler<StreamIdType>::RegisterStream(
// (e.g. SpdyClientDispatcher) modified to pass StreamPrecedence instances
// appropriate for protocol version under test.
//
- // SPDY_BUG_IF(precedence.is_spdy3_priority())
+ // SPDY_BUG_IF(spdy_bug_8_1, precedence.is_spdy3_priority())
// << "Expected HTTP/2 stream dependency";
if (StreamRegistered(stream_id)) {
- SPDY_BUG << "Stream " << stream_id << " already registered";
+ SPDY_BUG(spdy_bug_8_2) << "Stream " << stream_id << " already registered";
return;
}
@@ -272,13 +272,13 @@ template <typename StreamIdType>
void Http2PriorityWriteScheduler<StreamIdType>::UnregisterStream(
StreamIdType stream_id) {
if (stream_id == kHttp2RootStreamId) {
- SPDY_BUG << "Cannot unregister root stream";
+ SPDY_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 << "Stream " << stream_id << " not registered";
+ SPDY_BUG(spdy_bug_8_4) << "Stream " << stream_id << " not registered";
return;
}
std::unique_ptr<StreamInfo> stream_info(std::move(it->second));
@@ -335,7 +335,7 @@ Http2PriorityWriteScheduler<StreamIdType>::GetStreamChildren(
std::vector<StreamIdType> child_vec;
const StreamInfo* stream_info = FindStream(stream_id);
if (stream_info == nullptr) {
- SPDY_BUG << "Stream " << stream_id << " not registered";
+ SPDY_BUG(spdy_bug_8_5) << "Stream " << stream_id << " not registered";
} else {
child_vec.reserve(stream_info->children.size());
for (StreamInfo* child : stream_info->children) {
@@ -353,10 +353,10 @@ void Http2PriorityWriteScheduler<StreamIdType>::UpdateStreamPrecedence(
// (e.g. SpdyClientDispatcher) modified to pass StreamPrecedence instances
// appropriate for protocol version under test.
//
- // SPDY_BUG_IF(precedence.is_spdy3_priority())
+ // SPDY_BUG_IF(spdy_bug_8_6, precedence.is_spdy3_priority())
// << "Expected HTTP/2 stream dependency";
if (stream_id == kHttp2RootStreamId) {
- SPDY_BUG << "Cannot set precedence of root stream";
+ SPDY_BUG(spdy_bug_8_7) << "Cannot set precedence of root stream";
return;
}
@@ -393,7 +393,7 @@ void Http2PriorityWriteScheduler<StreamIdType>::UpdateStreamParent(
StreamIdType parent_id,
bool exclusive) {
if (stream_info->id == parent_id) {
- SPDY_BUG << "Cannot set stream to be its own parent";
+ SPDY_BUG(spdy_bug_8_8) << "Cannot set stream to be its own parent";
return;
}
StreamInfo* new_parent = FindStream(parent_id);
@@ -457,12 +457,12 @@ void Http2PriorityWriteScheduler<StreamIdType>::RecordStreamEventTime(
StreamIdType stream_id,
int64_t now_in_usec) {
if (stream_id == kHttp2RootStreamId) {
- SPDY_BUG << "Cannot record event time for root stream";
+ SPDY_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 << "Stream " << stream_id << " not registered";
+ SPDY_BUG(spdy_bug_8_10) << "Stream " << stream_id << " not registered";
return;
}
stream_info->last_event_time_usec = now_in_usec;
@@ -477,12 +477,12 @@ template <typename StreamIdType>
int64_t Http2PriorityWriteScheduler<StreamIdType>::GetLatestEventWithPrecedence(
StreamIdType stream_id) const {
if (stream_id == kHttp2RootStreamId) {
- SPDY_BUG << "Invalid argument: root stream";
+ SPDY_BUG(spdy_bug_8_11) << "Invalid argument: root stream";
return 0;
}
const StreamInfo* stream_info = FindStream(stream_id);
if (stream_info == nullptr) {
- SPDY_BUG << "Stream " << stream_id << " not registered";
+ SPDY_BUG(spdy_bug_8_12) << "Stream " << stream_id << " not registered";
return 0;
}
int64_t last_event_time_usec = 0;
@@ -503,12 +503,12 @@ template <typename StreamIdType>
bool Http2PriorityWriteScheduler<StreamIdType>::ShouldYield(
StreamIdType stream_id) const {
if (stream_id == kHttp2RootStreamId) {
- SPDY_BUG << "Invalid argument: root stream";
+ SPDY_BUG(spdy_bug_8_13) << "Invalid argument: root stream";
return false;
}
const StreamInfo* stream_info = FindStream(stream_id);
if (stream_info == nullptr) {
- SPDY_BUG << "Stream " << stream_id << " not registered";
+ SPDY_BUG(spdy_bug_8_14) << "Stream " << stream_id << " not registered";
return false;
}
if (HasReadyAncestor(*stream_info)) {
@@ -534,12 +534,12 @@ void Http2PriorityWriteScheduler<StreamIdType>::MarkStreamReady(
StreamIdType stream_id,
bool add_to_front) {
if (stream_id == kHttp2RootStreamId) {
- SPDY_BUG << "Cannot mark root stream ready";
+ SPDY_BUG(spdy_bug_8_15) << "Cannot mark root stream ready";
return;
}
StreamInfo* stream_info = FindStream(stream_id);
if (stream_info == nullptr) {
- SPDY_BUG << "Stream " << stream_id << " not registered";
+ SPDY_BUG(spdy_bug_8_16) << "Stream " << stream_id << " not registered";
return;
}
if (stream_info->ready) {
@@ -553,12 +553,12 @@ template <typename StreamIdType>
void Http2PriorityWriteScheduler<StreamIdType>::MarkStreamNotReady(
StreamIdType stream_id) {
if (stream_id == kHttp2RootStreamId) {
- SPDY_BUG << "Cannot mark root stream unready";
+ SPDY_BUG(spdy_bug_8_17) << "Cannot mark root stream unready";
return;
}
StreamInfo* stream_info = FindStream(stream_id);
if (stream_info == nullptr) {
- SPDY_BUG << "Stream " << stream_id << " not registered";
+ SPDY_BUG(spdy_bug_8_18) << "Stream " << stream_id << " not registered";
return;
}
if (!stream_info->ready) {
@@ -680,7 +680,7 @@ Http2PriorityWriteScheduler<StreamIdType>::PopNextReadyStreamAndPrecedence() {
return std::make_tuple(stream_info.id, stream_info.ToStreamPrecedence());
}
}
- SPDY_BUG << "No ready streams";
+ SPDY_BUG(spdy_bug_8_19) << "No ready streams";
return std::make_tuple(
kHttp2RootStreamId,
StreamPrecedenceType(kHttp2RootStreamId, kHttp2MinStreamWeight, false));
@@ -695,12 +695,12 @@ template <typename StreamIdType>
bool Http2PriorityWriteScheduler<StreamIdType>::IsStreamReady(
StreamIdType stream_id) const {
if (stream_id == kHttp2RootStreamId) {
- SPDY_BUG << "Try to check whether root stream is ready";
+ SPDY_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 << "Stream " << stream_id << " not registered";
+ SPDY_BUG(spdy_bug_8_21) << "Stream " << stream_id << " not registered";
return false;
}
return stream_info->ready;
diff --git a/chromium/net/third_party/quiche/src/spdy/core/lifo_write_scheduler.h b/chromium/net/third_party/quiche/src/spdy/core/lifo_write_scheduler.h
deleted file mode 100644
index cbe53d20ae2..00000000000
--- a/chromium/net/third_party/quiche/src/spdy/core/lifo_write_scheduler.h
+++ /dev/null
@@ -1,238 +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_CORE_LIFO_WRITE_SCHEDULER_H_
-#define QUICHE_SPDY_CORE_LIFO_WRITE_SCHEDULER_H_
-
-#include <cstdint>
-#include <map>
-#include <set>
-#include <string>
-
-#include "absl/strings/str_cat.h"
-#include "spdy/core/write_scheduler.h"
-#include "spdy/platform/api/spdy_containers.h"
-
-namespace spdy {
-
-namespace test {
-
-template <typename StreamIdType>
-class LifoWriteSchedulerPeer;
-
-} // namespace test
-
-// Create a write scheduler where the stream added last will have the highest
-// priority.
-template <typename StreamIdType>
-class LifoWriteScheduler : public WriteScheduler<StreamIdType> {
- public:
- using typename WriteScheduler<StreamIdType>::StreamPrecedenceType;
-
- LifoWriteScheduler() = default;
-
- void RegisterStream(StreamIdType stream_id,
- const StreamPrecedenceType& /*precedence*/) override;
-
- void UnregisterStream(StreamIdType stream_id) override;
-
- bool StreamRegistered(StreamIdType stream_id) const override {
- return registered_streams_.find(stream_id) != registered_streams_.end();
- }
-
- // Stream precedence is available but note that it is not used for scheduling
- // in this scheduler.
- StreamPrecedenceType GetStreamPrecedence(
- StreamIdType stream_id) const override;
-
- void UpdateStreamPrecedence(StreamIdType stream_id,
- const StreamPrecedenceType& precedence) override;
-
- std::vector<StreamIdType> GetStreamChildren(
- StreamIdType /*stream_id*/) const override {
- return std::vector<StreamIdType>();
- }
-
- void RecordStreamEventTime(StreamIdType stream_id,
- int64_t now_in_usec) override;
-
- int64_t GetLatestEventWithPrecedence(StreamIdType stream_id) const override;
-
- StreamIdType PopNextReadyStream() override;
-
- std::tuple<StreamIdType, StreamPrecedenceType>
- PopNextReadyStreamAndPrecedence() override {
- return std::make_tuple(PopNextReadyStream(),
- StreamPrecedenceType(kV3LowestPriority));
- }
-
- bool ShouldYield(StreamIdType stream_id) const override {
- return !ready_streams_.empty() && stream_id < *ready_streams_.rbegin();
- }
-
- void MarkStreamReady(StreamIdType stream_id, bool /*add_to_front*/) override;
-
- void MarkStreamNotReady(StreamIdType stream_id) override;
-
- bool HasReadyStreams() const override { return !ready_streams_.empty(); }
- size_t NumReadyStreams() const override { return ready_streams_.size(); }
- bool IsStreamReady(StreamIdType stream_id) const override;
- size_t NumRegisteredStreams() const override;
- std::string DebugString() const override;
-
- private:
- friend class test::LifoWriteSchedulerPeer<StreamIdType>;
-
- struct StreamInfo {
- SpdyPriority priority;
- int64_t event_time; // read/write event time (us since Unix epoch).
- };
-
- std::set<StreamIdType> ready_streams_;
- std::map<StreamIdType, StreamInfo> registered_streams_;
-};
-
-template <typename StreamIdType>
-void LifoWriteScheduler<StreamIdType>::RegisterStream(
- StreamIdType stream_id,
- const StreamPrecedenceType& precedence) {
- if (StreamRegistered(stream_id)) {
- SPDY_BUG << "Stream " << stream_id << " already registered";
- return;
- }
- registered_streams_.emplace_hint(
- registered_streams_.end(), stream_id,
- StreamInfo{/*priority=*/precedence.spdy3_priority(), /*event_time=*/0});
-}
-
-template <typename StreamIdType>
-void LifoWriteScheduler<StreamIdType>::UnregisterStream(
- StreamIdType stream_id) {
- if (!StreamRegistered(stream_id)) {
- SPDY_BUG << "Stream " << stream_id << " is not registered";
- return;
- }
- registered_streams_.erase(stream_id);
- ready_streams_.erase(stream_id);
-}
-
-template <typename StreamIdType>
-typename LifoWriteScheduler<StreamIdType>::StreamPrecedenceType
-LifoWriteScheduler<StreamIdType>::GetStreamPrecedence(
- StreamIdType stream_id) const {
- auto it = registered_streams_.find(stream_id);
- if (it == registered_streams_.end()) {
- SPDY_DVLOG(1) << "Stream " << stream_id << " not registered";
- return StreamPrecedenceType(kV3LowestPriority);
- }
- return StreamPrecedenceType(it->second.priority);
-}
-
-template <typename StreamIdType>
-void LifoWriteScheduler<StreamIdType>::UpdateStreamPrecedence(
- StreamIdType stream_id,
- const StreamPrecedenceType& precedence) {
- auto it = registered_streams_.find(stream_id);
- if (it == registered_streams_.end()) {
- SPDY_DVLOG(1) << "Stream " << stream_id << " not registered";
- return;
- }
- it->second.priority = precedence.spdy3_priority();
-}
-
-template <typename StreamIdType>
-void LifoWriteScheduler<StreamIdType>::RecordStreamEventTime(
- StreamIdType stream_id,
- int64_t now_in_usec) {
- auto it = registered_streams_.find(stream_id);
- if (it != registered_streams_.end()) {
- it->second.event_time = now_in_usec;
- } else {
- SPDY_BUG << "Stream " << stream_id << " is not registered";
- }
-}
-
-template <typename StreamIdType>
-int64_t LifoWriteScheduler<StreamIdType>::GetLatestEventWithPrecedence(
- StreamIdType stream_id) const {
- if (!StreamRegistered(stream_id)) {
- SPDY_BUG << "Stream " << stream_id << " is not registered";
- return 0;
- }
- int64_t latest_event_time_us = 0;
- for (auto it = registered_streams_.rbegin(); it != registered_streams_.rend();
- ++it) {
- if (stream_id < it->first) {
- if (it->second.event_time > latest_event_time_us) {
- latest_event_time_us = it->second.event_time;
- }
- } else {
- break;
- }
- }
- return latest_event_time_us;
-}
-
-template <typename StreamIdType>
-StreamIdType LifoWriteScheduler<StreamIdType>::PopNextReadyStream() {
- if (ready_streams_.empty()) {
- SPDY_BUG << "No ready streams available";
- return 0;
- }
- auto it = --ready_streams_.end();
- StreamIdType id = *it;
- ready_streams_.erase(it);
- return id;
-}
-
-template <typename StreamIdType>
-void LifoWriteScheduler<StreamIdType>::MarkStreamReady(StreamIdType stream_id,
- bool /*add_to_front*/) {
- if (!StreamRegistered(stream_id)) {
- SPDY_BUG << "Stream " << stream_id << " is not registered";
- return;
- }
- if (ready_streams_.find(stream_id) != ready_streams_.end()) {
- SPDY_VLOG(1) << "Stream already exists in the list";
- return;
- }
- ready_streams_.insert(stream_id);
-}
-
-template <typename StreamIdType>
-void LifoWriteScheduler<StreamIdType>::MarkStreamNotReady(
- StreamIdType stream_id) {
- auto it = ready_streams_.find(stream_id);
- if (it == ready_streams_.end()) {
- SPDY_VLOG(1) << "Try to remove a stream that is not on list";
- return;
- }
- ready_streams_.erase(it);
-}
-
-template <typename StreamIdType>
-bool LifoWriteScheduler<StreamIdType>::IsStreamReady(
- StreamIdType stream_id) const {
- if (!StreamRegistered(stream_id)) {
- SPDY_BUG << "Stream " << stream_id << " is not registered";
- return false;
- }
- return ready_streams_.find(stream_id) != ready_streams_.end();
-}
-
-template <typename StreamIdType>
-size_t LifoWriteScheduler<StreamIdType>::NumRegisteredStreams() const {
- return registered_streams_.size();
-}
-
-template <typename StreamIdType>
-std::string LifoWriteScheduler<StreamIdType>::DebugString() const {
- return absl::StrCat(
- "LifoWriteScheduler {num_streams=", registered_streams_.size(),
- " num_ready_streams=", NumReadyStreams(), "}");
-}
-
-} // namespace spdy
-
-#endif // QUICHE_SPDY_CORE_LIFO_WRITE_SCHEDULER_H_
diff --git a/chromium/net/third_party/quiche/src/spdy/core/lifo_write_scheduler_test.cc b/chromium/net/third_party/quiche/src/spdy/core/lifo_write_scheduler_test.cc
deleted file mode 100644
index c7305e7dac1..00000000000
--- a/chromium/net/third_party/quiche/src/spdy/core/lifo_write_scheduler_test.cc
+++ /dev/null
@@ -1,174 +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 "spdy/core/lifo_write_scheduler.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_test_helpers.h"
-
-namespace spdy {
-
-namespace test {
-
-template <typename StreamIdType>
-class LifoWriteSchedulerPeer {
- public:
- explicit LifoWriteSchedulerPeer(LifoWriteScheduler<StreamIdType>* scheduler)
- : scheduler_(scheduler) {}
-
- size_t NumRegisteredListStreams() const {
- return scheduler_->registered_streams_.size();
- }
-
- std::set<StreamIdType>* GetReadyList() const {
- return &scheduler_->ready_streams_;
- }
-
- private:
- LifoWriteScheduler<StreamIdType>* scheduler_;
-};
-
-// Test add and remove from ready list.
-TEST(LifoWriteSchedulerTest, ReadyListTest) {
- LifoWriteScheduler<SpdyStreamId> lifo;
- LifoWriteSchedulerPeer<SpdyStreamId> peer(&lifo);
-
- EXPECT_SPDY_BUG(
- EXPECT_EQ(0u, std::get<0>(lifo.PopNextReadyStreamAndPrecedence())),
- "No ready streams available");
- EXPECT_SPDY_BUG(EXPECT_EQ(0u, lifo.PopNextReadyStream()),
- "No ready streams available");
- EXPECT_FALSE(lifo.HasReadyStreams());
- EXPECT_SPDY_BUG(lifo.MarkStreamReady(9, true), "Stream 9 is not registered");
- EXPECT_SPDY_BUG(lifo.IsStreamReady(9), "Stream 9 is not registered");
- SpdyStreamPrecedence precedence(1);
- lifo.RegisterStream(3, precedence);
- EXPECT_FALSE(lifo.IsStreamReady(3));
- lifo.RegisterStream(7, precedence);
- lifo.RegisterStream(9, precedence);
- lifo.RegisterStream(11, precedence);
- lifo.RegisterStream(13, precedence);
- lifo.RegisterStream(15, precedence);
- lifo.RegisterStream(17, precedence);
- lifo.MarkStreamReady(9, true);
- lifo.MarkStreamReady(15, true);
- lifo.MarkStreamReady(7, true);
- lifo.MarkStreamReady(13, true);
- lifo.MarkStreamReady(11, true);
- lifo.MarkStreamReady(3, true);
- EXPECT_TRUE(lifo.IsStreamReady(3));
- lifo.MarkStreamReady(17, true);
- EXPECT_TRUE(lifo.HasReadyStreams());
- EXPECT_EQ(7u, lifo.NumReadyStreams());
-
- // Verify MarkStream(Not)Ready() can be called multiple times for the same
- // stream.
- lifo.MarkStreamReady(11, true);
- lifo.MarkStreamNotReady(5);
- lifo.MarkStreamNotReady(21);
-
- EXPECT_EQ(17u, lifo.PopNextReadyStream());
- EXPECT_EQ(15u, std::get<0>(lifo.PopNextReadyStreamAndPrecedence()));
- EXPECT_TRUE(lifo.ShouldYield(9));
- EXPECT_FALSE(lifo.ShouldYield(13));
- EXPECT_FALSE(lifo.ShouldYield(15));
-
- lifo.MarkStreamNotReady(3);
- EXPECT_TRUE(peer.GetReadyList()->find(3) == peer.GetReadyList()->end());
- lifo.MarkStreamNotReady(13);
- EXPECT_TRUE(peer.GetReadyList()->find(13) == peer.GetReadyList()->end());
- lifo.MarkStreamNotReady(7);
- EXPECT_TRUE(peer.GetReadyList()->find(7) == peer.GetReadyList()->end());
- EXPECT_EQ(2u, lifo.NumReadyStreams());
-
- lifo.MarkStreamNotReady(9);
- lifo.MarkStreamNotReady(11);
- EXPECT_FALSE(lifo.ShouldYield(1));
-}
-
-// Test add and remove from registered list.
-TEST(LifoWriteSchedulerTest, RegisterListTest) {
- LifoWriteScheduler<SpdyStreamId> lifo;
- LifoWriteSchedulerPeer<SpdyStreamId> peer(&lifo);
- SpdyStreamPrecedence precedence(1);
- EXPECT_EQ(0u, lifo.NumRegisteredStreams());
- lifo.RegisterStream(3, precedence);
- lifo.RegisterStream(5, precedence);
- lifo.RegisterStream(7, precedence);
- lifo.RegisterStream(9, precedence);
- lifo.RegisterStream(11, precedence);
- EXPECT_EQ(5u, lifo.NumRegisteredStreams());
-
- EXPECT_TRUE(lifo.StreamRegistered(3));
- EXPECT_TRUE(lifo.StreamRegistered(5));
- EXPECT_TRUE(lifo.StreamRegistered(7));
- EXPECT_TRUE(lifo.StreamRegistered(9));
- EXPECT_TRUE(lifo.StreamRegistered(11));
- EXPECT_SPDY_BUG(lifo.RegisterStream(11, precedence),
- "Stream 11 already registered");
- EXPECT_EQ(5u, peer.NumRegisteredListStreams());
-
- lifo.UnregisterStream(3);
- EXPECT_EQ(4u, lifo.NumRegisteredStreams());
- EXPECT_FALSE(lifo.StreamRegistered(3));
- EXPECT_SPDY_BUG(lifo.UnregisterStream(3), "Stream 3 is not registered");
- EXPECT_SPDY_BUG(lifo.UnregisterStream(13), "Stream 13 is not registered");
- lifo.UnregisterStream(11);
- EXPECT_FALSE(lifo.StreamRegistered(11));
- lifo.UnregisterStream(7);
- EXPECT_EQ(2u, lifo.NumRegisteredStreams());
- EXPECT_FALSE(lifo.StreamRegistered(7));
- EXPECT_TRUE(lifo.StreamRegistered(5));
- EXPECT_TRUE(lifo.StreamRegistered(9));
-}
-
-// Test mark latest event time.
-TEST(LifoWriteSchedulerTest, GetLatestEventTest) {
- LifoWriteScheduler<SpdyStreamId> lifo;
- LifoWriteSchedulerPeer<SpdyStreamId> peer(&lifo);
- SpdyStreamPrecedence precedence(1);
- lifo.RegisterStream(1, precedence);
- lifo.RegisterStream(3, precedence);
- lifo.RegisterStream(5, precedence);
- lifo.RegisterStream(7, precedence);
- lifo.RegisterStream(9, precedence);
- lifo.RecordStreamEventTime(1, 1);
- lifo.RecordStreamEventTime(3, 8);
- lifo.RecordStreamEventTime(5, 4);
- lifo.RecordStreamEventTime(7, 2);
- lifo.RecordStreamEventTime(9, 3);
- EXPECT_SPDY_BUG(lifo.RecordStreamEventTime(11, 1),
- "Stream 11 is not registered");
- EXPECT_EQ(0, lifo.GetLatestEventWithPrecedence(9));
- EXPECT_EQ(3, lifo.GetLatestEventWithPrecedence(7));
- EXPECT_EQ(3, lifo.GetLatestEventWithPrecedence(5));
- EXPECT_EQ(4, lifo.GetLatestEventWithPrecedence(3));
- EXPECT_EQ(8, lifo.GetLatestEventWithPrecedence(1));
- EXPECT_SPDY_BUG(lifo.GetLatestEventWithPrecedence(11),
- "Stream 11 is not registered");
-}
-
-TEST(LifoWriteSchedulerTest, GetStreamPrecedence) {
- LifoWriteScheduler<SpdyStreamId> lifo;
- // Return lowest priority for unknown stream.
- EXPECT_EQ(kV3LowestPriority, lifo.GetStreamPrecedence(1).spdy3_priority());
-
- lifo.RegisterStream(1, SpdyStreamPrecedence(3));
- EXPECT_TRUE(lifo.GetStreamPrecedence(1).is_spdy3_priority());
- EXPECT_EQ(3, lifo.GetStreamPrecedence(1).spdy3_priority());
-
- // Redundant registration shouldn't change stream priority.
- EXPECT_SPDY_BUG(lifo.RegisterStream(1, SpdyStreamPrecedence(4)),
- "Stream 1 already registered");
- EXPECT_EQ(3, lifo.GetStreamPrecedence(1).spdy3_priority());
-
- lifo.UpdateStreamPrecedence(1, SpdyStreamPrecedence(5));
- EXPECT_EQ(5, lifo.GetStreamPrecedence(1).spdy3_priority());
-}
-
-} // namespace test
-
-} // namespace spdy
diff --git a/chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler.h b/chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler.h
index c6824c67bd1..fde9a286ed5 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler.h
@@ -8,6 +8,7 @@
#include <algorithm>
#include <cstddef>
#include <cstdint>
+#include <deque>
#include <string>
#include <tuple>
#include <unordered_map>
@@ -15,7 +16,6 @@
#include <vector>
#include "absl/strings/str_cat.h"
-#include "http2/platform/api/http2_containers.h"
#include "spdy/core/spdy_protocol.h"
#include "spdy/core/write_scheduler.h"
#include "spdy/platform/api/spdy_bug_tracker.h"
@@ -61,19 +61,21 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
<< "Parent stream " << parent_id << " not registered";
if (stream_id == root_stream_id_) {
- SPDY_BUG << "Stream " << root_stream_id_ << " already registered";
+ SPDY_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(!inserted) << "Stream " << stream_id << " already registered";
+ SPDY_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 << "Stream " << stream_id << " not registered";
+ SPDY_BUG(spdy_bug_19_3) << "Stream " << stream_id << " not registered";
return;
}
StreamInfo& stream_info = it->second;
@@ -141,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 << "Stream " << stream_id << " not registered";
+ SPDY_BUG(spdy_bug_19_4) << "Stream " << stream_id << " not registered";
return;
}
PriorityInfo& priority_info = priority_infos_[it->second.priority];
@@ -152,7 +154,7 @@ 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 << "Stream " << stream_id << " not registered";
+ SPDY_BUG(spdy_bug_19_5) << "Stream " << stream_id << " not registered";
return 0;
}
int64_t last_event_time_usec = 0;
@@ -185,14 +187,14 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
StreamPrecedenceType(info->priority));
}
}
- SPDY_BUG << "No ready streams available";
+ SPDY_BUG(spdy_bug_19_6) << "No ready streams available";
return std::make_tuple(0, StreamPrecedenceType(kV3LowestPriority));
}
bool ShouldYield(StreamIdType stream_id) const override {
auto it = stream_infos_.find(stream_id);
if (it == stream_infos_.end()) {
- SPDY_BUG << "Stream " << stream_id << " not registered";
+ SPDY_BUG(spdy_bug_19_7) << "Stream " << stream_id << " not registered";
return false;
}
@@ -219,7 +221,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 << "Stream " << stream_id << " not registered";
+ SPDY_BUG(spdy_bug_19_8) << "Stream " << stream_id << " not registered";
return;
}
StreamInfo& stream_info = it->second;
@@ -239,7 +241,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 << "Stream " << stream_id << " not registered";
+ SPDY_BUG(spdy_bug_19_9) << "Stream " << stream_id << " not registered";
return;
}
StreamInfo& stream_info = it->second;
@@ -288,7 +290,7 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
};
// O(1) size lookup, O(1) insert at front or back (amortized).
- using ReadyList = http2::Http2Deque<StreamInfo*>;
+ using ReadyList = std::deque<StreamInfo*>;
// State kept for each priority level.
struct PriorityInfo {
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 4f6b4f3ecfa..5b6af98a9ac 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
@@ -265,15 +265,14 @@ std::string SpdyAltSvcWireFormat::SerializeHeaderFieldValue(
}
value.push_back(c);
}
- value.append(absl::StrCat(":", altsvc.port, "\""));
+ absl::StrAppend(&value, ":", altsvc.port, "\"");
if (altsvc.max_age != 86400) {
- value.append(absl::StrCat("; ma=", altsvc.max_age));
+ absl::StrAppend(&value, "; ma=", altsvc.max_age);
}
if (!altsvc.version.empty()) {
if (is_ietf_format_quic) {
for (uint32_t quic_version : altsvc.version) {
- value.append("; quic=");
- value.append(SpdyHexEncodeUInt32AndTrim(quic_version));
+ absl::StrAppend(&value, "; quic=", absl::Hex(quic_version));
}
} else {
value.append("; v=\"");
@@ -282,7 +281,7 @@ std::string SpdyAltSvcWireFormat::SerializeHeaderFieldValue(
if (it != altsvc.version.begin()) {
value.append(",");
}
- value.append(absl::StrCat(*it));
+ absl::StrAppend(&value, *it);
}
value.append("\"");
}
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 d8d23dfe9ce..fccda75ac6e 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
@@ -14,9 +14,9 @@
#include <string>
#include <vector>
+#include "absl/container/inlined_vector.h"
#include "absl/strings/string_view.h"
#include "common/platform/api/quiche_export.h"
-#include "spdy/platform/api/spdy_containers.h"
namespace spdy {
@@ -26,7 +26,7 @@ class SpdyAltSvcWireFormatPeer;
class QUICHE_EXPORT_PRIVATE SpdyAltSvcWireFormat {
public:
- using VersionVector = SpdyInlinedVector<uint32_t, 8>;
+ using VersionVector = absl::InlinedVector<uint32_t, 8>;
struct QUICHE_EXPORT_PRIVATE AlternativeService {
std::string protocol_id;
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 5c93128d9d6..ee63594ca6c 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
@@ -69,8 +69,9 @@ bool SpdyFrameBuilder::BeginNewFrame(SpdyFrameType type,
QUICHE_DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
bool success = true;
if (length_ > 0) {
- SPDY_BUG << "SpdyFrameBuilder doesn't have a clean state when BeginNewFrame"
- << "is called. Leftover length_ is " << length_;
+ SPDY_BUG(spdy_bug_73_1)
+ << "SpdyFrameBuilder doesn't have a clean state when BeginNewFrame"
+ << "is called. Leftover length_ is " << length_;
offset_ += length_;
length_ = 0;
}
@@ -90,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(length > kHttp2DefaultFramePayloadLimit)
+ SPDY_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);
}
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 b18e9a0a18f..01fce6be819 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
@@ -66,9 +66,10 @@ class QUICHE_EXPORT_PRIVATE SpdyFrameBuilder {
// Takes the buffer from the SpdyFrameBuilder.
SpdySerializedFrame take() {
- SPDY_BUG_IF(output_ != nullptr) << "ZeroCopyOutputBuffer is used to build "
- << "frames. take() shouldn't be called";
- SPDY_BUG_IF(kMaxFrameSizeLimit < length_)
+ SPDY_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_)
<< "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 6b850c2987d..bc7cd1767a0 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
@@ -294,8 +294,9 @@ SpdyFramer::SpdyFrameIterator::~SpdyFrameIterator() = default;
size_t SpdyFramer::SpdyFrameIterator::NextFrame(ZeroCopyOutputBuffer* output) {
const SpdyFrameIR& frame_ir = GetIR();
if (!has_next_frame_) {
- SPDY_BUG << "SpdyFramer::SpdyFrameIterator::NextFrame called without "
- << "a next frame.";
+ SPDY_BUG(spdy_bug_75_1)
+ << "SpdyFramer::SpdyFrameIterator::NextFrame called without "
+ << "a next frame.";
return false;
}
@@ -406,7 +407,6 @@ const SpdyFrameIR& SpdyFramer::SpdyControlFrameIterator::GetIR() const {
return *(frame_ir_.get());
}
-// TODO(yasong): remove all the static_casts.
std::unique_ptr<SpdyFrameSequence> SpdyFramer::CreateIterator(
SpdyFramer* framer,
std::unique_ptr<const SpdyFrameIR> frame_ir) {
@@ -418,8 +418,8 @@ std::unique_ptr<SpdyFrameSequence> SpdyFramer::CreateIterator(
}
case SpdyFrameType::PUSH_PROMISE: {
return std::make_unique<SpdyPushPromiseFrameIterator>(
- framer, absl::WrapUnique(
- static_cast<const SpdyPushPromiseIR*>(frame_ir.release())));
+ framer, absl::WrapUnique(static_cast<const SpdyPushPromiseIR*>(
+ frame_ir.release())));
}
case SpdyFrameType::DATA: {
SPDY_DVLOG(1) << "Serialize a stream end DATA frame for VTL";
@@ -1379,11 +1379,6 @@ size_t SpdyFramer::header_encoder_table_size() const {
}
}
-void SpdyFramer::SetEncoderHeaderTableDebugVisitor(
- std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) {
- GetHpackEncoder()->SetHeaderTableDebugVisitor(std::move(visitor));
-}
-
size_t SpdyFramer::EstimateMemoryUsage() const {
return SpdyEstimateMemoryUsage(hpack_encoder_);
}
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_framer.h b/chromium/net/third_party/quiche/src/spdy/core/spdy_framer.h
index d7a81c10a21..4e3dc35f1d3 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_framer.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_framer.h
@@ -233,9 +233,6 @@ class QUICHE_EXPORT_PRIVATE SpdyFramer {
// Returns the maximum size of the header encoder compression table.
size_t header_encoder_table_size() const;
- void SetEncoderHeaderTableDebugVisitor(
- std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor);
-
// Get (and lazily initialize) the HPACK encoder state.
HpackEncoder* GetHpackEncoder();
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 96b9f4c4258..d7fb6a7a332 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
@@ -4570,12 +4570,7 @@ TEST_P(SpdyFramerTest, ReadPriorityUpdateFrame) {
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
deframer_.set_visitor(&visitor);
- if (GetHttp2RestartFlag(http2_parse_priority_update_frame)) {
- EXPECT_CALL(visitor, OnPriorityUpdate(3, "foo"));
- } else {
- EXPECT_CALL(visitor, OnUnknownFrame(0, _)).WillOnce(testing::Return(true));
- }
-
+ EXPECT_CALL(visitor, OnPriorityUpdate(3, "foo"));
deframer_.ProcessInput(kFrameData, sizeof(kFrameData));
EXPECT_FALSE(deframer_.HasError());
}
@@ -4592,12 +4587,7 @@ TEST_P(SpdyFramerTest, ReadPriorityUpdateFrameWithEmptyPriorityFieldValue) {
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
deframer_.set_visitor(&visitor);
- if (GetHttp2RestartFlag(http2_parse_priority_update_frame)) {
- EXPECT_CALL(visitor, OnPriorityUpdate(3, ""));
- } else {
- EXPECT_CALL(visitor, OnUnknownFrame(0, _)).WillOnce(testing::Return(true));
- }
-
+ EXPECT_CALL(visitor, OnPriorityUpdate(3, ""));
deframer_.ProcessInput(kFrameData, sizeof(kFrameData));
EXPECT_FALSE(deframer_.HasError());
}
@@ -4613,17 +4603,10 @@ TEST_P(SpdyFramerTest, PriorityUpdateFrameWithEmptyPayload) {
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
deframer_.set_visitor(&visitor);
- if (GetHttp2RestartFlag(http2_parse_priority_update_frame)) {
- EXPECT_CALL(
- visitor,
- OnError(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME_SIZE, _));
- deframer_.ProcessInput(kFrameData, sizeof(kFrameData));
- EXPECT_TRUE(deframer_.HasError());
- } else {
- EXPECT_CALL(visitor, OnUnknownFrame(0, _)).WillOnce(testing::Return(true));
- deframer_.ProcessInput(kFrameData, sizeof(kFrameData));
- EXPECT_FALSE(deframer_.HasError());
- }
+ EXPECT_CALL(visitor,
+ OnError(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME_SIZE, _));
+ deframer_.ProcessInput(kFrameData, sizeof(kFrameData));
+ EXPECT_TRUE(deframer_.HasError());
}
TEST_P(SpdyFramerTest, PriorityUpdateFrameWithShortPayload) {
@@ -4639,17 +4622,10 @@ TEST_P(SpdyFramerTest, PriorityUpdateFrameWithShortPayload) {
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
deframer_.set_visitor(&visitor);
- if (GetHttp2RestartFlag(http2_parse_priority_update_frame)) {
- EXPECT_CALL(
- visitor,
- OnError(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME_SIZE, _));
- deframer_.ProcessInput(kFrameData, sizeof(kFrameData));
- EXPECT_TRUE(deframer_.HasError());
- } else {
- EXPECT_CALL(visitor, OnUnknownFrame(0, _)).WillOnce(testing::Return(true));
- deframer_.ProcessInput(kFrameData, sizeof(kFrameData));
- EXPECT_FALSE(deframer_.HasError());
- }
+ EXPECT_CALL(visitor,
+ OnError(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME_SIZE, _));
+ deframer_.ProcessInput(kFrameData, sizeof(kFrameData));
+ EXPECT_TRUE(deframer_.HasError());
}
TEST_P(SpdyFramerTest, PriorityUpdateFrameOnIncorrectStream) {
@@ -4664,16 +4640,9 @@ TEST_P(SpdyFramerTest, PriorityUpdateFrameOnIncorrectStream) {
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
deframer_.set_visitor(&visitor);
- if (GetHttp2RestartFlag(http2_parse_priority_update_frame)) {
- EXPECT_CALL(visitor,
- OnError(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID, _));
- deframer_.ProcessInput(kFrameData, sizeof(kFrameData));
- EXPECT_TRUE(deframer_.HasError());
- } else {
- EXPECT_CALL(visitor, OnUnknownFrame(1, _)).WillOnce(testing::Return(true));
- deframer_.ProcessInput(kFrameData, sizeof(kFrameData));
- EXPECT_FALSE(deframer_.HasError());
- }
+ EXPECT_CALL(visitor, OnError(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID, _));
+ deframer_.ProcessInput(kFrameData, sizeof(kFrameData));
+ EXPECT_TRUE(deframer_.HasError());
}
TEST_P(SpdyFramerTest, PriorityUpdateFramePrioritizingIncorrectStream) {
@@ -4688,16 +4657,9 @@ TEST_P(SpdyFramerTest, PriorityUpdateFramePrioritizingIncorrectStream) {
testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
deframer_.set_visitor(&visitor);
- if (GetHttp2RestartFlag(http2_parse_priority_update_frame)) {
- EXPECT_CALL(visitor,
- OnError(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID, _));
- deframer_.ProcessInput(kFrameData, sizeof(kFrameData));
- EXPECT_TRUE(deframer_.HasError());
- } else {
- EXPECT_CALL(visitor, OnUnknownFrame(0, _)).WillOnce(testing::Return(true));
- deframer_.ProcessInput(kFrameData, sizeof(kFrameData));
- EXPECT_FALSE(deframer_.HasError());
- }
+ EXPECT_CALL(visitor, OnError(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID, _));
+ deframer_.ProcessInput(kFrameData, sizeof(kFrameData));
+ EXPECT_TRUE(deframer_.HasError());
}
// Tests handling of PRIORITY frames.
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 93ae28f1273..59a9069a220 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
@@ -9,9 +9,9 @@
#include <algorithm>
#include <utility>
+#include "absl/strings/str_cat.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 {
namespace {
@@ -223,9 +223,9 @@ std::string Http2HeaderBlock::DebugString() const {
std::string output = "\n{\n";
for (auto it = begin(); it != end(); ++it) {
- SpdyStrAppend(&output, " ", it->first, " ", it->second, "\n");
+ absl::StrAppend(&output, " ", it->first, " ", it->second, "\n");
}
- SpdyStrAppend(&output, "}\n");
+ absl::StrAppend(&output, "}\n");
return output;
}
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.h b/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.h
index 76ec4363678..46584191461 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.h
@@ -14,12 +14,14 @@
#include <vector>
#include "absl/base/attributes.h"
+#include "absl/hash/hash.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
#include "common/platform/api/quiche_export.h"
#include "common/platform/api/quiche_logging.h"
#include "spdy/core/spdy_header_storage.h"
#include "spdy/platform/api/spdy_containers.h"
-#include "spdy/platform/api/spdy_string_utils.h"
namespace spdy {
@@ -92,10 +94,24 @@ class QUICHE_EXPORT_PRIVATE Http2HeaderBlock {
size_t separator_size_ = 0;
};
+ struct StringPieceCaseHash {
+ size_t operator()(absl::string_view data) const {
+ std::string lower = absl::AsciiStrToLower(data);
+ absl::Hash<absl::string_view> hasher;
+ return hasher(lower);
+ }
+ };
+
+ struct StringPieceCaseEqual {
+ bool operator()(absl::string_view piece1, absl::string_view piece2) const {
+ return absl::EqualsIgnoreCase(piece1, piece2);
+ }
+ };
+
typedef SpdyLinkedHashMap<absl::string_view,
HeaderValue,
- SpdyStringPieceCaseHash,
- SpdyStringPieceCaseEq>
+ StringPieceCaseHash,
+ StringPieceCaseEqual>
MapType;
public:
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 9a5c2291590..ea90b6500ed 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
@@ -9,7 +9,6 @@
#include "absl/strings/str_cat.h"
#include "spdy/platform/api/spdy_bug_tracker.h"
-#include "spdy/platform/api/spdy_string_utils.h"
namespace spdy {
@@ -29,7 +28,8 @@ 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 << "Invalid priority: " << static_cast<int>(priority);
+ SPDY_BUG(spdy_bug_22_1)
+ << "Invalid priority: " << static_cast<int>(priority);
return kV3LowestPriority;
}
return priority;
@@ -37,11 +37,11 @@ SpdyPriority ClampSpdy3Priority(SpdyPriority priority) {
int ClampHttp2Weight(int weight) {
if (weight < kHttp2MinStreamWeight) {
- SPDY_BUG << "Invalid weight: " << weight;
+ SPDY_BUG(spdy_bug_22_2) << "Invalid weight: " << weight;
return kHttp2MinStreamWeight;
}
if (weight > kHttp2MaxStreamWeight) {
- SPDY_BUG << "Invalid weight: " << weight;
+ SPDY_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(!IsDefinedFrameType(frame_type_field))
+ SPDY_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);
}
@@ -191,8 +191,7 @@ bool ParseSettingsId(SpdySettingsId wire_setting_id,
std::string SettingsIdToString(SpdySettingsId id) {
SpdyKnownSettingsId known_id;
if (!ParseSettingsId(id, &known_id)) {
- return absl::StrCat("SETTINGS_UNKNOWN_",
- SpdyHexEncodeUInt32AndTrim(uint32_t{id}));
+ return absl::StrCat("SETTINGS_UNKNOWN_", absl::Hex(uint32_t{id}));
}
switch (known_id) {
@@ -216,8 +215,7 @@ std::string SettingsIdToString(SpdySettingsId id) {
return "SETTINGS_EXPERIMENT_SCHEDULER";
}
- return absl::StrCat("SETTINGS_UNKNOWN_",
- SpdyHexEncodeUInt32AndTrim(uint32_t{id}));
+ return absl::StrCat("SETTINGS_UNKNOWN_", absl::Hex(uint32_t{id}));
}
SpdyErrorCode ParseErrorCode(uint32_t wire_error_code) {
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 fcd6adad15f..d4a671b8933 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
@@ -1039,6 +1039,12 @@ class QUICHE_EXPORT_PRIVATE SpdySerializedFrame {
// Returns the actual size of the underlying buffer.
size_t size() const { return size_; }
+ operator absl::string_view() const {
+ return absl::string_view{frame_, size_};
+ }
+
+ operator std::string() const { return std::string{frame_, size_}; }
+
// Returns a buffer containing the contents of the frame, of which the caller
// takes ownership, and clears this SpdySerializedFrame.
char* ReleaseBuffer() {
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
index d750a21f976..f00bbc8b376 100644
--- 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
@@ -8,7 +8,8 @@
#include "net/spdy/platform/impl/spdy_bug_tracker_impl.h"
#define SPDY_BUG SPDY_BUG_IMPL
-#define SPDY_BUG_IF(condition) SPDY_BUG_IF_IMPL(condition)
+#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
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 a1a00e67e2c..9e3813f5b42 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
@@ -9,27 +9,10 @@
namespace spdy {
-template <typename KeyType>
-using SpdyHash = SpdyHashImpl<KeyType>;
-
-// SpdyHashMap does not guarantee pointer stability.
-template <typename KeyType,
- typename ValueType,
- typename Hash = SpdyHash<KeyType>>
-using SpdyHashMap = SpdyHashMapImpl<KeyType, ValueType, Hash>;
-
-// SpdyHashSet does not guarantee pointer stability.
-template <typename ElementType, typename Hasher, typename Eq>
-using SpdyHashSet = SpdyHashSetImpl<ElementType, Hasher, Eq>;
-
// A map which offers insertion-ordered iteration.
template <typename Key, typename Value, typename Hash, typename Eq>
using SpdyLinkedHashMap = SpdyLinkedHashMapImpl<Key, Value, Hash, Eq>;
-// 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 SpdyInlinedVector = SpdyInlinedVectorImpl<T, N, A>;
-
// 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.
diff --git a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_mem_slice.h b/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_mem_slice.h
deleted file mode 100644
index 8288f33e21c..00000000000
--- a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_mem_slice.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_SPDY_PLATFORM_API_SPDY_MEM_SLICE_H_
-#define QUICHE_SPDY_PLATFORM_API_SPDY_MEM_SLICE_H_
-
-#include <utility>
-
-#include "common/platform/api/quiche_export.h"
-#include "net/spdy/platform/impl/spdy_mem_slice_impl.h"
-
-namespace spdy {
-
-// SpdyMemSlice is an internally reference counted data buffer used as the
-// source buffers for write operations. SpdyMemSlice implicitly maintains a
-// reference count and will free the underlying data buffer when the reference
-// count reaches zero.
-class QUICHE_EXPORT_PRIVATE SpdyMemSlice {
- public:
- // Constructs an empty SpdyMemSlice with no underlying data and 0 reference
- // count.
- SpdyMemSlice() = default;
-
- // Constructs a SpdyMemSlice with reference count 1 to a newly allocated data
- // buffer of |length| bytes.
- explicit SpdyMemSlice(size_t length) : impl_(length) {}
-
- // Constructs a SpdyMemSlice from |impl|. It takes the reference away from
- // |impl|.
- explicit SpdyMemSlice(SpdyMemSliceImpl impl) : impl_(std::move(impl)) {}
-
- SpdyMemSlice(const SpdyMemSlice& other) = delete;
- SpdyMemSlice& operator=(const SpdyMemSlice& other) = delete;
-
- // Move constructors. |other| will not hold a reference to the data buffer
- // after this call completes.
- SpdyMemSlice(SpdyMemSlice&& other) = default;
- SpdyMemSlice& operator=(SpdyMemSlice&& other) = default;
-
- ~SpdyMemSlice() = default;
-
- // Returns a char pointer to underlying data buffer.
- const char* data() const { return impl_.data(); }
- // Returns the length of underlying data buffer.
- size_t length() const { return impl_.length(); }
-
- private:
- SpdyMemSliceImpl impl_;
-};
-
-} // namespace spdy
-
-#endif // QUICHE_SPDY_PLATFORM_API_SPDY_MEM_SLICE_H_
diff --git a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_mem_slice_test.cc b/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_mem_slice_test.cc
deleted file mode 100644
index 0efb7404593..00000000000
--- a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_mem_slice_test.cc
+++ /dev/null
@@ -1,47 +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_mem_slice.h"
-
-#include <utility>
-
-#include "common/platform/api/quiche_test.h"
-
-namespace spdy {
-namespace test {
-namespace {
-
-class SpdyMemSliceTest : public QuicheTest {
- public:
- SpdyMemSliceTest() {
- slice_ = SpdyMemSlice(1024);
- orig_data_ = slice_.data();
- orig_length_ = slice_.length();
- }
-
- SpdyMemSlice slice_;
- const char* orig_data_;
- size_t orig_length_;
-};
-
-TEST_F(SpdyMemSliceTest, MoveConstruct) {
- SpdyMemSlice moved(std::move(slice_));
- EXPECT_EQ(moved.data(), orig_data_);
- EXPECT_EQ(moved.length(), orig_length_);
- EXPECT_EQ(nullptr, slice_.data());
- EXPECT_EQ(0u, slice_.length());
-}
-
-TEST_F(SpdyMemSliceTest, MoveAssign) {
- SpdyMemSlice moved;
- moved = std::move(slice_);
- EXPECT_EQ(moved.data(), orig_data_);
- EXPECT_EQ(moved.length(), orig_length_);
- EXPECT_EQ(nullptr, slice_.data());
- EXPECT_EQ(0u, slice_.length());
-}
-
-} // namespace
-} // namespace test
-} // namespace spdy
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 81a0866a11f..178415b0ed6 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
@@ -8,22 +8,11 @@
#include <string>
#include <utility>
-// The following header file has to be included from at least
-// non-test file in order to avoid strange linking errors.
-// TODO(bnc): Remove this include as soon as it is included elsewhere in
-// non-test code.
-#include "spdy/platform/api/spdy_mem_slice.h"
-
#include "absl/strings/string_view.h"
#include "net/spdy/platform/impl/spdy_string_utils_impl.h"
namespace spdy {
-template <typename... Args>
-inline void SpdyStrAppend(std::string* output, const Args&... args) {
- SpdyStrAppendImpl(output, std::forward<const Args&>(args)...);
-}
-
inline char SpdyHexDigitToInt(char c) {
return SpdyHexDigitToIntImpl(c);
}
@@ -40,18 +29,10 @@ inline std::string SpdyHexEncode(const char* bytes, size_t size) {
return SpdyHexEncodeImpl(bytes, size);
}
-inline std::string SpdyHexEncodeUInt32AndTrim(uint32_t data) {
- return SpdyHexEncodeUInt32AndTrimImpl(data);
-}
-
inline std::string SpdyHexDump(absl::string_view data) {
return SpdyHexDumpImpl(data);
}
-using SpdyStringPieceCaseHash = SpdyStringPieceCaseHashImpl;
-
-using SpdyStringPieceCaseEq = SpdyStringPieceCaseEqImpl;
-
} // namespace spdy
#endif // QUICHE_SPDY_PLATFORM_API_SPDY_STRING_UTILS_H_
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
index 2964876ddc7..cb73a9b2ece 100644
--- 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
@@ -13,101 +13,6 @@ namespace spdy {
namespace test {
namespace {
-TEST(SpdyStringUtilsTest, SpdyStrAppend) {
- // No arguments on empty string.
- std::string output;
- SpdyStrAppend(&output);
- EXPECT_TRUE(output.empty());
-
- // Single string-like argument.
- const char kFoo[] = "foo";
- const std::string string_foo(kFoo);
- const absl::string_view stringpiece_foo(string_foo);
- SpdyStrAppend(&output, kFoo);
- EXPECT_EQ("foo", output);
- SpdyStrAppend(&output, string_foo);
- EXPECT_EQ("foofoo", output);
- SpdyStrAppend(&output, stringpiece_foo);
- EXPECT_EQ("foofoofoo", output);
-
- // No arguments on non-empty string.
- SpdyStrAppend(&output);
- EXPECT_EQ("foofoofoo", output);
-
- output.clear();
-
- // Two string-like arguments.
- const char kBar[] = "bar";
- const absl::string_view stringpiece_bar(kBar);
- const std::string string_bar(kBar);
- SpdyStrAppend(&output, kFoo, kBar);
- EXPECT_EQ("foobar", output);
- SpdyStrAppend(&output, kFoo, string_bar);
- EXPECT_EQ("foobarfoobar", output);
- SpdyStrAppend(&output, kFoo, stringpiece_bar);
- EXPECT_EQ("foobarfoobarfoobar", output);
- SpdyStrAppend(&output, string_foo, kBar);
- EXPECT_EQ("foobarfoobarfoobarfoobar", output);
-
- output.clear();
-
- SpdyStrAppend(&output, string_foo, string_bar);
- EXPECT_EQ("foobar", output);
- SpdyStrAppend(&output, string_foo, stringpiece_bar);
- EXPECT_EQ("foobarfoobar", output);
- SpdyStrAppend(&output, stringpiece_foo, kBar);
- EXPECT_EQ("foobarfoobarfoobar", output);
- SpdyStrAppend(&output, stringpiece_foo, string_bar);
- EXPECT_EQ("foobarfoobarfoobarfoobar", output);
-
- output.clear();
-
- SpdyStrAppend(&output, stringpiece_foo, stringpiece_bar);
- EXPECT_EQ("foobar", output);
-
- // Many-many arguments.
- SpdyStrAppend(&output, "foo", "bar", "baz", "qux", "quux", "quuz", "corge",
- "grault", "garply", "waldo", "fred", "plugh", "xyzzy", "thud");
- EXPECT_EQ(
- "foobarfoobarbazquxquuxquuzcorgegraultgarplywaldofredplughxyzzythud",
- output);
-
- output.clear();
-
- // Numerical arguments.
- const int16_t i = 1;
- const uint64_t u = 8;
- const double d = 3.1415;
-
- SpdyStrAppend(&output, i, " ", u);
- EXPECT_EQ("1 8", output);
- SpdyStrAppend(&output, d, i, i, u, i);
- EXPECT_EQ("1 83.14151181", output);
- SpdyStrAppend(&output, "i: ", i, ", u: ", u, ", d: ", d);
- EXPECT_EQ("1 83.14151181i: 1, u: 8, d: 3.1415", output);
-
- output.clear();
-
- // Boolean arguments.
- const bool t = true;
- const bool f = false;
-
- SpdyStrAppend(&output, t);
- EXPECT_EQ("1", output);
- SpdyStrAppend(&output, f);
- EXPECT_EQ("10", output);
- SpdyStrAppend(&output, f, t, t, f);
- EXPECT_EQ("100110", output);
-
- output.clear();
-
- // Mixed string-like, numerical, and Boolean arguments.
- SpdyStrAppend(&output, kFoo, i, string_foo, f, u, t, stringpiece_bar, d, t);
- EXPECT_EQ("foo1foo081bar3.14151", output);
- SpdyStrAppend(&output, d, t, t, string_bar, i, u, kBar, t, d, f);
- EXPECT_EQ("foo1foo081bar3.141513.141511bar18bar13.14150", output);
-}
-
TEST(SpdyStringUtilsTest, SpdyHexDigitToInt) {
EXPECT_EQ(0, SpdyHexDigitToInt('0'));
EXPECT_EQ(1, SpdyHexDigitToInt('1'));
@@ -168,40 +73,6 @@ TEST(SpdyStringUtilsTest, SpdyHexEncode) {
SpdyHexEncode(reinterpret_cast<char*>(bytes), sizeof(bytes)));
}
-TEST(SpdyStringUtilsTest, SpdyHexEncodeUInt32AndTrim) {
- EXPECT_EQ("0", SpdyHexEncodeUInt32AndTrim(0));
- EXPECT_EQ("1", SpdyHexEncodeUInt32AndTrim(1));
- EXPECT_EQ("a", SpdyHexEncodeUInt32AndTrim(0xA));
- EXPECT_EQ("f", SpdyHexEncodeUInt32AndTrim(0xF));
- EXPECT_EQ("a9", SpdyHexEncodeUInt32AndTrim(0xA9));
- EXPECT_EQ("9abcdef", SpdyHexEncodeUInt32AndTrim(0x9ABCDEF));
- EXPECT_EQ("12345678", SpdyHexEncodeUInt32AndTrim(0x12345678));
- EXPECT_EQ("ffffffff", SpdyHexEncodeUInt32AndTrim(0xFFFFFFFF));
- EXPECT_EQ("10000001", SpdyHexEncodeUInt32AndTrim(0x10000001));
-}
-
-TEST(SpdyStringUtilsTest, SpdyStringPieceCaseHash) {
- SpdyStringPieceCaseHash hasher;
- auto mixed = hasher("To Be Or Not To Be, That is The Question");
- auto lower = hasher("to be or not to be, that is the question");
- EXPECT_EQ(mixed, lower);
- auto lower2 = hasher("to be or not to be, that is the question");
- EXPECT_EQ(lower, lower2);
- auto different = hasher("to see or not to see, that is the question");
- EXPECT_NE(lower, different);
- EXPECT_NE(lower, hasher(""));
-}
-
-TEST(SpdyStringUtilsTest, SpdyStringPieceCaseEq) {
- SpdyStringPieceCaseEq eq;
- EXPECT_TRUE(eq("To Be Or Not To Be, That is The Question",
- "to be or not to be, that is the question"));
- EXPECT_TRUE(eq("to be or not to be, that is the question",
- "to be or not to be, that is the question"));
- EXPECT_FALSE(eq("to be or not to be, that is the question",
- "to see or not to see, that is the question"));
-}
-
} // namespace
} // namespace test
} // namespace spdy