summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche/src/quic
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-03-11 11:32:04 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-03-18 13:40:17 +0000
commit31ccca0778db85c159634478b4ec7997f6704860 (patch)
tree3d33fc3afd9d5ec95541e1bbe074a9cf8da12a0e /chromium/net/third_party/quiche/src/quic
parent248b70b82a40964d5594eb04feca0fa36716185d (diff)
downloadqtwebengine-chromium-31ccca0778db85c159634478b4ec7997f6704860.tar.gz
BASELINE: Update Chromium to 80.0.3987.136
Change-Id: I98e1649aafae85ba3a83e67af00bb27ef301db7b Reviewed-by: Jüri Valdmann <juri.valdmann@qt.io>
Diffstat (limited to 'chromium/net/third_party/quiche/src/quic')
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/chlo_extractor.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler_test.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_drain.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.h13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.cc35
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.cc21
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.h14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_simulator_test.cc86
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.cc17
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.cc63
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender_test.cc106
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.cc35
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.h18
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm_test.cc64
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/loss_detection_interface.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats_test.cc34
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h43
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc27
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.cc17
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm_test.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/windowed_filter.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aead_base_encrypter.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_decrypter_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_256_gcm_decrypter_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_decrypter_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_decrypter.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/chacha_base_encrypter.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.cc13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_printer_bin.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h21
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_server_test.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/null_decrypter.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/proof_source.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.cc13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h57
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc17
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config_test.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.cc18
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.h9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.cc32
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters_test.cc60
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_ack_frame.cc173
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_ack_frame.h13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.cc95
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_frames_test.cc145
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.h18
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/handshaker_delegate_interface.h53
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc122
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_decoder_test.cc129
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_encoder.cc84
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_encoder.h51
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_encoder_test.cc50
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_frames.h18
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_client_push_promise_index_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_header_list.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_header_list_test.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream_test.cc15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.cc13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream_test.cc43
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.cc30
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc29
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_test.cc32
-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.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_server_stream_base.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_server_stream_base_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc91
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.h29
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc232
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc137
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager_test.cc195
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc298
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/packet_number_indexed_queue.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/offline/README.md28
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.cc34
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.h19
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager_test.cc82
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.cc79
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.h82
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator_test.cc158
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.cc20
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test.cc67
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.cc60
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h27
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.cc31
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h18
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.cc110
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.h42
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder_test.cc97
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.cc18
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.h15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder_test.cc148
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instructions.cc (renamed from chromium/net/third_party/quiche/src/quic/core/qpack/qpack_constants.cc)131
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h (renamed from chromium/net/third_party/quiche/src/quic/core/qpack/qpack_constants.h)71
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_offline_decoder_bin.cc (renamed from chromium/net/third_party/quiche/src/quic/core/qpack/offline/qpack_offline_decoder_bin.cc)3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.cc28
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_round_trip_test.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_utils.h23
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list_test.cc70
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_arena_scoped_ptr.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_circular_deque.h744
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_circular_deque_test.cc790
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.cc119
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.h72
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet_test.cc114
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_config.cc62
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_config.h18
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_config_test.cc68
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection.cc925
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection.h155
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_id.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_id.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.cc53
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.h99
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc1170
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_constants.h12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc17
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.cc37
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h16
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream_test.cc86
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.cc56
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_test.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_data_reader.cc27
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_data_reader.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_data_writer.cc31
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_data_writer.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_data_writer_test.cc138
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.cc24
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_dispatcher_test.cc226
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_epoll_alarm_factory.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h23
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_framer.cc155
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_framer.h12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_framer_test.cc457
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_ietf_framer_test.cc103
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_interval.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_interval_set.h50
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_interval_set_test.cc41
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_lru_cache.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_mtu_discovery.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_one_block_arena.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.cc417
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.h91
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_creator_test.cc2160
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_generator.cc556
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_generator.h269
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_generator_test.cc1512
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_number.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_number.h19
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_writer_wrapper.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packets.cc43
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packets.h17
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packets_test.cc41
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_pending_retransmission.h54
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_process_packet_interface.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc593
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h118
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc1559
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_session.cc308
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_session.h59
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc137
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream.cc144
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream.h31
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.cc27
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer_test.cc45
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer.cc42
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer.h11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer_test.cc147
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_test.cc40
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_test.cc325
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time_accumulator.h69
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time_accumulator_test.cc82
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_transmission_info.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_transmission_info.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_types.cc69
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_types.h66
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_types_test.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.cc167
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h35
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map_test.cc195
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_utils.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_utils_test.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc16
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_version_manager_test.cc56
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_versions.cc62
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_versions.h31
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc281
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc72
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.h28
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_handshaker.cc32
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_handshaker.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_handshaker_test.cc64
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.cc23
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.h9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_cert_utils.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_endian.h54
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_endian_test.cc51
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_export.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_test.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_test_mem_slice_vector.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_text_utils.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_thread.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable_test.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/mock_packet_exchanger_stats_interface.h27
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/internet_checksum.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/ip_range.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/netlink_test.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet.cc15
-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_packet_processor.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc43
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_session_test.cc48
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint_test.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_factory.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer_test.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_packet_writer.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_session.cc30
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_session.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_session_test.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_stream_test.cc23
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.cc130
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.h62
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session_test.cc103
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_integration_test.cc331
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h15
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session_test.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_session_interface.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc112
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h72
-rw-r--r--chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream_test.cc123
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc26
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.cc (renamed from chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.cc)2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.h (renamed from chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.h)8
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.cc (renamed from chromium/net/third_party/quiche/src/quic/test_tools/qpack_encoder_peer.cc)2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.h (renamed from chromium/net/third_party/quiche/src/quic/test_tools/qpack_encoder_peer.h)6
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.cc (renamed from chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test_utils.cc)2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.h (renamed from chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test_utils.h)8
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.cc (renamed from chromium/net/third_party/quiche/src/quic/test_tools/qpack_header_table_peer.cc)2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.h (renamed from chromium/net/third_party/quiche/src/quic/test_tools/qpack_header_table_peer.h)6
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.cc (renamed from chromium/net/third_party/quiche/src/quic/core/qpack/offline/qpack_offline_decoder.cc)32
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.h (renamed from chromium/net/third_party/quiche/src/quic/core/qpack/offline/qpack_offline_decoder.h)12
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.cc (renamed from chromium/net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.cc)2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h (renamed from chromium/net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h)13
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc58
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h12
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_generator_peer.cc20
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_generator_peer.h28
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.cc22
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_peer.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_sequencer_buffer_peer.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.cc23
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.h72
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h36
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_quic_framer.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_quic_framer.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_session_cache.cc28
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_session_cache.h35
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier_test.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.cc246
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h113
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_base.cc222
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_base.h158
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_test.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client.cc43
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client.h16
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_base.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_base.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_interop_test_bin.cc127
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend_test.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_server.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_stream.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_stream.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session_test.cc63
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc42
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.cc55
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.h41
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.cc226
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.h72
393 files changed, 13971 insertions, 10522 deletions
diff --git a/chromium/net/third_party/quiche/src/quic/core/chlo_extractor.h b/chromium/net/third_party/quiche/src/quic/core/chlo_extractor.h
index 3cf0d24b3b5..89dffe16a24 100644
--- a/chromium/net/third_party/quiche/src/quic/core/chlo_extractor.h
+++ b/chromium/net/third_party/quiche/src/quic/core/chlo_extractor.h
@@ -12,9 +12,9 @@ namespace quic {
// A utility for extracting QUIC Client Hello messages from packets,
// without needs to spin up a full QuicSession.
-class ChloExtractor {
+class QUIC_NO_EXPORT ChloExtractor {
public:
- class Delegate {
+ class QUIC_NO_EXPORT Delegate {
public:
virtual ~Delegate() {}
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 19158435ac6..cc90cb00539 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
@@ -21,6 +21,7 @@ QuicByteCount MaxAckHeightTracker::Update(QuicBandwidth bandwidth_estimate,
if (aggregation_epoch_start_time_ == QuicTime::Zero()) {
aggregation_epoch_bytes_ = bytes_acked;
aggregation_epoch_start_time_ = ack_time;
+ ++num_ack_aggregation_epochs_;
return 0;
}
@@ -30,10 +31,13 @@ QuicByteCount MaxAckHeightTracker::Update(QuicBandwidth bandwidth_estimate,
bandwidth_estimate * (ack_time - aggregation_epoch_start_time_);
// Reset the current aggregation epoch as soon as the ack arrival rate is less
// than or equal to the max bandwidth.
- if (aggregation_epoch_bytes_ <= expected_bytes_acked) {
+ if (aggregation_epoch_bytes_ <=
+ GetQuicFlag(FLAGS_quic_ack_aggregation_bandwidth_threshold) *
+ expected_bytes_acked) {
// Reset to start measuring a new aggregation epoch.
aggregation_epoch_bytes_ = bytes_acked;
aggregation_epoch_start_time_ = ack_time;
+ ++num_ack_aggregation_epochs_;
return 0;
}
@@ -195,7 +199,7 @@ BandwidthSample BandwidthSampler::OnPacketAcknowledgedInner(
} else {
QUIC_CODE_COUNT_N(quic_prev_ack_time_larger_than_current_ack_time, 2, 2);
}
- QUIC_LOG_EVERY_N_SEC(ERROR, 5)
+ QUIC_LOG_EVERY_N_SEC(ERROR, 60)
<< "Time of the previously acked packet:"
<< sent_packet.last_acked_packet_ack_time.ToDebuggingValue()
<< " is larger than the ack time of the current packet:"
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h
index 5bbb6ba7487..51f5e870819 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h
@@ -100,6 +100,10 @@ class QUIC_EXPORT_PRIVATE MaxAckHeightTracker {
max_ack_height_filter_.Reset(new_height, new_time);
}
+ uint64_t num_ack_aggregation_epochs() const {
+ return num_ack_aggregation_epochs_;
+ }
+
private:
// Tracks the maximum number of bytes acked faster than the estimated
// bandwidth.
@@ -113,6 +117,9 @@ class QUIC_EXPORT_PRIVATE MaxAckHeightTracker {
// The time this aggregation started and the number of bytes acked during it.
QuicTime aggregation_epoch_start_time_ = QuicTime::Zero();
QuicByteCount aggregation_epoch_bytes_ = 0;
+ // The number of ack aggregation epochs ever started, including the ongoing
+ // one. Stats only.
+ uint64_t num_ack_aggregation_epochs_ = 0;
};
// An interface common to any class that can provide bandwidth samples from the
@@ -273,6 +280,10 @@ class QUIC_EXPORT_PRIVATE BandwidthSampler : public BandwidthSamplerInterface {
QuicByteCount max_ack_height() const { return max_ack_height_tracker_.Get(); }
+ uint64_t num_ack_aggregation_epochs() const {
+ return max_ack_height_tracker_.num_ack_aggregation_epochs();
+ }
+
void SetMaxAckHeightTrackerWindowLength(QuicRoundTripCount length) {
max_ack_height_tracker_.SetFilterWindowLength(length);
}
@@ -289,7 +300,7 @@ class QUIC_EXPORT_PRIVATE BandwidthSampler : public BandwidthSamplerInterface {
// and the state of the connection at the moment the packet was sent,
// specifically the information about the most recently acknowledged packet at
// that moment.
- struct ConnectionStateOnSentPacket {
+ struct QUIC_EXPORT_PRIVATE ConnectionStateOnSentPacket {
// Time at which the packet is sent.
QuicTime sent_time;
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler_test.cc
index 558971aab69..59318a98590 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler_test.cc
@@ -551,6 +551,7 @@ TEST_F(MaxAckHeightTrackerTest, VeryAggregatedLargeAck) {
AggregationEpisode(bandwidth_ * 20, QuicTime::Delta::FromMilliseconds(6),
1200, false);
+ EXPECT_EQ(2u, tracker_.num_ack_aggregation_epochs());
}
TEST_F(MaxAckHeightTrackerTest, VeryAggregatedSmallAcks) {
@@ -562,6 +563,7 @@ TEST_F(MaxAckHeightTrackerTest, VeryAggregatedSmallAcks) {
AggregationEpisode(bandwidth_ * 20, QuicTime::Delta::FromMilliseconds(6), 300,
false);
+ EXPECT_EQ(2u, tracker_.num_ack_aggregation_epochs());
}
TEST_F(MaxAckHeightTrackerTest, SomewhatAggregatedLargeAck) {
@@ -573,6 +575,7 @@ TEST_F(MaxAckHeightTrackerTest, SomewhatAggregatedLargeAck) {
AggregationEpisode(bandwidth_ * 2, QuicTime::Delta::FromMilliseconds(50),
1000, false);
+ EXPECT_EQ(2u, tracker_.num_ack_aggregation_epochs());
}
TEST_F(MaxAckHeightTrackerTest, SomewhatAggregatedSmallAcks) {
@@ -584,11 +587,13 @@ TEST_F(MaxAckHeightTrackerTest, SomewhatAggregatedSmallAcks) {
AggregationEpisode(bandwidth_ * 2, QuicTime::Delta::FromMilliseconds(50), 100,
false);
+ EXPECT_EQ(2u, tracker_.num_ack_aggregation_epochs());
}
TEST_F(MaxAckHeightTrackerTest, NotAggregated) {
AggregationEpisode(bandwidth_, QuicTime::Delta::FromMilliseconds(100), 100,
true);
+ EXPECT_LT(2u, tracker_.num_ack_aggregation_epochs());
}
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_drain.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_drain.h
index 546962bfc1f..e083aeb655b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_drain.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_drain.h
@@ -18,6 +18,7 @@ class QUIC_EXPORT_PRIVATE Bbr2DrainMode final : public Bbr2ModeBase {
using Bbr2ModeBase::Bbr2ModeBase;
void Enter(const Bbr2CongestionEvent& congestion_event) override;
+ void Leave(const Bbr2CongestionEvent& /*congestion_event*/) override {}
Bbr2Mode OnCongestionEvent(
QuicByteCount prior_in_flight,
@@ -32,7 +33,7 @@ class QUIC_EXPORT_PRIVATE Bbr2DrainMode final : public Bbr2ModeBase {
bool IsProbingForBandwidth() const override { return false; }
- struct DebugState {
+ struct QUIC_EXPORT_PRIVATE DebugState {
QuicByteCount drain_target;
};
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 d5b2742ec0d..8f08a58c6fc 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
@@ -331,6 +331,10 @@ class QUIC_EXPORT_PRIVATE Bbr2NetworkModel {
return bandwidth_sampler_.max_ack_height();
}
+ uint64_t num_ack_aggregation_epochs() const {
+ return bandwidth_sampler_.num_ack_aggregation_epochs();
+ }
+
bool MaybeExpireMinRtt(const Bbr2CongestionEvent& congestion_event);
QuicBandwidth BandwidthEstimate() const {
@@ -372,7 +376,10 @@ class QUIC_EXPORT_PRIVATE Bbr2NetworkModel {
QuicBandwidth bandwidth_latest() const { return bandwidth_latest_; }
QuicBandwidth bandwidth_lo() const { return bandwidth_lo_; }
- void clear_bandwidth_lo() { bandwidth_lo_ = QuicBandwidth::Infinite(); }
+ static QuicBandwidth bandwidth_lo_default() {
+ return QuicBandwidth::Infinite();
+ }
+ void clear_bandwidth_lo() { bandwidth_lo_ = bandwidth_lo_default(); }
QuicByteCount inflight_latest() const { return inflight_latest_; }
QuicByteCount inflight_lo() const { return inflight_lo_; }
@@ -420,7 +427,7 @@ class QUIC_EXPORT_PRIVATE Bbr2NetworkModel {
// Max bandwidth in the current round. Updated once per congestion event.
QuicBandwidth bandwidth_latest_ = QuicBandwidth::Zero();
// Max bandwidth of recent rounds. Updated once per round.
- QuicBandwidth bandwidth_lo_ = QuicBandwidth::Infinite();
+ QuicBandwidth bandwidth_lo_ = bandwidth_lo_default();
// Max inflight in the current round. Updated once per congestion event.
QuicByteCount inflight_latest_ = 0;
@@ -470,7 +477,9 @@ class QUIC_EXPORT_PRIVATE Bbr2ModeBase {
virtual ~Bbr2ModeBase() = default;
+ // Called when entering/leaving this mode.
virtual void Enter(const Bbr2CongestionEvent& congestion_event) = 0;
+ virtual void Leave(const Bbr2CongestionEvent& congestion_event) = 0;
virtual Bbr2Mode OnCongestionEvent(
QuicByteCount prior_in_flight,
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 887d553371f..4487cbf879b 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
@@ -48,6 +48,8 @@ Bbr2Mode Bbr2ProbeBwMode::OnCongestionEvent(
}
}
+ bool switch_to_probe_rtt = false;
+
if (cycle_.phase == CyclePhase::PROBE_UP) {
UpdateProbeUp(prior_in_flight, congestion_event);
} else if (cycle_.phase == CyclePhase::PROBE_DOWN) {
@@ -55,7 +57,7 @@ Bbr2Mode Bbr2ProbeBwMode::OnCongestionEvent(
// Maybe transition to PROBE_RTT at the end of this cycle.
if (cycle_.phase != CyclePhase::PROBE_DOWN &&
model_->MaybeExpireMinRtt(congestion_event)) {
- return Bbr2Mode::PROBE_RTT;
+ switch_to_probe_rtt = true;
}
} else if (cycle_.phase == CyclePhase::PROBE_CRUISE) {
UpdateProbeCruise(congestion_event);
@@ -63,10 +65,14 @@ Bbr2Mode Bbr2ProbeBwMode::OnCongestionEvent(
UpdateProbeRefill(congestion_event);
}
- model_->set_pacing_gain(PacingGainForPhase(cycle_.phase));
- model_->set_cwnd_gain(Params().probe_bw_cwnd_gain);
+ // Do not need to set the gains if switching to PROBE_RTT, they will be set
+ // when Bbr2ProbeRttMode::Enter is called.
+ if (!switch_to_probe_rtt) {
+ model_->set_pacing_gain(PacingGainForPhase(cycle_.phase));
+ model_->set_cwnd_gain(Params().probe_bw_cwnd_gain);
+ }
- return Bbr2Mode::PROBE_BW;
+ return switch_to_probe_rtt ? Bbr2Mode::PROBE_RTT : Bbr2Mode::PROBE_BW;
}
Limits<QuicByteCount> Bbr2ProbeBwMode::GetCwndLimits() const {
@@ -194,6 +200,15 @@ bool Bbr2ProbeBwMode::IsTimeToProbeBandwidth(
// long, as seen in some multi-sender simulator tests.
bool Bbr2ProbeBwMode::HasStayedLongEnoughInProbeDown(
const Bbr2CongestionEvent& congestion_event) const {
+ if (exit_probe_down_after_one_rtt_) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_bbr2_exit_probe_bw_down_after_one_rtt);
+ // Stay in PROBE_DOWN for at most the time of a min rtt, as it is done in
+ // BBRv1. The intention here is to figure out whether the performance
+ // regression in BBRv2 is because it stays in PROBE_DOWN for too long.
+ // TODO(wub): Consider exit after a full round instead, which typically
+ // indicates most(if not all) packets sent during PROBE_UP have been acked.
+ return HasPhaseLasted(model_->MinRtt(), congestion_event);
+ }
// The amount of time to stay in PROBE_DOWN, as a fraction of probe wait time.
const double kProbeWaitFraction = 0.2;
return HasCycleLasted(cycle_.probe_wait_time * kProbeWaitFraction,
@@ -271,9 +286,7 @@ void Bbr2ProbeBwMode::ProbeInflightHighUpward(
return;
}
- if (GetQuicReloadableFlag(quic_bbr2_fix_inflight_bounds) &&
- congestion_event.prior_cwnd < model_->inflight_hi()) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_fix_inflight_bounds, 1, 2);
+ if (congestion_event.prior_cwnd < model_->inflight_hi()) {
QUIC_DVLOG(3)
<< sender_
<< " Raising inflight_hi early return: inflight_hi not fully used.";
@@ -296,7 +309,7 @@ void Bbr2ProbeBwMode::ProbeInflightHighUpward(
<< ", (new)probe_up_acked:" << cycle_.probe_up_acked;
model_->set_inflight_hi(new_inflight_hi);
- } else if (GetQuicReloadableFlag(quic_bbr2_fix_inflight_bounds)) {
+ } else {
QUIC_BUG << "Not growing inflight_hi due to wrap around. Old value:"
<< model_->inflight_hi() << ", new value:" << new_inflight_hi;
}
@@ -417,10 +430,8 @@ void Bbr2ProbeBwMode::EnterProbeCruise(
<< congestion_event.event_time - cycle_.phase_start_time
<< ", or " << cycle_.rounds_in_phase << " rounds. @ "
<< congestion_event.event_time;
- if (GetQuicReloadableFlag(quic_bbr2_fix_inflight_bounds)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_fix_inflight_bounds, 2, 2);
- model_->cap_inflight_lo(model_->inflight_hi());
- }
+
+ model_->cap_inflight_lo(model_->inflight_hi());
cycle_.phase = CyclePhase::PROBE_CRUISE;
cycle_.rounds_in_phase = 0;
cycle_.phase_start_time = congestion_event.event_time;
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.h
index 407056b5f49..45b5a73835e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.h
@@ -11,6 +11,7 @@
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
namespace quic {
@@ -20,6 +21,7 @@ class QUIC_EXPORT_PRIVATE Bbr2ProbeBwMode final : public Bbr2ModeBase {
using Bbr2ModeBase::Bbr2ModeBase;
void Enter(const Bbr2CongestionEvent& congestion_event) override;
+ void Leave(const Bbr2CongestionEvent& /*congestion_event*/) override {}
Bbr2Mode OnCongestionEvent(
QuicByteCount prior_in_flight,
@@ -42,7 +44,7 @@ class QUIC_EXPORT_PRIVATE Bbr2ProbeBwMode final : public Bbr2ModeBase {
static const char* CyclePhaseToString(CyclePhase phase);
- struct DebugState {
+ struct QUIC_EXPORT_PRIVATE DebugState {
CyclePhase phase;
QuicTime cycle_start_time = QuicTime::Zero();
QuicTime phase_start_time = QuicTime::Zero();
@@ -102,7 +104,7 @@ class QUIC_EXPORT_PRIVATE Bbr2ProbeBwMode final : public Bbr2ModeBase {
void RaiseInflightHighSlope();
void ProbeInflightHighUpward(const Bbr2CongestionEvent& congestion_event);
- struct Cycle {
+ struct QUIC_EXPORT_PRIVATE Cycle {
QuicTime cycle_start_time = QuicTime::Zero();
CyclePhase phase = CyclePhase::PROBE_NOT_STARTED;
uint64_t rounds_in_phase = 0;
@@ -120,6 +122,10 @@ class QUIC_EXPORT_PRIVATE Bbr2ProbeBwMode final : public Bbr2ModeBase {
bool last_cycle_probed_too_high_;
bool last_cycle_stopped_risky_probe_;
+
+ // Latched value of --quic_bbr2_exit_probe_bw_down_after_one_rtt.
+ const bool exit_probe_down_after_one_rtt_ =
+ GetQuicReloadableFlag(quic_bbr2_exit_probe_bw_down_after_one_rtt);
};
QUIC_EXPORT_PRIVATE std::ostream& operator<<(
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.cc
index fe4506b5bc0..f9c77097324 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.cc
@@ -26,6 +26,12 @@ Bbr2Mode Bbr2ProbeRttMode::OnCongestionEvent(
congestion_event.bytes_in_flight <=
sender_->GetMinimumCongestionWindow()) {
exit_time_ = congestion_event.event_time + Params().probe_rtt_duration;
+ QUIC_DVLOG(2) << sender_ << " PROBE_RTT exit time set to " << exit_time_
+ << ". bytes_inflight:" << congestion_event.bytes_in_flight
+ << ", inflight_target:" << InflightTarget()
+ << ", min_congestion_window:"
+ << sender_->GetMinimumCongestionWindow() << " @ "
+ << congestion_event.event_time;
}
return Bbr2Mode::PROBE_RTT;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.h
index 811c6467fa0..80a9d93d423 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.h
@@ -18,6 +18,7 @@ class QUIC_EXPORT_PRIVATE Bbr2ProbeRttMode final : public Bbr2ModeBase {
using Bbr2ModeBase::Bbr2ModeBase;
void Enter(const Bbr2CongestionEvent& congestion_event) override;
+ void Leave(const Bbr2CongestionEvent& /*congestion_event*/) override {}
Bbr2Mode OnCongestionEvent(
QuicByteCount prior_in_flight,
@@ -30,7 +31,7 @@ class QUIC_EXPORT_PRIVATE Bbr2ProbeRttMode final : public Bbr2ModeBase {
bool IsProbingForBandwidth() const override { return false; }
- struct DebugState {
+ struct QUIC_EXPORT_PRIVATE DebugState {
QuicByteCount inflight_target;
QuicTime exit_time = QuicTime::Zero();
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.cc
index 9cd40b93621..31bf29946e5 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
@@ -57,11 +57,12 @@ Bbr2Sender::Bbr2Sender(QuicTime now,
QuicPacketCount initial_cwnd_in_packets,
QuicPacketCount max_cwnd_in_packets,
QuicRandom* random,
- QuicConnectionStats* /*stats*/)
+ QuicConnectionStats* stats)
: mode_(Bbr2Mode::STARTUP),
rtt_stats_(rtt_stats),
unacked_packets_(unacked_packets),
random_(random),
+ connection_stats_(stats),
params_(kDefaultMinimumCongestionWindow,
max_cwnd_in_packets * kDefaultTCPMSS),
model_(&params_,
@@ -75,7 +76,7 @@ Bbr2Sender::Bbr2Sender(QuicTime now,
pacing_rate_(kInitialPacingGain * QuicBandwidth::FromBytesAndTimeDelta(
cwnd_,
rtt_stats->SmoothedOrInitialRtt())),
- startup_(this, &model_),
+ startup_(this, &model_, now),
drain_(this, &model_),
probe_bw_(this, &model_),
probe_rtt_(this, &model_),
@@ -114,10 +115,8 @@ const Limits<QuicByteCount>& Bbr2Sender::cwnd_limits() const {
return params_.cwnd_limits;
}
-void Bbr2Sender::AdjustNetworkParameters(QuicBandwidth bandwidth,
- QuicTime::Delta rtt,
- bool allow_cwnd_to_decrease) {
- model_.UpdateNetworkParameters(bandwidth, rtt);
+void Bbr2Sender::AdjustNetworkParameters(const NetworkParams& params) {
+ model_.UpdateNetworkParameters(params.bandwidth, params.rtt);
if (mode_ == Bbr2Mode::STARTUP) {
const QuicByteCount prior_cwnd = cwnd_;
@@ -127,7 +126,7 @@ void Bbr2Sender::AdjustNetworkParameters(QuicBandwidth bandwidth,
// we are reducing the number of updates needed to arrive at the target.
cwnd_ = model_.BDP(model_.BandwidthEstimate());
UpdateCongestionWindow(0);
- if (!allow_cwnd_to_decrease) {
+ if (!params.allow_cwnd_to_decrease) {
cwnd_ = std::max(cwnd_, prior_cwnd);
}
}
@@ -170,6 +169,7 @@ void Bbr2Sender::OnCongestionEvent(bool /*rtt_updated*/,
QUIC_DVLOG(2) << this << " Mode change: " << mode_ << " ==> " << next_mode
<< " @ " << event_time;
+ BBR2_MODE_DISPATCH(Leave(congestion_event));
mode_ = next_mode;
BBR2_MODE_DISPATCH(Enter(congestion_event));
--mode_changes_allowed;
@@ -311,6 +311,10 @@ void Bbr2Sender::OnApplicationLimited(QuicByteCount bytes_in_flight) {
<< ", CWND: " << GetCongestionWindow();
}
+void Bbr2Sender::PopulateConnectionStats(QuicConnectionStats* stats) const {
+ stats->num_ack_aggregation_epochs = model_.num_ack_aggregation_epochs();
+}
+
bool Bbr2Sender::ShouldSendProbingPacket() const {
// TODO(wub): Implement ShouldSendProbingPacket properly.
if (!BBR2_MODE_DISPATCH(IsProbingForBandwidth())) {
@@ -363,6 +367,9 @@ Bbr2Sender::DebugState Bbr2Sender::ExportDebugState() const {
s.bandwidth_hi = model_.MaxBandwidth();
s.bandwidth_lo = model_.bandwidth_lo();
s.bandwidth_est = BandwidthEstimate();
+ s.inflight_hi = model_.inflight_hi();
+ s.inflight_lo = model_.inflight_lo();
+ s.max_ack_height = model_.MaxAckHeight();
s.min_rtt = model_.MinRtt();
s.min_rtt_timestamp = model_.MinRttTimestamp();
s.congestion_window = cwnd_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.h
index b58dd93e271..4cfd34c74c7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.h
@@ -30,7 +30,7 @@ class QUIC_EXPORT_PRIVATE Bbr2Sender final : public SendAlgorithmInterface {
QuicPacketCount initial_cwnd_in_packets,
QuicPacketCount max_cwnd_in_packets,
QuicRandom* random,
- QuicConnectionStats* /*stats*/);
+ QuicConnectionStats* stats);
~Bbr2Sender() override = default;
@@ -47,9 +47,7 @@ class QUIC_EXPORT_PRIVATE Bbr2Sender final : public SendAlgorithmInterface {
void SetFromConfig(const QuicConfig& config,
Perspective perspective) override;
- void AdjustNetworkParameters(QuicBandwidth bandwidth,
- QuicTime::Delta rtt,
- bool allow_cwnd_to_decrease) override;
+ void AdjustNetworkParameters(const NetworkParams& params) override;
void SetInitialCongestionWindowInPackets(
QuicPacketCount congestion_window) override;
@@ -89,6 +87,8 @@ class QUIC_EXPORT_PRIVATE Bbr2Sender final : public SendAlgorithmInterface {
std::string GetDebugState() const override;
void OnApplicationLimited(QuicByteCount bytes_in_flight) override;
+
+ void PopulateConnectionStats(QuicConnectionStats* stats) const override;
// End implementation of SendAlgorithmInterface.
const Bbr2Params& Params() const { return params_; }
@@ -97,7 +97,7 @@ class QUIC_EXPORT_PRIVATE Bbr2Sender final : public SendAlgorithmInterface {
return cwnd_limits().Min();
}
- struct DebugState {
+ struct QUIC_EXPORT_PRIVATE DebugState {
Bbr2Mode mode;
// Shared states.
@@ -105,6 +105,9 @@ class QUIC_EXPORT_PRIVATE Bbr2Sender final : public SendAlgorithmInterface {
QuicBandwidth bandwidth_hi = QuicBandwidth::Zero();
QuicBandwidth bandwidth_lo = QuicBandwidth::Zero();
QuicBandwidth bandwidth_est = QuicBandwidth::Zero();
+ QuicByteCount inflight_hi;
+ QuicByteCount inflight_lo;
+ QuicByteCount max_ack_height;
QuicTime::Delta min_rtt = QuicTime::Delta::Zero();
QuicTime min_rtt_timestamp = QuicTime::Zero();
QuicByteCount congestion_window;
@@ -156,6 +159,7 @@ class QUIC_EXPORT_PRIVATE Bbr2Sender final : public SendAlgorithmInterface {
const RttStats* const rtt_stats_;
const QuicUnackedPacketMap* const unacked_packets_;
QuicRandom* random_;
+ QuicConnectionStats* connection_stats_;
const Bbr2Params params_;
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 71f3048198a..005e11deae7 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
@@ -24,6 +24,10 @@
#include "net/third_party/quiche/src/quic/test_tools/simulator/switch.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/traffic_policer.h"
+using testing::AllOf;
+using testing::Ge;
+using testing::Le;
+
namespace quic {
using CyclePhase = Bbr2ProbeBwMode::CyclePhase;
@@ -135,9 +139,13 @@ class Bbr2DefaultTopologyTest : public Bbr2SimulatorTest {
~Bbr2DefaultTopologyTest() {
const auto* test_info =
::testing::UnitTest::GetInstance()->current_test_info();
+ const Bbr2Sender::DebugState& debug_state = sender_->ExportDebugState();
QUIC_LOG(INFO) << "Bbr2DefaultTopologyTest." << test_info->name()
<< " completed at simulated time: "
- << SimulatedNow().ToDebuggingValue() / 1e6 << " sec.";
+ << SimulatedNow().ToDebuggingValue() / 1e6
+ << " sec. packet loss:"
+ << sender_loss_rate_in_packets() * 100
+ << "%, bw_hi:" << debug_state.bandwidth_hi;
}
Bbr2Sender* SetupBbr2Sender(simulator::QuicEndpoint* endpoint) {
@@ -147,8 +155,9 @@ class Bbr2DefaultTopologyTest : public Bbr2SimulatorTest {
endpoint->connection()->sent_packet_manager().GetRttStats(),
QuicSentPacketManagerPeer::GetUnackedPacketMap(
QuicConnectionPeer::GetSentPacketManager(endpoint->connection())),
- kDefaultInitialCwndPackets, kDefaultMaxCongestionWindowPackets,
- &random_, QuicConnectionPeer::GetStats(endpoint->connection()));
+ kDefaultInitialCwndPackets,
+ GetQuicFlag(FLAGS_quic_max_congestion_window), &random_,
+ QuicConnectionPeer::GetStats(endpoint->connection()));
QuicConnectionPeer::SetSendAlgorithm(endpoint->connection(), sender);
endpoint->RecordTrace();
return sender;
@@ -413,7 +422,7 @@ TEST_F(Bbr2DefaultTopologyTest, SimpleTransferAckDecimation) {
}
// Test Bbr2's reaction to a 100x bandwidth decrease during a transfer.
-TEST_F(Bbr2DefaultTopologyTest, BandwidthDecrease) {
+TEST_F(Bbr2DefaultTopologyTest, QUIC_SLOW_TEST(BandwidthDecrease)) {
DefaultTopologyParams params;
params.local_link.bandwidth = QuicBandwidth::FromKBitsPerSecond(15000);
params.test_link.bandwidth = QuicBandwidth::FromKBitsPerSecond(10000);
@@ -442,7 +451,7 @@ TEST_F(Bbr2DefaultTopologyTest, BandwidthDecrease) {
}
// Test Bbr2's reaction to a 100x bandwidth increase during a transfer.
-TEST_F(Bbr2DefaultTopologyTest, BandwidthIncrease) {
+TEST_F(Bbr2DefaultTopologyTest, QUIC_SLOW_TEST(BandwidthIncrease)) {
DefaultTopologyParams params;
params.local_link.bandwidth = QuicBandwidth::FromKBitsPerSecond(15000);
params.test_link.bandwidth = QuicBandwidth::FromKBitsPerSecond(100);
@@ -668,7 +677,26 @@ TEST_F(Bbr2DefaultTopologyTest, SenderPoliced) {
EXPECT_TRUE(Bbr2ModeIsOneOf({Bbr2Mode::PROBE_BW, Bbr2Mode::PROBE_RTT}));
// TODO(wub): Fix (long-term) bandwidth overestimation in policer mode, then
// reduce the loss rate upper bound.
- EXPECT_LE(sender_loss_rate_in_packets(), 0.15);
+ EXPECT_LE(sender_loss_rate_in_packets(), 0.30);
+}
+
+// TODO(wub): Add other slowstart stats to BBRv2.
+TEST_F(Bbr2DefaultTopologyTest, StartupStats) {
+ DefaultTopologyParams params;
+ CreateNetwork(params);
+
+ DriveOutOfStartup(params);
+ ASSERT_FALSE(sender_->InSlowStart());
+
+ const QuicConnectionStats& stats = sender_connection_stats();
+ EXPECT_EQ(1u, stats.slowstart_count);
+ EXPECT_FALSE(stats.slowstart_duration.IsRunning());
+ EXPECT_THAT(stats.slowstart_duration.GetTotalElapsedTime(),
+ AllOf(Ge(QuicTime::Delta::FromMilliseconds(500)),
+ Le(QuicTime::Delta::FromMilliseconds(1500))));
+ EXPECT_EQ(stats.slowstart_duration.GetTotalElapsedTime(),
+ QuicConnectionPeer::GetSentPacketManager(sender_connection())
+ ->GetSlowStartDuration());
}
// All Bbr2MultiSenderTests uses the following network topology:
@@ -741,7 +769,7 @@ class Bbr2MultiSenderTest : public Bbr2SimulatorTest {
protected:
Bbr2MultiSenderTest() {
uint64_t first_connection_id = 42;
- std::vector<simulator::QuicEndpoint*> receiver_endpoint_pointers;
+ std::vector<simulator::QuicEndpointBase*> receiver_endpoint_pointers;
for (size_t i = 0; i < MultiSenderTopologyParams::kNumLocalLinks; ++i) {
std::string sender_name = QuicStrCat("Sender", i + 1);
std::string receiver_name = QuicStrCat("Receiver", i + 1);
@@ -770,7 +798,17 @@ class Bbr2MultiSenderTest : public Bbr2SimulatorTest {
::testing::UnitTest::GetInstance()->current_test_info();
QUIC_LOG(INFO) << "Bbr2MultiSenderTest." << test_info->name()
<< " completed at simulated time: "
- << SimulatedNow().ToDebuggingValue() / 1e6 << " sec.";
+ << SimulatedNow().ToDebuggingValue() / 1e6
+ << " sec. Per sender stats:";
+ for (size_t i = 0; i < sender_endpoints_.size(); ++i) {
+ QUIC_LOG(INFO) << "sender[" << i << "]: "
+ << sender_connection(i)
+ ->sent_packet_manager()
+ .GetSendAlgorithm()
+ ->GetCongestionControlType()
+ << ", packet_loss:"
+ << 100.0 * sender_loss_rate_in_packets(i) << "%";
+ }
}
Bbr2Sender* SetupBbr2Sender(simulator::QuicEndpoint* endpoint) {
@@ -780,8 +818,9 @@ class Bbr2MultiSenderTest : public Bbr2SimulatorTest {
endpoint->connection()->sent_packet_manager().GetRttStats(),
QuicSentPacketManagerPeer::GetUnackedPacketMap(
QuicConnectionPeer::GetSentPacketManager(endpoint->connection())),
- kDefaultInitialCwndPackets, kDefaultMaxCongestionWindowPackets,
- &random_, QuicConnectionPeer::GetStats(endpoint->connection()));
+ kDefaultInitialCwndPackets,
+ GetQuicFlag(FLAGS_quic_max_congestion_window), &random_,
+ QuicConnectionPeer::GetStats(endpoint->connection()));
QuicConnectionPeer::SetSendAlgorithm(endpoint->connection(), sender);
endpoint->RecordTrace();
return sender;
@@ -794,8 +833,9 @@ class Bbr2MultiSenderTest : public Bbr2SimulatorTest {
endpoint->connection()->sent_packet_manager().GetRttStats(),
QuicSentPacketManagerPeer::GetUnackedPacketMap(
QuicConnectionPeer::GetSentPacketManager(endpoint->connection())),
- kDefaultInitialCwndPackets, kDefaultMaxCongestionWindowPackets,
- &random_, QuicConnectionPeer::GetStats(endpoint->connection()));
+ kDefaultInitialCwndPackets,
+ GetQuicFlag(FLAGS_quic_max_congestion_window), &random_,
+ QuicConnectionPeer::GetStats(endpoint->connection()));
QuicConnectionPeer::SetSendAlgorithm(endpoint->connection(), sender);
endpoint->RecordTrace();
return sender;
@@ -808,7 +848,8 @@ class Bbr2MultiSenderTest : public Bbr2SimulatorTest {
TcpCubicSenderBytes* sender = new TcpCubicSenderBytes(
endpoint->connection()->clock(),
endpoint->connection()->sent_packet_manager().GetRttStats(), reno,
- kDefaultInitialCwndPackets, kDefaultMaxCongestionWindowPackets,
+ kDefaultInitialCwndPackets,
+ GetQuicFlag(FLAGS_quic_max_congestion_window),
QuicConnectionPeer::GetStats(endpoint->connection()));
QuicConnectionPeer::SetSendAlgorithm(endpoint->connection(), sender);
endpoint->RecordTrace();
@@ -834,6 +875,19 @@ class Bbr2MultiSenderTest : public Bbr2SimulatorTest {
QuicTime SimulatedNow() const { return simulator_.GetClock()->Now(); }
+ QuicConnection* sender_connection(size_t which) {
+ return sender_endpoints_[which]->connection();
+ }
+
+ const QuicConnectionStats& sender_connection_stats(size_t which) {
+ return sender_connection(which)->GetStats();
+ }
+
+ float sender_loss_rate_in_packets(size_t which) {
+ return static_cast<float>(sender_connection_stats(which).packets_lost) /
+ sender_connection_stats(which).packets_sent;
+ }
+
simulator::Simulator simulator_;
std::vector<std::unique_ptr<simulator::QuicEndpoint>> sender_endpoints_;
std::vector<std::unique_ptr<simulator::QuicEndpoint>> receiver_endpoints_;
@@ -876,7 +930,7 @@ TEST_F(Bbr2MultiSenderTest, Bbr2VsBbr2) {
ASSERT_TRUE(simulator_result);
}
-TEST_F(Bbr2MultiSenderTest, MultipleBbr2s) {
+TEST_F(Bbr2MultiSenderTest, QUIC_SLOW_TEST(MultipleBbr2s)) {
const int kTotalNumSenders = 6;
for (int i = 1; i < kTotalNumSenders; ++i) {
SetupBbr2Sender(sender_endpoints_[i].get());
@@ -992,7 +1046,7 @@ TEST_F(Bbr2MultiSenderTest, Bbr2VsBbr1) {
ASSERT_TRUE(simulator_result);
}
-TEST_F(Bbr2MultiSenderTest, Bbr2VsReno) {
+TEST_F(Bbr2MultiSenderTest, QUIC_SLOW_TEST(Bbr2VsReno)) {
SetupTcpSender(sender_endpoints_[1].get(), /*reno=*/true);
MultiSenderTopologyParams params;
@@ -1023,7 +1077,7 @@ TEST_F(Bbr2MultiSenderTest, Bbr2VsReno) {
ASSERT_TRUE(simulator_result);
}
-TEST_F(Bbr2MultiSenderTest, Bbr2VsCubic) {
+TEST_F(Bbr2MultiSenderTest, QUIC_SLOW_TEST(Bbr2VsCubic)) {
SetupTcpSender(sender_endpoints_[1].get(), /*reno=*/false);
MultiSenderTopologyParams 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 5ff10503025..187b349b327 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
@@ -12,17 +12,30 @@
namespace quic {
Bbr2StartupMode::Bbr2StartupMode(const Bbr2Sender* sender,
- Bbr2NetworkModel* model)
+ Bbr2NetworkModel* model,
+ QuicTime now)
: Bbr2ModeBase(sender, model),
full_bandwidth_reached_(false),
full_bandwidth_baseline_(QuicBandwidth::Zero()),
rounds_without_bandwidth_growth_(0),
- loss_events_in_round_(0) {}
+ loss_events_in_round_(0) {
+ // Clear some startup stats if |sender_->connection_stats_| has been used by
+ // another sender, which happens e.g. when QuicConnection switch send
+ // algorithms.
+ sender_->connection_stats_->slowstart_count = 1;
+ sender_->connection_stats_->slowstart_duration = QuicTimeAccumulator();
+ sender_->connection_stats_->slowstart_duration.Start(now);
+}
void Bbr2StartupMode::Enter(const Bbr2CongestionEvent& /*congestion_event*/) {
QUIC_BUG << "Bbr2StartupMode::Enter should not be called";
}
+void Bbr2StartupMode::Leave(const Bbr2CongestionEvent& congestion_event) {
+ sender_->connection_stats_->slowstart_duration.Stop(
+ congestion_event.event_time);
+}
+
Bbr2Mode Bbr2StartupMode::OnCongestionEvent(
QuicByteCount /*prior_in_flight*/,
QuicTime /*event_time*/,
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.h
index df3f9a747c7..80539d9a108 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_startup.h
@@ -16,9 +16,12 @@ namespace quic {
class Bbr2Sender;
class QUIC_EXPORT_PRIVATE Bbr2StartupMode final : public Bbr2ModeBase {
public:
- Bbr2StartupMode(const Bbr2Sender* sender, Bbr2NetworkModel* model);
+ Bbr2StartupMode(const Bbr2Sender* sender,
+ Bbr2NetworkModel* model,
+ QuicTime now);
void Enter(const Bbr2CongestionEvent& congestion_event) override;
+ void Leave(const Bbr2CongestionEvent& congestion_event) override;
Bbr2Mode OnCongestionEvent(
QuicByteCount prior_in_flight,
@@ -35,7 +38,7 @@ class QUIC_EXPORT_PRIVATE Bbr2StartupMode final : public Bbr2ModeBase {
bool FullBandwidthReached() const { return full_bandwidth_reached_; }
- struct DebugState {
+ struct QUIC_EXPORT_PRIVATE DebugState {
bool full_bandwidth_reached;
QuicBandwidth full_bandwidth_baseline = QuicBandwidth::Zero();
QuicRoundTripCount round_trips_without_bandwidth_growth;
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.cc
index b0fd50d4c8b..0096ca5b095 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.cc
@@ -11,6 +11,7 @@
#include "net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
+#include "net/third_party/quiche/src/quic/core/quic_time_accumulator.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_fallthrough.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
@@ -136,8 +137,10 @@ BbrSender::BbrSender(QuicTime now,
app_limited_since_last_probe_rtt_(false),
min_rtt_since_last_probe_rtt_(QuicTime::Delta::Infinite()) {
if (stats_) {
+ // Clear some startup stats if |stats_| has been used by another sender,
+ // which happens e.g. when QuicConnection switch send algorithms.
stats_->slowstart_count = 0;
- stats_->slowstart_start_time = QuicTime::Zero();
+ stats_->slowstart_duration = QuicTimeAccumulator();
}
EnterStartupMode(now);
}
@@ -324,27 +327,31 @@ void BbrSender::SetFromConfig(const QuicConfig& config,
}
}
-void BbrSender::AdjustNetworkParameters(QuicBandwidth bandwidth,
- QuicTime::Delta rtt,
- bool allow_cwnd_to_decrease) {
- if (!bandwidth.IsZero()) {
+void BbrSender::AdjustNetworkParameters(const NetworkParams& params) {
+ const QuicBandwidth& bandwidth = params.bandwidth;
+ const QuicTime::Delta& rtt = params.rtt;
+
+ if (GetQuicReloadableFlag(quic_bbr_donot_inject_bandwidth)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_bbr_donot_inject_bandwidth);
+ } else if (!bandwidth.IsZero()) {
max_bandwidth_.Update(bandwidth, round_trip_count_);
}
if (!rtt.IsZero() && (min_rtt_ > rtt || min_rtt_.IsZero())) {
min_rtt_ = rtt;
}
- if (GetQuicReloadableFlag(quic_fix_bbr_cwnd_in_bandwidth_resumption) &&
- mode_ == STARTUP) {
+
+ if (params.quic_fix_bbr_cwnd_in_bandwidth_resumption && mode_ == STARTUP) {
if (bandwidth.IsZero()) {
// Ignore bad bandwidth samples.
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_fix_bbr_cwnd_in_bandwidth_resumption, 3,
- 3);
return;
}
- const QuicByteCount new_cwnd =
- std::max(kMinInitialCongestionWindow * kDefaultTCPMSS,
- std::min(kMaxInitialCongestionWindow * kDefaultTCPMSS,
- bandwidth * rtt_stats_->SmoothedOrInitialRtt()));
+ const QuicByteCount new_cwnd = std::max(
+ kMinInitialCongestionWindow * kDefaultTCPMSS,
+ std::min(
+ kMaxInitialCongestionWindow * kDefaultTCPMSS,
+ bandwidth * (GetQuicReloadableFlag(quic_bbr_donot_inject_bandwidth)
+ ? GetMinRtt()
+ : rtt_stats_->SmoothedOrInitialRtt())));
if (!rtt_stats_->smoothed_rtt().IsZero()) {
QUIC_CODE_COUNT(quic_smoothed_rtt_available);
} else if (rtt_stats_->initial_rtt() !=
@@ -353,14 +360,7 @@ void BbrSender::AdjustNetworkParameters(QuicBandwidth bandwidth,
} else {
QUIC_CODE_COUNT(quic_default_initial_rtt);
}
- if (new_cwnd > congestion_window_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_fix_bbr_cwnd_in_bandwidth_resumption, 1,
- 3);
- } else {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_fix_bbr_cwnd_in_bandwidth_resumption, 2,
- 3);
- }
- if (new_cwnd < congestion_window_ && !allow_cwnd_to_decrease) {
+ if (new_cwnd < congestion_window_ && !params.allow_cwnd_to_decrease) {
// Only decrease cwnd if allow_cwnd_to_decrease is true.
return;
}
@@ -372,6 +372,12 @@ void BbrSender::AdjustNetworkParameters(QuicBandwidth bandwidth,
set_high_cwnd_gain(kDerivedHighCWNDGain);
}
congestion_window_ = new_cwnd;
+ if (params.quic_bbr_fix_pacing_rate) {
+ // Pace at the rate of new_cwnd / RTT.
+ QuicBandwidth new_pacing_rate =
+ QuicBandwidth::FromBytesAndTimeDelta(congestion_window_, GetMinRtt());
+ pacing_rate_ = std::max(pacing_rate_, new_pacing_rate);
+ }
}
}
@@ -462,8 +468,7 @@ QuicByteCount BbrSender::ProbeRttCongestionWindow() const {
void BbrSender::EnterStartupMode(QuicTime now) {
if (stats_) {
++stats_->slowstart_count;
- DCHECK_EQ(stats_->slowstart_start_time, QuicTime::Zero()) << mode_;
- stats_->slowstart_start_time = now;
+ stats_->slowstart_duration.Start(now);
}
mode_ = STARTUP;
pacing_gain_ = high_gain_;
@@ -668,12 +673,7 @@ void BbrSender::MaybeExitStartupOrDrain(QuicTime now) {
void BbrSender::OnExitStartup(QuicTime now) {
DCHECK_EQ(mode_, STARTUP);
if (stats_) {
- DCHECK_NE(stats_->slowstart_start_time, QuicTime::Zero());
- if (now > stats_->slowstart_start_time) {
- stats_->slowstart_duration =
- now - stats_->slowstart_start_time + stats_->slowstart_duration;
- }
- stats_->slowstart_start_time = QuicTime::Zero();
+ stats_->slowstart_duration.Stop(now);
}
}
@@ -877,6 +877,7 @@ void BbrSender::CalculateRecoveryWindow(QuicByteCount bytes_acked,
recovery_window_ = std::max(
recovery_window_, unacked_packets_->bytes_in_flight() + bytes_acked);
if (GetQuicReloadableFlag(quic_bbr_one_mss_conservation)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_bbr_one_mss_conservation);
recovery_window_ =
std::max(recovery_window_,
unacked_packets_->bytes_in_flight() + kMaxSegmentSize);
@@ -904,6 +905,10 @@ void BbrSender::OnApplicationLimited(QuicByteCount bytes_in_flight) {
<< last_sent_packet_ << ", CWND: " << GetCongestionWindow();
}
+void BbrSender::PopulateConnectionStats(QuicConnectionStats* stats) const {
+ stats->num_ack_aggregation_epochs = sampler_.num_ack_aggregation_epochs();
+}
+
BbrSender::DebugState BbrSender::ExportDebugState() const {
return DebugState(*this);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.h
index 8321b8c9e27..dc512cf59be 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.h
@@ -62,7 +62,7 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
// Debug state can be exported in order to troubleshoot potential congestion
// control issues.
- struct DebugState {
+ struct QUIC_EXPORT_PRIVATE DebugState {
explicit DebugState(const BbrSender& sender);
DebugState(const DebugState& state);
@@ -105,9 +105,7 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
void SetFromConfig(const QuicConfig& config,
Perspective perspective) override;
- void AdjustNetworkParameters(QuicBandwidth bandwidth,
- QuicTime::Delta rtt,
- bool allow_cwnd_to_decrease) override;
+ void AdjustNetworkParameters(const NetworkParams& params) override;
void SetInitialCongestionWindowInPackets(
QuicPacketCount congestion_window) override;
void OnCongestionEvent(bool rtt_updated,
@@ -130,6 +128,7 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
CongestionControlType GetCongestionControlType() const override;
std::string GetDebugState() const override;
void OnApplicationLimited(QuicByteCount bytes_in_flight) override;
+ void PopulateConnectionStats(QuicConnectionStats* stats) const override;
// End implementation of SendAlgorithmInterface.
// Gets the number of RTTs BBR remains in STARTUP phase.
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender_test.cc
index 8ecab8736ae..6acfe80519a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender_test.cc
@@ -135,8 +135,9 @@ class BbrSenderTest : public QuicTest {
endpoint->connection()->clock()->Now(), rtt_stats,
QuicSentPacketManagerPeer::GetUnackedPacketMap(
QuicConnectionPeer::GetSentPacketManager(endpoint->connection())),
- kInitialCongestionWindowPackets, kDefaultMaxCongestionWindowPackets,
- &random_, QuicConnectionPeer::GetStats(endpoint->connection()));
+ kInitialCongestionWindowPackets,
+ GetQuicFlag(FLAGS_quic_max_congestion_window), &random_,
+ QuicConnectionPeer::GetStats(endpoint->connection()));
QuicConnectionPeer::SetSendAlgorithm(endpoint->connection(), sender);
endpoint->RecordTrace();
return sender;
@@ -379,8 +380,9 @@ TEST_F(BbrSenderTest, SimpleTransferAckDecimation) {
bbr_sender_.connection()->clock()->Now(), rtt_stats_,
QuicSentPacketManagerPeer::GetUnackedPacketMap(
QuicConnectionPeer::GetSentPacketManager(bbr_sender_.connection())),
- kInitialCongestionWindowPackets, kDefaultMaxCongestionWindowPackets,
- &random_, QuicConnectionPeer::GetStats(bbr_sender_.connection()));
+ kInitialCongestionWindowPackets,
+ GetQuicFlag(FLAGS_quic_max_congestion_window), &random_,
+ QuicConnectionPeer::GetStats(bbr_sender_.connection()));
QuicConnectionPeer::SetSendAlgorithm(bbr_sender_.connection(), sender_);
// Enable Ack Decimation on the receiver.
QuicConnectionPeer::SetAckMode(receiver_.connection(),
@@ -1247,10 +1249,18 @@ TEST_F(BbrSenderTest, SimpleCompetition) {
TEST_F(BbrSenderTest, ResumeConnectionState) {
CreateDefaultSetup();
- bbr_sender_.connection()->AdjustNetworkParameters(kTestLinkBandwidth,
- kTestRtt, false);
- EXPECT_EQ(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth);
- EXPECT_EQ(kTestLinkBandwidth, sender_->BandwidthEstimate());
+ bbr_sender_.connection()->AdjustNetworkParameters(
+ SendAlgorithmInterface::NetworkParams(kTestLinkBandwidth, kTestRtt,
+ false));
+ if (!GetQuicReloadableFlag(quic_bbr_donot_inject_bandwidth)) {
+ EXPECT_EQ(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth);
+ EXPECT_EQ(kTestLinkBandwidth, sender_->BandwidthEstimate());
+ }
+ EXPECT_EQ(kTestLinkBandwidth * kTestRtt,
+ sender_->ExportDebugState().congestion_window);
+ if (GetQuicReloadableFlag(quic_bbr_fix_pacing_rate)) {
+ EXPECT_EQ(kTestLinkBandwidth, sender_->PacingRate(/*bytes_in_flight=*/0));
+ }
EXPECT_APPROX_EQ(kTestRtt, sender_->ExportDebugState().min_rtt, 0.01f);
DriveOutOfStartup();
@@ -1299,14 +1309,88 @@ TEST_F(BbrSenderTest, StartupStats) {
EXPECT_THAT(stats.slowstart_bytes_sent, AllOf(Ge(100000u), Le(1000000u)));
EXPECT_LE(stats.slowstart_packets_lost, 10u);
EXPECT_LE(stats.slowstart_bytes_lost, 10000u);
- EXPECT_THAT(stats.slowstart_duration,
+ EXPECT_FALSE(stats.slowstart_duration.IsRunning());
+ EXPECT_THAT(stats.slowstart_duration.GetTotalElapsedTime(),
AllOf(Ge(QuicTime::Delta::FromMilliseconds(500)),
Le(QuicTime::Delta::FromMilliseconds(1500))));
- EXPECT_EQ(QuicTime::Zero(), stats.slowstart_start_time);
- EXPECT_EQ(stats.slowstart_duration,
+ EXPECT_EQ(stats.slowstart_duration.GetTotalElapsedTime(),
QuicConnectionPeer::GetSentPacketManager(bbr_sender_.connection())
->GetSlowStartDuration());
}
+// Regression test for b/143540157.
+TEST_F(BbrSenderTest, RecalculatePacingRateOnCwndChange1RTT) {
+ CreateDefaultSetup();
+
+ bbr_sender_.AddBytesToTransfer(1 * 1024 * 1024);
+ // Wait until an ACK comes back.
+ const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(5);
+ bool simulator_result = simulator_.RunUntilOrTimeout(
+ [this]() { return !sender_->ExportDebugState().min_rtt.IsZero(); },
+ timeout);
+ ASSERT_TRUE(simulator_result);
+ const QuicByteCount previous_cwnd =
+ sender_->ExportDebugState().congestion_window;
+
+ // Bootstrap cwnd.
+ bbr_sender_.connection()->AdjustNetworkParameters(
+ SendAlgorithmInterface::NetworkParams(kTestLinkBandwidth,
+ QuicTime::Delta::Zero(), false));
+ if (!GetQuicReloadableFlag(quic_bbr_donot_inject_bandwidth)) {
+ EXPECT_EQ(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth);
+ EXPECT_EQ(kTestLinkBandwidth, sender_->BandwidthEstimate());
+ }
+ EXPECT_LT(previous_cwnd, sender_->ExportDebugState().congestion_window);
+
+ if (GetQuicReloadableFlag(quic_bbr_fix_pacing_rate)) {
+ // Verify pacing rate is re-calculated based on the new cwnd and min_rtt.
+ EXPECT_APPROX_EQ(QuicBandwidth::FromBytesAndTimeDelta(
+ sender_->ExportDebugState().congestion_window,
+ sender_->ExportDebugState().min_rtt),
+ sender_->PacingRate(/*bytes_in_flight=*/0), 0.01f);
+ } else {
+ // Pacing rate is still based on initial cwnd.
+ EXPECT_APPROX_EQ(QuicBandwidth::FromBytesAndTimeDelta(
+ kInitialCongestionWindowPackets * kDefaultTCPMSS,
+ sender_->ExportDebugState().min_rtt),
+ sender_->PacingRate(/*bytes_in_flight=*/0), 0.01f);
+ }
+}
+
+TEST_F(BbrSenderTest, RecalculatePacingRateOnCwndChange0RTT) {
+ CreateDefaultSetup();
+ // Initial RTT is available.
+ const_cast<RttStats*>(rtt_stats_)->set_initial_rtt(kTestRtt);
+
+ // Bootstrap cwnd.
+ bbr_sender_.connection()->AdjustNetworkParameters(
+ SendAlgorithmInterface::NetworkParams(kTestLinkBandwidth,
+ QuicTime::Delta::Zero(), false));
+ if (!GetQuicReloadableFlag(quic_bbr_donot_inject_bandwidth)) {
+ EXPECT_EQ(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth);
+ EXPECT_EQ(kTestLinkBandwidth, sender_->BandwidthEstimate());
+ }
+ EXPECT_LT(kInitialCongestionWindowPackets * kDefaultTCPMSS,
+ sender_->ExportDebugState().congestion_window);
+ // No Rtt sample is available.
+ EXPECT_TRUE(sender_->ExportDebugState().min_rtt.IsZero());
+
+ if (GetQuicReloadableFlag(quic_bbr_fix_pacing_rate)) {
+ // Verify pacing rate is re-calculated based on the new cwnd and initial
+ // RTT.
+ EXPECT_APPROX_EQ(QuicBandwidth::FromBytesAndTimeDelta(
+ sender_->ExportDebugState().congestion_window,
+ rtt_stats_->initial_rtt()),
+ sender_->PacingRate(/*bytes_in_flight=*/0), 0.01f);
+ } else {
+ // Pacing rate is still based on initial cwnd.
+ EXPECT_APPROX_EQ(
+ 2.885f * QuicBandwidth::FromBytesAndTimeDelta(
+ kInitialCongestionWindowPackets * kDefaultTCPMSS,
+ rtt_stats_->initial_rtt()),
+ sender_->PacingRate(/*bytes_in_flight=*/0), 0.01f);
+ }
+}
+
} // namespace test
} // namespace quic
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 3502031a7c7..8798322eb76 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
@@ -32,6 +32,7 @@ GeneralLossAlgorithm::GeneralLossAlgorithm(LossDetectionType loss_type)
: loss_detection_timeout_(QuicTime::Zero()),
reordering_threshold_(kNumberOfNacksBeforeRetransmission),
use_adaptive_reordering_threshold_(false),
+ use_adaptive_time_threshold_(false),
least_in_flight_(1),
packet_number_space_(NUM_PACKET_NUMBER_SPACES) {
SetLossDetectionType(loss_type);
@@ -39,7 +40,6 @@ GeneralLossAlgorithm::GeneralLossAlgorithm(LossDetectionType loss_type)
void GeneralLossAlgorithm::SetLossDetectionType(LossDetectionType loss_type) {
loss_detection_timeout_ = QuicTime::Zero();
- largest_sent_on_spurious_retransmit_.Clear();
loss_type_ = loss_type;
if (loss_type == kAdaptiveTime) {
reordering_shift_ = kDefaultAdaptiveLossDelayShift;
@@ -185,43 +185,14 @@ QuicTime GeneralLossAlgorithm::GetLossTimeout() const {
return loss_detection_timeout_;
}
-void GeneralLossAlgorithm::SpuriousRetransmitDetected(
- const QuicUnackedPacketMap& unacked_packets,
- QuicTime time,
- const RttStats& rtt_stats,
- QuicPacketNumber spurious_retransmission) {
- if (loss_type_ != kAdaptiveTime || reordering_shift_ == 0) {
- return;
- }
- // Calculate the extra time needed so this wouldn't have been declared lost.
- // Extra time needed is based on how long it's been since the spurious
- // retransmission was sent, because the SRTT and latest RTT may have changed.
- QuicTime::Delta extra_time_needed =
- time -
- unacked_packets.GetTransmissionInfo(spurious_retransmission).sent_time;
- // Increase the reordering fraction until enough time would be allowed.
- QuicTime::Delta max_rtt =
- std::max(rtt_stats.previous_srtt(), rtt_stats.latest_rtt());
-
- if (largest_sent_on_spurious_retransmit_.IsInitialized() &&
- spurious_retransmission <= largest_sent_on_spurious_retransmit_) {
- return;
- }
- largest_sent_on_spurious_retransmit_ = unacked_packets.largest_sent_packet();
- QuicTime::Delta proposed_extra_time(QuicTime::Delta::Zero());
- do {
- proposed_extra_time = max_rtt >> reordering_shift_;
- --reordering_shift_;
- } while (proposed_extra_time < extra_time_needed && reordering_shift_ > 0);
-}
-
void GeneralLossAlgorithm::SpuriousLossDetected(
const QuicUnackedPacketMap& unacked_packets,
const RttStats& rtt_stats,
QuicTime ack_receive_time,
QuicPacketNumber packet_number,
QuicPacketNumber previous_largest_acked) {
- if (loss_type_ == kAdaptiveTime && reordering_shift_ > 0) {
+ if ((loss_type_ == kAdaptiveTime || use_adaptive_time_threshold_) &&
+ reordering_shift_ > 0) {
// Increase reordering fraction such that the packet would not have been
// declared lost.
QuicTime::Delta time_needed =
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.h
index c9da8370e20..fb85523c63e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.h
@@ -47,13 +47,6 @@ class QUIC_EXPORT_PRIVATE GeneralLossAlgorithm : public LossDetectionInterface {
// Returns a non-zero value when the early retransmit timer is active.
QuicTime GetLossTimeout() const override;
- // Increases the loss detection threshold for time loss detection.
- void SpuriousRetransmitDetected(
- const QuicUnackedPacketMap& unacked_packets,
- QuicTime time,
- const RttStats& rtt_stats,
- QuicPacketNumber spurious_retransmission) override;
-
// Called to increases time and/or packet threshold.
void SpuriousLossDetected(const QuicUnackedPacketMap& unacked_packets,
const RttStats& rtt_stats,
@@ -77,11 +70,14 @@ class QUIC_EXPORT_PRIVATE GeneralLossAlgorithm : public LossDetectionInterface {
use_adaptive_reordering_threshold_ = true;
}
+ bool use_adaptive_time_threshold() const {
+ return use_adaptive_time_threshold_;
+ }
+
+ void enable_adaptive_time_threshold() { use_adaptive_time_threshold_ = true; }
+
private:
QuicTime loss_detection_timeout_;
- // Largest sent packet when a spurious retransmit is detected.
- // Prevents increasing the reordering threshold multiple times per epoch.
- QuicPacketNumber largest_sent_on_spurious_retransmit_;
LossDetectionType loss_type_;
// Fraction of a max(SRTT, latest_rtt) to permit reordering before declaring
// loss. Fraction calculated by shifting max(SRTT, latest_rtt) to the right
@@ -91,6 +87,8 @@ class QUIC_EXPORT_PRIVATE GeneralLossAlgorithm : public LossDetectionInterface {
QuicPacketCount reordering_threshold_;
// If true, uses adaptive reordering threshold for loss detection.
bool use_adaptive_reordering_threshold_;
+ // If true, uses adaptive time threshold for time based loss detection.
+ bool use_adaptive_time_threshold_;
// The largest newly acked from the previous call to DetectLosses.
QuicPacketNumber largest_previously_acked_;
// The least in flight packet. Loss detection should start from this. Please
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm_test.cc
index dba6d5b5484..aaf9c7c32bc 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm_test.cc
@@ -41,16 +41,16 @@ class GeneralLossAlgorithmTest : public QuicTest {
PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
false, false);
packet.retransmittable_frames.push_back(QuicFrame(frame));
- unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(),
- NOT_RETRANSMISSION, clock_.Now(), true);
+ unacked_packets_.AddSentPacket(&packet, NOT_RETRANSMISSION, clock_.Now(),
+ true);
}
void SendAckPacket(uint64_t packet_number) {
SerializedPacket packet(QuicPacketNumber(packet_number),
PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
true, false);
- unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(),
- NOT_RETRANSMISSION, clock_.Now(), false);
+ unacked_packets_.AddSentPacket(&packet, NOT_RETRANSMISSION, clock_.Now(),
+ false);
}
void VerifyLosses(uint64_t largest_newly_acked,
@@ -514,21 +514,51 @@ TEST_F(GeneralLossAlgorithmTest, IncreaseThresholdUponSpuriousLoss) {
// Advance the time 1/4 RTT and indicate the loss was spurious.
// The new threshold should be 1/2 RTT.
clock_.AdvanceTime(rtt_stats_.smoothed_rtt() * (1.0f / 4));
- if (GetQuicReloadableFlag(quic_detect_spurious_loss)) {
- loss_algorithm_.SpuriousLossDetected(unacked_packets_, rtt_stats_,
- clock_.Now(), QuicPacketNumber(1),
- QuicPacketNumber(2));
- EXPECT_EQ(1, loss_algorithm_.reordering_shift());
- return;
- }
- loss_algorithm_.SpuriousRetransmitDetected(unacked_packets_, clock_.Now(),
- rtt_stats_, QuicPacketNumber(11));
+ loss_algorithm_.SpuriousLossDetected(unacked_packets_, rtt_stats_,
+ clock_.Now(), QuicPacketNumber(1),
+ QuicPacketNumber(2));
EXPECT_EQ(1, loss_algorithm_.reordering_shift());
+}
+
+TEST_F(GeneralLossAlgorithmTest, IncreaseTimeThresholdUponSpuriousLoss) {
+ loss_algorithm_.SetLossDetectionType(kIetfLossDetection);
+ loss_algorithm_.enable_adaptive_time_threshold();
+ loss_algorithm_.set_reordering_shift(kDefaultLossDelayShift);
+ EXPECT_EQ(kDefaultLossDelayShift, loss_algorithm_.reordering_shift());
+ EXPECT_TRUE(loss_algorithm_.use_adaptive_time_threshold());
+ const size_t kNumSentPackets = 10;
+ // Transmit 2 packets at 1/10th an RTT interval.
+ for (size_t i = 1; i <= kNumSentPackets; ++i) {
+ SendDataPacket(i);
+ clock_.AdvanceTime(0.1 * rtt_stats_.smoothed_rtt());
+ }
+ EXPECT_EQ(QuicTime::Zero() + rtt_stats_.smoothed_rtt(), clock_.Now());
+ AckedPacketVector packets_acked;
+ // Expect the timer to not be set.
+ EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
+ // Packet 1 should not be lost until 1/4 RTTs pass.
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
+ packets_acked.push_back(AckedPacket(
+ QuicPacketNumber(2), kMaxOutgoingPacketSize, QuicTime::Zero()));
+ VerifyLosses(2, packets_acked, std::vector<uint64_t>{});
+ packets_acked.clear();
+ // Expect the timer to be set to 1/4 RTT's in the future.
+ EXPECT_EQ(rtt_stats_.smoothed_rtt() * (1.0f / 4),
+ loss_algorithm_.GetLossTimeout() - clock_.Now());
+ VerifyLosses(2, packets_acked, std::vector<uint64_t>{});
+ clock_.AdvanceTime(rtt_stats_.smoothed_rtt() * (1.0f / 4));
+ VerifyLosses(2, packets_acked, {1});
+ EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
+ // Retransmit packet 1 as 11 and 2 as 12.
+ SendDataPacket(11);
+ SendDataPacket(12);
- // Detect another spurious retransmit and ensure the threshold doesn't
- // increase again.
- loss_algorithm_.SpuriousRetransmitDetected(unacked_packets_, clock_.Now(),
- rtt_stats_, QuicPacketNumber(12));
+ // Advance the time 1/4 RTT and indicate the loss was spurious.
+ // The new threshold should be 1/2 RTT.
+ clock_.AdvanceTime(rtt_stats_.smoothed_rtt() * (1.0f / 4));
+ loss_algorithm_.SpuriousLossDetected(unacked_packets_, rtt_stats_,
+ clock_.Now(), QuicPacketNumber(1),
+ QuicPacketNumber(2));
EXPECT_EQ(1, loss_algorithm_.reordering_shift());
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/loss_detection_interface.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/loss_detection_interface.h
index f6867853dab..af9c1962656 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/loss_detection_interface.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/loss_detection_interface.h
@@ -35,16 +35,6 @@ class QUIC_EXPORT_PRIVATE LossDetectionInterface {
// Returns QuicTime::Zero if no alarm needs to be set.
virtual QuicTime GetLossTimeout() const = 0;
- // Called when a |spurious_retransmission| is detected. The original
- // transmission must have been caused by DetectLosses.
- // TODO(fayang): Remove this method when deprecating
- // quic_detect_spurious_loss.
- virtual void SpuriousRetransmitDetected(
- const QuicUnackedPacketMap& unacked_packets,
- QuicTime time,
- const RttStats& rtt_stats,
- QuicPacketNumber spurious_retransmission) = 0;
-
// Called when |packet_number| was detected lost but gets acked later.
virtual void SpuriousLossDetected(
const QuicUnackedPacketMap& unacked_packets,
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 997faa402e8..1c0466a424f 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
@@ -73,11 +73,6 @@ class QUIC_EXPORT_PRIVATE RttStats {
QuicTime::Delta mean_deviation() const { return mean_deviation_; }
- QuicTime::Delta max_ack_delay() const {
- DCHECK(!GetQuicReloadableFlag(quic_sent_packet_manager_cleanup));
- return max_ack_delay_;
- }
-
QuicTime last_update_time() const { return last_update_time_; }
bool ignore_max_ack_delay() const { return ignore_max_ack_delay_; }
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats_test.cc
index 4d259d3b248..be5f4d679f0 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats_test.cc
@@ -35,28 +35,17 @@ TEST_F(RttStatsTest, SmoothedRtt) {
QuicTime::Zero());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.latest_rtt());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.smoothed_rtt());
- if (!GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)) {
- EXPECT_EQ(QuicTime::Delta::Zero(), rtt_stats_.max_ack_delay());
- }
// Verify that a plausible ack delay increases the max ack delay.
rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(400),
QuicTime::Delta::FromMilliseconds(100),
QuicTime::Zero());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.latest_rtt());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.smoothed_rtt());
- if (!GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)) {
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100),
- rtt_stats_.max_ack_delay());
- }
// Verify that Smoothed RTT includes max ack delay if it's reasonable.
rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(350),
QuicTime::Delta::FromMilliseconds(50), QuicTime::Zero());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.latest_rtt());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.smoothed_rtt());
- if (!GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)) {
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100),
- rtt_stats_.max_ack_delay());
- }
// Verify that large erroneous ack_delay does not change Smoothed RTT.
rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(200),
QuicTime::Delta::FromMilliseconds(300),
@@ -64,10 +53,6 @@ TEST_F(RttStatsTest, SmoothedRtt) {
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.latest_rtt());
EXPECT_EQ(QuicTime::Delta::FromMicroseconds(287500),
rtt_stats_.smoothed_rtt());
- if (!GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)) {
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100),
- rtt_stats_.max_ack_delay());
- }
}
TEST_F(RttStatsTest, SmoothedRttIgnoreAckDelay) {
@@ -78,18 +63,12 @@ TEST_F(RttStatsTest, SmoothedRttIgnoreAckDelay) {
QuicTime::Zero());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.latest_rtt());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.smoothed_rtt());
- if (!GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)) {
- EXPECT_EQ(QuicTime::Delta::Zero(), rtt_stats_.max_ack_delay());
- }
// Verify that a plausible ack delay increases the max ack delay.
rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(300),
QuicTime::Delta::FromMilliseconds(100),
QuicTime::Zero());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.latest_rtt());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.smoothed_rtt());
- if (!GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)) {
- EXPECT_EQ(QuicTime::Delta::Zero(), rtt_stats_.max_ack_delay());
- }
// Verify that Smoothed RTT includes max ack delay if it's reasonable.
rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(300),
QuicTime::Delta::FromMilliseconds(50), QuicTime::Zero());
@@ -102,9 +81,6 @@ TEST_F(RttStatsTest, SmoothedRttIgnoreAckDelay) {
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.latest_rtt());
EXPECT_EQ(QuicTime::Delta::FromMicroseconds(287500),
rtt_stats_.smoothed_rtt());
- if (!GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)) {
- EXPECT_EQ(QuicTime::Delta::Zero(), rtt_stats_.max_ack_delay());
- }
}
// Ensure that the potential rounding artifacts in EWMA calculation do not cause
@@ -225,9 +201,6 @@ TEST_F(RttStatsTest, ResetAfterConnectionMigrations) {
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.latest_rtt());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.smoothed_rtt());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.min_rtt());
- if (!GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)) {
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(0), rtt_stats_.max_ack_delay());
- }
rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(300),
QuicTime::Delta::FromMilliseconds(100),
@@ -235,19 +208,12 @@ TEST_F(RttStatsTest, ResetAfterConnectionMigrations) {
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.latest_rtt());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.smoothed_rtt());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.min_rtt());
- if (!GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)) {
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100),
- rtt_stats_.max_ack_delay());
- }
// Reset rtt stats on connection migrations.
rtt_stats_.OnConnectionMigration();
EXPECT_EQ(QuicTime::Delta::Zero(), rtt_stats_.latest_rtt());
EXPECT_EQ(QuicTime::Delta::Zero(), rtt_stats_.smoothed_rtt());
EXPECT_EQ(QuicTime::Delta::Zero(), rtt_stats_.min_rtt());
- if (!GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)) {
- EXPECT_EQ(QuicTime::Delta::Zero(), rtt_stats_.max_ack_delay());
- }
}
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.cc
index b641eb4bb3d..83529c6e76c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.cc
@@ -27,7 +27,8 @@ SendAlgorithmInterface* SendAlgorithmInterface::Create(
QuicRandom* random,
QuicConnectionStats* stats,
QuicPacketCount initial_congestion_window) {
- QuicPacketCount max_congestion_window = kDefaultMaxCongestionWindowPackets;
+ QuicPacketCount max_congestion_window =
+ GetQuicFlag(FLAGS_quic_max_congestion_window);
switch (congestion_control_type) {
case kGoogCC: // GoogCC is not supported by quic/core, fall back to BBR.
case kBBR:
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h
index dab8fc294a7..628e0d62e0c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h
@@ -29,10 +29,42 @@ typedef uint64_t QuicRoundTripCount;
class CachedNetworkParameters;
class RttStats;
-const QuicPacketCount kDefaultMaxCongestionWindowPackets = 2000;
-
class QUIC_EXPORT_PRIVATE SendAlgorithmInterface {
public:
+ // Network Params for AdjustNetworkParameters.
+ struct QUIC_NO_EXPORT NetworkParams {
+ NetworkParams()
+ : NetworkParams(QuicBandwidth::Zero(), QuicTime::Delta::Zero(), false) {
+ }
+ NetworkParams(const QuicBandwidth& bandwidth,
+ const QuicTime::Delta& rtt,
+ bool allow_cwnd_to_decrease)
+ : bandwidth(bandwidth),
+ rtt(rtt),
+ allow_cwnd_to_decrease(allow_cwnd_to_decrease),
+ quic_fix_bbr_cwnd_in_bandwidth_resumption(
+ GetQuicReloadableFlag(quic_fix_bbr_cwnd_in_bandwidth_resumption)),
+ quic_bbr_fix_pacing_rate(
+ GetQuicReloadableFlag(quic_bbr_fix_pacing_rate)) {}
+
+ bool operator==(const NetworkParams& other) const {
+ return bandwidth == other.bandwidth && rtt == other.rtt &&
+ allow_cwnd_to_decrease == other.allow_cwnd_to_decrease &&
+ quic_fix_bbr_cwnd_in_bandwidth_resumption ==
+ other.quic_fix_bbr_cwnd_in_bandwidth_resumption &&
+ quic_bbr_fix_pacing_rate == other.quic_bbr_fix_pacing_rate;
+ }
+
+ QuicBandwidth bandwidth;
+ QuicTime::Delta rtt;
+ bool allow_cwnd_to_decrease;
+ // Code changes that are controlled by flags.
+ // TODO(b/131899599): Remove when impact of fix is measured.
+ bool quic_fix_bbr_cwnd_in_bandwidth_resumption;
+ // TODO(b/143540157): Remove when impact of fix is measured.
+ bool quic_bbr_fix_pacing_rate;
+ };
+
static SendAlgorithmInterface* Create(
const QuicClock* clock,
const RttStats* rtt_stats,
@@ -117,9 +149,7 @@ class QUIC_EXPORT_PRIVATE SendAlgorithmInterface {
// Notifies the congestion control algorithm of an external network
// measurement or prediction. Either |bandwidth| or |rtt| may be zero if no
// sample is available.
- virtual void AdjustNetworkParameters(QuicBandwidth bandwidth,
- QuicTime::Delta rtt,
- bool allow_cwnd_to_decrease) = 0;
+ virtual void AdjustNetworkParameters(const NetworkParams& params) = 0;
// Retrieves debugging information about the current state of the
// send algorithm.
@@ -138,6 +168,9 @@ class QUIC_EXPORT_PRIVATE SendAlgorithmInterface {
// such cases, it should use the internal state it uses for congestion control
// for that.
virtual void OnApplicationLimited(QuicByteCount bytes_in_flight) = 0;
+
+ // Called before connection close to collect stats.
+ virtual void PopulateConnectionStats(QuicConnectionStats* stats) const = 0;
};
} // namespace quic
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 28f284e4ce0..cf400e5a1cc 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
@@ -105,15 +105,11 @@ void TcpCubicSenderBytes::SetFromConfig(const QuicConfig& config,
}
}
-void TcpCubicSenderBytes::AdjustNetworkParameters(
- QuicBandwidth bandwidth,
- QuicTime::Delta rtt,
- bool /*allow_cwnd_to_decrease*/) {
- if (bandwidth.IsZero() || rtt.IsZero()) {
+void TcpCubicSenderBytes::AdjustNetworkParameters(const NetworkParams& params) {
+ if (params.bandwidth.IsZero() || params.rtt.IsZero()) {
return;
}
-
- SetCongestionWindowFromBandwidthAndRtt(bandwidth, rtt);
+ SetCongestionWindowFromBandwidthAndRtt(params.bandwidth, params.rtt);
}
float TcpCubicSenderBytes::RenoBeta() const {
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.h
index 50f7981b81e..9144b8a5913 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.h
@@ -46,9 +46,7 @@ class QUIC_EXPORT_PRIVATE TcpCubicSenderBytes : public SendAlgorithmInterface {
// Start implementation of SendAlgorithmInterface.
void SetFromConfig(const QuicConfig& config,
Perspective perspective) override;
- void AdjustNetworkParameters(QuicBandwidth bandwidth,
- QuicTime::Delta rtt,
- bool allow_cwnd_to_decrease) override;
+ void AdjustNetworkParameters(const NetworkParams& params) override;
void SetNumEmulatedConnections(int num_connections);
void SetInitialCongestionWindowInPackets(
QuicPacketCount congestion_window) override;
@@ -75,6 +73,7 @@ class QUIC_EXPORT_PRIVATE TcpCubicSenderBytes : public SendAlgorithmInterface {
bool ShouldSendProbingPacket() const override;
std::string GetDebugState() const override;
void OnApplicationLimited(QuicByteCount bytes_in_flight) override;
+ void PopulateConnectionStats(QuicConnectionStats* /*stats*/) const override {}
// End implementation of SendAlgorithmInterface.
QuicByteCount min_congestion_window() const { return min_congestion_window_; }
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
index 4c51742cd3e..04c0e8a41ec 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
@@ -677,20 +677,29 @@ TEST_F(TcpCubicSenderBytesTest, BandwidthResumption) {
const QuicBandwidth kBandwidthEstimate =
QuicBandwidth::FromBytesPerSecond(kNumberOfPackets * kDefaultTCPMSS);
const QuicTime::Delta kRttEstimate = QuicTime::Delta::FromSeconds(1);
- sender_->AdjustNetworkParameters(kBandwidthEstimate, kRttEstimate, false);
+
+ SendAlgorithmInterface::NetworkParams network_param;
+ network_param.bandwidth = kBandwidthEstimate;
+ network_param.rtt = kRttEstimate;
+ sender_->AdjustNetworkParameters(network_param);
EXPECT_EQ(kNumberOfPackets * kDefaultTCPMSS, sender_->GetCongestionWindow());
// Resume with an illegal value of 0 and verify the server ignores it.
- sender_->AdjustNetworkParameters(QuicBandwidth::Zero(), kRttEstimate, false);
+ SendAlgorithmInterface::NetworkParams network_param_no_bandwidth;
+ network_param_no_bandwidth.bandwidth = QuicBandwidth::Zero();
+ network_param_no_bandwidth.rtt = kRttEstimate;
+ sender_->AdjustNetworkParameters(network_param_no_bandwidth);
EXPECT_EQ(kNumberOfPackets * kDefaultTCPMSS, sender_->GetCongestionWindow());
// Resumed CWND is limited to be in a sensible range.
const QuicBandwidth kUnreasonableBandwidth =
- QuicBandwidth::FromBytesPerSecond((kMaxCongestionWindowPackets + 1) *
+ QuicBandwidth::FromBytesPerSecond((kMaxResumptionCongestionWindow + 1) *
kDefaultTCPMSS);
- sender_->AdjustNetworkParameters(kUnreasonableBandwidth,
- QuicTime::Delta::FromSeconds(1), false);
- EXPECT_EQ(kMaxCongestionWindowPackets * kDefaultTCPMSS,
+ SendAlgorithmInterface::NetworkParams network_param_large_bandwidth;
+ network_param_large_bandwidth.bandwidth = kUnreasonableBandwidth;
+ network_param_large_bandwidth.rtt = QuicTime::Delta::FromSeconds(1);
+ sender_->AdjustNetworkParameters(network_param_large_bandwidth);
+ EXPECT_EQ(kMaxResumptionCongestionWindow * kDefaultTCPMSS,
sender_->GetCongestionWindow());
}
@@ -781,14 +790,16 @@ TEST_F(TcpCubicSenderBytesTest, DefaultMaxCwnd) {
AckedPacketVector acked_packets;
LostPacketVector missing_packets;
- for (uint64_t i = 1; i < kDefaultMaxCongestionWindowPackets; ++i) {
+ QuicPacketCount max_congestion_window =
+ GetQuicFlag(FLAGS_quic_max_congestion_window);
+ for (uint64_t i = 1; i < max_congestion_window; ++i) {
acked_packets.clear();
acked_packets.push_back(
AckedPacket(QuicPacketNumber(i), 1350, QuicTime::Zero()));
sender->OnCongestionEvent(true, sender->GetCongestionWindow(), clock_.Now(),
acked_packets, missing_packets);
}
- EXPECT_EQ(kDefaultMaxCongestionWindowPackets,
+ EXPECT_EQ(max_congestion_window,
sender->GetCongestionWindow() / kDefaultTCPMSS);
}
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 3b669e23e25..4e7f07b3b10 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
@@ -70,17 +70,6 @@ QuicTime UberLossAlgorithm::GetLossTimeout() const {
return loss_timeout;
}
-void UberLossAlgorithm::SpuriousRetransmitDetected(
- const QuicUnackedPacketMap& unacked_packets,
- QuicTime time,
- const RttStats& rtt_stats,
- QuicPacketNumber spurious_retransmission) {
- general_loss_algorithms_[unacked_packets.GetPacketNumberSpace(
- spurious_retransmission)]
- .SpuriousRetransmitDetected(unacked_packets, time, rtt_stats,
- spurious_retransmission);
-}
-
void UberLossAlgorithm::SpuriousLossDetected(
const QuicUnackedPacketMap& unacked_packets,
const RttStats& rtt_stats,
@@ -104,4 +93,10 @@ void UberLossAlgorithm::EnableAdaptiveReorderingThreshold() {
}
}
+void UberLossAlgorithm::EnableAdaptiveTimeThreshold() {
+ for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
+ general_loss_algorithms_[i].enable_adaptive_time_threshold();
+ }
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.h
index 0d2b788ea96..f922bba1abf 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.h
@@ -41,13 +41,6 @@ class QUIC_EXPORT_PRIVATE UberLossAlgorithm : public LossDetectionInterface {
// Returns the earliest time the early retransmit timer should be active.
QuicTime GetLossTimeout() const override;
- // Increases the loss detection threshold for time loss detection.
- void SpuriousRetransmitDetected(
- const QuicUnackedPacketMap& unacked_packets,
- QuicTime time,
- const RttStats& rtt_stats,
- QuicPacketNumber spurious_retransmission) override;
-
// Called to increases time or packet threshold.
void SpuriousLossDetected(const QuicUnackedPacketMap& unacked_packets,
const RttStats& rtt_stats,
@@ -61,6 +54,9 @@ class QUIC_EXPORT_PRIVATE UberLossAlgorithm : public LossDetectionInterface {
// Enable adaptive reordering threshold of all packet number spaces.
void EnableAdaptiveReorderingThreshold();
+ // Enable adaptive time threshold of all packet number spaces.
+ void EnableAdaptiveTimeThreshold();
+
private:
friend class test::QuicSentPacketManagerPeer;
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm_test.cc
index 8d69c136c0a..79d0ff76867 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm_test.cc
@@ -48,8 +48,8 @@ class UberLossAlgorithmTest : public QuicTest {
false, false);
packet.encryption_level = encryption_level;
packet.retransmittable_frames.push_back(QuicFrame(frame));
- unacked_packets_->AddSentPacket(&packet, QuicPacketNumber(),
- NOT_RETRANSMISSION, clock_.Now(), true);
+ unacked_packets_->AddSentPacket(&packet, NOT_RETRANSMISSION, clock_.Now(),
+ true);
}
void AckPackets(const std::vector<uint64_t>& packets_acked) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/windowed_filter.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/windowed_filter.h
index 8729895d9e0..4176d730536 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/windowed_filter.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/windowed_filter.h
@@ -38,14 +38,14 @@ namespace quic {
// Compares two values and returns true if the first is less than or equal
// to the second.
template <class T>
-struct MinFilter {
+struct QUIC_EXPORT_PRIVATE MinFilter {
bool operator()(const T& lhs, const T& rhs) const { return lhs <= rhs; }
};
// Compares two values and returns true if the first is greater than or equal
// to the second.
template <class T>
-struct MaxFilter {
+struct QUIC_EXPORT_PRIVATE MaxFilter {
bool operator()(const T& lhs, const T& rhs) const { return lhs >= rhs; }
};
@@ -63,7 +63,7 @@ struct MaxFilter {
// two timestamps. Has to be the type of (a - b) if both |a| and |b| are
// of type TimeT.
template <class T, class Compare, typename TimeT, typename TimeDeltaT>
-class WindowedFilter {
+class QUIC_EXPORT_PRIVATE WindowedFilter {
public:
// |window_length| is the period after which a best estimate expires.
// |zero_value| is used as the uninitialized value for objects of T.
@@ -143,7 +143,7 @@ class WindowedFilter {
T GetThirdBest() const { return estimates_[2].sample; }
private:
- struct Sample {
+ struct QUIC_EXPORT_PRIVATE Sample {
T sample;
TimeT time;
Sample(T init_sample, TimeT init_time)
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 405292ea083..a3173f54456 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
@@ -168,7 +168,7 @@ size_t AeadBaseEncrypter::GetIVSize() const {
}
size_t AeadBaseEncrypter::GetMaxPlaintextSize(size_t ciphertext_size) const {
- return ciphertext_size - auth_tag_size_;
+ return ciphertext_size - std::min(ciphertext_size, auth_tag_size_);
}
size_t AeadBaseEncrypter::GetCiphertextSize(size_t plaintext_size) const {
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc
index dd8a680ec32..9ce4bda19ba 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc
@@ -269,7 +269,7 @@ TEST_F(Aes128Gcm12DecrypterTest, Decrypt) {
// handle an AAD that is set to nullptr, as opposed
// to a zero-length, non-nullptr pointer.
aad.length() ? aad : QuicStringPiece(), ciphertext));
- if (!decrypted.get()) {
+ if (!decrypted) {
EXPECT_FALSE(has_pt);
continue;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc
index 5ccc44da3c6..d529d5d60d4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter_test.cc
@@ -228,6 +228,7 @@ TEST_F(Aes128Gcm12EncrypterTest, GetMaxPlaintextSize) {
EXPECT_EQ(1000u, encrypter.GetMaxPlaintextSize(1012));
EXPECT_EQ(100u, encrypter.GetMaxPlaintextSize(112));
EXPECT_EQ(10u, encrypter.GetMaxPlaintextSize(22));
+ EXPECT_EQ(0u, encrypter.GetMaxPlaintextSize(11));
}
TEST_F(Aes128Gcm12EncrypterTest, GetCiphertextSize) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_decrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_decrypter_test.cc
index 54793f8c6e2..579f76d498d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_decrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_decrypter_test.cc
@@ -258,7 +258,7 @@ TEST_F(Aes128GcmDecrypterTest, Decrypt) {
// handle an AAD that is set to nullptr, as opposed
// to a zero-length, non-nullptr pointer.
aad.length() ? aad : QuicStringPiece(), ciphertext));
- if (!decrypted.get()) {
+ if (!decrypted) {
EXPECT_FALSE(has_pt);
continue;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_256_gcm_decrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_256_gcm_decrypter_test.cc
index 73a3b3deec4..b3d61c7798f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_256_gcm_decrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_256_gcm_decrypter_test.cc
@@ -262,7 +262,7 @@ TEST_F(Aes256GcmDecrypterTest, Decrypt) {
// handle an AAD that is set to nullptr, as opposed
// to a zero-length, non-nullptr pointer.
aad.length() ? aad : QuicStringPiece(), ciphertext));
- if (!decrypted.get()) {
+ if (!decrypted) {
EXPECT_FALSE(has_pt);
continue;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_decrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_decrypter_test.cc
index a9c4999683b..930af24a3b3 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_decrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_decrypter_test.cc
@@ -159,7 +159,7 @@ TEST_F(ChaCha20Poly1305DecrypterTest, Decrypt) {
// is set to nullptr, as opposed to a zero-length, non-nullptr pointer.
QuicStringPiece(aad.length() ? aad.data() : nullptr, aad.length()),
ct));
- if (!decrypted.get()) {
+ if (!decrypted) {
EXPECT_FALSE(has_pt);
continue;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc
index ce4dea9f385..90052d60520 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc
@@ -154,7 +154,7 @@ TEST_F(ChaCha20Poly1305TlsDecrypterTest, Decrypt) {
// is set to nullptr, as opposed to a zero-length, non-nullptr pointer.
QuicStringPiece(aad.length() ? aad.data() : nullptr, aad.length()),
ct));
- if (!decrypted.get()) {
+ if (!decrypted) {
EXPECT_FALSE(has_pt);
continue;
}
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 eb1e95fb98c..c67fd89d4ef 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
@@ -10,6 +10,7 @@
#include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
@@ -30,7 +31,7 @@ std::string ChaChaBaseDecrypter::GenerateHeaderProtectionMask(
}
const uint8_t* nonce = reinterpret_cast<const uint8_t*>(sample.data()) + 4;
uint32_t counter;
- QuicDataReader(sample.data(), 4, Endianness::HOST_BYTE_ORDER)
+ QuicDataReader(sample.data(), 4, quiche::HOST_BYTE_ORDER)
.ReadUInt32(&counter);
const uint8_t zeroes[] = {0, 0, 0, 0, 0};
std::string out(QUIC_ARRAYSIZE(zeroes), 0);
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 04d902f4b4c..9c465a944c9 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
@@ -8,6 +8,7 @@
#include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
@@ -27,7 +28,7 @@ std::string ChaChaBaseEncrypter::GenerateHeaderProtectionMask(
}
const uint8_t* nonce = reinterpret_cast<const uint8_t*>(sample.data()) + 4;
uint32_t counter;
- QuicDataReader(sample.data(), 4, Endianness::HOST_BYTE_ORDER)
+ QuicDataReader(sample.data(), 4, quiche::HOST_BYTE_ORDER)
.ReadUInt32(&counter);
const uint8_t zeroes[] = {0, 0, 0, 0, 0};
std::string out(QUIC_ARRAYSIZE(zeroes), 0);
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.cc
index 6feaa8a0e9d..c3dd2aa142b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.cc
@@ -15,6 +15,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
@@ -117,7 +118,8 @@ bool CryptoFramer::HasTag(QuicTag tag) const {
}
void CryptoFramer::ForceHandshake() {
- QuicDataReader reader(buffer_.data(), buffer_.length(), HOST_BYTE_ORDER);
+ QuicDataReader reader(buffer_.data(), buffer_.length(),
+ quiche::HOST_BYTE_ORDER);
for (const std::pair<QuicTag, size_t>& item : tags_and_lengths_) {
QuicStringPiece value;
if (reader.BytesRemaining() < item.second) {
@@ -156,7 +158,7 @@ std::unique_ptr<QuicData> CryptoFramer::ConstructHandshakeMessage(
}
std::unique_ptr<char[]> buffer(new char[len]);
- QuicDataWriter writer(len, buffer.get(), HOST_BYTE_ORDER);
+ QuicDataWriter writer(len, buffer.get(), quiche::HOST_BYTE_ORDER);
if (!writer.WriteTag(message.tag())) {
DCHECK(false) << "Failed to write message tag.";
return nullptr;
@@ -244,7 +246,8 @@ void CryptoFramer::Clear() {
QuicErrorCode CryptoFramer::Process(QuicStringPiece input) {
// Add this data to the buffer.
buffer_.append(input.data(), input.length());
- QuicDataReader reader(buffer_.data(), buffer_.length(), HOST_BYTE_ORDER);
+ QuicDataReader reader(buffer_.data(), buffer_.length(),
+ quiche::HOST_BYTE_ORDER);
switch (state_) {
case STATE_READING_TAG:
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 022a86b9227..56f0bd62a1f 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
@@ -12,10 +12,10 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_socket_address_coder.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
@@ -57,7 +57,7 @@ void CryptoHandshakeMessage::Clear() {
}
const QuicData& CryptoHandshakeMessage::GetSerialized() const {
- if (!serialized_.get()) {
+ if (!serialized_) {
serialized_ = CryptoFramer::ConstructHandshakeMessage(*this);
}
return *serialized_;
@@ -73,14 +73,15 @@ void CryptoHandshakeMessage::SetVersionVector(
QuicVersionLabelVector version_labels;
for (ParsedQuicVersion version : versions) {
version_labels.push_back(
- QuicEndian::HostToNet32(CreateQuicVersionLabel(version)));
+ quiche::QuicheEndian::HostToNet32(CreateQuicVersionLabel(version)));
}
SetVector(tag, version_labels);
}
void CryptoHandshakeMessage::SetVersion(QuicTag tag,
ParsedQuicVersion version) {
- SetValue(tag, QuicEndian::HostToNet32(CreateQuicVersionLabel(version)));
+ SetValue(tag,
+ quiche::QuicheEndian::HostToNet32(CreateQuicVersionLabel(version)));
}
void CryptoHandshakeMessage::SetStringPiece(QuicTag tag,
@@ -128,7 +129,7 @@ QuicErrorCode CryptoHandshakeMessage::GetVersionLabelList(
}
for (size_t i = 0; i < out->size(); ++i) {
- (*out)[i] = QuicEndian::HostToNet32((*out)[i]);
+ (*out)[i] = quiche::QuicheEndian::HostToNet32((*out)[i]);
}
return QUIC_NO_ERROR;
@@ -142,7 +143,7 @@ QuicErrorCode CryptoHandshakeMessage::GetVersionLabel(
return error;
}
- *out = QuicEndian::HostToNet32(*out);
+ *out = quiche::QuicheEndian::HostToNet32(*out);
return QUIC_NO_ERROR;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message_test.cc
index f595581601f..b6dfdd4cdaa 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message_test.cc
@@ -6,8 +6,8 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
namespace test {
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_printer_bin.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_printer_bin.cc
index ecbcab82e53..67cd531dd72 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_printer_bin.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_printer_bin.cc
@@ -14,7 +14,6 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
-using quic::Perspective;
using std::cerr;
using std::cout;
using std::endl;
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 4d5a890bba2..9707fb5b0ca 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
@@ -176,6 +176,11 @@ const QuicTag kILD3 = TAG('I', 'L', 'D', '3'); // IETF style loss detection
// with 1/4 RTT time threshold
// and adaptive packet
// threshold
+const QuicTag kILD4 = TAG('I', 'L', 'D', '4'); // IETF style loss detection
+ // with both adaptive time
+ // threshold (default 1/4 RTT)
+ // and adaptive packet
+ // threshold
// TODO(fayang): Remove this connection option when QUIC_VERSION_35, is removed
// Since MAX_HEADER_LIST_SIZE settings frame is supported instead.
const QuicTag kSMHL = TAG('S', 'M', 'H', 'L'); // Support MAX_HEADER_LIST_SIZE
@@ -194,6 +199,16 @@ const QuicTag k8PTO = TAG('8', 'P', 'T', 'O'); // Closes connection on 8
// consecutive PTOs.
const QuicTag kPTOS = TAG('P', 'T', 'O', 'S'); // Skip packet number before
// sending the last PTO.
+const QuicTag kPTOA = TAG('P', 'T', 'O', 'A'); // Do not add max ack delay
+ // when computing PTO timeout
+ // if an immediate ACK is
+ // expected.
+const QuicTag kPEB1 = TAG('P', 'E', 'B', '1'); // Start exponential backoff
+ // since 1st PTO.
+const QuicTag kPEB2 = TAG('P', 'E', 'B', '2'); // Start exponential backoff
+ // since 2nd PTO.
+const QuicTag kPVS1 = TAG('P', 'V', 'S', '1'); // Use 2 * rttvar when
+ // calculating PTO timeout.
// 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
@@ -217,6 +232,12 @@ const QuicTag kBWS2 = TAG('B', 'W', 'S', '2'); // Server bw resumption v2.
const QuicTag kBWS3 = TAG('B', 'W', 'S', '3'); // QUIC Initial CWND - Control.
const QuicTag kBWS4 = TAG('B', 'W', 'S', '4'); // QUIC Initial CWND - Enabled.
const QuicTag kBWS5 = TAG('B', 'W', 'S', '5'); // QUIC Initial CWND up and down
+const QuicTag kBWS6 = TAG('B', 'W', 'S', '6'); // QUIC Initial CWND - Enabled
+ // with 0.5 * default
+ // multiplier.
+const QuicTag kBWS7 = TAG('B', 'W', 'S', '7'); // QUIC Initial CWND - Enabled
+ // with 0.75 * default
+ // multiplier.
// Enable path MTU discovery experiment.
const QuicTag kMTUH = TAG('M', 'T', 'U', 'H'); // High-target MTU discovery.
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_server_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_server_test.cc
index b869f8bdeea..2db49d22a42 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
@@ -22,7 +22,6 @@
#include "net/third_party/quiche/src/quic/core/quic_socket_address_coder.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
@@ -33,6 +32,7 @@
#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
namespace test {
@@ -125,7 +125,7 @@ class CryptoServerTest : public QuicTestWithParam<TestParams> {
config_.GenerateConfig(rand_, &clock_, config_options_);
primary_config.set_primary_time(clock_.WallNow().ToUNIXSeconds());
std::unique_ptr<CryptoHandshakeMessage> msg(
- config_.AddConfig(std::move(primary_config), clock_.WallNow()));
+ config_.AddConfig(primary_config, clock_.WallNow()));
QuicStringPiece orbit;
CHECK(msg->GetStringPiece(kORBT, &orbit));
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 59cc9673653..037990ae797 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
@@ -30,6 +30,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
@@ -109,8 +110,8 @@ void CryptoUtils::SetKeyAndIV(const EVP_MD* prf,
namespace {
-static_assert(kQuicIetfDraftVersion == 23, "Salts do not match draft version");
-// Salt from https://tools.ietf.org/html/draft-ietf-quic-tls-23#section-5.2
+static_assert(kQuicIetfDraftVersion == 24, "Salts do not match draft version");
+// Salt from https://tools.ietf.org/html/draft-ietf-quic-tls-24#section-5.2
const uint8_t kDraft23InitialSalt[] = {0xc3, 0xee, 0xf7, 0x12, 0xc7, 0x2e, 0xbb,
0x5a, 0x11, 0xa7, 0xd2, 0x43, 0x2b, 0xb4,
0x63, 0x65, 0xbe, 0xf9, 0xf5, 0x02};
@@ -141,7 +142,7 @@ const uint8_t kQ099Salt[] = {0xc0, 0xa2, 0xee, 0x20, 0xc7, 0xe1, 0x83,
const uint8_t* InitialSaltForVersion(const ParsedQuicVersion& version,
size_t* out_len) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
"Supported versions out of sync with initial encryption salts");
switch (version.handshake_protocol) {
case PROTOCOL_QUIC_CRYPTO:
@@ -299,7 +300,7 @@ bool CryptoUtils::DeriveKeys(const ParsedQuicVersion& version,
psk_premaster_secret = std::make_unique<char[]>(psk_premaster_secret_size);
QuicDataWriter writer(psk_premaster_secret_size, psk_premaster_secret.get(),
- HOST_BYTE_ORDER);
+ quiche::HOST_BYTE_ORDER);
if (!writer.WriteStringPiece(label) || !writer.WriteUInt8(0) ||
!writer.WriteStringPiece(pre_shared_key) ||
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.h b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.h
index cb02dd79542..da746e3d63c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.h
@@ -32,7 +32,7 @@ class QUIC_EXPORT_PRIVATE CryptoUtils {
// Diversification is a utility class that's used to act like a union type.
// Values can be created by calling the functions like |NoDiversification|,
// below.
- class Diversification {
+ class QUIC_EXPORT_PRIVATE Diversification {
public:
enum Mode {
NEVER, // Key diversification will never be used. Forward secure
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.h b/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.h
index c695523ef32..127dc62ea14 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.h
@@ -25,7 +25,7 @@ class QUIC_EXPORT_PRIVATE AsynchronousKeyExchange {
// Callback base class for receiving the results of an async call to
// CalculateSharedKeys.
- class Callback {
+ class QUIC_EXPORT_PRIVATE Callback {
public:
Callback() = default;
virtual ~Callback() = default;
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 af0a8868cb5..51d8b11695b 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
@@ -10,6 +10,7 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
@@ -50,7 +51,7 @@ bool NullDecrypter::DecryptPacket(uint64_t /*packet_number*/,
size_t* output_length,
size_t max_output_length) {
QuicDataReader reader(ciphertext.data(), ciphertext.length(),
- HOST_BYTE_ORDER);
+ quiche::HOST_BYTE_ORDER);
QuicUint128 hash;
if (!ReadHash(&reader, &hash)) {
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 4ad9b2ad382..1fe0fdfc8bf 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
@@ -75,7 +75,7 @@ size_t NullEncrypter::GetIVSize() const {
}
size_t NullEncrypter::GetMaxPlaintextSize(size_t ciphertext_size) const {
- return ciphertext_size - GetHashLength();
+ return ciphertext_size - std::min(ciphertext_size, GetHashLength());
}
size_t NullEncrypter::GetCiphertextSize(size_t plaintext_size) const {
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter_test.cc
index fd95cc6fb76..c6a89efbf29 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/null_encrypter_test.cc
@@ -87,6 +87,7 @@ TEST_F(NullEncrypterTest, GetMaxPlaintextSize) {
EXPECT_EQ(1000u, encrypter.GetMaxPlaintextSize(1012));
EXPECT_EQ(100u, encrypter.GetMaxPlaintextSize(112));
EXPECT_EQ(10u, encrypter.GetMaxPlaintextSize(22));
+ EXPECT_EQ(0u, encrypter.GetMaxPlaintextSize(11));
}
TEST_F(NullEncrypterTest, GetCiphertextSize) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source.h b/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source.h
index fd890987d5d..f774efc3f22 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source.h
@@ -37,13 +37,13 @@ class QUIC_EXPORT_PRIVATE ProofSource {
// Details is an abstract class which acts as a container for any
// implementation-specific details that a ProofSource wants to return.
- class Details {
+ class QUIC_EXPORT_PRIVATE Details {
public:
virtual ~Details() {}
};
// Callback base class for receiving the results of an async call to GetProof.
- class Callback {
+ class QUIC_EXPORT_PRIVATE Callback {
public:
Callback() {}
virtual ~Callback() {}
@@ -74,7 +74,7 @@ class QUIC_EXPORT_PRIVATE ProofSource {
};
// Base class for signalling the completion of a call to ComputeTlsSignature.
- class SignatureCallback {
+ class QUIC_EXPORT_PRIVATE SignatureCallback {
public:
SignatureCallback() {}
virtual ~SignatureCallback() = default;
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache.h b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache.h
index 20031874c83..586ea88f676 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache.h
@@ -52,7 +52,7 @@ class QUIC_EXPORT_PRIVATE QuicCompressedCertsCache {
// A wrapper of the tuple:
// |chain, client_common_set_hashes, client_cached_cert_hashes|
// to identify uncompressed representation of certs.
- struct UncompressedCerts {
+ struct QUIC_EXPORT_PRIVATE UncompressedCerts {
UncompressedCerts();
UncompressedCerts(
const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
@@ -68,7 +68,7 @@ class QUIC_EXPORT_PRIVATE QuicCompressedCertsCache {
// Certs stored by QuicCompressedCertsCache where uncompressed certs data is
// used to identify the uncompressed representation of certs and
// |compressed_cert| is the cached compressed representation.
- class CachedCerts {
+ class QUIC_EXPORT_PRIVATE CachedCerts {
public:
CachedCerts();
CachedCerts(const UncompressedCerts& uncompressed_certs,
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 75b2e6a2884..d674126b6df 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
@@ -28,7 +28,6 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_client_stats.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
@@ -61,7 +60,13 @@ void RecordDiskCacheServerConfigState(
QuicCryptoClientConfig::QuicCryptoClientConfig(
std::unique_ptr<ProofVerifier> proof_verifier)
+ : QuicCryptoClientConfig(std::move(proof_verifier), nullptr) {}
+
+QuicCryptoClientConfig::QuicCryptoClientConfig(
+ std::unique_ptr<ProofVerifier> proof_verifier,
+ std::unique_ptr<SessionCache> session_cache)
: proof_verifier_(std::move(proof_verifier)),
+ session_cache_(std::move(session_cache)),
ssl_ctx_(TlsClientConnection::CreateSslCtx()) {
DCHECK(proof_verifier_.get());
SetDefaults();
@@ -120,7 +125,7 @@ QuicCryptoClientConfig::CachedState::GetServerConfig() const {
return nullptr;
}
- if (!scfg_.get()) {
+ if (!scfg_) {
scfg_ = CryptoFramer::ParseMessage(server_config_);
DCHECK(scfg_.get());
}
@@ -850,6 +855,10 @@ ProofVerifier* QuicCryptoClientConfig::proof_verifier() const {
return proof_verifier_.get();
}
+SessionCache* QuicCryptoClientConfig::session_cache() const {
+ return session_cache_.get();
+}
+
SSL_CTX* QuicCryptoClientConfig::ssl_ctx() const {
return ssl_ctx_.get();
}
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 838b2eef010..a3e1bcd18b2 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
@@ -12,8 +12,10 @@
#include <vector>
#include "third_party/boringssl/src/include/openssl/base.h"
+#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
+#include "net/third_party/quiche/src/quic/core/crypto/transport_parameters.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
@@ -27,6 +29,53 @@ class ProofVerifier;
class ProofVerifyDetails;
class QuicRandom;
+// QuicResumptionState stores the state a client needs for performing connection
+// resumption.
+struct QUIC_EXPORT_PRIVATE QuicResumptionState {
+ // |tls_session| holds the cryptographic state necessary for a resumption. It
+ // includes the ALPN negotiated on the connection where the ticket was
+ // received.
+ bssl::UniquePtr<SSL_SESSION> tls_session;
+
+ // If the application using QUIC doesn't support 0-RTT handshakes or the
+ // client didn't receive a 0-RTT capable session ticket from the server,
+ // |transport_params| will be null. Otherwise, it will contain the transport
+ // parameters received from the server on the original connection.
+ std::unique_ptr<TransportParameters> transport_params;
+
+ // If |transport_params| is null, then |application_state| is ignored and
+ // should be empty. |application_state| contains serialized state that the
+ // client received from the server at the application layer that the client
+ // needs to remember when performing a 0-RTT handshake.
+ std::vector<uint8_t> application_state;
+};
+
+// SessionCache is an interface for managing storing and retrieving
+// QuicResumptionState structs.
+class QUIC_EXPORT_PRIVATE SessionCache {
+ public:
+ virtual ~SessionCache() {}
+
+ // Inserts |state| into the cache, keyed by |server_id|. Insert is called
+ // after a session ticket is received. If the session ticket is valid for
+ // 0-RTT, there may be a delay between its receipt and the call to Insert
+ // while waiting for application state for |state|.
+ //
+ // Insert may be called multiple times per connection. SessionCache
+ // implementations should support storing multiple entries per server ID.
+ virtual void Insert(const QuicServerId& server_id,
+ std::unique_ptr<QuicResumptionState> state) = 0;
+
+ // Lookup is called once at the beginning of each TLS handshake to potentially
+ // provide the saved state both for the TLS handshake and for sending 0-RTT
+ // data (if supported). Lookup may return a nullptr. Implementations should
+ // delete cache entries after returning them in Lookup so that session tickets
+ // are used only once.
+ virtual std::unique_ptr<QuicResumptionState> Lookup(
+ const QuicServerId& server_id,
+ const SSL_CTX* ctx) = 0;
+};
+
// QuicCryptoClientConfig contains crypto-related configuration settings for a
// client. Note that this object isn't thread-safe. It's designed to be used on
// a single thread at a time.
@@ -195,7 +244,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
};
// Used to filter server ids for partial config deletion.
- class ServerIdFilter {
+ class QUIC_EXPORT_PRIVATE ServerIdFilter {
public:
virtual ~ServerIdFilter() {}
@@ -203,8 +252,11 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
virtual bool Matches(const QuicServerId& server_id) const = 0;
};
+ // DEPRECATED: Use the constructor below instead.
explicit QuicCryptoClientConfig(
std::unique_ptr<ProofVerifier> proof_verifier);
+ QuicCryptoClientConfig(std::unique_ptr<ProofVerifier> proof_verifier,
+ std::unique_ptr<SessionCache> session_cache);
QuicCryptoClientConfig(const QuicCryptoClientConfig&) = delete;
QuicCryptoClientConfig& operator=(const QuicCryptoClientConfig&) = delete;
~QuicCryptoClientConfig();
@@ -309,7 +361,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
std::string* error_details);
ProofVerifier* proof_verifier() const;
-
+ SessionCache* session_cache() const;
SSL_CTX* ssl_ctx() const;
// Initialize the CachedState from |canonical_crypto_config| for the
@@ -388,6 +440,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
std::vector<std::string> canonical_suffixes_;
std::unique_ptr<ProofVerifier> proof_verifier_;
+ std::unique_ptr<SessionCache> session_cache_;
bssl::UniquePtr<SSL_CTX> ssl_ctx_;
// The |user_agent_id_| passed in QUIC's CHLO message.
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc
index 683180bf030..8b5f116d107 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc
@@ -10,7 +10,6 @@
#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
@@ -115,11 +114,9 @@ TEST_F(QuicCryptoClientConfigTest, CachedState_ServerDesignatedConnectionId) {
TEST_F(QuicCryptoClientConfigTest, CachedState_ServerIdConsumedBeforeSet) {
QuicCryptoClientConfig::CachedState state;
EXPECT_FALSE(state.has_server_designated_connection_id());
-#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
- EXPECT_DEBUG_DEATH(state.GetNextServerDesignatedConnectionId(),
- "Attempting to consume a connection id "
- "that was never designated.");
-#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
+ EXPECT_QUIC_DEBUG_DEATH(state.GetNextServerDesignatedConnectionId(),
+ "Attempting to consume a connection id "
+ "that was never designated.");
}
TEST_F(QuicCryptoClientConfigTest, CachedState_ServerNonce) {
@@ -156,11 +153,9 @@ TEST_F(QuicCryptoClientConfigTest, CachedState_ServerNonce) {
TEST_F(QuicCryptoClientConfigTest, CachedState_ServerNonceConsumedBeforeSet) {
QuicCryptoClientConfig::CachedState state;
EXPECT_FALSE(state.has_server_nonce());
-#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
- EXPECT_DEBUG_DEATH(state.GetNextServerNonce(),
- "Attempting to consume a server nonce "
- "that was never designated.");
-#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
+ EXPECT_QUIC_DEBUG_DEATH(state.GetNextServerNonce(),
+ "Attempting to consume a server nonce "
+ "that was never designated.");
}
TEST_F(QuicCryptoClientConfigTest, CachedState_InitializeFrom) {
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 c211cdb3345..d5689862fcf 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
@@ -38,7 +38,6 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_cert_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_fallthrough.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
@@ -385,14 +384,14 @@ std::unique_ptr<CryptoHandshakeMessage> QuicCryptoServerConfig::AddConfig(
std::unique_ptr<CryptoHandshakeMessage> msg =
CryptoFramer::ParseMessage(protobuf.config());
- if (!msg.get()) {
+ if (!msg) {
QUIC_LOG(WARNING) << "Failed to parse server config message";
return nullptr;
}
QuicReferenceCountedPointer<Config> config =
ParseConfigProtobuf(protobuf, /* is_fallback = */ false);
- if (!config.get()) {
+ if (!config) {
QUIC_LOG(WARNING) << "Failed to parse server config message";
return nullptr;
}
@@ -896,7 +895,7 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterCalculateSharedKeys(
}
std::unique_ptr<CryptoHandshakeMessage> cetv(CryptoFramer::ParseMessage(
QuicStringPiece(plaintext, plaintext_length)));
- if (!cetv.get()) {
+ if (!cetv) {
context->Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, "CETV parse error");
return;
}
@@ -1281,7 +1280,6 @@ void QuicCryptoServerConfig::EvaluateClientHello(
// Server nonce is optional, and used for key derivation if present.
client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce);
- QUIC_DVLOG(1) << "No 0-RTT replay protection in QUIC_VERSION_33 and higher.";
// If the server nonce is empty and we're requiring handshake confirmation
// for DoS reasons then we must reject the CHLO.
if (GetQuicReloadableFlag(quic_require_handshake_confirmation) &&
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 3fb424d4022..809ebaec575 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
@@ -41,7 +41,7 @@ struct QuicSignedServerConfig;
// ClientHelloInfo contains information about a client hello message that is
// only kept for as long as it's being processed.
-struct ClientHelloInfo {
+struct QUIC_EXPORT_PRIVATE ClientHelloInfo {
ClientHelloInfo(const QuicIpAddress& in_client_ip, QuicWallTime in_now);
ClientHelloInfo(const ClientHelloInfo& other);
~ClientHelloInfo();
@@ -68,7 +68,7 @@ class QuicCryptoServerConfigPeer;
} // namespace test
// Hook that allows application code to subscribe to primary config changes.
-class PrimaryConfigChangedCallback {
+class QUIC_EXPORT_PRIVATE PrimaryConfigChangedCallback {
public:
PrimaryConfigChangedCallback();
PrimaryConfigChangedCallback(const PrimaryConfigChangedCallback&) = delete;
@@ -128,7 +128,7 @@ class QUIC_EXPORT_PRIVATE ProcessClientHelloResultCallback {
// Callback used to receive the results of a call to
// BuildServerConfigUpdateMessage.
-class BuildServerConfigUpdateMessageResultCallback {
+class QUIC_EXPORT_PRIVATE BuildServerConfigUpdateMessageResultCallback {
public:
BuildServerConfigUpdateMessageResultCallback() = default;
virtual ~BuildServerConfigUpdateMessageResultCallback() {}
@@ -141,7 +141,7 @@ class BuildServerConfigUpdateMessageResultCallback {
// Object that is interested in built rejections (which include REJ, SREJ and
// cheap SREJ).
-class RejectionObserver {
+class QUIC_EXPORT_PRIVATE RejectionObserver {
public:
RejectionObserver() = default;
virtual ~RejectionObserver() {}
@@ -511,7 +511,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig {
QUIC_SHARED_LOCKS_REQUIRED(configs_lock_);
// A snapshot of the configs associated with an in-progress handshake.
- struct Configs {
+ struct QUIC_EXPORT_PRIVATE Configs {
QuicReferenceCountedPointer<Config> requested;
QuicReferenceCountedPointer<Config> primary;
QuicReferenceCountedPointer<Config> fallback;
@@ -552,7 +552,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig {
// Convenience class which carries the arguments passed to
// |ProcessClientHellp| along.
- class ProcessClientHelloContext {
+ class QUIC_EXPORT_PRIVATE ProcessClientHelloContext {
public:
ProcessClientHelloContext(
QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config_test.cc
index bc9b2efe200..8f9e4ba776a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config_test.cc
@@ -18,6 +18,7 @@
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.h"
@@ -351,7 +352,7 @@ class CryptoServerConfigsTest : public QuicTest {
QuicCryptoServerConfig::GenerateConfig(rand_, &clock_, options);
protobuf.set_primary_time(primary_time);
protobuf.set_priority(priority);
- if (std::string(server_config_id).find("INVALID") == 0) {
+ if (QuicTextUtils::StartsWith(std::string(server_config_id), "INVALID")) {
protobuf.clear_key();
has_invalid = true;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h
index 09006eef4db..94d45bc91a6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h
@@ -15,7 +15,7 @@ namespace quic {
// QuicHKDF implements the key derivation function specified in RFC 5869
// (using SHA-256) and outputs key material, as needed by QUIC.
// See https://tools.ietf.org/html/rfc5869 for details.
-class QUIC_EXPORT QuicHKDF {
+class QUIC_EXPORT_PRIVATE QuicHKDF {
public:
// |secret|: the input shared secret (or, from RFC 5869, the IKM).
// |salt|: an (optional) public salt / non-secret random value. While
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.cc
index f28af660e90..7d112245b3c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.cc
@@ -14,11 +14,14 @@ TlsClientConnection::TlsClientConnection(SSL_CTX* ssl_ctx, Delegate* delegate)
bssl::UniquePtr<SSL_CTX> TlsClientConnection::CreateSslCtx() {
bssl::UniquePtr<SSL_CTX> ssl_ctx = TlsConnection::CreateSslCtx();
// Configure certificate verification.
- // TODO(nharper): This only verifies certs on initial connection, not on
- // resumption. Chromium has this callback be a no-op and verifies the
- // certificate after the connection is complete. We need to re-verify on
- // resumption in case of expiration or revocation/distrust.
SSL_CTX_set_custom_verify(ssl_ctx.get(), SSL_VERIFY_PEER, &VerifyCallback);
+ int reverify_on_resume_enabled = 1;
+ SSL_CTX_set_reverify_on_resume(ssl_ctx.get(), reverify_on_resume_enabled);
+
+ // Configure session caching.
+ SSL_CTX_set_session_cache_mode(
+ ssl_ctx.get(), SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL);
+ SSL_CTX_sess_set_new_cb(ssl_ctx.get(), NewSessionCallback);
return ssl_ctx;
}
@@ -30,4 +33,11 @@ enum ssl_verify_result_t TlsClientConnection::VerifyCallback(
->delegate_->VerifyCert(out_alert);
}
+// static
+int TlsClientConnection::NewSessionCallback(SSL* ssl, SSL_SESSION* session) {
+ static_cast<TlsClientConnection*>(ConnectionFromSsl(ssl))
+ ->delegate_->InsertSession(bssl::UniquePtr<SSL_SESSION>(session));
+ return 1;
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.h b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.h
index a9212ff2a72..035f420a835 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.h
@@ -15,7 +15,7 @@ class QUIC_EXPORT_PRIVATE TlsClientConnection : public TlsConnection {
public:
// A TlsClientConnection::Delegate implements the client-specific methods that
// are set as callbacks for an SSL object.
- class Delegate {
+ class QUIC_EXPORT_PRIVATE Delegate {
public:
virtual ~Delegate() {}
@@ -26,6 +26,9 @@ class QUIC_EXPORT_PRIVATE TlsClientConnection : public TlsConnection {
// or ssl_verify_retry if verification is happening asynchronously.
virtual enum ssl_verify_result_t VerifyCert(uint8_t* out_alert) = 0;
+ // Called when a NewSessionTicket is received from the server.
+ virtual void InsertSession(bssl::UniquePtr<SSL_SESSION> session) = 0;
+
// Provides the delegate for callbacks that are shared between client and
// server.
virtual TlsConnection::Delegate* ConnectionDelegate() = 0;
@@ -43,6 +46,10 @@ class QUIC_EXPORT_PRIVATE TlsClientConnection : public TlsConnection {
// implementation is delegated to Delegate::VerifyCert.
static enum ssl_verify_result_t VerifyCallback(SSL* ssl, uint8_t* out_alert);
+ // Registered as the callback for SSL_CTX_sess_set_new_cb, which calls
+ // Delegate::InsertSession.
+ static int NewSessionCallback(SSL* ssl, SSL_SESSION* session);
+
Delegate* delegate_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.h b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.h
index 4774ba6924d..fd4f64b1978 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.h
@@ -26,7 +26,7 @@ class QUIC_EXPORT_PRIVATE TlsConnection {
public:
// A TlsConnection::Delegate implements the methods that are set as callbacks
// of TlsConnection.
- class Delegate {
+ class QUIC_EXPORT_PRIVATE Delegate {
public:
virtual ~Delegate() {}
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 927c75af318..f539a089d2c 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
@@ -16,6 +16,7 @@ bssl::UniquePtr<SSL_CTX> TlsServerConnection::CreateSslCtx() {
SSL_CTX_set_tlsext_servername_callback(ssl_ctx.get(),
&SelectCertificateCallback);
SSL_CTX_set_alpn_select_cb(ssl_ctx.get(), &SelectAlpnCallback, nullptr);
+ SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_NO_TICKET);
return ssl_ctx;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h
index 0e78d1bf015..96d71e2bef1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h
@@ -15,7 +15,7 @@ class QUIC_EXPORT_PRIVATE TlsServerConnection : public TlsConnection {
public:
// A TlsServerConnection::Delegate implement the server-specific methods that
// are set as callbacks for an SSL object.
- class Delegate {
+ class QUIC_EXPORT_PRIVATE Delegate {
public:
virtual ~Delegate() {}
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 ce6cc2005c3..a870017b0b3 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
@@ -44,6 +44,8 @@ enum TransportParameters::TransportParameterId : uint16_t {
kPreferredAddress = 0xd,
kActiveConnectionIdLimit = 0xe,
+ kMaxDatagramFrameSize = 0x20,
+
kGoogleQuicParam = 18257, // Used for non-standard Google-specific params.
kGoogleQuicVersion =
18258, // Used to transmit version and supported_versions.
@@ -95,6 +97,8 @@ std::string TransportParameterIdToString(
return "preferred_address";
case TransportParameters::kActiveConnectionIdLimit:
return "active_connection_id_limit";
+ case TransportParameters::kMaxDatagramFrameSize:
+ return "max_datagram_frame_size";
case TransportParameters::kGoogleQuicParam:
return "google";
case TransportParameters::kGoogleQuicVersion:
@@ -279,6 +283,7 @@ std::string TransportParameters::ToString() const {
preferred_address->ToString();
}
rv += active_connection_id_limit.ToString(/*for_use_in_list=*/true);
+ rv += max_datagram_frame_size.ToString(/*for_use_in_list=*/true);
if (google_quic_params) {
rv += " " + TransportParameterIdToString(kGoogleQuicParam);
}
@@ -313,7 +318,8 @@ TransportParameters::TransportParameters()
0,
kMaxMaxAckDelayTransportParam),
disable_migration(false),
- active_connection_id_limit(kActiveConnectionIdLimit)
+ active_connection_id_limit(kActiveConnectionIdLimit),
+ max_datagram_frame_size(kMaxDatagramFrameSize)
// Important note: any new transport parameters must be added
// to TransportParameters::AreValid, SerializeTransportParameters and
// ParseTransportParameters.
@@ -354,15 +360,15 @@ bool TransportParameters::AreValid() const {
QUIC_BUG << "Preferred address family failure";
return false;
}
- const bool ok = idle_timeout_milliseconds.IsValid() &&
- max_packet_size.IsValid() && initial_max_data.IsValid() &&
- initial_max_stream_data_bidi_local.IsValid() &&
- initial_max_stream_data_bidi_remote.IsValid() &&
- initial_max_stream_data_uni.IsValid() &&
- initial_max_streams_bidi.IsValid() &&
- initial_max_streams_uni.IsValid() &&
- ack_delay_exponent.IsValid() && max_ack_delay.IsValid() &&
- active_connection_id_limit.IsValid();
+ const bool ok =
+ idle_timeout_milliseconds.IsValid() && max_packet_size.IsValid() &&
+ initial_max_data.IsValid() &&
+ initial_max_stream_data_bidi_local.IsValid() &&
+ initial_max_stream_data_bidi_remote.IsValid() &&
+ initial_max_stream_data_uni.IsValid() &&
+ initial_max_streams_bidi.IsValid() && initial_max_streams_uni.IsValid() &&
+ ack_delay_exponent.IsValid() && max_ack_delay.IsValid() &&
+ active_connection_id_limit.IsValid() && max_datagram_frame_size.IsValid();
if (!ok) {
QUIC_DLOG(ERROR) << "Invalid transport parameters " << *this;
}
@@ -445,7 +451,8 @@ bool SerializeTransportParameters(ParsedQuicVersion /*version*/,
!in.initial_max_streams_uni.WriteToCbb(&params) ||
!in.ack_delay_exponent.WriteToCbb(&params) ||
!in.max_ack_delay.WriteToCbb(&params) ||
- !in.active_connection_id_limit.WriteToCbb(&params)) {
+ !in.active_connection_id_limit.WriteToCbb(&params) ||
+ !in.max_datagram_frame_size.WriteToCbb(&params)) {
QUIC_BUG << "Failed to write integers for " << in;
return false;
}
@@ -734,6 +741,9 @@ bool ParseTransportParameters(ParsedQuicVersion version,
case TransportParameters::kActiveConnectionIdLimit:
parse_success = out->active_connection_id_limit.ReadFromCbs(&value);
break;
+ case TransportParameters::kMaxDatagramFrameSize:
+ parse_success = out->max_datagram_frame_size.ReadFromCbs(&value);
+ break;
case TransportParameters::kGoogleQuicParam: {
if (out->google_quic_params) {
QUIC_DLOG(ERROR) << "Received a second Google parameter";
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h
index 22dc252405c..c5ec1a4f71b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h
@@ -168,6 +168,10 @@ struct QUIC_EXPORT_PRIVATE TransportParameters {
// to store.
IntegerParameter active_connection_id_limit;
+ // Indicates support for the DATAGRAM frame and the maximum frame size that
+ // the sender accepts. See draft-pauly-quic-datagram.
+ IntegerParameter max_datagram_frame_size;
+
// Transport parameters used by Google QUIC but not IETF QUIC. This is
// serialized into a TransportParameter struct with a TransportParameterId of
// kGoogleQuicParamId.
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 90afe221bd7..61a6e0d4d6b 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
@@ -24,14 +24,10 @@ using testing::UnorderedElementsAre;
const ParsedQuicVersion kVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99);
const QuicVersionLabel kFakeVersionLabel = 0x01234567;
const QuicVersionLabel kFakeVersionLabel2 = 0x89ABCDEF;
-const QuicConnectionId kFakeOriginalConnectionId = TestConnectionId(0x1337);
const uint64_t kFakeIdleTimeoutMilliseconds = 12012;
const uint8_t kFakeStatelessResetTokenData[16] = {
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F};
-const std::vector<uint8_t> kFakeStatelessResetToken(
- kFakeStatelessResetTokenData,
- kFakeStatelessResetTokenData + sizeof(kFakeStatelessResetTokenData));
const uint64_t kFakeMaxPacketSize = 9001;
const uint64_t kFakeInitialMaxData = 101;
const uint64_t kFakeInitialMaxStreamDataBidiLocal = 2001;
@@ -43,14 +39,10 @@ const uint64_t kFakeAckDelayExponent = 10;
const uint64_t kFakeMaxAckDelay = 51;
const bool kFakeDisableMigration = true;
const uint64_t kFakeActiveConnectionIdLimit = 52;
-const QuicConnectionId kFakePreferredConnectionId = TestConnectionId(0xBEEF);
const uint8_t kFakePreferredStatelessResetTokenData[16] = {
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F};
-const std::vector<uint8_t> kFakePreferredStatelessResetToken(
- kFakePreferredStatelessResetTokenData,
- kFakePreferredStatelessResetTokenData +
- sizeof(kFakeStatelessResetTokenData));
+
const auto kCustomParameter1 =
static_cast<TransportParameters::TransportParameterId>(0xffcd);
const char* kCustomParameter1Value = "foo";
@@ -58,6 +50,27 @@ const auto kCustomParameter2 =
static_cast<TransportParameters::TransportParameterId>(0xff34);
const char* kCustomParameter2Value = "bar";
+QuicConnectionId CreateFakeOriginalConnectionId() {
+ return TestConnectionId(0x1337);
+}
+
+QuicConnectionId CreateFakePreferredConnectionId() {
+ return TestConnectionId(0xBEEF);
+}
+
+std::vector<uint8_t> CreateFakeStatelessResetToken() {
+ return std::vector<uint8_t>(
+ kFakeStatelessResetTokenData,
+ kFakeStatelessResetTokenData + sizeof(kFakeStatelessResetTokenData));
+}
+
+std::vector<uint8_t> CreateFakePreferredStatelessResetToken() {
+ return std::vector<uint8_t>(
+ kFakePreferredStatelessResetTokenData,
+ kFakePreferredStatelessResetTokenData +
+ sizeof(kFakePreferredStatelessResetTokenData));
+}
+
QuicSocketAddress CreateFakeV4SocketAddress() {
QuicIpAddress ipv4_address;
if (!ipv4_address.FromString("65.66.67.68")) { // 0x41, 0x42, 0x43, 0x44
@@ -81,8 +94,9 @@ CreateFakePreferredAddress() {
TransportParameters::PreferredAddress preferred_address;
preferred_address.ipv4_socket_address = CreateFakeV4SocketAddress();
preferred_address.ipv6_socket_address = CreateFakeV6SocketAddress();
- preferred_address.connection_id = kFakePreferredConnectionId;
- preferred_address.stateless_reset_token = kFakePreferredStatelessResetToken;
+ preferred_address.connection_id = CreateFakePreferredConnectionId();
+ preferred_address.stateless_reset_token =
+ CreateFakePreferredStatelessResetToken();
return std::make_unique<TransportParameters::PreferredAddress>(
preferred_address);
}
@@ -158,9 +172,9 @@ TEST_F(TransportParametersTest, RoundTripServer) {
orig_params.version = kFakeVersionLabel;
orig_params.supported_versions.push_back(kFakeVersionLabel);
orig_params.supported_versions.push_back(kFakeVersionLabel2);
- orig_params.original_connection_id = kFakeOriginalConnectionId;
+ orig_params.original_connection_id = CreateFakeOriginalConnectionId();
orig_params.idle_timeout_milliseconds.set_value(kFakeIdleTimeoutMilliseconds);
- orig_params.stateless_reset_token = kFakeStatelessResetToken;
+ orig_params.stateless_reset_token = CreateFakeStatelessResetToken();
orig_params.max_packet_size.set_value(kFakeMaxPacketSize);
orig_params.initial_max_data.set_value(kFakeInitialMaxData);
orig_params.initial_max_stream_data_bidi_local.set_value(
@@ -191,10 +205,11 @@ TEST_F(TransportParametersTest, RoundTripServer) {
EXPECT_EQ(2u, new_params.supported_versions.size());
EXPECT_EQ(kFakeVersionLabel, new_params.supported_versions[0]);
EXPECT_EQ(kFakeVersionLabel2, new_params.supported_versions[1]);
- EXPECT_EQ(kFakeOriginalConnectionId, new_params.original_connection_id);
+ EXPECT_EQ(CreateFakeOriginalConnectionId(),
+ new_params.original_connection_id);
EXPECT_EQ(kFakeIdleTimeoutMilliseconds,
new_params.idle_timeout_milliseconds.value());
- EXPECT_EQ(kFakeStatelessResetToken, new_params.stateless_reset_token);
+ EXPECT_EQ(CreateFakeStatelessResetToken(), new_params.stateless_reset_token);
EXPECT_EQ(kFakeMaxPacketSize, new_params.max_packet_size.value());
EXPECT_EQ(kFakeInitialMaxData, new_params.initial_max_data.value());
EXPECT_EQ(kFakeInitialMaxStreamDataBidiLocal,
@@ -215,9 +230,9 @@ TEST_F(TransportParametersTest, RoundTripServer) {
new_params.preferred_address->ipv4_socket_address);
EXPECT_EQ(CreateFakeV6SocketAddress(),
new_params.preferred_address->ipv6_socket_address);
- EXPECT_EQ(kFakePreferredConnectionId,
+ EXPECT_EQ(CreateFakePreferredConnectionId(),
new_params.preferred_address->connection_id);
- EXPECT_EQ(kFakePreferredStatelessResetToken,
+ EXPECT_EQ(CreateFakePreferredStatelessResetToken(),
new_params.preferred_address->stateless_reset_token);
EXPECT_EQ(kFakeActiveConnectionIdLimit,
new_params.active_connection_id_limit.value());
@@ -272,7 +287,7 @@ TEST_F(TransportParametersTest, NoClientParamsWithStatelessResetToken) {
orig_params.perspective = Perspective::IS_CLIENT;
orig_params.version = kFakeVersionLabel;
orig_params.idle_timeout_milliseconds.set_value(kFakeIdleTimeoutMilliseconds);
- orig_params.stateless_reset_token = kFakeStatelessResetToken;
+ orig_params.stateless_reset_token = CreateFakeStatelessResetToken();
orig_params.max_packet_size.set_value(kFakeMaxPacketSize);
std::vector<uint8_t> out;
@@ -543,10 +558,11 @@ TEST_F(TransportParametersTest, ParseServerParams) {
EXPECT_EQ(2u, new_params.supported_versions.size());
EXPECT_EQ(kFakeVersionLabel, new_params.supported_versions[0]);
EXPECT_EQ(kFakeVersionLabel2, new_params.supported_versions[1]);
- EXPECT_EQ(kFakeOriginalConnectionId, new_params.original_connection_id);
+ EXPECT_EQ(CreateFakeOriginalConnectionId(),
+ new_params.original_connection_id);
EXPECT_EQ(kFakeIdleTimeoutMilliseconds,
new_params.idle_timeout_milliseconds.value());
- EXPECT_EQ(kFakeStatelessResetToken, new_params.stateless_reset_token);
+ EXPECT_EQ(CreateFakeStatelessResetToken(), new_params.stateless_reset_token);
EXPECT_EQ(kFakeMaxPacketSize, new_params.max_packet_size.value());
EXPECT_EQ(kFakeInitialMaxData, new_params.initial_max_data.value());
EXPECT_EQ(kFakeInitialMaxStreamDataBidiLocal,
@@ -567,9 +583,9 @@ TEST_F(TransportParametersTest, ParseServerParams) {
new_params.preferred_address->ipv4_socket_address);
EXPECT_EQ(CreateFakeV6SocketAddress(),
new_params.preferred_address->ipv6_socket_address);
- EXPECT_EQ(kFakePreferredConnectionId,
+ EXPECT_EQ(CreateFakePreferredConnectionId(),
new_params.preferred_address->connection_id);
- EXPECT_EQ(kFakePreferredStatelessResetToken,
+ EXPECT_EQ(CreateFakePreferredStatelessResetToken(),
new_params.preferred_address->stateless_reset_token);
EXPECT_EQ(kFakeActiveConnectionIdLimit,
new_params.active_connection_id_limit.value());
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 389f1c04a0a..2946c01af8b 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
@@ -15,13 +15,6 @@ namespace {
const QuicPacketCount kMaxPrintRange = 128;
-uint64_t PacketNumberIntervalLength(
- const QuicInterval<QuicPacketNumber>& interval) {
- if (interval.Empty()) {
- return 0u;
- }
- return interval.max() - interval.min();
-}
} // namespace
bool IsAwaitingPacket(const QuicAckFrame& ack_frame,
@@ -86,77 +79,8 @@ void PacketNumberQueue::Add(QuicPacketNumber packet_number) {
if (!packet_number.IsInitialized()) {
return;
}
- // Check if the deque is empty
- if (packet_number_deque_.empty()) {
- packet_number_deque_.push_front(
- QuicInterval<QuicPacketNumber>(packet_number, packet_number + 1));
- return;
- }
- QuicInterval<QuicPacketNumber> back = packet_number_deque_.back();
-
- // Check for the typical case,
- // when the next packet in order is acked
- if (back.max() == packet_number) {
- packet_number_deque_.back().SetMax(packet_number + 1);
- return;
- }
- // Check if the next packet in order is skipped
- if (back.max() < packet_number) {
- packet_number_deque_.push_back(
- QuicInterval<QuicPacketNumber>(packet_number, packet_number + 1));
- return;
- }
-
- QuicInterval<QuicPacketNumber> front = packet_number_deque_.front();
- // Check if the packet can be popped on the front
- if (front.min() > packet_number + 1) {
- packet_number_deque_.push_front(
- QuicInterval<QuicPacketNumber>(packet_number, packet_number + 1));
- return;
- }
- if (front.min() == packet_number + 1) {
- packet_number_deque_.front().SetMin(packet_number);
- return;
- }
-
- int i = packet_number_deque_.size() - 1;
- // Iterating through the queue backwards
- // to find a proper place for the packet
- while (i >= 0) {
- QuicInterval<QuicPacketNumber> packet_interval = packet_number_deque_[i];
- DCHECK(packet_interval.min() < packet_interval.max());
- // Check if the packet is contained in an interval already
- if (packet_interval.Contains(packet_number)) {
- return;
- }
-
- // Check if the packet can extend an interval.
- if (packet_interval.max() == packet_number) {
- packet_number_deque_[i].SetMax(packet_number + 1);
- return;
- }
- // Check if the packet can extend an interval
- // and merge two intervals if needed.
- // There is no need to merge an interval in the previous
- // if statement, as all merges will happen here.
- if (packet_interval.min() == packet_number + 1) {
- packet_number_deque_[i].SetMin(packet_number);
- if (i > 0 && packet_number == packet_number_deque_[i - 1].max()) {
- packet_number_deque_[i - 1].SetMax(packet_interval.max());
- packet_number_deque_.erase(packet_number_deque_.begin() + i);
- }
- return;
- }
-
- // Check if we need to make a new interval for the packet
- if (packet_interval.max() < packet_number + 1) {
- packet_number_deque_.insert(
- packet_number_deque_.begin() + i + 1,
- QuicInterval<QuicPacketNumber>(packet_number, packet_number + 1));
- return;
- }
- i--;
- }
+ packet_number_intervals_.AddOptimizedForAppend(packet_number,
+ packet_number + 1);
}
void PacketNumberQueue::AddRange(QuicPacketNumber lower,
@@ -164,136 +88,81 @@ void PacketNumberQueue::AddRange(QuicPacketNumber lower,
if (!lower.IsInitialized() || !higher.IsInitialized() || lower >= higher) {
return;
}
- if (packet_number_deque_.empty()) {
- packet_number_deque_.push_front(
- QuicInterval<QuicPacketNumber>(lower, higher));
- return;
- }
- QuicInterval<QuicPacketNumber> back = packet_number_deque_.back();
- if (back.max() == lower) {
- // Check for the typical case,
- // when the next packet in order is acked
- packet_number_deque_.back().SetMax(higher);
- return;
- }
- if (back.max() < lower) {
- // Check if the next packet in order is skipped
- packet_number_deque_.push_back(
- QuicInterval<QuicPacketNumber>(lower, higher));
- return;
- }
- QuicInterval<QuicPacketNumber> front = packet_number_deque_.front();
- // Check if the packets are being added in reverse order
- if (front.min() == higher) {
- packet_number_deque_.front().SetMin(lower);
- } else if (front.min() > higher) {
- packet_number_deque_.push_front(
- QuicInterval<QuicPacketNumber>(lower, higher));
-
- } else {
- // Ranges must be above or below all existing ranges.
- QUIC_BUG << "AddRange only supports adding packets above or below the "
- << "current min:" << Min() << " and max:" << Max()
- << ", but adding [" << lower << "," << higher << ")";
- }
+ packet_number_intervals_.AddOptimizedForAppend(lower, higher);
}
bool PacketNumberQueue::RemoveUpTo(QuicPacketNumber higher) {
if (!higher.IsInitialized() || Empty()) {
return false;
}
- const QuicPacketNumber old_min = Min();
- while (!packet_number_deque_.empty()) {
- QuicInterval<QuicPacketNumber> front = packet_number_deque_.front();
- if (front.max() < higher) {
- packet_number_deque_.pop_front();
- } else if (front.min() < higher && front.max() >= higher) {
- packet_number_deque_.front().SetMin(higher);
- if (front.max() == higher) {
- packet_number_deque_.pop_front();
- }
- break;
- } else {
- break;
- }
- }
-
- return Empty() || old_min != Min();
+ return packet_number_intervals_.TrimLessThan(higher);
}
void PacketNumberQueue::RemoveSmallestInterval() {
- QUIC_BUG_IF(packet_number_deque_.size() < 2)
+ // TODO(wub): Move this QUIC_BUG to upper level.
+ QUIC_BUG_IF(packet_number_intervals_.Size() < 2)
<< (Empty() ? "No intervals to remove."
: "Can't remove the last interval.");
- packet_number_deque_.pop_front();
+ packet_number_intervals_.PopFront();
}
void PacketNumberQueue::Clear() {
- packet_number_deque_.clear();
+ packet_number_intervals_.Clear();
}
bool PacketNumberQueue::Contains(QuicPacketNumber packet_number) const {
- if (!packet_number.IsInitialized() || packet_number_deque_.empty()) {
- return false;
- }
- if (packet_number_deque_.front().min() > packet_number ||
- packet_number_deque_.back().max() <= packet_number) {
+ if (!packet_number.IsInitialized()) {
return false;
}
- for (QuicInterval<QuicPacketNumber> interval : packet_number_deque_) {
- if (interval.Contains(packet_number)) {
- return true;
- }
- }
- return false;
+ return packet_number_intervals_.Contains(packet_number);
}
bool PacketNumberQueue::Empty() const {
- return packet_number_deque_.empty();
+ return packet_number_intervals_.Empty();
}
QuicPacketNumber PacketNumberQueue::Min() const {
DCHECK(!Empty());
- return packet_number_deque_.front().min();
+ return packet_number_intervals_.begin()->min();
}
QuicPacketNumber PacketNumberQueue::Max() const {
DCHECK(!Empty());
- return packet_number_deque_.back().max() - 1;
+ return packet_number_intervals_.rbegin()->max() - 1;
}
QuicPacketCount PacketNumberQueue::NumPacketsSlow() const {
QuicPacketCount n_packets = 0;
- for (QuicInterval<QuicPacketNumber> interval : packet_number_deque_) {
- n_packets += PacketNumberIntervalLength(interval);
+ for (const auto& interval : packet_number_intervals_) {
+ n_packets += interval.Length();
}
return n_packets;
}
size_t PacketNumberQueue::NumIntervals() const {
- return packet_number_deque_.size();
+ return packet_number_intervals_.Size();
}
PacketNumberQueue::const_iterator PacketNumberQueue::begin() const {
- return packet_number_deque_.begin();
+ return packet_number_intervals_.begin();
}
PacketNumberQueue::const_iterator PacketNumberQueue::end() const {
- return packet_number_deque_.end();
+ return packet_number_intervals_.end();
}
PacketNumberQueue::const_reverse_iterator PacketNumberQueue::rbegin() const {
- return packet_number_deque_.rbegin();
+ return packet_number_intervals_.rbegin();
}
PacketNumberQueue::const_reverse_iterator PacketNumberQueue::rend() const {
- return packet_number_deque_.rend();
+ return packet_number_intervals_.rend();
}
QuicPacketCount PacketNumberQueue::LastIntervalLength() const {
DCHECK(!Empty());
- return PacketNumberIntervalLength(packet_number_deque_.back());
+ return packet_number_intervals_.rbegin()->Length();
}
// Largest min...max range for packet numbers where we print the numbers
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_ack_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_ack_frame.h
index 771d93e3285..9003c76e3d3 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_ack_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_ack_frame.h
@@ -8,6 +8,7 @@
#include <ostream>
#include "net/third_party/quiche/src/quic/core/quic_interval.h"
+#include "net/third_party/quiche/src/quic/core/quic_interval_set.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
@@ -28,16 +29,16 @@ class QUIC_EXPORT_PRIVATE PacketNumberQueue {
PacketNumberQueue& operator=(const PacketNumberQueue& other);
PacketNumberQueue& operator=(PacketNumberQueue&& other);
- typedef QuicDeque<QuicInterval<QuicPacketNumber>>::const_iterator
- const_iterator;
- typedef QuicDeque<QuicInterval<QuicPacketNumber>>::const_reverse_iterator
+ typedef QuicIntervalSet<QuicPacketNumber>::const_iterator const_iterator;
+ typedef QuicIntervalSet<QuicPacketNumber>::const_reverse_iterator
const_reverse_iterator;
// Adds |packet_number| to the set of packets in the queue.
void Add(QuicPacketNumber packet_number);
- // Adds packets between [lower, higher) to the set of packets in the queue. It
- // is undefined behavior to call this with |higher| < |lower|.
+ // Adds packets between [lower, higher) to the set of packets in the queue.
+ // No-op if |higher| < |lower|.
+ // NOTE(wub): Only used in tests as of Nov 2019.
void AddRange(QuicPacketNumber lower, QuicPacketNumber higher);
// Removes packets with values less than |higher| from the set of packets in
@@ -86,7 +87,7 @@ class QUIC_EXPORT_PRIVATE PacketNumberQueue {
const PacketNumberQueue& q);
private:
- QuicDeque<QuicInterval<QuicPacketNumber>> packet_number_deque_;
+ QuicIntervalSet<QuicPacketNumber> packet_number_intervals_;
};
struct QUIC_EXPORT_PRIVATE QuicAckFrame {
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 5e85fc0b4e3..e640179c460 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
@@ -254,6 +254,101 @@ QuicFrame CopyRetransmittableControlFrame(const QuicFrame& frame) {
return copy;
}
+QuicFrame CopyQuicFrame(QuicBufferAllocator* allocator,
+ const QuicFrame& frame) {
+ QuicFrame copy;
+ switch (frame.type) {
+ case PADDING_FRAME:
+ copy = QuicFrame(QuicPaddingFrame(frame.padding_frame));
+ break;
+ case RST_STREAM_FRAME:
+ copy = QuicFrame(new QuicRstStreamFrame(*frame.rst_stream_frame));
+ break;
+ case CONNECTION_CLOSE_FRAME:
+ copy = QuicFrame(
+ new QuicConnectionCloseFrame(*frame.connection_close_frame));
+ break;
+ case GOAWAY_FRAME:
+ copy = QuicFrame(new QuicGoAwayFrame(*frame.goaway_frame));
+ break;
+ case WINDOW_UPDATE_FRAME:
+ copy = QuicFrame(new QuicWindowUpdateFrame(*frame.window_update_frame));
+ break;
+ case BLOCKED_FRAME:
+ copy = QuicFrame(new QuicBlockedFrame(*frame.blocked_frame));
+ break;
+ case STOP_WAITING_FRAME:
+ copy = QuicFrame(QuicStopWaitingFrame(frame.stop_waiting_frame));
+ break;
+ case PING_FRAME:
+ copy = QuicFrame(QuicPingFrame(frame.ping_frame.control_frame_id));
+ break;
+ case CRYPTO_FRAME:
+ copy = QuicFrame(new QuicCryptoFrame(*frame.crypto_frame));
+ break;
+ case STREAM_FRAME:
+ copy = QuicFrame(QuicStreamFrame(frame.stream_frame));
+ break;
+ case ACK_FRAME:
+ copy = QuicFrame(new QuicAckFrame(*frame.ack_frame));
+ break;
+ case MTU_DISCOVERY_FRAME:
+ copy = QuicFrame(QuicMtuDiscoveryFrame(frame.mtu_discovery_frame));
+ break;
+ case NEW_CONNECTION_ID_FRAME:
+ copy = QuicFrame(
+ new QuicNewConnectionIdFrame(*frame.new_connection_id_frame));
+ break;
+ case MAX_STREAMS_FRAME:
+ copy = QuicFrame(QuicMaxStreamsFrame(frame.max_streams_frame));
+ break;
+ case STREAMS_BLOCKED_FRAME:
+ copy = QuicFrame(QuicStreamsBlockedFrame(frame.streams_blocked_frame));
+ break;
+ case PATH_RESPONSE_FRAME:
+ copy = QuicFrame(new QuicPathResponseFrame(*frame.path_response_frame));
+ break;
+ case PATH_CHALLENGE_FRAME:
+ copy = QuicFrame(new QuicPathChallengeFrame(*frame.path_challenge_frame));
+ break;
+ case STOP_SENDING_FRAME:
+ copy = QuicFrame(new QuicStopSendingFrame(*frame.stop_sending_frame));
+ break;
+ case MESSAGE_FRAME:
+ copy = QuicFrame(new QuicMessageFrame(frame.message_frame->message_id));
+ copy.message_frame->data = frame.message_frame->data;
+ copy.message_frame->message_length = frame.message_frame->message_length;
+ for (const auto& slice : frame.message_frame->message_data) {
+ QuicMemSlice copy_slice(allocator, slice.length());
+ memcpy(const_cast<char*>(copy_slice.data()), slice.data(),
+ slice.length());
+ copy.message_frame->message_data.push_back(std::move(copy_slice));
+ }
+ break;
+ case NEW_TOKEN_FRAME:
+ copy = QuicFrame(new QuicNewTokenFrame(*frame.new_token_frame));
+ break;
+ case RETIRE_CONNECTION_ID_FRAME:
+ copy = QuicFrame(
+ new QuicRetireConnectionIdFrame(*frame.retire_connection_id_frame));
+ break;
+ default:
+ QUIC_BUG << "Cannot copy frame: " << frame;
+ copy = QuicFrame(QuicPingFrame(kInvalidControlFrameId));
+ break;
+ }
+ return copy;
+}
+
+QuicFrames CopyQuicFrames(QuicBufferAllocator* allocator,
+ const QuicFrames& frames) {
+ QuicFrames copy;
+ for (const auto& frame : frames) {
+ copy.push_back(CopyQuicFrame(allocator, frame));
+ }
+ return copy;
+}
+
std::ostream& operator<<(std::ostream& os, const QuicFrame& frame) {
switch (frame.type) {
case PADDING_FRAME: {
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.h
index 1fa9e01af56..226cbfb2d83 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.h
@@ -140,6 +140,14 @@ QUIC_EXPORT_PRIVATE void SetControlFrameId(QuicControlFrameId control_frame_id,
QUIC_EXPORT_PRIVATE QuicFrame
CopyRetransmittableControlFrame(const QuicFrame& frame);
+// Returns a copy of |frame|.
+QUIC_EXPORT_PRIVATE QuicFrame CopyQuicFrame(QuicBufferAllocator* allocator,
+ const QuicFrame& frame);
+
+// Returns a copy of |frames|.
+QUIC_EXPORT_PRIVATE QuicFrames CopyQuicFrames(QuicBufferAllocator* allocator,
+ const QuicFrames& frames);
+
// Human-readable description suitable for logging.
QUIC_EXPORT_PRIVATE std::string QuicFramesToString(const QuicFrames& frames);
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 8492a0c5112..1764e170f03 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
@@ -204,9 +204,9 @@ TEST_F(QuicFramesTest, WindowUpdateFrameToString) {
EXPECT_EQ(3u, GetControlFrameId(frame));
std::ostringstream stream;
window_update.stream_id = 1;
- window_update.byte_offset = 2;
+ window_update.max_data = 2;
stream << window_update;
- EXPECT_EQ("{ control_frame_id: 3, stream_id: 1, byte_offset: 2 }\n",
+ EXPECT_EQ("{ control_frame_id: 3, stream_id: 1, max_data: 2 }\n",
stream.str());
EXPECT_TRUE(IsControlFrame(frame.type));
}
@@ -376,30 +376,27 @@ TEST_F(QuicFramesTest, AddInterval) {
EXPECT_EQ(QuicPacketNumber(1u), ack_frame1.packets.Min());
EXPECT_EQ(QuicPacketNumber(99u), ack_frame1.packets.Max());
- std::vector<QuicInterval<QuicPacketNumber>> expected_intervals;
- expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(
- QuicPacketNumber(1), QuicPacketNumber(10)));
- expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(
- QuicPacketNumber(50), QuicPacketNumber(100)));
+ std::vector<QuicInterval<QuicPacketNumber>> expected_intervals{
+ {QuicPacketNumber(1), QuicPacketNumber(10)},
+ {QuicPacketNumber(50), QuicPacketNumber(100)},
+ };
const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals(
ack_frame1.packets.begin(), ack_frame1.packets.end());
EXPECT_EQ(expected_intervals, actual_intervals);
- // Ensure adding a range within the existing ranges fails.
- EXPECT_QUIC_BUG(
- ack_frame1.packets.AddRange(QuicPacketNumber(20), QuicPacketNumber(30)),
- "");
+ // Add a range in the middle.
+ ack_frame1.packets.AddRange(QuicPacketNumber(20), QuicPacketNumber(30));
const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals2(
ack_frame1.packets.begin(), ack_frame1.packets.end());
- std::vector<QuicInterval<QuicPacketNumber>> expected_intervals2;
- expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(
- QuicPacketNumber(1), QuicPacketNumber(10)));
- expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(
- QuicPacketNumber(50), QuicPacketNumber(100)));
+ std::vector<QuicInterval<QuicPacketNumber>> expected_intervals2{
+ {QuicPacketNumber(1), QuicPacketNumber(10)},
+ {QuicPacketNumber(20), QuicPacketNumber(30)},
+ {QuicPacketNumber(50), QuicPacketNumber(100)},
+ };
EXPECT_EQ(expected_intervals2.size(), ack_frame1.packets.NumIntervals());
EXPECT_EQ(expected_intervals2, actual_intervals2);
@@ -415,17 +412,13 @@ TEST_F(QuicFramesTest, AddInterval) {
const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals8(
ack_frame2.packets.begin(), ack_frame2.packets.end());
- std::vector<QuicInterval<QuicPacketNumber>> expected_intervals8;
- expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(
- QuicPacketNumber(10), QuicPacketNumber(15)));
- expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(
- QuicPacketNumber(20), QuicPacketNumber(25)));
- expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(
- QuicPacketNumber(40), QuicPacketNumber(45)));
- expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(
- QuicPacketNumber(60), QuicPacketNumber(65)));
- expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(
- QuicPacketNumber(80), QuicPacketNumber(85)));
+ std::vector<QuicInterval<QuicPacketNumber>> expected_intervals8{
+ {QuicPacketNumber(10), QuicPacketNumber(15)},
+ {QuicPacketNumber(20), QuicPacketNumber(25)},
+ {QuicPacketNumber(40), QuicPacketNumber(45)},
+ {QuicPacketNumber(60), QuicPacketNumber(65)},
+ {QuicPacketNumber(80), QuicPacketNumber(85)},
+ };
EXPECT_EQ(expected_intervals8, actual_intervals8);
}
@@ -481,6 +474,104 @@ TEST_F(QuicFramesTest, RemoveSmallestInterval) {
EXPECT_EQ(QuicPacketNumber(99u), ack_frame1.packets.Max());
}
+TEST_F(QuicFramesTest, CopyQuicFrames) {
+ QuicFrames frames;
+ SimpleBufferAllocator allocator;
+ QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
+ QuicMessageFrame* message_frame =
+ new QuicMessageFrame(1, MakeSpan(&allocator, "message", &storage));
+ // Construct a frame list.
+ for (uint8_t i = 0; i < NUM_FRAME_TYPES; ++i) {
+ switch (i) {
+ case PADDING_FRAME:
+ frames.push_back(QuicFrame(QuicPaddingFrame(-1)));
+ break;
+ case RST_STREAM_FRAME:
+ frames.push_back(QuicFrame(new QuicRstStreamFrame()));
+ break;
+ case CONNECTION_CLOSE_FRAME:
+ frames.push_back(QuicFrame(new QuicConnectionCloseFrame()));
+ break;
+ case GOAWAY_FRAME:
+ frames.push_back(QuicFrame(new QuicGoAwayFrame()));
+ break;
+ case WINDOW_UPDATE_FRAME:
+ frames.push_back(QuicFrame(new QuicWindowUpdateFrame()));
+ break;
+ case BLOCKED_FRAME:
+ frames.push_back(QuicFrame(new QuicBlockedFrame()));
+ break;
+ case STOP_WAITING_FRAME:
+ frames.push_back(QuicFrame(QuicStopWaitingFrame()));
+ break;
+ case PING_FRAME:
+ frames.push_back(QuicFrame(QuicPingFrame()));
+ break;
+ case CRYPTO_FRAME:
+ frames.push_back(QuicFrame(new QuicCryptoFrame()));
+ break;
+ case STREAM_FRAME:
+ frames.push_back(QuicFrame(QuicStreamFrame()));
+ break;
+ case ACK_FRAME:
+ frames.push_back(QuicFrame(new QuicAckFrame()));
+ break;
+ case MTU_DISCOVERY_FRAME:
+ frames.push_back(QuicFrame(QuicMtuDiscoveryFrame()));
+ break;
+ case NEW_CONNECTION_ID_FRAME:
+ frames.push_back(QuicFrame(new QuicNewConnectionIdFrame()));
+ break;
+ case MAX_STREAMS_FRAME:
+ frames.push_back(QuicFrame(QuicMaxStreamsFrame()));
+ break;
+ case STREAMS_BLOCKED_FRAME:
+ frames.push_back(QuicFrame(QuicStreamsBlockedFrame()));
+ break;
+ case PATH_RESPONSE_FRAME:
+ frames.push_back(QuicFrame(new QuicPathResponseFrame()));
+ break;
+ case PATH_CHALLENGE_FRAME:
+ frames.push_back(QuicFrame(new QuicPathChallengeFrame()));
+ break;
+ case STOP_SENDING_FRAME:
+ frames.push_back(QuicFrame(new QuicStopSendingFrame()));
+ break;
+ case MESSAGE_FRAME:
+ frames.push_back(QuicFrame(message_frame));
+ break;
+ case NEW_TOKEN_FRAME:
+ frames.push_back(QuicFrame(new QuicNewTokenFrame()));
+ break;
+ case RETIRE_CONNECTION_ID_FRAME:
+ frames.push_back(QuicFrame(new QuicRetireConnectionIdFrame()));
+ break;
+ default:
+ ASSERT_TRUE(false)
+ << "Please fix CopyQuicFrames if a new frame type is added.";
+ break;
+ }
+ }
+
+ QuicFrames copy = CopyQuicFrames(&allocator, frames);
+ ASSERT_EQ(NUM_FRAME_TYPES, copy.size());
+ for (uint8_t i = 0; i < NUM_FRAME_TYPES; ++i) {
+ EXPECT_EQ(i, copy[i].type);
+ if (i != MESSAGE_FRAME) {
+ continue;
+ }
+ // Verify message frame is correctly copied.
+ EXPECT_EQ(1u, copy[i].message_frame->message_id);
+ EXPECT_EQ(nullptr, copy[i].message_frame->data);
+ EXPECT_EQ(7u, copy[i].message_frame->message_length);
+ ASSERT_EQ(1u, copy[i].message_frame->message_data.size());
+ EXPECT_EQ(0, memcmp(copy[i].message_frame->message_data[0].data(),
+ frames[i].message_frame->message_data[0].data(), 7));
+ }
+ DeleteFrames(&frames);
+ DeleteFrames(&copy);
+}
+
class PacketNumberQueueTest : public QuicTest {};
// Tests that a queue contains the expected data after calls to Add().
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.cc
index b9413c7e271..d0e65d20d13 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.cc
@@ -43,4 +43,14 @@ std::ostream& operator<<(std::ostream& os,
return os;
}
+bool QuicStreamFrame::operator==(const QuicStreamFrame& rhs) const {
+ return fin == rhs.fin && data_length == rhs.data_length &&
+ stream_id == rhs.stream_id && data_buffer == rhs.data_buffer &&
+ offset == rhs.offset;
+}
+
+bool QuicStreamFrame::operator!=(const QuicStreamFrame& rhs) const {
+ return !(*this == rhs);
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h
index 6cd510d41f5..5c5323b2d57 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h
@@ -31,6 +31,10 @@ struct QUIC_EXPORT_PRIVATE QuicStreamFrame
friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
const QuicStreamFrame& s);
+ bool operator==(const QuicStreamFrame& rhs) const;
+
+ bool operator!=(const QuicStreamFrame& rhs) const;
+
bool fin;
QuicPacketLength data_length;
QuicStreamId stream_id;
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.cc
index 07e31687fbd..81ca125b64c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.cc
@@ -13,16 +13,16 @@ QuicWindowUpdateFrame::QuicWindowUpdateFrame()
QuicWindowUpdateFrame::QuicWindowUpdateFrame(
QuicControlFrameId control_frame_id,
QuicStreamId stream_id,
- QuicStreamOffset byte_offset)
+ QuicByteCount max_data)
: control_frame_id(control_frame_id),
stream_id(stream_id),
- byte_offset(byte_offset) {}
+ max_data(max_data) {}
std::ostream& operator<<(std::ostream& os,
const QuicWindowUpdateFrame& window_update_frame) {
os << "{ control_frame_id: " << window_update_frame.control_frame_id
<< ", stream_id: " << window_update_frame.stream_id
- << ", byte_offset: " << window_update_frame.byte_offset << " }\n";
+ << ", max_data: " << window_update_frame.max_data << " }\n";
return os;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.h
index 73163cecb19..ff4478528dd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.h
@@ -12,15 +12,13 @@
namespace quic {
// Flow control updates per-stream and at the connection level.
-// Based on SPDY's WINDOW_UPDATE frame, but uses an absolute byte offset rather
-// than a window delta.
-// TODO(rjshade): A possible future optimization is to make stream_id and
-// byte_offset variable length, similar to stream frames.
+// Based on SPDY's WINDOW_UPDATE frame, but uses an absolute max data bytes
+// rather than a window delta.
struct QUIC_EXPORT_PRIVATE QuicWindowUpdateFrame {
QuicWindowUpdateFrame();
QuicWindowUpdateFrame(QuicControlFrameId control_frame_id,
QuicStreamId stream_id,
- QuicStreamOffset byte_offset);
+ QuicByteCount max_data);
friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
std::ostream& os,
@@ -34,13 +32,9 @@ struct QUIC_EXPORT_PRIVATE QuicWindowUpdateFrame {
// connection rather than a specific stream.
QuicStreamId stream_id;
- // Byte offset in the stream or connection. The receiver of this frame must
- // not send data which would result in this offset being exceeded.
- //
- // TODO(fkastenholz): Rename this to max_data and change the type to
- // QuicByteCount because the IETF defines this as the "maximum
- // amount of data that can be sent".
- QuicStreamOffset byte_offset;
+ // Maximum data allowed in the stream or connection. The receiver of this
+ // frame must not send data which would exceedes this restriction.
+ QuicByteCount max_data;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/handshaker_delegate_interface.h b/chromium/net/third_party/quiche/src/quic/core/handshaker_delegate_interface.h
new file mode 100644
index 00000000000..9eae32ab8cf
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/handshaker_delegate_interface.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_HANDSHAKER_DELEGATE_INTERFACE_H_
+#define QUICHE_QUIC_CORE_HANDSHAKER_DELEGATE_INTERFACE_H_
+
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+
+namespace quic {
+
+class QuicDecrypter;
+class QuicEncrypter;
+
+// Pure virtual class to get notified when particular handshake events occurred.
+class QUIC_EXPORT_PRIVATE HandshakerDelegateInterface {
+ public:
+ virtual ~HandshakerDelegateInterface() {}
+
+ // Called when new keys are available.
+ virtual void OnNewKeysAvailable(EncryptionLevel level,
+ std::unique_ptr<QuicDecrypter> decrypter,
+ bool set_alternative_decrypter,
+ bool latch_once_used,
+ std::unique_ptr<QuicEncrypter> encrypter) = 0;
+
+ // Called to set default encryption level to |level|.
+ virtual void SetDefaultEncryptionLevel(EncryptionLevel level) = 0;
+
+ // Called to discard old decryption keys to stop processing packets of
+ // encryption |level|.
+ virtual void DiscardOldDecryptionKey(EncryptionLevel level) = 0;
+
+ // Called to discard old encryption keys (and neuter obsolete data).
+ // TODO(fayang): consider to combine this with DiscardOldDecryptionKey.
+ virtual void DiscardOldEncryptionKey(EncryptionLevel level) = 0;
+
+ // Called to neuter ENCRYPTION_INITIAL data (without discarding initial keys).
+ virtual void NeuterUnencryptedData() = 0;
+
+ // Called to neuter data of HANDSHAKE_DATA packet number space. In QUIC
+ // crypto, this is called 1) when a client switches to forward secure
+ // encryption level and 2) a server successfully processes a forward secure
+ // packet. Temporarily use this method in TLS handshake when both endpoints
+ // switch to forward secure encryption level.
+ // TODO(fayang): use DiscardOldEncryptionKey instead of this method in TLS
+ // handshake when handshake key discarding settles down.
+ virtual void NeuterHandshakeData() = 0;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_HANDSHAKER_DELEGATE_INTERFACE_H_
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 e7d0329b2af..df2b458d588 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
@@ -14,7 +14,6 @@
#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
#include "net/third_party/quiche/src/quic/core/http/http_constants.h"
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
#include "net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
@@ -42,6 +41,8 @@
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/packet_dropping_test_writer.h"
#include "net/third_party/quiche/src/quic/test_tools/packet_reordering_writer.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_client_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
@@ -66,7 +67,6 @@
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h"
using spdy::kV3LowestPriority;
-using spdy::SETTINGS_MAX_HEADER_LIST_SIZE;
using spdy::SpdyFramer;
using spdy::SpdyHeaderBlock;
using spdy::SpdySerializedFrame;
@@ -141,12 +141,12 @@ std::vector<TestParams> GetTestParams(bool use_tls_handshake) {
ParsedQuicVersionVector all_supported_versions =
FilterSupportedVersions(AllSupportedVersions());
- // Buckets are separated by versions: versions prior to QUIC_VERSION_47 use
+ // Buckets are separated by versions: versions without crypto frames use
// STREAM frames for the handshake, and only have QUIC crypto as the handshake
- // protocol. Version 47 and greater use CRYPTO frames for the handshake, and
- // must also be split based on the handshake protocol. If the handshake
- // protocol (QUIC crypto or TLS) changes, the ClientHello/CHLO must be
- // reconstructed for the correct protocol.
+ // protocol. Versions that use CRYPTO frames for the handshake must also be
+ // split based on the handshake protocol. If the handshake protocol (QUIC
+ // crypto or TLS) changes, the ClientHello/CHLO must be reconstructed for the
+ // correct protocol.
ParsedQuicVersionVector version_buckets[3];
for (const ParsedQuicVersion& version : all_supported_versions) {
@@ -248,7 +248,6 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
support_server_push_(false),
expected_server_connection_id_length_(kQuicDefaultConnectionIdLength) {
SetQuicReloadableFlag(quic_supports_tls_handshake, true);
- SetQuicReloadableFlag(quic_simplify_stop_waiting, true);
client_supported_versions_ = GetParam().client_supported_versions;
server_supported_versions_ = GetParam().server_supported_versions;
negotiated_version_ = GetParam().negotiated_version;
@@ -682,6 +681,21 @@ TEST_P(EndToEndTestWithTls, SimpleRequestResponse) {
EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
}
+TEST_P(EndToEndTestWithTls, SendAndReceiveCoalescedPackets) {
+ ASSERT_TRUE(Initialize());
+ if (!GetClientConnection()->version().CanSendCoalescedPackets()) {
+ return;
+ }
+ EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
+ EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+ // Verify client successfully processes coalesced packets.
+ QuicConnectionStats client_stats = GetClientConnection()->GetStats();
+ EXPECT_LT(0u, client_stats.num_coalesced_packets_received);
+ EXPECT_EQ(client_stats.num_coalesced_packets_processed,
+ client_stats.num_coalesced_packets_received);
+ // TODO(fayang): verify server successfully processes coalesced packets.
+}
+
// Simple transaction, but set a non-default ack delay at the client
// and ensure it gets to the server.
TEST_P(EndToEndTest, SimpleRequestResponseWithAckDelayChange) {
@@ -1628,8 +1642,9 @@ TEST_P(EndToEndTest, InvalidStream) {
session, GetNthServerInitiatedBidirectionalId(0));
client_->SendCustomSynchronousRequest(headers, body);
- EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error());
- EXPECT_EQ(QUIC_INVALID_STREAM_ID, client_->connection_error());
+ EXPECT_THAT(client_->stream_error(),
+ IsStreamError(QUIC_STREAM_CONNECTION_ERROR));
+ EXPECT_THAT(client_->connection_error(), IsError(QUIC_INVALID_STREAM_ID));
}
// Test that if the server will close the connection if the client attempts
@@ -1654,11 +1669,11 @@ TEST_P(EndToEndTest, LargeHeaders) {
->client_session()
->connection()
->transport_version())) {
- EXPECT_EQ(QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE,
- client_->connection_error());
+ EXPECT_THAT(client_->connection_error(),
+ IsError(QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE));
} else {
- EXPECT_EQ(QUIC_HEADERS_TOO_LARGE, client_->stream_error());
- EXPECT_EQ(QUIC_NO_ERROR, client_->connection_error());
+ EXPECT_THAT(client_->stream_error(), IsStreamError(QUIC_HEADERS_TOO_LARGE));
+ EXPECT_THAT(client_->connection_error(), IsQuicNoError());
}
}
@@ -1679,8 +1694,8 @@ TEST_P(EndToEndTest, EarlyResponseWithQuicStreamNoError) {
client_->SendCustomSynchronousRequest(headers, large_body);
EXPECT_EQ("bad", client_->response_body());
EXPECT_EQ("500", client_->response_headers()->find(":status")->second);
- EXPECT_EQ(QUIC_STREAM_NO_ERROR, client_->stream_error());
- EXPECT_EQ(QUIC_NO_ERROR, client_->connection_error());
+ EXPECT_THAT(client_->stream_error(), IsQuicStreamNoError());
+ EXPECT_THAT(client_->connection_error(), IsQuicNoError());
}
// TODO(rch): this test seems to cause net_unittests timeouts :|
@@ -1726,11 +1741,13 @@ TEST_P(EndToEndTestWithTls, MaxIncomingDynamicStreamsLimitRespected) {
ASSERT_TRUE(Initialize());
if (VersionHasIetfQuicFrames(
GetParam().negotiated_version.transport_version)) {
- // Do not run this test for /IETF QUIC. Note that the test needs
- // to be here, after calling Initialize(), because all tests end up calling
- // EndToEndTest::TearDown(), which asserts that Initialize has been called
- // and then proceeds to tear things down -- which fails if they are not
- // properly set up.
+ // Do not run this test for /IETF QUIC. This test relies on the fact that
+ // Google QUIC allows a small number of additional streams beyond the
+ // negotiated limit, which is not supported in IETF QUIC. Note that the test
+ // needs to be here, after calling Initialize(), because all tests end up
+ // calling EndToEndTest::TearDown(), which asserts that Initialize has been
+ // called and then proceeds to tear things down -- which fails if they are
+ // not properly set up.
return;
}
EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
@@ -1755,8 +1772,8 @@ TEST_P(EndToEndTestWithTls, MaxIncomingDynamicStreamsLimitRespected) {
client_->WaitForResponse();
EXPECT_TRUE(client_->connected());
- EXPECT_EQ(QUIC_REFUSED_STREAM, client_->stream_error());
- EXPECT_EQ(QUIC_NO_ERROR, client_->connection_error());
+ EXPECT_THAT(client_->stream_error(), IsStreamError(QUIC_REFUSED_STREAM));
+ EXPECT_THAT(client_->connection_error(), IsQuicNoError());
}
TEST_P(EndToEndTest, SetIndependentMaxIncomingDynamicStreamsLimits) {
@@ -2090,7 +2107,7 @@ TEST_P(EndToEndTestWithTls, StreamCancelErrorTest) {
}
// It should be completely fine to RST a stream before any data has been
// received for that stream.
- EXPECT_EQ(QUIC_NO_ERROR, client_->connection_error());
+ EXPECT_THAT(client_->connection_error(), IsQuicNoError());
}
TEST_P(EndToEndTest, ConnectionMigrationClientIPChanged) {
@@ -2604,7 +2621,7 @@ TEST_P(EndToEndTestWithTls, ServerSendPublicReset) {
// The request should fail.
EXPECT_EQ("", client_->SendSynchronousRequest("/foo"));
EXPECT_TRUE(client_->response_headers()->empty());
- EXPECT_EQ(QUIC_PUBLIC_RESET, client_->connection_error());
+ EXPECT_THAT(client_->connection_error(), IsError(QUIC_PUBLIC_RESET));
}
// Send a public reset from the server for a different connection ID.
@@ -2650,7 +2667,7 @@ TEST_P(EndToEndTestWithTls, ServerSendPublicResetWithDifferentConnectionId) {
// ID.
EXPECT_EQ("", client_->SendSynchronousRequest("/foo"));
EXPECT_TRUE(client_->response_headers()->empty());
- EXPECT_EQ(QUIC_PUBLIC_RESET, client_->connection_error());
+ EXPECT_THAT(client_->connection_error(), IsError(QUIC_PUBLIC_RESET));
return;
}
// The connection should be unaffected.
@@ -2745,8 +2762,8 @@ TEST_P(EndToEndTestWithTls, BadPacketHeaderTruncated) {
server_thread_->Pause();
QuicDispatcher* dispatcher =
QuicServerPeer::GetDispatcher(server_thread_->server());
- EXPECT_EQ(QUIC_INVALID_PACKET_HEADER,
- QuicDispatcherPeer::GetAndClearLastError(dispatcher));
+ EXPECT_THAT(QuicDispatcherPeer::GetAndClearLastError(dispatcher),
+ IsError(QUIC_INVALID_PACKET_HEADER));
server_thread_->Resume();
// The connection should not be terminated.
@@ -2796,8 +2813,8 @@ TEST_P(EndToEndTestWithTls, BadPacketHeaderFlags) {
server_thread_->Pause();
QuicDispatcher* dispatcher =
QuicServerPeer::GetDispatcher(server_thread_->server());
- EXPECT_EQ(QUIC_INVALID_PACKET_HEADER,
- QuicDispatcherPeer::GetAndClearLastError(dispatcher));
+ EXPECT_THAT(QuicDispatcherPeer::GetAndClearLastError(dispatcher),
+ IsError(QUIC_INVALID_PACKET_HEADER));
server_thread_->Resume();
// The connection should not be terminated.
@@ -2834,8 +2851,8 @@ TEST_P(EndToEndTestWithTls, BadEncryptedData) {
server_thread_->Pause();
QuicDispatcher* dispatcher =
QuicServerPeer::GetDispatcher(server_thread_->server());
- EXPECT_EQ(QUIC_NO_ERROR,
- QuicDispatcherPeer::GetAndClearLastError(dispatcher));
+ EXPECT_THAT(QuicDispatcherPeer::GetAndClearLastError(dispatcher),
+ IsQuicNoError());
server_thread_->Resume();
// The connection should not be terminated.
@@ -3105,7 +3122,6 @@ TEST_P(EndToEndTestWithTls, Trailers) {
SpdyHeaderBlock headers;
headers[":status"] = "200";
- headers[":version"] = "HTTP/1.1";
headers["content-length"] = QuicTextUtils::Uint64ToString(kBody.size());
SpdyHeaderBlock trailers;
@@ -3159,7 +3175,6 @@ class EndToEndTestServerPush : public EndToEndTest {
? large_resource
: QuicStrCat("This is server push response body for ", url);
SpdyHeaderBlock response_headers;
- response_headers[":version"] = "HTTP/1.1";
response_headers[":status"] = "200";
response_headers["content-length"] =
QuicTextUtils::Uint64ToString(body.size());
@@ -3235,6 +3250,7 @@ TEST_P(EndToEndTestServerPush, ServerPush) {
}
TEST_P(EndToEndTestServerPush, ServerPushUnderLimit) {
+ SetQuicReloadableFlag(quic_send_max_push_id_with_settings, true);
// Tests that sending a request which has 4 push resources will trigger server
// to push those 4 resources and client can handle pushed resources and match
// them with requests later.
@@ -3340,6 +3356,7 @@ TEST_P(EndToEndTestServerPush, ServerPushOverLimitNonBlocking) {
}
TEST_P(EndToEndTestServerPush, ServerPushOverLimitWithBlocking) {
+ SetQuicReloadableFlag(quic_send_max_push_id_with_settings, true);
// Tests that when server tries to send more large resources(large enough to
// be blocked by flow control window or congestion control window) than max
// open outgoing streams , server can open upto max number of outgoing
@@ -3555,8 +3572,8 @@ TEST_P(EndToEndTest, WayTooLongRequestHeaders) {
client_->SendMessage(headers, "");
client_->WaitForResponse();
- EXPECT_EQ(QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE,
- client_->connection_error());
+ EXPECT_THAT(client_->connection_error(),
+ IsError(QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE));
}
class WindowUpdateObserver : public QuicConnectionDebugVisitor {
@@ -3633,7 +3650,7 @@ TEST_P(EndToEndTest,
client_.reset(CreateQuicClient(client_writer_));
EXPECT_EQ("", client_->SendSynchronousRequest("/foo"));
- EXPECT_EQ(QUIC_HANDSHAKE_FAILED, client_->connection_error());
+ EXPECT_THAT(client_->connection_error(), IsError(QUIC_HANDSHAKE_FAILED));
}
// Regression test for b/116200989.
@@ -3670,7 +3687,7 @@ TEST_P(EndToEndTest,
// Second, a /big_response request with big response should fail.
EXPECT_LT(client_->SendSynchronousRequest("/big_response").length(),
kBigResponseBodySize);
- EXPECT_EQ(QUIC_PUBLIC_RESET, client_->connection_error());
+ EXPECT_THAT(client_->connection_error(), IsError(QUIC_PUBLIC_RESET));
}
// Regression test of b/70782529.
@@ -3742,7 +3759,7 @@ TEST_P(EndToEndTest, QUIC_TEST_DISABLED_IN_CHROME(PreSharedKeyMismatch)) {
// return whether it is successful.
ASSERT_FALSE(Initialize() &&
client_->client()->WaitForCryptoHandshakeConfirmed());
- EXPECT_EQ(QUIC_HANDSHAKE_TIMEOUT, client_->connection_error());
+ EXPECT_THAT(client_->connection_error(), IsError(QUIC_HANDSHAKE_TIMEOUT));
}
// TODO: reenable once we have a way to make this run faster.
@@ -3754,7 +3771,7 @@ TEST_P(EndToEndTest, QUIC_TEST_DISABLED_IN_CHROME(PreSharedKeyNoClient)) {
pre_shared_key_server_ = "foobar";
ASSERT_FALSE(Initialize() &&
client_->client()->WaitForCryptoHandshakeConfirmed());
- EXPECT_EQ(QUIC_HANDSHAKE_TIMEOUT, client_->connection_error());
+ EXPECT_THAT(client_->connection_error(), IsError(QUIC_HANDSHAKE_TIMEOUT));
}
// TODO: reenable once we have a way to make this run faster.
@@ -3766,7 +3783,7 @@ TEST_P(EndToEndTest, QUIC_TEST_DISABLED_IN_CHROME(PreSharedKeyNoServer)) {
pre_shared_key_client_ = "foobar";
ASSERT_FALSE(Initialize() &&
client_->client()->WaitForCryptoHandshakeConfirmed());
- EXPECT_EQ(QUIC_HANDSHAKE_TIMEOUT, client_->connection_error());
+ EXPECT_THAT(client_->connection_error(), IsError(QUIC_HANDSHAKE_TIMEOUT));
}
TEST_P(EndToEndTest, RequestAndStreamRstInOnePacket) {
@@ -3801,15 +3818,12 @@ TEST_P(EndToEndTest, RequestAndStreamRstInOnePacket) {
client_->WaitForDelayedAcks();
// The real expectation is the test does not crash or timeout.
- EXPECT_EQ(QUIC_NO_ERROR, client_->connection_error());
+ EXPECT_THAT(client_->connection_error(), IsQuicNoError());
}
TEST_P(EndToEndTest, ResetStreamOnTtlExpires) {
ASSERT_TRUE(Initialize());
EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
- if (!GetClientSession()->session_decides_what_to_write()) {
- return;
- }
SetPacketLossPercentage(30);
QuicSpdyClientStream* stream = client_->GetOrCreateStream();
@@ -3821,7 +3835,7 @@ TEST_P(EndToEndTest, ResetStreamOnTtlExpires) {
std::string body(1024 * 1024, 'a');
stream->WriteOrBufferBody(body, true);
client_->WaitForResponse();
- EXPECT_EQ(QUIC_STREAM_TTL_EXPIRED, client_->stream_error());
+ EXPECT_THAT(client_->stream_error(), IsStreamError(QUIC_STREAM_TTL_EXPIRED));
}
TEST_P(EndToEndTest, SendMessages) {
@@ -3888,7 +3902,7 @@ TEST_P(EndToEndTest, SendMessages) {
client_session->GetCurrentLargestMessagePayload() + 1),
&storage))
.status);
- EXPECT_EQ(QUIC_NO_ERROR, client_->connection_error());
+ EXPECT_THAT(client_->connection_error(), IsQuicNoError());
}
class EndToEndPacketReorderingTest : public EndToEndTest {
@@ -4037,14 +4051,15 @@ TEST_P(EndToEndTest, SimpleStopSendingTest) {
client_->WaitForDelayedAcks();
// The real expectation is the test does not crash or timeout.
- EXPECT_EQ(QUIC_NO_ERROR, client_->connection_error());
+ EXPECT_THAT(client_->connection_error(), IsQuicNoError());
// And that the stop-sending code is received.
QuicSimpleClientStream* client_stream =
static_cast<QuicSimpleClientStream*>(client_->latest_created_stream());
ASSERT_NE(nullptr, client_stream);
// Make sure we have the correct stream
EXPECT_EQ(stream_id, client_stream->id());
- EXPECT_EQ(kStopSendingTestCode, client_stream->last_stop_sending_code());
+ EXPECT_EQ(kStopSendingTestCode,
+ static_cast<uint16_t>(client_stream->stream_error()));
}
TEST_P(EndToEndTest, SimpleStopSendingRstStreamTest) {
@@ -4127,7 +4142,7 @@ TEST_P(EndToEndTest, ZeroRttProtectedConnectionClose) {
EXPECT_EQ("", client_->SendSynchronousRequest("/foo"));
// Verify ZERO_RTT_PROTECTED connection close is successfully processed by
// client which switches to FORWARD_SECURE.
- EXPECT_EQ(QUIC_PACKET_WRITE_ERROR, client_->connection_error());
+ EXPECT_THAT(client_->connection_error(), IsError(QUIC_PACKET_WRITE_ERROR));
}
class BadShloPacketWriter2 : public QuicPacketWriterWrapper {
@@ -4185,7 +4200,7 @@ TEST_P(EndToEndTest, ForwardSecureConnectionClose) {
EXPECT_EQ("", client_->SendSynchronousRequest("/foo"));
// Verify ZERO_RTT_PROTECTED connection close is successfully processed by
// client.
- EXPECT_EQ(QUIC_PACKET_WRITE_ERROR, client_->connection_error());
+ EXPECT_THAT(client_->connection_error(), IsError(QUIC_PACKET_WRITE_ERROR));
}
// Test that the stream id manager closes the connection if a stream
@@ -4215,8 +4230,9 @@ TEST_P(EndToEndTest, TooBigStreamIdClosesConnection) {
QuicSessionPeer::SetNextOutgoingBidirectionalStreamId(
session, GetNthClientInitiatedBidirectionalId(max_number_of_streams + 1));
client_->SendCustomSynchronousRequest(headers, body);
- EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error());
- EXPECT_EQ(QUIC_INVALID_STREAM_ID, GetClientSession()->error());
+ EXPECT_THAT(client_->stream_error(),
+ IsStreamError(QUIC_STREAM_CONNECTION_ERROR));
+ EXPECT_THAT(GetClientSession()->error(), IsError(QUIC_INVALID_STREAM_ID));
EXPECT_EQ(IETF_QUIC_TRANSPORT_CONNECTION_CLOSE,
GetClientSession()->close_type());
EXPECT_TRUE(
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 42b4dd2a5ac..751ca5876bb 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 "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
using ::testing::_;
using ::testing::Eq;
@@ -133,7 +134,7 @@ class HttpDecoderTest : public QuicTest {
};
TEST_F(HttpDecoderTest, InitialState) {
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
}
@@ -171,7 +172,7 @@ TEST_F(HttpDecoderTest, UnknownFrame) {
EXPECT_EQ(total_length, decoder_.ProcessInput(input.get(), total_length));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
ASSERT_EQ("", decoder_.error_detail());
EXPECT_EQ(frame_type, current_frame_type());
}
@@ -189,19 +190,19 @@ TEST_F(HttpDecoderTest, CancelPush) {
EXPECT_CALL(visitor_, OnCancelPushFrame(CancelPushFrame({1})))
.WillOnce(Return(false));
EXPECT_EQ(input.size(), ProcessInputWithGarbageAppended(input));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the full frame.
EXPECT_CALL(visitor_, OnCancelPushFrame(CancelPushFrame({1})));
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the frame incrementally.
EXPECT_CALL(visitor_, OnCancelPushFrame(CancelPushFrame({1})));
ProcessInputCharByChar(input);
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
}
@@ -233,7 +234,7 @@ TEST_F(HttpDecoderTest, PushPromiseFrame) {
EXPECT_CALL(visitor_, OnPushPromiseFrameEnd()).WillOnce(Return(false));
EXPECT_EQ(0u, ProcessInputWithGarbageAppended(""));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the full frame.
@@ -242,7 +243,7 @@ TEST_F(HttpDecoderTest, PushPromiseFrame) {
EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("Headers")));
EXPECT_CALL(visitor_, OnPushPromiseFrameEnd());
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the frame incrementally.
@@ -257,7 +258,7 @@ TEST_F(HttpDecoderTest, PushPromiseFrame) {
EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("s")));
EXPECT_CALL(visitor_, OnPushPromiseFrameEnd());
ProcessInputCharByChar(input);
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process push id incrementally and append headers with last byte of push id.
@@ -267,7 +268,7 @@ TEST_F(HttpDecoderTest, PushPromiseFrame) {
EXPECT_CALL(visitor_, OnPushPromiseFrameEnd());
ProcessInputCharByChar(input.substr(0, 9));
EXPECT_EQ(8u, ProcessInput(input.substr(9)));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
}
@@ -286,7 +287,7 @@ TEST_F(HttpDecoderTest, CorruptPushPromiseFrame) {
decoder.ProcessInput(input.data(), input.size());
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, decoder.error());
+ EXPECT_THAT(decoder.error(), IsError(QUIC_INVALID_FRAME_DATA));
EXPECT_EQ("PUSH_PROMISE frame malformed.", decoder.error_detail());
}
{
@@ -298,7 +299,7 @@ TEST_F(HttpDecoderTest, CorruptPushPromiseFrame) {
decoder.ProcessInput(&c, 1);
}
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, decoder.error());
+ EXPECT_THAT(decoder.error(), IsError(QUIC_INVALID_FRAME_DATA));
EXPECT_EQ("PUSH_PROMISE frame malformed.", decoder.error_detail());
}
}
@@ -314,19 +315,19 @@ TEST_F(HttpDecoderTest, MaxPushId) {
EXPECT_CALL(visitor_, OnMaxPushIdFrame(MaxPushIdFrame({1})))
.WillOnce(Return(false));
EXPECT_EQ(input.size(), ProcessInputWithGarbageAppended(input));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the full frame.
EXPECT_CALL(visitor_, OnMaxPushIdFrame(MaxPushIdFrame({1})));
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the frame incrementally.
EXPECT_CALL(visitor_, OnMaxPushIdFrame(MaxPushIdFrame({1})));
ProcessInputCharByChar(input);
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
}
@@ -341,19 +342,19 @@ TEST_F(HttpDecoderTest, DuplicatePush) {
EXPECT_CALL(visitor_, OnDuplicatePushFrame(DuplicatePushFrame({1})))
.WillOnce(Return(false));
EXPECT_EQ(input.size(), ProcessInputWithGarbageAppended(input));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the full frame.
EXPECT_CALL(visitor_, OnDuplicatePushFrame(DuplicatePushFrame({1})));
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the frame incrementally.
EXPECT_CALL(visitor_, OnDuplicatePushFrame(DuplicatePushFrame({1})));
ProcessInputCharByChar(input);
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
}
@@ -386,21 +387,21 @@ TEST_F(HttpDecoderTest, PriorityFrame) {
EXPECT_CALL(visitor_, OnPriorityFrame(frame)).WillOnce(Return(false));
processed_bytes = ProcessInputWithGarbageAppended(remaining_input);
EXPECT_EQ(remaining_input.size(), processed_bytes);
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the full frame.
EXPECT_CALL(visitor_, OnPriorityFrameStart(2));
EXPECT_CALL(visitor_, OnPriorityFrame(frame));
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the frame incrementally.
EXPECT_CALL(visitor_, OnPriorityFrameStart(2));
EXPECT_CALL(visitor_, OnPriorityFrame(frame));
ProcessInputCharByChar(input);
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
std::string input2 = QuicTextUtils::HexDecode(
@@ -417,7 +418,7 @@ TEST_F(HttpDecoderTest, PriorityFrame) {
EXPECT_CALL(visitor_, OnPriorityFrameStart(2));
EXPECT_CALL(visitor_, OnPriorityFrame(frame2));
EXPECT_EQ(input2.size(), ProcessInput(input2));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
}
@@ -462,7 +463,7 @@ TEST_F(HttpDecoderTest, CorruptPriorityFrame) {
QuicByteCount processed_bytes =
decoder.ProcessInput(input.data(), input.size());
EXPECT_EQ(input.size(), processed_bytes);
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, decoder.error());
+ EXPECT_THAT(decoder.error(), IsError(QUIC_INVALID_FRAME_DATA));
EXPECT_EQ(test_data.error_message, decoder.error_detail());
}
}
@@ -495,21 +496,21 @@ TEST_F(HttpDecoderTest, SettingsFrame) {
EXPECT_CALL(visitor_, OnSettingsFrame(frame)).WillOnce(Return(false));
processed_bytes = ProcessInputWithGarbageAppended(remaining_input);
EXPECT_EQ(remaining_input.size(), processed_bytes);
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the full frame.
EXPECT_CALL(visitor_, OnSettingsFrameStart(2));
EXPECT_CALL(visitor_, OnSettingsFrame(frame));
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the frame incrementally.
EXPECT_CALL(visitor_, OnSettingsFrameStart(2));
EXPECT_CALL(visitor_, OnSettingsFrame(frame));
ProcessInputCharByChar(input);
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
}
@@ -543,7 +544,7 @@ TEST_F(HttpDecoderTest, CorruptSettingsFrame) {
QuicByteCount processed_bytes =
decoder.ProcessInput(input.data(), input.size());
EXPECT_EQ(input.size(), processed_bytes);
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, decoder.error());
+ EXPECT_THAT(decoder.error(), IsError(QUIC_INVALID_FRAME_DATA));
EXPECT_EQ(test_data.error_message, decoder.error_detail());
}
}
@@ -562,7 +563,7 @@ TEST_F(HttpDecoderTest, DuplicateSettingsIdentifier) {
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_INVALID_FRAME_DATA));
EXPECT_EQ("Duplicate SETTINGS identifier.", decoder_.error_detail());
}
@@ -587,7 +588,7 @@ TEST_F(HttpDecoderTest, DataFrame) {
EXPECT_CALL(visitor_, OnDataFrameEnd()).WillOnce(Return(false));
EXPECT_EQ(0u, ProcessInputWithGarbageAppended(""));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the full frame.
@@ -595,7 +596,7 @@ TEST_F(HttpDecoderTest, DataFrame) {
EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("Data!")));
EXPECT_CALL(visitor_, OnDataFrameEnd());
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the frame incrementally.
@@ -607,7 +608,7 @@ TEST_F(HttpDecoderTest, DataFrame) {
EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("!")));
EXPECT_CALL(visitor_, OnDataFrameEnd());
ProcessInputCharByChar(input);
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
}
@@ -615,28 +616,27 @@ TEST_F(HttpDecoderTest, FrameHeaderPartialDelivery) {
InSequence s;
// A large input that will occupy more than 1 byte in the length field.
std::string input(2048, 'x');
- HttpEncoder encoder;
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
- encoder.SerializeDataFrameHeader(input.length(), &buffer);
+ HttpEncoder::SerializeDataFrameHeader(input.length(), &buffer);
std::string header = std::string(buffer.get(), header_length);
// Partially send only 1 byte of the header to process.
EXPECT_EQ(1u, decoder_.ProcessInput(header.data(), 1));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Send the rest of the header.
EXPECT_CALL(visitor_, OnDataFrameStart(3));
EXPECT_EQ(header_length - 1,
decoder_.ProcessInput(header.data() + 1, header_length - 1));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Send data.
EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece(input)));
EXPECT_CALL(visitor_, OnDataFrameEnd());
EXPECT_EQ(2048u, decoder_.ProcessInput(input.data(), 2048));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
}
@@ -662,7 +662,7 @@ TEST_F(HttpDecoderTest, PartialDeliveryOfLargeFrameType) {
EXPECT_EQ(1u, decoder_.ProcessInput(&c, 1));
}
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
EXPECT_EQ(frame_type, current_frame_type());
}
@@ -678,19 +678,19 @@ TEST_F(HttpDecoderTest, GoAway) {
EXPECT_CALL(visitor_, OnGoAwayFrame(GoAwayFrame({1})))
.WillOnce(Return(false));
EXPECT_EQ(input.size(), ProcessInputWithGarbageAppended(input));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the full frame.
EXPECT_CALL(visitor_, OnGoAwayFrame(GoAwayFrame({1})));
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the frame incrementally.
EXPECT_CALL(visitor_, OnGoAwayFrame(GoAwayFrame({1})));
ProcessInputCharByChar(input);
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
}
@@ -716,7 +716,7 @@ TEST_F(HttpDecoderTest, HeadersFrame) {
EXPECT_CALL(visitor_, OnHeadersFrameEnd()).WillOnce(Return(false));
EXPECT_EQ(0u, ProcessInputWithGarbageAppended(""));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the full frame.
@@ -724,7 +724,7 @@ TEST_F(HttpDecoderTest, HeadersFrame) {
EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("Headers")));
EXPECT_CALL(visitor_, OnHeadersFrameEnd());
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the frame incrementally.
@@ -738,7 +738,7 @@ TEST_F(HttpDecoderTest, HeadersFrame) {
EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("s")));
EXPECT_CALL(visitor_, OnHeadersFrameEnd());
ProcessInputCharByChar(input);
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
}
@@ -754,21 +754,21 @@ TEST_F(HttpDecoderTest, EmptyDataFrame) {
EXPECT_CALL(visitor_, OnDataFrameEnd()).WillOnce(Return(false));
EXPECT_EQ(0u, ProcessInputWithGarbageAppended(""));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the full frame.
EXPECT_CALL(visitor_, OnDataFrameStart(2));
EXPECT_CALL(visitor_, OnDataFrameEnd());
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the frame incrementally.
EXPECT_CALL(visitor_, OnDataFrameStart(2));
EXPECT_CALL(visitor_, OnDataFrameEnd());
ProcessInputCharByChar(input);
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
}
@@ -784,21 +784,21 @@ TEST_F(HttpDecoderTest, EmptyHeadersFrame) {
EXPECT_CALL(visitor_, OnHeadersFrameEnd()).WillOnce(Return(false));
EXPECT_EQ(0u, ProcessInputWithGarbageAppended(""));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the full frame.
EXPECT_CALL(visitor_, OnHeadersFrameStart(2));
EXPECT_CALL(visitor_, OnHeadersFrameEnd());
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the frame incrementally.
EXPECT_CALL(visitor_, OnHeadersFrameStart(2));
EXPECT_CALL(visitor_, OnHeadersFrameEnd());
ProcessInputCharByChar(input);
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
}
@@ -816,7 +816,7 @@ TEST_F(HttpDecoderTest, PushPromiseFrameNoHeaders) {
EXPECT_CALL(visitor_, OnPushPromiseFrameEnd()).WillOnce(Return(false));
EXPECT_EQ(0u, ProcessInputWithGarbageAppended(""));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the full frame.
@@ -824,7 +824,7 @@ TEST_F(HttpDecoderTest, PushPromiseFrameNoHeaders) {
EXPECT_CALL(visitor_, OnPushPromiseFramePushId(1, 1));
EXPECT_CALL(visitor_, OnPushPromiseFrameEnd());
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
// Process the frame incrementally.
@@ -832,7 +832,7 @@ TEST_F(HttpDecoderTest, PushPromiseFrameNoHeaders) {
EXPECT_CALL(visitor_, OnPushPromiseFramePushId(1, 1));
EXPECT_CALL(visitor_, OnPushPromiseFrameEnd());
ProcessInputCharByChar(input);
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
}
@@ -844,7 +844,7 @@ TEST_F(HttpDecoderTest, MalformedFrameWithOverlyLargePayload) {
// Process the full frame.
EXPECT_CALL(visitor_, OnError(&decoder_));
EXPECT_EQ(2u, ProcessInput(input));
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_INVALID_FRAME_DATA));
EXPECT_EQ("Frame is too large", decoder_.error_detail());
}
@@ -859,7 +859,7 @@ TEST_F(HttpDecoderTest, MalformedSettingsFrame) {
writer.WriteStringPiece("Malformed payload");
EXPECT_CALL(visitor_, OnError(&decoder_));
EXPECT_EQ(5u, decoder_.ProcessInput(input, QUIC_ARRAYSIZE(input)));
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_INVALID_FRAME_DATA));
EXPECT_EQ("Frame is too large", decoder_.error_detail());
}
@@ -891,7 +891,7 @@ TEST_F(HttpDecoderTest, HeadersPausedThenData) {
processed_bytes = ProcessInput(remaining_input);
EXPECT_EQ(remaining_input.size(), processed_bytes);
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
}
@@ -945,7 +945,7 @@ TEST_F(HttpDecoderTest, CorruptFrame) {
QuicStringPiece input(test_data.input);
decoder.ProcessInput(input.data(), input.size());
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, decoder.error());
+ EXPECT_THAT(decoder.error(), IsError(QUIC_INVALID_FRAME_DATA));
EXPECT_EQ(test_data.error_message, decoder.error_detail());
}
{
@@ -956,7 +956,7 @@ TEST_F(HttpDecoderTest, CorruptFrame) {
for (auto c : input) {
decoder.ProcessInput(&c, 1);
}
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, decoder.error());
+ EXPECT_THAT(decoder.error(), IsError(QUIC_INVALID_FRAME_DATA));
EXPECT_EQ(test_data.error_message, decoder.error_detail());
}
}
@@ -969,7 +969,7 @@ TEST_F(HttpDecoderTest, EmptyCancelPushFrame) {
EXPECT_CALL(visitor_, OnError(&decoder_));
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_INVALID_FRAME_DATA));
EXPECT_EQ("Unable to read push_id", decoder_.error_detail());
}
@@ -984,7 +984,7 @@ TEST_F(HttpDecoderTest, EmptySettingsFrame) {
EXPECT_CALL(visitor_, OnSettingsFrame(empty_frame));
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
}
@@ -996,7 +996,7 @@ TEST_F(HttpDecoderTest, EmptyPushPromiseFrame) {
EXPECT_CALL(visitor_, OnError(&decoder_));
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_INVALID_FRAME_DATA));
EXPECT_EQ("Corrupt PUSH_PROMISE frame.", decoder_.error_detail());
}
@@ -1007,7 +1007,7 @@ TEST_F(HttpDecoderTest, EmptyGoAwayFrame) {
EXPECT_CALL(visitor_, OnError(&decoder_));
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_INVALID_FRAME_DATA));
EXPECT_EQ("Unable to read GOAWAY stream_id", decoder_.error_detail());
}
@@ -1018,7 +1018,7 @@ TEST_F(HttpDecoderTest, EmptyMaxPushIdFrame) {
EXPECT_CALL(visitor_, OnError(&decoder_));
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_INVALID_FRAME_DATA));
EXPECT_EQ("Unable to read push_id", decoder_.error_detail());
}
@@ -1029,20 +1029,19 @@ TEST_F(HttpDecoderTest, EmptyDuplicatePushFrame) {
EXPECT_CALL(visitor_, OnError(&decoder_));
EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_INVALID_FRAME_DATA));
EXPECT_EQ("Unable to read push_id", decoder_.error_detail());
}
TEST_F(HttpDecoderTest, LargeStreamIdInGoAway) {
- HttpEncoder encoder;
GoAwayFrame frame;
frame.stream_id = 1 << 30;
std::unique_ptr<char[]> buffer;
- uint64_t length = encoder.SerializeGoAwayFrame(frame, &buffer);
+ uint64_t length = HttpEncoder::SerializeGoAwayFrame(frame, &buffer);
EXPECT_CALL(visitor_, OnGoAwayFrame(frame));
EXPECT_GT(length, 0u);
EXPECT_EQ(length, decoder_.ProcessInput(buffer.get(), length));
- EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
}
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 b97f7f79619..6bb25cf16fe 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
@@ -40,12 +40,45 @@ uint8_t SetPriorityFields(uint8_t num,
}
}
-} // namespace
+bool WriteFrameHeader(QuicByteCount length,
+ HttpFrameType type,
+ QuicDataWriter* writer) {
+ return writer->WriteVarInt62(static_cast<uint64_t>(type)) &&
+ writer->WriteVarInt62(length);
+}
-HttpEncoder::HttpEncoder() {}
+QuicByteCount GetTotalLength(QuicByteCount payload_length, HttpFrameType type) {
+ return QuicDataWriter::GetVarInt62Len(payload_length) +
+ QuicDataWriter::GetVarInt62Len(static_cast<uint64_t>(type)) +
+ payload_length;
+}
+
+// Write prioritized element id and element dependency id if needed.
+bool MaybeWriteIds(const PriorityFrame& priority, QuicDataWriter* writer) {
+ if (priority.prioritized_type != ROOT_OF_TREE) {
+ if (!writer->WriteVarInt62(priority.prioritized_element_id)) {
+ return false;
+ }
+ } else {
+ DCHECK_EQ(0u, priority.prioritized_element_id)
+ << "Prioritized element id should be 0 when prioritized type is "
+ "ROOT_OF_TREE";
+ }
+ if (priority.dependency_type != ROOT_OF_TREE) {
+ if (!writer->WriteVarInt62(priority.element_dependency_id)) {
+ return false;
+ }
+ } else {
+ DCHECK_EQ(0u, priority.element_dependency_id)
+ << "Element dependency id should be 0 when dependency type is "
+ "ROOT_OF_TREE";
+ }
+ return true;
+}
-HttpEncoder::~HttpEncoder() {}
+} // namespace
+// static
QuicByteCount HttpEncoder::SerializeDataFrameHeader(
QuicByteCount payload_length,
std::unique_ptr<char[]>* output) {
@@ -65,6 +98,7 @@ QuicByteCount HttpEncoder::SerializeDataFrameHeader(
return 0;
}
+// static
QuicByteCount HttpEncoder::SerializeHeadersFrameHeader(
QuicByteCount payload_length,
std::unique_ptr<char[]>* output) {
@@ -86,6 +120,7 @@ QuicByteCount HttpEncoder::SerializeHeadersFrameHeader(
return 0;
}
+// static
QuicByteCount HttpEncoder::SerializePriorityFrame(
const PriorityFrame& priority,
std::unique_ptr<char[]>* output) {
@@ -127,6 +162,7 @@ QuicByteCount HttpEncoder::SerializePriorityFrame(
return 0;
}
+// static
QuicByteCount HttpEncoder::SerializeCancelPushFrame(
const CancelPushFrame& cancel_push,
std::unique_ptr<char[]>* output) {
@@ -147,6 +183,7 @@ QuicByteCount HttpEncoder::SerializeCancelPushFrame(
return 0;
}
+// static
QuicByteCount HttpEncoder::SerializeSettingsFrame(
const SettingsFrame& settings,
std::unique_ptr<char[]>* output) {
@@ -180,6 +217,7 @@ QuicByteCount HttpEncoder::SerializeSettingsFrame(
return total_length;
}
+// static
QuicByteCount HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
const PushPromiseFrame& push_promise,
std::unique_ptr<char[]>* output) {
@@ -205,6 +243,7 @@ QuicByteCount HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
return 0;
}
+// static
QuicByteCount HttpEncoder::SerializeGoAwayFrame(
const GoAwayFrame& goaway,
std::unique_ptr<char[]>* output) {
@@ -225,6 +264,7 @@ QuicByteCount HttpEncoder::SerializeGoAwayFrame(
return 0;
}
+// static
QuicByteCount HttpEncoder::SerializeMaxPushIdFrame(
const MaxPushIdFrame& max_push_id,
std::unique_ptr<char[]>* output) {
@@ -245,6 +285,7 @@ QuicByteCount HttpEncoder::SerializeMaxPushIdFrame(
return 0;
}
+// static
QuicByteCount HttpEncoder::SerializeDuplicatePushFrame(
const DuplicatePushFrame& duplicate_push,
std::unique_ptr<char[]>* output) {
@@ -266,41 +307,4 @@ QuicByteCount HttpEncoder::SerializeDuplicatePushFrame(
return 0;
}
-bool HttpEncoder::WriteFrameHeader(QuicByteCount length,
- HttpFrameType type,
- QuicDataWriter* writer) {
- return writer->WriteVarInt62(static_cast<uint64_t>(type)) &&
- writer->WriteVarInt62(length);
-}
-
-QuicByteCount HttpEncoder::GetTotalLength(QuicByteCount payload_length,
- HttpFrameType type) {
- return QuicDataWriter::GetVarInt62Len(payload_length) +
- QuicDataWriter::GetVarInt62Len(static_cast<uint64_t>(type)) +
- payload_length;
-}
-
-bool HttpEncoder::MaybeWriteIds(const PriorityFrame& priority,
- QuicDataWriter* writer) {
- if (priority.prioritized_type != ROOT_OF_TREE) {
- if (!writer->WriteVarInt62(priority.prioritized_element_id)) {
- return false;
- }
- } else {
- DCHECK_EQ(0u, priority.prioritized_element_id)
- << "Prioritized element id should be 0 when prioritized type is "
- "ROOT_OF_TREE";
- }
- if (priority.dependency_type != ROOT_OF_TREE) {
- if (!writer->WriteVarInt62(priority.element_dependency_id)) {
- return false;
- }
- } else {
- DCHECK_EQ(0u, priority.element_dependency_id)
- << "Element dependency id should be 0 when dependency type is "
- "ROOT_OF_TREE";
- }
- return true;
-}
-
} // namespace 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 12c5bab56c2..4420fc65b7b 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
@@ -17,68 +17,59 @@ class QuicDataWriter;
// session.
class QUIC_EXPORT_PRIVATE HttpEncoder {
public:
- HttpEncoder();
-
- ~HttpEncoder();
+ HttpEncoder() = delete;
// Serializes a DATA frame header into a new buffer stored in |output|.
// Returns the length of the buffer on success, or 0 otherwise.
- QuicByteCount SerializeDataFrameHeader(QuicByteCount payload_length,
- std::unique_ptr<char[]>* output);
+ static QuicByteCount SerializeDataFrameHeader(
+ QuicByteCount payload_length,
+ std::unique_ptr<char[]>* output);
// Serializes a HEADERS frame header into a new buffer stored in |output|.
// Returns the length of the buffer on success, or 0 otherwise.
- QuicByteCount SerializeHeadersFrameHeader(QuicByteCount payload_length,
- std::unique_ptr<char[]>* output);
+ static QuicByteCount SerializeHeadersFrameHeader(
+ QuicByteCount payload_length,
+ std::unique_ptr<char[]>* output);
// Serializes a PRIORITY frame into a new buffer stored in |output|.
// Returns the length of the buffer on success, or 0 otherwise.
- QuicByteCount SerializePriorityFrame(const PriorityFrame& priority,
- std::unique_ptr<char[]>* output);
+ static QuicByteCount SerializePriorityFrame(const PriorityFrame& priority,
+ std::unique_ptr<char[]>* output);
// Serializes a CANCEL_PUSH frame into a new buffer stored in |output|.
// Returns the length of the buffer on success, or 0 otherwise.
- QuicByteCount SerializeCancelPushFrame(const CancelPushFrame& cancel_push,
- std::unique_ptr<char[]>* output);
+ 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.
- QuicByteCount SerializeSettingsFrame(const SettingsFrame& settings,
- std::unique_ptr<char[]>* output);
+ 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.
- QuicByteCount SerializePushPromiseFrameWithOnlyPushId(
+ 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.
- QuicByteCount SerializeGoAwayFrame(const GoAwayFrame& goaway,
- std::unique_ptr<char[]>* output);
+ 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.
- QuicByteCount SerializeMaxPushIdFrame(const MaxPushIdFrame& max_push_id,
- std::unique_ptr<char[]>* output);
+ static QuicByteCount SerializeMaxPushIdFrame(
+ const MaxPushIdFrame& max_push_id,
+ std::unique_ptr<char[]>* output);
// Serialize a DUPLICATE_PUSH frame into a new buffer stored in |output|.
// Returns the length of the buffer on success, or 0 otherwise.
- QuicByteCount SerializeDuplicatePushFrame(
+ static QuicByteCount SerializeDuplicatePushFrame(
const DuplicatePushFrame& duplicate_push,
std::unique_ptr<char[]>* output);
-
- private:
- bool WriteFrameHeader(QuicByteCount length,
- HttpFrameType type,
- QuicDataWriter* writer);
-
- QuicByteCount GetTotalLength(QuicByteCount payload_length,
- HttpFrameType type);
-
- // Write prioritized element id and element dependency id if needed.
- bool MaybeWriteIds(const PriorityFrame& priority, QuicDataWriter* writer);
};
} // 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 43ae7cd4a29..2df89bd4ae6 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
@@ -11,16 +11,10 @@
namespace quic {
namespace test {
-class HttpEncoderTest : public QuicTest {
- public:
- HttpEncoderTest() {}
- HttpEncoder encoder_;
-};
-
-TEST_F(HttpEncoderTest, SerializeDataFrameHeader) {
+TEST(HttpEncoderTest, SerializeDataFrameHeader) {
std::unique_ptr<char[]> buffer;
uint64_t length =
- encoder_.SerializeDataFrameHeader(/* payload_length = */ 5, &buffer);
+ HttpEncoder::SerializeDataFrameHeader(/* payload_length = */ 5, &buffer);
char output[] = {// type (DATA)
0x00,
// length
@@ -30,10 +24,10 @@ TEST_F(HttpEncoderTest, SerializeDataFrameHeader) {
QUIC_ARRAYSIZE(output));
}
-TEST_F(HttpEncoderTest, SerializeHeadersFrameHeader) {
+TEST(HttpEncoderTest, SerializeHeadersFrameHeader) {
std::unique_ptr<char[]> buffer;
- uint64_t length =
- encoder_.SerializeHeadersFrameHeader(/* payload_length = */ 7, &buffer);
+ uint64_t length = HttpEncoder::SerializeHeadersFrameHeader(
+ /* payload_length = */ 7, &buffer);
char output[] = {// type (HEADERS)
0x01,
// length
@@ -43,7 +37,7 @@ TEST_F(HttpEncoderTest, SerializeHeadersFrameHeader) {
QUIC_ARRAYSIZE(output));
}
-TEST_F(HttpEncoderTest, SerializePriorityFrame) {
+TEST(HttpEncoderTest, SerializePriorityFrame) {
PriorityFrame priority;
priority.prioritized_type = REQUEST_STREAM;
priority.dependency_type = REQUEST_STREAM;
@@ -65,7 +59,7 @@ TEST_F(HttpEncoderTest, SerializePriorityFrame) {
0xFF};
std::unique_ptr<char[]> buffer;
- uint64_t length = encoder_.SerializePriorityFrame(priority, &buffer);
+ uint64_t length = HttpEncoder::SerializePriorityFrame(priority, &buffer);
EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
CompareCharArraysWithHexError("PRIORITY", buffer.get(), length, output,
QUIC_ARRAYSIZE(output));
@@ -86,7 +80,7 @@ TEST_F(HttpEncoderTest, SerializePriorityFrame) {
0x04,
// weight
0xff};
- length = encoder_.SerializePriorityFrame(priority2, &buffer);
+ length = HttpEncoder::SerializePriorityFrame(priority2, &buffer);
EXPECT_EQ(QUIC_ARRAYSIZE(output2), length);
CompareCharArraysWithHexError("PRIORITY", buffer.get(), length, output2,
QUIC_ARRAYSIZE(output2));
@@ -104,13 +98,13 @@ TEST_F(HttpEncoderTest, SerializePriorityFrame) {
0xf8,
// weight
0xff};
- length = encoder_.SerializePriorityFrame(priority3, &buffer);
+ length = HttpEncoder::SerializePriorityFrame(priority3, &buffer);
EXPECT_EQ(QUIC_ARRAYSIZE(output3), length);
CompareCharArraysWithHexError("PRIORITY", buffer.get(), length, output3,
QUIC_ARRAYSIZE(output3));
}
-TEST_F(HttpEncoderTest, SerializeCancelPushFrame) {
+TEST(HttpEncoderTest, SerializeCancelPushFrame) {
CancelPushFrame cancel_push;
cancel_push.push_id = 0x01;
char output[] = {// type (CANCEL_PUSH)
@@ -120,13 +114,13 @@ TEST_F(HttpEncoderTest, SerializeCancelPushFrame) {
// Push Id
0x01};
std::unique_ptr<char[]> buffer;
- uint64_t length = encoder_.SerializeCancelPushFrame(cancel_push, &buffer);
+ uint64_t length = HttpEncoder::SerializeCancelPushFrame(cancel_push, &buffer);
EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
CompareCharArraysWithHexError("CANCEL_PUSH", buffer.get(), length, output,
QUIC_ARRAYSIZE(output));
}
-TEST_F(HttpEncoderTest, SerializeSettingsFrame) {
+TEST(HttpEncoderTest, SerializeSettingsFrame) {
SettingsFrame settings;
settings.values[1] = 2;
settings.values[6] = 5;
@@ -148,13 +142,13 @@ TEST_F(HttpEncoderTest, SerializeSettingsFrame) {
// content
0x04};
std::unique_ptr<char[]> buffer;
- uint64_t length = encoder_.SerializeSettingsFrame(settings, &buffer);
+ uint64_t length = HttpEncoder::SerializeSettingsFrame(settings, &buffer);
EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
CompareCharArraysWithHexError("SETTINGS", buffer.get(), length, output,
QUIC_ARRAYSIZE(output));
}
-TEST_F(HttpEncoderTest, SerializePushPromiseFrameWithOnlyPushId) {
+TEST(HttpEncoderTest, SerializePushPromiseFrameWithOnlyPushId) {
PushPromiseFrame push_promise;
push_promise.push_id = 0x01;
push_promise.headers = "Headers";
@@ -165,14 +159,14 @@ TEST_F(HttpEncoderTest, SerializePushPromiseFrameWithOnlyPushId) {
// Push Id
0x01};
std::unique_ptr<char[]> buffer;
- uint64_t length =
- encoder_.SerializePushPromiseFrameWithOnlyPushId(push_promise, &buffer);
+ uint64_t length = HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
+ push_promise, &buffer);
EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
CompareCharArraysWithHexError("PUSH_PROMISE", buffer.get(), length, output,
QUIC_ARRAYSIZE(output));
}
-TEST_F(HttpEncoderTest, SerializeGoAwayFrame) {
+TEST(HttpEncoderTest, SerializeGoAwayFrame) {
GoAwayFrame goaway;
goaway.stream_id = 0x1;
char output[] = {// type (GOAWAY)
@@ -182,13 +176,13 @@ TEST_F(HttpEncoderTest, SerializeGoAwayFrame) {
// StreamId
0x01};
std::unique_ptr<char[]> buffer;
- uint64_t length = encoder_.SerializeGoAwayFrame(goaway, &buffer);
+ uint64_t length = HttpEncoder::SerializeGoAwayFrame(goaway, &buffer);
EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
CompareCharArraysWithHexError("GOAWAY", buffer.get(), length, output,
QUIC_ARRAYSIZE(output));
}
-TEST_F(HttpEncoderTest, SerializeMaxPushIdFrame) {
+TEST(HttpEncoderTest, SerializeMaxPushIdFrame) {
MaxPushIdFrame max_push_id;
max_push_id.push_id = 0x1;
char output[] = {// type (MAX_PUSH_ID)
@@ -198,13 +192,13 @@ TEST_F(HttpEncoderTest, SerializeMaxPushIdFrame) {
// Push Id
0x01};
std::unique_ptr<char[]> buffer;
- uint64_t length = encoder_.SerializeMaxPushIdFrame(max_push_id, &buffer);
+ uint64_t length = HttpEncoder::SerializeMaxPushIdFrame(max_push_id, &buffer);
EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
CompareCharArraysWithHexError("MAX_PUSH_ID", buffer.get(), length, output,
QUIC_ARRAYSIZE(output));
}
-TEST_F(HttpEncoderTest, SerializeDuplicatePushFrame) {
+TEST(HttpEncoderTest, SerializeDuplicatePushFrame) {
DuplicatePushFrame duplicate_push;
duplicate_push.push_id = 0x1;
char output[] = {// type (DUPLICATE_PUSH)
@@ -215,7 +209,7 @@ TEST_F(HttpEncoderTest, SerializeDuplicatePushFrame) {
0x01};
std::unique_ptr<char[]> buffer;
uint64_t length =
- encoder_.SerializeDuplicatePushFrame(duplicate_push, &buffer);
+ HttpEncoder::SerializeDuplicatePushFrame(duplicate_push, &buffer);
EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
CompareCharArraysWithHexError("DUPLICATE_PUSH", buffer.get(), length, output,
QUIC_ARRAYSIZE(output));
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 dde8b1e6f9e..215fa568d29 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
@@ -34,7 +34,7 @@ enum class HttpFrameType : uint8_t {
//
// DATA frames (type=0x0) convey arbitrary, variable-length sequences of
// octets associated with an HTTP request or response payload.
-struct DataFrame {
+struct QUIC_EXPORT_PRIVATE DataFrame {
QuicStringPiece data;
};
@@ -42,7 +42,7 @@ struct DataFrame {
//
// The HEADERS frame (type=0x1) is used to carry a header block,
// compressed using QPACK.
-struct HeadersFrame {
+struct QUIC_EXPORT_PRIVATE HeadersFrame {
QuicStringPiece headers;
};
@@ -65,7 +65,7 @@ enum PriorityElementType : uint8_t {
ROOT_OF_TREE = 3
};
-struct PriorityFrame {
+struct QUIC_EXPORT_PRIVATE PriorityFrame {
PriorityElementType prioritized_type = REQUEST_STREAM;
PriorityElementType dependency_type = REQUEST_STREAM;
bool exclusive = false;
@@ -103,7 +103,7 @@ struct PriorityFrame {
// server push prior to the push stream being created.
using PushId = uint64_t;
-struct CancelPushFrame {
+struct QUIC_EXPORT_PRIVATE CancelPushFrame {
PushId push_id;
bool operator==(const CancelPushFrame& rhs) const {
@@ -119,7 +119,7 @@ struct CancelPushFrame {
using SettingsMap = std::map<uint64_t, uint64_t>;
-struct SettingsFrame {
+struct QUIC_EXPORT_PRIVATE SettingsFrame {
SettingsMap values;
bool operator==(const SettingsFrame& rhs) const {
@@ -148,7 +148,7 @@ struct SettingsFrame {
//
// The PUSH_PROMISE frame (type=0x05) is used to carry a request header
// set from server to client, as in HTTP/2.
-struct PushPromiseFrame {
+struct QUIC_EXPORT_PRIVATE PushPromiseFrame {
PushId push_id;
QuicStringPiece headers;
@@ -161,7 +161,7 @@ struct PushPromiseFrame {
//
// The GOAWAY frame (type=0x7) is used to initiate graceful shutdown of
// a connection by a server.
-struct GoAwayFrame {
+struct QUIC_EXPORT_PRIVATE GoAwayFrame {
QuicStreamId stream_id;
bool operator==(const GoAwayFrame& rhs) const {
@@ -173,7 +173,7 @@ struct GoAwayFrame {
//
// The MAX_PUSH_ID frame (type=0xD) is used by clients to control the
// number of server pushes that the server can initiate.
-struct MaxPushIdFrame {
+struct QUIC_EXPORT_PRIVATE MaxPushIdFrame {
PushId push_id;
bool operator==(const MaxPushIdFrame& rhs) const {
@@ -186,7 +186,7 @@ struct MaxPushIdFrame {
// The DUPLICATE_PUSH frame (type=0xE) is used by servers to indicate
// that an existing pushed resource is related to multiple client
// requests.
-struct DuplicatePushFrame {
+struct QUIC_EXPORT_PRIVATE DuplicatePushFrame {
PushId push_id;
bool operator==(const DuplicatePushFrame& rhs) const {
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info.h
index bf614051fc1..9268940240e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info.h
@@ -84,7 +84,7 @@ class QUIC_EXPORT_PRIVATE QuicClientPromisedInfo
private:
friend class test::QuicClientPromisedInfoPeer;
- class CleanupAlarm : public QuicAlarm::Delegate {
+ class QUIC_EXPORT_PRIVATE CleanupAlarm : public QuicAlarm::Delegate {
public:
explicit CleanupAlarm(QuicClientPromisedInfo* promised)
: promised_(promised) {}
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info_test.cc
index e244fcf83c3..27d9fe89630 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info_test.cc
@@ -89,7 +89,6 @@ class QuicClientPromisedInfoTest : public QuicTest {
push_promise_[":path"] = "/bar";
push_promise_[":authority"] = "www.google.com";
- push_promise_[":version"] = "HTTP/1.1";
push_promise_[":method"] = "GET";
push_promise_[":scheme"] = "https";
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_client_push_promise_index_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_client_push_promise_index_test.cc
index 933ef6bb808..3ca377eb729 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_client_push_promise_index_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_client_push_promise_index_test.cc
@@ -60,7 +60,6 @@ class QuicClientPushPromiseIndexTest : public QuicTest {
url_) {
request_[":path"] = "/bar";
request_[":authority"] = "www.google.com";
- request_[":version"] = "HTTP/1.1";
request_[":method"] = "GET";
request_[":scheme"] = "https";
url_ = SpdyServerPushUtils::GetPromisedUrlFromHeaders(request_);
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 f9b730bcb4c..cba3e587ab3 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
@@ -4,6 +4,7 @@
#include "net/third_party/quiche/src/quic/core/http/quic_header_list.h"
+#include <limits>
#include <string>
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
@@ -13,7 +14,7 @@
namespace quic {
QuicHeaderList::QuicHeaderList()
- : max_header_list_size_(kDefaultMaxUncompressedHeaderSize),
+ : max_header_list_size_(std::numeric_limits<size_t>::max()),
current_header_list_size_(0),
uncompressed_header_bytes_(0),
compressed_header_bytes_(0) {}
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_header_list_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_header_list_test.cc
index 67bd35f2644..5ff3c5a6b58 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_header_list_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_header_list_test.cc
@@ -37,9 +37,12 @@ TEST_F(QuicHeaderListTest, DebugString) {
}
TEST_F(QuicHeaderListTest, TooLarge) {
+ const size_t kMaxHeaderListSize = 256;
+
QuicHeaderList headers;
+ headers.set_max_header_list_size(kMaxHeaderListSize);
std::string key = "key";
- std::string value(1 << 18, '1');
+ std::string value(kMaxHeaderListSize, '1');
// Send a header that exceeds max_header_list_size.
headers.OnHeader(key, value);
// Send a second header exceeding max_header_list_size.
@@ -48,8 +51,8 @@ TEST_F(QuicHeaderListTest, TooLarge) {
EXPECT_LT(headers.DebugString().size(), 2 * value.size());
size_t total_bytes = 2 * (key.size() + value.size()) + 1;
headers.OnHeaderBlockEnd(total_bytes, total_bytes);
- EXPECT_TRUE(headers.empty());
+ EXPECT_TRUE(headers.empty());
EXPECT_EQ("{ }", headers.DebugString());
}
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 079150638f4..4cf11cc2976 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
@@ -25,6 +25,7 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
#include "net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h"
#include "net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
@@ -36,7 +37,6 @@ using spdy::SETTINGS_HEADER_TABLE_SIZE;
using spdy::SETTINGS_INITIAL_WINDOW_SIZE;
using spdy::SETTINGS_MAX_CONCURRENT_STREAMS;
using spdy::SETTINGS_MAX_FRAME_SIZE;
-using spdy::SETTINGS_MAX_HEADER_LIST_SIZE;
using spdy::Spdy3PriorityToHttp2Weight;
using spdy::SpdyAltSvcWireFormat;
using spdy::SpdyDataIR;
@@ -200,7 +200,6 @@ class QuicHeadersStreamTest : public QuicTestWithParam<TestParams> {
QuicSpdySessionPeer::SetMaxInboundHeaderListSize(&session_, 256 * 1024);
session_.Initialize();
headers_stream_ = QuicSpdySessionPeer::GetHeadersStream(&session_);
- headers_[":version"] = "HTTP/1.1";
headers_[":status"] = "200 Ok";
headers_["content-length"] = "11";
framer_ = std::unique_ptr<SpdyFramer>(
@@ -228,7 +227,7 @@ class QuicHeadersStreamTest : public QuicTestWithParam<TestParams> {
QuicConsumedData SaveIov(size_t write_length) {
char* buf = new char[write_length];
- QuicDataWriter writer(write_length, buf, NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(write_length, buf, quiche::NETWORK_BYTE_ORDER);
headers_stream_->WriteStreamData(headers_stream_->stream_bytes_written(),
write_length, &writer);
saved_data_.append(buf, write_length);
@@ -306,7 +305,7 @@ class QuicHeadersStreamTest : public QuicTestWithParam<TestParams> {
} else {
EXPECT_CALL(visitor_,
OnHeaders(stream_id, !kHasPriority,
- /*priority=*/0,
+ /*weight=*/0,
/*parent_stream_id=*/0,
/*exclusive=*/false, fin, kFrameComplete));
}
@@ -521,13 +520,7 @@ TEST_P(QuicHeadersStreamTest, ProcessPriorityFrame) {
SpdyPriorityIR priority_frame(stream_id, parent_stream_id, weight, true);
SpdySerializedFrame frame(framer_->SerializeFrame(priority_frame));
parent_stream_id = stream_id;
- if (transport_version() <= QUIC_VERSION_39) {
- EXPECT_CALL(*connection_,
- CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
- "SPDY PRIORITY frame received.", _))
- .WillRepeatedly(InvokeWithoutArgs(
- this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
- } else if (perspective() == Perspective::IS_CLIENT) {
+ if (perspective() == Perspective::IS_CLIENT) {
EXPECT_CALL(*connection_,
CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
"Server must not send PRIORITY frames.", _))
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 4d78106f372..c949fa77c7f 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
@@ -9,6 +9,7 @@
#include "net/third_party/quiche/src/quic/core/http/http_constants.h"
#include "net/third_party/quiche/src/quic/core/http/http_decoder.h"
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_session.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
namespace quic {
@@ -65,9 +66,15 @@ class QuicReceiveControlStream::HttpDecoderVisitor
return false;
}
- bool OnGoAwayFrame(const GoAwayFrame& /*frame*/) override {
- CloseConnectionOnWrongFrame("Goaway");
- return false;
+ bool OnGoAwayFrame(const GoAwayFrame& frame) override {
+ QuicSpdySession* spdy_session =
+ static_cast<QuicSpdySession*>(stream_->session());
+ if (spdy_session->perspective() == Perspective::IS_SERVER) {
+ CloseConnectionOnWrongFrame("Go Away");
+ return false;
+ }
+ spdy_session->OnHttp3GoAway(frame.stream_id);
+ return true;
}
bool OnSettingsFrameStart(QuicByteCount header_length) override {
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 73b30b3ff09..8418766a97a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream_test.cc
@@ -5,6 +5,7 @@
#include "net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h"
#include "net/third_party/quiche/src/quic/core/http/http_constants.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
@@ -17,7 +18,6 @@ namespace test {
namespace {
using ::testing::_;
-using ::testing::AtLeast;
using ::testing::StrictMock;
struct TestParams {
@@ -103,18 +103,16 @@ class QuicReceiveControlStreamTest : public QuicTestWithParam<TestParams> {
Perspective perspective() const { return GetParam().perspective; }
std::string EncodeSettings(const SettingsFrame& settings) {
- HttpEncoder encoder;
std::unique_ptr<char[]> buffer;
QuicByteCount settings_frame_length =
- encoder.SerializeSettingsFrame(settings, &buffer);
+ HttpEncoder::SerializeSettingsFrame(settings, &buffer);
return std::string(buffer.get(), settings_frame_length);
}
std::string PriorityFrame(const PriorityFrame& frame) {
- HttpEncoder encoder;
std::unique_ptr<char[]> priority_buffer;
QuicByteCount priority_frame_length =
- encoder.SerializePriorityFrame(frame, &priority_buffer);
+ HttpEncoder::SerializePriorityFrame(frame, &priority_buffer);
return std::string(priority_buffer.get(), priority_frame_length);
}
@@ -214,11 +212,11 @@ TEST_P(QuicReceiveControlStreamTest, ReceiveSettingsFragments) {
}
TEST_P(QuicReceiveControlStreamTest, ReceiveWrongFrame) {
- GoAwayFrame goaway;
- goaway.stream_id = 0x1;
- HttpEncoder encoder;
+ DuplicatePushFrame dup;
+ dup.push_id = 0x1;
std::unique_ptr<char[]> buffer;
- QuicByteCount header_length = encoder.SerializeGoAwayFrame(goaway, &buffer);
+ QuicByteCount header_length =
+ HttpEncoder::SerializeDuplicatePushFrame(dup, &buffer);
std::string data = std::string(buffer.get(), header_length);
QuicStreamFrame frame(receive_control_stream_->id(), false, 1, data);
@@ -245,14 +243,35 @@ TEST_P(QuicReceiveControlStreamTest, ReceivePriorityFrame) {
EXPECT_EQ(1u, stream_->precedence().spdy3_priority());
}
+TEST_P(QuicReceiveControlStreamTest, ReceiveGoAwayFrame) {
+ GoAwayFrame goaway;
+ goaway.stream_id = 0x00;
+
+ std::unique_ptr<char[]> buffer;
+ QuicByteCount header_length =
+ HttpEncoder::SerializeGoAwayFrame(goaway, &buffer);
+ std::string data = std::string(buffer.get(), header_length);
+
+ QuicStreamFrame frame(receive_control_stream_->id(), false, 1, data);
+ EXPECT_FALSE(session_.http3_goaway_received());
+
+ if (perspective() == Perspective::IS_SERVER) {
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_DECODER_ERROR, _, _));
+ }
+
+ receive_control_stream_->OnStreamFrame(frame);
+ if (perspective() == Perspective::IS_CLIENT) {
+ EXPECT_TRUE(session_.http3_goaway_received());
+ }
+}
+
TEST_P(QuicReceiveControlStreamTest, PushPromiseOnControlStreamShouldClose) {
PushPromiseFrame push_promise;
push_promise.push_id = 0x01;
push_promise.headers = "Headers";
std::unique_ptr<char[]> buffer;
- HttpEncoder encoder;
- uint64_t length =
- encoder.SerializePushPromiseFrameWithOnlyPushId(push_promise, &buffer);
+ uint64_t length = HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
+ push_promise, &buffer);
QuicStreamFrame frame(receive_control_stream_->id(), false, 1, buffer.get(),
length);
// TODO(lassey) Check for HTTP_WRONG_STREAM error code.
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 da7f79e0f92..ed7cd7ffb40 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.cc
@@ -3,11 +3,15 @@
// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/http/quic_send_control_stream.h"
+#include <memory>
#include "net/third_party/quiche/src/quic/core/http/http_constants.h"
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_session.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
namespace quic {
@@ -55,7 +59,7 @@ void QuicSendControlStream::MaybeSendSettingsFrame() {
std::unique_ptr<char[]> buffer;
QuicByteCount frame_length =
- encoder_.SerializeSettingsFrame(settings, &buffer);
+ HttpEncoder::SerializeSettingsFrame(settings, &buffer);
QUIC_DVLOG(1) << "Control stream " << id() << " is writing settings frame "
<< settings;
QuicSpdySession* spdy_session = static_cast<QuicSpdySession*>(session());
@@ -72,7 +76,7 @@ void QuicSendControlStream::WritePriority(const PriorityFrame& priority) {
MaybeSendSettingsFrame();
std::unique_ptr<char[]> buffer;
QuicByteCount frame_length =
- encoder_.SerializePriorityFrame(priority, &buffer);
+ HttpEncoder::SerializePriorityFrame(priority, &buffer);
QUIC_DVLOG(1) << "Control Stream " << id() << " is writing " << priority;
WriteOrBufferData(QuicStringPiece(buffer.get(), frame_length), false,
nullptr);
@@ -85,9 +89,29 @@ void QuicSendControlStream::SendMaxPushIdFrame(PushId max_push_id) {
MaxPushIdFrame frame;
frame.push_id = max_push_id;
std::unique_ptr<char[]> buffer;
- QuicByteCount frame_length = encoder_.SerializeMaxPushIdFrame(frame, &buffer);
+ QuicByteCount frame_length =
+ HttpEncoder::SerializeMaxPushIdFrame(frame, &buffer);
WriteOrBufferData(QuicStringPiece(buffer.get(), frame_length),
/*fin = */ false, nullptr);
}
+void QuicSendControlStream::SendGoAway(QuicStreamId stream_id) {
+ QuicConnection::ScopedPacketFlusher flusher(session()->connection());
+
+ MaybeSendSettingsFrame();
+ GoAwayFrame frame;
+ // If the peer hasn't created any stream yet. Use stream id 0 to indicate no
+ // request is accepted.
+ if (stream_id ==
+ QuicUtils::GetInvalidStreamId(session()->transport_version())) {
+ stream_id = 0;
+ }
+ frame.stream_id = stream_id;
+ std::unique_ptr<char[]> buffer;
+ QuicByteCount frame_length =
+ HttpEncoder::SerializeGoAwayFrame(frame, &buffer);
+ WriteOrBufferData(QuicStringPiece(buffer.get(), frame_length), false,
+ nullptr);
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream.h
index aa8fff156b3..ac946d35a6f 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
@@ -7,6 +7,7 @@
#include "net/third_party/quiche/src/quic/core/http/http_encoder.h"
#include "net/third_party/quiche/src/quic/core/quic_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
namespace quic {
@@ -42,12 +43,14 @@ class QUIC_EXPORT_PRIVATE QuicSendControlStream : public QuicStream {
// Send |Priority| on this stream. It must be sent after settings.
void WritePriority(const PriorityFrame& priority);
+ // Serialize a GOAWAY frame from |stream_id| and send it on this stream.
+ void SendGoAway(QuicStreamId stream_id);
+
// The send control stream is write unidirectional, so this method should
// never be called.
void OnDataAvailable() override { QUIC_NOTREACHED(); }
private:
- HttpEncoder encoder_;
// Track if a settings frame is already sent.
bool settings_sent_;
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 a06a3196880..de2e705e8c6 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
@@ -93,7 +93,6 @@ class QuicSendControlStreamTest : public QuicTestWithParam<TestParams> {
MockAlarmFactory alarm_factory_;
StrictMock<MockQuicConnection>* connection_;
StrictMock<MockQuicSpdySession> session_;
- HttpEncoder encoder_;
QuicSendControlStream* send_control_stream_;
};
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 c7ab6236c29..9e8c749025b 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
@@ -152,9 +152,10 @@ class QuicServerSessionBaseTest : public QuicTestWithParam<ParsedQuicVersion> {
QuicCryptoServerConfig::ConfigOptions());
SetQuicReloadableFlag(quic_supports_tls_handshake, true);
session_->Initialize();
- QuicSessionPeer::GetMutableCryptoStream(session_.get())
- ->OnSuccessfulVersionNegotiation(supported_versions.front());
- visitor_ = QuicConnectionPeer::GetVisitor(connection_);
+ if (!GetQuicReloadableFlag(quic_version_negotiated_by_default_at_server)) {
+ QuicSessionPeer::GetMutableCryptoStream(session_.get())
+ ->OnSuccessfulVersionNegotiation(supported_versions.front());
+ }
QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(
session_->config(), kMinimumFlowControlSendWindow);
session_->OnConfigNegotiated();
@@ -208,7 +209,6 @@ class QuicServerSessionBaseTest : public QuicTestWithParam<ParsedQuicVersion> {
QuicMemoryCacheBackend memory_cache_backend_;
std::unique_ptr<TestServerSession> session_;
std::unique_ptr<CryptoHandshakeMessage> handshake_message_;
- QuicConnectionVisitorInterface* visitor_;
};
// Compares CachedNetworkParameters.
@@ -253,7 +253,7 @@ TEST_P(QuicServerSessionBaseTest, CloseStreamDueToReset) {
OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
QUIC_RST_ACKNOWLEDGEMENT));
}
- visitor_->OnRstStream(rst1);
+ session_->OnRstStream(rst1);
// For version-99 will create and receive a stop-sending, completing
// the full-close expected by this test.
@@ -263,7 +263,7 @@ TEST_P(QuicServerSessionBaseTest, CloseStreamDueToReset) {
EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
// Send the same two bytes of payload in a new packet.
- visitor_->OnStreamFrame(data1);
+ session_->OnStreamFrame(data1);
// The stream should not be re-opened.
EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
@@ -284,7 +284,7 @@ TEST_P(QuicServerSessionBaseTest, NeverOpenStreamDueToReset) {
OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
QUIC_RST_ACKNOWLEDGEMENT));
}
- visitor_->OnRstStream(rst1);
+ session_->OnRstStream(rst1);
// For version-99 will create and receive a stop-sending, completing
// the full-close expected by this test.
@@ -296,7 +296,7 @@ TEST_P(QuicServerSessionBaseTest, NeverOpenStreamDueToReset) {
// Send two bytes of payload.
QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
QuicStringPiece("HT"));
- visitor_->OnStreamFrame(data1);
+ session_->OnStreamFrame(data1);
// The stream should never be opened, now that the reset is received.
EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
@@ -309,8 +309,8 @@ TEST_P(QuicServerSessionBaseTest, AcceptClosedStream) {
QuicStringPiece("\1\0\0\0\0\0\0\0HT"));
QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(1), false, 0,
QuicStringPiece("\2\0\0\0\0\0\0\0HT"));
- visitor_->OnStreamFrame(frame1);
- visitor_->OnStreamFrame(frame2);
+ session_->OnStreamFrame(frame1);
+ session_->OnStreamFrame(frame2);
EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams());
// Send a reset (and expect the peer to send a RST in response).
@@ -326,7 +326,7 @@ TEST_P(QuicServerSessionBaseTest, AcceptClosedStream) {
OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
QUIC_RST_ACKNOWLEDGEMENT));
}
- visitor_->OnRstStream(rst);
+ session_->OnRstStream(rst);
// For version-99 will create and receive a stop-sending, completing
// the full-close expected by this test.
@@ -340,8 +340,8 @@ TEST_P(QuicServerSessionBaseTest, AcceptClosedStream) {
QuicStringPiece("TP"));
QuicStreamFrame frame4(GetNthClientInitiatedBidirectionalId(1), false, 2,
QuicStringPiece("TP"));
- visitor_->OnStreamFrame(frame3);
- visitor_->OnStreamFrame(frame4);
+ session_->OnStreamFrame(frame3);
+ session_->OnStreamFrame(frame4);
// The stream should never be opened, now that the reset is received.
EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
EXPECT_TRUE(connection_->connected());
@@ -570,8 +570,7 @@ TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) {
SerializedPacket packet(
QuicPacketNumber(1) + kMinPacketsBetweenServerConfigUpdates,
PACKET_4BYTE_PACKET_NUMBER, nullptr, 1000, false, false);
- sent_packet_manager->OnPacketSent(&packet, QuicPacketNumber(), now,
- NOT_RETRANSMISSION,
+ sent_packet_manager->OnPacketSent(&packet, now, NOT_RETRANSMISSION,
HAS_RETRANSMITTABLE_DATA);
// Verify that the proto has exactly the values we expect.
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 c6f99ff9f61..da3336d26a0 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
@@ -53,6 +53,9 @@ bool QuicSpdyClientSession::ShouldCreateOutgoingBidirectionalStream() {
QUIC_DLOG(INFO) << "Encryption not active so no outgoing stream created.";
return false;
}
+ bool goaway_received = VersionUsesHttp3(transport_version())
+ ? http3_goaway_received()
+ : QuicSession::goaway_received();
if (!GetQuicReloadableFlag(quic_use_common_stream_check) &&
!VersionHasIetfQuicFrames(transport_version())) {
if (GetNumOpenOutgoingStreams() >=
@@ -61,14 +64,14 @@ bool QuicSpdyClientSession::ShouldCreateOutgoingBidirectionalStream() {
<< "Already " << GetNumOpenOutgoingStreams() << " open.";
return false;
}
- if (goaway_received() && respect_goaway_) {
+ if (goaway_received && respect_goaway_) {
QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. "
<< "Already received goaway.";
return false;
}
return true;
}
- if (goaway_received() && respect_goaway_) {
+ if (goaway_received && respect_goaway_) {
QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. "
<< "Already received goaway.";
return false;
@@ -132,7 +135,10 @@ bool QuicSpdyClientSession::ShouldCreateIncomingStream(QuicStreamId id) {
QUIC_BUG << "ShouldCreateIncomingStream called when disconnected";
return false;
}
- if (goaway_received() && respect_goaway_) {
+ bool goaway_received = quic::VersionUsesHttp3(transport_version())
+ ? http3_goaway_received()
+ : QuicSession::goaway_received();
+ if (goaway_received && respect_goaway_) {
QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. "
<< "Already received goaway.";
return false;
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 3611c69bcf0..b3def0aca29 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,7 @@ namespace quic {
class QuicConnection;
class QuicServerId;
-class QuicSpdyClientSession : public QuicSpdyClientSessionBase {
+class QUIC_NO_EXPORT QuicSpdyClientSession : public QuicSpdyClientSessionBase {
public:
// Takes ownership of |connection|. Caller retains ownership of
// |promised_by_url|.
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 aef68c8ff8f..7dd2aec34e7 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
@@ -39,15 +39,6 @@ void QuicSpdyClientSessionBase::OnConfigNegotiated() {
QuicSpdySession::OnConfigNegotiated();
}
-void QuicSpdyClientSessionBase::OnCryptoHandshakeEvent(
- CryptoHandshakeEvent event) {
- QuicSpdySession::OnCryptoHandshakeEvent(event);
- if (event == HANDSHAKE_CONFIRMED && max_allowed_push_id() > 0 &&
- VersionUsesHttp3(transport_version())) {
- SendMaxPushId();
- }
-}
-
void QuicSpdyClientSessionBase::OnInitialHeadersComplete(
QuicStreamId stream_id,
const SpdyHeaderBlock& response_headers) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.h
index aec5e75947f..3ca3499e8c7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.h
@@ -50,9 +50,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdyClientSessionBase
void OnConfigNegotiated() override;
- // Override base class to set FEC policy before any data is sent by client.
- void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
-
// Called by |headers_stream_| when push promise headers have been
// completely received.
void OnPromiseHeaderList(QuicStreamId stream_id,
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 59634f8ef69..7c4d914da98 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
@@ -32,6 +32,7 @@
using spdy::SpdyHeaderBlock;
using testing::_;
using testing::AnyNumber;
+using testing::AtLeast;
using testing::AtMost;
using testing::Invoke;
using testing::Truly;
@@ -106,7 +107,6 @@ class QuicSpdyClientSessionTest : public QuicTestWithParam<ParsedQuicVersion> {
session_->Initialize();
push_promise_[":path"] = "/bar";
push_promise_[":authority"] = "www.google.com";
- push_promise_[":version"] = "HTTP/1.1";
push_promise_[":method"] = "GET";
push_promise_[":scheme"] = "https";
promise_url_ =
@@ -165,9 +165,11 @@ class QuicSpdyClientSessionTest : public QuicTestWithParam<ParsedQuicVersion> {
config.SetMaxIncomingBidirectionalStreamsToSend(
server_max_incoming_streams);
}
+ std::unique_ptr<QuicCryptoServerConfig> crypto_config =
+ crypto_test_utils::CryptoServerConfigForTesting();
crypto_test_utils::HandshakeWithFakeServer(
- &config, &helper_, &alarm_factory_, connection_, stream,
- AlpnForVersion(connection_->version()));
+ &config, crypto_config.get(), &helper_, &alarm_factory_, connection_,
+ stream, AlpnForVersion(connection_->version()));
}
QuicCryptoClientConfig crypto_config_;
@@ -244,8 +246,6 @@ TEST_P(QuicSpdyClientSessionTest, MaxNumStreamsWithNoFinOrRst) {
// TODO(nharper): Add support for Transport Parameters in the TLS handshake.
return;
}
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(AnyNumber());
- EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(AnyNumber());
uint32_t kServerMaxIncomingStreams = 1;
CompleteCryptoHandshake(kServerMaxIncomingStreams);
@@ -276,8 +276,6 @@ TEST_P(QuicSpdyClientSessionTest, MaxNumStreamsWithRst) {
// TODO(nharper): Add support for Transport Parameters in the TLS handshake.
return;
}
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(AnyNumber());
- EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(AnyNumber());
uint32_t kServerMaxIncomingStreams = 1;
CompleteCryptoHandshake(kServerMaxIncomingStreams);
@@ -345,7 +343,9 @@ TEST_P(QuicSpdyClientSessionTest, ResetAndTrailers) {
QuicStreamId stream_id = stream->id();
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(AtLeast(1))
+ .WillRepeatedly(Invoke(&ClearControlFrame));
EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(1);
session_->SendRstStream(stream_id, QUIC_STREAM_PEER_GOING_AWAY, 0);
@@ -395,7 +395,9 @@ TEST_P(QuicSpdyClientSessionTest, ReceivedMalformedTrailersAfterSendingRst) {
// Send the RST, which results in the stream being closed locally (but some
// state remains while the client waits for a response from the server).
QuicStreamId stream_id = stream->id();
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(AtLeast(1))
+ .WillRepeatedly(Invoke(&ClearControlFrame));
EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(1);
session_->SendRstStream(stream_id, QUIC_STREAM_PEER_GOING_AWAY, 0);
@@ -532,14 +534,15 @@ TEST_P(QuicSpdyClientSessionTest, InvalidPacketReceived) {
// A packet with invalid framing should cause a connection to be closed.
TEST_P(QuicSpdyClientSessionTest, InvalidFramedPacketReceived) {
- if (GetParam().handshake_protocol == PROTOCOL_TLS1_3) {
+ const ParsedQuicVersion version = GetParam();
+ if (version.handshake_protocol == PROTOCOL_TLS1_3) {
// TODO(nharper, b/112643533): Figure out why this test fails when TLS is
// enabled and fix it.
return;
}
QuicSocketAddress server_address(TestPeerIPAddress(), kTestPort);
QuicSocketAddress client_address(TestPeerIPAddress(), kTestPort);
- if (GetParam().KnowsWhichDecrypterToUse()) {
+ if (version.KnowsWhichDecrypterToUse()) {
connection_->InstallDecrypter(
ENCRYPTION_FORWARD_SECURE,
std::make_unique<NullDecrypter>(Perspective::IS_CLIENT));
@@ -560,10 +563,9 @@ TEST_P(QuicSpdyClientSessionTest, InvalidFramedPacketReceived) {
QuicConnectionId source_connection_id = EmptyQuicConnectionId();
QuicFramerPeer::SetLastSerializedServerConnectionId(
QuicConnectionPeer::GetFramer(connection_), destination_connection_id);
- ParsedQuicVersionVector versions = {GetParam()};
bool version_flag = false;
QuicConnectionIdIncluded scid_included = CONNECTION_ID_ABSENT;
- if (VersionHasIetfInvariantHeader(GetParam().transport_version)) {
+ if (VersionHasIetfInvariantHeader(version.transport_version)) {
version_flag = true;
source_connection_id = destination_connection_id;
scid_included = CONNECTION_ID_PRESENT;
@@ -571,7 +573,7 @@ TEST_P(QuicSpdyClientSessionTest, InvalidFramedPacketReceived) {
std::unique_ptr<QuicEncryptedPacket> packet(ConstructMisFramedEncryptedPacket(
destination_connection_id, source_connection_id, version_flag, false, 100,
"data", CONNECTION_ID_ABSENT, scid_included, PACKET_4BYTE_PACKET_NUMBER,
- &versions, Perspective::IS_SERVER));
+ version, Perspective::IS_SERVER));
std::unique_ptr<QuicReceivedPacket> received(
ConstructReceivedPacket(*packet, QuicTime::Zero()));
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(1);
@@ -618,7 +620,6 @@ TEST_P(QuicSpdyClientSessionTest, PushPromiseStreamIdTooHigh) {
headers.OnHeaderBlockStart();
headers.OnHeader(":path", "/bar");
headers.OnHeader(":authority", "www.google.com");
- headers.OnHeader(":version", "HTTP/1.1");
headers.OnHeader(":method", "GET");
headers.OnHeader(":scheme", "https");
headers.OnHeaderBlockEnd(0, 0);
@@ -924,7 +925,6 @@ TEST_P(QuicSpdyClientSessionTest, TooManyPushPromises) {
headers.OnHeaderBlockStart();
headers.OnHeader(":path", QuicStrCat("/", promise_count));
headers.OnHeader(":authority", "www.google.com");
- headers.OnHeader(":version", "HTTP/1.1");
headers.OnHeader(":method", "GET");
headers.OnHeader(":scheme", "https");
headers.OnHeaderBlockEnd(0, 0);
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 9c94b700936..5cd27d4a6b8 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 QuicSpdyClientStream : public QuicSpdyStream {
+class QUIC_NO_EXPORT 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 84a207ad26c..dd1cadebbd8 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
@@ -96,7 +96,6 @@ class QuicSpdyClientStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
std::unique_ptr<StreamVisitor> stream_visitor_;
SpdyHeaderBlock headers_;
std::string body_;
- HttpEncoder encoder_;
};
INSTANTIATE_TEST_SUITE_P(Tests,
@@ -113,7 +112,8 @@ TEST_P(QuicSpdyClientStreamTest, TestReceivingIllegalResponseStatusCode) {
auto headers = AsHeaderList(headers_);
stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
headers);
- EXPECT_EQ(QUIC_BAD_APPLICATION_PAYLOAD, stream_->stream_error());
+ EXPECT_THAT(stream_->stream_error(),
+ IsStreamError(QUIC_BAD_APPLICATION_PAYLOAD));
}
TEST_P(QuicSpdyClientStreamTest, TestFraming) {
@@ -122,7 +122,7 @@ TEST_P(QuicSpdyClientStreamTest, TestFraming) {
headers);
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
- encoder_.SerializeDataFrameHeader(body_.length(), &buffer);
+ HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
std::string header = std::string(buffer.get(), header_length);
std::string data = VersionUsesHttp3(connection_->transport_version())
? header + body_
@@ -153,7 +153,7 @@ TEST_P(QuicSpdyClientStreamTest, TestFramingOnePacket) {
headers);
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
- encoder_.SerializeDataFrameHeader(body_.length(), &buffer);
+ HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
std::string header = std::string(buffer.get(), header_length);
std::string data = VersionUsesHttp3(connection_->transport_version())
? header + body_
@@ -173,12 +173,12 @@ TEST_P(QuicSpdyClientStreamTest,
stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
headers);
// The headers should parse successfully.
- EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error());
+ EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
EXPECT_EQ("200", stream_->response_headers().find(":status")->second);
EXPECT_EQ(200, stream_->response_code());
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
- encoder_.SerializeDataFrameHeader(large_body.length(), &buffer);
+ HttpEncoder::SerializeDataFrameHeader(large_body.length(), &buffer);
std::string header = std::string(buffer.get(), header_length);
std::string data = VersionUsesHttp3(connection_->transport_version())
? header + large_body
@@ -222,7 +222,7 @@ TEST_P(QuicSpdyClientStreamTest, ReceivingTrailers) {
// received, as well as all data.
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
- encoder_.SerializeDataFrameHeader(body_.length(), &buffer);
+ HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
std::string header = std::string(buffer.get(), header_length);
std::string data = VersionUsesHttp3(connection_->transport_version())
? header + body_
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_server_stream_base.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_server_stream_base.h
index ad0d32699f0..b66b459d021 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_server_stream_base.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_server_stream_base.h
@@ -9,7 +9,7 @@
namespace quic {
-class QuicSpdyServerStreamBase : public QuicSpdyStream {
+class QUIC_NO_EXPORT QuicSpdyServerStreamBase : public QuicSpdyStream {
public:
QuicSpdyServerStreamBase(QuicStreamId id,
QuicSpdySession* session,
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 1888e033f25..1a8eef2935f 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
@@ -31,6 +31,7 @@ class QuicSpdyServerStreamBaseTest : public QuicTest {
: session_(new MockQuicConnection(&helper_,
&alarm_factory_,
Perspective::IS_SERVER)) {
+ session_.Initialize();
stream_ =
new TestQuicSpdyServerStream(GetNthClientInitiatedBidirectionalStreamId(
session_.transport_version(), 0),
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 c876e3d1a93..3a3441bc416 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
@@ -11,6 +11,8 @@
#include "net/third_party/quiche/src/quic/core/http/http_constants.h"
#include "net/third_party/quiche/src/quic/core/http/quic_headers_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
@@ -44,7 +46,6 @@ using spdy::SpdyPriorityIR;
using spdy::SpdyPushPromiseIR;
using spdy::SpdySerializedFrame;
using spdy::SpdySettingsId;
-using spdy::SpdySettingsIR;
using spdy::SpdyStreamId;
namespace quic {
@@ -245,11 +246,6 @@ class QuicSpdySession::SpdyFramerVisitor
int weight,
bool exclusive) override {
DCHECK(!VersionUsesHttp3(session_->transport_version()));
- if (session_->transport_version() <= QUIC_VERSION_39) {
- CloseConnection("SPDY PRIORITY frame received.",
- QUIC_INVALID_HEADERS_STREAM_DATA);
- return;
- }
if (!session_->IsConnected()) {
return;
}
@@ -303,7 +299,6 @@ class QuicSpdySession::SpdyFramerVisitor
}
}
- private:
QuicSpdySession* session_;
QuicHeaderList header_list_;
};
@@ -352,7 +347,10 @@ QuicSpdySession::QuicSpdySession(
spdy_framer_visitor_(new SpdyFramerVisitor(this)),
max_allowed_push_id_(0),
destruction_indicator_(123456789),
- debug_visitor_(nullptr) {
+ debug_visitor_(nullptr),
+ http3_goaway_received_(false),
+ http3_goaway_sent_(false),
+ http3_max_push_id_sent_(false) {
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());
@@ -416,18 +414,16 @@ void QuicSpdySession::Initialize() {
void QuicSpdySession::OnDecoderStreamError(QuicStringPiece error_message) {
DCHECK(VersionUsesHttp3(transport_version()));
- // TODO(b/124216424): Use HTTP_QPACK_DECODER_STREAM_ERROR.
CloseConnectionWithDetails(
- QUIC_DECOMPRESSION_FAILURE,
+ QUIC_QPACK_DECODER_STREAM_ERROR,
QuicStrCat("Decoder stream error: ", error_message));
}
void QuicSpdySession::OnEncoderStreamError(QuicStringPiece error_message) {
DCHECK(VersionUsesHttp3(transport_version()));
- // TODO(b/124216424): Use HTTP_QPACK_ENCODER_STREAM_ERROR.
CloseConnectionWithDetails(
- QUIC_DECOMPRESSION_FAILURE,
+ QUIC_QPACK_ENCODER_STREAM_ERROR,
QuicStrCat("Encoder stream error: ", error_message));
}
@@ -520,9 +516,6 @@ size_t QuicSpdySession::WritePriority(QuicStreamId id,
int weight,
bool exclusive) {
DCHECK(!VersionUsesHttp3(transport_version()));
- if (transport_version() <= QUIC_VERSION_39) {
- return 0;
- }
SpdyPriorityIR priority_frame(id, parent_stream_id, weight, exclusive);
SpdySerializedFrame frame(spdy_framer_.SerializeFrame(priority_frame));
headers_stream()->WriteOrBufferData(
@@ -537,10 +530,29 @@ void QuicSpdySession::WriteH3Priority(const PriorityFrame& priority) {
<< "Server must not send priority";
QuicConnection::ScopedPacketFlusher flusher(connection());
- SendInitialData();
send_control_stream_->WritePriority(priority);
}
+void QuicSpdySession::OnHttp3GoAway(QuicStreamId stream_id) {
+ DCHECK_EQ(perspective(), Perspective::IS_CLIENT);
+ if (!QuicUtils::IsBidirectionalStreamId(stream_id) ||
+ IsIncomingStream(stream_id)) {
+ CloseConnectionWithDetails(
+ QUIC_INVALID_STREAM_ID,
+ "GOAWAY's last stream id has to point to a request stream");
+ return;
+ }
+ http3_goaway_received_ = true;
+}
+
+void QuicSpdySession::SendHttp3GoAway() {
+ DCHECK_EQ(perspective(), Perspective::IS_SERVER);
+ DCHECK(VersionUsesHttp3(transport_version()));
+ http3_goaway_sent_ = true;
+ send_control_stream_->SendGoAway(
+ GetLargestPeerCreatedStreamId(/*unidirectional = */ false));
+}
+
void QuicSpdySession::WritePushPromise(QuicStreamId original_stream_id,
QuicStreamId promised_stream_id,
SpdyHeaderBlock headers) {
@@ -580,27 +592,18 @@ void QuicSpdySession::WritePushPromise(QuicStreamId original_stream_id,
}
void QuicSpdySession::SendInitialData() {
- if (VersionUsesHttp3(transport_version())) {
- QuicConnection::ScopedPacketFlusher flusher(connection());
- send_control_stream_->MaybeSendSettingsFrame();
- // TODO(renjietang): Remove this once stream id manager can take dynamically
- // created HTTP/3 unidirectional streams.
- qpack_encoder_send_stream_->MaybeSendStreamType();
- qpack_decoder_send_stream_->MaybeSendStreamType();
+ if (!VersionUsesHttp3(transport_version())) {
return;
}
- if (GetQuicReloadableFlag(quic_do_not_send_settings)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_do_not_send_settings);
- return;
+ QuicConnection::ScopedPacketFlusher flusher(connection());
+ send_control_stream_->MaybeSendSettingsFrame();
+ if (GetQuicReloadableFlag(quic_send_max_push_id_with_settings) &&
+ perspective() == Perspective::IS_CLIENT && !http3_max_push_id_sent_) {
+ SendMaxPushId();
+ http3_max_push_id_sent_ = true;
}
-
- SpdySettingsIR settings_frame;
- settings_frame.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE,
- max_inbound_header_list_size_);
-
- SpdySerializedFrame frame(spdy_framer_.SerializeFrame(settings_frame));
- headers_stream()->WriteOrBufferData(
- QuicStringPiece(frame.data(), frame.size()), false, nullptr);
+ qpack_decoder_send_stream_->MaybeSendStreamType();
+ qpack_encoder_send_stream_->MaybeSendStreamType();
}
QpackEncoder* QuicSpdySession::qpack_encoder() {
@@ -630,19 +633,20 @@ QuicSpdyStream* QuicSpdySession::GetSpdyDataStream(
void QuicSpdySession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
QuicSession::OnCryptoHandshakeEvent(event);
- if (VersionUsesHttp3(transport_version()) ||
- (event == HANDSHAKE_CONFIRMED && config()->SupportMaxHeaderListSize())) {
- SendInitialData();
- }
+ SendInitialData();
+}
+
+void QuicSpdySession::SetDefaultEncryptionLevel(quic::EncryptionLevel level) {
+ QuicSession::SetDefaultEncryptionLevel(level);
+ SendInitialData();
}
// True if there are open HTTP requests.
bool QuicSpdySession::ShouldKeepConnectionAlive() const {
- if (GetQuicReloadableFlag(quic_aggressive_connection_aliveness)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_aggressive_connection_aliveness);
- return GetNumActiveStreams() > 0;
+ if (!VersionUsesHttp3(transport_version())) {
+ DCHECK(pending_streams().empty());
}
- return GetNumOpenDynamicStreams() > 0;
+ return GetNumActiveStreams() + pending_streams().size() > 0;
}
bool QuicSpdySession::UsesPendingStreams() const {
@@ -1035,9 +1039,8 @@ void QuicSpdySession::SetMaxAllowedPushId(QuicStreamId max_allowed_push_id) {
}
DCHECK(perspective() == Perspective::IS_CLIENT);
- if (IsHandshakeConfirmed()) {
+ if (IsCryptoHandshakeConfirmed()) {
SendMaxPushId();
- send_control_stream_->SendMaxPushIdFrame(max_allowed_push_id_);
}
}
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 0eb3751e679..575d6641a61 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
@@ -21,7 +21,6 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
@@ -153,6 +152,13 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// Writes a HTTP/3 PRIORITY frame to the peer.
void WriteH3Priority(const PriorityFrame& priority);
+ // Process received HTTP/3 GOAWAY frame. This method should only be called on
+ // the client side.
+ virtual void OnHttp3GoAway(QuicStreamId stream_id);
+
+ // Write the GOAWAY |frame| on control stream.
+ void SendHttp3GoAway();
+
// Write |headers| for |promised_stream_id| on |original_stream_id| in a
// PUSH_PROMISE frame to peer.
virtual void WritePushPromise(QuicStreamId original_stream_id,
@@ -237,6 +243,10 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
Http3DebugVisitor* debug_visitor() { return debug_visitor_; }
+ bool http3_goaway_received() const { return http3_goaway_received_; }
+
+ bool http3_goaway_sent() const { return http3_goaway_sent_; }
+
// Log header compression ratio histogram.
// |using_qpack| is true for QPACK, false for HPACK.
// |is_sent| is true for sent headers, false for received ones.
@@ -255,6 +265,14 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
QuicByteCount compressed,
QuicByteCount uncompressed);
+ // True if any dynamic table entries have been referenced from either a sent
+ // or received header block. Used for stats.
+ bool dynamic_table_entry_referenced() const {
+ return (qpack_encoder_ &&
+ qpack_encoder_->dynamic_table_entry_referenced()) ||
+ (qpack_decoder_ && qpack_decoder_->dynamic_table_entry_referenced());
+ }
+
protected:
// Override CreateIncomingStream(), CreateOutgoingBidirectionalStream() and
// CreateOutgoingUnidirectionalStream() with QuicSpdyStream return type to
@@ -295,6 +313,7 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
+ void SetDefaultEncryptionLevel(quic::EncryptionLevel level) override;
bool supports_push_promise() { return supports_push_promise_; }
@@ -416,6 +435,14 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// Not owned by the session.
Http3DebugVisitor* debug_visitor_;
+
+ // If the endpoint has received HTTP/3 GOAWAY frame.
+ bool http3_goaway_received_;
+ // If the endpoint has sent HTTP/3 GOAWAY frame.
+ bool http3_goaway_sent_;
+
+ // If the sendpoint has sent the initial HTTP/3 MAX_PUSH_ID frame.
+ bool http3_max_push_id_sent_;
};
} // 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 85e79a7a987..b37246acd23 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
@@ -13,6 +13,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h"
#include "net/third_party/quiche/src/quic/core/http/http_constants.h"
+#include "net/third_party/quiche/src/quic/core/http/http_encoder.h"
#include "net/third_party/quiche/src/quic/core/quic_config.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
@@ -29,8 +30,9 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
-#include "net/third_party/quiche/src/quic/test_tools/qpack_encoder_peer.h"
-#include "net/third_party/quiche/src/quic/test_tools/qpack_header_table_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_flow_controller_peer.h"
@@ -39,6 +41,7 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
using spdy::kV3HighestPriority;
@@ -95,11 +98,16 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
error =
session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
}
- EXPECT_EQ(QUIC_NO_ERROR, error);
+ EXPECT_THAT(error, IsQuicNoError());
session()->OnConfigNegotiated();
- session()->connection()->SetDefaultEncryptionLevel(
- ENCRYPTION_FORWARD_SECURE);
- session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
+ if (session()->use_handshake_delegate()) {
+ session()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
+ } else {
+ session()->connection()->SetDefaultEncryptionLevel(
+ ENCRYPTION_FORWARD_SECURE);
+ session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
+ }
}
// QuicCryptoStream implementation
@@ -114,6 +122,7 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
CryptoMessageParser* crypto_message_parser() override {
return QuicCryptoHandshaker::crypto_message_parser();
}
+ void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
MOCK_METHOD0(OnCanWrite, void());
@@ -296,6 +305,7 @@ class TestSession : public QuicSpdySession {
}
using QuicSession::closed_streams;
+ using QuicSession::ShouldKeepConnectionAlive;
using QuicSession::zombie_streams;
using QuicSpdySession::ProcessPendingStream;
using QuicSpdySession::UsesPendingStreams;
@@ -350,10 +360,9 @@ class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
void CheckClosedStreams() {
QuicStreamId first_stream_id = QuicUtils::GetFirstBidirectionalStreamId(
- connection_->transport_version(), Perspective::IS_CLIENT);
- if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
- first_stream_id =
- QuicUtils::GetCryptoStreamId(connection_->transport_version());
+ transport_version(), Perspective::IS_CLIENT);
+ if (!QuicVersionUsesCryptoFrames(transport_version())) {
+ first_stream_id = QuicUtils::GetCryptoStreamId(transport_version());
}
for (QuicStreamId i = first_stream_id; i < 100; i++) {
if (!QuicContainsKey(closed_streams_, i)) {
@@ -388,18 +397,16 @@ class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
}
QuicStreamId GetNthServerInitiatedBidirectionalId(int n) {
- return GetNthServerInitiatedBidirectionalStreamId(
- connection_->transport_version(), n);
+ return GetNthServerInitiatedBidirectionalStreamId(transport_version(), n);
}
QuicStreamId IdDelta() {
- return QuicUtils::StreamIdDelta(connection_->transport_version());
+ return QuicUtils::StreamIdDelta(transport_version());
}
std::string EncodeSettings(const SettingsFrame& settings) {
- HttpEncoder encoder;
std::unique_ptr<char[]> buffer;
- auto header_length = encoder.SerializeSettingsFrame(settings, &buffer);
+ auto header_length = HttpEncoder::SerializeSettingsFrame(settings, &buffer);
return std::string(buffer.get(), header_length);
}
@@ -456,8 +463,7 @@ TEST_P(QuicSpdySessionTestServer, SelfAddress) {
}
TEST_P(QuicSpdySessionTestServer, IsCryptoHandshakeConfirmed) {
- if (!GetQuicReloadableFlag(quic_do_not_send_settings) ||
- VersionUsesHttp3(transport_version())) {
+ if (VersionUsesHttp3(transport_version())) {
MockPacketWriter* writer = static_cast<MockPacketWriter*>(
QuicConnectionPeer::GetWriter(session_.connection()));
EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
@@ -473,10 +479,9 @@ TEST_P(QuicSpdySessionTestServer, IsCryptoHandshakeConfirmed) {
TEST_P(QuicSpdySessionTestServer, IsClosedStreamDefault) {
// Ensure that no streams are initially closed.
QuicStreamId first_stream_id = QuicUtils::GetFirstBidirectionalStreamId(
- connection_->transport_version(), Perspective::IS_CLIENT);
- if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
- first_stream_id =
- QuicUtils::GetCryptoStreamId(connection_->transport_version());
+ transport_version(), Perspective::IS_CLIENT);
+ if (!QuicVersionUsesCryptoFrames(transport_version())) {
+ first_stream_id = QuicUtils::GetCryptoStreamId(transport_version());
}
for (QuicStreamId i = first_stream_id; i < 100; i++) {
EXPECT_FALSE(session_.IsClosedStream(i)) << "stream id: " << i;
@@ -850,7 +855,7 @@ TEST_P(QuicSpdySessionTestServer, BufferedHandshake) {
// This tests prioritization of the crypto stream when flow control limits are
// reached. When CRYPTO frames are in use, there is no flow control for the
// crypto handshake, so this test is irrelevant.
- if (QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ if (QuicVersionUsesCryptoFrames(transport_version())) {
return;
}
session_.set_writev_consumes_all_data(true);
@@ -867,7 +872,7 @@ TEST_P(QuicSpdySessionTestServer, BufferedHandshake) {
// Blocking (due to buffering of) the Crypto stream is detected.
session_.MarkConnectionLevelWriteBlocked(
- QuicUtils::GetCryptoStreamId(connection_->transport_version()));
+ QuicUtils::GetCryptoStreamId(transport_version()));
EXPECT_TRUE(session_.HasPendingHandshake());
TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
@@ -940,9 +945,9 @@ TEST_P(QuicSpdySessionTestServer,
// Mark the crypto and headers streams as write blocked, we expect them to be
// allowed to write later.
- if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ if (!QuicVersionUsesCryptoFrames(transport_version())) {
session_.MarkConnectionLevelWriteBlocked(
- QuicUtils::GetCryptoStreamId(connection_->transport_version()));
+ QuicUtils::GetCryptoStreamId(transport_version()));
}
// Create a data stream, and although it is write blocked we never expect it
@@ -953,18 +958,18 @@ TEST_P(QuicSpdySessionTestServer,
// The crypto and headers streams should be called even though we are
// connection flow control blocked.
- if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ if (!QuicVersionUsesCryptoFrames(transport_version())) {
TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
EXPECT_CALL(*crypto_stream, OnCanWrite());
}
- if (!VersionUsesHttp3(connection_->transport_version())) {
+ if (!VersionUsesHttp3(transport_version())) {
TestHeadersStream* headers_stream;
QuicSpdySessionPeer::SetHeadersStream(&session_, nullptr);
headers_stream = new TestHeadersStream(&session_);
QuicSpdySessionPeer::SetHeadersStream(&session_, headers_stream);
session_.MarkConnectionLevelWriteBlocked(
- QuicUtils::GetHeadersStreamId(connection_->transport_version()));
+ QuicUtils::GetHeadersStreamId(transport_version()));
EXPECT_CALL(*headers_stream, OnCanWrite());
}
@@ -978,7 +983,7 @@ TEST_P(QuicSpdySessionTestServer,
TEST_P(QuicSpdySessionTestServer, SendGoAway) {
if (VersionHasIetfQuicFrames(transport_version())) {
- // GoAway frames are not in version 99
+ // HTTP/3 GOAWAY has different semantic and thus has its own test.
return;
}
connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
@@ -1001,10 +1006,24 @@ TEST_P(QuicSpdySessionTestServer, SendGoAway) {
EXPECT_TRUE(session_.GetOrCreateStream(kTestStreamId));
}
+TEST_P(QuicSpdySessionTestServer, SendHttp3GoAway) {
+ if (!VersionUsesHttp3(transport_version())) {
+ return;
+ }
+ connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+
+ session_.SendHttp3GoAway();
+ EXPECT_TRUE(session_.http3_goaway_sent());
+
+ const QuicStreamId kTestStreamId =
+ GetNthClientInitiatedBidirectionalStreamId(transport_version(), 0);
+ EXPECT_CALL(*connection_, OnStreamReset(kTestStreamId, _)).Times(0);
+ EXPECT_TRUE(session_.GetOrCreateStream(kTestStreamId));
+}
+
TEST_P(QuicSpdySessionTestServer, DoNotSendGoAwayTwice) {
if (VersionHasIetfQuicFrames(transport_version())) {
- // TODO(b/118808809): Enable this test for version 99 when GOAWAY is
- // supported.
+ // HTTP/3 GOAWAY doesn't have such restriction.
return;
}
EXPECT_CALL(*connection_, SendControlFrame(_))
@@ -1016,8 +1035,7 @@ TEST_P(QuicSpdySessionTestServer, DoNotSendGoAwayTwice) {
TEST_P(QuicSpdySessionTestServer, InvalidGoAway) {
if (VersionHasIetfQuicFrames(transport_version())) {
- // TODO(b/118808809): Enable this test for version 99 when GOAWAY is
- // supported.
+ // HTTP/3 GOAWAY has different semantics and thus has its own test.
return;
}
QuicGoAwayFrame go_away(kInvalidControlFrameId, QUIC_PEER_GOING_AWAY,
@@ -1049,8 +1067,7 @@ TEST_P(QuicSpdySessionTestServer, ServerReplyToConnecitivityProbe) {
}
TEST_P(QuicSpdySessionTestServer, IncreasedTimeoutAfterCryptoHandshake) {
- if (!GetQuicReloadableFlag(quic_do_not_send_settings) ||
- VersionUsesHttp3(transport_version())) {
+ if (VersionUsesHttp3(transport_version())) {
MockPacketWriter* writer = static_cast<MockPacketWriter*>(
QuicConnectionPeer::GetWriter(session_.connection()));
EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
@@ -1115,7 +1132,7 @@ TEST_P(QuicSpdySessionTestServer, OnStreamFrameFinStaticStreamId) {
QuicStreamFrame data1(id, false, 0, QuicStringPiece(type, 1));
session_.OnStreamFrame(data1);
} else {
- id = QuicUtils::GetHeadersStreamId(connection_->transport_version());
+ id = QuicUtils::GetHeadersStreamId(transport_version());
}
// Send two bytes of payload.
@@ -1137,7 +1154,7 @@ TEST_P(QuicSpdySessionTestServer, OnRstStreamStaticStreamId) {
QuicStreamFrame data1(id, false, 0, QuicStringPiece(type, 1));
session_.OnStreamFrame(data1);
} else {
- id = QuicUtils::GetHeadersStreamId(connection_->transport_version());
+ id = QuicUtils::GetHeadersStreamId(transport_version());
}
// Send two bytes of payload.
@@ -1152,9 +1169,8 @@ TEST_P(QuicSpdySessionTestServer, OnRstStreamStaticStreamId) {
TEST_P(QuicSpdySessionTestServer, OnStreamFrameInvalidStreamId) {
// Send two bytes of payload.
- QuicStreamFrame data1(
- QuicUtils::GetInvalidStreamId(connection_->transport_version()), true, 0,
- QuicStringPiece("HT"));
+ QuicStreamFrame data1(QuicUtils::GetInvalidStreamId(transport_version()),
+ true, 0, QuicStringPiece("HT"));
EXPECT_CALL(*connection_,
CloseConnection(
QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
@@ -1164,10 +1180,9 @@ TEST_P(QuicSpdySessionTestServer, OnStreamFrameInvalidStreamId) {
TEST_P(QuicSpdySessionTestServer, OnRstStreamInvalidStreamId) {
// Send two bytes of payload.
- QuicRstStreamFrame rst1(
- kInvalidControlFrameId,
- QuicUtils::GetInvalidStreamId(connection_->transport_version()),
- QUIC_ERROR_PROCESSING_STREAM, 0);
+ QuicRstStreamFrame rst1(kInvalidControlFrameId,
+ QuicUtils::GetInvalidStreamId(transport_version()),
+ QUIC_ERROR_PROCESSING_STREAM, 0);
EXPECT_CALL(*connection_,
CloseConnection(
QUIC_INVALID_STREAM_ID, "Received data for an invalid stream",
@@ -1213,7 +1228,7 @@ TEST_P(QuicSpdySessionTestServer, HandshakeUnblocksFlowControlBlockedStream) {
TEST_P(QuicSpdySessionTestServer,
HandshakeUnblocksFlowControlBlockedCryptoStream) {
- if (QuicVersionUsesCryptoFrames(GetParam().transport_version)) {
+ if (QuicVersionUsesCryptoFrames(transport_version())) {
// QUIC version 47 onwards uses CRYPTO frames for the handshake, so this
// test doesn't make sense for those versions.
return;
@@ -1230,13 +1245,8 @@ TEST_P(QuicSpdySessionTestServer,
EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked());
EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
- if (VersionHasIetfQuicFrames(transport_version())) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillOnce(Invoke(&ClearControlFrame));
- } else {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillOnce(Invoke(&ClearControlFrame));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&ClearControlFrame));
for (QuicStreamId i = 0;
!crypto_stream->flow_controller()->IsBlocked() && i < 1000u; i++) {
EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
@@ -1247,7 +1257,7 @@ TEST_P(QuicSpdySessionTestServer,
config.ToHandshakeMessage(&crypto_message, transport_version());
crypto_stream->SendHandshakeMessage(crypto_message);
char buf[1000];
- QuicDataWriter writer(1000, buf, NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(1000, buf, quiche::NETWORK_BYTE_ORDER);
crypto_stream->WriteStreamData(offset, crypto_message.size(), &writer);
}
EXPECT_TRUE(crypto_stream->flow_controller()->IsBlocked());
@@ -1262,8 +1272,7 @@ TEST_P(QuicSpdySessionTestServer,
CryptoHandshakeMessage msg;
session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(
- &session_,
- QuicUtils::GetCryptoStreamId(connection_->transport_version())));
+ &session_, QuicUtils::GetCryptoStreamId(transport_version())));
// Stream is now unblocked and will no longer have buffered data.
EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
@@ -1280,7 +1289,7 @@ TEST_P(QuicSpdySessionTestServer,
HandshakeUnblocksFlowControlBlockedHeadersStream) {
// This test depends on stream-level flow control for the crypto stream, which
// doesn't exist when CRYPTO frames are used.
- if (QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ if (QuicVersionUsesCryptoFrames(transport_version())) {
return;
}
@@ -1341,8 +1350,7 @@ TEST_P(QuicSpdySessionTestServer,
EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
EXPECT_TRUE(headers_stream->HasBufferedData());
EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(
- &session_,
- QuicUtils::GetHeadersStreamId(connection_->transport_version())));
+ &session_, QuicUtils::GetHeadersStreamId(transport_version())));
}
#endif // !defined(OS_IOS)
@@ -1566,7 +1574,7 @@ TEST_P(QuicSpdySessionTestServer, FlowControlWithInvalidFinalOffset) {
}
TEST_P(QuicSpdySessionTestServer, WindowUpdateUnblocksHeadersStream) {
- if (VersionUsesHttp3(GetParam().transport_version)) {
+ if (VersionUsesHttp3(transport_version())) {
// The test relies on headers stream, which no longer exists in IETF QUIC.
return;
}
@@ -1620,8 +1628,7 @@ TEST_P(QuicSpdySessionTestServer,
GetNthClientInitiatedBidirectionalId(kMaxStreams);
// Create kMaxStreams data streams, and close them all without receiving a
// FIN or a RST_STREAM from the client.
- const QuicStreamId kNextId =
- QuicUtils::StreamIdDelta(connection_->transport_version());
+ const QuicStreamId kNextId = QuicUtils::StreamIdDelta(transport_version());
for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += kNextId) {
QuicStreamFrame data1(i, false, 0, QuicStringPiece("HT"));
session_.OnStreamFrame(data1);
@@ -1738,6 +1745,21 @@ TEST_P(QuicSpdySessionTestClient, BadStreamFramePendingStream) {
session_.OnStreamFrame(data1);
}
+TEST_P(QuicSpdySessionTestClient, PendingStreamKeepsConnectionAlive) {
+ if (!VersionUsesHttp3(transport_version())) {
+ return;
+ }
+
+ QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
+ transport_version(), Perspective::IS_SERVER);
+
+ QuicStreamFrame frame(stream_id, false, 1, "test");
+ EXPECT_FALSE(session_.ShouldKeepConnectionAlive());
+ session_.OnStreamFrame(frame);
+ EXPECT_TRUE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
+ EXPECT_TRUE(session_.ShouldKeepConnectionAlive());
+}
+
TEST_P(QuicSpdySessionTestClient, AvailableStreamsClient) {
ASSERT_TRUE(session_.GetOrCreateStream(
GetNthServerInitiatedBidirectionalId(2)) != nullptr);
@@ -1838,21 +1860,17 @@ TEST_P(QuicSpdySessionTestClient, WritePriority) {
QuicStreamSendBuffer& send_buffer =
QuicStreamPeer::SendBuffer(headers_stream);
- if (transport_version() > QUIC_VERSION_39) {
- ASSERT_EQ(1u, send_buffer.size());
-
- SpdyPriorityIR priority_frame(
- id, parent_stream_id, Spdy3PriorityToHttp2Weight(priority), exclusive);
- SpdyFramer spdy_framer(SpdyFramer::ENABLE_COMPRESSION);
- SpdySerializedFrame frame = spdy_framer.SerializeFrame(priority_frame);
-
- const QuicMemSlice& slice =
- QuicStreamSendBufferPeer::CurrentWriteSlice(&send_buffer)->slice;
- EXPECT_EQ(QuicStringPiece(frame.data(), frame.size()),
- QuicStringPiece(slice.data(), slice.length()));
- } else {
- EXPECT_EQ(0u, send_buffer.size());
- }
+ ASSERT_EQ(1u, send_buffer.size());
+
+ SpdyPriorityIR priority_frame(
+ id, parent_stream_id, Spdy3PriorityToHttp2Weight(priority), exclusive);
+ SpdyFramer spdy_framer(SpdyFramer::ENABLE_COMPRESSION);
+ SpdySerializedFrame frame = spdy_framer.SerializeFrame(priority_frame);
+
+ const QuicMemSlice& slice =
+ QuicStreamSendBufferPeer::CurrentWriteSlice(&send_buffer)->slice;
+ EXPECT_EQ(QuicStringPiece(frame.data(), frame.size()),
+ QuicStringPiece(slice.data(), slice.length()));
}
TEST_P(QuicSpdySessionTestClient, Http3ServerPush) {
@@ -1936,7 +1954,6 @@ TEST_P(QuicSpdySessionTestServer, ZombieStreams) {
}
TEST_P(QuicSpdySessionTestServer, OnStreamFrameLost) {
- QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
InSequence s;
// Drive congestion control manually.
@@ -1952,16 +1969,15 @@ TEST_P(QuicSpdySessionTestServer, OnStreamFrameLost) {
// Lost data on cryption stream, streams 2 and 4.
EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(true));
- if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ if (!QuicVersionUsesCryptoFrames(transport_version())) {
EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
.WillOnce(Return(true));
}
EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(true));
session_.OnFrameLost(QuicFrame(frame3));
- if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
- QuicStreamFrame frame1(
- QuicUtils::GetCryptoStreamId(connection_->transport_version()), false,
- 0, 1300);
+ if (!QuicVersionUsesCryptoFrames(transport_version())) {
+ QuicStreamFrame frame1(QuicUtils::GetCryptoStreamId(transport_version()),
+ false, 0, 1300);
session_.OnFrameLost(QuicFrame(frame1));
} else {
QuicCryptoFrame crypto_frame(ENCRYPTION_INITIAL, 0, 1300);
@@ -1978,7 +1994,7 @@ TEST_P(QuicSpdySessionTestServer, OnStreamFrameLost) {
// stream go first.
// Do not check congestion window when crypto stream has lost data.
EXPECT_CALL(*send_algorithm, CanSend(_)).Times(0);
- if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ if (!QuicVersionUsesCryptoFrames(transport_version())) {
EXPECT_CALL(*crypto_stream, OnCanWrite());
EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
.WillOnce(Return(false));
@@ -2010,7 +2026,14 @@ TEST_P(QuicSpdySessionTestServer, OnStreamFrameLost) {
}
TEST_P(QuicSpdySessionTestServer, DonotRetransmitDataOfClosedStreams) {
- QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
+ // Resetting a stream will send a QPACK Stream Cancellation instruction on the
+ // decoder stream. For simplicity, ignore writes on this stream.
+ NoopQpackStreamSenderDelegate qpack_stream_sender_delegate;
+ if (VersionUsesHttp3(transport_version())) {
+ session_.qpack_decoder()->set_qpack_stream_sender_delegate(
+ &qpack_stream_sender_delegate);
+ }
+
InSequence s;
TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
@@ -2050,7 +2073,6 @@ TEST_P(QuicSpdySessionTestServer, DonotRetransmitDataOfClosedStreams) {
}
TEST_P(QuicSpdySessionTestServer, RetransmitFrames) {
- QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
InSequence s;
@@ -2290,10 +2312,9 @@ TEST_P(QuicSpdySessionTestServer, StreamClosedWhileHeaderDecodingBlocked) {
// HEADERS frame referencing first dynamic table entry.
std::string headers_payload = QuicTextUtils::HexDecode("020080");
std::unique_ptr<char[]> headers_buffer;
- HttpEncoder encoder;
QuicByteCount headers_frame_header_length =
- encoder.SerializeHeadersFrameHeader(headers_payload.length(),
- &headers_buffer);
+ HttpEncoder::SerializeHeadersFrameHeader(headers_payload.length(),
+ &headers_buffer);
QuicStringPiece headers_frame_header(headers_buffer.get(),
headers_frame_header_length);
std::string headers = QuicStrCat(headers_frame_header, headers_payload);
@@ -2325,10 +2346,9 @@ TEST_P(QuicSpdySessionTestServer, SessionDestroyedWhileHeaderDecodingBlocked) {
// HEADERS frame referencing first dynamic table entry.
std::string headers_payload = QuicTextUtils::HexDecode("020080");
std::unique_ptr<char[]> headers_buffer;
- HttpEncoder encoder;
QuicByteCount headers_frame_header_length =
- encoder.SerializeHeadersFrameHeader(headers_payload.length(),
- &headers_buffer);
+ HttpEncoder::SerializeHeadersFrameHeader(headers_payload.length(),
+ &headers_buffer);
QuicStringPiece headers_frame_header(headers_buffer.get(),
headers_frame_header_length);
std::string headers = QuicStrCat(headers_frame_header, headers_payload);
@@ -2384,12 +2404,6 @@ TEST_P(QuicSpdySessionTestClient, ResetAfterInvalidIncomingStreamType) {
QUIC_STREAM_CANCELLED,
/* bytes_written = */ payload.size());
- // This will trigger the sending of two control frames: one RESET_STREAM with
- // QUIC_RST_ACKNOWLEDGEMENT, and one STOP_SENDING.
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(2)
- .WillRepeatedly(Invoke(&ClearControlFrame));
- EXPECT_CALL(*connection_, OnStreamReset(stream_id, QUIC_RST_ACKNOWLEDGEMENT));
session_.OnRstStream(rst_frame);
// The stream is closed.
@@ -2457,12 +2471,6 @@ TEST_P(QuicSpdySessionTestClient, ResetInMiddleOfStreamType) {
QUIC_STREAM_CANCELLED,
/* bytes_written = */ payload.size());
- // This will trigger the sending of two control frames: one RESET_STREAM with
- // QUIC_RST_ACKNOWLEDGEMENT, and one STOP_SENDING.
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(2)
- .WillRepeatedly(Invoke(&ClearControlFrame));
- EXPECT_CALL(*connection_, OnStreamReset(stream_id, QUIC_RST_ACKNOWLEDGEMENT));
session_.OnRstStream(rst_frame);
// The stream is closed.
@@ -2567,7 +2575,7 @@ TEST_P(QuicSpdySessionTestClient, EncoderStreamError) {
EXPECT_CALL(
*connection_,
- CloseConnection(QUIC_DECOMPRESSION_FAILURE,
+ CloseConnection(QUIC_QPACK_ENCODER_STREAM_ERROR,
"Encoder stream error: Invalid relative index.", _));
session_.OnStreamFrame(frame);
}
@@ -2588,11 +2596,25 @@ TEST_P(QuicSpdySessionTestClient, DecoderStreamError) {
EXPECT_CALL(
*connection_,
- CloseConnection(QUIC_DECOMPRESSION_FAILURE,
+ CloseConnection(QUIC_QPACK_DECODER_STREAM_ERROR,
"Decoder stream error: Invalid increment value 0.", _));
session_.OnStreamFrame(frame);
}
+TEST_P(QuicSpdySessionTestClient, InvalidHttp3GoAway) {
+ if (!VersionUsesHttp3(transport_version())) {
+ return;
+ }
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(
+ QUIC_INVALID_STREAM_ID,
+ "GOAWAY's last stream id has to point to a request stream", _));
+ QuicStreamId stream_id =
+ GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
+ session_.OnHttp3GoAway(stream_id);
+}
+
} // 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 5dd9f3a832f..f7a13f62254 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
@@ -193,6 +193,7 @@ QuicSpdyStream::QuicSpdyStream(QuicStreamId id,
visitor_(nullptr),
blocked_on_decoding_headers_(false),
headers_decompressed_(false),
+ header_list_size_limit_exceeded_(false),
headers_payload_length_(0),
trailers_payload_length_(0),
trailers_decompressed_(false),
@@ -227,6 +228,7 @@ QuicSpdyStream::QuicSpdyStream(PendingStream* pending,
visitor_(nullptr),
blocked_on_decoding_headers_(false),
headers_decompressed_(false),
+ header_list_size_limit_exceeded_(false),
headers_payload_length_(0),
trailers_payload_length_(0),
trailers_decompressed_(false),
@@ -297,7 +299,7 @@ void QuicSpdyStream::WriteOrBufferBody(QuicStringPiece data, bool fin) {
// Write frame header.
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
- encoder_.SerializeDataFrameHeader(data.length(), &buffer);
+ HttpEncoder::SerializeDataFrameHeader(data.length(), &buffer);
unacked_frame_headers_offsets_.Add(
send_buffer().stream_offset(),
send_buffer().stream_offset() + header_length);
@@ -310,7 +312,7 @@ void QuicSpdyStream::WriteOrBufferBody(QuicStringPiece data, bool fin) {
// Write body.
QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
<< " is writing DATA frame payload of length "
- << data.length();
+ << data.length() << " with fin " << fin;
WriteOrBufferData(data, fin, nullptr);
}
@@ -358,7 +360,7 @@ void QuicSpdyStream::WritePushPromise(const PushPromiseFrame& frame) {
DCHECK(VersionUsesHttp3(transport_version()));
std::unique_ptr<char[]> push_promise_frame_with_id;
const size_t push_promise_frame_length =
- encoder_.SerializePushPromiseFrameWithOnlyPushId(
+ HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
frame, &push_promise_frame_with_id);
unacked_frame_headers_offsets_.Add(send_buffer().stream_offset(),
@@ -401,7 +403,7 @@ QuicConsumedData QuicSpdyStream::WriteBodySlices(QuicMemSliceSpan slices,
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
- encoder_.SerializeDataFrameHeader(slices.total_length(), &buffer);
+ HttpEncoder::SerializeDataFrameHeader(slices.total_length(), &buffer);
if (!CanWriteNewDataAfterData(header_length)) {
return {0, false};
}
@@ -517,13 +519,13 @@ void QuicSpdyStream::OnStreamHeaderList(bool fin,
size_t frame_len,
const QuicHeaderList& header_list) {
// TODO(b/134706391): remove |fin| argument.
- // The headers list avoid infinite buffering by clearing the headers list
- // if the current headers are too large. So if the list is empty here
- // then the headers list must have been too large, and the stream should
- // be reset.
- // TODO(rch): Use an explicit "headers too large" signal. An empty header list
- // might be acceptable if it corresponds to a trailing header frame.
- if (header_list.empty()) {
+ // When using Google QUIC, an empty header list indicates that the size limit
+ // has been exceeded.
+ // When using IETF QUIC, there is an explicit signal from
+ // QpackDecodedHeadersAccumulator.
+ if ((VersionUsesHttp3(transport_version()) &&
+ header_list_size_limit_exceeded_) ||
+ (!VersionUsesHttp3(transport_version()) && header_list.empty())) {
OnHeadersTooLarge();
if (IsDoneReading()) {
return;
@@ -537,26 +539,46 @@ void QuicSpdyStream::OnStreamHeaderList(bool fin,
}
void QuicSpdyStream::OnHeadersDecoded(QuicHeaderList headers) {
- blocked_on_decoding_headers_ = false;
- ProcessDecodedHeaders(headers);
- // Continue decoding HTTP/3 frames.
- OnDataAvailable();
+ header_list_size_limit_exceeded_ =
+ qpack_decoded_headers_accumulator_->header_list_size_limit_exceeded();
+ qpack_decoded_headers_accumulator_.reset();
+
+ QuicSpdySession::LogHeaderCompressionRatioHistogram(
+ /* using_qpack = */ true,
+ /* is_sent = */ false, headers.compressed_header_bytes(),
+ headers.uncompressed_header_bytes());
+
+ if (spdy_session_->promised_stream_id() ==
+ QuicUtils::GetInvalidStreamId(session()->transport_version())) {
+ const QuicByteCount frame_length = headers_decompressed_
+ ? trailers_payload_length_
+ : headers_payload_length_;
+ OnStreamHeaderList(/* fin = */ false, frame_length, headers);
+ } else {
+ spdy_session_->OnHeaderList(headers);
+ }
+
+ if (blocked_on_decoding_headers_) {
+ blocked_on_decoding_headers_ = false;
+ // Continue decoding HTTP/3 frames.
+ OnDataAvailable();
+ }
}
-void QuicSpdyStream::OnHeaderDecodingError() {
- // TODO(b/124216424): Use HTTP_EXCESSIVE_LOAD or
- // HTTP_QPACK_DECOMPRESSION_FAILED error code as indicated by
- // |qpack_decoded_headers_accumulator_|.
- std::string error_message = QuicStrCat(
- "Error during async decoding of ",
- headers_decompressed_ ? "trailers" : "headers", " on stream ", id(), ": ",
- qpack_decoded_headers_accumulator_->error_message());
- CloseConnectionWithDetails(QUIC_DECOMPRESSION_FAILURE, error_message);
+void QuicSpdyStream::OnHeaderDecodingError(QuicStringPiece error_message) {
+ qpack_decoded_headers_accumulator_.reset();
+
+ std::string connection_close_error_message = QuicStrCat(
+ "Error decoding ", headers_decompressed_ ? "trailers" : "headers",
+ " on stream ", id(), ": ", error_message);
+ CloseConnectionWithDetails(QUIC_QPACK_DECOMPRESSION_FAILED,
+ connection_close_error_message);
}
void QuicSpdyStream::OnHeadersTooLarge() {
if (VersionUsesHttp3(transport_version())) {
- // TODO(124216424): Use HTTP_EXCESSIVE_LOAD error code.
+ // TODO(b/124216424): Reset stream with H3_REQUEST_CANCELLED (if client)
+ // or with H3_REQUEST_REJECTED (if server).
std::string error_message =
QuicStrCat("Too large headers received on stream ", id());
CloseConnectionWithDetails(QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE,
@@ -658,9 +680,12 @@ void QuicSpdyStream::OnPriorityFrame(
void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) {
if (frame.error_code != QUIC_STREAM_NO_ERROR) {
+ // TODO(b/145684124) Call QpackDecoder::OnStreamReset().
+
QuicStream::OnStreamReset(frame);
return;
}
+
QUIC_DVLOG(1) << ENDPOINT
<< "Received QUIC_STREAM_NO_ERROR, not discarding response";
set_rst_received(true);
@@ -669,6 +694,12 @@ void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) {
CloseWriteSide();
}
+void QuicSpdyStream::Reset(QuicRstStreamErrorCode error) {
+ // TODO(b/145684124) Call QpackDecoder::OnStreamReset().
+
+ QuicStream::Reset(error);
+}
+
void QuicSpdyStream::OnDataAvailable() {
if (!VersionUsesHttp3(transport_version())) {
// Sequencer must be blocked until headers are consumed.
@@ -899,18 +930,14 @@ bool QuicSpdyStream::OnHeadersFramePayload(QuicStringPiece payload) {
headers_payload_length_ += payload.length();
}
- const bool success = qpack_decoded_headers_accumulator_->Decode(payload);
+ qpack_decoded_headers_accumulator_->Decode(payload);
- sequencer()->MarkConsumed(body_manager_.OnNonBody(payload.size()));
-
- if (!success) {
- // TODO(124216424): Use HTTP_QPACK_DECOMPRESSION_FAILED error code.
- std::string error_message =
- QuicStrCat("Error decompressing header block on stream ", id(), ": ",
- qpack_decoded_headers_accumulator_->error_message());
- CloseConnectionWithDetails(QUIC_DECOMPRESSION_FAILURE, error_message);
+ // |qpack_decoded_headers_accumulator_| is reset if an error is detected.
+ if (!qpack_decoded_headers_accumulator_) {
return false;
}
+
+ sequencer()->MarkConsumed(body_manager_.OnNonBody(payload.size()));
return true;
}
@@ -918,25 +945,15 @@ bool QuicSpdyStream::OnHeadersFrameEnd() {
DCHECK(VersionUsesHttp3(transport_version()));
DCHECK(qpack_decoded_headers_accumulator_);
- auto result = qpack_decoded_headers_accumulator_->EndHeaderBlock();
+ qpack_decoded_headers_accumulator_->EndHeaderBlock();
- if (result == QpackDecodedHeadersAccumulator::Status::kError) {
- // TODO(124216424): Use HTTP_QPACK_DECOMPRESSION_FAILED error code.
- std::string error_message =
- QuicStrCat("Error decompressing header block on stream ", id(), ": ",
- qpack_decoded_headers_accumulator_->error_message());
- CloseConnectionWithDetails(QUIC_DECOMPRESSION_FAILURE, error_message);
- return false;
- }
-
- if (result == QpackDecodedHeadersAccumulator::Status::kBlocked) {
+ // If decoding is complete or an error is detected, then
+ // |qpack_decoded_headers_accumulator_| is already reset.
+ if (qpack_decoded_headers_accumulator_) {
blocked_on_decoding_headers_ = true;
return false;
}
- DCHECK(result == QpackDecodedHeadersAccumulator::Status::kSuccess);
-
- ProcessDecodedHeaders(qpack_decoded_headers_accumulator_->quic_header_list());
return !sequencer()->IsClosed() && !reading_stopped();
}
@@ -999,24 +1016,6 @@ bool QuicSpdyStream::OnUnknownFrameEnd() {
return true;
}
-void QuicSpdyStream::ProcessDecodedHeaders(const QuicHeaderList& headers) {
- QuicSpdySession::LogHeaderCompressionRatioHistogram(
- /* using_qpack = */ true,
- /* is_sent = */ false, headers.compressed_header_bytes(),
- headers.uncompressed_header_bytes());
-
- if (spdy_session_->promised_stream_id() ==
- QuicUtils::GetInvalidStreamId(session()->transport_version())) {
- const QuicByteCount frame_length = headers_decompressed_
- ? trailers_payload_length_
- : headers_payload_length_;
- OnStreamHeaderList(/* fin = */ false, frame_length, headers);
- } else {
- spdy_session_->OnHeaderList(headers);
- }
- qpack_decoded_headers_accumulator_.reset();
-}
-
size_t QuicSpdyStream::WriteHeadersImpl(
spdy::SpdyHeaderBlock header_block,
bool fin,
@@ -1044,8 +1043,8 @@ size_t QuicSpdyStream::WriteHeadersImpl(
// Write HEADERS frame.
std::unique_ptr<char[]> headers_frame_header;
const size_t headers_frame_header_length =
- encoder_.SerializeHeadersFrameHeader(encoded_headers.size(),
- &headers_frame_header);
+ HttpEncoder::SerializeHeadersFrameHeader(encoded_headers.size(),
+ &headers_frame_header);
unacked_frame_headers_offsets_.Add(
send_buffer().stream_offset(),
send_buffer().stream_offset() + headers_frame_header_length);
@@ -1059,7 +1058,7 @@ size_t QuicSpdyStream::WriteHeadersImpl(
QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
<< " is writing HEADERS frame payload of length "
- << encoded_headers.length();
+ << encoded_headers.length() << " with fin " << fin;
WriteOrBufferData(encoded_headers, fin, nullptr);
QuicSpdySession::LogHeaderCompressionRatioHistogram(
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 6da102bd56c..8610dbb1f2d 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
@@ -102,6 +102,8 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
// QUIC_STREAM_NO_ERROR.
void OnStreamReset(const QuicRstStreamFrame& frame) override;
+ void Reset(QuicRstStreamErrorCode error) override;
+
// Called by the sequencer when new data is available. Decodes the data and
// calls OnBodyAvailable() to pass to the upper layer.
void OnDataAvailable() override;
@@ -211,11 +213,9 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
// will be available.
bool IsClosed() { return sequencer()->IsClosed(); }
- using QuicStream::CloseWriteSide;
-
// QpackDecodedHeadersAccumulator::Visitor implementation.
void OnHeadersDecoded(QuicHeaderList headers) override;
- void OnHeaderDecodingError() override;
+ void OnHeaderDecodingError(QuicStringPiece error_message) override;
protected:
// Called when the received headers are too large. By default this will
@@ -267,9 +267,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
bool OnUnknownFramePayload(QuicStringPiece payload);
bool OnUnknownFrameEnd();
- // Called internally when headers are decoded.
- void ProcessDecodedHeaders(const QuicHeaderList& headers);
-
// Given the interval marked by [|offset|, |offset| + |data_length|), return
// the number of frame header bytes contained in it.
QuicByteCount GetNumFrameHeadersInInterval(QuicStreamOffset offset,
@@ -286,6 +283,9 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
bool blocked_on_decoding_headers_;
// True if the headers have been completely decompressed.
bool headers_decompressed_;
+ // True if uncompressed headers or trailers exceed maximum allowed size
+ // advertised to peer via SETTINGS_MAX_HEADER_LIST_SIZE.
+ bool header_list_size_limit_exceeded_;
// Contains a copy of the decompressed header (name, value) pairs until they
// are consumed via Readv.
QuicHeaderList header_list_;
@@ -305,8 +305,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
// The parsed trailers received from the peer.
spdy::SpdyHeaderBlock received_trailers_;
- // Http encoder for writing streams.
- HttpEncoder encoder_;
// Headers accumulator for decoding HEADERS frame payload.
std::unique_ptr<QpackDecodedHeadersAccumulator>
qpack_decoded_headers_accumulator_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.h
index 6b2dd62b02d..1942c261188 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager.h
@@ -77,7 +77,7 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStreamBodyManager {
// A Fragment instance represents a body fragment with a count of bytes
// received afterwards but before the next body fragment that can be marked
// consumed as soon as all of the body fragment is read.
- struct Fragment {
+ struct QUIC_EXPORT_PRIVATE Fragment {
// |body| must not be empty.
QuicStringPiece body;
// Might be zero.
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager_test.cc
index 3a5b720d277..10b19f1d668 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_manager_test.cc
@@ -50,29 +50,29 @@ TEST_F(QuicSpdyStreamBodyManagerTest, ConsumeMoreThanAvailable) {
EXPECT_EQ(0u, bytes_to_consume);
}
-struct {
- std::vector<QuicByteCount> frame_header_lengths;
- std::vector<const char*> frame_payloads;
- std::vector<QuicByteCount> body_bytes_to_read;
- std::vector<QuicByteCount> expected_return_values;
-} const kOnBodyConsumedTestData[] = {
- // One frame consumed in one call.
- {{2}, {"foobar"}, {6}, {6}},
- // Two frames consumed in one call.
- {{3, 5}, {"foobar", "baz"}, {9}, {14}},
- // One frame consumed in two calls.
- {{2}, {"foobar"}, {4, 2}, {4, 2}},
- // Two frames consumed in two calls matching frame boundaries.
- {{3, 5}, {"foobar", "baz"}, {6, 3}, {11, 3}},
- // Two frames consumed in two calls,
- // the first call only consuming part of the first frame.
- {{3, 5}, {"foobar", "baz"}, {5, 4}, {5, 9}},
- // Two frames consumed in two calls,
- // the first call consuming the entire first frame and part of the second.
- {{3, 5}, {"foobar", "baz"}, {7, 2}, {12, 2}},
-};
-
TEST_F(QuicSpdyStreamBodyManagerTest, OnBodyConsumed) {
+ struct {
+ std::vector<QuicByteCount> frame_header_lengths;
+ std::vector<const char*> frame_payloads;
+ std::vector<QuicByteCount> body_bytes_to_read;
+ std::vector<QuicByteCount> expected_return_values;
+ } const kOnBodyConsumedTestData[] = {
+ // One frame consumed in one call.
+ {{2}, {"foobar"}, {6}, {6}},
+ // Two frames consumed in one call.
+ {{3, 5}, {"foobar", "baz"}, {9}, {14}},
+ // One frame consumed in two calls.
+ {{2}, {"foobar"}, {4, 2}, {4, 2}},
+ // Two frames consumed in two calls matching frame boundaries.
+ {{3, 5}, {"foobar", "baz"}, {6, 3}, {11, 3}},
+ // Two frames consumed in two calls,
+ // the first call only consuming part of the first frame.
+ {{3, 5}, {"foobar", "baz"}, {5, 4}, {5, 9}},
+ // Two frames consumed in two calls,
+ // the first call consuming the entire first frame and part of the second.
+ {{3, 5}, {"foobar", "baz"}, {7, 2}, {12, 2}},
+ };
+
for (size_t test_case_index = 0;
test_case_index < QUIC_ARRAYSIZE(kOnBodyConsumedTestData);
++test_case_index) {
@@ -105,26 +105,26 @@ TEST_F(QuicSpdyStreamBodyManagerTest, OnBodyConsumed) {
}
}
-struct {
- std::vector<QuicByteCount> frame_header_lengths;
- std::vector<const char*> frame_payloads;
- size_t iov_len;
-} const kPeekBodyTestData[] = {
- // No frames, more iovecs than frames.
- {{}, {}, 1},
- // One frame, same number of iovecs.
- {{3}, {"foobar"}, 1},
- // One frame, more iovecs than frames.
- {{3}, {"foobar"}, 2},
- // Two frames, fewer iovecs than frames.
- {{3, 5}, {"foobar", "baz"}, 1},
- // Two frames, same number of iovecs.
- {{3, 5}, {"foobar", "baz"}, 2},
- // Two frames, more iovecs than frames.
- {{3, 5}, {"foobar", "baz"}, 3},
-};
-
TEST_F(QuicSpdyStreamBodyManagerTest, PeekBody) {
+ struct {
+ std::vector<QuicByteCount> frame_header_lengths;
+ std::vector<const char*> frame_payloads;
+ size_t iov_len;
+ } const kPeekBodyTestData[] = {
+ // No frames, more iovecs than frames.
+ {{}, {}, 1},
+ // One frame, same number of iovecs.
+ {{3}, {"foobar"}, 1},
+ // One frame, more iovecs than frames.
+ {{3}, {"foobar"}, 2},
+ // Two frames, fewer iovecs than frames.
+ {{3, 5}, {"foobar", "baz"}, 1},
+ // Two frames, same number of iovecs.
+ {{3, 5}, {"foobar", "baz"}, 2},
+ // Two frames, more iovecs than frames.
+ {{3, 5}, {"foobar", "baz"}, 3},
+ };
+
for (size_t test_case_index = 0;
test_case_index < QUIC_ARRAYSIZE(kPeekBodyTestData); ++test_case_index) {
const std::vector<QuicByteCount>& frame_header_lengths =
@@ -159,62 +159,65 @@ TEST_F(QuicSpdyStreamBodyManagerTest, PeekBody) {
}
}
-struct {
- std::vector<QuicByteCount> frame_header_lengths;
- std::vector<const char*> frame_payloads;
- std::vector<std::vector<QuicByteCount>> iov_lengths;
- std::vector<QuicByteCount> expected_total_bytes_read;
- std::vector<QuicByteCount> expected_return_values;
-} const kReadBodyTestData[] = {
- // One frame, one read with smaller iovec.
- {{4}, {"foo"}, {{2}}, {2}, {2}},
- // One frame, one read with same size iovec.
- {{4}, {"foo"}, {{3}}, {3}, {3}},
- // One frame, one read with larger iovec.
- {{4}, {"foo"}, {{5}}, {3}, {3}},
- // One frame, one read with two iovecs, smaller total size.
- {{4}, {"foobar"}, {{2, 3}}, {5}, {5}},
- // One frame, one read with two iovecs, same total size.
- {{4}, {"foobar"}, {{2, 4}}, {6}, {6}},
- // One frame, one read with two iovecs, larger total size in last iovec.
- {{4}, {"foobar"}, {{2, 6}}, {6}, {6}},
- // One frame, one read with extra iovecs, body ends at iovec boundary.
- {{4}, {"foobar"}, {{2, 4, 4, 3}}, {6}, {6}},
- // One frame, one read with extra iovecs, body ends not at iovec boundary.
- {{4}, {"foobar"}, {{2, 7, 4, 3}}, {6}, {6}},
- // One frame, two reads with two iovecs each, smaller total size.
- {{4}, {"foobarbaz"}, {{2, 1}, {3, 2}}, {3, 5}, {3, 5}},
- // One frame, two reads with two iovecs each, same total size.
- {{4}, {"foobarbaz"}, {{2, 1}, {4, 2}}, {3, 6}, {3, 6}},
- // One frame, two reads with two iovecs each, larger total size.
- {{4}, {"foobarbaz"}, {{2, 1}, {4, 10}}, {3, 6}, {3, 6}},
- // Two frames, one read with smaller iovec.
- {{4, 3}, {"foobar", "baz"}, {{8}}, {8}, {11}},
- // Two frames, one read with same size iovec.
- {{4, 3}, {"foobar", "baz"}, {{9}}, {9}, {12}},
- // Two frames, one read with larger iovec.
- {{4, 3}, {"foobar", "baz"}, {{10}}, {9}, {12}},
- // Two frames, one read with two iovecs, smaller total size.
- {{4, 3}, {"foobar", "baz"}, {{4, 3}}, {7}, {10}},
- // Two frames, one read with two iovecs, same total size.
- {{4, 3}, {"foobar", "baz"}, {{4, 5}}, {9}, {12}},
- // Two frames, one read with two iovecs, larger total size in last iovec.
- {{4, 3}, {"foobar", "baz"}, {{4, 6}}, {9}, {12}},
- // Two frames, one read with extra iovecs, body ends at iovec boundary.
- {{4, 3}, {"foobar", "baz"}, {{4, 6, 4, 3}}, {9}, {12}},
- // Two frames, one read with extra iovecs, body ends not at iovec boundary.
- {{4, 3}, {"foobar", "baz"}, {{4, 7, 4, 3}}, {9}, {12}},
- // Two frames, two reads with two iovecs each, reads end on frame boundary.
- {{4, 3}, {"foobar", "baz"}, {{2, 4}, {2, 1}}, {6, 3}, {9, 3}},
- // Three frames, three reads, extra iovecs, no iovec ends on frame boundary.
- {{4, 3, 6},
- {"foobar", "bazquux", "qux"},
- {{4, 3}, {2, 3}, {5, 3}},
- {7, 5, 4},
- {10, 5, 10}},
-};
-
TEST_F(QuicSpdyStreamBodyManagerTest, ReadBody) {
+ struct {
+ std::vector<QuicByteCount> frame_header_lengths;
+ std::vector<const char*> frame_payloads;
+ std::vector<std::vector<QuicByteCount>> iov_lengths;
+ std::vector<QuicByteCount> expected_total_bytes_read;
+ std::vector<QuicByteCount> expected_return_values;
+ } const kReadBodyTestData[] = {
+ // One frame, one read with smaller iovec.
+ {{4}, {"foo"}, {{2}}, {2}, {2}},
+ // One frame, one read with same size iovec.
+ {{4}, {"foo"}, {{3}}, {3}, {3}},
+ // One frame, one read with larger iovec.
+ {{4}, {"foo"}, {{5}}, {3}, {3}},
+ // One frame, one read with two iovecs, smaller total size.
+ {{4}, {"foobar"}, {{2, 3}}, {5}, {5}},
+ // One frame, one read with two iovecs, same total size.
+ {{4}, {"foobar"}, {{2, 4}}, {6}, {6}},
+ // One frame, one read with two iovecs, larger total size in last iovec.
+ {{4}, {"foobar"}, {{2, 6}}, {6}, {6}},
+ // One frame, one read with extra iovecs, body ends at iovec boundary.
+ {{4}, {"foobar"}, {{2, 4, 4, 3}}, {6}, {6}},
+ // One frame, one read with extra iovecs, body ends not at iovec boundary.
+ {{4}, {"foobar"}, {{2, 7, 4, 3}}, {6}, {6}},
+ // One frame, two reads with two iovecs each, smaller total size.
+ {{4}, {"foobarbaz"}, {{2, 1}, {3, 2}}, {3, 5}, {3, 5}},
+ // One frame, two reads with two iovecs each, same total size.
+ {{4}, {"foobarbaz"}, {{2, 1}, {4, 2}}, {3, 6}, {3, 6}},
+ // One frame, two reads with two iovecs each, larger total size.
+ {{4}, {"foobarbaz"}, {{2, 1}, {4, 10}}, {3, 6}, {3, 6}},
+ // Two frames, one read with smaller iovec.
+ {{4, 3}, {"foobar", "baz"}, {{8}}, {8}, {11}},
+ // Two frames, one read with same size iovec.
+ {{4, 3}, {"foobar", "baz"}, {{9}}, {9}, {12}},
+ // Two frames, one read with larger iovec.
+ {{4, 3}, {"foobar", "baz"}, {{10}}, {9}, {12}},
+ // Two frames, one read with two iovecs, smaller total size.
+ {{4, 3}, {"foobar", "baz"}, {{4, 3}}, {7}, {10}},
+ // Two frames, one read with two iovecs, same total size.
+ {{4, 3}, {"foobar", "baz"}, {{4, 5}}, {9}, {12}},
+ // Two frames, one read with two iovecs, larger total size in last iovec.
+ {{4, 3}, {"foobar", "baz"}, {{4, 6}}, {9}, {12}},
+ // Two frames, one read with extra iovecs, body ends at iovec boundary.
+ {{4, 3}, {"foobar", "baz"}, {{4, 6, 4, 3}}, {9}, {12}},
+ // Two frames, one read with extra iovecs, body ends not at iovec
+ // boundary.
+ {{4, 3}, {"foobar", "baz"}, {{4, 7, 4, 3}}, {9}, {12}},
+ // Two frames, two reads with two iovecs each, reads end on frame
+ // boundary.
+ {{4, 3}, {"foobar", "baz"}, {{2, 4}, {2, 1}}, {6, 3}, {9, 3}},
+ // Three frames, three reads, extra iovecs, no iovec ends on frame
+ // boundary.
+ {{4, 3, 6},
+ {"foobar", "bazquux", "qux"},
+ {{4, 3}, {2, 3}, {5, 3}},
+ {7, 5, 4},
+ {10, 5, 10}},
+ };
+
for (size_t test_case_index = 0;
test_case_index < QUIC_ARRAYSIZE(kReadBodyTestData); ++test_case_index) {
const std::vector<QuicByteCount>& frame_header_lengths =
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 c545265dd77..62ef3b5015a 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
@@ -22,6 +22,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_flow_controller_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
@@ -231,21 +232,31 @@ class QuicSpdyStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
auto send_control_stream =
QuicSpdySessionPeer::GetSendControlStream(session_.get());
// The control stream will write 3 times, including stream type, settings
- // frame, priority for headers.
+ // frame and max push id, priority for headers.
+ int num_control_stream_writes = 2;
+ if (session_->perspective() == Perspective::IS_CLIENT) {
+ // The control stream also writes the max push id frame.
+ num_control_stream_writes++;
+ }
EXPECT_CALL(*session_, WritevData(send_control_stream,
send_control_stream->id(), _, _, _))
- .Times(2);
- auto qpack_encoder_stream =
- QuicSpdySessionPeer::GetQpackEncoderSendStream(session_.get());
- EXPECT_CALL(*session_, WritevData(qpack_encoder_stream,
- qpack_encoder_stream->id(), 1, 0, _));
+ .Times(num_control_stream_writes);
auto qpack_decoder_stream =
QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
EXPECT_CALL(*session_, WritevData(qpack_decoder_stream,
qpack_decoder_stream->id(), 1, 0, _));
+ auto qpack_encoder_stream =
+ QuicSpdySessionPeer::GetQpackEncoderSendStream(session_.get());
+ EXPECT_CALL(*session_, WritevData(qpack_encoder_stream,
+ qpack_encoder_stream->id(), 1, 0, _));
+ }
+ if (session_->use_handshake_delegate()) {
+ static_cast<QuicSession*>(session_.get())
+ ->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ } else {
+ static_cast<QuicSession*>(session_.get())
+ ->OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_ESTABLISHED);
}
- static_cast<QuicSession*>(session_.get())
- ->OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_ESTABLISHED);
}
QuicHeaderList ProcessHeaders(bool fin, const SpdyHeaderBlock& headers) {
@@ -280,7 +291,8 @@ class QuicSpdyStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
std::string HeadersFrame(QuicStringPiece payload) {
std::unique_ptr<char[]> headers_buffer;
QuicByteCount headers_frame_header_length =
- encoder_.SerializeHeadersFrameHeader(payload.length(), &headers_buffer);
+ HttpEncoder::SerializeHeadersFrameHeader(payload.length(),
+ &headers_buffer);
QuicStringPiece headers_frame_header(headers_buffer.get(),
headers_frame_header_length);
return QuicStrCat(headers_frame_header, payload);
@@ -289,7 +301,7 @@ class QuicSpdyStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
std::string DataFrame(QuicStringPiece payload) {
std::unique_ptr<char[]> data_buffer;
QuicByteCount data_frame_header_length =
- encoder_.SerializeDataFrameHeader(payload.length(), &data_buffer);
+ HttpEncoder::SerializeDataFrameHeader(payload.length(), &data_buffer);
QuicStringPiece data_frame_header(data_buffer.get(),
data_frame_header_length);
return QuicStrCat(data_frame_header, payload);
@@ -323,8 +335,6 @@ class QuicSpdyStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
TestStream* stream2_;
SpdyHeaderBlock headers_;
-
- HttpEncoder encoder_;
};
INSTANTIATE_TEST_SUITE_P(Tests,
@@ -346,29 +356,36 @@ TEST_P(QuicSpdyStreamTest, ProcessHeaderList) {
TEST_P(QuicSpdyStreamTest, ProcessTooLargeHeaderList) {
Initialize(kShouldProcessData);
- QuicHeaderList headers;
- stream_->OnStreamHeadersPriority(
- spdy::SpdyStreamPrecedence(kV3HighestPriority));
-
- const bool version_uses_qpack =
- VersionUsesHttp3(GetParam().transport_version);
+ if (!UsesHttp3()) {
+ QuicHeaderList headers;
+ stream_->OnStreamHeadersPriority(
+ spdy::SpdyStreamPrecedence(kV3HighestPriority));
- if (version_uses_qpack) {
- EXPECT_CALL(
- *connection_,
- CloseConnection(
- QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE,
- MatchesRegex("Too large headers received on stream \\d+"), _));
- } else {
EXPECT_CALL(*session_,
SendRstStream(stream_->id(), QUIC_HEADERS_TOO_LARGE, 0));
- }
+ stream_->OnStreamHeaderList(false, 1 << 20, headers);
- stream_->OnStreamHeaderList(false, 1 << 20, headers);
+ EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_HEADERS_TOO_LARGE));
- if (!version_uses_qpack) {
- EXPECT_EQ(QUIC_HEADERS_TOO_LARGE, stream_->stream_error());
+ return;
}
+
+ // Header list size includes 32 bytes for overhead per header field.
+ 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);
+
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE,
+ MatchesRegex("Too large headers received on stream \\d+"),
+ _));
+
+ stream_->OnStreamFrame(frame);
+
+ EXPECT_TRUE(stream_->header_list().empty());
}
TEST_P(QuicSpdyStreamTest, ProcessHeaderListWithFin) {
@@ -386,7 +403,7 @@ TEST_P(QuicSpdyStreamTest, ProcessHeaderListWithFin) {
EXPECT_EQ("", stream_->data());
EXPECT_FALSE(stream_->header_list().empty());
EXPECT_FALSE(stream_->IsDoneReading());
- EXPECT_TRUE(stream_->HasFinalReceivedByteOffset());
+ EXPECT_TRUE(stream_->HasReceivedFinalOffset());
}
// A valid status code should be 3-digit integer. The first digit should be in
@@ -469,7 +486,8 @@ TEST_P(QuicSpdyStreamTest, ProcessWrongFramesOnSpdyStream) {
GoAwayFrame goaway;
goaway.stream_id = 0x1;
std::unique_ptr<char[]> buffer;
- QuicByteCount header_length = encoder_.SerializeGoAwayFrame(goaway, &buffer);
+ QuicByteCount header_length =
+ HttpEncoder::SerializeGoAwayFrame(goaway, &buffer);
std::string data = std::string(buffer.get(), header_length);
EXPECT_EQ("", stream_->data());
@@ -763,7 +781,8 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlNoWindowUpdateIfNotConsumed) {
if (UsesHttp3()) {
std::unique_ptr<char[]> buffer;
- header_length = encoder_.SerializeDataFrameHeader(body.length(), &buffer);
+ header_length =
+ HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
std::string header = std::string(buffer.get(), header_length);
data = header + body;
} else {
@@ -812,7 +831,8 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlWindowUpdate) {
if (UsesHttp3()) {
std::unique_ptr<char[]> buffer;
- header_length = encoder_.SerializeDataFrameHeader(body.length(), &buffer);
+ header_length =
+ HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
std::string header = std::string(buffer.get(), header_length);
data = header + body;
} else {
@@ -882,12 +902,13 @@ TEST_P(QuicSpdyStreamTest, ConnectionFlowControlWindowUpdate) {
if (UsesHttp3()) {
body = std::string(kWindow / 4 - 2, 'a');
std::unique_ptr<char[]> buffer;
- header_length = encoder_.SerializeDataFrameHeader(body.length(), &buffer);
+ header_length =
+ HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
std::string header = std::string(buffer.get(), header_length);
data = header + body;
std::unique_ptr<char[]> buffer2;
QuicByteCount header_length2 =
- encoder_.SerializeDataFrameHeader(body2.length(), &buffer2);
+ HttpEncoder::SerializeDataFrameHeader(body2.length(), &buffer2);
std::string header2 = std::string(buffer2.get(), header_length2);
data2 = header2 + body2;
} else {
@@ -1023,7 +1044,7 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersViaHeaderList) {
trailers_block["key2"] = "value2";
trailers_block["key3"] = "value3";
SpdyHeaderBlock trailers_block_with_final_offset = trailers_block.Clone();
- if (!VersionUsesHttp3(GetParam().transport_version)) {
+ if (!UsesHttp3()) {
// :final-offset pseudo-header is only added if trailers are sent
// on the headers stream.
trailers_block_with_final_offset[kFinalOffsetHeaderKey] = "0";
@@ -1051,7 +1072,7 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersViaHeaderList) {
TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithOffset) {
// kFinalOffsetHeaderKey is not used when HEADERS are sent on the
// request/response stream.
- if (VersionUsesHttp3(GetParam().transport_version)) {
+ if (UsesHttp3()) {
return;
}
@@ -1098,7 +1119,7 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithOffset) {
TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutOffset) {
// kFinalOffsetHeaderKey is not used when HEADERS are sent on the
// request/response stream.
- if (VersionUsesHttp3(GetParam().transport_version)) {
+ if (UsesHttp3()) {
return;
}
@@ -1130,7 +1151,7 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutOffset) {
TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutFin) {
// In IETF QUIC, there is no such thing as FIN flag on HTTP/3 frames like the
// HEADERS frame.
- if (VersionUsesHttp3(GetParam().transport_version)) {
+ if (UsesHttp3()) {
return;
}
@@ -1161,7 +1182,7 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterHeadersWithFin) {
// If HEADERS frames are sent on the request/response stream, then the
// sequencer will signal an error if any stream data arrives after a FIN,
// so QuicSpdyStream does not need to.
- if (VersionUsesHttp3(GetParam().transport_version)) {
+ if (UsesHttp3()) {
return;
}
@@ -1183,7 +1204,7 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterBodyWithFin) {
// If HEADERS frames are sent on the request/response stream,
// then the sequencer will block them from reaching QuicSpdyStream
// after the stream is closed.
- if (VersionUsesHttp3(GetParam().transport_version)) {
+ if (UsesHttp3()) {
return;
}
@@ -1233,7 +1254,7 @@ TEST_P(QuicSpdyStreamTest, ClosingStreamWithNoTrailers) {
TEST_P(QuicSpdyStreamTest, WritingTrailersSendsAFin) {
Initialize(kShouldProcessData);
- if (VersionUsesHttp3(GetParam().transport_version)) {
+ if (UsesHttp3()) {
// In this case, TestStream::WriteHeadersImpl() does not prevent writes.
EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _))
.Times(AtLeast(1));
@@ -1253,9 +1274,10 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersSendsAFin) {
TEST_P(QuicSpdyStreamTest, ClientWritesPriority) {
SetQuicFlag(FLAGS_quic_allow_http3_priority, true);
+ SetQuicReloadableFlag(quic_send_max_push_id_with_settings, true);
InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
- if (VersionUsesHttp3(GetParam().transport_version)) {
+ if (UsesHttp3()) {
// In this case, TestStream::WriteHeadersImpl() does not prevent writes.
// Six writes include priority for headers, headers frame header, headers
// frame, priority of trailers, trailing headers frame header, and trailers.
@@ -1263,7 +1285,8 @@ TEST_P(QuicSpdyStreamTest, ClientWritesPriority) {
.Times(4);
auto send_control_stream =
QuicSpdySessionPeer::GetSendControlStream(session_.get());
- // The control stream will write priority for headers.
+ // The control stream will write priority for headers as well as
+ // the settings/max_push_id.
EXPECT_CALL(*session_, WritevData(send_control_stream,
send_control_stream->id(), _, _, _))
.Times(1);
@@ -1286,7 +1309,7 @@ TEST_P(QuicSpdyStreamTest, ClientWritesPriority) {
TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {
Initialize(kShouldProcessData);
- if (VersionUsesHttp3(GetParam().transport_version)) {
+ if (UsesHttp3()) {
// In this case, TestStream::WriteHeadersImpl() does not prevent writes.
EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _))
.Times(AtLeast(1));
@@ -1302,7 +1325,7 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {
QuicByteCount header_length = 0;
if (UsesHttp3()) {
std::unique_ptr<char[]> buf;
- header_length = encoder_.SerializeDataFrameHeader(body.length(), &buf);
+ header_length = HttpEncoder::SerializeDataFrameHeader(body.length(), &buf);
}
stream_->WriteOrBufferBody(body, false);
@@ -1315,7 +1338,7 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {
SpdyHeaderBlock expected_trailers(trailers.Clone());
// :final-offset pseudo-header is only added if trailers are sent
// on the headers stream.
- if (!VersionUsesHttp3(GetParam().transport_version)) {
+ if (!UsesHttp3()) {
expected_trailers[kFinalOffsetHeaderKey] =
QuicTextUtils::Uint64ToString(body.length() + header_length);
}
@@ -1357,7 +1380,7 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersWithQueuedBytes) {
// This test exercises sending trailers on the headers stream while data is
// still queued on the response/request stream. In IETF QUIC, data and
// trailers are sent on the same stream, so this test does not apply.
- if (VersionUsesHttp3(GetParam().transport_version)) {
+ if (UsesHttp3()) {
return;
}
@@ -1416,7 +1439,7 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersAfterFIN) {
TEST_P(QuicSpdyStreamTest, HeaderStreamNotiferCorrespondingSpdyStream) {
// There is no headers stream if QPACK is used.
- if (VersionUsesHttp3(GetParam().transport_version)) {
+ if (UsesHttp3()) {
return;
}
@@ -1652,10 +1675,11 @@ TEST_P(QuicSpdyStreamTest, HeadersAckNotReportedWriteOrBufferBody) {
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
- encoder_.SerializeDataFrameHeader(body.length(), &buffer);
+ HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
std::string header = std::string(buffer.get(), header_length);
- header_length = encoder_.SerializeDataFrameHeader(body2.length(), &buffer);
+ header_length =
+ HttpEncoder::SerializeDataFrameHeader(body2.length(), &buffer);
std::string header2 = std::string(buffer.get(), header_length);
EXPECT_CALL(*mock_ack_listener, OnPacketAcked(body.length(), _));
@@ -1748,7 +1772,7 @@ TEST_P(QuicSpdyStreamTest, HeaderBytesNotReportedOnRetransmission) {
}
TEST_P(QuicSpdyStreamTest, HeadersFrameOnRequestStream) {
- if (!VersionUsesHttp3(GetParam().transport_version)) {
+ if (!UsesHttp3()) {
return;
}
@@ -1776,7 +1800,7 @@ TEST_P(QuicSpdyStreamTest, HeadersFrameOnRequestStream) {
}
TEST_P(QuicSpdyStreamTest, ProcessBodyAfterTrailers) {
- if (!VersionUsesHttp3(GetParam().transport_version)) {
+ if (!UsesHttp3()) {
return;
}
@@ -1820,7 +1844,7 @@ TEST_P(QuicSpdyStreamTest, ProcessBodyAfterTrailers) {
// normal body. Make sure the http decoder stops processing body after the
// connection shuts down.
TEST_P(QuicSpdyStreamTest, MalformedHeadersStopHttpDecoder) {
- if (!VersionUsesHttp3(GetParam().transport_version)) {
+ if (!UsesHttp3()) {
return;
}
@@ -1839,11 +1863,10 @@ TEST_P(QuicSpdyStreamTest, MalformedHeadersStopHttpDecoder) {
EXPECT_CALL(
*connection_,
- CloseConnection(
- QUIC_DECOMPRESSION_FAILURE,
- MatchesRegex("Error decompressing header block on stream \\d+: "
- "Incomplete header block."),
- _))
+ CloseConnection(QUIC_QPACK_DECOMPRESSION_FAILED,
+ MatchesRegex("Error decoding headers on stream \\d+: "
+ "Incomplete header block."),
+ _))
.WillOnce(
(Invoke([this](QuicErrorCode error, const std::string& error_details,
ConnectionCloseBehavior connection_close_behavior) {
@@ -1861,8 +1884,50 @@ TEST_P(QuicSpdyStreamTest, MalformedHeadersStopHttpDecoder) {
stream_->OnStreamFrame(frame);
}
+// Regression test for https://crbug.com/1027895: a HEADERS frame triggers an
+// error in QuicSpdyStream::OnHeadersFramePayload(). This closes the
+// connection, freeing the buffer of QuicStreamSequencer. Therefore
+// QuicStreamSequencer::MarkConsumed() must not be called from
+// QuicSpdyStream::OnHeadersFramePayload().
+TEST_P(QuicSpdyStreamTest, DoNotMarkConsumedAfterQpackDecodingError) {
+ if (!UsesHttp3()) {
+ return;
+ }
+
+ Initialize(kShouldProcessData);
+ connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
+
+ testing::InSequence s;
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_QPACK_DECOMPRESSION_FAILED,
+ MatchesRegex("Error decoding headers on stream \\d+: "
+ "Invalid relative index."),
+ _))
+ .WillOnce(
+ (Invoke([this](QuicErrorCode error, const std::string& error_details,
+ ConnectionCloseBehavior connection_close_behavior) {
+ connection_->ReallyCloseConnection(error, error_details,
+ connection_close_behavior);
+ })));
+ EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _));
+ EXPECT_CALL(*session_, OnConnectionClosed(_, _))
+ .WillOnce(Invoke([this](const QuicConnectionCloseFrame& frame,
+ ConnectionCloseSource source) {
+ session_->ReallyOnConnectionClosed(frame, source);
+ }));
+ EXPECT_CALL(*session_, SendRstStream(stream_->id(), _, _));
+ EXPECT_CALL(*session_, SendRstStream(stream2_->id(), _, _));
+
+ // Invalid headers: Required Insert Count is zero, but the header block
+ // contains a dynamic table reference.
+ std::string headers = HeadersFrame(QuicTextUtils::HexDecode("000080"));
+ QuicStreamFrame frame(stream_->id(), false, 0, headers);
+ stream_->OnStreamFrame(frame);
+}
+
TEST_P(QuicSpdyStreamTest, ImmediateHeaderDecodingWithDynamicTableEntries) {
- if (!VersionUsesHttp3(GetParam().transport_version)) {
+ if (!UsesHttp3()) {
return;
}
@@ -1917,7 +1982,7 @@ TEST_P(QuicSpdyStreamTest, ImmediateHeaderDecodingWithDynamicTableEntries) {
}
TEST_P(QuicSpdyStreamTest, BlockedHeaderDecoding) {
- if (!VersionUsesHttp3(GetParam().transport_version)) {
+ if (!UsesHttp3()) {
return;
}
@@ -1974,7 +2039,7 @@ TEST_P(QuicSpdyStreamTest, BlockedHeaderDecoding) {
}
TEST_P(QuicSpdyStreamTest, AsyncErrorDecodingHeaders) {
- if (!VersionUsesHttp3(GetParam().transport_version)) {
+ if (!UsesHttp3()) {
return;
}
@@ -1993,11 +2058,10 @@ TEST_P(QuicSpdyStreamTest, AsyncErrorDecodingHeaders) {
EXPECT_CALL(
*connection_,
- CloseConnection(
- QUIC_DECOMPRESSION_FAILURE,
- MatchesRegex("Error during async decoding of headers on stream \\d+: "
- "Required Insert Count too large."),
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
+ CloseConnection(QUIC_QPACK_DECOMPRESSION_FAILED,
+ MatchesRegex("Error decoding headers on stream \\d+: "
+ "Required Insert Count too large."),
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
// Deliver two dynamic table entries to decoder
// to trigger decoding of header block.
@@ -2005,8 +2069,37 @@ TEST_P(QuicSpdyStreamTest, AsyncErrorDecodingHeaders) {
session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
}
+// Regression test for https://crbug.com/1024263 and for
+// https://crbug.com/1025209#c11.
+TEST_P(QuicSpdyStreamTest, BlockedHeaderDecodingUnblockedWithBufferedError) {
+ if (!UsesHttp3()) {
+ return;
+ }
+
+ Initialize(kShouldProcessData);
+ session_->qpack_decoder()->OnSetDynamicTableCapacity(1024);
+
+ // Relative index 2 is invalid because it is larger than or equal to the Base.
+ std::string headers = HeadersFrame(QuicTextUtils::HexDecode("020082"));
+ stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers));
+
+ // Decoding is blocked.
+ EXPECT_FALSE(stream_->headers_decompressed());
+
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_QPACK_DECOMPRESSION_FAILED,
+ MatchesRegex("Error decoding headers on stream \\d+: "
+ "Invalid relative index."),
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
+
+ // Deliver one dynamic table entry to decoder
+ // to trigger decoding of header block.
+ session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar");
+}
+
TEST_P(QuicSpdyStreamTest, AsyncErrorDecodingTrailers) {
- if (!VersionUsesHttp3(GetParam().transport_version)) {
+ if (!UsesHttp3()) {
return;
}
@@ -2053,13 +2146,12 @@ TEST_P(QuicSpdyStreamTest, AsyncErrorDecodingTrailers) {
// Insert Count value advertised in the header block prefix.
EXPECT_FALSE(stream_->trailers_decompressed());
- EXPECT_CALL(*connection_,
- CloseConnection(
- QUIC_DECOMPRESSION_FAILURE,
- MatchesRegex(
- "Error during async decoding of trailers on stream \\d+: "
- "Required Insert Count too large."),
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_QPACK_DECOMPRESSION_FAILED,
+ MatchesRegex("Error decoding trailers on stream \\d+: "
+ "Required Insert Count too large."),
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
// Deliver second dynamic table entry to decoder
// to trigger decoding of trailing header block.
@@ -2116,7 +2208,7 @@ INSTANTIATE_TEST_SUITE_P(Tests,
// Test that stream bytes are consumed (by calling
// sequencer()->MarkConsumed()) incrementally, as soon as possible.
TEST_P(QuicSpdyStreamIncrementalConsumptionTest, OnlyKnownFrames) {
- if (!VersionUsesHttp3(GetParam().transport_version)) {
+ if (!UsesHttp3()) {
return;
}
@@ -2175,7 +2267,7 @@ TEST_P(QuicSpdyStreamIncrementalConsumptionTest, OnlyKnownFrames) {
}
TEST_P(QuicSpdyStreamIncrementalConsumptionTest, UnknownFramesInterleaved) {
- if (!VersionUsesHttp3(GetParam().transport_version)) {
+ if (!UsesHttp3()) {
return;
}
@@ -2268,9 +2360,8 @@ TEST_P(QuicSpdyStreamTest, PushPromiseOnDataStream) {
push_promise.push_id = 0x01;
push_promise.headers = headers;
std::unique_ptr<char[]> buffer;
- HttpEncoder encoder;
- uint64_t length =
- encoder.SerializePushPromiseFrameWithOnlyPushId(push_promise, &buffer);
+ uint64_t length = HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
+ push_promise, &buffer);
std::string data = std::string(buffer.get(), length) + headers;
QuicStreamFrame frame(stream_->id(), false, 0, data);
@@ -2282,7 +2373,7 @@ TEST_P(QuicSpdyStreamTest, PushPromiseOnDataStream) {
// Close connection if a DATA frame is received before a HEADERS frame.
TEST_P(QuicSpdyStreamTest, DataBeforeHeaders) {
- if (!VersionUsesHttp3(GetParam().transport_version)) {
+ if (!UsesHttp3()) {
return;
}
@@ -2304,7 +2395,7 @@ TEST_P(QuicSpdyStreamTest, DataBeforeHeaders) {
// Close connection if a HEADERS frame is received after the trailing HEADERS.
TEST_P(QuicSpdyStreamTest, TrailersAfterTrailers) {
- if (!VersionUsesHttp3(GetParam().transport_version)) {
+ if (!UsesHttp3()) {
return;
}
@@ -2357,7 +2448,7 @@ TEST_P(QuicSpdyStreamTest, TrailersAfterTrailers) {
// Regression test for https://crbug.com/978733.
// Close connection if a DATA frame is received after the trailing HEADERS.
TEST_P(QuicSpdyStreamTest, DataAfterTrailers) {
- if (!VersionUsesHttp3(GetParam().transport_version)) {
+ if (!UsesHttp3()) {
return;
}
@@ -2407,7 +2498,7 @@ TEST_P(QuicSpdyStreamTest, DataAfterTrailers) {
// SETTINGS frames are invalid on bidirectional streams. If one is received,
// the connection is closed. No more data should be processed.
TEST_P(QuicSpdyStreamTest, StopProcessingIfConnectionClosed) {
- if (!VersionUsesHttp3(GetParam().transport_version)) {
+ if (!UsesHttp3()) {
return;
}
@@ -2438,6 +2529,45 @@ TEST_P(QuicSpdyStreamTest, StopProcessingIfConnectionClosed) {
EXPECT_EQ(0u, stream_->sequencer()->NumBytesConsumed());
}
+// Stream Cancellation instruction is sent on QPACK decoder stream
+// when stream is reset.
+// TODO(b/145684124) Re-enable.
+TEST_P(QuicSpdyStreamTest, DISABLED_StreamCancellationWhenStreamReset) {
+ if (!UsesHttp3()) {
+ return;
+ }
+
+ Initialize(kShouldProcessData);
+
+ auto qpack_decoder_stream =
+ QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
+ EXPECT_CALL(*session_, WritevData(qpack_decoder_stream,
+ qpack_decoder_stream->id(), 1, 1, _));
+ EXPECT_CALL(*session_,
+ SendRstStream(stream_->id(), QUIC_STREAM_CANCELLED, 0));
+
+ stream_->Reset(QUIC_STREAM_CANCELLED);
+}
+
+// Stream Cancellation instruction is sent on QPACK decoder stream
+// when RESET_STREAM frame is received.
+// TODO(b/145684124) Re-enable.
+TEST_P(QuicSpdyStreamTest, DISABLED_StreamCancellationOnResetReceived) {
+ if (!UsesHttp3()) {
+ return;
+ }
+
+ Initialize(kShouldProcessData);
+
+ auto qpack_decoder_stream =
+ QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get());
+ EXPECT_CALL(*session_, WritevData(qpack_decoder_stream,
+ qpack_decoder_stream->id(), 1, 1, _));
+
+ stream_->OnStreamReset(QuicRstStreamFrame(
+ kInvalidControlFrameId, stream_->id(), QUIC_STREAM_CANCELLED, 0));
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils_test.cc
index 72d4a25ed13..0f6ec8a6287 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/spdy_server_push_utils_test.cc
@@ -13,8 +13,6 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
using spdy::SpdyHeaderBlock;
-using testing::Pair;
-using testing::UnorderedElementsAre;
namespace quic {
namespace test {
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 695ff7d91ec..470a58c1f11 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
@@ -35,7 +35,7 @@ namespace quic {
// Because of that, it is not a general-purpose container and should not be used
// as one.
template <typename T>
-class PacketNumberIndexedQueue {
+class QUIC_NO_EXPORT PacketNumberIndexedQueue {
public:
PacketNumberIndexedQueue() : number_of_present_entries_(0) {}
@@ -86,7 +86,7 @@ class PacketNumberIndexedQueue {
private:
// Wrapper around T used to mark whether the entry is actually in the map.
- struct EntryWrapper : T {
+ struct QUIC_NO_EXPORT EntryWrapper : T {
bool present;
EntryWrapper() : present(false) {}
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/offline/README.md b/chromium/net/third_party/quiche/src/quic/core/qpack/offline/README.md
deleted file mode 100644
index 4f6697c66b5..00000000000
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/offline/README.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# QPACK Offline Interop Testing tools
-
-See
-[QPACK Offline Interop](https://github.com/quicwg/base-drafts/wiki/QPACK-Offline-Interop)
-for description of test data format.
-
-Example usage:
-
-```shell
-$ # Download test data
-$ cd $TEST_DATA
-$ git clone https://github.com/qpackers/qifs.git
-$ TEST_ENCODED_DATA=`pwd`/qifs/encoded/qpack-03
-$ TEST_QIF_DATA=`pwd`/qifs/qifs
-$
-$ # Decode encoded test data in four files and verify that they match
-$ # the original headers in corresponding files
-$ $BIN/qpack_offline_decoder \
-> $TEST_ENCODED_DATA/f5/fb-req.qifencoded.4096.100.0 \
-> $TEST_QIF_DATA/fb-req.qif
-> $TEST_ENCODED_DATA/h2o/fb-req-hq.out.512.0.1 \
-> $TEST_QIF_DATA/fb-req-hq.qif
-> $TEST_ENCODED_DATA/ls-qpack/fb-resp-hq.out.0.0.0 \
-> $TEST_QIF_DATA/fb-resp-hq.qif
-> $TEST_ENCODED_DATA/proxygen/netbsd.qif.proxygen.out.4096.0.0 \
-> $TEST_QIF_DATA/netbsd.qif
-$
-```
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.cc
index ffec17280f6..3544f1ca10b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.cc
@@ -24,7 +24,7 @@ bool QpackBlockingManager::OnHeaderAcknowledgement(QuicStreamId stream_id) {
const uint64_t required_index_count = RequiredInsertCount(indices);
if (known_received_count_ < required_index_count) {
- IncreaseKnownReceivedCountTo(required_index_count);
+ known_received_count_ = required_index_count;
}
DecreaseReferenceCounts(indices);
@@ -56,7 +56,7 @@ bool QpackBlockingManager::OnInsertCountIncrement(uint64_t increment) {
return false;
}
- IncreaseKnownReceivedCountTo(known_received_count_ + increment);
+ known_received_count_ += increment;
return true;
}
@@ -68,16 +68,6 @@ void QpackBlockingManager::OnHeaderBlockSent(QuicStreamId stream_id,
header_blocks_[stream_id].push_back(std::move(indices));
}
-void QpackBlockingManager::OnReferenceSentOnEncoderStream(
- uint64_t inserted_index,
- uint64_t referred_index) {
- auto result = unacked_encoder_stream_references_.insert(
- {inserted_index, referred_index});
- // Each dynamic table entry can refer to at most one |referred_index|.
- DCHECK(result.second);
- IncreaseReferenceCounts({referred_index});
-}
-
bool QpackBlockingManager::blocking_allowed_on_stream(
QuicStreamId stream_id,
uint64_t maximum_blocked_streams) const {
@@ -141,26 +131,6 @@ uint64_t QpackBlockingManager::RequiredInsertCount(const IndexSet& indices) {
return *indices.rbegin() + 1;
}
-void QpackBlockingManager::IncreaseKnownReceivedCountTo(
- uint64_t new_known_received_count) {
- DCHECK_GT(new_known_received_count, known_received_count_);
-
- known_received_count_ = new_known_received_count;
-
- // Remove referred indices with key less than new Known Received Count from
- // |unacked_encoder_stream_references_| and |entry_reference_counts_|.
- IndexSet acknowledged_references;
- auto it = unacked_encoder_stream_references_.begin();
- while (it != unacked_encoder_stream_references_.end() &&
- it->first < known_received_count_) {
- acknowledged_references.insert(it->second);
- ++it;
- }
- unacked_encoder_stream_references_.erase(
- unacked_encoder_stream_references_.begin(), it);
- DecreaseReferenceCounts(acknowledged_references);
-}
-
void QpackBlockingManager::IncreaseReferenceCounts(const IndexSet& indices) {
for (const uint64_t index : indices) {
auto it = entry_reference_counts_.lower_bound(index);
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.h
index 60f7db7060a..6d2df9cfcf8 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager.h
@@ -48,12 +48,6 @@ class QUIC_EXPORT_PRIVATE QpackBlockingManager {
// entries with |indices|. |indices| must not be empty.
void OnHeaderBlockSent(QuicStreamId stream_id, IndexSet indices);
- // Called when sending Insert With Name Reference or Duplicate instruction on
- // encoder stream, inserting entry |inserted_index| referring to
- // |referred_index|.
- void OnReferenceSentOnEncoderStream(uint64_t inserted_index,
- uint64_t referred_index);
-
// Returns true if sending blocking references on stream |stream_id| would not
// increase the total number of blocked streams above
// |maximum_blocked_streams|. Note that if |stream_id| is already blocked
@@ -85,11 +79,6 @@ class QUIC_EXPORT_PRIVATE QpackBlockingManager {
using HeaderBlocksForStream = std::list<IndexSet>;
using HeaderBlocks = QuicUnorderedMap<QuicStreamId, HeaderBlocksForStream>;
- // Increases |known_received_count_| to |new_known_received_count|, which must
- // me larger than |known_received_count_|. Removes acknowledged references
- // from |unacked_encoder_stream_references_|.
- void IncreaseKnownReceivedCountTo(uint64_t new_known_received_count);
-
// Increase or decrease the reference count for each index in |indices|.
void IncreaseReferenceCounts(const IndexSet& indices);
void DecreaseReferenceCounts(const IndexSet& indices);
@@ -98,13 +87,7 @@ class QUIC_EXPORT_PRIVATE QpackBlockingManager {
// Must not contain a stream id with an empty queue.
HeaderBlocks header_blocks_;
- // Unacknowledged references on the encoder stream.
- // The key is the absolute index of the inserted entry,
- // the mapped value is the absolute index of the entry referred.
- std::map<uint64_t, uint64_t> unacked_encoder_stream_references_;
-
- // Number of references in |header_blocks_| and
- // |unacked_encoder_stream_references_| for each entry index.
+ // Number of references in |header_blocks_| for each entry index.
std::map<uint64_t, uint64_t> entry_reference_counts_;
uint64_t known_received_count_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager_test.cc
index 64bfb97f71d..d92dda549ef 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_blocking_manager_test.cc
@@ -236,88 +236,6 @@ TEST_F(QpackBlockingManagerTest, CancelStream) {
manager_.smallest_blocking_index());
}
-TEST_F(QpackBlockingManagerTest,
- ReferenceOnEncoderStreamUnblockedByInsertCountIncrement) {
- EXPECT_EQ(0u, manager_.known_received_count());
- EXPECT_EQ(std::numeric_limits<uint64_t>::max(),
- manager_.smallest_blocking_index());
-
- // Entry 1 refers to entry 0.
- manager_.OnReferenceSentOnEncoderStream(1, 0);
- // Entry 2 also refers to entry 0.
- manager_.OnReferenceSentOnEncoderStream(2, 0);
-
- EXPECT_EQ(0u, manager_.known_received_count());
- EXPECT_EQ(0u, manager_.smallest_blocking_index());
-
- // Acknowledging entry 1 still leaves one unacknowledged reference to entry 0.
- EXPECT_TRUE(manager_.OnInsertCountIncrement(2));
-
- EXPECT_EQ(2u, manager_.known_received_count());
- EXPECT_EQ(0u, manager_.smallest_blocking_index());
-
- // Entry 3 also refers to entry 2.
- manager_.OnReferenceSentOnEncoderStream(3, 2);
-
- EXPECT_EQ(2u, manager_.known_received_count());
- EXPECT_EQ(0u, manager_.smallest_blocking_index());
-
- // Acknowledging entry 2 removes last reference to entry 0.
- EXPECT_TRUE(manager_.OnInsertCountIncrement(1));
-
- EXPECT_EQ(3u, manager_.known_received_count());
- EXPECT_EQ(2u, manager_.smallest_blocking_index());
-
- // Acknowledging entry 4 (and implicitly 3) removes reference to entry 2.
- EXPECT_TRUE(manager_.OnInsertCountIncrement(2));
-
- EXPECT_EQ(5u, manager_.known_received_count());
- EXPECT_EQ(std::numeric_limits<uint64_t>::max(),
- manager_.smallest_blocking_index());
-}
-
-TEST_F(QpackBlockingManagerTest,
- ReferenceOnEncoderStreamUnblockedByHeaderAcknowledgement) {
- EXPECT_EQ(0u, manager_.known_received_count());
- EXPECT_EQ(std::numeric_limits<uint64_t>::max(),
- manager_.smallest_blocking_index());
-
- // Entry 1 refers to entry 0.
- manager_.OnReferenceSentOnEncoderStream(1, 0);
- // Entry 2 also refers to entry 0.
- manager_.OnReferenceSentOnEncoderStream(2, 0);
-
- EXPECT_EQ(0u, manager_.known_received_count());
- EXPECT_EQ(0u, manager_.smallest_blocking_index());
-
- // Acknowledging a header block with entries up to 1 still leave one
- // unacknowledged reference to entry 0.
- manager_.OnHeaderBlockSent(/* stream_id = */ 0, {0, 1});
- manager_.OnHeaderAcknowledgement(/* stream_id = */ 0);
-
- EXPECT_EQ(2u, manager_.known_received_count());
- EXPECT_EQ(0u, manager_.smallest_blocking_index());
-
- // Entry 3 also refers to entry 2.
- manager_.OnReferenceSentOnEncoderStream(3, 2);
-
- // Acknowledging a header block with entries up to 2 removes last reference to
- // entry 0.
- manager_.OnHeaderBlockSent(/* stream_id = */ 0, {2, 0, 2});
- manager_.OnHeaderAcknowledgement(/* stream_id = */ 0);
-
- EXPECT_EQ(3u, manager_.known_received_count());
- EXPECT_EQ(2u, manager_.smallest_blocking_index());
-
- // Acknowledging entry 4 (and implicitly 3) removes reference to entry 2.
- manager_.OnHeaderBlockSent(/* stream_id = */ 0, {1, 4, 2, 0});
- manager_.OnHeaderAcknowledgement(/* stream_id = */ 0);
-
- EXPECT_EQ(5u, manager_.known_received_count());
- EXPECT_EQ(std::numeric_limits<uint64_t>::max(),
- manager_.smallest_blocking_index());
-}
-
TEST_F(QpackBlockingManagerTest, BlockingAllowedOnStream) {
const QuicStreamId kStreamId1 = 1;
const QuicStreamId kStreamId2 = 2;
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 9cce57365b6..e16aa5a2de7 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
@@ -8,6 +8,12 @@
namespace quic {
+namespace {
+
+size_t kHeaderFieldSizeOverhead = 32;
+
+}
+
QpackDecodedHeadersAccumulator::QpackDecodedHeadersAccumulator(
QuicStreamId id,
QpackDecoder* qpack_decoder,
@@ -15,12 +21,13 @@ QpackDecodedHeadersAccumulator::QpackDecodedHeadersAccumulator(
size_t max_header_list_size)
: decoder_(qpack_decoder->CreateProgressiveDecoder(id, this)),
visitor_(visitor),
- uncompressed_header_bytes_(0),
+ max_header_list_size_(max_header_list_size),
+ uncompressed_header_bytes_including_overhead_(0),
+ uncompressed_header_bytes_without_overhead_(0),
compressed_header_bytes_(0),
+ header_list_size_limit_exceeded_(false),
headers_decoded_(false),
- blocked_(false),
error_detected_(false) {
- quic_header_list_.set_max_header_list_size(max_header_list_size);
quic_header_list_.OnHeaderBlockStart();
}
@@ -28,8 +35,21 @@ void QpackDecodedHeadersAccumulator::OnHeaderDecoded(QuicStringPiece name,
QuicStringPiece value) {
DCHECK(!error_detected_);
- uncompressed_header_bytes_ += name.size() + value.size();
- quic_header_list_.OnHeader(name, value);
+ uncompressed_header_bytes_without_overhead_ += name.size() + value.size();
+
+ if (header_list_size_limit_exceeded_) {
+ return;
+ }
+
+ uncompressed_header_bytes_including_overhead_ +=
+ name.size() + value.size() + kHeaderFieldSizeOverhead;
+
+ if (uncompressed_header_bytes_including_overhead_ > max_header_list_size_) {
+ header_list_size_limit_exceeded_ = true;
+ quic_header_list_.Clear();
+ } else {
+ quic_header_list_.OnHeader(name, value);
+ }
}
void QpackDecodedHeadersAccumulator::OnDecodingCompleted() {
@@ -37,12 +57,12 @@ void QpackDecodedHeadersAccumulator::OnDecodingCompleted() {
DCHECK(!error_detected_);
headers_decoded_ = true;
- quic_header_list_.OnHeaderBlockEnd(uncompressed_header_bytes_,
- compressed_header_bytes_);
- if (blocked_) {
- visitor_->OnHeadersDecoded(quic_header_list_);
- }
+ quic_header_list_.OnHeaderBlockEnd(
+ uncompressed_header_bytes_without_overhead_, compressed_header_bytes_);
+
+ // Might destroy |this|.
+ visitor_->OnHeadersDecoded(std::move(quic_header_list_));
}
void QpackDecodedHeadersAccumulator::OnDecodingErrorDetected(
@@ -51,51 +71,24 @@ void QpackDecodedHeadersAccumulator::OnDecodingErrorDetected(
DCHECK(!headers_decoded_);
error_detected_ = true;
- // Copy error message to ensure it remains valid for the lifetime of |this|.
- error_message_.assign(error_message.data(), error_message.size());
-
- if (blocked_) {
- visitor_->OnHeaderDecodingError();
- }
+ // Might destroy |this|.
+ visitor_->OnHeaderDecodingError(error_message);
}
-bool QpackDecodedHeadersAccumulator::Decode(QuicStringPiece data) {
+void QpackDecodedHeadersAccumulator::Decode(QuicStringPiece data) {
DCHECK(!error_detected_);
compressed_header_bytes_ += data.size();
+ // Might destroy |this|.
decoder_->Decode(data);
-
- return !error_detected_;
}
-QpackDecodedHeadersAccumulator::Status
-QpackDecodedHeadersAccumulator::EndHeaderBlock() {
+void QpackDecodedHeadersAccumulator::EndHeaderBlock() {
DCHECK(!error_detected_);
DCHECK(!headers_decoded_);
+ // Might destroy |this|.
decoder_->EndHeaderBlock();
-
- if (error_detected_) {
- DCHECK(!headers_decoded_);
- return Status::kError;
- }
-
- if (headers_decoded_) {
- return Status::kSuccess;
- }
-
- blocked_ = true;
- return Status::kBlocked;
-}
-
-const QuicHeaderList& QpackDecodedHeadersAccumulator::quic_header_list() const {
- DCHECK(!error_detected_);
- return quic_header_list_;
-}
-
-QuicStringPiece QpackDecodedHeadersAccumulator::error_message() const {
- DCHECK(error_detected_);
- return error_message_;
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.h
index c64932214dc..0a2db6a348d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.h
@@ -20,32 +20,30 @@ class QpackDecoder;
// A class that creates and owns a QpackProgressiveDecoder instance, accumulates
// decoded headers in a QuicHeaderList, and keeps track of uncompressed and
-// compressed size so that it can be passed to QuicHeaderList::EndHeaderBlock().
+// compressed size so that it can be passed to
+// QuicHeaderList::OnHeaderBlockEnd().
class QUIC_EXPORT_PRIVATE QpackDecodedHeadersAccumulator
: public QpackProgressiveDecoder::HeadersHandlerInterface {
public:
- // Return value for EndHeaderBlock().
- enum class Status {
- // Headers have been successfully decoded.
- kSuccess,
- // An error has occurred.
- kError,
- // Decoding is blocked.
- kBlocked
- };
-
- // Visitor interface used for blocked decoding. Exactly one visitor method
- // will be called if EndHeaderBlock() returned kBlocked. No visitor method
- // will be called if EndHeaderBlock() returned any other value.
- class Visitor {
+ // Visitor interface to signal success or error.
+ // Exactly one method will be called.
+ // Methods may be called synchronously from Decode() and EndHeaderBlock(),
+ // or asynchronously.
+ // Method implementations are allowed to destroy |this|.
+ class QUIC_EXPORT_PRIVATE Visitor {
public:
virtual ~Visitor() = default;
- // Called when headers are successfully decoded.
+ // Called when headers are successfully decoded. If header list size
+ // exceeds the limit specified via |max_header_list_size| in
+ // QpackDecodedHeadersAccumulator constructor, then |headers| will be empty,
+ // but will still have the correct compressed and uncompressed size
+ // information. However, header_list_size_limit_exceeded() is recommended
+ // instead of headers.empty() to check whether header size exceeds limit.
virtual void OnHeadersDecoded(QuicHeaderList headers) = 0;
// Called when an error has occurred.
- virtual void OnHeaderDecodingError() = 0;
+ virtual void OnHeaderDecodingError(QuicStringPiece error_message) = 0;
};
QpackDecodedHeadersAccumulator(QuicStreamId id,
@@ -60,42 +58,48 @@ class QUIC_EXPORT_PRIVATE QpackDecodedHeadersAccumulator
void OnDecodingCompleted() override;
void OnDecodingErrorDetected(QuicStringPiece error_message) override;
- // Decode payload data. Returns true on success, false on error.
+ // Decode payload data.
// Must not be called if an error has been detected.
// Must not be called after EndHeaderBlock().
- bool Decode(QuicStringPiece data);
+ void Decode(QuicStringPiece data);
// Signal end of HEADERS frame.
// Must not be called if an error has been detected.
// Must not be called more that once.
- // Returns kSuccess if headers can be readily decoded.
- // Returns kError if an error occurred.
- // Returns kBlocked if headers cannot be decoded at the moment, in which case
- // exactly one Visitor method will be called as soon as sufficient data
- // is received on the QPACK decoder stream.
- Status EndHeaderBlock();
-
- // Returns accumulated header list.
- const QuicHeaderList& quic_header_list() const;
-
- // Returns error message.
- // Must not be called unless an error has been detected.
- // TODO(b/124216424): Add accessor for error code, return HTTP_EXCESSIVE_LOAD
- // or HTTP_QPACK_DECOMPRESSION_FAILED.
- QuicStringPiece error_message() const;
+ void EndHeaderBlock();
+
+ // Returns true if the uncompressed size of the header list, including an
+ // overhead for each header field, exceeds |max_header_list_size| passed in
+ // the constructor.
+ bool header_list_size_limit_exceeded() const {
+ return header_list_size_limit_exceeded_;
+ }
private:
std::unique_ptr<QpackProgressiveDecoder> decoder_;
Visitor* visitor_;
+ // Maximum header list size including overhead.
+ size_t max_header_list_size_;
+ // Uncompressed header list size including overhead, for enforcing the limit.
+ size_t uncompressed_header_bytes_including_overhead_;
QuicHeaderList quic_header_list_;
- size_t uncompressed_header_bytes_;
+ // Uncompressed header list size with overhead,
+ // for passing in to QuicHeaderList::OnHeaderBlockEnd().
+ size_t uncompressed_header_bytes_without_overhead_;
+ // Compressed header list size
+ // for passing in to QuicHeaderList::OnHeaderBlockEnd().
size_t compressed_header_bytes_;
- // Set to true when OnDecodingCompleted() is called.
+
+ // True if the header size limit has been exceeded.
+ // Input data is still fed to QpackProgressiveDecoder.
+ bool header_list_size_limit_exceeded_;
+
+ // The following two members are only used for DCHECKs.
+
+ // True if headers have been completedly and successfully decoded.
bool headers_decoded_;
- // Set to true when EndHeaderBlock() returns kBlocked.
- bool blocked_;
+ // True if an error has been detected during decoding.
bool error_detected_;
- std::string error_message_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator_test.cc
index 1d60660e9c4..6616517330f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator_test.cc
@@ -7,16 +7,17 @@
#include <cstring>
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
+using ::testing::_;
using ::testing::ElementsAre;
using ::testing::Eq;
using ::testing::Pair;
+using ::testing::SaveArg;
using ::testing::StrictMock;
-using Status = quic::QpackDecodedHeadersAccumulator::Status;
namespace quic {
namespace test {
@@ -37,15 +38,15 @@ const uint64_t kMaximumBlockedStreams = 1;
// Header Acknowledgement decoder stream instruction with stream_id = 1.
const char* const kHeaderAcknowledgement = "\x81";
-} // anonymous namespace
-
-class NoopVisitor : public QpackDecodedHeadersAccumulator::Visitor {
+class MockVisitor : public QpackDecodedHeadersAccumulator::Visitor {
public:
- ~NoopVisitor() override = default;
- void OnHeadersDecoded(QuicHeaderList /* headers */) override {}
- void OnHeaderDecodingError() override {}
+ ~MockVisitor() override = default;
+ MOCK_METHOD1(OnHeadersDecoded, void(QuicHeaderList headers));
+ MOCK_METHOD1(OnHeaderDecodingError, void(QuicStringPiece error_message));
};
+} // anonymous namespace
+
class QpackDecodedHeadersAccumulatorTest : public QuicTest {
protected:
QpackDecodedHeadersAccumulatorTest()
@@ -63,91 +64,143 @@ class QpackDecodedHeadersAccumulatorTest : public QuicTest {
NoopEncoderStreamErrorDelegate encoder_stream_error_delegate_;
StrictMock<MockQpackStreamSenderDelegate> decoder_stream_sender_delegate_;
QpackDecoder qpack_decoder_;
- NoopVisitor visitor_;
+ StrictMock<MockVisitor> visitor_;
QpackDecodedHeadersAccumulator accumulator_;
};
// HEADERS frame payload must have a complete Header Block Prefix.
TEST_F(QpackDecodedHeadersAccumulatorTest, EmptyPayload) {
- EXPECT_EQ(Status::kError, accumulator_.EndHeaderBlock());
- EXPECT_EQ("Incomplete header data prefix.", accumulator_.error_message());
+ EXPECT_CALL(visitor_,
+ OnHeaderDecodingError(Eq("Incomplete header data prefix.")));
+ accumulator_.EndHeaderBlock();
}
// HEADERS frame payload must have a complete Header Block Prefix.
TEST_F(QpackDecodedHeadersAccumulatorTest, TruncatedHeaderBlockPrefix) {
- EXPECT_TRUE(accumulator_.Decode(QuicTextUtils::HexDecode("00")));
- EXPECT_EQ(Status::kError, accumulator_.EndHeaderBlock());
- EXPECT_EQ("Incomplete header data prefix.", accumulator_.error_message());
+ accumulator_.Decode(QuicTextUtils::HexDecode("00"));
+
+ EXPECT_CALL(visitor_,
+ OnHeaderDecodingError(Eq("Incomplete header data prefix.")));
+ accumulator_.EndHeaderBlock();
}
TEST_F(QpackDecodedHeadersAccumulatorTest, EmptyHeaderList) {
- EXPECT_TRUE(accumulator_.Decode(QuicTextUtils::HexDecode("0000")));
- EXPECT_EQ(Status::kSuccess, accumulator_.EndHeaderBlock());
+ std::string encoded_data(QuicTextUtils::HexDecode("0000"));
+ accumulator_.Decode(encoded_data);
- EXPECT_TRUE(accumulator_.quic_header_list().empty());
+ QuicHeaderList header_list;
+ EXPECT_CALL(visitor_, OnHeadersDecoded(_)).WillOnce(SaveArg<0>(&header_list));
+ accumulator_.EndHeaderBlock();
+ EXPECT_FALSE(accumulator_.header_list_size_limit_exceeded());
+
+ EXPECT_EQ(0u, header_list.uncompressed_header_bytes());
+ EXPECT_EQ(encoded_data.size(), header_list.compressed_header_bytes());
+ EXPECT_TRUE(header_list.empty());
}
// This payload is the prefix of a valid payload, but EndHeaderBlock() is called
// before it can be completely decoded.
TEST_F(QpackDecodedHeadersAccumulatorTest, TruncatedPayload) {
- EXPECT_TRUE(accumulator_.Decode(QuicTextUtils::HexDecode("00002366")));
- EXPECT_EQ(Status::kError, accumulator_.EndHeaderBlock());
- EXPECT_EQ("Incomplete header block.", accumulator_.error_message());
+ accumulator_.Decode(QuicTextUtils::HexDecode("00002366"));
+
+ EXPECT_CALL(visitor_, OnHeaderDecodingError(Eq("Incomplete header block.")));
+ accumulator_.EndHeaderBlock();
}
// This payload is invalid because it refers to a non-existing static entry.
TEST_F(QpackDecodedHeadersAccumulatorTest, InvalidPayload) {
- EXPECT_FALSE(accumulator_.Decode(QuicTextUtils::HexDecode("0000ff23ff24")));
- EXPECT_EQ("Static table entry not found.", accumulator_.error_message());
+ EXPECT_CALL(visitor_,
+ OnHeaderDecodingError(Eq("Static table entry not found.")));
+ accumulator_.Decode(QuicTextUtils::HexDecode("0000ff23ff24"));
}
TEST_F(QpackDecodedHeadersAccumulatorTest, Success) {
std::string encoded_data(QuicTextUtils::HexDecode("000023666f6f03626172"));
- EXPECT_TRUE(accumulator_.Decode(encoded_data));
- EXPECT_EQ(Status::kSuccess, accumulator_.EndHeaderBlock());
+ accumulator_.Decode(encoded_data);
- const QuicHeaderList& header_list = accumulator_.quic_header_list();
- EXPECT_THAT(header_list, ElementsAre(Pair("foo", "bar")));
+ QuicHeaderList header_list;
+ EXPECT_CALL(visitor_, OnHeadersDecoded(_)).WillOnce(SaveArg<0>(&header_list));
+ accumulator_.EndHeaderBlock();
+ EXPECT_FALSE(accumulator_.header_list_size_limit_exceeded());
+ EXPECT_THAT(header_list, ElementsAre(Pair("foo", "bar")));
EXPECT_EQ(strlen("foo") + strlen("bar"),
header_list.uncompressed_header_bytes());
EXPECT_EQ(encoded_data.size(), header_list.compressed_header_bytes());
}
-TEST_F(QpackDecodedHeadersAccumulatorTest, ExceedingLimit) {
+// Test that Decode() calls are not ignored after header list limit is exceeded,
+// otherwise decoding could fail with "incomplete header block" error.
+TEST_F(QpackDecodedHeadersAccumulatorTest, ExceedLimitThenSplitInstruction) {
// Total length of header list exceeds kMaxHeaderListSize.
- EXPECT_TRUE(accumulator_.Decode(QuicTextUtils::HexDecode(
+ accumulator_.Decode(QuicTextUtils::HexDecode(
"0000" // header block prefix
"26666f6f626172" // header key: "foobar"
"7d61616161616161616161616161616161616161" // header value: 'a' 125 times
"616161616161616161616161616161616161616161616161616161616161616161616161"
"616161616161616161616161616161616161616161616161616161616161616161616161"
- "61616161616161616161616161616161616161616161616161616161616161616161")));
- EXPECT_EQ(Status::kSuccess, accumulator_.EndHeaderBlock());
+ "61616161616161616161616161616161616161616161616161616161616161616161"
+ "ff")); // first byte of a two-byte long Indexed Header Field instruction
+ accumulator_.Decode(QuicTextUtils::HexDecode(
+ "0f" // second byte of a two-byte long Indexed Header Field instruction
+ ));
+
+ EXPECT_CALL(visitor_, OnHeadersDecoded(_));
+ accumulator_.EndHeaderBlock();
+ EXPECT_TRUE(accumulator_.header_list_size_limit_exceeded());
+}
- // QuicHeaderList signals header list over limit by clearing it.
- EXPECT_TRUE(accumulator_.quic_header_list().empty());
+// Test that header list limit enforcement works with blocked encoding.
+TEST_F(QpackDecodedHeadersAccumulatorTest, ExceedLimitBlocked) {
+ // Total length of header list exceeds kMaxHeaderListSize.
+ accumulator_.Decode(QuicTextUtils::HexDecode(
+ "0200" // header block prefix
+ "80" // reference to dynamic table entry not yet received
+ "26666f6f626172" // header key: "foobar"
+ "7d61616161616161616161616161616161616161" // header value: 'a' 125 times
+ "616161616161616161616161616161616161616161616161616161616161616161616161"
+ "616161616161616161616161616161616161616161616161616161616161616161616161"
+ "61616161616161616161616161616161616161616161616161616161616161616161"));
+ accumulator_.EndHeaderBlock();
+
+ // Set dynamic table capacity.
+ qpack_decoder_.OnSetDynamicTableCapacity(kMaxDynamicTableCapacity);
+ // Adding dynamic table entry unblocks decoding.
+ EXPECT_CALL(decoder_stream_sender_delegate_,
+ WriteStreamData(Eq(kHeaderAcknowledgement)));
+
+ EXPECT_CALL(visitor_, OnHeadersDecoded(_));
+ qpack_decoder_.OnInsertWithoutNameReference("foo", "bar");
+ EXPECT_TRUE(accumulator_.header_list_size_limit_exceeded());
}
TEST_F(QpackDecodedHeadersAccumulatorTest, BlockedDecoding) {
// Reference to dynamic table entry not yet received.
- EXPECT_TRUE(accumulator_.Decode(QuicTextUtils::HexDecode("020080")));
- EXPECT_EQ(Status::kBlocked, accumulator_.EndHeaderBlock());
+ std::string encoded_data(QuicTextUtils::HexDecode("020080"));
+ accumulator_.Decode(encoded_data);
+ accumulator_.EndHeaderBlock();
// Set dynamic table capacity.
qpack_decoder_.OnSetDynamicTableCapacity(kMaxDynamicTableCapacity);
// Adding dynamic table entry unblocks decoding.
EXPECT_CALL(decoder_stream_sender_delegate_,
WriteStreamData(Eq(kHeaderAcknowledgement)));
+
+ QuicHeaderList header_list;
+ EXPECT_CALL(visitor_, OnHeadersDecoded(_)).WillOnce(SaveArg<0>(&header_list));
qpack_decoder_.OnInsertWithoutNameReference("foo", "bar");
- EXPECT_THAT(accumulator_.quic_header_list(), ElementsAre(Pair("foo", "bar")));
+ EXPECT_FALSE(accumulator_.header_list_size_limit_exceeded());
+ EXPECT_THAT(header_list, ElementsAre(Pair("foo", "bar")));
+ EXPECT_EQ(strlen("foo") + strlen("bar"),
+ header_list.uncompressed_header_bytes());
+ EXPECT_EQ(encoded_data.size(), header_list.compressed_header_bytes());
}
TEST_F(QpackDecodedHeadersAccumulatorTest,
BlockedDecodingUnblockedBeforeEndOfHeaderBlock) {
// Reference to dynamic table entry not yet received.
- EXPECT_TRUE(accumulator_.Decode(QuicTextUtils::HexDecode("020080")));
+ accumulator_.Decode(QuicTextUtils::HexDecode("020080"));
// Set dynamic table capacity.
qpack_decoder_.OnSetDynamicTableCapacity(kMaxDynamicTableCapacity);
@@ -157,11 +210,34 @@ TEST_F(QpackDecodedHeadersAccumulatorTest,
// Rest of header block: same entry again.
EXPECT_CALL(decoder_stream_sender_delegate_,
WriteStreamData(Eq(kHeaderAcknowledgement)));
- EXPECT_TRUE(accumulator_.Decode(QuicTextUtils::HexDecode("80")));
- EXPECT_EQ(Status::kSuccess, accumulator_.EndHeaderBlock());
+ accumulator_.Decode(QuicTextUtils::HexDecode("80"));
- EXPECT_THAT(accumulator_.quic_header_list(),
- ElementsAre(Pair("foo", "bar"), Pair("foo", "bar")));
+ QuicHeaderList header_list;
+ EXPECT_CALL(visitor_, OnHeadersDecoded(_)).WillOnce(SaveArg<0>(&header_list));
+ accumulator_.EndHeaderBlock();
+ EXPECT_FALSE(accumulator_.header_list_size_limit_exceeded());
+
+ EXPECT_THAT(header_list, ElementsAre(Pair("foo", "bar"), Pair("foo", "bar")));
+}
+
+// Regression test for https://crbug.com/1024263.
+TEST_F(QpackDecodedHeadersAccumulatorTest,
+ BlockedDecodingUnblockedAndErrorBeforeEndOfHeaderBlock) {
+ // Required Insert Count higher than number of entries causes decoding to be
+ // blocked.
+ accumulator_.Decode(QuicTextUtils::HexDecode("0200"));
+ // Indexed Header Field instruction addressing dynamic table entry with
+ // relative index 0, absolute index 0.
+ accumulator_.Decode(QuicTextUtils::HexDecode("80"));
+ // Relative index larger than or equal to Base is invalid.
+ accumulator_.Decode(QuicTextUtils::HexDecode("81"));
+
+ // Set dynamic table capacity.
+ qpack_decoder_.OnSetDynamicTableCapacity(kMaxDynamicTableCapacity);
+
+ // Adding dynamic table entry unblocks decoding. Error is detected.
+ EXPECT_CALL(visitor_, OnHeaderDecodingError(Eq("Invalid relative index.")));
+ qpack_decoder_.OnInsertWithoutNameReference("foo", "bar");
}
} // namespace test
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 4f39e3b39b2..3ae6bce6e6b 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
@@ -27,10 +27,10 @@ QpackDecoder::QpackDecoder(
QpackDecoder::~QpackDecoder() {}
void QpackDecoder::OnStreamReset(QuicStreamId stream_id) {
- // TODO(bnc): SendStreamCancellation should not be called if maximum dynamic
- // table capacity is zero.
- decoder_stream_sender_.SendStreamCancellation(stream_id);
- decoder_stream_sender_.Flush();
+ if (header_table_.maximum_dynamic_table_capacity() > 0) {
+ decoder_stream_sender_.SendStreamCancellation(stream_id);
+ decoder_stream_sender_.Flush();
+ }
}
bool QpackDecoder::OnStreamBlocked(QuicStreamId stream_id) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h
index 113c6ea8e4a..4ac1e449bc6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h
@@ -95,6 +95,11 @@ class QUIC_EXPORT_PRIVATE QpackDecoder
return &encoder_stream_receiver_;
}
+ // True if any dynamic table entries have been referenced from a header block.
+ bool dynamic_table_entry_referenced() const {
+ return header_table_.dynamic_table_entry_referenced();
+ }
+
private:
EncoderStreamErrorDelegate* const encoder_stream_error_delegate_;
QpackEncoderStreamReceiver encoder_stream_receiver_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.cc
index 559ce433376..2ba89d48a82 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.cc
@@ -6,7 +6,7 @@
#include "net/third_party/quiche/src/http2/decoder/decode_buffer.h"
#include "net/third_party/quiche/src/http2/decoder/decode_status.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.h
index 60719399d8b..396c6df8779 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.h
@@ -23,7 +23,7 @@ class QUIC_EXPORT_PRIVATE QpackDecoderStreamReceiver
public:
// An interface for handling instructions decoded from the decoder stream, see
// https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5.3
- class Delegate {
+ class QUIC_EXPORT_PRIVATE Delegate {
public:
virtual ~Delegate() = default;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.cc
index 68e4d67816c..72a446b420a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.cc
@@ -8,7 +8,7 @@
#include <limits>
#include <string>
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
namespace quic {
@@ -16,25 +16,19 @@ namespace quic {
QpackDecoderStreamSender::QpackDecoderStreamSender() : delegate_(nullptr) {}
void QpackDecoderStreamSender::SendInsertCountIncrement(uint64_t increment) {
- values_.varint = increment;
-
- instruction_encoder_.Encode(InsertCountIncrementInstruction(), values_,
- &buffer_);
+ instruction_encoder_.Encode(
+ QpackInstructionWithValues::InsertCountIncrement(increment), &buffer_);
}
void QpackDecoderStreamSender::SendHeaderAcknowledgement(
QuicStreamId stream_id) {
- values_.varint = stream_id;
-
- instruction_encoder_.Encode(HeaderAcknowledgementInstruction(), values_,
- &buffer_);
+ instruction_encoder_.Encode(
+ QpackInstructionWithValues::HeaderAcknowledgement(stream_id), &buffer_);
}
void QpackDecoderStreamSender::SendStreamCancellation(QuicStreamId stream_id) {
- values_.varint = stream_id;
-
- instruction_encoder_.Encode(StreamCancellationInstruction(), values_,
- &buffer_);
+ instruction_encoder_.Encode(
+ QpackInstructionWithValues::StreamCancellation(stream_id), &buffer_);
}
void QpackDecoderStreamSender::Flush() {
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h
index 93d95d91476..d9033b04dee 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h
@@ -44,7 +44,6 @@ class QUIC_EXPORT_PRIVATE QpackDecoderStreamSender {
private:
QpackStreamSenderDelegate* delegate_;
QpackInstructionEncoder instruction_encoder_;
- QpackInstructionEncoder::Values values_;
std::string buffer_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender_test.cc
index 6e042590833..e3dc12497e3 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender_test.cc
@@ -4,9 +4,9 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
using ::testing::Eq;
using ::testing::StrictMock;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test.cc
index d0ff30ff679..1fc5802d83c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test.cc
@@ -6,14 +6,16 @@
#include <algorithm>
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
+using ::testing::_;
using ::testing::Eq;
+using ::testing::Invoke;
using ::testing::Mock;
using ::testing::Sequence;
using ::testing::StrictMock;
@@ -42,6 +44,15 @@ class QpackDecoderTest : public QuicTestWithParam<FragmentMode> {
~QpackDecoderTest() override = default;
+ void SetUp() override {
+ // Destroy QpackProgressiveDecoder on error to test that it does not crash.
+ // See https://crbug.com/1025209.
+ ON_CALL(handler_, OnDecodingErrorDetected(_))
+ .WillByDefault(Invoke([this](QuicStringPiece /* error_message */) {
+ progressive_decoder_.reset();
+ }));
+ }
+
void DecodeEncoderStreamData(QuicStringPiece data) {
qpack_decoder_.encoder_stream_receiver()->Decode(data);
}
@@ -61,7 +72,7 @@ class QpackDecoderTest : public QuicTestWithParam<FragmentMode> {
void DecodeData(QuicStringPiece data) {
auto fragment_size_generator =
FragmentModeToFragmentSizeGenerator(fragment_mode_);
- while (!data.empty()) {
+ while (progressive_decoder_ && !data.empty()) {
size_t fragment_size = std::min(fragment_size_generator(), data.size());
progressive_decoder_->Decode(data.substr(0, fragment_size));
data = data.substr(fragment_size);
@@ -70,9 +81,11 @@ class QpackDecoderTest : public QuicTestWithParam<FragmentMode> {
// Signal end of header block to QpackProgressiveDecoder.
void EndDecoding() {
- progressive_decoder_->EndHeaderBlock();
- // |progressive_decoder_| is kept alive so that it can
- // handle callbacks later in case of blocked decoding.
+ if (progressive_decoder_) {
+ progressive_decoder_->EndHeaderBlock();
+ }
+ // If no error was detected, |*progressive_decoder_| is kept alive so that
+ // it can handle callbacks later in case of blocked decoding.
}
// Decode an entire header block.
@@ -105,6 +118,18 @@ TEST_P(QpackDecoderTest, NoPrefix) {
DecodeHeaderBlock(QuicTextUtils::HexDecode("00"));
}
+// Regression test for https://1025209: QpackProgressiveDecoder must not crash
+// in Decode() if it is destroyed by handler_.OnDecodingErrorDetected().
+TEST_P(QpackDecoderTest, InvalidPrefix) {
+ StartDecoding();
+
+ EXPECT_CALL(handler_,
+ OnDecodingErrorDetected(Eq("Encoded integer too large.")));
+
+ // Encoded Required Insert Count in Header Data Prefix is too large.
+ DecodeData(QuicTextUtils::HexDecode("ffffffffffffffffffffffffffff"));
+}
+
TEST_P(QpackDecoderTest, EmptyHeaderBlock) {
EXPECT_CALL(handler_, OnDecodingCompleted());
@@ -780,16 +805,15 @@ TEST_P(QpackDecoderTest, BlockedDecodingUnblockedBeforeEndOfHeaderBlock) {
// entry with relative index 0, absolute index 0.
"d1")); // Static table entry with index 17.
+ // Set dynamic table capacity to 1024.
+ DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
+
// Add literal entry with name "foo" and value "bar". Decoding is now
// unblocked because dynamic table Insert Count reached the Required Insert
// Count of the header block. |handler_| methods are called immediately for
// the already consumed part of the header block.
EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("GET")));
-
- // Set dynamic table capacity to 1024.
- DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
- // Add literal entry with name "foo" and value "bar".
DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
Mock::VerifyAndClearExpectations(&handler_);
@@ -809,6 +833,29 @@ TEST_P(QpackDecoderTest, BlockedDecodingUnblockedBeforeEndOfHeaderBlock) {
EndDecoding();
}
+// Regression test for https://crbug.com/1024263.
+TEST_P(QpackDecoderTest,
+ BlockedDecodingUnblockedAndErrorBeforeEndOfHeaderBlock) {
+ StartDecoding();
+ DecodeData(QuicTextUtils::HexDecode(
+ "0200" // Required Insert Count 1 and Delta Base 0.
+ // Base is 1 + 0 = 1.
+ "80" // Indexed Header Field instruction addressing dynamic table
+ // entry with relative index 0, absolute index 0.
+ "81")); // Relative index 1 is equal to Base, therefore invalid.
+
+ // Set dynamic table capacity to 1024.
+ DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe107"));
+
+ // Add literal entry with name "foo" and value "bar". Decoding is now
+ // unblocked because dynamic table Insert Count reached the Required Insert
+ // Count of the header block. |handler_| methods are called immediately for
+ // the already consumed part of the header block.
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
+ EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Invalid relative index.")));
+ DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
+}
+
// Make sure that Required Insert Count is compared to Insert Count,
// not size of dynamic table.
TEST_P(QpackDecoderTest, BlockedDecodingAndEvictedEntries) {
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 319af82115a..59e172ec75a 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
@@ -7,7 +7,6 @@
#include <algorithm>
#include <utility>
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_index_conversions.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_required_insert_count.h"
@@ -42,47 +41,37 @@ QpackEncoder::QpackEncoder(
QpackEncoder::~QpackEncoder() {}
// static
-QpackEncoder::InstructionWithValues QpackEncoder::EncodeIndexedHeaderField(
+QpackInstructionWithValues QpackEncoder::EncodeIndexedHeaderField(
bool is_static,
uint64_t index,
QpackBlockingManager::IndexSet* referred_indices) {
- InstructionWithValues instruction{QpackIndexedHeaderFieldInstruction(), {}};
- instruction.values.s_bit = is_static;
- instruction.values.varint = index;
// Add |index| to |*referred_indices| only if entry is in the dynamic table.
if (!is_static) {
referred_indices->insert(index);
}
- return instruction;
+ return QpackInstructionWithValues::IndexedHeaderField(is_static, index);
}
// static
-QpackEncoder::InstructionWithValues
+QpackInstructionWithValues
QpackEncoder::EncodeLiteralHeaderFieldWithNameReference(
bool is_static,
uint64_t index,
QuicStringPiece value,
QpackBlockingManager::IndexSet* referred_indices) {
- InstructionWithValues instruction{
- QpackLiteralHeaderFieldNameReferenceInstruction(), {}};
- instruction.values.s_bit = is_static;
- instruction.values.varint = index;
- instruction.values.value = value;
// Add |index| to |*referred_indices| only if entry is in the dynamic table.
if (!is_static) {
referred_indices->insert(index);
}
- return instruction;
+ return QpackInstructionWithValues::LiteralHeaderFieldNameReference(
+ is_static, index, value);
}
// static
-QpackEncoder::InstructionWithValues QpackEncoder::EncodeLiteralHeaderField(
+QpackInstructionWithValues QpackEncoder::EncodeLiteralHeaderField(
QuicStringPiece name,
QuicStringPiece value) {
- InstructionWithValues instruction{QpackLiteralHeaderFieldInstruction(), {}};
- instruction.values.name = name;
- instruction.values.value = value;
- return instruction;
+ return QpackInstructionWithValues::LiteralHeaderField(name, value);
}
QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
@@ -142,6 +131,7 @@ QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
instructions.push_back(
EncodeIndexedHeaderField(is_static, index, referred_indices));
smallest_blocking_index = std::min(smallest_blocking_index, index);
+ header_table_.set_dynamic_table_entry_referenced();
break;
}
@@ -159,11 +149,10 @@ QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
QpackAbsoluteIndexToEncoderStreamRelativeIndex(
index, header_table_.inserted_entry_count()));
auto entry = header_table_.InsertEntry(name, value);
- blocking_manager_.OnReferenceSentOnEncoderStream(
- entry->InsertionIndex(), index);
instructions.push_back(EncodeIndexedHeaderField(
is_static, entry->InsertionIndex(), referred_indices));
smallest_blocking_index = std::min(smallest_blocking_index, index);
+ header_table_.set_dynamic_table_entry_referenced();
break;
}
@@ -218,11 +207,10 @@ QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
index, header_table_.inserted_entry_count()),
value);
auto entry = header_table_.InsertEntry(name, value);
- blocking_manager_.OnReferenceSentOnEncoderStream(
- entry->InsertionIndex(), index);
instructions.push_back(EncodeIndexedHeaderField(
is_static, entry->InsertionIndex(), referred_indices));
smallest_blocking_index = std::min(smallest_blocking_index, index);
+ header_table_.set_dynamic_table_entry_referenced();
break;
}
@@ -233,6 +221,7 @@ QpackEncoder::Instructions QpackEncoder::FirstPassEncode(
instructions.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();
break;
}
@@ -329,29 +318,24 @@ std::string QpackEncoder::SecondPassEncode(
std::string encoded_headers;
// Header block prefix.
- QpackInstructionEncoder::Values values;
- values.varint = QpackEncodeRequiredInsertCount(required_insert_count,
- header_table_.max_entries());
- values.varint2 = 0; // Delta Base.
- values.s_bit = false; // Delta Base sign.
- const uint64_t base = required_insert_count;
+ instruction_encoder.Encode(
+ QpackInstructionWithValues::Prefix(QpackEncodeRequiredInsertCount(
+ required_insert_count, header_table_.max_entries())),
+ &encoded_headers);
- instruction_encoder.Encode(QpackPrefixInstruction(), values,
- &encoded_headers);
+ const uint64_t base = required_insert_count;
for (auto& instruction : instructions) {
// Dynamic table references must be transformed from absolute to relative
// indices.
- if ((instruction.instruction == QpackIndexedHeaderFieldInstruction() ||
- instruction.instruction ==
+ if ((instruction.instruction() == QpackIndexedHeaderFieldInstruction() ||
+ instruction.instruction() ==
QpackLiteralHeaderFieldNameReferenceInstruction()) &&
- !instruction.values.s_bit) {
- instruction.values.varint =
- QpackAbsoluteIndexToRequestStreamRelativeIndex(
- instruction.values.varint, base);
+ !instruction.s_bit()) {
+ instruction.set_varint(QpackAbsoluteIndexToRequestStreamRelativeIndex(
+ instruction.varint(), base));
}
- instruction_encoder.Encode(instruction.instruction, instruction.values,
- &encoded_headers);
+ instruction_encoder.Encode(instruction, &encoded_headers);
}
return encoded_headers;
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 1ed56a82e11..e635e3bf04b 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
@@ -14,6 +14,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_exported_stats.h"
@@ -87,39 +88,35 @@ class QUIC_EXPORT_PRIVATE QpackEncoder
return &decoder_stream_receiver_;
}
+ // True if any dynamic table entries have been referenced from a header block.
+ bool dynamic_table_entry_referenced() const {
+ return header_table_.dynamic_table_entry_referenced();
+ }
+
private:
friend class test::QpackEncoderPeer;
- // TODO(bnc): Consider moving this class to QpackInstructionEncoder or
- // qpack_constants, adding factory methods, one for each instruction, and
- // changing QpackInstructionEncoder::Encoder() to take an
- // InstructionWithValues struct instead of separate |instruction| and |values|
- // arguments.
- struct InstructionWithValues {
- // |instruction| is not owned.
- const QpackInstruction* instruction;
- QpackInstructionEncoder::Values values;
- };
- using Instructions = std::vector<InstructionWithValues>;
+ using Instructions = std::vector<QpackInstructionWithValues>;
// Generate indexed header field instruction
// and optionally update |*referred_indices|.
- static InstructionWithValues EncodeIndexedHeaderField(
+ static QpackInstructionWithValues EncodeIndexedHeaderField(
bool is_static,
uint64_t index,
QpackBlockingManager::IndexSet* referred_indices);
// Generate literal header field with name reference instruction
// and optionally update |*referred_indices|.
- static InstructionWithValues EncodeLiteralHeaderFieldWithNameReference(
+ static QpackInstructionWithValues EncodeLiteralHeaderFieldWithNameReference(
bool is_static,
uint64_t index,
QuicStringPiece value,
QpackBlockingManager::IndexSet* referred_indices);
// Generate literal header field instruction.
- static InstructionWithValues EncodeLiteralHeaderField(QuicStringPiece name,
- QuicStringPiece value);
+ static QpackInstructionWithValues EncodeLiteralHeaderField(
+ QuicStringPiece name,
+ QuicStringPiece 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
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.cc
index 3f8ef08a7ee..c46cc3c0f41 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.cc
@@ -6,7 +6,7 @@
#include "net/third_party/quiche/src/http2/decoder/decode_buffer.h"
#include "net/third_party/quiche/src/http2/decoder/decode_status.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.h
index 8da3147d1ea..b393b546b60 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.h
@@ -22,7 +22,7 @@ class QUIC_EXPORT_PRIVATE QpackEncoderStreamReceiver
public:
// An interface for handling instructions decoded from the encoder stream, see
// https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5.2
- class Delegate {
+ class QUIC_EXPORT_PRIVATE Delegate {
public:
virtual ~Delegate() = default;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.cc
index 4a7f12cd3a3..5182864ce6d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.cc
@@ -8,7 +8,7 @@
#include <limits>
#include <string>
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
namespace quic {
@@ -19,35 +19,28 @@ void QpackEncoderStreamSender::SendInsertWithNameReference(
bool is_static,
uint64_t name_index,
QuicStringPiece value) {
- values_.s_bit = is_static;
- values_.varint = name_index;
- values_.value = value;
-
- instruction_encoder_.Encode(InsertWithNameReferenceInstruction(), values_,
- &buffer_);
+ instruction_encoder_.Encode(
+ QpackInstructionWithValues::InsertWithNameReference(is_static, name_index,
+ value),
+ &buffer_);
}
void QpackEncoderStreamSender::SendInsertWithoutNameReference(
QuicStringPiece name,
QuicStringPiece value) {
- values_.name = name;
- values_.value = value;
-
- instruction_encoder_.Encode(InsertWithoutNameReferenceInstruction(), values_,
- &buffer_);
+ instruction_encoder_.Encode(
+ QpackInstructionWithValues::InsertWithoutNameReference(name, value),
+ &buffer_);
}
void QpackEncoderStreamSender::SendDuplicate(uint64_t index) {
- values_.varint = index;
-
- instruction_encoder_.Encode(DuplicateInstruction(), values_, &buffer_);
+ instruction_encoder_.Encode(QpackInstructionWithValues::Duplicate(index),
+ &buffer_);
}
void QpackEncoderStreamSender::SendSetDynamicTableCapacity(uint64_t capacity) {
- values_.varint = capacity;
-
- instruction_encoder_.Encode(SetDynamicTableCapacityInstruction(), values_,
- &buffer_);
+ instruction_encoder_.Encode(
+ QpackInstructionWithValues::SetDynamicTableCapacity(capacity), &buffer_);
}
QuicByteCount QpackEncoderStreamSender::Flush() {
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h
index efbfbc632d5..de9e8f14839 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h
@@ -50,7 +50,6 @@ class QUIC_EXPORT_PRIVATE QpackEncoderStreamSender {
private:
QpackStreamSenderDelegate* delegate_;
QpackInstructionEncoder instruction_encoder_;
- QpackInstructionEncoder::Values values_;
std::string buffer_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender_test.cc
index 80a6ed3c06f..0a42df220cb 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender_test.cc
@@ -4,9 +4,9 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
using ::testing::Eq;
using ::testing::StrictMock;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc
index 6f2efe3aecc..6b92e4bfc95 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc
@@ -7,13 +7,12 @@
#include <limits>
#include <string>
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test_utils.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
-#include "net/third_party/quiche/src/quic/test_tools/qpack_encoder_peer.h"
-#include "net/third_party/quiche/src/quic/test_tools/qpack_header_table_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
using ::testing::_;
using ::testing::Eq;
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 ff9be9a79fd..4cafa196815 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
@@ -17,7 +17,8 @@ QpackHeaderTable::QpackHeaderTable()
dynamic_table_capacity_(0),
maximum_dynamic_table_capacity_(0),
max_entries_(0),
- dropped_entry_count_(0) {}
+ dropped_entry_count_(0),
+ dynamic_table_entry_referenced_(false) {}
QpackHeaderTable::~QpackHeaderTable() {
for (auto& entry : observers_) {
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 78d85f6ae29..dd5ca3ba3e5 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
@@ -40,7 +40,7 @@ class QUIC_EXPORT_PRIVATE QpackHeaderTable {
enum class MatchType { kNameAndValue, kName, kNoMatch };
// Observer interface for dynamic table insertion.
- class Observer {
+ class QUIC_EXPORT_PRIVATE Observer {
public:
virtual ~Observer() = default;
@@ -98,6 +98,11 @@ class QUIC_EXPORT_PRIVATE QpackHeaderTable {
// This method must only be called at most once.
void SetMaximumDynamicTableCapacity(uint64_t maximum_dynamic_table_capacity);
+ // Get |maximum_dynamic_table_capacity_|.
+ uint64_t maximum_dynamic_table_capacity() const {
+ return maximum_dynamic_table_capacity_;
+ }
+
// Register an observer to be notified when inserted_entry_count() reaches
// |required_insert_count|. After the notification, |observer| automatically
// gets unregistered. Each observer must only be registered at most once.
@@ -130,6 +135,13 @@ class QUIC_EXPORT_PRIVATE QpackHeaderTable {
// The returned index might not be the index of a valid entry.
uint64_t draining_index(float draining_fraction) const;
+ void set_dynamic_table_entry_referenced() {
+ dynamic_table_entry_referenced_ = true;
+ }
+ bool dynamic_table_entry_referenced() const {
+ return dynamic_table_entry_referenced_;
+ }
+
private:
friend class test::QpackHeaderTablePeer;
@@ -192,6 +204,10 @@ class QUIC_EXPORT_PRIVATE QpackHeaderTable {
// Observers waiting to be notified, sorted by required insert count.
std::multimap<uint64_t, Observer*> observers_;
+
+ // True if any dynamic table entries have been referenced from a header block.
+ // Set directly by the encoder or decoder. Used for stats.
+ bool dynamic_table_entry_referenced_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.cc
index 187894d374e..fede8e307df 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
@@ -32,44 +32,48 @@ QpackInstructionDecoder::QpackInstructionDecoder(const QpackLanguage* language,
error_detected_(false),
state_(State::kStartInstruction) {}
-void QpackInstructionDecoder::Decode(QuicStringPiece data) {
+bool QpackInstructionDecoder::Decode(QuicStringPiece data) {
DCHECK(!data.empty());
DCHECK(!error_detected_);
while (true) {
+ bool success = true;
size_t bytes_consumed = 0;
switch (state_) {
case State::kStartInstruction:
- DoStartInstruction(data);
+ success = DoStartInstruction(data);
break;
case State::kStartField:
- DoStartField();
+ success = DoStartField();
break;
case State::kReadBit:
- DoReadBit(data);
+ success = DoReadBit(data);
break;
case State::kVarintStart:
- bytes_consumed = DoVarintStart(data);
+ success = DoVarintStart(data, &bytes_consumed);
break;
case State::kVarintResume:
- bytes_consumed = DoVarintResume(data);
+ success = DoVarintResume(data, &bytes_consumed);
break;
case State::kVarintDone:
- DoVarintDone();
+ success = DoVarintDone();
break;
case State::kReadString:
- bytes_consumed = DoReadString(data);
+ success = DoReadString(data, &bytes_consumed);
break;
case State::kReadStringDone:
- DoReadStringDone();
+ success = DoReadStringDone();
break;
}
- if (error_detected_) {
- return;
+ if (!success) {
+ return false;
}
+ // |success| must be false if an error is detected.
+ DCHECK(!error_detected_);
+
DCHECK_LE(bytes_consumed, data.size());
data = QuicStringPiece(data.data() + bytes_consumed,
@@ -78,35 +82,37 @@ void QpackInstructionDecoder::Decode(QuicStringPiece data) {
// Stop processing if no more data but next state would require it.
if (data.empty() && (state_ != State::kStartField) &&
(state_ != State::kVarintDone) && (state_ != State::kReadStringDone)) {
- return;
+ return true;
}
}
+
+ return true;
}
bool QpackInstructionDecoder::AtInstructionBoundary() const {
return state_ == State::kStartInstruction;
}
-void QpackInstructionDecoder::DoStartInstruction(QuicStringPiece data) {
+bool QpackInstructionDecoder::DoStartInstruction(QuicStringPiece data) {
DCHECK(!data.empty());
instruction_ = LookupOpcode(data[0]);
field_ = instruction_->fields.begin();
state_ = State::kStartField;
+ return true;
}
-void QpackInstructionDecoder::DoStartField() {
+bool QpackInstructionDecoder::DoStartField() {
if (field_ == instruction_->fields.end()) {
// Completed decoding this instruction.
if (!delegate_->OnInstructionDecoded(instruction_)) {
- error_detected_ = true;
- return;
+ return false;
}
state_ = State::kStartInstruction;
- return;
+ return true;
}
switch (field_->type) {
@@ -114,15 +120,18 @@ void QpackInstructionDecoder::DoStartField() {
case QpackInstructionFieldType::kName:
case QpackInstructionFieldType::kValue:
state_ = State::kReadBit;
- return;
+ return true;
case QpackInstructionFieldType::kVarint:
case QpackInstructionFieldType::kVarint2:
state_ = State::kVarintStart;
- return;
+ return true;
+ default:
+ QUIC_BUG << "Invalid field type.";
+ return false;
}
}
-void QpackInstructionDecoder::DoReadBit(QuicStringPiece data) {
+bool QpackInstructionDecoder::DoReadBit(QuicStringPiece data) {
DCHECK(!data.empty());
switch (field_->type) {
@@ -133,7 +142,7 @@ void QpackInstructionDecoder::DoReadBit(QuicStringPiece data) {
++field_;
state_ = State::kStartField;
- return;
+ return true;
}
case QpackInstructionFieldType::kName:
case QpackInstructionFieldType::kValue: {
@@ -144,14 +153,16 @@ void QpackInstructionDecoder::DoReadBit(QuicStringPiece data) {
state_ = State::kVarintStart;
- return;
+ return true;
}
default:
- DCHECK(false);
+ QUIC_BUG << "Invalid field type.";
+ return false;
}
}
-size_t QpackInstructionDecoder::DoVarintStart(QuicStringPiece data) {
+bool QpackInstructionDecoder::DoVarintStart(QuicStringPiece data,
+ size_t* bytes_consumed) {
DCHECK(!data.empty());
DCHECK(field_->type == QpackInstructionFieldType::kVarint ||
field_->type == QpackInstructionFieldType::kVarint2 ||
@@ -162,24 +173,25 @@ size_t QpackInstructionDecoder::DoVarintStart(QuicStringPiece data) {
http2::DecodeStatus status =
varint_decoder_.Start(data[0], field_->param, &buffer);
- size_t bytes_consumed = 1 + buffer.Offset();
+ *bytes_consumed = 1 + buffer.Offset();
switch (status) {
case http2::DecodeStatus::kDecodeDone:
state_ = State::kVarintDone;
- return bytes_consumed;
+ return true;
case http2::DecodeStatus::kDecodeInProgress:
state_ = State::kVarintResume;
- return bytes_consumed;
+ return true;
case http2::DecodeStatus::kDecodeError:
OnError("Encoded integer too large.");
- return bytes_consumed;
+ return false;
default:
QUIC_BUG << "Unknown decode status " << status;
- return bytes_consumed;
+ return false;
}
}
-size_t QpackInstructionDecoder::DoVarintResume(QuicStringPiece data) {
+bool QpackInstructionDecoder::DoVarintResume(QuicStringPiece data,
+ size_t* bytes_consumed) {
DCHECK(!data.empty());
DCHECK(field_->type == QpackInstructionFieldType::kVarint ||
field_->type == QpackInstructionFieldType::kVarint2 ||
@@ -189,25 +201,25 @@ size_t QpackInstructionDecoder::DoVarintResume(QuicStringPiece data) {
http2::DecodeBuffer buffer(data);
http2::DecodeStatus status = varint_decoder_.Resume(&buffer);
- size_t bytes_consumed = buffer.Offset();
+ *bytes_consumed = buffer.Offset();
switch (status) {
case http2::DecodeStatus::kDecodeDone:
state_ = State::kVarintDone;
- return bytes_consumed;
+ return true;
case http2::DecodeStatus::kDecodeInProgress:
- DCHECK_EQ(bytes_consumed, data.size());
+ DCHECK_EQ(*bytes_consumed, data.size());
DCHECK(buffer.Empty());
- return bytes_consumed;
+ return true;
case http2::DecodeStatus::kDecodeError:
OnError("Encoded integer too large.");
- return bytes_consumed;
+ return false;
default:
QUIC_BUG << "Unknown decode status " << status;
- return bytes_consumed;
+ return false;
}
}
-void QpackInstructionDecoder::DoVarintDone() {
+bool QpackInstructionDecoder::DoVarintDone() {
DCHECK(field_->type == QpackInstructionFieldType::kVarint ||
field_->type == QpackInstructionFieldType::kVarint2 ||
field_->type == QpackInstructionFieldType::kName ||
@@ -218,7 +230,7 @@ void QpackInstructionDecoder::DoVarintDone() {
++field_;
state_ = State::kStartField;
- return;
+ return true;
}
if (field_->type == QpackInstructionFieldType::kVarint2) {
@@ -226,13 +238,13 @@ void QpackInstructionDecoder::DoVarintDone() {
++field_;
state_ = State::kStartField;
- return;
+ return true;
}
string_length_ = varint_decoder_.value();
if (string_length_ > kStringLiteralLengthLimit) {
OnError("String literal too long.");
- return;
+ return false;
}
std::string* const string =
@@ -242,15 +254,17 @@ void QpackInstructionDecoder::DoVarintDone() {
if (string_length_ == 0) {
++field_;
state_ = State::kStartField;
- return;
+ return true;
}
string->reserve(string_length_);
state_ = State::kReadString;
+ return true;
}
-size_t QpackInstructionDecoder::DoReadString(QuicStringPiece data) {
+bool QpackInstructionDecoder::DoReadString(QuicStringPiece data,
+ size_t* bytes_consumed) {
DCHECK(!data.empty());
DCHECK(field_->type == QpackInstructionFieldType::kName ||
field_->type == QpackInstructionFieldType::kValue);
@@ -259,18 +273,17 @@ size_t QpackInstructionDecoder::DoReadString(QuicStringPiece data) {
(field_->type == QpackInstructionFieldType::kName) ? &name_ : &value_;
DCHECK_LT(string->size(), string_length_);
- size_t bytes_consumed =
- std::min(string_length_ - string->size(), data.size());
- string->append(data.data(), bytes_consumed);
+ *bytes_consumed = std::min(string_length_ - string->size(), data.size());
+ string->append(data.data(), *bytes_consumed);
DCHECK_LE(string->size(), string_length_);
if (string->size() == string_length_) {
state_ = State::kReadStringDone;
}
- return bytes_consumed;
+ return true;
}
-void QpackInstructionDecoder::DoReadStringDone() {
+bool QpackInstructionDecoder::DoReadStringDone() {
DCHECK(field_->type == QpackInstructionFieldType::kName ||
field_->type == QpackInstructionFieldType::kValue);
@@ -285,13 +298,14 @@ void QpackInstructionDecoder::DoReadStringDone() {
huffman_decoder_.Decode(*string, &decoded_value);
if (!huffman_decoder_.InputProperlyTerminated()) {
OnError("Error in Huffman-encoded string.");
- return;
+ return false;
}
*string = std::move(decoded_value);
}
++field_;
state_ = State::kStartField;
+ return true;
}
const QpackInstruction* QpackInstructionDecoder::LookupOpcode(
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.h
index f478c249b07..4c217731a92 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.h
@@ -11,7 +11,7 @@
#include "net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder.h"
#include "net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
@@ -33,11 +33,15 @@ class QUIC_EXPORT_PRIVATE QpackInstructionDecoder {
// Returns true if decoded fields are valid.
// Returns false otherwise, in which case QpackInstructionDecoder stops
// decoding: Delegate methods will not be called, and Decode() must not be
- // called.
+ // called. Implementations are allowed to destroy the
+ // QpackInstructionDecoder instance synchronously if OnInstructionDecoded()
+ // returns false.
virtual bool OnInstructionDecoded(const QpackInstruction* instruction) = 0;
// Called by QpackInstructionDecoder if an error has occurred.
// No more data is processed afterwards.
+ // Implementations are allowed to destroy the QpackInstructionDecoder
+ // instance synchronously.
virtual void OnError(QuicStringPiece error_message) = 0;
};
@@ -48,8 +52,9 @@ class QUIC_EXPORT_PRIVATE QpackInstructionDecoder {
QpackInstructionDecoder& operator=(const QpackInstructionDecoder&) = delete;
// Provide a data fragment to decode. Must not be called after an error has
- // occurred. Must not be called with empty |data|.
- void Decode(QuicStringPiece data);
+ // occurred. Must not be called with empty |data|. Return true on success,
+ // false on error (in which case Delegate::OnError() is called synchronously).
+ bool Decode(QuicStringPiece data);
// Returns true if no decoding has taken place yet or if the last instruction
// has been entirely parsed.
@@ -84,18 +89,19 @@ class QUIC_EXPORT_PRIVATE QpackInstructionDecoder {
kReadStringDone
};
- // One method for each state. Some take input data and return the number of
- // octets processed. Some take input data but do have void return type
- // because they not consume any bytes. Some do not take any arguments because
- // they only change internal state.
- void DoStartInstruction(QuicStringPiece data);
- void DoStartField();
- void DoReadBit(QuicStringPiece data);
- size_t DoVarintStart(QuicStringPiece data);
- size_t DoVarintResume(QuicStringPiece data);
- void DoVarintDone();
- size_t DoReadString(QuicStringPiece data);
- void DoReadStringDone();
+ // One method for each state. They each return true on success, false on
+ // error (in which case |this| might already be destroyed). Some take input
+ // data and set |*bytes_consumed| to the number of octets processed. Some
+ // take input data but do not consume any bytes. Some do not take any
+ // arguments because they only change internal state.
+ bool DoStartInstruction(QuicStringPiece data);
+ bool DoStartField();
+ bool DoReadBit(QuicStringPiece data);
+ bool DoVarintStart(QuicStringPiece data, size_t* bytes_consumed);
+ bool DoVarintResume(QuicStringPiece data, size_t* bytes_consumed);
+ bool DoVarintDone();
+ bool DoReadString(QuicStringPiece data, size_t* bytes_consumed);
+ bool DoReadStringDone();
// Identify instruction based on opcode encoded in |byte|.
// Returns a pointer to an element of |*language_|.
@@ -127,8 +133,8 @@ class QUIC_EXPORT_PRIVATE QpackInstructionDecoder {
// Decoder instance for decoding Huffman encoded strings.
http2::HpackHuffmanDecoder huffman_decoder_;
- // True if a decoding error has been detected either by
- // QpackInstructionDecoder or by Delegate.
+ // True if a decoding error has been detected by QpackInstructionDecoder.
+ // Only used in DCHECKs.
bool error_detected_;
// Decoding state.
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder_test.cc
index 2d57f5c5320..c066827d295 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder_test.cc
@@ -6,15 +6,16 @@
#include <algorithm>
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
using ::testing::_;
using ::testing::Eq;
using ::testing::Expectation;
+using ::testing::Invoke;
using ::testing::Return;
using ::testing::StrictMock;
using ::testing::Values;
@@ -64,36 +65,52 @@ class MockDelegate : public QpackInstructionDecoder::Delegate {
};
class QpackInstructionDecoderTest : public QuicTestWithParam<FragmentMode> {
- public:
+ protected:
QpackInstructionDecoderTest()
- : decoder_(TestLanguage(), &delegate_), fragment_mode_(GetParam()) {}
+ : decoder_(std::make_unique<QpackInstructionDecoder>(TestLanguage(),
+ &delegate_)),
+ fragment_mode_(GetParam()) {}
~QpackInstructionDecoderTest() override = default;
- protected:
+ void SetUp() override {
+ // Destroy QpackInstructionDecoder on error to test that it does not crash.
+ // See https://crbug.com/1025209.
+ ON_CALL(delegate_, OnError(_))
+ .WillByDefault(Invoke(
+ [this](QuicStringPiece /* error_message */) { decoder_.reset(); }));
+ }
+
// Decode one full instruction with fragment sizes dictated by
// |fragment_mode_|.
- // Verifies that AtInstructionBoundary() returns true before and after the
+ // Assumes that |data| is a single complete instruction, and accordingly
+ // verifies that AtInstructionBoundary() returns true before and after the
// instruction, and returns false while decoding is in progress.
+ // Assumes that delegate methods destroy |decoder_| if they return false.
void DecodeInstruction(QuicStringPiece data) {
- EXPECT_TRUE(decoder_.AtInstructionBoundary());
+ EXPECT_TRUE(decoder_->AtInstructionBoundary());
FragmentSizeGenerator fragment_size_generator =
FragmentModeToFragmentSizeGenerator(fragment_mode_);
while (!data.empty()) {
size_t fragment_size = std::min(fragment_size_generator(), data.size());
- decoder_.Decode(data.substr(0, fragment_size));
+ bool success = decoder_->Decode(data.substr(0, fragment_size));
+ if (!decoder_) {
+ EXPECT_FALSE(success);
+ return;
+ }
+ EXPECT_TRUE(success);
data = data.substr(fragment_size);
if (!data.empty()) {
- EXPECT_FALSE(decoder_.AtInstructionBoundary());
+ EXPECT_FALSE(decoder_->AtInstructionBoundary());
}
}
- EXPECT_TRUE(decoder_.AtInstructionBoundary());
+ EXPECT_TRUE(decoder_->AtInstructionBoundary());
}
StrictMock<MockDelegate> delegate_;
- QpackInstructionDecoder decoder_;
+ std::unique_ptr<QpackInstructionDecoder> decoder_;
private:
const FragmentMode fragment_mode_;
@@ -108,60 +125,82 @@ TEST_P(QpackInstructionDecoderTest, SBitAndVarint2) {
EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction1()));
DecodeInstruction(QuicTextUtils::HexDecode("7f01ff65"));
- EXPECT_TRUE(decoder_.s_bit());
- EXPECT_EQ(64u, decoder_.varint());
- EXPECT_EQ(356u, decoder_.varint2());
+ EXPECT_TRUE(decoder_->s_bit());
+ EXPECT_EQ(64u, decoder_->varint());
+ EXPECT_EQ(356u, decoder_->varint2());
EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction1()));
DecodeInstruction(QuicTextUtils::HexDecode("05c8"));
- EXPECT_FALSE(decoder_.s_bit());
- EXPECT_EQ(5u, decoder_.varint());
- EXPECT_EQ(200u, decoder_.varint2());
+ EXPECT_FALSE(decoder_->s_bit());
+ EXPECT_EQ(5u, decoder_->varint());
+ EXPECT_EQ(200u, decoder_->varint2());
}
TEST_P(QpackInstructionDecoderTest, NameAndValue) {
EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction2()));
DecodeInstruction(QuicTextUtils::HexDecode("83666f6f03626172"));
- EXPECT_EQ("foo", decoder_.name());
- EXPECT_EQ("bar", decoder_.value());
+ EXPECT_EQ("foo", decoder_->name());
+ EXPECT_EQ("bar", decoder_->value());
EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction2()));
DecodeInstruction(QuicTextUtils::HexDecode("8000"));
- EXPECT_EQ("", decoder_.name());
- EXPECT_EQ("", decoder_.value());
+ EXPECT_EQ("", decoder_->name());
+ EXPECT_EQ("", decoder_->value());
EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction2()));
DecodeInstruction(QuicTextUtils::HexDecode("c294e7838c767f"));
- EXPECT_EQ("foo", decoder_.name());
- EXPECT_EQ("bar", decoder_.value());
+ EXPECT_EQ("foo", decoder_->name());
+ EXPECT_EQ("bar", decoder_->value());
}
TEST_P(QpackInstructionDecoderTest, InvalidHuffmanEncoding) {
EXPECT_CALL(delegate_, OnError(Eq("Error in Huffman-encoded string.")));
- decoder_.Decode(QuicTextUtils::HexDecode("c1ff"));
+ DecodeInstruction(QuicTextUtils::HexDecode("c1ff"));
}
TEST_P(QpackInstructionDecoderTest, InvalidVarintEncoding) {
EXPECT_CALL(delegate_, OnError(Eq("Encoded integer too large.")));
- decoder_.Decode(QuicTextUtils::HexDecode("ffffffffffffffffffffff"));
+ DecodeInstruction(QuicTextUtils::HexDecode("ffffffffffffffffffffff"));
}
TEST_P(QpackInstructionDecoderTest, DelegateSignalsError) {
// First instruction is valid.
Expectation first_call =
EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction1()))
- .WillOnce(Return(true));
+ .WillOnce(Invoke(
+ [this](const QpackInstruction * /* instruction */) -> bool {
+ EXPECT_EQ(1u, decoder_->varint());
+ return true;
+ }));
+
// Second instruction is invalid. Decoding must halt.
EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction1()))
.After(first_call)
- .WillOnce(Return(false));
- decoder_.Decode(QuicTextUtils::HexDecode("01000200030004000500"));
+ .WillOnce(
+ Invoke([this](const QpackInstruction * /* instruction */) -> bool {
+ EXPECT_EQ(2u, decoder_->varint());
+ return false;
+ }));
+
+ EXPECT_FALSE(
+ decoder_->Decode(QuicTextUtils::HexDecode("01000200030004000500")));
+}
- EXPECT_EQ(2u, decoder_.varint());
+// QpackInstructionDecoder must not crash if it is destroyed from a
+// Delegate::OnInstructionDecoded() call as long as it returns false.
+TEST_P(QpackInstructionDecoderTest, DelegateSignalsErrorAndDestroysDecoder) {
+ EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction1()))
+ .WillOnce(
+ Invoke([this](const QpackInstruction * /* instruction */) -> bool {
+ EXPECT_EQ(1u, decoder_->varint());
+ decoder_.reset();
+ return false;
+ }));
+ DecodeInstruction(QuicTextUtils::HexDecode("0100"));
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.cc
index 5845a748ffc..a87489d9e67 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.cc
@@ -16,13 +16,13 @@ namespace quic {
QpackInstructionEncoder::QpackInstructionEncoder()
: byte_(0), state_(State::kOpcode), instruction_(nullptr) {}
-void QpackInstructionEncoder::Encode(const QpackInstruction* instruction,
- const Values& values,
- std::string* output) {
- DCHECK(instruction);
+void QpackInstructionEncoder::Encode(
+ const QpackInstructionWithValues& instruction_with_values,
+ std::string* output) {
+ DCHECK(instruction_with_values.instruction());
state_ = State::kOpcode;
- instruction_ = instruction;
+ instruction_ = instruction_with_values.instruction();
field_ = instruction_->fields.begin();
// Field list must not be empty.
@@ -37,13 +37,15 @@ void QpackInstructionEncoder::Encode(const QpackInstruction* instruction,
DoStartField();
break;
case State::kSbit:
- DoSBit(values.s_bit);
+ DoSBit(instruction_with_values.s_bit());
break;
case State::kVarintEncode:
- DoVarintEncode(values.varint, values.varint2, output);
+ DoVarintEncode(instruction_with_values.varint(),
+ instruction_with_values.varint2(), output);
break;
case State::kStartString:
- DoStartString(values.name, values.value);
+ DoStartString(instruction_with_values.name(),
+ instruction_with_values.value());
break;
case State::kWriteString:
DoWriteString(output);
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.h
index 1ca52e667ec..04b2888172e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.h
@@ -8,7 +8,7 @@
#include <cstdint>
#include <string>
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
@@ -19,23 +19,12 @@ namespace quic {
// fields that follow each instruction.
class QUIC_EXPORT_PRIVATE QpackInstructionEncoder {
public:
- // Storage for field values to be encoded.
- // The encoded instruction determines which values are actually used.
- struct Values {
- bool s_bit;
- uint64_t varint;
- uint64_t varint2;
- QuicStringPiece name;
- QuicStringPiece value;
- };
-
QpackInstructionEncoder();
QpackInstructionEncoder(const QpackInstructionEncoder&) = delete;
QpackInstructionEncoder& operator=(const QpackInstructionEncoder&) = delete;
// Append encoded instruction to |output|.
- void Encode(const QpackInstruction* instruction,
- const Values& values,
+ void Encode(const QpackInstructionWithValues& instruction_with_values,
std::string* output);
private:
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder_test.cc
index 0d172cd6847..79dfe2af379 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder_test.cc
@@ -8,10 +8,44 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
-using ::testing::Values;
-
namespace quic {
namespace test {
+
+class QpackInstructionWithValuesPeer {
+ public:
+ static QpackInstructionWithValues CreateQpackInstructionWithValues(
+ const QpackInstruction* instruction) {
+ QpackInstructionWithValues instruction_with_values;
+ instruction_with_values.instruction_ = instruction;
+ return instruction_with_values;
+ }
+
+ static void set_s_bit(QpackInstructionWithValues* instruction_with_values,
+ bool s_bit) {
+ instruction_with_values->s_bit_ = s_bit;
+ }
+
+ static void set_varint(QpackInstructionWithValues* instruction_with_values,
+ uint64_t varint) {
+ instruction_with_values->varint_ = varint;
+ }
+
+ static void set_varint2(QpackInstructionWithValues* instruction_with_values,
+ uint64_t varint2) {
+ instruction_with_values->varint2_ = varint2;
+ }
+
+ static void set_name(QpackInstructionWithValues* instruction_with_values,
+ QuicStringPiece name) {
+ instruction_with_values->name_ = name;
+ }
+
+ static void set_value(QpackInstructionWithValues* instruction_with_values,
+ QuicStringPiece value) {
+ instruction_with_values->value_ = value;
+ }
+};
+
namespace {
class QpackInstructionEncoderTest : public QuicTest {
@@ -20,9 +54,9 @@ class QpackInstructionEncoderTest : public QuicTest {
~QpackInstructionEncoderTest() override = default;
// Append encoded |instruction| to |output_|.
- void EncodeInstruction(const QpackInstruction* instruction,
- const QpackInstructionEncoder::Values& values) {
- encoder_.Encode(instruction, values, &output_);
+ void EncodeInstruction(
+ const QpackInstructionWithValues& instruction_with_values) {
+ encoder_.Encode(instruction_with_values, &output_);
}
// Compare substring appended to |output_| since last EncodedSegmentMatches()
@@ -44,13 +78,15 @@ TEST_F(QpackInstructionEncoderTest, Varint) {
const QpackInstruction instruction{QpackInstructionOpcode{0x00, 0x80},
{{QpackInstructionFieldType::kVarint, 7}}};
- QpackInstructionEncoder::Values values;
- values.varint = 5;
- EncodeInstruction(&instruction, values);
+ auto instruction_with_values =
+ QpackInstructionWithValuesPeer::CreateQpackInstructionWithValues(
+ &instruction);
+ QpackInstructionWithValuesPeer::set_varint(&instruction_with_values, 5);
+ EncodeInstruction(instruction_with_values);
EXPECT_TRUE(EncodedSegmentMatches("05"));
- values.varint = 127;
- EncodeInstruction(&instruction, values);
+ QpackInstructionWithValuesPeer::set_varint(&instruction_with_values, 127);
+ EncodeInstruction(instruction_with_values);
EXPECT_TRUE(EncodedSegmentMatches("7f00"));
}
@@ -61,17 +97,19 @@ TEST_F(QpackInstructionEncoderTest, SBitAndTwoVarint2) {
{QpackInstructionFieldType::kVarint, 5},
{QpackInstructionFieldType::kVarint2, 8}}};
- QpackInstructionEncoder::Values values;
- values.s_bit = true;
- values.varint = 5;
- values.varint2 = 200;
- EncodeInstruction(&instruction, values);
+ auto instruction_with_values =
+ QpackInstructionWithValuesPeer::CreateQpackInstructionWithValues(
+ &instruction);
+ QpackInstructionWithValuesPeer::set_s_bit(&instruction_with_values, true);
+ QpackInstructionWithValuesPeer::set_varint(&instruction_with_values, 5);
+ QpackInstructionWithValuesPeer::set_varint2(&instruction_with_values, 200);
+ EncodeInstruction(instruction_with_values);
EXPECT_TRUE(EncodedSegmentMatches("a5c8"));
- values.s_bit = false;
- values.varint = 31;
- values.varint2 = 356;
- EncodeInstruction(&instruction, values);
+ QpackInstructionWithValuesPeer::set_s_bit(&instruction_with_values, false);
+ QpackInstructionWithValuesPeer::set_varint(&instruction_with_values, 31);
+ QpackInstructionWithValuesPeer::set_varint2(&instruction_with_values, 356);
+ EncodeInstruction(instruction_with_values);
EXPECT_TRUE(EncodedSegmentMatches("9f00ff65"));
}
@@ -81,17 +119,19 @@ TEST_F(QpackInstructionEncoderTest, SBitAndVarintAndValue) {
{QpackInstructionFieldType::kVarint, 5},
{QpackInstructionFieldType::kValue, 7}}};
- QpackInstructionEncoder::Values values;
- values.s_bit = true;
- values.varint = 100;
- values.value = "foo";
- EncodeInstruction(&instruction, values);
+ auto instruction_with_values =
+ QpackInstructionWithValuesPeer::CreateQpackInstructionWithValues(
+ &instruction);
+ QpackInstructionWithValuesPeer::set_s_bit(&instruction_with_values, true);
+ QpackInstructionWithValuesPeer::set_varint(&instruction_with_values, 100);
+ QpackInstructionWithValuesPeer::set_value(&instruction_with_values, "foo");
+ EncodeInstruction(instruction_with_values);
EXPECT_TRUE(EncodedSegmentMatches("ff458294e7"));
- values.s_bit = false;
- values.varint = 3;
- values.value = "bar";
- EncodeInstruction(&instruction, values);
+ QpackInstructionWithValuesPeer::set_s_bit(&instruction_with_values, false);
+ QpackInstructionWithValuesPeer::set_varint(&instruction_with_values, 3);
+ QpackInstructionWithValuesPeer::set_value(&instruction_with_values, "bar");
+ EncodeInstruction(instruction_with_values);
EXPECT_TRUE(EncodedSegmentMatches("c303626172"));
}
@@ -99,17 +139,19 @@ TEST_F(QpackInstructionEncoderTest, Name) {
const QpackInstruction instruction{QpackInstructionOpcode{0xe0, 0xe0},
{{QpackInstructionFieldType::kName, 4}}};
- QpackInstructionEncoder::Values values;
- values.name = "";
- EncodeInstruction(&instruction, values);
+ auto instruction_with_values =
+ QpackInstructionWithValuesPeer::CreateQpackInstructionWithValues(
+ &instruction);
+ QpackInstructionWithValuesPeer::set_name(&instruction_with_values, "");
+ EncodeInstruction(instruction_with_values);
EXPECT_TRUE(EncodedSegmentMatches("e0"));
- values.name = "foo";
- EncodeInstruction(&instruction, values);
+ QpackInstructionWithValuesPeer::set_name(&instruction_with_values, "foo");
+ EncodeInstruction(instruction_with_values);
EXPECT_TRUE(EncodedSegmentMatches("f294e7"));
- values.name = "bar";
- EncodeInstruction(&instruction, values);
+ QpackInstructionWithValuesPeer::set_name(&instruction_with_values, "bar");
+ EncodeInstruction(instruction_with_values);
EXPECT_TRUE(EncodedSegmentMatches("e3626172"));
}
@@ -117,17 +159,19 @@ TEST_F(QpackInstructionEncoderTest, Value) {
const QpackInstruction instruction{QpackInstructionOpcode{0xf0, 0xf0},
{{QpackInstructionFieldType::kValue, 3}}};
- QpackInstructionEncoder::Values values;
- values.value = "";
- EncodeInstruction(&instruction, values);
+ auto instruction_with_values =
+ QpackInstructionWithValuesPeer::CreateQpackInstructionWithValues(
+ &instruction);
+ QpackInstructionWithValuesPeer::set_value(&instruction_with_values, "");
+ EncodeInstruction(instruction_with_values);
EXPECT_TRUE(EncodedSegmentMatches("f0"));
- values.value = "foo";
- EncodeInstruction(&instruction, values);
+ QpackInstructionWithValuesPeer::set_value(&instruction_with_values, "foo");
+ EncodeInstruction(instruction_with_values);
EXPECT_TRUE(EncodedSegmentMatches("fa94e7"));
- values.value = "bar";
- EncodeInstruction(&instruction, values);
+ QpackInstructionWithValuesPeer::set_value(&instruction_with_values, "bar");
+ EncodeInstruction(instruction_with_values);
EXPECT_TRUE(EncodedSegmentMatches("f3626172"));
}
@@ -137,17 +181,19 @@ TEST_F(QpackInstructionEncoderTest, SBitAndNameAndValue) {
{QpackInstructionFieldType::kName, 2},
{QpackInstructionFieldType::kValue, 7}}};
- QpackInstructionEncoder::Values values;
- values.s_bit = false;
- values.name = "";
- values.value = "";
- EncodeInstruction(&instruction, values);
+ auto instruction_with_values =
+ QpackInstructionWithValuesPeer::CreateQpackInstructionWithValues(
+ &instruction);
+ QpackInstructionWithValuesPeer::set_s_bit(&instruction_with_values, false);
+ QpackInstructionWithValuesPeer::set_name(&instruction_with_values, "");
+ QpackInstructionWithValuesPeer::set_value(&instruction_with_values, "");
+ EncodeInstruction(instruction_with_values);
EXPECT_TRUE(EncodedSegmentMatches("f000"));
- values.s_bit = true;
- values.name = "foo";
- values.value = "bar";
- EncodeInstruction(&instruction, values);
+ QpackInstructionWithValuesPeer::set_s_bit(&instruction_with_values, true);
+ QpackInstructionWithValuesPeer::set_name(&instruction_with_values, "foo");
+ QpackInstructionWithValuesPeer::set_value(&instruction_with_values, "bar");
+ EncodeInstruction(instruction_with_values);
EXPECT_TRUE(EncodedSegmentMatches("fe94e703626172"));
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_constants.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instructions.cc
index 6644918b34a..a6a7529bf09 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_constants.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instructions.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
#include <limits>
@@ -199,4 +199,133 @@ const QpackLanguage* QpackRequestStreamLanguage() {
return language;
}
+// static
+QpackInstructionWithValues QpackInstructionWithValues::InsertWithNameReference(
+ bool is_static,
+ uint64_t name_index,
+ QuicStringPiece value) {
+ QpackInstructionWithValues instruction_with_values;
+ instruction_with_values.instruction_ = InsertWithNameReferenceInstruction();
+ instruction_with_values.s_bit_ = is_static;
+ instruction_with_values.varint_ = name_index;
+ instruction_with_values.value_ = value;
+
+ return instruction_with_values;
+}
+
+// static
+QpackInstructionWithValues
+QpackInstructionWithValues::InsertWithoutNameReference(QuicStringPiece name,
+ QuicStringPiece value) {
+ QpackInstructionWithValues instruction_with_values;
+ instruction_with_values.instruction_ =
+ InsertWithoutNameReferenceInstruction();
+ instruction_with_values.name_ = name;
+ instruction_with_values.value_ = value;
+
+ return instruction_with_values;
+}
+
+// static
+QpackInstructionWithValues QpackInstructionWithValues::Duplicate(
+ uint64_t index) {
+ QpackInstructionWithValues instruction_with_values;
+ instruction_with_values.instruction_ = DuplicateInstruction();
+ instruction_with_values.varint_ = index;
+
+ return instruction_with_values;
+}
+
+// static
+QpackInstructionWithValues QpackInstructionWithValues::SetDynamicTableCapacity(
+ uint64_t capacity) {
+ QpackInstructionWithValues instruction_with_values;
+ instruction_with_values.instruction_ = SetDynamicTableCapacityInstruction();
+ instruction_with_values.varint_ = capacity;
+
+ return instruction_with_values;
+}
+
+// static
+QpackInstructionWithValues QpackInstructionWithValues::InsertCountIncrement(
+ uint64_t increment) {
+ QpackInstructionWithValues instruction_with_values;
+ instruction_with_values.instruction_ = InsertCountIncrementInstruction();
+ instruction_with_values.varint_ = increment;
+
+ return instruction_with_values;
+}
+
+// static
+QpackInstructionWithValues QpackInstructionWithValues::HeaderAcknowledgement(
+ uint64_t stream_id) {
+ QpackInstructionWithValues instruction_with_values;
+ instruction_with_values.instruction_ = HeaderAcknowledgementInstruction();
+ instruction_with_values.varint_ = stream_id;
+
+ return instruction_with_values;
+}
+
+// static
+QpackInstructionWithValues QpackInstructionWithValues::StreamCancellation(
+ uint64_t stream_id) {
+ QpackInstructionWithValues instruction_with_values;
+ instruction_with_values.instruction_ = StreamCancellationInstruction();
+ instruction_with_values.varint_ = stream_id;
+
+ return instruction_with_values;
+}
+
+// static
+QpackInstructionWithValues QpackInstructionWithValues::Prefix(
+ uint64_t required_insert_count) {
+ QpackInstructionWithValues instruction_with_values;
+ instruction_with_values.instruction_ = QpackPrefixInstruction();
+ instruction_with_values.varint_ = required_insert_count;
+ instruction_with_values.varint2_ = 0; // Delta Base.
+ instruction_with_values.s_bit_ = false; // Delta Base sign.
+
+ return instruction_with_values;
+}
+
+// static
+QpackInstructionWithValues QpackInstructionWithValues::IndexedHeaderField(
+ bool is_static,
+ uint64_t index) {
+ QpackInstructionWithValues instruction_with_values;
+ instruction_with_values.instruction_ = QpackIndexedHeaderFieldInstruction();
+ instruction_with_values.s_bit_ = is_static;
+ instruction_with_values.varint_ = index;
+
+ return instruction_with_values;
+}
+
+// static
+QpackInstructionWithValues
+QpackInstructionWithValues::LiteralHeaderFieldNameReference(
+ bool is_static,
+ uint64_t index,
+ QuicStringPiece value) {
+ QpackInstructionWithValues instruction_with_values;
+ instruction_with_values.instruction_ =
+ QpackLiteralHeaderFieldNameReferenceInstruction();
+ instruction_with_values.s_bit_ = is_static;
+ instruction_with_values.varint_ = index;
+ instruction_with_values.value_ = value;
+
+ return instruction_with_values;
+}
+
+// static
+QpackInstructionWithValues QpackInstructionWithValues::LiteralHeaderField(
+ QuicStringPiece name,
+ QuicStringPiece value) {
+ QpackInstructionWithValues instruction_with_values;
+ instruction_with_values.instruction_ = QpackLiteralHeaderFieldInstruction();
+ instruction_with_values.name_ = name;
+ instruction_with_values.value_ = value;
+
+ return instruction_with_values;
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_constants.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h
index 35e4d560bef..0ff18bff254 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_constants.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef QUICHE_QUIC_CORE_QPACK_QPACK_CONSTANTS_H_
-#define QUICHE_QUIC_CORE_QPACK_QPACK_CONSTANTS_H_
+#ifndef QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTIONS_H_
+#define QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTIONS_H_
#include <cstdint>
#include <string>
@@ -11,9 +11,14 @@
#include <vector>
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
namespace quic {
+namespace test {
+class QpackInstructionWithValuesPeer;
+} // namespace test
+
// Each instruction is identified with an opcode in the first byte.
// |mask| determines which bits are part of the opcode.
// |value| is the value of these bits. (Other bits in value must be zero.)
@@ -137,6 +142,66 @@ const QpackInstruction* QpackLiteralHeaderFieldInstruction();
// Request and push stream language.
const QpackLanguage* QpackRequestStreamLanguage();
+// Storage for instruction and field values to be encoded.
+// This class can only be instantiated using factory methods that take exactly
+// the arguments that the corresponding instruction needs.
+class QUIC_EXPORT_PRIVATE QpackInstructionWithValues {
+ public:
+ // 5.2 Encoder stream instructions
+ static QpackInstructionWithValues InsertWithNameReference(
+ bool is_static,
+ uint64_t name_index,
+ QuicStringPiece value);
+ static QpackInstructionWithValues InsertWithoutNameReference(
+ QuicStringPiece name,
+ QuicStringPiece value);
+ static QpackInstructionWithValues Duplicate(uint64_t index);
+ static QpackInstructionWithValues SetDynamicTableCapacity(uint64_t capacity);
+
+ // 5.3 Decoder stream instructions
+ static QpackInstructionWithValues InsertCountIncrement(uint64_t increment);
+ static QpackInstructionWithValues HeaderAcknowledgement(uint64_t stream_id);
+ static QpackInstructionWithValues StreamCancellation(uint64_t stream_id);
+
+ // 5.4.1. Header data prefix. Delta Base is hardcoded to be zero.
+ static QpackInstructionWithValues Prefix(uint64_t required_insert_count);
+
+ // 5.4.2. Request and push stream instructions
+ static QpackInstructionWithValues IndexedHeaderField(bool is_static,
+ uint64_t index);
+ static QpackInstructionWithValues LiteralHeaderFieldNameReference(
+ bool is_static,
+ uint64_t index,
+ QuicStringPiece value);
+ static QpackInstructionWithValues LiteralHeaderField(QuicStringPiece name,
+ QuicStringPiece value);
+
+ const QpackInstruction* instruction() const { return instruction_; }
+ bool s_bit() const { return s_bit_; }
+ uint64_t varint() const { return varint_; }
+ uint64_t varint2() const { return varint2_; }
+ QuicStringPiece name() const { return name_; }
+ QuicStringPiece value() const { return value_; }
+
+ // Used by QpackEncoder, because in the first pass it stores absolute indices,
+ // which are converted into relative indices in the second pass after base is
+ // determined.
+ void set_varint(uint64_t varint) { varint_ = varint; }
+
+ private:
+ friend test::QpackInstructionWithValuesPeer;
+
+ QpackInstructionWithValues() = default;
+
+ // |*instruction| is not owned.
+ const QpackInstruction* instruction_;
+ bool s_bit_;
+ uint64_t varint_;
+ uint64_t varint2_;
+ QuicStringPiece name_;
+ QuicStringPiece value_;
+};
+
} // namespace quic
-#endif // QUICHE_QUIC_CORE_QPACK_QPACK_CONSTANTS_H_
+#endif // QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTIONS_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/offline/qpack_offline_decoder_bin.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_offline_decoder_bin.cc
index d72b0003da4..327816e8cb2 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/offline/qpack_offline_decoder_bin.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_offline_decoder_bin.cc
@@ -2,14 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/third_party/quiche/src/quic/core/qpack/offline/qpack_offline_decoder.h"
-
#include <cstddef>
#include <iostream>
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.h"
int main(int argc, char* argv[]) {
const char* usage =
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.cc
index 3c0b0f546fa..c9e19d2d013 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.cc
@@ -8,8 +8,8 @@
#include <limits>
#include <utility>
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_index_conversions.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_instructions.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_required_insert_count.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
@@ -57,11 +57,13 @@ void QpackProgressiveDecoder::Decode(QuicStringPiece data) {
while (!prefix_decoded_) {
DCHECK(!blocked_);
- prefix_decoder_->Decode(data.substr(0, 1));
- if (error_detected_) {
+ if (!prefix_decoder_->Decode(data.substr(0, 1))) {
return;
}
+ // |prefix_decoder_->Decode()| must return false if an error is detected.
+ DCHECK(!error_detected_);
+
data = data.substr(1);
if (data.empty()) {
return;
@@ -115,20 +117,28 @@ void QpackProgressiveDecoder::OnError(QuicStringPiece error_message) {
DCHECK(!error_detected_);
error_detected_ = true;
+ // Might destroy |this|.
handler_->OnDecodingErrorDetected(error_message);
}
void QpackProgressiveDecoder::OnInsertCountReachedThreshold() {
DCHECK(blocked_);
+ // Clear |blocked_| before calling instruction_decoder_.Decode() below,
+ // because that might destroy |this| and ~QpackProgressiveDecoder() needs to
+ // know not to call UnregisterObserver().
+ blocked_ = false;
+ enforcer_->OnStreamUnblocked(stream_id_);
+
if (!buffer_.empty()) {
- instruction_decoder_.Decode(buffer_);
+ std::string buffer(std::move(buffer_));
buffer_.clear();
+ if (!instruction_decoder_.Decode(buffer)) {
+ // |this| might be destroyed.
+ return;
+ }
}
- blocked_ = false;
- enforcer_->OnStreamUnblocked(stream_id_);
-
if (!decoding_) {
FinishDecoding();
}
@@ -163,6 +173,7 @@ bool QpackProgressiveDecoder::DoIndexedHeaderFieldInstruction() {
return false;
}
+ header_table_->set_dynamic_table_entry_referenced();
handler_->OnHeaderDecoded(entry->name(), entry->value());
return true;
}
@@ -202,6 +213,7 @@ bool QpackProgressiveDecoder::DoIndexedHeaderFieldPostBaseInstruction() {
return false;
}
+ header_table_->set_dynamic_table_entry_referenced();
handler_->OnHeaderDecoded(entry->name(), entry->value());
return true;
}
@@ -231,6 +243,7 @@ bool QpackProgressiveDecoder::DoLiteralHeaderFieldNameReferenceInstruction() {
return false;
}
+ header_table_->set_dynamic_table_entry_referenced();
handler_->OnHeaderDecoded(entry->name(), instruction_decoder_.value());
return true;
}
@@ -270,6 +283,7 @@ bool QpackProgressiveDecoder::DoLiteralHeaderFieldPostBaseInstruction() {
return false;
}
+ header_table_->set_dynamic_table_entry_referenced();
handler_->OnHeaderDecoded(entry->name(), instruction_decoder_.value());
return true;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.h
index 2f306c8e19c..6599c1a3ff8 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.h
@@ -44,7 +44,8 @@ class QUIC_EXPORT_PRIVATE QpackProgressiveDecoder
virtual void OnDecodingCompleted() = 0;
// Called when a decoding error has occurred. No other methods will be
- // called afterwards.
+ // called afterwards. Implementations are allowed to destroy
+ // the QpackProgressiveDecoder instance synchronously.
virtual void OnDecodingErrorDetected(QuicStringPiece error_message) = 0;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_round_trip_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_round_trip_test.cc
index 567676c75d2..f0dc797fa3b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_round_trip_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_round_trip_test.cc
@@ -5,15 +5,13 @@
#include <string>
#include <tuple>
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test_utils.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
-using ::testing::Combine;
using ::testing::Values;
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_utils.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_utils.h
deleted file mode 100644
index 1b63422d4ac..00000000000
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_utils.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_QUIC_CORE_QPACK_QPACK_UTILS_H_
-#define QUICHE_QUIC_CORE_QPACK_QPACK_UTILS_H_
-
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_stream_sender_delegate.h"
-
-namespace quic {
-// TODO(renjietang): Move this class to qpack_test_utils.h once it is not needed
-// in QuicSpdySession.
-class QUIC_EXPORT_PRIVATE NoopQpackStreamSenderDelegate
- : public QpackStreamSenderDelegate {
- public:
- ~NoopQpackStreamSenderDelegate() override = default;
-
- void WriteStreamData(QuicStringPiece /*data*/) override {}
-};
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_CORE_QPACK_QPACK_UTILS_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list_test.cc
index 03a5eb03def..bab52386512 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list_test.cc
@@ -60,10 +60,16 @@ TEST(ValueSplittingHeaderListTest, Comparison) {
EXPECT_FALSE(it1 == it2);
EXPECT_TRUE(it1 != it2);
}
- ++it2;
+ if (j < kEnd - 1) {
+ ASSERT_NE(it2, headers.end());
+ ++it2;
+ }
}
- ++it1;
+ if (i < kEnd - 1) {
+ ASSERT_NE(it1, headers.end());
+ ++it1;
+ }
}
}
@@ -75,37 +81,37 @@ TEST(ValueSplittingHeaderListTest, Empty) {
EXPECT_EQ(headers.begin(), headers.end());
}
-struct {
- const char* name;
- QuicStringPiece value;
- std::vector<const char*> expected_values;
-} kTestData[]{
- // Empty value.
- {"foo", "", {""}},
- // Trivial case.
- {"foo", "bar", {"bar"}},
- // Simple split.
- {"foo", {"bar\0baz", 7}, {"bar", "baz"}},
- {"cookie", "foo;bar", {"foo", "bar"}},
- {"cookie", "foo; bar", {"foo", "bar"}},
- // Empty fragments with \0 separator.
- {"foo", {"\0", 1}, {"", ""}},
- {"bar", {"foo\0", 4}, {"foo", ""}},
- {"baz", {"\0bar", 4}, {"", "bar"}},
- {"qux", {"\0foobar\0", 8}, {"", "foobar", ""}},
- // Empty fragments with ";" separator.
- {"cookie", ";", {"", ""}},
- {"cookie", "foo;", {"foo", ""}},
- {"cookie", ";bar", {"", "bar"}},
- {"cookie", ";foobar;", {"", "foobar", ""}},
- // Empty fragments with "; " separator.
- {"cookie", "; ", {"", ""}},
- {"cookie", "foo; ", {"foo", ""}},
- {"cookie", "; bar", {"", "bar"}},
- {"cookie", "; foobar; ", {"", "foobar", ""}},
-};
-
TEST(ValueSplittingHeaderListTest, Split) {
+ struct {
+ const char* name;
+ QuicStringPiece value;
+ std::vector<const char*> expected_values;
+ } kTestData[]{
+ // Empty value.
+ {"foo", "", {""}},
+ // Trivial case.
+ {"foo", "bar", {"bar"}},
+ // Simple split.
+ {"foo", {"bar\0baz", 7}, {"bar", "baz"}},
+ {"cookie", "foo;bar", {"foo", "bar"}},
+ {"cookie", "foo; bar", {"foo", "bar"}},
+ // Empty fragments with \0 separator.
+ {"foo", {"\0", 1}, {"", ""}},
+ {"bar", {"foo\0", 4}, {"foo", ""}},
+ {"baz", {"\0bar", 4}, {"", "bar"}},
+ {"qux", {"\0foobar\0", 8}, {"", "foobar", ""}},
+ // Empty fragments with ";" separator.
+ {"cookie", ";", {"", ""}},
+ {"cookie", "foo;", {"foo", ""}},
+ {"cookie", ";bar", {"", "bar"}},
+ {"cookie", ";foobar;", {"", "foobar", ""}},
+ // Empty fragments with "; " separator.
+ {"cookie", "; ", {"", ""}},
+ {"cookie", "foo; ", {"foo", ""}},
+ {"cookie", "; bar", {"", "bar"}},
+ {"cookie", "; foobar; ", {"", "foobar", ""}},
+ };
+
for (size_t i = 0; i < QUIC_ARRAYSIZE(kTestData); ++i) {
spdy::SpdyHeaderBlock block;
block[kTestData[i].name] = kTestData[i].value;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_arena_scoped_ptr.h b/chromium/net/third_party/quiche/src/quic/core/quic_arena_scoped_ptr.h
index 7c20fc7af4c..92da3dbc9de 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_arena_scoped_ptr.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_arena_scoped_ptr.h
@@ -14,12 +14,13 @@
#include <cstdint> // for uintptr_t
#include "net/third_party/quiche/src/quic/platform/api/quic_aligned.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
namespace quic {
template <typename T>
-class QuicArenaScopedPtr {
+class QUIC_NO_EXPORT QuicArenaScopedPtr {
static_assert(QUIC_ALIGN_OF(T*) > 1,
"QuicArenaScopedPtr can only store objects that are aligned to "
"greater than 1 byte.");
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_circular_deque.h b/chromium/net/third_party/quiche/src/quic/core/quic_circular_deque.h
new file mode 100644
index 00000000000..39eed8e6768
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_circular_deque.h
@@ -0,0 +1,744 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_QUIC_CIRCULAR_DEQUE_H_
+#define QUICHE_QUIC_CORE_QUIC_CIRCULAR_DEQUE_H_
+
+#include <algorithm>
+#include <cstddef>
+#include <iterator>
+#include <memory>
+#include <ostream>
+#include <type_traits>
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+
+namespace quic {
+
+// QuicCircularDeque is a STL-style container that is similar to std deque in
+// API and std::vector in capacity management. The goal is to optimize a common
+// QUIC use case where we keep adding new elements to the end and removing old
+// elements from the beginning, under such scenarios, if the container's size()
+// remain relatively stable, QuicCircularDeque requires little to no memory
+// allocations or deallocations.
+//
+// The implementation, as the name suggests, uses a flat circular buffer to hold
+// all elements. At any point in time, either
+// a) All elements are placed in a contiguous portion of this buffer, like a
+// c-array, or
+// b) Elements are phycially divided into two parts: the first part occupies the
+// end of the buffer and the second part occupies the beginning of the
+// buffer.
+//
+// Currently, elements can only be pushed or poped from either ends, it can't be
+// inserted or erased in the middle.
+//
+// TODO(wub): Make memory grow/shrink strategies customizable.
+template <typename T,
+ size_t MinCapacityIncrement = 3,
+ typename Allocator = std::allocator<T>>
+class QUIC_NO_EXPORT QuicCircularDeque {
+ using AllocatorTraits = std::allocator_traits<Allocator>;
+
+ // Pointee is either T or const T.
+ template <typename Pointee>
+ class QUIC_NO_EXPORT basic_iterator {
+ using size_type = typename AllocatorTraits::size_type;
+
+ public:
+ using iterator_category = std::random_access_iterator_tag;
+ using value_type = typename AllocatorTraits::value_type;
+ using difference_type = typename AllocatorTraits::difference_type;
+ using pointer = Pointee*;
+ using reference = Pointee&;
+
+ basic_iterator() = default;
+
+ // A copy constructor if Pointee is T.
+ // A conversion from iterator to const_iterator if Pointee is const T.
+ basic_iterator(
+ const basic_iterator<value_type>& it) // NOLINT(runtime/explicit)
+ : deque_(it.deque_), index_(it.index_) {}
+
+ reference operator*() const { return *deque_->index_to_address(index_); }
+ pointer operator->() const { return deque_->index_to_address(index_); }
+ reference operator[](difference_type i) { return *(*this + i); }
+
+ basic_iterator& operator++() {
+ Increment();
+ return *this;
+ }
+
+ basic_iterator operator++(int) {
+ basic_iterator result = *this;
+ Increment();
+ return result;
+ }
+
+ basic_iterator operator--() {
+ Decrement();
+ return *this;
+ }
+
+ basic_iterator operator--(int) {
+ basic_iterator result = *this;
+ Decrement();
+ return result;
+ }
+
+ friend basic_iterator operator+(const basic_iterator& it,
+ difference_type delta) {
+ basic_iterator result = it;
+ result.IncrementBy(delta);
+ return result;
+ }
+
+ basic_iterator& operator+=(difference_type delta) {
+ IncrementBy(delta);
+ return *this;
+ }
+
+ friend basic_iterator operator-(const basic_iterator& it,
+ difference_type delta) {
+ basic_iterator result = it;
+ result.IncrementBy(-delta);
+ return result;
+ }
+
+ basic_iterator& operator-=(difference_type delta) {
+ IncrementBy(-delta);
+ return *this;
+ }
+
+ friend difference_type operator-(const basic_iterator& lhs,
+ const basic_iterator& rhs) {
+ return lhs.ExternalPosition() - rhs.ExternalPosition();
+ }
+
+ friend bool operator==(const basic_iterator& lhs,
+ const basic_iterator& rhs) {
+ return lhs.index_ == rhs.index_;
+ }
+
+ friend bool operator!=(const basic_iterator& lhs,
+ const basic_iterator& rhs) {
+ return !(lhs == rhs);
+ }
+
+ friend bool operator<(const basic_iterator& lhs,
+ const basic_iterator& rhs) {
+ return lhs.ExternalPosition() < rhs.ExternalPosition();
+ }
+
+ friend bool operator<=(const basic_iterator& lhs,
+ const basic_iterator& rhs) {
+ return !(lhs > rhs);
+ }
+
+ friend bool operator>(const basic_iterator& lhs,
+ const basic_iterator& rhs) {
+ return lhs.ExternalPosition() > rhs.ExternalPosition();
+ }
+
+ friend bool operator>=(const basic_iterator& lhs,
+ const basic_iterator& rhs) {
+ return !(lhs < rhs);
+ }
+
+ private:
+ basic_iterator(const QuicCircularDeque* deque, size_type index)
+ : deque_(deque), index_(index) {}
+
+ void Increment() {
+ DCHECK_LE(ExternalPosition() + 1, deque_->size());
+ index_ = deque_->index_next(index_);
+ }
+
+ void Decrement() {
+ DCHECK_GE(ExternalPosition(), 1u);
+ index_ = deque_->index_prev(index_);
+ }
+
+ void IncrementBy(difference_type delta) {
+ if (delta >= 0) {
+ // After increment we are before or at end().
+ DCHECK_LE(static_cast<size_type>(ExternalPosition() + delta),
+ deque_->size());
+ } else {
+ // After decrement we are after or at begin().
+ DCHECK_GE(ExternalPosition(), static_cast<size_type>(-delta));
+ }
+ index_ = deque_->index_increment_by(index_, delta);
+ }
+
+ size_type ExternalPosition() const {
+ if (index_ >= deque_->begin_) {
+ return index_ - deque_->begin_;
+ }
+ return index_ + deque_->data_capacity() - deque_->begin_;
+ }
+
+ friend class QuicCircularDeque;
+ const QuicCircularDeque* deque_ = nullptr;
+ size_type index_ = 0;
+ };
+
+ public:
+ using allocator_type = typename AllocatorTraits::allocator_type;
+ using value_type = typename AllocatorTraits::value_type;
+ using size_type = typename AllocatorTraits::size_type;
+ using difference_type = typename AllocatorTraits::difference_type;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+ using pointer = typename AllocatorTraits::pointer;
+ using const_pointer = typename AllocatorTraits::const_pointer;
+ using iterator = basic_iterator<T>;
+ using const_iterator = basic_iterator<const T>;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ QuicCircularDeque() : QuicCircularDeque(allocator_type()) {}
+ explicit QuicCircularDeque(const allocator_type& alloc)
+ : allocator_and_data_(alloc) {}
+
+ QuicCircularDeque(size_type count,
+ const T& value,
+ const Allocator& alloc = allocator_type())
+ : allocator_and_data_(alloc) {
+ resize(count, value);
+ }
+
+ explicit QuicCircularDeque(size_type count,
+ const Allocator& alloc = allocator_type())
+ : allocator_and_data_(alloc) {
+ resize(count);
+ }
+
+ template <
+ class InputIt,
+ typename = std::enable_if_t<std::is_base_of<
+ std::input_iterator_tag,
+ typename std::iterator_traits<InputIt>::iterator_category>::value>>
+ QuicCircularDeque(InputIt first,
+ InputIt last,
+ const Allocator& alloc = allocator_type())
+ : allocator_and_data_(alloc) {
+ AssignRange(first, last);
+ }
+
+ QuicCircularDeque(const QuicCircularDeque& other)
+ : QuicCircularDeque(
+ other,
+ AllocatorTraits::select_on_container_copy_construction(
+ other.allocator_and_data_.allocator())) {}
+
+ QuicCircularDeque(const QuicCircularDeque& other, const allocator_type& alloc)
+ : allocator_and_data_(alloc) {
+ assign(other.begin(), other.end());
+ }
+
+ QuicCircularDeque(QuicCircularDeque&& other)
+ : begin_(other.begin_),
+ end_(other.end_),
+ allocator_and_data_(std::move(other.allocator_and_data_)) {
+ other.begin_ = other.end_ = 0;
+ other.allocator_and_data_.data = nullptr;
+ other.allocator_and_data_.data_capacity = 0;
+ }
+
+ QuicCircularDeque(QuicCircularDeque&& other, const allocator_type& alloc)
+ : allocator_and_data_(alloc) {
+ MoveRetainAllocator(std::move(other));
+ }
+
+ QuicCircularDeque(std::initializer_list<T> init,
+ const allocator_type& alloc = allocator_type())
+ : QuicCircularDeque(init.begin(), init.end(), alloc) {}
+
+ QuicCircularDeque& operator=(const QuicCircularDeque& other) {
+ if (this == &other) {
+ return *this;
+ }
+ if (AllocatorTraits::propagate_on_container_copy_assignment::value &&
+ (allocator_and_data_.allocator() !=
+ other.allocator_and_data_.allocator())) {
+ // Destroy all current elements and blocks with the current allocator,
+ // before switching this to use the allocator propagated from "other".
+ DestroyAndDeallocateAll();
+ begin_ = end_ = 0;
+ allocator_and_data_ =
+ AllocatorAndData(other.allocator_and_data_.allocator());
+ }
+ assign(other.begin(), other.end());
+ return *this;
+ }
+
+ QuicCircularDeque& operator=(QuicCircularDeque&& other) {
+ if (this == &other) {
+ return *this;
+ }
+ if (AllocatorTraits::propagate_on_container_move_assignment::value) {
+ // Take over the storage of "other", along with its allocator.
+ this->~QuicCircularDeque();
+ new (this) QuicCircularDeque(std::move(other));
+ } else {
+ MoveRetainAllocator(std::move(other));
+ }
+ return *this;
+ }
+
+ ~QuicCircularDeque() { DestroyAndDeallocateAll(); }
+
+ void assign(size_type count, const T& value) {
+ ClearRetainCapacity();
+ reserve(count);
+ for (size_t i = 0; i < count; ++i) {
+ emplace_back(value);
+ }
+ }
+
+ template <
+ class InputIt,
+ typename = std::enable_if_t<std::is_base_of<
+ std::input_iterator_tag,
+ typename std::iterator_traits<InputIt>::iterator_category>::value>>
+ void assign(InputIt first, InputIt last) {
+ AssignRange(first, last);
+ }
+
+ void assign(std::initializer_list<T> ilist) {
+ assign(ilist.begin(), ilist.end());
+ }
+
+ reference at(size_type pos) {
+ DCHECK(pos < size()) << "pos:" << pos << ", size():" << size();
+ size_type index = begin_ + pos;
+ if (index < data_capacity()) {
+ return *index_to_address(index);
+ }
+ return *index_to_address(index - data_capacity());
+ }
+
+ const_reference at(size_type pos) const {
+ return const_cast<QuicCircularDeque*>(this)->at(pos);
+ }
+
+ reference operator[](size_type pos) { return at(pos); }
+
+ const_reference operator[](size_type pos) const { return at(pos); }
+
+ reference front() {
+ DCHECK(!empty());
+ return *index_to_address(begin_);
+ }
+
+ const_reference front() const {
+ return const_cast<QuicCircularDeque*>(this)->front();
+ }
+
+ reference back() {
+ DCHECK(!empty());
+ return *(index_to_address(end_ == 0 ? data_capacity() - 1 : end_ - 1));
+ }
+
+ const_reference back() const {
+ return const_cast<QuicCircularDeque*>(this)->back();
+ }
+
+ iterator begin() { return iterator(this, begin_); }
+ const_iterator begin() const { return const_iterator(this, begin_); }
+ const_iterator cbegin() const { return const_iterator(this, begin_); }
+
+ iterator end() { return iterator(this, end_); }
+ const_iterator end() const { return const_iterator(this, end_); }
+ const_iterator cend() const { return const_iterator(this, end_); }
+
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
+ const_reverse_iterator rbegin() const {
+ return const_reverse_iterator(end());
+ }
+ const_reverse_iterator crbegin() const { return rbegin(); }
+
+ reverse_iterator rend() { return reverse_iterator(begin()); }
+ const_reverse_iterator rend() const {
+ return const_reverse_iterator(begin());
+ }
+ const_reverse_iterator crend() const { return rend(); }
+
+ size_type capacity() const {
+ return data_capacity() == 0 ? 0 : data_capacity() - 1;
+ }
+
+ void reserve(size_type new_cap) {
+ if (new_cap > capacity()) {
+ Relocate(new_cap);
+ }
+ }
+
+ // Remove all elements. Leave capacity unchanged.
+ void clear() { ClearRetainCapacity(); }
+
+ bool empty() const { return begin_ == end_; }
+
+ size_type size() const {
+ if (begin_ <= end_) {
+ return end_ - begin_;
+ }
+ return data_capacity() + end_ - begin_;
+ }
+
+ void resize(size_type count) { ResizeInternal(count); }
+
+ void resize(size_type count, const value_type& value) {
+ ResizeInternal(count, value);
+ }
+
+ void push_front(const T& value) { emplace_front(value); }
+ void push_front(T&& value) { emplace_front(std::move(value)); }
+
+ template <class... Args>
+ reference emplace_front(Args&&... args) {
+ MaybeExpandCapacity(1);
+ begin_ = index_prev(begin_);
+ new (index_to_address(begin_)) T(std::forward<Args>(args)...);
+ return front();
+ }
+
+ void push_back(const T& value) { emplace_back(value); }
+ void push_back(T&& value) { emplace_back(std::move(value)); }
+
+ template <class... Args>
+ reference emplace_back(Args&&... args) {
+ MaybeExpandCapacity(1);
+ new (index_to_address(end_)) T(std::forward<Args>(args)...);
+ end_ = index_next(end_);
+ return back();
+ }
+
+ void pop_front() {
+ DCHECK(!empty());
+ DestroyByIndex(begin_);
+ begin_ = index_next(begin_);
+ MaybeShrinkCapacity();
+ }
+
+ size_type pop_front_n(size_type count) {
+ size_type num_elements_to_pop = std::min(count, size());
+ size_type new_begin = index_increment_by(begin_, num_elements_to_pop);
+ DestroyRange(begin_, new_begin);
+ begin_ = new_begin;
+ MaybeShrinkCapacity();
+ return num_elements_to_pop;
+ }
+
+ void pop_back() {
+ DCHECK(!empty());
+ end_ = index_prev(end_);
+ DestroyByIndex(end_);
+ MaybeShrinkCapacity();
+ }
+
+ size_type pop_back_n(size_type count) {
+ size_type num_elements_to_pop = std::min(count, size());
+ size_type new_end = index_increment_by(end_, -num_elements_to_pop);
+ DestroyRange(new_end, end_);
+ end_ = new_end;
+ MaybeShrinkCapacity();
+ return num_elements_to_pop;
+ }
+
+ void swap(QuicCircularDeque& other) {
+ using std::swap;
+ swap(begin_, other.begin_);
+ swap(end_, other.end_);
+
+ if (AllocatorTraits::propagate_on_container_swap::value) {
+ swap(allocator_and_data_, other.allocator_and_data_);
+ } else {
+ // When propagate_on_container_swap is false, it is undefined behavior, by
+ // c++ standard, to swap between two AllocatorAwareContainer(s) with
+ // unequal allocators.
+ DCHECK(get_allocator() == other.get_allocator())
+ << "Undefined swap behavior";
+ swap(allocator_and_data_.data, other.allocator_and_data_.data);
+ swap(allocator_and_data_.data_capacity,
+ other.allocator_and_data_.data_capacity);
+ }
+ }
+
+ friend void swap(QuicCircularDeque& lhs, QuicCircularDeque& rhs) {
+ lhs.swap(rhs);
+ }
+
+ allocator_type get_allocator() const {
+ return allocator_and_data_.allocator();
+ }
+
+ friend bool operator==(const QuicCircularDeque& lhs,
+ const QuicCircularDeque& rhs) {
+ return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
+ }
+
+ friend bool operator!=(const QuicCircularDeque& lhs,
+ const QuicCircularDeque& rhs) {
+ return !(lhs == rhs);
+ }
+
+ friend QUIC_NO_EXPORT std::ostream& operator<<(std::ostream& os,
+ const QuicCircularDeque& dq) {
+ os << "{";
+ for (size_type pos = 0; pos != dq.size(); ++pos) {
+ if (pos != 0) {
+ os << ",";
+ }
+ os << " " << dq[pos];
+ }
+ os << " }";
+ return os;
+ }
+
+ private:
+ void MoveRetainAllocator(QuicCircularDeque&& other) {
+ if (get_allocator() == other.get_allocator()) {
+ // Take over the storage of "other", with which we share an allocator.
+ DestroyAndDeallocateAll();
+
+ begin_ = other.begin_;
+ end_ = other.end_;
+ allocator_and_data_.data = other.allocator_and_data_.data;
+ allocator_and_data_.data_capacity =
+ other.allocator_and_data_.data_capacity;
+
+ other.begin_ = other.end_ = 0;
+ other.allocator_and_data_.data = nullptr;
+ other.allocator_and_data_.data_capacity = 0;
+ } else {
+ // We cannot take over of the storage from "other", since it has a
+ // different allocator; we're stuck move-assigning elements individually.
+ ClearRetainCapacity();
+ for (auto& elem : other) {
+ push_back(std::move(elem));
+ }
+ other.clear();
+ }
+ }
+
+ template <
+ typename InputIt,
+ typename = std::enable_if_t<std::is_base_of<
+ std::input_iterator_tag,
+ typename std::iterator_traits<InputIt>::iterator_category>::value>>
+ void AssignRange(InputIt first, InputIt last) {
+ ClearRetainCapacity();
+ if (std::is_base_of<
+ std::random_access_iterator_tag,
+ typename std::iterator_traits<InputIt>::iterator_category>::value) {
+ reserve(std::distance(first, last));
+ }
+ for (; first != last; ++first) {
+ emplace_back(*first);
+ }
+ }
+
+ // WARNING: begin_, end_ and allocator_and_data_ are not modified.
+ void DestroyAndDeallocateAll() {
+ DestroyRange(begin_, end_);
+
+ if (data_capacity() > 0) {
+ DCHECK_NE(nullptr, allocator_and_data_.data);
+ AllocatorTraits::deallocate(allocator_and_data_.allocator(),
+ allocator_and_data_.data, data_capacity());
+ }
+ }
+
+ void ClearRetainCapacity() {
+ DestroyRange(begin_, end_);
+ begin_ = end_ = 0;
+ }
+
+ void MaybeShrinkCapacity() {
+ // TODO(wub): Implement a storage policy that actually shrinks.
+ }
+
+ void MaybeExpandCapacity(size_t num_additional_elements) {
+ size_t new_size = size() + num_additional_elements;
+ if (capacity() >= new_size) {
+ return;
+ }
+
+ // The minimum amount of additional capacity to grow.
+ size_t min_additional_capacity =
+ std::max(MinCapacityIncrement, capacity() / 4);
+ size_t new_capacity =
+ std::max(new_size, capacity() + min_additional_capacity);
+
+ Relocate(new_capacity);
+ }
+
+ void Relocate(size_t new_capacity) {
+ const size_t num_elements = size();
+ DCHECK_GT(new_capacity, num_elements)
+ << "new_capacity:" << new_capacity << ", num_elements:" << num_elements;
+
+ size_t new_data_capacity = new_capacity + 1;
+ pointer new_data = AllocatorTraits::allocate(
+ allocator_and_data_.allocator(), new_data_capacity);
+
+ if (begin_ <= end_) {
+ // Not wrapped.
+ RelocateUnwrappedRange(begin_, end_, new_data);
+ } else {
+ // Wrapped.
+ const size_t num_elements_before_wrap = data_capacity() - begin_;
+ RelocateUnwrappedRange(begin_, data_capacity(), new_data);
+ RelocateUnwrappedRange(0, end_, new_data + num_elements_before_wrap);
+ }
+
+ if (data_capacity()) {
+ AllocatorTraits::deallocate(allocator_and_data_.allocator(),
+ allocator_and_data_.data, data_capacity());
+ }
+
+ allocator_and_data_.data = new_data;
+ allocator_and_data_.data_capacity = new_data_capacity;
+ begin_ = 0;
+ end_ = num_elements;
+ }
+
+ template <typename T_ = T>
+ typename std::enable_if<std::is_trivially_copyable<T_>::value, void>::type
+ RelocateUnwrappedRange(size_type begin, size_type end, pointer dest) const {
+ DCHECK_LE(begin, end) << "begin:" << begin << ", end:" << end;
+ memcpy(dest, index_to_address(begin), sizeof(T) * (end - begin));
+ DestroyRange(begin, end);
+ }
+
+ template <typename T_ = T>
+ typename std::enable_if<!std::is_trivially_copyable<T_>::value &&
+ std::is_move_constructible<T_>::value,
+ void>::type
+ RelocateUnwrappedRange(size_type begin, size_type end, pointer dest) const {
+ DCHECK_LE(begin, end) << "begin:" << begin << ", end:" << end;
+ pointer src = index_to_address(begin);
+ pointer src_end = index_to_address(end);
+ while (src != src_end) {
+ new (dest) T(std::move(*src));
+ DestroyByAddress(src);
+ ++dest;
+ ++src;
+ }
+ }
+
+ template <typename T_ = T>
+ typename std::enable_if<!std::is_trivially_copyable<T_>::value &&
+ !std::is_move_constructible<T_>::value,
+ void>::type
+ RelocateUnwrappedRange(size_type begin, size_type end, pointer dest) const {
+ DCHECK_LE(begin, end) << "begin:" << begin << ", end:" << end;
+ pointer src = index_to_address(begin);
+ pointer src_end = index_to_address(end);
+ while (src != src_end) {
+ new (dest) T(*src);
+ DestroyByAddress(src);
+ ++dest;
+ ++src;
+ }
+ }
+
+ template <class... U>
+ void ResizeInternal(size_type count, U&&... u) {
+ if (count > size()) {
+ // Expanding.
+ MaybeExpandCapacity(count - size());
+ while (size() < count) {
+ emplace_back(std::forward<U>(u)...);
+ }
+ } else {
+ // Most likely shrinking. No-op if count == size().
+ size_type new_end = (begin_ + count) % data_capacity();
+ DestroyRange(new_end, end_);
+ end_ = new_end;
+
+ MaybeShrinkCapacity();
+ }
+ }
+
+ void DestroyRange(size_type begin, size_type end) const {
+ if (std::is_trivially_destructible<T>::value) {
+ return;
+ }
+ if (end >= begin) {
+ DestroyUnwrappedRange(begin, end);
+ } else {
+ DestroyUnwrappedRange(begin, data_capacity());
+ DestroyUnwrappedRange(0, end);
+ }
+ }
+
+ // Should only be called from DestroyRange.
+ void DestroyUnwrappedRange(size_type begin, size_type end) const {
+ DCHECK_LE(begin, end) << "begin:" << begin << ", end:" << end;
+ for (; begin != end; ++begin) {
+ DestroyByIndex(begin);
+ }
+ }
+
+ void DestroyByIndex(size_type index) const {
+ DestroyByAddress(index_to_address(index));
+ }
+
+ void DestroyByAddress(pointer address) const {
+ if (std::is_trivially_destructible<T>::value) {
+ return;
+ }
+ address->~T();
+ }
+
+ size_type data_capacity() const { return allocator_and_data_.data_capacity; }
+
+ pointer index_to_address(size_type index) const {
+ return allocator_and_data_.data + index;
+ }
+
+ size_type index_prev(size_type index) const {
+ return index == 0 ? data_capacity() - 1 : index - 1;
+ }
+
+ size_type index_next(size_type index) const {
+ return index == data_capacity() - 1 ? 0 : index + 1;
+ }
+
+ size_type index_increment_by(size_type index, difference_type delta) const {
+ if (delta == 0) {
+ return index;
+ }
+
+ DCHECK_LT(static_cast<size_type>(std::abs(delta)), data_capacity());
+ return (index + data_capacity() + delta) % data_capacity();
+ }
+
+ // Empty base-class optimization: bundle storage for our allocator together
+ // with the fields we had to store anyway, via inheriting from the allocator,
+ // so this allocator instance doesn't consume any storage when its type has no
+ // data members.
+ struct AllocatorAndData : private allocator_type {
+ explicit AllocatorAndData(const allocator_type& alloc)
+ : allocator_type(alloc) {}
+
+ const allocator_type& allocator() const { return *this; }
+ allocator_type& allocator() { return *this; }
+
+ pointer data = nullptr;
+ size_type data_capacity = 0;
+ };
+
+ size_type begin_ = 0;
+ size_type end_ = 0;
+ AllocatorAndData allocator_and_data_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QUIC_CIRCULAR_DEQUE_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_circular_deque_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_circular_deque_test.cc
new file mode 100644
index 00000000000..c1658985a48
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_circular_deque_test.cc
@@ -0,0 +1,790 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_circular_deque.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <type_traits>
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+
+using testing::ElementsAre;
+
+namespace quic {
+namespace test {
+
+template <typename T, template <typename> class BaseAllocator = std::allocator>
+class CountingAllocator : public BaseAllocator<T> {
+ typedef BaseAllocator<T> BaseType;
+
+ public:
+ using propagate_on_container_copy_assignment = std::true_type;
+ using propagate_on_container_move_assignment = std::true_type;
+ using propagate_on_container_swap = std::true_type;
+
+ T* allocate(std::size_t n) {
+ ++shared_counts_->allocate_count;
+ return BaseType::allocate(n);
+ }
+
+ void deallocate(T* ptr, std::size_t n) {
+ ++shared_counts_->deallocate_count;
+ return BaseType::deallocate(ptr, n);
+ }
+
+ size_t allocate_count() const { return shared_counts_->allocate_count; }
+
+ size_t deallocate_count() const { return shared_counts_->deallocate_count; }
+
+ friend bool operator==(const CountingAllocator& lhs,
+ const CountingAllocator& rhs) {
+ return lhs.shared_counts_ == rhs.shared_counts_;
+ }
+
+ friend bool operator!=(const CountingAllocator& lhs,
+ const CountingAllocator& rhs) {
+ return !(lhs == rhs);
+ }
+
+ private:
+ struct Counts {
+ size_t allocate_count = 0;
+ size_t deallocate_count = 0;
+ };
+
+ std::shared_ptr<Counts> shared_counts_ = std::make_shared<Counts>();
+};
+
+template <typename T,
+ typename propagate_on_copy_assignment,
+ typename propagate_on_move_assignment,
+ typename propagate_on_swap,
+ bool equality_result,
+ template <typename> class BaseAllocator = std::allocator>
+struct ConfigurableAllocator : public BaseAllocator<T> {
+ using propagate_on_container_copy_assignment = propagate_on_copy_assignment;
+ using propagate_on_container_move_assignment = propagate_on_move_assignment;
+ using propagate_on_container_swap = propagate_on_swap;
+
+ friend bool operator==(const ConfigurableAllocator& /*lhs*/,
+ const ConfigurableAllocator& /*rhs*/) {
+ return equality_result;
+ }
+
+ friend bool operator!=(const ConfigurableAllocator& lhs,
+ const ConfigurableAllocator& rhs) {
+ return !(lhs == rhs);
+ }
+};
+
+// [1, 2, 3, 4] ==> [4, 1, 2, 3]
+template <typename Deque>
+void ShiftRight(Deque* dq, bool emplace) {
+ auto back = *(&dq->back());
+ dq->pop_back();
+ if (emplace) {
+ dq->emplace_front(back);
+ } else {
+ dq->push_front(back);
+ }
+}
+
+// [1, 2, 3, 4] ==> [2, 3, 4, 1]
+template <typename Deque>
+void ShiftLeft(Deque* dq, bool emplace) {
+ auto front = *(&dq->front());
+ dq->pop_front();
+ if (emplace) {
+ dq->emplace_back(front);
+ } else {
+ dq->push_back(front);
+ }
+}
+
+TEST(QuicCircularDeque, Empty) {
+ QuicCircularDeque<int> dq;
+ EXPECT_TRUE(dq.empty());
+ EXPECT_EQ(0u, dq.size());
+ dq.clear();
+ dq.push_back(10);
+ EXPECT_FALSE(dq.empty());
+ EXPECT_EQ(1u, dq.size());
+ EXPECT_EQ(10, dq.front());
+ EXPECT_EQ(10, dq.back());
+ dq.pop_front();
+ EXPECT_TRUE(dq.empty());
+ EXPECT_EQ(0u, dq.size());
+
+ EXPECT_QUIC_DEBUG_DEATH(dq.front(), "");
+ EXPECT_QUIC_DEBUG_DEATH(dq.back(), "");
+ EXPECT_QUIC_DEBUG_DEATH(dq.at(0), "");
+ EXPECT_QUIC_DEBUG_DEATH(dq[0], "");
+}
+
+TEST(QuicCircularDeque, Constructor) {
+ QuicCircularDeque<int> dq;
+ EXPECT_TRUE(dq.empty());
+
+ std::allocator<int> alloc;
+ QuicCircularDeque<int> dq1(alloc);
+ EXPECT_TRUE(dq1.empty());
+
+ QuicCircularDeque<int> dq2(8, 100, alloc);
+ EXPECT_THAT(dq2, ElementsAre(100, 100, 100, 100, 100, 100, 100, 100));
+
+ QuicCircularDeque<int> dq3(5, alloc);
+ EXPECT_THAT(dq3, ElementsAre(0, 0, 0, 0, 0));
+
+ QuicCircularDeque<int> dq4_rand_iter(dq3.begin(), dq3.end(), alloc);
+ EXPECT_THAT(dq4_rand_iter, ElementsAre(0, 0, 0, 0, 0));
+ EXPECT_EQ(dq4_rand_iter, dq3);
+
+ std::list<int> dq4_src = {4, 4, 4, 4};
+ QuicCircularDeque<int> dq4_bidi_iter(dq4_src.begin(), dq4_src.end());
+ EXPECT_THAT(dq4_bidi_iter, ElementsAre(4, 4, 4, 4));
+
+ QuicCircularDeque<int> dq5(dq4_bidi_iter);
+ EXPECT_THAT(dq5, ElementsAre(4, 4, 4, 4));
+ EXPECT_EQ(dq5, dq4_bidi_iter);
+
+ QuicCircularDeque<int> dq6(dq5, alloc);
+ EXPECT_THAT(dq6, ElementsAre(4, 4, 4, 4));
+ EXPECT_EQ(dq6, dq5);
+
+ QuicCircularDeque<int> dq7(std::move(*&dq6));
+ EXPECT_THAT(dq7, ElementsAre(4, 4, 4, 4));
+ EXPECT_TRUE(dq6.empty());
+
+ QuicCircularDeque<int> dq8_equal_allocator(std::move(*&dq7), alloc);
+ EXPECT_THAT(dq8_equal_allocator, ElementsAre(4, 4, 4, 4));
+ EXPECT_TRUE(dq7.empty());
+
+ QuicCircularDeque<int, 3, CountingAllocator<int>> dq8_temp = {5, 6, 7, 8, 9};
+ QuicCircularDeque<int, 3, CountingAllocator<int>> dq8_unequal_allocator(
+ std::move(*&dq8_temp), CountingAllocator<int>());
+ EXPECT_THAT(dq8_unequal_allocator, ElementsAre(5, 6, 7, 8, 9));
+ EXPECT_TRUE(dq8_temp.empty());
+
+ QuicCircularDeque<int> dq9({3, 4, 5, 6, 7}, alloc);
+ EXPECT_THAT(dq9, ElementsAre(3, 4, 5, 6, 7));
+}
+
+TEST(QuicCircularDeque, Assign) {
+ // assign()
+ QuicCircularDeque<int, 3, CountingAllocator<int>> dq;
+ dq.assign(7, 1);
+ EXPECT_THAT(dq, ElementsAre(1, 1, 1, 1, 1, 1, 1));
+ EXPECT_EQ(1u, dq.get_allocator().allocate_count());
+
+ QuicCircularDeque<int, 3, CountingAllocator<int>> dq2;
+ dq2.assign(dq.begin(), dq.end());
+ EXPECT_THAT(dq2, ElementsAre(1, 1, 1, 1, 1, 1, 1));
+ EXPECT_EQ(1u, dq2.get_allocator().allocate_count());
+ EXPECT_TRUE(std::equal(dq.begin(), dq.end(), dq2.begin(), dq2.end()));
+
+ dq2.assign({2, 2, 2, 2, 2, 2});
+ EXPECT_THAT(dq2, ElementsAre(2, 2, 2, 2, 2, 2));
+
+ // Assign from a non random access iterator.
+ std::list<int> dq3_src = {3, 3, 3, 3, 3};
+ QuicCircularDeque<int, 3, CountingAllocator<int>> dq3;
+ dq3.assign(dq3_src.begin(), dq3_src.end());
+ EXPECT_THAT(dq3, ElementsAre(3, 3, 3, 3, 3));
+ EXPECT_LT(1u, dq3.get_allocator().allocate_count());
+
+ // Copy assignment
+ dq3 = *&dq3;
+ EXPECT_THAT(dq3, ElementsAre(3, 3, 3, 3, 3));
+
+ QuicCircularDeque<
+ int, 3,
+ ConfigurableAllocator<int,
+ /*propagate_on_copy_assignment=*/std::true_type,
+ /*propagate_on_move_assignment=*/std::true_type,
+ /*propagate_on_swap=*/std::true_type,
+ /*equality_result=*/false>>
+ dq4, dq5;
+ dq4.assign(dq3.begin(), dq3.end());
+ dq5 = dq4;
+ EXPECT_THAT(dq5, ElementsAre(3, 3, 3, 3, 3));
+
+ QuicCircularDeque<
+ int, 3,
+ ConfigurableAllocator<int,
+ /*propagate_on_copy_assignment=*/std::false_type,
+ /*propagate_on_move_assignment=*/std::true_type,
+ /*propagate_on_swap=*/std::true_type,
+ /*equality_result=*/true>>
+ dq6, dq7;
+ dq6.assign(dq3.begin(), dq3.end());
+ dq7 = dq6;
+ EXPECT_THAT(dq7, ElementsAre(3, 3, 3, 3, 3));
+
+ // Move assignment
+ dq3 = std::move(*&dq3);
+ EXPECT_THAT(dq3, ElementsAre(3, 3, 3, 3, 3));
+
+ ASSERT_TRUE(decltype(
+ dq3.get_allocator())::propagate_on_container_move_assignment::value);
+ decltype(dq3) dq8;
+ dq8 = std::move(*&dq3);
+ EXPECT_THAT(dq8, ElementsAre(3, 3, 3, 3, 3));
+ EXPECT_TRUE(dq3.empty());
+
+ QuicCircularDeque<
+ int, 3,
+ ConfigurableAllocator<int,
+ /*propagate_on_copy_assignment=*/std::true_type,
+ /*propagate_on_move_assignment=*/std::false_type,
+ /*propagate_on_swap=*/std::true_type,
+ /*equality_result=*/true>>
+ dq9, dq10;
+ dq9.assign(dq8.begin(), dq8.end());
+ dq10.assign(dq2.begin(), dq2.end());
+ dq9 = std::move(*&dq10);
+ EXPECT_THAT(dq9, ElementsAre(2, 2, 2, 2, 2, 2));
+ EXPECT_TRUE(dq10.empty());
+
+ QuicCircularDeque<
+ int, 3,
+ ConfigurableAllocator<int,
+ /*propagate_on_copy_assignment=*/std::true_type,
+ /*propagate_on_move_assignment=*/std::false_type,
+ /*propagate_on_swap=*/std::true_type,
+ /*equality_result=*/false>>
+ dq11, dq12;
+ dq11.assign(dq8.begin(), dq8.end());
+ dq12.assign(dq2.begin(), dq2.end());
+ dq11 = std::move(*&dq12);
+ EXPECT_THAT(dq11, ElementsAre(2, 2, 2, 2, 2, 2));
+ EXPECT_TRUE(dq12.empty());
+}
+
+TEST(QuicCircularDeque, Access) {
+ // at()
+ // operator[]
+ // front()
+ // back()
+
+ QuicCircularDeque<int, 3, CountingAllocator<int>> dq;
+ dq.push_back(10);
+ EXPECT_EQ(dq.front(), 10);
+ EXPECT_EQ(dq.back(), 10);
+ EXPECT_EQ(dq.at(0), 10);
+ EXPECT_EQ(dq[0], 10);
+ dq.front() = 12;
+ EXPECT_EQ(dq.front(), 12);
+ EXPECT_EQ(dq.back(), 12);
+ EXPECT_EQ(dq.at(0), 12);
+ EXPECT_EQ(dq[0], 12);
+
+ const auto& dqref = dq;
+ EXPECT_EQ(dqref.front(), 12);
+ EXPECT_EQ(dqref.back(), 12);
+ EXPECT_EQ(dqref.at(0), 12);
+ EXPECT_EQ(dqref[0], 12);
+
+ dq.pop_front();
+ EXPECT_TRUE(dqref.empty());
+
+ // Push to capacity.
+ dq.push_back(15);
+ dq.push_front(5);
+ dq.push_back(25);
+ EXPECT_EQ(dq.size(), dq.capacity());
+ EXPECT_THAT(dq, ElementsAre(5, 15, 25));
+ EXPECT_LT(&dq.front(), &dq.back());
+ EXPECT_EQ(dq.front(), 5);
+ EXPECT_EQ(dq.back(), 25);
+ EXPECT_EQ(dq.at(0), 5);
+ EXPECT_EQ(dq.at(1), 15);
+ EXPECT_EQ(dq.at(2), 25);
+ EXPECT_EQ(dq[0], 5);
+ EXPECT_EQ(dq[1], 15);
+ EXPECT_EQ(dq[2], 25);
+
+ // Shift right such that begin=1 and end=0. Data is still not wrapped.
+ dq.pop_front();
+ dq.push_back(35);
+ EXPECT_THAT(dq, ElementsAre(15, 25, 35));
+ EXPECT_LT(&dq.front(), &dq.back());
+ EXPECT_EQ(dq.front(), 15);
+ EXPECT_EQ(dq.back(), 35);
+ EXPECT_EQ(dq.at(0), 15);
+ EXPECT_EQ(dq.at(1), 25);
+ EXPECT_EQ(dq.at(2), 35);
+ EXPECT_EQ(dq[0], 15);
+ EXPECT_EQ(dq[1], 25);
+ EXPECT_EQ(dq[2], 35);
+
+ // Shift right such that data is wrapped.
+ dq.pop_front();
+ dq.push_back(45);
+ EXPECT_THAT(dq, ElementsAre(25, 35, 45));
+ EXPECT_GT(&dq.front(), &dq.back());
+ EXPECT_EQ(dq.front(), 25);
+ EXPECT_EQ(dq.back(), 45);
+ EXPECT_EQ(dq.at(0), 25);
+ EXPECT_EQ(dq.at(1), 35);
+ EXPECT_EQ(dq.at(2), 45);
+ EXPECT_EQ(dq[0], 25);
+ EXPECT_EQ(dq[1], 35);
+ EXPECT_EQ(dq[2], 45);
+
+ // Shift right again, data is still wrapped.
+ dq.pop_front();
+ dq.push_back(55);
+ EXPECT_THAT(dq, ElementsAre(35, 45, 55));
+ EXPECT_GT(&dq.front(), &dq.back());
+ EXPECT_EQ(dq.front(), 35);
+ EXPECT_EQ(dq.back(), 55);
+ EXPECT_EQ(dq.at(0), 35);
+ EXPECT_EQ(dq.at(1), 45);
+ EXPECT_EQ(dq.at(2), 55);
+ EXPECT_EQ(dq[0], 35);
+ EXPECT_EQ(dq[1], 45);
+ EXPECT_EQ(dq[2], 55);
+
+ // Shift right one last time. begin returns to 0. Data is no longer wrapped.
+ dq.pop_front();
+ dq.push_back(65);
+ EXPECT_THAT(dq, ElementsAre(45, 55, 65));
+ EXPECT_LT(&dq.front(), &dq.back());
+ EXPECT_EQ(dq.front(), 45);
+ EXPECT_EQ(dq.back(), 65);
+ EXPECT_EQ(dq.at(0), 45);
+ EXPECT_EQ(dq.at(1), 55);
+ EXPECT_EQ(dq.at(2), 65);
+ EXPECT_EQ(dq[0], 45);
+ EXPECT_EQ(dq[1], 55);
+ EXPECT_EQ(dq[2], 65);
+
+ EXPECT_EQ(1u, dq.get_allocator().allocate_count());
+}
+
+TEST(QuicCircularDeque, Iterate) {
+ QuicCircularDeque<int> dq;
+ EXPECT_EQ(dq.begin(), dq.end());
+ EXPECT_EQ(dq.cbegin(), dq.cend());
+ EXPECT_EQ(dq.rbegin(), dq.rend());
+ EXPECT_EQ(dq.crbegin(), dq.crend());
+
+ dq.emplace_back(2);
+ QuicCircularDeque<int>::const_iterator citer = dq.begin();
+ EXPECT_NE(citer, dq.end());
+ EXPECT_EQ(*citer, 2);
+ ++citer;
+ EXPECT_EQ(citer, dq.end());
+
+ EXPECT_EQ(*dq.begin(), 2);
+ EXPECT_EQ(*dq.cbegin(), 2);
+ EXPECT_EQ(*dq.rbegin(), 2);
+ EXPECT_EQ(*dq.crbegin(), 2);
+
+ dq.emplace_front(1);
+ QuicCircularDeque<int>::const_reverse_iterator criter = dq.rbegin();
+ EXPECT_NE(criter, dq.rend());
+ EXPECT_EQ(*criter, 2);
+ ++criter;
+ EXPECT_NE(criter, dq.rend());
+ EXPECT_EQ(*criter, 1);
+ ++criter;
+ EXPECT_EQ(criter, dq.rend());
+
+ EXPECT_EQ(*dq.begin(), 1);
+ EXPECT_EQ(*dq.cbegin(), 1);
+ EXPECT_EQ(*dq.rbegin(), 2);
+ EXPECT_EQ(*dq.crbegin(), 2);
+
+ dq.push_back(3);
+
+ // Forward iterate.
+ int expected_value = 1;
+ for (QuicCircularDeque<int>::iterator it = dq.begin(); it != dq.end(); ++it) {
+ EXPECT_EQ(expected_value++, *it);
+ }
+
+ expected_value = 1;
+ for (QuicCircularDeque<int>::const_iterator it = dq.cbegin(); it != dq.cend();
+ ++it) {
+ EXPECT_EQ(expected_value++, *it);
+ }
+
+ // Reverse iterate.
+ expected_value = 3;
+ for (QuicCircularDeque<int>::reverse_iterator it = dq.rbegin();
+ it != dq.rend(); ++it) {
+ EXPECT_EQ(expected_value--, *it);
+ }
+
+ expected_value = 3;
+ for (QuicCircularDeque<int>::const_reverse_iterator it = dq.crbegin();
+ it != dq.crend(); ++it) {
+ EXPECT_EQ(expected_value--, *it);
+ }
+}
+
+TEST(QuicCircularDeque, Iterator) {
+ // Default constructed iterators of the same type compare equal.
+ EXPECT_EQ(QuicCircularDeque<int>::iterator(),
+ QuicCircularDeque<int>::iterator());
+ EXPECT_EQ(QuicCircularDeque<int>::const_iterator(),
+ QuicCircularDeque<int>::const_iterator());
+ EXPECT_EQ(QuicCircularDeque<int>::reverse_iterator(),
+ QuicCircularDeque<int>::reverse_iterator());
+ EXPECT_EQ(QuicCircularDeque<int>::const_reverse_iterator(),
+ QuicCircularDeque<int>::const_reverse_iterator());
+
+ QuicCircularDeque<QuicCircularDeque<int>, 3> dqdq = {
+ {1, 2}, {10, 20, 30}, {100, 200, 300, 400}};
+
+ // iter points to {1, 2}
+ decltype(dqdq)::iterator iter = dqdq.begin();
+ EXPECT_EQ(iter->size(), 2u);
+ EXPECT_THAT(*iter, ElementsAre(1, 2));
+
+ // citer points to {10, 20, 30}
+ decltype(dqdq)::const_iterator citer = dqdq.cbegin() + 1;
+ EXPECT_NE(*iter, *citer);
+ EXPECT_EQ(citer->size(), 3u);
+ int x = 10;
+ for (auto it = citer->begin(); it != citer->end(); ++it) {
+ EXPECT_EQ(*it, x);
+ x += 10;
+ }
+
+ EXPECT_LT(iter, citer);
+ EXPECT_LE(iter, iter);
+ EXPECT_GT(citer, iter);
+ EXPECT_GE(citer, citer);
+
+ // iter points to {100, 200, 300, 400}
+ iter += 2;
+ EXPECT_NE(*iter, *citer);
+ EXPECT_EQ(iter->size(), 4u);
+ for (int i = 1; i <= 4; ++i) {
+ EXPECT_EQ(iter->begin()[i - 1], i * 100);
+ }
+
+ EXPECT_LT(citer, iter);
+ EXPECT_LE(iter, iter);
+ EXPECT_GT(iter, citer);
+ EXPECT_GE(citer, citer);
+
+ // iter points to {10, 20, 30}. (same as citer)
+ iter -= 1;
+ EXPECT_EQ(*iter, *citer);
+ EXPECT_EQ(iter->size(), 3u);
+ x = 10;
+ for (auto it = iter->begin(); it != iter->end();) {
+ EXPECT_EQ(*(it++), x);
+ x += 10;
+ }
+ x = 30;
+ for (auto it = iter->begin() + 2; it != iter->begin();) {
+ EXPECT_EQ(*(it--), x);
+ x -= 10;
+ }
+}
+
+TEST(QuicCircularDeque, Resize) {
+ QuicCircularDeque<int, 3, CountingAllocator<int>> dq;
+ dq.resize(8);
+ EXPECT_THAT(dq, ElementsAre(0, 0, 0, 0, 0, 0, 0, 0));
+ EXPECT_EQ(1u, dq.get_allocator().allocate_count());
+
+ dq.resize(10, 5);
+ EXPECT_THAT(dq, ElementsAre(0, 0, 0, 0, 0, 0, 0, 0, 5, 5));
+
+ QuicCircularDeque<int, 3, CountingAllocator<int>> dq2 = dq;
+
+ for (size_t new_size = dq.size(); new_size != 0; --new_size) {
+ dq.resize(new_size);
+ EXPECT_TRUE(
+ std::equal(dq.begin(), dq.end(), dq2.begin(), dq2.begin() + new_size));
+ }
+
+ dq.resize(0);
+ EXPECT_TRUE(dq.empty());
+
+ // Resize when data is wrapped.
+ ASSERT_EQ(dq2.size(), dq2.capacity());
+ while (dq2.size() < dq2.capacity()) {
+ dq2.push_back(5);
+ }
+
+ // Shift left once such that data is wrapped.
+ ASSERT_LT(&dq2.front(), &dq2.back());
+ dq2.pop_back();
+ dq2.push_front(-5);
+ ASSERT_GT(&dq2.front(), &dq2.back());
+
+ EXPECT_EQ(-5, dq2.front());
+ EXPECT_EQ(5, dq2.back());
+ dq2.resize(dq2.size() + 1, 10);
+
+ // Data should be unwrapped after the resize.
+ ASSERT_LT(&dq2.front(), &dq2.back());
+ EXPECT_EQ(-5, dq2.front());
+ EXPECT_EQ(10, dq2.back());
+ EXPECT_EQ(5, *(dq2.rbegin() + 1));
+}
+
+namespace {
+class Foo {
+ public:
+ Foo() : Foo(0xF00) {}
+
+ explicit Foo(int i) : i_(new int(i)) {}
+
+ ~Foo() {
+ if (i_ != nullptr) {
+ delete i_;
+ // Do not set i_ to nullptr such that if the container calls destructor
+ // multiple times, asan can detect it.
+ }
+ }
+
+ Foo(const Foo& other) : i_(new int(*other.i_)) {}
+
+ Foo(Foo&& other) = delete;
+
+ void Set(int i) { *i_ = i; }
+
+ int i() const { return *i_; }
+
+ friend bool operator==(const Foo& lhs, const Foo& rhs) {
+ return lhs.i() == rhs.i();
+ }
+
+ friend std::ostream& operator<<(std::ostream& os, const Foo& foo) {
+ return os << "Foo(" << foo.i() << ")";
+ }
+
+ private:
+ // By pointing i_ to a dynamically allocated integer, a memory leak will be
+ // reported if the container forget to properly destruct this object.
+ int* i_ = nullptr;
+};
+} // namespace
+
+TEST(QuicCircularDeque, RelocateNonTriviallyCopyable) {
+ // When relocating non-trivially-copyable objects:
+ // - Move constructor is preferred, if available.
+ // - Copy constructor is used otherwise.
+
+ {
+ // Move construct in Relocate.
+ typedef std::unique_ptr<Foo> MoveConstructible;
+ ASSERT_FALSE(std::is_trivially_copyable<MoveConstructible>::value);
+ ASSERT_TRUE(std::is_move_constructible<MoveConstructible>::value);
+ QuicCircularDeque<MoveConstructible, 3,
+ CountingAllocator<MoveConstructible>>
+ dq1;
+ dq1.resize(3);
+ EXPECT_EQ(dq1.size(), dq1.capacity());
+ EXPECT_EQ(1u, dq1.get_allocator().allocate_count());
+
+ dq1.emplace_back(new Foo(0xF1)); // Cause existing elements to relocate.
+ EXPECT_EQ(4u, dq1.size());
+ EXPECT_EQ(2u, dq1.get_allocator().allocate_count());
+ EXPECT_EQ(dq1[0], nullptr);
+ EXPECT_EQ(dq1[1], nullptr);
+ EXPECT_EQ(dq1[2], nullptr);
+ EXPECT_EQ(dq1[3]->i(), 0xF1);
+ }
+
+ {
+ // Copy construct in Relocate.
+ typedef Foo NonMoveConstructible;
+ ASSERT_FALSE(std::is_trivially_copyable<NonMoveConstructible>::value);
+ ASSERT_FALSE(std::is_move_constructible<NonMoveConstructible>::value);
+ QuicCircularDeque<NonMoveConstructible, 3,
+ CountingAllocator<NonMoveConstructible>>
+ dq2;
+ dq2.resize(3);
+ EXPECT_EQ(dq2.size(), dq2.capacity());
+ EXPECT_EQ(1u, dq2.get_allocator().allocate_count());
+
+ dq2.emplace_back(0xF1); // Cause existing elements to relocate.
+ EXPECT_EQ(4u, dq2.size());
+ EXPECT_EQ(2u, dq2.get_allocator().allocate_count());
+ EXPECT_EQ(dq2[0].i(), 0xF00);
+ EXPECT_EQ(dq2[1].i(), 0xF00);
+ EXPECT_EQ(dq2[2].i(), 0xF00);
+ EXPECT_EQ(dq2[3].i(), 0xF1);
+ }
+}
+
+TEST(QuicCircularDeque, PushPop) {
+ // (push|pop|emplace)_(back|front)
+
+ {
+ QuicCircularDeque<Foo, 4, CountingAllocator<Foo>> dq(4);
+ for (size_t i = 0; i < dq.size(); ++i) {
+ dq[i].Set(i + 1);
+ }
+ QUIC_LOG(INFO) << "dq initialized to " << dq;
+ EXPECT_THAT(dq, ElementsAre(Foo(1), Foo(2), Foo(3), Foo(4)));
+
+ ShiftLeft(&dq, false);
+ QUIC_LOG(INFO) << "shift left once : " << dq;
+ EXPECT_THAT(dq, ElementsAre(Foo(2), Foo(3), Foo(4), Foo(1)));
+
+ ShiftLeft(&dq, true);
+ QUIC_LOG(INFO) << "shift left twice: " << dq;
+ EXPECT_THAT(dq, ElementsAre(Foo(3), Foo(4), Foo(1), Foo(2)));
+ ASSERT_GT(&dq.front(), &dq.back());
+ // dq destructs with wrapped data.
+ }
+
+ {
+ QuicCircularDeque<Foo, 4, CountingAllocator<Foo>> dq1(4);
+ for (size_t i = 0; i < dq1.size(); ++i) {
+ dq1[i].Set(i + 1);
+ }
+ QUIC_LOG(INFO) << "dq1 initialized to " << dq1;
+ EXPECT_THAT(dq1, ElementsAre(Foo(1), Foo(2), Foo(3), Foo(4)));
+
+ ShiftRight(&dq1, false);
+ QUIC_LOG(INFO) << "shift right once : " << dq1;
+ EXPECT_THAT(dq1, ElementsAre(Foo(4), Foo(1), Foo(2), Foo(3)));
+
+ ShiftRight(&dq1, true);
+ QUIC_LOG(INFO) << "shift right twice: " << dq1;
+ EXPECT_THAT(dq1, ElementsAre(Foo(3), Foo(4), Foo(1), Foo(2)));
+ ASSERT_GT(&dq1.front(), &dq1.back());
+ // dq1 destructs with wrapped data.
+ }
+
+ { // Pop n elements from front.
+ QuicCircularDeque<Foo, 4, CountingAllocator<Foo>> dq2(5);
+ for (size_t i = 0; i < dq2.size(); ++i) {
+ dq2[i].Set(i + 1);
+ }
+ EXPECT_THAT(dq2, ElementsAre(Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)));
+
+ EXPECT_EQ(2u, dq2.pop_front_n(2));
+ EXPECT_THAT(dq2, ElementsAre(Foo(3), Foo(4), Foo(5)));
+
+ EXPECT_EQ(3u, dq2.pop_front_n(100));
+ EXPECT_TRUE(dq2.empty());
+ }
+
+ { // Pop n elements from back.
+ QuicCircularDeque<Foo, 4, CountingAllocator<Foo>> dq3(6);
+ for (size_t i = 0; i < dq3.size(); ++i) {
+ dq3[i].Set(i + 1);
+ }
+ EXPECT_THAT(dq3,
+ ElementsAre(Foo(1), Foo(2), Foo(3), Foo(4), Foo(5), Foo(6)));
+
+ ShiftRight(&dq3, true);
+ ShiftRight(&dq3, true);
+ ShiftRight(&dq3, true);
+ EXPECT_THAT(dq3,
+ ElementsAre(Foo(4), Foo(5), Foo(6), Foo(1), Foo(2), Foo(3)));
+
+ EXPECT_EQ(2u, dq3.pop_back_n(2));
+ EXPECT_THAT(dq3, ElementsAre(Foo(4), Foo(5), Foo(6), Foo(1)));
+
+ EXPECT_EQ(2u, dq3.pop_back_n(2));
+ EXPECT_THAT(dq3, ElementsAre(Foo(4), Foo(5)));
+ }
+}
+
+TEST(QuicCircularDeque, Allocation) {
+ CountingAllocator<int> alloc;
+
+ {
+ QuicCircularDeque<int, 3, CountingAllocator<int>> dq(alloc);
+ EXPECT_EQ(alloc, dq.get_allocator());
+ EXPECT_EQ(0u, dq.size());
+ EXPECT_EQ(0u, dq.capacity());
+ EXPECT_EQ(0u, alloc.allocate_count());
+ EXPECT_EQ(0u, alloc.deallocate_count());
+
+ for (int i = 1; i <= 18; ++i) {
+ SCOPED_TRACE(testing::Message()
+ << "i=" << i << ", capacity_b4_push=" << dq.capacity());
+ dq.push_back(i);
+ EXPECT_EQ(i, static_cast<int>(dq.size()));
+
+ const size_t capacity = 3 + (i - 1) / 3 * 3;
+ EXPECT_EQ(capacity, dq.capacity());
+ EXPECT_EQ(capacity / 3, alloc.allocate_count());
+ EXPECT_EQ(capacity / 3 - 1, alloc.deallocate_count());
+ }
+
+ dq.push_back(19);
+ EXPECT_EQ(22u, dq.capacity()); // 18 + 18 / 4
+ EXPECT_EQ(7u, alloc.allocate_count());
+ EXPECT_EQ(6u, alloc.deallocate_count());
+ }
+
+ EXPECT_EQ(7u, alloc.deallocate_count());
+}
+
+} // namespace test
+} // namespace quic
+
+// Use a non-quic namespace to make sure swap can be used via ADL.
+namespace {
+
+template <typename T>
+using SwappableAllocator = quic::test::ConfigurableAllocator<
+ T,
+ /*propagate_on_copy_assignment=*/std::true_type,
+ /*propagate_on_move_assignment=*/std::true_type,
+ /*propagate_on_swap=*/std::true_type,
+ /*equality_result=*/true>;
+
+template <typename T>
+using UnswappableEqualAllocator = quic::test::ConfigurableAllocator<
+ T,
+ /*propagate_on_copy_assignment=*/std::true_type,
+ /*propagate_on_move_assignment=*/std::true_type,
+ /*propagate_on_swap=*/std::false_type,
+ /*equality_result=*/true>;
+
+template <typename T>
+using UnswappableUnequalAllocator = quic::test::ConfigurableAllocator<
+ T,
+ /*propagate_on_copy_assignment=*/std::true_type,
+ /*propagate_on_move_assignment=*/std::true_type,
+ /*propagate_on_swap=*/std::false_type,
+ /*equality_result=*/false>;
+
+TEST(QuicCircularDeque, Swap) {
+ using std::swap;
+
+ quic::QuicCircularDeque<int64_t, 3, SwappableAllocator<int64_t>> dq1, dq2;
+ dq1.push_back(10);
+ dq1.push_back(11);
+ dq2.push_back(20);
+ swap(dq1, dq2);
+ EXPECT_THAT(dq1, ElementsAre(20));
+ EXPECT_THAT(dq2, ElementsAre(10, 11));
+
+ quic::QuicCircularDeque<char, 3, UnswappableEqualAllocator<char>> dq3, dq4;
+ dq3 = {1, 2, 3, 4, 5};
+ dq4 = {6, 7, 8, 9, 0};
+ swap(dq3, dq4);
+ EXPECT_THAT(dq3, ElementsAre(6, 7, 8, 9, 0));
+ EXPECT_THAT(dq4, ElementsAre(1, 2, 3, 4, 5));
+
+ quic::QuicCircularDeque<int, 3, UnswappableUnequalAllocator<int>> dq5, dq6;
+ dq6.push_front(4);
+
+ // Using UnswappableUnequalAllocator is ok as long as swap is not called.
+ dq5.assign(dq6.begin(), dq6.end());
+ EXPECT_THAT(dq5, ElementsAre(4));
+
+ // Undefined behavior to swap between two containers with unequal allocators.
+ EXPECT_QUIC_DEBUG_DEATH(swap(dq5, dq6), "Undefined swap behavior");
+}
+} // namespace
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
new file mode 100644
index 00000000000..3dd9b24a4a4
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.cc
@@ -0,0 +1,119 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_coalesced_packet.h"
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
+
+namespace quic {
+
+QuicCoalescedPacket::QuicCoalescedPacket()
+ : length_(0), max_packet_length_(0) {}
+
+QuicCoalescedPacket::~QuicCoalescedPacket() {
+ Clear();
+}
+
+bool QuicCoalescedPacket::MaybeCoalescePacket(
+ const SerializedPacket& packet,
+ const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
+ QuicBufferAllocator* allocator,
+ QuicPacketLength current_max_packet_length) {
+ if (packet.encrypted_length == 0) {
+ QUIC_BUG << "Trying to coalesce an empty packet";
+ return true;
+ }
+ if (length_ == 0) {
+#ifndef NDEBUG
+ for (const auto& buffer : encrypted_buffers_) {
+ DCHECK(buffer.empty());
+ }
+#endif
+ DCHECK(initial_packet_ == nullptr);
+ // This is the first packet, set max_packet_length and self/peer
+ // addresses.
+ max_packet_length_ = current_max_packet_length;
+ self_address_ = self_address;
+ peer_address_ = peer_address;
+ } else {
+ if (self_address_ != self_address || peer_address_ != peer_address) {
+ // Do not coalesce packet with different self/peer addresses.
+ QUIC_DLOG(INFO)
+ << "Cannot coalesce packet because self/peer address changed";
+ return false;
+ }
+ if (max_packet_length_ != current_max_packet_length) {
+ QUIC_BUG << "Max packet length changes in the middle of the write path";
+ return false;
+ }
+ if (!encrypted_buffers_[packet.encryption_level].empty() ||
+ (packet.encryption_level == ENCRYPTION_INITIAL &&
+ initial_packet_ != nullptr)) {
+ // Do not coalesce packets of the same encryption level.
+ return false;
+ }
+ }
+
+ if (length_ + packet.encrypted_length > max_packet_length_) {
+ // Packet does not fit.
+ return false;
+ }
+ QUIC_DVLOG(1) << "Successfully coalesced packet: encryption_level: "
+ << EncryptionLevelToString(packet.encryption_level)
+ << ", encrypted_length: " << packet.encrypted_length
+ << ", current length: " << length_
+ << ", max_packet_length: " << max_packet_length_;
+ if (length_ > 0) {
+ QUIC_CODE_COUNT(QUIC_SUCCESSFULLY_COALESCED_MULTIPLE_PACKETS);
+ }
+ length_ += packet.encrypted_length;
+ 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>(
+ CopySerializedPacket(packet, allocator, /*copy_buffer=*/false));
+ return true;
+ }
+ // Copy encrypted buffer of packets with other encryption levels.
+ encrypted_buffers_[packet.encryption_level] =
+ std::string(packet.encrypted_buffer, packet.encrypted_length);
+ return true;
+}
+
+void QuicCoalescedPacket::Clear() {
+ self_address_ = QuicSocketAddress();
+ peer_address_ = QuicSocketAddress();
+ length_ = 0;
+ max_packet_length_ = 0;
+ for (auto& packet : encrypted_buffers_) {
+ packet.clear();
+ }
+ if (initial_packet_ != nullptr) {
+ ClearSerializedPacket(initial_packet_.get());
+ }
+ initial_packet_ = nullptr;
+}
+
+bool QuicCoalescedPacket::CopyEncryptedBuffers(char* buffer,
+ size_t buffer_len,
+ size_t* length_copied) const {
+ *length_copied = 0;
+ for (const auto& packet : encrypted_buffers_) {
+ if (packet.empty()) {
+ continue;
+ }
+ if (packet.length() > buffer_len) {
+ return false;
+ }
+ memcpy(buffer, packet.data(), packet.length());
+ buffer += packet.length();
+ buffer_len -= packet.length();
+ *length_copied += packet.length();
+ }
+ return true;
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.h b/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.h
new file mode 100644
index 00000000000..f03f87544b9
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet.h
@@ -0,0 +1,72 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_QUIC_COALESCED_PACKET_H_
+#define QUICHE_QUIC_CORE_QUIC_COALESCED_PACKET_H_
+
+#include "net/third_party/quiche/src/quic/core/quic_packets.h"
+
+namespace quic {
+
+// QuicCoalescedPacket is used to buffer multiple packets which can be coalesced
+// into the same UDP datagram.
+class QUIC_EXPORT_PRIVATE QuicCoalescedPacket {
+ public:
+ QuicCoalescedPacket();
+ ~QuicCoalescedPacket();
+
+ // Returns true if |packet| is successfully coalesced with existing packets.
+ // Returns false otherwise.
+ bool MaybeCoalescePacket(const SerializedPacket& packet,
+ const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address,
+ QuicBufferAllocator* allocator,
+ QuicPacketLength current_max_packet_length);
+
+ // Clears this coalesced packet.
+ void Clear();
+
+ // Copies encrypted_buffers_ to |buffer| and sets |length_copied| to the
+ // copied amount. Returns false if copy fails (i.e., |buffer_len| is not
+ // enough).
+ bool CopyEncryptedBuffers(char* buffer,
+ size_t buffer_len,
+ size_t* length_copied) const;
+
+ const SerializedPacket* initial_packet() const {
+ return initial_packet_.get();
+ }
+
+ const QuicSocketAddress& self_address() const { return self_address_; }
+
+ const QuicSocketAddress& peer_address() const { return peer_address_; }
+
+ QuicPacketLength length() const { return length_; }
+
+ QuicPacketLength max_packet_length() const { return max_packet_length_; }
+
+ private:
+ // self/peer addresses are set when trying to coalesce the first packet.
+ // Packets with different self/peer addresses cannot be coalesced.
+ QuicSocketAddress self_address_;
+ QuicSocketAddress peer_address_;
+ // Length of this coalesced packet.
+ QuicPacketLength length_;
+ // Max packet length. Do not try to coalesce packet when max packet length
+ // changes (e.g., with MTU discovery).
+ QuicPacketLength max_packet_length_;
+ // Copies of packets' encrypted buffers according to different encryption
+ // levels.
+ std::string encrypted_buffers_[NUM_ENCRYPTION_LEVELS];
+
+ // A copy of ENCRYPTION_INITIAL packet if this coalesced packet contains one.
+ // Null otherwise. Please note, the encrypted_buffer field is not copied. The
+ // frames are copied to allow it be re-serialized when this coalesced packet
+ // gets sent.
+ std::unique_ptr<SerializedPacket> initial_packet_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QUIC_COALESCED_PACKET_H_
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
new file mode 100644
index 00000000000..8213480bf91
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_coalesced_packet_test.cc
@@ -0,0 +1,114 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_coalesced_packet.h"
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+
+namespace quic {
+namespace test {
+namespace {
+
+TEST(QuicCoalescedPacketTest, MaybeCoalescePacket) {
+ QuicCoalescedPacket coalesced;
+ SimpleBufferAllocator allocator;
+ EXPECT_EQ(0u, coalesced.length());
+ char buffer[1000];
+ QuicSocketAddress self_address(QuicIpAddress::Loopback4(), 1);
+ QuicSocketAddress peer_address(QuicIpAddress::Loopback4(), 2);
+ SerializedPacket packet1(QuicPacketNumber(1), PACKET_4BYTE_PACKET_NUMBER,
+ buffer, 500, false, false);
+ QuicAckFrame ack_frame(InitAckFrame(1));
+ packet1.nonretransmittable_frames.push_back(QuicFrame(&ack_frame));
+ packet1.retransmittable_frames.push_back(
+ QuicFrame(QuicStreamFrame(1, true, 0, 100)));
+ ASSERT_TRUE(coalesced.MaybeCoalescePacket(packet1, self_address, peer_address,
+ &allocator, 1500));
+ EXPECT_EQ(1500u, coalesced.max_packet_length());
+ EXPECT_EQ(500u, coalesced.length());
+
+ // Cannot coalesce packet of the same encryption level.
+ SerializedPacket packet2(QuicPacketNumber(2), PACKET_4BYTE_PACKET_NUMBER,
+ buffer, 500, false, false);
+ EXPECT_FALSE(coalesced.MaybeCoalescePacket(packet2, self_address,
+ peer_address, &allocator, 1500));
+
+ SerializedPacket packet3(QuicPacketNumber(3), PACKET_4BYTE_PACKET_NUMBER,
+ buffer, 500, false, false);
+ packet3.nonretransmittable_frames.push_back(QuicFrame(QuicPaddingFrame(100)));
+ packet3.encryption_level = ENCRYPTION_ZERO_RTT;
+ ASSERT_TRUE(coalesced.MaybeCoalescePacket(packet3, self_address, peer_address,
+ &allocator, 1500));
+ EXPECT_EQ(1500u, coalesced.max_packet_length());
+ EXPECT_EQ(1000u, coalesced.length());
+
+ SerializedPacket packet4(QuicPacketNumber(4), PACKET_4BYTE_PACKET_NUMBER,
+ buffer, 500, false, false);
+ packet4.encryption_level = ENCRYPTION_FORWARD_SECURE;
+ // Cannot coalesce packet of changed self/peer address.
+ EXPECT_FALSE(coalesced.MaybeCoalescePacket(
+ packet4, QuicSocketAddress(QuicIpAddress::Loopback4(), 3), peer_address,
+ &allocator, 1500));
+
+ // Packet does not fit.
+ SerializedPacket packet5(QuicPacketNumber(5), PACKET_4BYTE_PACKET_NUMBER,
+ buffer, 501, false, false);
+ packet5.encryption_level = ENCRYPTION_FORWARD_SECURE;
+ EXPECT_FALSE(coalesced.MaybeCoalescePacket(packet5, self_address,
+ peer_address, &allocator, 1500));
+ EXPECT_EQ(1500u, coalesced.max_packet_length());
+ EXPECT_EQ(1000u, coalesced.length());
+
+ // Max packet number length changed.
+ SerializedPacket packet6(QuicPacketNumber(6), PACKET_4BYTE_PACKET_NUMBER,
+ buffer, 100, false, false);
+ packet6.encryption_level = ENCRYPTION_FORWARD_SECURE;
+ EXPECT_QUIC_BUG(coalesced.MaybeCoalescePacket(packet6, self_address,
+ peer_address, &allocator, 1000),
+ "Max packet length changes in the middle of the write path");
+ EXPECT_EQ(1500u, coalesced.max_packet_length());
+ EXPECT_EQ(1000u, coalesced.length());
+}
+
+TEST(QuicCoalescedPacketTest, CopyEncryptedBuffers) {
+ QuicCoalescedPacket coalesced;
+ SimpleBufferAllocator allocator;
+ QuicSocketAddress self_address(QuicIpAddress::Loopback4(), 1);
+ QuicSocketAddress peer_address(QuicIpAddress::Loopback4(), 2);
+ std::string buffer(500, 'a');
+ std::string buffer2(500, 'b');
+ SerializedPacket packet1(QuicPacketNumber(1), PACKET_4BYTE_PACKET_NUMBER,
+ buffer.data(), 500,
+ /*has_ack=*/false, /*has_stop_waiting=*/false);
+ packet1.encryption_level = ENCRYPTION_ZERO_RTT;
+ SerializedPacket packet2(QuicPacketNumber(2), PACKET_4BYTE_PACKET_NUMBER,
+ buffer2.data(), 500,
+ /*has_ack=*/false, /*has_stop_waiting=*/false);
+ packet2.encryption_level = ENCRYPTION_FORWARD_SECURE;
+
+ ASSERT_TRUE(coalesced.MaybeCoalescePacket(packet1, self_address, peer_address,
+ &allocator, 1500));
+ ASSERT_TRUE(coalesced.MaybeCoalescePacket(packet2, self_address, peer_address,
+ &allocator, 1500));
+ EXPECT_EQ(1000u, coalesced.length());
+
+ char copy_buffer[1000];
+ size_t length_copied = 0;
+ EXPECT_FALSE(
+ coalesced.CopyEncryptedBuffers(copy_buffer, 900, &length_copied));
+ ASSERT_TRUE(
+ coalesced.CopyEncryptedBuffers(copy_buffer, 1000, &length_copied));
+ EXPECT_EQ(1000u, length_copied);
+ char expected[1000];
+ memset(expected, 'a', 500);
+ memset(expected + 500, 'b', 500);
+ test::CompareCharArraysWithHexError("copied buffers", copy_buffer,
+ length_copied, expected, 1000);
+}
+
+} // namespace
+} // namespace test
+} // namespace quic
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 a3840ec8e9b..3d8fe3fa318 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
@@ -420,7 +420,9 @@ QuicConfig::QuicConfig()
stateless_reset_token_(kSRST, PRESENCE_OPTIONAL),
max_incoming_unidirectional_streams_(kMIUS, PRESENCE_OPTIONAL),
max_ack_delay_ms_(kMAD, PRESENCE_OPTIONAL),
- ack_delay_exponent_(kADE, PRESENCE_OPTIONAL) {
+ ack_delay_exponent_(kADE, PRESENCE_OPTIONAL),
+ max_packet_size_(0, PRESENCE_OPTIONAL),
+ max_datagram_frame_size_(0, PRESENCE_OPTIONAL) {
SetDefaults();
}
@@ -579,6 +581,39 @@ uint32_t QuicConfig::ReceivedAckDelayExponent() const {
return ack_delay_exponent_.GetReceivedValue();
}
+void QuicConfig::SetMaxPacketSizeToSend(uint32_t max_packet_size) {
+ max_packet_size_.SetSendValue(max_packet_size);
+}
+
+uint32_t QuicConfig::GetMaxPacketSizeToSend() const {
+ return max_packet_size_.GetSendValue();
+}
+
+bool QuicConfig::HasReceivedMaxPacketSize() const {
+ return max_packet_size_.HasReceivedValue();
+}
+
+uint32_t QuicConfig::ReceivedMaxPacketSize() const {
+ return max_packet_size_.GetReceivedValue();
+}
+
+void QuicConfig::SetMaxDatagramFrameSizeToSend(
+ uint32_t max_datagram_frame_size) {
+ max_datagram_frame_size_.SetSendValue(max_datagram_frame_size);
+}
+
+uint32_t QuicConfig::GetMaxDatagramFrameSizeToSend() const {
+ return max_datagram_frame_size_.GetSendValue();
+}
+
+bool QuicConfig::HasReceivedMaxDatagramFrameSize() const {
+ return max_datagram_frame_size_.HasReceivedValue();
+}
+
+uint32_t QuicConfig::ReceivedMaxDatagramFrameSize() const {
+ return max_datagram_frame_size_.GetReceivedValue();
+}
+
bool QuicConfig::HasSetBytesForConnectionIdToSend() const {
return bytes_for_connection_id_.HasSendValue();
}
@@ -806,6 +841,8 @@ void QuicConfig::SetDefaults() {
SetMaxAckDelayToSendMs(kDefaultDelayedAckTimeMs);
SetSupportMaxHeaderListSize();
SetAckDelayExponentToSend(kDefaultAckDelayExponent);
+ SetMaxPacketSizeToSend(kMaxIncomingPacketSize);
+ SetMaxDatagramFrameSizeToSend(kMaxAcceptedDatagramFrameSize);
}
void QuicConfig::ToHandshakeMessage(
@@ -921,7 +958,8 @@ bool QuicConfig::FillTransportParameters(TransportParameters* params) const {
sizeof(stateless_reset_token));
}
- params->max_packet_size.set_value(kMaxIncomingPacketSize);
+ params->max_packet_size.set_value(GetMaxPacketSizeToSend());
+ params->max_datagram_frame_size.set_value(GetMaxDatagramFrameSizeToSend());
params->initial_max_data.set_value(
GetInitialSessionFlowControlWindowToSend());
// The max stream data bidirectional transport parameters can be either local
@@ -1008,10 +1046,19 @@ QuicErrorCode QuicConfig::ProcessTransportParameters(
stateless_reset_token_.SetReceivedValue(stateless_reset_token);
}
- if (params.max_packet_size.value() < kMaxOutgoingPacketSize) {
+ if (params.max_packet_size.IsValid()) {
+ max_packet_size_.SetReceivedValue(params.max_packet_size.value());
+ if (ReceivedMaxPacketSize() < kMaxOutgoingPacketSize) {
+ // TODO(dschinazi) act on this.
+ QUIC_DLOG(ERROR) << "Ignoring peer's requested max packet size of "
+ << ReceivedMaxPacketSize();
+ }
+ }
+
+ if (params.max_datagram_frame_size.IsValid()) {
+ max_datagram_frame_size_.SetReceivedValue(
+ params.max_datagram_frame_size.value());
// TODO(dschinazi) act on this.
- QUIC_DLOG(ERROR) << "Ignoring peer's requested max packet size of "
- << params.max_packet_size.value();
}
initial_session_flow_control_window_bytes_.SetReceivedValue(
@@ -1048,8 +1095,9 @@ QuicErrorCode QuicConfig::ProcessTransportParameters(
if (params.ack_delay_exponent.IsValid()) {
ack_delay_exponent_.SetReceivedValue(params.ack_delay_exponent.value());
}
- connection_migration_disabled_.SetReceivedValue(
- params.disable_migration ? 1u : 0u);
+ if (params.disable_migration) {
+ connection_migration_disabled_.SetReceivedValue(1u);
+ }
if (params.preferred_address != nullptr) {
if (params.preferred_address->ipv6_socket_address.port() != 0) {
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 ecece2ae49f..de78d40144a 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
@@ -456,6 +456,18 @@ class QUIC_EXPORT_PRIVATE QuicConfig {
bool HasReceivedAckDelayExponent() const;
uint32_t ReceivedAckDelayExponent() const;
+ // IETF QUIC max_packet_size transport parameter.
+ void SetMaxPacketSizeToSend(uint32_t max_packet_size);
+ uint32_t GetMaxPacketSizeToSend() const;
+ bool HasReceivedMaxPacketSize() const;
+ uint32_t ReceivedMaxPacketSize() const;
+
+ // IETF QUIC max_datagram_frame_size transport parameter.
+ void SetMaxDatagramFrameSizeToSend(uint32_t max_datagram_frame_size);
+ uint32_t GetMaxDatagramFrameSizeToSend() const;
+ bool HasReceivedMaxDatagramFrameSize() const;
+ uint32_t ReceivedMaxDatagramFrameSize() const;
+
bool negotiated() const;
void SetCreateSessionTagIndicators(QuicTagVector tags);
@@ -573,6 +585,12 @@ class QUIC_EXPORT_PRIVATE QuicConfig {
// to serialize frames and this node uses to deserialize them.
QuicFixedUint32 ack_delay_exponent_;
+ // max_packet_size IETF QUIC transport parameter.
+ QuicFixedUint32 max_packet_size_;
+
+ // max_datagram_frame_size IETF QUIC transport parameter.
+ QuicFixedUint32 max_datagram_frame_size_;
+
// Custom transport parameters that can be sent and received in the TLS
// handshake.
TransportParameters::ParameterMap custom_transport_parameters_to_send_;
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 e0eb304a945..69ce78de0fd 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
@@ -21,6 +21,9 @@ namespace quic {
namespace test {
namespace {
+const uint32_t kMaxPacketSizeForTest = 1234;
+const uint32_t kMaxDatagramFrameSizeForTest = 1333;
+
class QuicConfigTest : public QuicTestWithParam<QuicTransportVersion> {
protected:
QuicConfig config_;
@@ -47,6 +50,8 @@ TEST_P(QuicConfigTest, SetDefaults) {
EXPECT_FALSE(
config_.HasReceivedInitialMaxStreamDataBytesOutgoingBidirectional());
EXPECT_FALSE(config_.HasReceivedInitialMaxStreamDataBytesUnidirectional());
+ EXPECT_EQ(kMaxIncomingPacketSize, config_.GetMaxPacketSizeToSend());
+ EXPECT_FALSE(config_.HasReceivedMaxPacketSize());
}
TEST_P(QuicConfigTest, AutoSetIetfFlowControl) {
@@ -91,15 +96,15 @@ TEST_P(QuicConfigTest, ToHandshakeMessage) {
uint32_t value;
QuicErrorCode error = msg.GetUint32(kICSL, &value);
- EXPECT_EQ(QUIC_NO_ERROR, error);
+ EXPECT_THAT(error, IsQuicNoError());
EXPECT_EQ(5u, value);
error = msg.GetUint32(kSFCW, &value);
- EXPECT_EQ(QUIC_NO_ERROR, error);
+ EXPECT_THAT(error, IsQuicNoError());
EXPECT_EQ(kInitialStreamFlowControlWindowForTest, value);
error = msg.GetUint32(kCFCW, &value);
- EXPECT_EQ(QUIC_NO_ERROR, error);
+ EXPECT_THAT(error, IsQuicNoError());
EXPECT_EQ(kInitialSessionFlowControlWindowForTest, value);
}
@@ -137,7 +142,7 @@ TEST_P(QuicConfigTest, ProcessClientHello) {
EXPECT_FALSE(
config_.SetInitialReceivedConnectionOptions(initial_received_options))
<< "You cannot set initial options after the hello.";
- EXPECT_EQ(QUIC_NO_ERROR, error);
+ EXPECT_THAT(error, IsQuicNoError());
EXPECT_TRUE(config_.negotiated());
EXPECT_EQ(QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs),
config_.IdleNetworkTimeout());
@@ -191,7 +196,7 @@ TEST_P(QuicConfigTest, ProcessServerHello) {
std::string error_details;
const QuicErrorCode error =
config_.ProcessPeerHello(msg, SERVER, &error_details);
- EXPECT_EQ(QUIC_NO_ERROR, error);
+ EXPECT_THAT(error, IsQuicNoError());
EXPECT_TRUE(config_.negotiated());
EXPECT_EQ(QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs / 2),
config_.IdleNetworkTimeout());
@@ -231,7 +236,7 @@ TEST_P(QuicConfigTest, MissingOptionalValuesInCHLO) {
std::string error_details;
const QuicErrorCode error =
config_.ProcessPeerHello(msg, CLIENT, &error_details);
- EXPECT_EQ(QUIC_NO_ERROR, error);
+ EXPECT_THAT(error, IsQuicNoError());
EXPECT_TRUE(config_.negotiated());
}
@@ -246,7 +251,7 @@ TEST_P(QuicConfigTest, MissingOptionalValuesInSHLO) {
std::string error_details;
const QuicErrorCode error =
config_.ProcessPeerHello(msg, SERVER, &error_details);
- EXPECT_EQ(QUIC_NO_ERROR, error);
+ EXPECT_THAT(error, IsQuicNoError());
EXPECT_TRUE(config_.negotiated());
}
@@ -256,7 +261,7 @@ TEST_P(QuicConfigTest, MissingValueInCHLO) {
std::string error_details;
const QuicErrorCode error =
config_.ProcessPeerHello(msg, CLIENT, &error_details);
- EXPECT_EQ(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND, error);
+ EXPECT_THAT(error, IsError(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND));
}
TEST_P(QuicConfigTest, MissingValueInSHLO) {
@@ -265,7 +270,7 @@ TEST_P(QuicConfigTest, MissingValueInSHLO) {
std::string error_details;
const QuicErrorCode error =
config_.ProcessPeerHello(msg, SERVER, &error_details);
- EXPECT_EQ(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND, error);
+ EXPECT_THAT(error, IsError(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND));
}
TEST_P(QuicConfigTest, OutOfBoundSHLO) {
@@ -279,7 +284,7 @@ TEST_P(QuicConfigTest, OutOfBoundSHLO) {
std::string error_details;
const QuicErrorCode error =
config_.ProcessPeerHello(msg, SERVER, &error_details);
- EXPECT_EQ(QUIC_INVALID_NEGOTIATED_VALUE, error);
+ EXPECT_THAT(error, IsError(QUIC_INVALID_NEGOTIATED_VALUE));
}
TEST_P(QuicConfigTest, InvalidFlowControlWindow) {
@@ -309,7 +314,7 @@ TEST_P(QuicConfigTest, HasClientSentConnectionOption) {
std::string error_details;
const QuicErrorCode error =
config_.ProcessPeerHello(msg, CLIENT, &error_details);
- EXPECT_EQ(QUIC_NO_ERROR, error);
+ EXPECT_THAT(error, IsQuicNoError());
EXPECT_TRUE(config_.negotiated());
EXPECT_TRUE(config_.HasReceivedConnectionOptions());
@@ -330,7 +335,7 @@ TEST_P(QuicConfigTest, DontSendClientConnectionOptions) {
std::string error_details;
const QuicErrorCode error =
config_.ProcessPeerHello(msg, CLIENT, &error_details);
- EXPECT_EQ(QUIC_NO_ERROR, error);
+ EXPECT_THAT(error, IsQuicNoError());
EXPECT_TRUE(config_.negotiated());
EXPECT_FALSE(config_.HasReceivedConnectionOptions());
@@ -357,7 +362,7 @@ TEST_P(QuicConfigTest, HasClientRequestedIndependentOption) {
std::string error_details;
const QuicErrorCode error =
config_.ProcessPeerHello(msg, CLIENT, &error_details);
- EXPECT_EQ(QUIC_NO_ERROR, error);
+ EXPECT_THAT(error, IsQuicNoError());
EXPECT_TRUE(config_.negotiated());
EXPECT_TRUE(config_.HasReceivedConnectionOptions());
@@ -377,8 +382,9 @@ TEST_P(QuicConfigTest, IncomingLargeIdleTimeoutTransportParameter) {
params.idle_timeout_milliseconds.set_value(120000);
std::string error_details = "foobar";
- EXPECT_EQ(QUIC_NO_ERROR,
- config_.ProcessTransportParameters(params, SERVER, &error_details));
+ EXPECT_THAT(
+ config_.ProcessTransportParameters(params, SERVER, &error_details),
+ IsQuicNoError());
EXPECT_EQ("", error_details);
EXPECT_EQ(quic::QuicTime::Delta::FromSeconds(60),
config_.IdleNetworkTimeout());
@@ -391,6 +397,8 @@ TEST_P(QuicConfigTest, FillTransportParams) {
3 * kMinimumFlowControlSendWindow);
config_.SetInitialMaxStreamDataBytesUnidirectionalToSend(
4 * kMinimumFlowControlSendWindow);
+ config_.SetMaxPacketSizeToSend(kMaxPacketSizeForTest);
+ config_.SetMaxDatagramFrameSizeToSend(kMaxDatagramFrameSizeForTest);
TransportParameters params;
config_.FillTransportParameters(&params);
@@ -404,6 +412,10 @@ TEST_P(QuicConfigTest, FillTransportParams) {
EXPECT_EQ(static_cast<uint64_t>(kMaximumIdleTimeoutSecs * 1000),
params.idle_timeout_milliseconds.value());
+
+ EXPECT_EQ(kMaxPacketSizeForTest, params.max_packet_size.value());
+ EXPECT_EQ(kMaxDatagramFrameSizeForTest,
+ params.max_datagram_frame_size.value());
}
TEST_P(QuicConfigTest, ProcessTransportParametersServer) {
@@ -415,10 +427,13 @@ TEST_P(QuicConfigTest, ProcessTransportParametersServer) {
3 * kMinimumFlowControlSendWindow);
params.initial_max_stream_data_uni.set_value(4 *
kMinimumFlowControlSendWindow);
+ params.max_packet_size.set_value(kMaxPacketSizeForTest);
+ params.max_datagram_frame_size.set_value(kMaxDatagramFrameSizeForTest);
std::string error_details;
- EXPECT_EQ(QUIC_NO_ERROR,
- config_.ProcessTransportParameters(params, SERVER, &error_details));
+ EXPECT_THAT(
+ config_.ProcessTransportParameters(params, SERVER, &error_details),
+ IsQuicNoError());
ASSERT_TRUE(
config_.HasReceivedInitialMaxStreamDataBytesIncomingBidirectional());
@@ -433,6 +448,25 @@ TEST_P(QuicConfigTest, ProcessTransportParametersServer) {
ASSERT_TRUE(config_.HasReceivedInitialMaxStreamDataBytesUnidirectional());
EXPECT_EQ(4 * kMinimumFlowControlSendWindow,
config_.ReceivedInitialMaxStreamDataBytesUnidirectional());
+
+ ASSERT_TRUE(config_.HasReceivedMaxPacketSize());
+ EXPECT_EQ(kMaxPacketSizeForTest, config_.ReceivedMaxPacketSize());
+
+ ASSERT_TRUE(config_.HasReceivedMaxDatagramFrameSize());
+ EXPECT_EQ(kMaxDatagramFrameSizeForTest,
+ config_.ReceivedMaxDatagramFrameSize());
+
+ EXPECT_FALSE(config_.DisableConnectionMigration());
+}
+
+TEST_P(QuicConfigTest, DisableMigrationTransportParameter) {
+ TransportParameters params;
+ params.disable_migration = true;
+ std::string error_details;
+ EXPECT_THAT(
+ config_.ProcessTransportParameters(params, SERVER, &error_details),
+ IsQuicNoError());
+ EXPECT_TRUE(config_.DisableConnectionMigration());
}
} // namespace
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 cb2409592a0..9349bf234fd 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
@@ -24,8 +24,6 @@
#include "net/third_party/quiche/src/quic/core/quic_config.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
-#include "net/third_party/quiche/src/quic/core/quic_packet_generator.h"
-#include "net/third_party/quiche/src/quic/core/quic_pending_retransmission.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
@@ -180,6 +178,17 @@ class ProcessUndecryptablePacketsAlarmDelegate : public QuicAlarm::Delegate {
QuicConnection* connection_;
};
+// When the clearer goes out of scope, the coalesced packet gets cleared.
+class ScopedCoalescedPacketClearer {
+ public:
+ explicit ScopedCoalescedPacketClearer(QuicCoalescedPacket* coalesced)
+ : coalesced_(coalesced) {}
+ ~ScopedCoalescedPacketClearer() { coalesced_->Clear(); }
+
+ private:
+ QuicCoalescedPacket* coalesced_; // Unowned.
+};
+
// Whether this incoming packet is allowed to replace our connection ID.
bool PacketCanReplaceConnectionId(const QuicPacketHeader& header,
Perspective perspective) {
@@ -256,7 +265,8 @@ QuicConnection::QuicConnection(
pending_retransmission_alarm_(false),
defer_send_in_response_to_packets_(false),
ping_timeout_(QuicTime::Delta::FromSeconds(kPingTimeoutSecs)),
- retransmittable_on_wire_timeout_(QuicTime::Delta::Infinite()),
+ initial_retransmittable_on_wire_timeout_(QuicTime::Delta::Infinite()),
+ consecutive_retransmittable_on_wire_ping_count_(0),
arena_(),
ack_alarm_(alarm_factory_->CreateAlarm(arena_.New<AckAlarmDelegate>(this),
&arena_)),
@@ -283,10 +293,7 @@ QuicConnection::QuicConnection(
&arena_)),
visitor_(nullptr),
debug_visitor_(nullptr),
- packet_generator_(server_connection_id_,
- &framer_,
- random_generator_,
- this),
+ packet_creator_(server_connection_id_, &framer_, random_generator_, this),
idle_network_timeout_(QuicTime::Delta::Infinite()),
handshake_timeout_(QuicTime::Delta::Infinite()),
time_of_first_packet_sent_after_receiving_(QuicTime::Zero()),
@@ -301,10 +308,7 @@ QuicConnection::QuicConnection(
perspective_(perspective),
connected_(true),
can_truncate_connection_ids_(perspective == Perspective::IS_SERVER),
- mtu_discovery_target_(0),
mtu_probe_count_(0),
- packets_between_mtu_probes_(kPacketsBetweenMtuProbesBase),
- next_mtu_probe_at_(kPacketsBetweenMtuProbesBase),
largest_received_packet_size_(0),
write_error_occurred_(false),
no_stop_waiting_frames_(
@@ -326,10 +330,11 @@ QuicConnection::QuicConnection(
bytes_received_before_address_validation_(0),
bytes_sent_before_address_validation_(0),
address_validated_(false),
- skip_packet_number_for_pto_(false),
- treat_queued_packets_as_sent_(
- GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)),
- mtu_discovery_v2_(GetQuicReloadableFlag(quic_mtu_discovery_v2)) {
+ quic_version_negotiated_by_default_at_server_(
+ GetQuicReloadableFlag(quic_version_negotiated_by_default_at_server)),
+ use_handshake_delegate_(
+ GetQuicReloadableFlag(quic_use_handshaker_delegate) ||
+ version().handshake_protocol == PROTOCOL_TLS1_3) {
QUIC_DLOG(INFO) << ENDPOINT << "Created connection with server connection ID "
<< server_connection_id
<< " and version: " << ParsedQuicVersionToString(version());
@@ -339,6 +344,9 @@ QuicConnection::QuicConnection(
<< "QuicConnection: attempted to use server connection ID "
<< server_connection_id << " which is invalid with version "
<< QuicVersionToString(transport_version());
+ if (use_handshake_delegate_) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_use_handshaker_delegate);
+ }
framer_.set_visitor(this);
stats_.connection_creation_time = clock_->ApproximateNow();
@@ -356,20 +364,23 @@ QuicConnection::QuicConnection(
? kDefaultServerMaxPacketSize
: kDefaultMaxPacketSize);
uber_received_packet_manager_.set_max_ack_ranges(255);
- MaybeEnableSessionDecidesWhatToWrite();
+ if (version().SupportsAntiAmplificationLimit()) {
+ sent_packet_manager_.EnableIetfPtoAndLossDetection();
+ }
MaybeEnableMultiplePacketNumberSpacesSupport();
DCHECK(perspective_ == Perspective::IS_CLIENT ||
supported_versions.size() == 1);
InstallInitialCrypters(server_connection_id_);
+
+ if (quic_version_negotiated_by_default_at_server() &&
+ perspective_ == Perspective::IS_SERVER) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_version_negotiated_by_default_at_server);
+ version_negotiated_ = true;
+ framer_.InferPacketHeaderTypeFromVersion();
+ }
}
void QuicConnection::InstallInitialCrypters(QuicConnectionId connection_id) {
- if (!framer_.framer_doesnt_create_initial_encrypter() &&
- !version().UsesInitialObfuscators() &&
- version().handshake_protocol != PROTOCOL_TLS1_3) {
- // Initial crypters are currently only supported with TLS.
- return;
- }
CrypterPair crypters;
CryptoUtils::CreateInitialObfuscators(perspective_, version(), connection_id,
&crypters);
@@ -389,15 +400,6 @@ QuicConnection::~QuicConnection() {
}
void QuicConnection::ClearQueuedPackets() {
- for (auto it = queued_packets_.begin(); it != queued_packets_.end(); ++it) {
- // Delete the buffer before calling ClearSerializedPacket, which sets
- // encrypted_buffer to nullptr.
- DCHECK(!treat_queued_packets_as_sent_);
- delete[] it->encrypted_buffer;
- ClearSerializedPacket(&(*it));
- }
- queued_packets_.clear();
-
buffered_packets_.clear();
}
@@ -418,17 +420,18 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
sent_packet_manager_.SetFromConfig(config);
if (config.HasReceivedBytesForConnectionId() &&
can_truncate_connection_ids_) {
- packet_generator_.SetServerConnectionIdLength(
+ packet_creator_.SetServerConnectionIdLength(
config.ReceivedBytesForConnectionId());
}
max_undecryptable_packets_ = config.max_undecryptable_packets();
- if (config.HasClientSentConnectionOption(kMTUH, perspective_)) {
+ if (config.HasClientRequestedIndependentOption(kMTUH, perspective_)) {
SetMtuDiscoveryTarget(kMtuDiscoveryTargetPacketSizeHigh);
}
- if (config.HasClientSentConnectionOption(kMTUL, perspective_)) {
+ if (config.HasClientRequestedIndependentOption(kMTUL, perspective_)) {
SetMtuDiscoveryTarget(kMtuDiscoveryTargetPacketSizeLow);
}
+
if (debug_visitor_ != nullptr) {
debug_visitor_->OnSetFromConfig(config);
}
@@ -443,16 +446,11 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
}
if (config.HasClientSentConnectionOption(k7PTO, perspective_)) {
max_consecutive_ptos_ = 6;
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 3, 4);
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 3, 8);
}
if (config.HasClientSentConnectionOption(k8PTO, perspective_)) {
max_consecutive_ptos_ = 7;
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 4, 4);
- }
- if (GetQuicReloadableFlag(quic_skip_packet_number_for_pto) &&
- config.HasClientSentConnectionOption(kPTOS, perspective_)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_skip_packet_number_for_pto);
- skip_packet_number_for_pto_ = true;
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 4, 8);
}
}
if (config.HasClientSentConnectionOption(kNSTP, perspective_)) {
@@ -506,11 +504,9 @@ void QuicConnection::SetMaxPacingRate(QuicBandwidth max_pacing_rate) {
sent_packet_manager_.SetMaxPacingRate(max_pacing_rate);
}
-void QuicConnection::AdjustNetworkParameters(QuicBandwidth bandwidth,
- QuicTime::Delta rtt,
- bool allow_cwnd_to_decrease) {
- sent_packet_manager_.AdjustNetworkParameters(bandwidth, rtt,
- allow_cwnd_to_decrease);
+void QuicConnection::AdjustNetworkParameters(
+ const SendAlgorithmInterface::NetworkParams& params) {
+ sent_packet_manager_.AdjustNetworkParameters(params);
}
QuicBandwidth QuicConnection::MaxPacingRate() const {
@@ -657,8 +653,8 @@ void QuicConnection::OnRetryPacket(QuicConnectionId original_connection_id,
<< ", received token "
<< QuicTextUtils::HexEncode(retry_token);
server_connection_id_ = new_connection_id;
- packet_generator_.SetServerConnectionId(server_connection_id_);
- packet_generator_.SetRetryToken(retry_token);
+ packet_creator_.SetServerConnectionId(server_connection_id_);
+ packet_creator_.SetRetryToken(retry_token);
// Reinstall initial crypters because the connection ID changed.
InstallInitialCrypters(server_connection_id_);
@@ -751,7 +747,7 @@ bool QuicConnection::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
GetServerConnectionIdAsRecipient(header, perspective_)) ||
PacketCanReplaceConnectionId(header, perspective_));
- if (packet_generator_.HasPendingFrames()) {
+ if (packet_creator_.HasPendingFrames()) {
// Incoming packets may change a queued ACK frame.
const std::string error_details =
"Pending frames must be serialized before incoming packets are "
@@ -762,32 +758,41 @@ bool QuicConnection::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
return false;
}
- if (!version_negotiated_ && perspective_ == Perspective::IS_SERVER) {
- if (!header.version_flag) {
- // Packets should have the version flag till version negotiation is
- // done.
- std::string error_details =
- QuicStrCat(ENDPOINT, "Packet ", header.packet_number.ToUint64(),
- " without version flag before version negotiated.");
- QUIC_DLOG(WARNING) << error_details;
- CloseConnection(QUIC_INVALID_VERSION, error_details,
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return false;
- } else {
- DCHECK_EQ(header.version, version());
- version_negotiated_ = true;
- framer_.InferPacketHeaderTypeFromVersion();
- visitor_->OnSuccessfulVersionNegotiation(version());
- if (debug_visitor_ != nullptr) {
- debug_visitor_->OnSuccessfulVersionNegotiation(version());
+ if (!quic_version_negotiated_by_default_at_server()) {
+ if (!version_negotiated_ && perspective_ == Perspective::IS_SERVER) {
+ if (!header.version_flag) {
+ // Packets should have the version flag till version negotiation is
+ // done.
+ std::string error_details =
+ QuicStrCat(ENDPOINT, "Packet ", header.packet_number.ToUint64(),
+ " without version flag before version negotiated.");
+ QUIC_DLOG(WARNING) << error_details;
+ CloseConnection(QUIC_INVALID_VERSION, error_details,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ } else {
+ DCHECK_EQ(header.version, version());
+ version_negotiated_ = true;
+ framer_.InferPacketHeaderTypeFromVersion();
+ visitor_->OnSuccessfulVersionNegotiation(version());
+ if (debug_visitor_ != nullptr) {
+ debug_visitor_->OnSuccessfulVersionNegotiation(version());
+ }
}
+ DCHECK(version_negotiated_);
}
- DCHECK(version_negotiated_);
}
return true;
}
+void QuicConnection::OnSuccessfulVersionNegotiation() {
+ visitor_->OnSuccessfulVersionNegotiation(version());
+ if (debug_visitor_ != nullptr) {
+ debug_visitor_->OnSuccessfulVersionNegotiation(version());
+ }
+}
+
void QuicConnection::OnDecryptedPacket(EncryptionLevel level) {
last_decrypted_packet_level_ = level;
last_packet_decrypted_ = true;
@@ -797,6 +802,11 @@ void QuicConnection::OnDecryptedPacket(EncryptionLevel level) {
address_validated_ = true;
}
+ if (use_handshake_delegate_) {
+ visitor_->OnPacketDecrypted(level);
+ return;
+ }
+
// Once the server receives a forward secure packet, the handshake is
// confirmed.
if (level == ENCRYPTION_FORWARD_SECURE &&
@@ -909,6 +919,7 @@ bool QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) {
visitor_->OnStreamFrame(frame);
stats_.stream_bytes_received += frame.data_length;
should_last_packet_instigate_acks_ = true;
+ consecutive_retransmittable_on_wire_ping_count_ = 0;
return connected_;
}
@@ -955,7 +966,11 @@ bool QuicConnection::OnAckFrameStart(QuicPacketNumber largest_acked,
largest_acked > GetLargestSentPacket()) {
QUIC_DLOG(WARNING) << ENDPOINT
<< "Peer's observed unsent packet:" << largest_acked
- << " vs " << GetLargestSentPacket();
+ << " vs " << GetLargestSentPacket()
+ << ". SupportsMultiplePacketNumberSpaces():"
+ << SupportsMultiplePacketNumberSpaces()
+ << ", last_decrypted_packet_level_:"
+ << last_decrypted_packet_level_;
// We got an ack for data we have not sent.
CloseConnection(QUIC_INVALID_ACK_DATA, "Largest observed too high.",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -1040,12 +1055,8 @@ bool QuicConnection::OnAckFrameEnd(QuicPacketNumber start) {
// If the incoming ack's packets set expresses received packets: peer is still
// acking packets which we never care about.
// Send an ack to raise the high water mark.
- bool send_stop_waiting = GetLeastUnacked() > start;
- if (GetQuicReloadableFlag(quic_simplify_stop_waiting) &&
- no_stop_waiting_frames_) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_simplify_stop_waiting);
- send_stop_waiting = false;
- }
+ const bool send_stop_waiting =
+ no_stop_waiting_frames_ ? false : GetLeastUnacked() > start;
PostProcessAfterAckFrame(send_stop_waiting,
ack_result == PACKETS_NEWLY_ACKED);
processing_ack_frame_ = false;
@@ -1298,9 +1309,7 @@ bool QuicConnection::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
if (debug_visitor_ != nullptr) {
debug_visitor_->OnWindowUpdateFrame(frame, time_of_last_received_packet_);
}
- QUIC_DVLOG(1) << ENDPOINT << "WINDOW_UPDATE_FRAME received for stream: "
- << frame.stream_id
- << " with byte offset: " << frame.byte_offset;
+ QUIC_DVLOG(1) << ENDPOINT << "WINDOW_UPDATE_FRAME received " << frame;
visitor_->OnWindowUpdateFrame(frame);
should_last_packet_instigate_acks_ = true;
return connected_;
@@ -1562,7 +1571,7 @@ void QuicConnection::SendVersionNegotiationPacket(bool ietf_quic,
framer_.supported_versions())
<< "}, " << (ietf_quic ? "" : "!") << "ietf_quic";
std::unique_ptr<QuicEncryptedPacket> version_packet(
- packet_generator_.SerializeVersionNegotiationPacket(
+ packet_creator_.SerializeVersionNegotiationPacket(
ietf_quic, has_length_prefix, framer_.supported_versions()));
QUIC_DVLOG(2) << ENDPOINT << "Sending version negotiation packet: {"
<< ParsedQuicVersionVectorToString(framer_.supported_versions())
@@ -1599,7 +1608,7 @@ size_t QuicConnection::SendCryptoData(EncryptionLevel level,
return 0;
}
ScopedPacketFlusher flusher(this);
- return packet_generator_.ConsumeCryptoData(level, write_length, offset);
+ return packet_creator_.ConsumeCryptoData(level, write_length, offset);
}
QuicConsumedData QuicConnection::SendStreamData(QuicStreamId id,
@@ -1617,7 +1626,7 @@ QuicConsumedData QuicConnection::SendStreamData(QuicStreamId id,
// packet (a handshake packet from client to server could result in a REJ or a
// SHLO from the server, leading to two different decrypters at the server.)
ScopedPacketFlusher flusher(this);
- return packet_generator_.ConsumeData(id, write_length, offset, state);
+ return packet_creator_.ConsumeData(id, write_length, offset, state);
}
bool QuicConnection::SendControlFrame(const QuicFrame& frame) {
@@ -1635,14 +1644,14 @@ bool QuicConnection::SendControlFrame(const QuicFrame& frame) {
}
ScopedPacketFlusher flusher(this);
const bool consumed =
- packet_generator_.ConsumeRetransmittableControlFrame(frame);
+ packet_creator_.ConsumeRetransmittableControlFrame(frame);
if (!consumed) {
QUIC_DVLOG(1) << ENDPOINT << "Failed to send control frame: " << frame;
return false;
}
if (frame.type == PING_FRAME) {
// Flush PING frame immediately.
- packet_generator_.FlushAllQueuedFrames();
+ packet_creator_.FlushCurrentPacket();
if (debug_visitor_ != nullptr) {
debug_visitor_->OnPingSent();
}
@@ -1661,32 +1670,9 @@ void QuicConnection::OnStreamReset(QuicStreamId id,
return;
}
// Flush stream frames of reset stream.
- if (packet_generator_.HasPendingStreamFramesOfStream(id)) {
+ if (packet_creator_.HasPendingStreamFramesOfStream(id)) {
ScopedPacketFlusher flusher(this);
- packet_generator_.FlushAllQueuedFrames();
- }
-
- sent_packet_manager_.CancelRetransmissionsForStream(id);
- // Remove all queued packets which only contain data for the reset stream.
- // TODO(fayang): consider removing this because it should be rarely executed.
- auto packet_iterator = queued_packets_.begin();
- while (packet_iterator != queued_packets_.end()) {
- QuicFrames* retransmittable_frames =
- &packet_iterator->retransmittable_frames;
- if (retransmittable_frames->empty()) {
- ++packet_iterator;
- continue;
- }
- // NOTE THAT RemoveFramesForStream removes only STREAM frames
- // for the specified stream.
- RemoveFramesForStream(retransmittable_frames, id);
- if (!retransmittable_frames->empty()) {
- ++packet_iterator;
- continue;
- }
- delete[] packet_iterator->encrypted_buffer;
- ClearSerializedPacket(&(*packet_iterator));
- packet_iterator = queued_packets_.erase(packet_iterator);
+ packet_creator_.FlushCurrentPacket();
}
// TODO(ianswett): Consider checking for 3 RTOs when the last stream is
// cancelled as well.
@@ -1707,7 +1693,11 @@ const QuicConnectionStats& QuicConnection::GetStats() {
stats_.srtt_us = srtt.ToMicroseconds();
stats_.estimated_bandwidth = sent_packet_manager_.BandwidthEstimate();
- stats_.max_packet_size = packet_generator_.GetCurrentMaxPacketLength();
+ if (GetQuicReloadableFlag(quic_log_ack_aggregation_stats)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_log_ack_aggregation_stats);
+ sent_packet_manager_.GetSendAlgorithm()->PopulateConnectionStats(&stats_);
+ }
+ stats_.max_packet_size = packet_creator_.max_packet_length();
stats_.max_received_packet_size = largest_received_packet_size_;
return stats_;
}
@@ -1879,9 +1869,6 @@ void QuicConnection::OnCanWrite() {
SendAck();
}
}
- if (!session_decides_what_to_write()) {
- WritePendingRetransmissions();
- }
WriteNewData();
}
@@ -1949,7 +1936,7 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
<< server_connection_id_ << " with "
<< header.source_connection_id;
server_connection_id_ = header.source_connection_id;
- packet_generator_.SetServerConnectionId(server_connection_id_);
+ packet_creator_.SetServerConnectionId(server_connection_id_);
}
if (!ValidateReceivedPacketNumber(header.packet_number)) {
@@ -1964,13 +1951,10 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
// it should stop sending version since the version negotiation is done.
// IETF QUIC stops sending version once encryption level switches to
// forward secure.
- packet_generator_.StopSendingVersion();
+ packet_creator_.StopSendingVersion();
}
version_negotiated_ = true;
- visitor_->OnSuccessfulVersionNegotiation(version());
- if (debug_visitor_ != nullptr) {
- debug_visitor_->OnSuccessfulVersionNegotiation(version());
- }
+ OnSuccessfulVersionNegotiation();
}
}
@@ -1980,7 +1964,7 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
if (perspective_ == Perspective::IS_SERVER &&
encryption_level_ == ENCRYPTION_INITIAL &&
- last_size_ > packet_generator_.GetCurrentMaxPacketLength()) {
+ last_size_ > packet_creator_.max_packet_length()) {
SetMaxPacketLength(last_size_);
}
return true;
@@ -2015,37 +1999,9 @@ void QuicConnection::WriteQueuedPackets() {
}
QUIC_CLIENT_HISTOGRAM_COUNTS("QuicSession.NumQueuedPacketsBeforeWrite",
- queued_packets_.size(), 1, 1000, 50, "");
- while (!queued_packets_.empty()) {
- DCHECK(!treat_queued_packets_as_sent_);
- // WritePacket() can potentially clear all queued packets, so we need to
- // save the first queued packet to a local variable before calling it.
- SerializedPacket packet(std::move(queued_packets_.front()));
- queued_packets_.pop_front();
-
- const bool write_result = WritePacket(&packet);
-
- if (connected_ && !write_result) {
- // Write failed but connection is open, re-insert |packet| into the
- // front of the queue, it will be retried later.
- queued_packets_.emplace_front(std::move(packet));
- break;
- }
-
- delete[] packet.encrypted_buffer;
- ClearSerializedPacket(&packet);
- if (!connected_) {
- DCHECK(queued_packets_.empty()) << "Queued packets should have been "
- "cleared while closing connection";
- break;
- }
-
- // Continue to send the next packet in queue.
- }
+ buffered_packets_.size(), 1, 1000, 50, "");
while (!buffered_packets_.empty()) {
- DCHECK(treat_queued_packets_as_sent_);
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_treat_queued_packets_as_sent, 1, 3);
if (HandleWriteBlocked()) {
break;
}
@@ -2054,7 +2010,7 @@ void QuicConnection::WriteQueuedPackets() {
packet.encrypted_buffer.data(), packet.encrypted_buffer.length(),
packet.self_address.host(), packet.peer_address, per_packet_options_);
QUIC_DVLOG(1) << ENDPOINT << "Sending buffered packet, result: " << result;
- if (mtu_discovery_v2_ && IsMsgTooBig(result) &&
+ if (IsMsgTooBig(result) &&
packet.encrypted_buffer.length() > long_term_mtu_) {
// When MSG_TOO_BIG is returned, the system typically knows what the
// actual MTU is, so there is no need to probe further.
@@ -2078,35 +2034,6 @@ void QuicConnection::WriteQueuedPackets() {
}
}
-void QuicConnection::WritePendingRetransmissions() {
- DCHECK(!session_decides_what_to_write());
- // Keep writing as long as there's a pending retransmission which can be
- // written.
- while (sent_packet_manager_.HasPendingRetransmissions() &&
- CanWrite(HAS_RETRANSMITTABLE_DATA)) {
- const QuicPendingRetransmission pending =
- sent_packet_manager_.NextPendingRetransmission();
-
- // Re-packetize the frames with a new packet number for retransmission.
- // Retransmitted packets use the same packet number length as the
- // original.
- // Flush the packet generator before making a new packet.
- // TODO(ianswett): Implement ReserializeAllFrames as a separate path that
- // does not require the creator to be flushed.
- // TODO(fayang): FlushAllQueuedFrames should only be called once, and should
- // be moved outside of the loop. Also, CanWrite is not checked after the
- // generator is flushed.
- {
- ScopedPacketFlusher flusher(this);
- packet_generator_.FlushAllQueuedFrames();
- }
- DCHECK(!packet_generator_.HasPendingFrames());
- char buffer[kMaxOutgoingPacketSize];
- packet_generator_.ReserializeAllFrames(pending, buffer,
- kMaxOutgoingPacketSize);
- }
-}
-
void QuicConnection::SendProbingRetransmissions() {
while (sent_packet_manager_.GetSendAlgorithm()->ShouldSendProbingPacket() &&
CanWrite(HAS_RETRANSMITTABLE_DATA)) {
@@ -2115,11 +2042,6 @@ void QuicConnection::SendProbingRetransmissions() {
<< "Cannot send probing retransmissions: nothing to retransmit.";
break;
}
-
- if (!session_decides_what_to_write()) {
- DCHECK(sent_packet_manager_.HasPendingRetransmissions());
- WritePendingRetransmissions();
- }
}
}
@@ -2187,8 +2109,7 @@ bool QuicConnection::CanWrite(HasRetransmittableData retransmittable) {
return false;
}
- if (session_decides_what_to_write() &&
- sent_packet_manager_.pending_timer_transmission_count() > 0) {
+ if (sent_packet_manager_.pending_timer_transmission_count() > 0) {
// Force sending the retransmissions for HANDSHAKE, TLP, RTO, PROBING cases.
return true;
}
@@ -2238,21 +2159,16 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
QUIC_BUG << "Attempt to write packet:" << packet->packet_number
<< " after:" << sent_packet_manager_.GetLargestSentPacket();
QUIC_CLIENT_HISTOGRAM_COUNTS("QuicSession.NumQueuedPacketsAtOutOfOrder",
- queued_packets_.size(), 1, 1000, 50, "");
+ buffered_packets_.size(), 1, 1000, 50, "");
CloseConnection(QUIC_INTERNAL_ERROR, "Packet written out of order.",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return true;
}
- SerializedPacketFate fate = DeterminePacketFate();
+ SerializedPacketFate fate = DeterminePacketFate(
+ /*is_mtu_discovery=*/packet->encrypted_length > long_term_mtu_);
// Termination packets are encrypted and saved, so don't exit early.
const bool is_termination_packet = IsTerminationPacket(*packet);
- if (!treat_queued_packets_as_sent_ && HandleWriteBlocked() &&
- !is_termination_packet) {
- return false;
- }
-
QuicPacketNumber packet_number = packet->packet_number;
-
QuicPacketLength encrypted_length = packet->encrypted_length;
// Termination packets are eventually owned by TimeWaitListManager.
// Others are deleted at the end of this call.
@@ -2265,18 +2181,13 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
char* buffer_copy = CopyBuffer(*packet);
termination_packets_->emplace_back(
new QuicEncryptedPacket(buffer_copy, encrypted_length, true));
- // This assures we won't try to write *forced* packets when blocked.
- // Return true to stop processing.
- if (!treat_queued_packets_as_sent_ && HandleWriteBlocked()) {
- return true;
- }
}
const bool looks_like_mtu_probe = packet->retransmittable_frames.empty() &&
packet->encrypted_length > long_term_mtu_;
DCHECK_LE(encrypted_length, kMaxOutgoingPacketSize);
if (!looks_like_mtu_probe) {
- DCHECK_LE(encrypted_length, packet_generator_.GetCurrentMaxPacketLength());
+ DCHECK_LE(encrypted_length, packet_creator_.max_packet_length());
}
QUIC_DVLOG(1) << ENDPOINT << "Sending packet " << packet_number << " : "
<< (IsRetransmittable(*packet) == HAS_RETRANSMITTABLE_DATA
@@ -2284,7 +2195,8 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
: " ack only ")
<< ", encryption level: "
<< EncryptionLevelToString(packet->encryption_level)
- << ", encrypted length:" << encrypted_length;
+ << ", encrypted length:" << encrypted_length
+ << ", fate: " << SerializedPacketFateToString(fate);
QUIC_DVLOG(2) << ENDPOINT << "packet(" << packet_number << "): " << std::endl
<< QuicTextUtils::HexDump(QuicStringPiece(
packet->encrypted_buffer, encrypted_length));
@@ -2307,11 +2219,36 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
WriteResult result(WRITE_STATUS_OK, encrypted_length);
switch (fate) {
case COALESCE:
- DCHECK(false);
+ QUIC_BUG_IF(!version().CanSendCoalescedPackets());
+ if (!coalesced_packet_.MaybeCoalescePacket(
+ *packet, self_address(), peer_address(),
+ helper_->GetStreamSendBufferAllocator(),
+ packet_creator_.max_packet_length())) {
+ // Failed to coalesce packet, flush current coalesced packet.
+ if (!FlushCoalescedPacket()) {
+ // Failed to flush coalesced packet, write error has been handled.
+ return false;
+ }
+ if (!coalesced_packet_.MaybeCoalescePacket(
+ *packet, self_address(), peer_address(),
+ helper_->GetStreamSendBufferAllocator(),
+ packet_creator_.max_packet_length())) {
+ // Failed to coalesce packet even it is the only packet, raise a write
+ // error.
+ QUIC_DLOG(ERROR) << ENDPOINT << "Failed to coalesce packet";
+ result.error_code = WRITE_STATUS_FAILED_TO_COALESCE_PACKET;
+ break;
+ }
+ }
+ if (coalesced_packet_.length() < coalesced_packet_.max_packet_length()) {
+ QUIC_DVLOG(1) << ENDPOINT << "Trying to set soft max packet length to "
+ << coalesced_packet_.max_packet_length() -
+ coalesced_packet_.length();
+ packet_creator_.SetSoftMaxPacketLength(
+ coalesced_packet_.max_packet_length() - coalesced_packet_.length());
+ }
break;
case BUFFER:
- DCHECK(treat_queued_packets_as_sent_);
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_treat_queued_packets_as_sent, 2, 3);
QUIC_DVLOG(1) << ENDPOINT << "Adding packet: " << packet->packet_number
<< " to buffered packets";
buffered_packets_.emplace_back(*packet, self_address(), peer_address());
@@ -2321,6 +2258,11 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
self_address().host(), peer_address(),
per_packet_options_);
break;
+ case FAILED_TO_WRITE_COALESCED_PACKET:
+ // Failed to send existing coalesced packet when determining packet fate,
+ // write error has been handled.
+ QUIC_BUG_IF(!version().CanSendCoalescedPackets());
+ return false;
default:
DCHECK(false);
break;
@@ -2341,31 +2283,22 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
// duplicate packet being sent. The helper must call OnCanWrite
// when the write completes, and OnWriteError if an error occurs.
if (result.status != WRITE_STATUS_BLOCKED_DATA_BUFFERED) {
- if (treat_queued_packets_as_sent_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_treat_queued_packets_as_sent, 3, 3);
- QUIC_DVLOG(1) << ENDPOINT << "Adding packet: " << packet->packet_number
- << " to buffered packets";
- buffered_packets_.emplace_back(*packet, self_address(), peer_address());
- } else {
- return false;
- }
+ QUIC_DVLOG(1) << ENDPOINT << "Adding packet: " << packet->packet_number
+ << " to buffered packets";
+ buffered_packets_.emplace_back(*packet, self_address(), peer_address());
}
}
// In some cases, an MTU probe can cause EMSGSIZE. This indicates that the
// MTU discovery is permanently unsuccessful.
if (IsMsgTooBig(result) && looks_like_mtu_probe) {
- if (mtu_discovery_v2_) {
- // When MSG_TOO_BIG is returned, the system typically knows what the
- // actual MTU is, so there is no need to probe further.
- // TODO(wub): Reduce max packet size to a safe default, or the actual MTU.
- QUIC_DVLOG(1) << ENDPOINT << " MTU probe packet too big, size:"
- << packet->encrypted_length
- << ", long_term_mtu_:" << long_term_mtu_;
- mtu_discoverer_.Disable();
- } else {
- mtu_discovery_target_ = 0;
- }
+ // When MSG_TOO_BIG is returned, the system typically knows what the
+ // actual MTU is, so there is no need to probe further.
+ // TODO(wub): Reduce max packet size to a safe default, or the actual MTU.
+ QUIC_DVLOG(1) << ENDPOINT << " MTU probe packet too big, size:"
+ << packet->encrypted_length
+ << ", long_term_mtu_:" << long_term_mtu_;
+ mtu_discoverer_.Disable();
mtu_discovery_alarm_->Cancel();
// The write failed, but the writer is not blocked, so return true.
return true;
@@ -2382,8 +2315,8 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
if (debug_visitor_ != nullptr) {
// Pass the write result to the visitor.
- debug_visitor_->OnPacketSent(*packet, packet->original_packet_number,
- packet->transmission_type, packet_send_time);
+ debug_visitor_->OnPacketSent(*packet, packet->transmission_type,
+ packet_send_time);
}
if (IsRetransmittable(*packet) == HAS_RETRANSMITTABLE_DATA) {
if (!is_path_degrading_ && !path_degrading_alarm_->IsSet()) {
@@ -2412,8 +2345,8 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
}
const bool in_flight = sent_packet_manager_.OnPacketSent(
- packet, packet->original_packet_number, packet_send_time,
- packet->transmission_type, IsRetransmittable(*packet));
+ packet, packet_send_time, packet->transmission_type,
+ IsRetransmittable(*packet));
if (in_flight || !retransmission_alarm_->IsSet()) {
SetRetransmissionAlarm();
@@ -2422,7 +2355,7 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
// The packet number length must be updated after OnPacketSent, because it
// may change the packet number length in packet.
- packet_generator_.UpdatePacketNumberLength(
+ packet_creator_.UpdatePacketNumberLength(
sent_packet_manager_.GetLeastUnacked(),
sent_packet_manager_.EstimateMaxPacketsInFlight(max_packet_length()));
@@ -2519,6 +2452,13 @@ void QuicConnection::OnWriteError(int error_code) {
}
char* QuicConnection::GetPacketBuffer() {
+ if (version().CanSendCoalescedPackets() &&
+ sent_packet_manager_.handshake_state() <
+ QuicSentPacketManager::HANDSHAKE_CONFIRMED) {
+ // Do not use writer's packet buffer for coalesced packets which may contain
+ // multiple QUIC packets.
+ return nullptr;
+ }
return writer_->GetNextWriteLocation(self_address().host(), peer_address());
}
@@ -2542,8 +2482,7 @@ void QuicConnection::OnSerializedPacket(SerializedPacket* serialized_packet) {
return;
}
- if (serialized_packet->retransmittable_frames.empty() &&
- !serialized_packet->original_packet_number.IsInitialized()) {
+ if (serialized_packet->retransmittable_frames.empty()) {
// Increment consecutive_num_packets_with_no_retransmittable_frames_ if
// this packet is a new transmission with no retransmittable frames.
++consecutive_num_packets_with_no_retransmittable_frames_;
@@ -2585,10 +2524,8 @@ void QuicConnection::OnPathMtuIncreased(QuicPacketLength packet_size) {
if (packet_size > max_packet_length()) {
const QuicByteCount old_max_packet_length = max_packet_length();
SetMaxPacketLength(packet_size);
- if (mtu_discovery_v2_) {
- mtu_discoverer_.OnMaxPacketLengthUpdated(old_max_packet_length,
- max_packet_length());
- }
+ mtu_discoverer_.OnMaxPacketLengthUpdated(old_max_packet_length,
+ max_packet_length());
}
}
@@ -2609,17 +2546,7 @@ void QuicConnection::SendOrQueuePacket(SerializedPacket* packet) {
QUIC_BUG << "packet.encrypted_buffer == nullptr in to SendOrQueuePacket";
return;
}
- // If there are already queued packets, queue this one immediately to ensure
- // it's written in sequence number order.
- if (!queued_packets_.empty() || !WritePacket(packet)) {
- if (!treat_queued_packets_as_sent_) {
- // Take ownership of the underlying encrypted packet.
- packet->encrypted_buffer = CopyBuffer(*packet);
- queued_packets_.push_back(*packet);
- packet->retransmittable_frames.clear();
- }
- }
-
+ WritePacket(packet);
ClearSerializedPacket(packet);
}
@@ -2639,7 +2566,7 @@ void QuicConnection::SendAck() {
PopulateStopWaitingFrame(&stop_waiting);
frames.push_back(QuicFrame(stop_waiting));
}
- if (!packet_generator_.FlushAckFrame(frames)) {
+ if (!packet_creator_.FlushAckFrame(frames)) {
return;
}
ResetAckStates();
@@ -2648,7 +2575,7 @@ void QuicConnection::SendAck() {
return;
}
consecutive_num_packets_with_no_retransmittable_frames_ = 0;
- if (packet_generator_.HasRetransmittableFrames() ||
+ if (packet_creator_.HasPendingRetransmittableFrames() ||
visitor_->WillingAndAbleToWrite()) {
// There are pending retransmittable frames.
return;
@@ -2665,9 +2592,9 @@ void QuicConnection::OnPathDegradingTimeout() {
void QuicConnection::OnRetransmissionTimeout() {
DCHECK(!sent_packet_manager_.unacked_packets().empty() ||
(sent_packet_manager_.handshake_mode_disabled() &&
- !sent_packet_manager_.handshake_confirmed()));
+ !IsHandshakeComplete()));
const QuicPacketNumber previous_created_packet_number =
- packet_generator_.packet_number();
+ packet_creator_.packet_number();
if (close_connection_after_five_rtos_ &&
sent_packet_manager_.GetConsecutiveRtoCount() >= 4) {
// Close on the 5th consecutive RTO, so after 4 previous RTOs have occurred.
@@ -2686,14 +2613,20 @@ void QuicConnection::OnRetransmissionTimeout() {
const auto retransmission_mode =
sent_packet_manager_.OnRetransmissionTimeout();
- if (skip_packet_number_for_pto_ &&
+ if (sent_packet_manager_.skip_packet_number_for_pto() &&
retransmission_mode == QuicSentPacketManager::PTO_MODE &&
sent_packet_manager_.pending_timer_transmission_count() == 1) {
// Skip a packet number when a single PTO packet is sent to elicit an
// immediate ACK.
- packet_generator_.SkipNPacketNumbers(
- 1, sent_packet_manager_.GetLeastUnacked(),
+ const QuicPacketCount num_packet_numbers_to_skip = 1;
+ packet_creator_.SkipNPacketNumbers(
+ num_packet_numbers_to_skip, sent_packet_manager_.GetLeastUnacked(),
sent_packet_manager_.EstimateMaxPacketsInFlight(max_packet_length()));
+ if (GetQuicReloadableFlag(quic_on_packet_numbers_skipped) &&
+ debug_visitor_ != nullptr) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_on_packet_numbers_skipped);
+ debug_visitor_->OnNPacketNumbersSkipped(num_packet_numbers_to_skip);
+ }
}
WriteIfNotBlocked();
@@ -2712,45 +2645,42 @@ void QuicConnection::OnRetransmissionTimeout() {
WriteIfNotBlocked();
}
- if (sent_packet_manager_.fix_rto_retransmission()) {
- if (packet_generator_.packet_number() == previous_created_packet_number &&
- (retransmission_mode == QuicSentPacketManager::TLP_MODE ||
- retransmission_mode == QuicSentPacketManager::RTO_MODE ||
- retransmission_mode == QuicSentPacketManager::PTO_MODE) &&
- !visitor_->WillingAndAbleToWrite()) {
- // Send PING if timer fires in RTO or PTO mode but there is no data to
- // send.
- // When TLP fires, either new data or tail loss probe should be sent.
- // There is corner case where TLP fires after RTO because packets get
- // acked. Two packets are marked RTO_RETRANSMITTED, but the first packet
- // is retransmitted as two packets because of packet number length
- // increases (please see QuicConnectionTest.RtoPacketAsTwo).
- QUIC_DLOG_IF(WARNING,
- retransmission_mode == QuicSentPacketManager::TLP_MODE &&
- stats_.rto_count == 0)
- << "No packet gets sent when timer fires in TLP mode, sending PING";
- DCHECK_LT(0u, sent_packet_manager_.pending_timer_transmission_count());
- visitor_->SendPing();
- }
- if (retransmission_mode == QuicSentPacketManager::PTO_MODE) {
- sent_packet_manager_.AdjustPendingTimerTransmissions();
- }
- if (retransmission_mode != QuicSentPacketManager::LOSS_MODE) {
- // When timer fires in TLP or RTO 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_generator_.packet_number() == previous_created_packet_number &&
- (!visitor_->WillingAndAbleToWrite() ||
- sent_packet_manager_.pending_timer_transmission_count() == 0u))
- << "retransmission_mode: " << retransmission_mode
- << ", packet_number: " << packet_generator_.packet_number()
- << ", session has data to write: "
- << visitor_->WillingAndAbleToWrite()
- << ", writer is blocked: " << writer_->IsWriteBlocked()
- << ", pending_timer_transmission_count: "
- << sent_packet_manager_.pending_timer_transmission_count();
- }
+ if (packet_creator_.packet_number() == previous_created_packet_number &&
+ (retransmission_mode == QuicSentPacketManager::TLP_MODE ||
+ retransmission_mode == QuicSentPacketManager::RTO_MODE ||
+ retransmission_mode == QuicSentPacketManager::PTO_MODE) &&
+ !visitor_->WillingAndAbleToWrite()) {
+ // Send PING if timer fires in RTO or PTO mode but there is no data to
+ // send.
+ // When TLP fires, either new data or tail loss probe should be sent.
+ // There is corner case where TLP fires after RTO because packets get
+ // acked. Two packets are marked RTO_RETRANSMITTED, but the first packet
+ // is retransmitted as two packets because of packet number length
+ // increases (please see QuicConnectionTest.RtoPacketAsTwo).
+ QUIC_DLOG_IF(WARNING,
+ retransmission_mode == QuicSentPacketManager::TLP_MODE &&
+ stats_.rto_count == 0)
+ << "No packet gets sent when timer fires in TLP mode, sending PING";
+ DCHECK_LT(0u, sent_packet_manager_.pending_timer_transmission_count());
+ visitor_->SendPing();
+ }
+ if (retransmission_mode == QuicSentPacketManager::PTO_MODE) {
+ sent_packet_manager_.AdjustPendingTimerTransmissions();
+ }
+ if (retransmission_mode != QuicSentPacketManager::LOSS_MODE) {
+ // When timer fires in TLP or RTO 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))
+ << "retransmission_mode: " << retransmission_mode
+ << ", packet_number: " << packet_creator_.packet_number()
+ << ", session has data to write: " << visitor_->WillingAndAbleToWrite()
+ << ", writer is blocked: " << writer_->IsWriteBlocked()
+ << ", pending_timer_transmission_count: "
+ << sent_packet_manager_.pending_timer_transmission_count();
}
// Ensure the retransmission alarm is always set if there are unacked packets
@@ -2764,26 +2694,26 @@ void QuicConnection::OnRetransmissionTimeout() {
void QuicConnection::SetEncrypter(EncryptionLevel level,
std::unique_ptr<QuicEncrypter> encrypter) {
- packet_generator_.SetEncrypter(level, std::move(encrypter));
+ packet_creator_.SetEncrypter(level, std::move(encrypter));
}
void QuicConnection::SetDiversificationNonce(
const DiversificationNonce& nonce) {
DCHECK_EQ(Perspective::IS_SERVER, perspective_);
- packet_generator_.SetDiversificationNonce(nonce);
+ packet_creator_.SetDiversificationNonce(nonce);
}
void QuicConnection::SetDefaultEncryptionLevel(EncryptionLevel level) {
QUIC_DVLOG(1) << ENDPOINT << "Setting default encryption level from "
<< EncryptionLevelToString(encryption_level_) << " to "
<< EncryptionLevelToString(level);
- if (level != encryption_level_ && packet_generator_.HasPendingFrames()) {
+ if (level != encryption_level_ && packet_creator_.HasPendingFrames()) {
// Flush all queued frames when encryption level changes.
ScopedPacketFlusher flusher(this);
- packet_generator_.FlushAllQueuedFrames();
+ packet_creator_.FlushCurrentPacket();
}
encryption_level_ = level;
- packet_generator_.set_encryption_level(level);
+ packet_creator_.set_encryption_level(level);
}
void QuicConnection::SetDecrypter(EncryptionLevel level,
@@ -2832,13 +2762,13 @@ const QuicDecrypter* QuicConnection::alternative_decrypter() const {
void QuicConnection::QueueUndecryptablePacket(
const QuicEncryptedPacket& packet) {
- for (const auto& saved_packet : undecryptable_packets_) {
- if (packet.data() == saved_packet->data() &&
- packet.length() == saved_packet->length()) {
- QUIC_DVLOG(1) << ENDPOINT << "Not queueing known undecryptable packet";
- return;
- }
+ for (const auto& saved_packet : undecryptable_packets_) {
+ if (packet.data() == saved_packet->data() &&
+ packet.length() == saved_packet->length()) {
+ QUIC_DVLOG(1) << ENDPOINT << "Not queueing known undecryptable packet";
+ return;
}
+ }
QUIC_DVLOG(1) << ENDPOINT << "Queueing undecryptable packet.";
undecryptable_packets_.push_back(packet.Clone());
}
@@ -2854,7 +2784,7 @@ void QuicConnection::MaybeProcessUndecryptablePackets() {
while (connected_ && !undecryptable_packets_.empty()) {
// Making sure there is no pending frames when processing next undecrypted
// packet because the queued ack frame may change.
- packet_generator_.FlushAllQueuedFrames();
+ packet_creator_.FlushCurrentPacket();
if (!connected_) {
return;
}
@@ -2888,26 +2818,28 @@ void QuicConnection::MaybeProcessUndecryptablePackets() {
void QuicConnection::QueueCoalescedPacket(const QuicEncryptedPacket& packet) {
QUIC_DVLOG(1) << ENDPOINT << "Queueing coalesced packet.";
- coalesced_packets_.push_back(packet.Clone());
+ received_coalesced_packets_.push_back(packet.Clone());
+ ++stats_.num_coalesced_packets_received;
}
void QuicConnection::MaybeProcessCoalescedPackets() {
bool processed = false;
- while (connected_ && !coalesced_packets_.empty()) {
+ 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_generator_.FlushAllQueuedFrames();
+ packet_creator_.FlushCurrentPacket();
if (!connected_) {
return;
}
std::unique_ptr<QuicEncryptedPacket> packet =
- std::move(coalesced_packets_.front());
- coalesced_packets_.pop_front();
+ std::move(received_coalesced_packets_.front());
+ received_coalesced_packets_.pop_front();
QUIC_DVLOG(1) << ENDPOINT << "Processing coalesced packet";
if (framer_.ProcessPacket(*packet)) {
processed = true;
+ ++stats_.num_coalesced_packets_processed;
} else {
// If we are unable to decrypt this packet, it might be
// because the CHLO or SHLO packet was lost.
@@ -2942,25 +2874,76 @@ void QuicConnection::CloseConnection(
void QuicConnection::SendConnectionClosePacket(QuicErrorCode error,
const std::string& details) {
- QUIC_DLOG(INFO) << ENDPOINT << "Sending connection close packet.";
- SetDefaultEncryptionLevel(GetConnectionCloseEncryptionLevel());
- ClearQueuedPackets();
- // If there was a packet write error, write the smallest close possible.
+ if (!GetQuicReloadableFlag(quic_close_all_encryptions_levels2)) {
+ QUIC_DLOG(INFO) << ENDPOINT << "Sending connection close packet.";
+ SetDefaultEncryptionLevel(GetConnectionCloseEncryptionLevel());
+ if (version().CanSendCoalescedPackets()) {
+ coalesced_packet_.Clear();
+ }
+ ClearQueuedPackets();
+ // If there was a packet write error, write the smallest close possible.
+ ScopedPacketFlusher flusher(this);
+ // When multiple packet number spaces is supported, an ACK frame will be
+ // bundled when connection is not write blocked.
+ if (!SupportsMultiplePacketNumberSpaces() &&
+ error != QUIC_PACKET_WRITE_ERROR &&
+ !GetUpdatedAckFrame().ack_frame->packets.Empty()) {
+ SendAck();
+ }
+ QuicConnectionCloseFrame* frame;
+
+ frame = new QuicConnectionCloseFrame(transport_version(), error, details,
+ framer_.current_received_frame_type());
+ packet_creator_.ConsumeRetransmittableControlFrame(QuicFrame(frame));
+ packet_creator_.FlushCurrentPacket();
+ if (version().CanSendCoalescedPackets()) {
+ FlushCoalescedPacket();
+ }
+ ClearQueuedPackets();
+ return;
+ }
+ const EncryptionLevel current_encryption_level = encryption_level_;
ScopedPacketFlusher flusher(this);
- // When multiple packet number spaces is supported, an ACK frame will be
- // bundled when connection is not write blocked.
- if (!SupportsMultiplePacketNumberSpaces() &&
- error != QUIC_PACKET_WRITE_ERROR &&
- !GetUpdatedAckFrame().ack_frame->packets.Empty()) {
- SendAck();
- }
- QuicConnectionCloseFrame* frame;
-
- frame = new QuicConnectionCloseFrame(transport_version(), error, details,
- framer_.current_received_frame_type());
- packet_generator_.ConsumeRetransmittableControlFrame(QuicFrame(frame));
- packet_generator_.FlushAllQueuedFrames();
+ QUIC_RELOADABLE_FLAG_COUNT(quic_close_all_encryptions_levels2);
+
+ // Now that the connection is being closed, discard any unsent packets
+ // so the only packets to be sent will be connection close packets.
+ if (version().CanSendCoalescedPackets()) {
+ coalesced_packet_.Clear();
+ }
+ ClearQueuedPackets();
+
+ for (EncryptionLevel level :
+ {ENCRYPTION_INITIAL, ENCRYPTION_HANDSHAKE, ENCRYPTION_ZERO_RTT,
+ ENCRYPTION_FORWARD_SECURE}) {
+ if (!framer_.HasEncrypterOfEncryptionLevel(level)) {
+ continue;
+ }
+ QUIC_DLOG(INFO) << ENDPOINT << "Sending connection close packet at level: "
+ << EncryptionLevelToString(level);
+ SetDefaultEncryptionLevel(level);
+ // If there was a packet write error, write the smallest close possible.
+ // When multiple packet number spaces are supported, an ACK frame will
+ // be bundled by the ScopedPacketFlusher. Otherwise, an ACK must be sent
+ // explicitly.
+ if (!SupportsMultiplePacketNumberSpaces() &&
+ error != QUIC_PACKET_WRITE_ERROR &&
+ !GetUpdatedAckFrame().ack_frame->packets.Empty()) {
+ SendAck();
+ }
+ auto* frame =
+ new QuicConnectionCloseFrame(transport_version(), error, details,
+ framer_.current_received_frame_type());
+ packet_creator_.ConsumeRetransmittableControlFrame(QuicFrame(frame));
+ packet_creator_.FlushCurrentPacket();
+ }
+ if (version().CanSendCoalescedPackets()) {
+ FlushCoalescedPacket();
+ }
+ // Since the connection is closing, if the connection close packets were not
+ // sent, then they should be discarded.
ClearQueuedPackets();
+ SetDefaultEncryptionLevel(current_encryption_level);
}
void QuicConnection::TearDownLocalConnectionState(
@@ -3007,24 +2990,23 @@ void QuicConnection::CancelAllAlarms() {
}
QuicByteCount QuicConnection::max_packet_length() const {
- return packet_generator_.GetCurrentMaxPacketLength();
+ return packet_creator_.max_packet_length();
}
void QuicConnection::SetMaxPacketLength(QuicByteCount length) {
long_term_mtu_ = length;
- packet_generator_.SetMaxPacketLength(GetLimitedMaxPacketSize(length));
+ packet_creator_.SetMaxPacketLength(GetLimitedMaxPacketSize(length));
}
bool QuicConnection::HasQueuedData() const {
- return pending_version_negotiation_packet_ || !queued_packets_.empty() ||
- packet_generator_.HasPendingFrames() || !buffered_packets_.empty();
+ return pending_version_negotiation_packet_ ||
+ packet_creator_.HasPendingFrames() || !buffered_packets_.empty();
}
bool QuicConnection::CanWriteStreamData() {
// Don't write stream data if there are negotiation or queued data packets
// to send. Otherwise, continue and bundle as many frames as possible.
- if (pending_version_negotiation_packet_ || !queued_packets_.empty() ||
- !buffered_packets_.empty()) {
+ if (pending_version_negotiation_packet_ || !buffered_packets_.empty()) {
return false;
}
@@ -3129,28 +3111,52 @@ void QuicConnection::SetPingAlarm() {
// because it is expecting a response from the server.
return;
}
- if (retransmittable_on_wire_timeout_.IsInfinite() ||
+ if (initial_retransmittable_on_wire_timeout_.IsInfinite() ||
sent_packet_manager_.HasInFlightPackets()) {
// Extend the ping alarm.
ping_alarm_->Update(clock_->ApproximateNow() + ping_timeout_,
QuicTime::Delta::FromSeconds(1));
return;
}
- DCHECK_LT(retransmittable_on_wire_timeout_, ping_timeout_);
+ DCHECK_LT(initial_retransmittable_on_wire_timeout_, ping_timeout_);
+ QuicTime::Delta retransmittable_on_wire_timeout =
+ initial_retransmittable_on_wire_timeout_;
+ int max_aggressive_retransmittable_on_wire_ping_count =
+ GetQuicFlag(FLAGS_quic_max_aggressive_retransmittable_on_wire_ping_count);
+ DCHECK_LE(0, max_aggressive_retransmittable_on_wire_ping_count);
+ if (consecutive_retransmittable_on_wire_ping_count_ >
+ max_aggressive_retransmittable_on_wire_ping_count) {
+ // Exponentially back off the timeout if the number of consecutive
+ // retransmittable on wire pings has exceeds the allowance.
+ int shift = consecutive_retransmittable_on_wire_ping_count_ -
+ max_aggressive_retransmittable_on_wire_ping_count;
+ retransmittable_on_wire_timeout =
+ initial_retransmittable_on_wire_timeout_ * (1 << shift);
+ }
// If it's already set to an earlier time, then don't update it.
if (ping_alarm_->IsSet() &&
ping_alarm_->deadline() <
- clock_->ApproximateNow() + retransmittable_on_wire_timeout_) {
+ clock_->ApproximateNow() + retransmittable_on_wire_timeout) {
+ return;
+ }
+
+ if (retransmittable_on_wire_timeout < ping_timeout_) {
+ // Use a shorter timeout if there are open streams, but nothing on the wire.
+ ping_alarm_->Update(
+ clock_->ApproximateNow() + retransmittable_on_wire_timeout,
+ QuicTime::Delta::FromMilliseconds(1));
+ if (max_aggressive_retransmittable_on_wire_ping_count != 0) {
+ consecutive_retransmittable_on_wire_ping_count_++;
+ }
return;
}
- // Use a shorter timeout if there are open streams, but nothing on the wire.
- ping_alarm_->Update(
- clock_->ApproximateNow() + retransmittable_on_wire_timeout_,
- QuicTime::Delta::FromMilliseconds(1));
+
+ ping_alarm_->Update(clock_->ApproximateNow() + ping_timeout_,
+ QuicTime::Delta::FromMilliseconds(1));
}
void QuicConnection::SetRetransmissionAlarm() {
- if (packet_generator_.PacketFlusherAttached()) {
+ if (packet_creator_.PacketFlusherAttached()) {
pending_retransmission_alarm_ = true;
return;
}
@@ -3175,35 +3181,11 @@ void QuicConnection::SetPathDegradingAlarm() {
}
void QuicConnection::MaybeSetMtuAlarm(QuicPacketNumber sent_packet_number) {
- if (mtu_discovery_v2_) {
- if (mtu_discovery_alarm_->IsSet() ||
- !mtu_discoverer_.ShouldProbeMtu(sent_packet_number)) {
- return;
- }
- mtu_discovery_alarm_->Set(clock_->ApproximateNow());
+ if (mtu_discovery_alarm_->IsSet() ||
+ !mtu_discoverer_.ShouldProbeMtu(sent_packet_number)) {
return;
}
-
- // Do not set the alarm if the target size is less than the current size.
- // This covers the case when |mtu_discovery_target_| is at its default value,
- // zero.
- if (mtu_discovery_target_ <= max_packet_length()) {
- return;
- }
-
- if (mtu_probe_count_ >= kMtuDiscoveryAttempts) {
- return;
- }
-
- if (mtu_discovery_alarm_->IsSet()) {
- return;
- }
-
- if (sent_packet_number >= next_mtu_probe_at_) {
- // Use an alarm to send the MTU probe to ensure that no ScopedPacketFlushers
- // are active.
- mtu_discovery_alarm_->Set(clock_->ApproximateNow());
- }
+ mtu_discovery_alarm_->Set(clock_->ApproximateNow());
}
void QuicConnection::MaybeSetAckAlarmTo(QuicTime time) {
@@ -3220,9 +3202,9 @@ QuicConnection::ScopedPacketFlusher::ScopedPacketFlusher(
return;
}
- if (!connection_->packet_generator_.PacketFlusherAttached()) {
+ if (!connection_->packet_creator_.PacketFlusherAttached()) {
flush_and_set_pending_retransmission_alarm_on_delete_ = true;
- connection->packet_generator_.AttachPacketFlusher();
+ connection->packet_creator_.AttachPacketFlusher();
}
}
@@ -3261,12 +3243,13 @@ QuicConnection::ScopedPacketFlusher::~ScopedPacketFlusher() {
connection_->SendAck();
}
}
- connection_->packet_generator_.Flush();
- connection_->FlushPackets();
- if (connection_->session_decides_what_to_write()) {
- // Reset transmission type.
- connection_->SetTransmissionType(NOT_RETRANSMISSION);
+ connection_->packet_creator_.Flush();
+ if (connection_->version().CanSendCoalescedPackets()) {
+ connection_->FlushCoalescedPacket();
}
+ connection_->FlushPackets();
+ // Reset transmission type.
+ connection_->SetTransmissionType(NOT_RETRANSMISSION);
// Once all transmissions are done, check if there is any outstanding data
// to send and notify the congestion controller if not.
@@ -3294,7 +3277,7 @@ QuicConnection::ScopedPacketFlusher::~ScopedPacketFlusher() {
}
}
DCHECK_EQ(flush_and_set_pending_retransmission_alarm_on_delete_,
- !connection_->packet_generator_.PacketFlusherAttached());
+ !connection_->packet_creator_.PacketFlusherAttached());
}
QuicConnection::BufferedPacket::BufferedPacket(
@@ -3305,6 +3288,16 @@ QuicConnection::BufferedPacket::BufferedPacket(
self_address(self_address),
peer_address(peer_address) {}
+QuicConnection::BufferedPacket::BufferedPacket(
+ char* encrypted_buffer,
+ QuicPacketLength encrypted_length,
+ const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address)
+ : encrypted_buffer(CopyBuffer(encrypted_buffer, encrypted_length),
+ encrypted_length),
+ self_address(self_address),
+ peer_address(peer_address) {}
+
QuicConnection::BufferedPacket::~BufferedPacket() {
delete[] encrypted_buffer.data();
}
@@ -3334,13 +3327,9 @@ bool QuicConnection::IsTerminationPacket(const SerializedPacket& packet) {
}
void QuicConnection::SetMtuDiscoveryTarget(QuicByteCount target) {
- if (mtu_discovery_v2_) {
- mtu_discoverer_.Disable();
- mtu_discoverer_.Enable(max_packet_length(),
- GetLimitedMaxPacketSize(target));
- } else {
- mtu_discovery_target_ = GetLimitedMaxPacketSize(target);
- }
+ QUIC_DVLOG(2) << ENDPOINT << "SetMtuDiscoveryTarget: " << target;
+ mtu_discoverer_.Disable();
+ mtu_discoverer_.Enable(max_packet_length(), GetLimitedMaxPacketSize(target));
}
QuicByteCount QuicConnection::GetLimitedMaxPacketSize(
@@ -3367,7 +3356,7 @@ void QuicConnection::SendMtuDiscoveryPacket(QuicByteCount target_mtu) {
DCHECK_EQ(target_mtu, GetLimitedMaxPacketSize(target_mtu));
// Send the probe.
- packet_generator_.GenerateMtuDiscoveryPacket(target_mtu);
+ packet_creator_.GenerateMtuDiscoveryPacket(target_mtu);
}
// TODO(zhongyi): change this method to generate a connectivity probing packet
@@ -3422,7 +3411,7 @@ bool QuicConnection::SendGenericPathProbePacket(
if (!VersionHasIetfQuicFrames(transport_version())) {
// Non-IETF QUIC, generate a padded ping regardless of whether this is a
// request or a response.
- probing_packet = packet_generator_.SerializeConnectivityProbingPacket();
+ probing_packet = packet_creator_.SerializeConnectivityProbingPacket();
} else {
if (is_response) {
// Respond using IETF QUIC PATH_RESPONSE frame
@@ -3430,14 +3419,14 @@ bool QuicConnection::SendGenericPathProbePacket(
// Pad the response if the request was a google connectivity probe
// (padded).
probing_packet =
- packet_generator_.SerializePathResponseConnectivityProbingPacket(
+ packet_creator_.SerializePathResponseConnectivityProbingPacket(
received_path_challenge_payloads_, /* is_padded = */ true);
received_path_challenge_payloads_.clear();
} else {
// Do not pad the response if the path challenge was not a google
// connectivity probe.
probing_packet =
- packet_generator_.SerializePathResponseConnectivityProbingPacket(
+ packet_creator_.SerializePathResponseConnectivityProbingPacket(
received_path_challenge_payloads_,
/* is_padded = */ false);
received_path_challenge_payloads_.clear();
@@ -3447,7 +3436,7 @@ bool QuicConnection::SendGenericPathProbePacket(
transmitted_connectivity_probe_payload_ =
std::make_unique<QuicPathFrameBuffer>();
probing_packet =
- packet_generator_.SerializePathChallengeConnectivityProbingPacket(
+ packet_creator_.SerializePathChallengeConnectivityProbingPacket(
transmitted_connectivity_probe_payload_.get());
if (!probing_packet) {
transmitted_connectivity_probe_payload_ = nullptr;
@@ -3484,15 +3473,13 @@ bool QuicConnection::SendGenericPathProbePacket(
if (debug_visitor_ != nullptr) {
debug_visitor_->OnPacketSent(
- *probing_packet, probing_packet->original_packet_number,
- probing_packet->transmission_type, packet_send_time);
+ *probing_packet, probing_packet->transmission_type, packet_send_time);
}
// Call OnPacketSent regardless of the write result.
- sent_packet_manager_.OnPacketSent(
- probing_packet.get(), probing_packet->original_packet_number,
- packet_send_time, probing_packet->transmission_type,
- NO_RETRANSMITTABLE_DATA);
+ sent_packet_manager_.OnPacketSent(probing_packet.get(), packet_send_time,
+ probing_packet->transmission_type,
+ NO_RETRANSMITTABLE_DATA);
if (IsWriteBlockedStatus(result.status)) {
if (probing_writer == writer_) {
@@ -3511,35 +3498,13 @@ bool QuicConnection::SendGenericPathProbePacket(
void QuicConnection::DiscoverMtu() {
DCHECK(!mtu_discovery_alarm_->IsSet());
- if (mtu_discovery_v2_) {
- const QuicPacketNumber largest_sent_packet =
- sent_packet_manager_.GetLargestSentPacket();
- if (mtu_discoverer_.ShouldProbeMtu(largest_sent_packet)) {
- ++mtu_probe_count_;
- SendMtuDiscoveryPacket(
- mtu_discoverer_.GetUpdatedMtuProbeSize(largest_sent_packet));
- }
- DCHECK(!mtu_discovery_alarm_->IsSet());
- return;
- }
-
- // Check if the MTU has been already increased.
- if (mtu_discovery_target_ <= max_packet_length()) {
- return;
+ const QuicPacketNumber largest_sent_packet =
+ sent_packet_manager_.GetLargestSentPacket();
+ if (mtu_discoverer_.ShouldProbeMtu(largest_sent_packet)) {
+ ++mtu_probe_count_;
+ SendMtuDiscoveryPacket(
+ mtu_discoverer_.GetUpdatedMtuProbeSize(largest_sent_packet));
}
-
- // Calculate the packet number of the next probe *before* sending the current
- // one. Otherwise, when SendMtuDiscoveryPacket() is called,
- // MaybeSetMtuAlarm() will not realize that the probe has been just sent, and
- // will reschedule this probe again.
- packets_between_mtu_probes_ *= 2;
- next_mtu_probe_at_ = sent_packet_manager_.GetLargestSentPacket() +
- packets_between_mtu_probes_ + 1;
- ++mtu_probe_count_;
-
- QUIC_DVLOG(2) << "Sending a path MTU discovery packet #" << mtu_probe_count_;
- SendMtuDiscoveryPacket(mtu_discovery_target_);
-
DCHECK(!mtu_discovery_alarm_->IsSet());
}
@@ -3623,7 +3588,7 @@ void QuicConnection::MaybeSendProbingRetransmissions() {
DCHECK(fill_up_link_during_probing_);
// Don't send probing retransmissions until the handshake has completed.
- if (!sent_packet_manager_.handshake_confirmed() ||
+ if (!IsHandshakeComplete() ||
sent_packet_manager().HasUnackedCryptoPackets()) {
return;
}
@@ -3640,14 +3605,12 @@ void QuicConnection::MaybeSendProbingRetransmissions() {
}
void QuicConnection::CheckIfApplicationLimited() {
- if (session_decides_what_to_write() && probing_retransmission_pending_) {
+ if (probing_retransmission_pending_) {
return;
}
bool application_limited =
- queued_packets_.empty() && buffered_packets_.empty() &&
- !sent_packet_manager_.HasPendingRetransmissions() &&
- !visitor_->WillingAndAbleToWrite();
+ buffered_packets_.empty() && !visitor_->WillingAndAbleToWrite();
if (!application_limited) {
return;
@@ -3716,20 +3679,6 @@ void QuicConnection::UpdatePacketContent(PacketContent type) {
current_effective_peer_migration_type_ = NO_CHANGE;
}
-void QuicConnection::MaybeEnableSessionDecidesWhatToWrite() {
- // Only enable session decides what to write code path for version 42+,
- // because it needs the receiver to allow receiving overlapping stream data.
- const bool enable_session_decides_what_to_write =
- transport_version() > QUIC_VERSION_39;
- sent_packet_manager_.SetSessionDecideWhatToWrite(
- enable_session_decides_what_to_write);
- if (version().SupportsAntiAmplificationLimit()) {
- sent_packet_manager_.EnableIetfPtoAndLossDetection();
- }
- packet_generator_.SetCanSetTransmissionType(
- enable_session_decides_what_to_write);
-}
-
void QuicConnection::PostProcessAfterAckFrame(bool send_stop_waiting,
bool acked_new_packet) {
if (no_stop_waiting_frames_) {
@@ -3777,11 +3726,7 @@ void QuicConnection::SetDataProducer(
}
void QuicConnection::SetTransmissionType(TransmissionType type) {
- packet_generator_.SetTransmissionType(type);
-}
-
-bool QuicConnection::session_decides_what_to_write() const {
- return sent_packet_manager_.session_decides_what_to_write();
+ packet_creator_.SetTransmissionType(type);
}
void QuicConnection::UpdateReleaseTimeIntoFuture() {
@@ -3803,7 +3748,8 @@ void QuicConnection::ResetAckStates() {
}
MessageStatus QuicConnection::SendMessage(QuicMessageId message_id,
- QuicMemSliceSpan message) {
+ QuicMemSliceSpan message,
+ bool flush) {
if (!VersionSupportsMessageFrames(transport_version())) {
QUIC_BUG << "MESSAGE frame is not supported for version "
<< transport_version();
@@ -3812,19 +3758,19 @@ MessageStatus QuicConnection::SendMessage(QuicMessageId message_id,
if (message.total_length() > GetCurrentLargestMessagePayload()) {
return MESSAGE_STATUS_TOO_LARGE;
}
- if (!CanWrite(HAS_RETRANSMITTABLE_DATA)) {
+ if (!connected_ || (!flush && !CanWrite(HAS_RETRANSMITTABLE_DATA))) {
return MESSAGE_STATUS_BLOCKED;
}
ScopedPacketFlusher flusher(this);
- return packet_generator_.AddMessageFrame(message_id, message);
+ return packet_creator_.AddMessageFrame(message_id, message);
}
QuicPacketLength QuicConnection::GetCurrentLargestMessagePayload() const {
- return packet_generator_.GetCurrentLargestMessagePayload();
+ return packet_creator_.GetCurrentLargestMessagePayload();
}
QuicPacketLength QuicConnection::GetGuaranteedLargestMessagePayload() const {
- return packet_generator_.GetGuaranteedLargestMessagePayload();
+ return packet_creator_.GetGuaranteedLargestMessagePayload();
}
uint32_t QuicConnection::cipher_id() const {
@@ -3838,7 +3784,7 @@ EncryptionLevel QuicConnection::GetConnectionCloseEncryptionLevel() const {
if (perspective_ == Perspective::IS_CLIENT) {
return encryption_level_;
}
- if (sent_packet_manager_.handshake_confirmed()) {
+ if (IsHandshakeComplete()) {
// A forward secure packet has been received.
QUIC_BUG_IF(encryption_level_ != ENCRYPTION_FORWARD_SECURE)
<< ENDPOINT << "Unexpected connection close encryption level "
@@ -3887,7 +3833,7 @@ void QuicConnection::SendAllPendingAcks() {
QuicFrames frames;
frames.push_back(uber_received_packet_manager_.GetUpdatedAckFrame(
static_cast<PacketNumberSpace>(i), clock_->ApproximateNow()));
- const bool flushed = packet_generator_.FlushAckFrame(frames);
+ const bool flushed = packet_creator_.FlushAckFrame(frames);
if (!flushed) {
// Connection is write blocked.
QUIC_BUG_IF(!writer_->IsWriteBlocked())
@@ -3913,7 +3859,7 @@ void QuicConnection::SendAllPendingAcks() {
return;
}
consecutive_num_packets_with_no_retransmittable_frames_ = 0;
- if (packet_generator_.HasRetransmittableFrames() ||
+ if (packet_creator_.HasPendingRetransmittableFrames() ||
visitor_->WillingAndAbleToWrite()) {
// There are pending retransmittable frames.
return;
@@ -3922,6 +3868,65 @@ void QuicConnection::SendAllPendingAcks() {
visitor_->OnAckNeedsRetransmittableFrame();
}
+bool QuicConnection::FlushCoalescedPacket() {
+ ScopedCoalescedPacketClearer clearer(&coalesced_packet_);
+ if (!version().CanSendCoalescedPackets()) {
+ QUIC_BUG_IF(coalesced_packet_.length() > 0);
+ return true;
+ }
+ if (coalesced_packet_.length() == 0) {
+ return true;
+ }
+ QUIC_DVLOG(1) << ENDPOINT << "Sending coalesced packet";
+ char buffer[kMaxOutgoingPacketSize];
+ const size_t length = packet_creator_.SerializeCoalescedPacket(
+ coalesced_packet_, buffer, coalesced_packet_.max_packet_length());
+ if (length == 0) {
+ return false;
+ }
+
+ if (!buffered_packets_.empty() || HandleWriteBlocked()) {
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Buffering coalesced packet of len: " << length;
+ buffered_packets_.emplace_back(buffer, length,
+ coalesced_packet_.self_address(),
+ coalesced_packet_.peer_address());
+ return true;
+ }
+
+ WriteResult result = writer_->WritePacket(
+ buffer, length, coalesced_packet_.self_address().host(),
+ coalesced_packet_.peer_address(), per_packet_options_);
+ if (IsWriteError(result.status)) {
+ OnWriteError(result.error_code);
+ return false;
+ }
+ if (IsWriteBlockedStatus(result.status)) {
+ visitor_->OnWriteBlocked();
+ if (result.status != WRITE_STATUS_BLOCKED_DATA_BUFFERED) {
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Buffering coalesced packet of len: " << length;
+ buffered_packets_.emplace_back(buffer, length,
+ coalesced_packet_.self_address(),
+ coalesced_packet_.peer_address());
+ }
+ }
+ // Account for added padding.
+ if (length > coalesced_packet_.length()) {
+ size_t padding_size = length - coalesced_packet_.length();
+ if (EnforceAntiAmplificationLimit()) {
+ bytes_sent_before_address_validation_ += padding_size;
+ }
+ stats_.bytes_sent += padding_size;
+ if (coalesced_packet_.initial_packet() != nullptr &&
+ coalesced_packet_.initial_packet()->transmission_type !=
+ NOT_RETRANSMISSION) {
+ stats_.bytes_retransmitted += padding_size;
+ }
+ }
+ return true;
+}
+
void QuicConnection::MaybeEnableMultiplePacketNumberSpacesSupport() {
if (version().handshake_protocol != PROTOCOL_TLS1_3) {
return;
@@ -3988,9 +3993,21 @@ bool QuicConnection::LimitedByAmplificationFactor() const {
bytes_received_before_address_validation_;
}
-QuicConnection::SerializedPacketFate QuicConnection::DeterminePacketFate() {
- if (treat_queued_packets_as_sent_ &&
- (!buffered_packets_.empty() || HandleWriteBlocked())) {
+SerializedPacketFate QuicConnection::DeterminePacketFate(
+ bool is_mtu_discovery) {
+ if (version().CanSendCoalescedPackets() &&
+ sent_packet_manager_.handshake_state() <
+ QuicSentPacketManager::HANDSHAKE_CONFIRMED &&
+ !is_mtu_discovery) {
+ // Before receiving ACK for any 1-RTT packets, always try to coalesce
+ // packet (except MTU discovery packet).
+ return COALESCE;
+ }
+ // Packet cannot be coalesced, flush existing coalesced packet.
+ if (version().CanSendCoalescedPackets() && !FlushCoalescedPacket()) {
+ return FAILED_TO_WRITE_COALESCED_PACKET;
+ }
+ if (!buffered_packets_.empty() || HandleWriteBlocked()) {
return BUFFER;
}
return SEND_TO_WRITER;
@@ -4037,7 +4054,7 @@ void QuicConnection::set_client_connection_id(
<< client_connection_id_
<< " for connection with server connection ID "
<< server_connection_id_;
- packet_generator_.SetClientConnectionId(client_connection_id_);
+ packet_creator_.SetClientConnectionId(client_connection_id_);
framer_.SetExpectedClientConnectionIdLength(client_connection_id_.length());
}
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 3d07946b316..abd836f4c6d 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
@@ -37,7 +37,6 @@
#include "net/third_party/quiche/src/quic/core/quic_mtu_discovery.h"
#include "net/third_party/quiche/src/quic/core/quic_one_block_arena.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_creator.h"
-#include "net/third_party/quiche/src/quic/core/quic_packet_generator.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_writer.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h"
@@ -165,7 +164,10 @@ class QUIC_EXPORT_PRIVATE QuicConnectionVisitorInterface {
virtual void OnForwardProgressConfirmed() = 0;
// Called when a STOP_SENDING frame has been received.
- virtual bool OnStopSendingFrame(const QuicStopSendingFrame& frame) = 0;
+ virtual void OnStopSendingFrame(const QuicStopSendingFrame& frame) = 0;
+
+ // Called when a packet of encryption |level| has been successfully decrypted.
+ virtual void OnPacketDecrypted(EncryptionLevel level) = 0;
};
// Interface which gets callbacks from the QuicConnection at interesting
@@ -178,7 +180,6 @@ class QUIC_EXPORT_PRIVATE QuicConnectionDebugVisitor
// Called when a packet has been sent.
virtual void OnPacketSent(const SerializedPacket& /*serialized_packet*/,
- QuicPacketNumber /*original_packet_number*/,
TransmissionType /*transmission_type*/,
QuicTime /*sent_time*/) {}
@@ -305,6 +306,9 @@ class QUIC_EXPORT_PRIVATE QuicConnectionDebugVisitor
// Called when a MaxStreamsFrame has been parsed.
virtual void OnMaxStreamsFrame(const QuicMaxStreamsFrame& /*frame*/) {}
+
+ // Called when |count| packet numbers have been skipped.
+ virtual void OnNPacketNumbersSkipped(QuicPacketCount /*count*/) {}
};
class QUIC_EXPORT_PRIVATE QuicConnectionHelperInterface {
@@ -364,6 +368,8 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Allows the client to adjust network parameters based on external
// information.
+ void AdjustNetworkParameters(
+ const SendAlgorithmInterface::NetworkParams& params);
void AdjustNetworkParameters(QuicBandwidth bandwidth,
QuicTime::Delta rtt,
bool allow_cwnd_to_decrease);
@@ -514,12 +520,10 @@ class QUIC_EXPORT_PRIVATE QuicConnection
void OnAuthenticatedIetfStatelessResetPacket(
const QuicIetfStatelessResetPacket& packet) override;
- // QuicPacketGenerator::DelegateInterface
+ // QuicPacketCreator::DelegateInterface
bool ShouldGeneratePacket(HasRetransmittableData retransmittable,
IsHandshake handshake) override;
const QuicFrames MaybeBundleAckOpportunistically() override;
-
- // QuicPacketCreator::DelegateInterface
char* GetPacketBuffer() override;
void OnSerializedPacket(SerializedPacket* packet) override;
void OnUnrecoverableError(QuicErrorCode error,
@@ -553,21 +557,21 @@ class QUIC_EXPORT_PRIVATE QuicConnection
DCHECK(!ping_alarm_->IsSet());
ping_timeout_ = ping_timeout;
}
- const QuicTime::Delta ping_timeout() { return ping_timeout_; }
+ const QuicTime::Delta ping_timeout() const { return ping_timeout_; }
// Used in Chromium, but not internally.
- // Sets a timeout for the ping alarm when there is no retransmittable data
- // in flight, allowing for a more aggressive ping alarm in that case.
- void set_retransmittable_on_wire_timeout(
+ // Sets an initial timeout for the ping alarm when there is no retransmittable
+ // data in flight, allowing for a more aggressive ping alarm in that case.
+ void set_initial_retransmittable_on_wire_timeout(
QuicTime::Delta retransmittable_on_wire_timeout) {
DCHECK(!ping_alarm_->IsSet());
- retransmittable_on_wire_timeout_ = retransmittable_on_wire_timeout;
+ initial_retransmittable_on_wire_timeout_ = retransmittable_on_wire_timeout;
}
- const QuicTime::Delta retransmittable_on_wire_timeout() {
- return retransmittable_on_wire_timeout_;
+ const QuicTime::Delta initial_retransmittable_on_wire_timeout() const {
+ return initial_retransmittable_on_wire_timeout_;
}
// Used in Chromium, but not internally.
void set_creator_debug_delegate(QuicPacketCreator::DebugDelegate* visitor) {
- packet_generator_.set_debug_delegate(visitor);
+ packet_creator_.set_debug_delegate(visitor);
}
const QuicSocketAddress& self_address() const { return self_address_; }
const QuicSocketAddress& peer_address() const { return direct_peer_address_; }
@@ -595,12 +599,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
}
// Testing only.
- size_t NumQueuedPackets() const {
- if (treat_queued_packets_as_sent_) {
- return buffered_packets_.size();
- }
- return queued_packets_.size();
- }
+ size_t NumQueuedPackets() const { return buffered_packets_.size(); }
// Returns true if the underlying UDP socket is writable, there is
// no queued data and the connection is not congestion-control
@@ -743,8 +742,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
virtual void SendConnectivityProbingResponsePacket(
const QuicSocketAddress& peer_address);
- // Sends an MTU discovery packet of size |mtu_discovery_target_| and updates
- // the MTU discovery alarm.
+ // Sends an MTU discovery packet and updates the MTU discovery alarm.
void DiscoverMtu();
// Sets the session notifier on the SentPacketManager.
@@ -757,8 +755,11 @@ class QUIC_EXPORT_PRIVATE QuicConnection
void SetTransmissionType(TransmissionType type);
// Tries to send |message| and returns the message status.
+ // If |flush| is false, this will return a MESSAGE_STATUS_BLOCKED
+ // when the connection is deemed unwritable.
virtual MessageStatus SendMessage(QuicMessageId message_id,
- QuicMemSliceSpan message);
+ QuicMemSliceSpan message,
+ bool flush);
// Returns the largest payload that will fit into a single MESSAGE frame.
// Because overhead can vary during a connection, this method should be
@@ -785,9 +786,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
const QuicFramer& framer() const { return framer_; }
- const QuicPacketGenerator& packet_generator() const {
- return packet_generator_;
- }
+ const QuicPacketCreator& packet_creator() const { return packet_creator_; }
EncryptionLevel encryption_level() const { return encryption_level_; }
EncryptionLevel last_decrypted_level() const {
@@ -812,11 +811,11 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// can only be set to false if there is some other mechanism of preventing
// amplification attacks, such as ICE (plus its a non-standard quic).
void set_fully_pad_crypto_handshake_packets(bool new_value) {
- packet_generator_.set_fully_pad_crypto_handshake_packets(new_value);
+ packet_creator_.set_fully_pad_crypto_handshake_packets(new_value);
}
bool fully_pad_during_crypto_handshake() const {
- return packet_generator_.fully_pad_crypto_handshake_packets();
+ return packet_creator_.fully_pad_crypto_handshake_packets();
}
size_t min_received_before_ack_decimation() const;
@@ -832,8 +831,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
defer_send_in_response_to_packets_ = defer;
}
- bool session_decides_what_to_write() const;
-
// Sets the current per-packet options for the connection. The QuicConnection
// does not take ownership of |options|; |options| must live for as long as
// the QuicConnection is in use.
@@ -862,9 +859,10 @@ class QUIC_EXPORT_PRIVATE QuicConnection
NOT_PADDED_PING, // Set if the packet is not {PING, PADDING}.
};
- // Whether the handshake is confirmed from this connection's perspective.
- bool IsHandshakeConfirmed() const {
- return sent_packet_manager_.handshake_confirmed();
+ // Whether the handshake completes from this connection's perspective.
+ bool IsHandshakeComplete() const {
+ return sent_packet_manager_.handshake_state() >=
+ QuicSentPacketManager::HANDSHAKE_COMPLETE;
}
// Returns the largest received packet number sent by peer.
@@ -890,6 +888,15 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// or the one sent after an IETF Retry.
void InstallInitialCrypters(QuicConnectionId connection_id);
+ // Called when version is considered negotiated.
+ void OnSuccessfulVersionNegotiation();
+
+ bool quic_version_negotiated_by_default_at_server() const {
+ return quic_version_negotiated_by_default_at_server_;
+ }
+
+ bool use_handshake_delegate() const { return use_handshake_delegate_; }
+
protected:
// Calls cancel() on all the alarms owned by this connection.
void CancelAllAlarms();
@@ -971,21 +978,18 @@ class QUIC_EXPORT_PRIVATE QuicConnection
typedef std::list<SerializedPacket> QueuedPacketList;
- // Indicates the fate of a serialized packet in WritePacket().
- enum SerializedPacketFate : uint8_t {
- COALESCE, // Try to coalesce packet.
- BUFFER, // Buffer packet in buffered_packets_.
- SEND_TO_WRITER, // Send packet to writer.
- };
-
// BufferedPacket stores necessary information (encrypted buffer and self/peer
// addresses) of those packets which are serialized but failed to send because
// socket is blocked. From unacked packet map and send algorithm's
// perspective, buffered packets are treated as sent.
- struct BufferedPacket {
+ struct QUIC_EXPORT_PRIVATE BufferedPacket {
BufferedPacket(const SerializedPacket& packet,
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address);
+ BufferedPacket(char* encrypted_buffer,
+ QuicPacketLength encrypted_length,
+ const QuicSocketAddress& self_address,
+ const QuicSocketAddress& peer_address);
BufferedPacket(const BufferedPacket& other) = delete;
BufferedPacket(const BufferedPacket&& other) = delete;
@@ -1042,9 +1046,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// blocked when this is called.
void WriteQueuedPackets();
- // Writes as many pending retransmissions as possible.
- void WritePendingRetransmissions();
-
// Writes new data if congestion control allows.
void WriteNewData();
@@ -1112,9 +1113,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// effective peer address change.
void UpdatePacketContent(PacketContent type);
- // Enables session decide what to write based on version and flags.
- void MaybeEnableSessionDecidesWhatToWrite();
-
// Called when last received ack frame has been processed.
// |send_stop_waiting| indicates whether a stop waiting needs to be sent.
// |acked_new_packet| is true if a previously-unacked packet was acked.
@@ -1146,8 +1144,12 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// and flags.
void MaybeEnableMultiplePacketNumberSpacesSupport();
- // Returns packet fate when trying to write a packet.
- SerializedPacketFate DeterminePacketFate();
+ // Returns packet fate when trying to write a packet via WritePacket().
+ SerializedPacketFate DeterminePacketFate(bool is_mtu_discovery);
+
+ // Serialize and send coalesced_packet. Returns false if serialization fails
+ // or the write causes errors, otherwise, returns true.
+ bool FlushCoalescedPacket();
// Returns the encryption level the connection close packet should be sent at,
// which is the highest encryption level that peer can guarantee to process.
@@ -1259,7 +1261,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Collection of coalesced packets which were received while processing
// the current packet.
- QuicDeque<std::unique_ptr<QuicEncryptedPacket>> coalesced_packets_;
+ QuicDeque<std::unique_ptr<QuicEncryptedPacket>> received_coalesced_packets_;
// Maximum number of undecryptable packets the connection will store.
size_t max_undecryptable_packets_;
@@ -1274,15 +1276,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
bool send_ietf_version_negotiation_packet_;
bool send_version_negotiation_packet_with_prefixed_lengths_;
- // When packets could not be sent because the socket was not writable,
- // they are added to this list. All corresponding frames are in
- // unacked_packets_ if they are to be retransmitted. Packets encrypted_buffer
- // fields are owned by the QueuedPacketList, in order to ensure they outlast
- // the original scope of the SerializedPacket.
- // TODO(fayang): Remove this when deprecating
- // quic_treat_queued_packets_as_sent.
- QueuedPacketList queued_packets_;
-
// Contains the connection close packets if the connection has been closed.
std::unique_ptr<std::vector<std::unique_ptr<QuicEncryptedPacket>>>
termination_packets_;
@@ -1301,7 +1294,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Indicates how many consecutive times an ack has arrived which indicates
// the peer needs to stop waiting for some packets.
- // TODO(fayang): remove this when deprecating quic_simplify_stop_waiting.
+ // TODO(fayang): remove this when deprecating QUIC_VERSION_43.
int stop_waiting_count_;
// Indicates the retransmission alarm needs to be set.
@@ -1314,8 +1307,12 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// The timeout for PING.
QuicTime::Delta ping_timeout_;
- // Timeout for how long the wire can have no retransmittable packets.
- QuicTime::Delta retransmittable_on_wire_timeout_;
+ // Initial timeout for how long the wire can have no retransmittable packets.
+ QuicTime::Delta initial_retransmittable_on_wire_timeout_;
+
+ // Indicates how many retransmittable-on-wire pings have been emitted without
+ // receiving any new data in between.
+ int consecutive_retransmittable_on_wire_ping_count_;
// Arena to store class implementations within the QuicConnection.
QuicConnectionArena arena_;
@@ -1344,7 +1341,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
QuicConnectionVisitorInterface* visitor_;
QuicConnectionDebugVisitor* debug_visitor_;
- QuicPacketGenerator packet_generator_;
+ QuicPacketCreator packet_creator_;
// Network idle time before this connection is closed.
QuicTime::Delta idle_network_timeout_;
@@ -1369,6 +1366,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
QuicSentPacketManager sent_packet_manager_;
// Indicates whether connection version has been negotiated.
+ // Always true for server connections.
bool version_negotiated_;
// Tracks if the connection was created by the server or the client.
@@ -1392,19 +1390,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// version negotiation packet.
ParsedQuicVersionVector server_supported_versions_;
- // The size of the packet we are targeting while doing path MTU discovery.
- QuicByteCount mtu_discovery_target_;
-
// The number of MTU probes already sent.
size_t mtu_probe_count_;
- // The number of packets between MTU probes.
- QuicPacketCount packets_between_mtu_probes_;
-
- // The packet number of the packet after which the next MTU probe will be
- // sent.
- QuicPacketNumber next_mtu_probe_at_;
-
// The value of the MTU regularly used by the connection. This is different
// from the value returned by max_packet_size(), as max_packet_size() returns
// the value of the MTU as currently used by the serializer, so if
@@ -1501,23 +1489,24 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// EnforceAntiAmplificationLimit returns true.
bool address_validated_;
- // If true, skip packet number before sending the last PTO retransmission.
- bool skip_packet_number_for_pto_;
-
// Used to store content of packets which cannot be sent because of write
// blocked. Packets' encrypted buffers are copied and owned by
// buffered_packets_. From unacked_packet_map (and congestion control)'s
- // perspective, those packets are considered sent. This is only used when
- // treat_queued_packets_as_sent_ is true.
+ // perspective, those packets are considered sent.
std::list<BufferedPacket> buffered_packets_;
- // Latched value of quic_treat_queued_packets_as_sent.
- const bool treat_queued_packets_as_sent_;
+ // Used to coalesce packets of different encryption level into the same UDP
+ // datagram. Connection stops trying to coalesce packets if a forward secure
+ // packet gets acknowledged.
+ QuicCoalescedPacket coalesced_packet_;
- // Latched value of quic_mtu_discovery_v2.
- const bool mtu_discovery_v2_;
- // Only used if quic_mtu_discovery_v2 is true.
QuicConnectionMtuDiscoverer mtu_discoverer_;
+
+ // Latched value of quic_version_negotiated_by_default_at_server.
+ const bool quic_version_negotiated_by_default_at_server_;
+
+ // Latched value of quic_use_handshaker_delegate.
+ const bool use_handshake_delegate_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_id.cc b/chromium/net/third_party/quiche/src/quic/core/quic_connection_id.cc
index c2a8754af39..49e90b6bb38 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection_id.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection_id.cc
@@ -14,11 +14,11 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
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 431cc741f60..25af43def29 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
@@ -127,7 +127,7 @@ QUIC_EXPORT_PRIVATE QuicConnectionId EmptyQuicConnectionId();
// Note however that this property is not guaranteed across process lifetimes.
// This makes QuicConnectionIdHash suitable for data structures such as hash
// tables but not for sending a hash over the network.
-class QuicConnectionIdHash {
+class QUIC_EXPORT_PRIVATE QuicConnectionIdHash {
public:
size_t operator()(QuicConnectionId const& connection_id) const noexcept {
return connection_id.Hash();
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.cc b/chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.cc
index 128bc93aa39..89f7e546d88 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.cc
@@ -6,55 +6,6 @@
namespace quic {
-QuicConnectionStats::QuicConnectionStats()
- : bytes_sent(0),
- packets_sent(0),
- stream_bytes_sent(0),
- packets_discarded(0),
- bytes_received(0),
- packets_received(0),
- packets_processed(0),
- stream_bytes_received(0),
- bytes_retransmitted(0),
- packets_retransmitted(0),
- bytes_spuriously_retransmitted(0),
- packets_spuriously_retransmitted(0),
- packets_lost(0),
- slowstart_count(0),
- slowstart_num_rtts(0),
- slowstart_packets_sent(0),
- slowstart_bytes_sent(0),
- slowstart_packets_lost(0),
- slowstart_bytes_lost(0),
- slowstart_duration(QuicTime::Delta::Zero()),
- slowstart_start_time(QuicTime::Zero()),
- packets_dropped(0),
- undecryptable_packets_received_before_handshake_complete(0),
- crypto_retransmit_count(0),
- loss_timeout_count(0),
- tlp_count(0),
- rto_count(0),
- pto_count(0),
- min_rtt_us(0),
- srtt_us(0),
- max_packet_size(0),
- max_received_packet_size(0),
- estimated_bandwidth(QuicBandwidth::Zero()),
- packets_reordered(0),
- max_sequence_reordering(0),
- max_time_reordering_us(0),
- tcp_loss_events(0),
- connection_creation_time(QuicTime::Zero()),
- blocked_frames_received(0),
- blocked_frames_sent(0),
- num_connectivity_probing_received(0),
- retry_packet_processed(false) {}
-
-QuicConnectionStats::QuicConnectionStats(const QuicConnectionStats& other) =
- default;
-
-QuicConnectionStats::~QuicConnectionStats() {}
-
std::ostream& operator<<(std::ostream& os, const QuicConnectionStats& s) {
os << "{ bytes_sent: " << s.bytes_sent;
os << " packets_sent: " << s.packets_sent;
@@ -98,6 +49,10 @@ std::ostream& operator<<(std::ostream& os, const QuicConnectionStats& s) {
<< s.num_connectivity_probing_received;
os << " retry_packet_processed: "
<< (s.retry_packet_processed ? "yes" : "no");
+ os << " num_coalesced_packets_received: " << s.num_coalesced_packets_received;
+ os << " num_coalesced_packets_processed: "
+ << s.num_coalesced_packets_processed;
+ os << " num_ack_aggregation_epochs: " << s.num_ack_aggregation_epochs;
os << " }";
return os;
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 805afd15a73..c76d591602b 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
@@ -11,104 +11,107 @@
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
+#include "net/third_party/quiche/src/quic/core/quic_time_accumulator.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
namespace quic {
// Structure to hold stats for a QuicConnection.
struct QUIC_EXPORT_PRIVATE QuicConnectionStats {
- QuicConnectionStats();
- QuicConnectionStats(const QuicConnectionStats& other);
- ~QuicConnectionStats();
-
QUIC_EXPORT_PRIVATE friend std::ostream& operator<<(
std::ostream& os,
const QuicConnectionStats& s);
- QuicByteCount bytes_sent; // Includes retransmissions.
- QuicPacketCount packets_sent;
+ QuicByteCount bytes_sent = 0; // Includes retransmissions.
+ QuicPacketCount packets_sent = 0;
// Non-retransmitted bytes sent in a stream frame.
- QuicByteCount stream_bytes_sent;
+ QuicByteCount stream_bytes_sent = 0;
// Packets serialized and discarded before sending.
- QuicPacketCount packets_discarded;
+ QuicPacketCount packets_discarded = 0;
// These include version negotiation and public reset packets, which do not
// have packet numbers or frame data.
- QuicByteCount bytes_received; // Includes duplicate data for a stream.
+ QuicByteCount bytes_received = 0; // Includes duplicate data for a stream.
// Includes packets which were not processable.
- QuicPacketCount packets_received;
+ QuicPacketCount packets_received = 0;
// Excludes packets which were not processable.
- QuicPacketCount packets_processed;
- QuicByteCount stream_bytes_received; // Bytes received in a stream frame.
+ QuicPacketCount packets_processed = 0;
+ QuicByteCount stream_bytes_received = 0; // Bytes received in a stream frame.
- QuicByteCount bytes_retransmitted;
- QuicPacketCount packets_retransmitted;
+ QuicByteCount bytes_retransmitted = 0;
+ QuicPacketCount packets_retransmitted = 0;
- QuicByteCount bytes_spuriously_retransmitted;
- QuicPacketCount packets_spuriously_retransmitted;
+ QuicByteCount bytes_spuriously_retransmitted = 0;
+ QuicPacketCount packets_spuriously_retransmitted = 0;
// Number of packets abandoned as lost by the loss detection algorithm.
- QuicPacketCount packets_lost;
+ QuicPacketCount packets_lost = 0;
// Number of times this connection went through the slow start phase.
- uint32_t slowstart_count;
+ uint32_t slowstart_count = 0;
// Number of round trips spent in slow start.
- uint32_t slowstart_num_rtts;
+ uint32_t slowstart_num_rtts = 0;
// Number of packets sent in slow start.
- QuicPacketCount slowstart_packets_sent;
+ QuicPacketCount slowstart_packets_sent = 0;
// Number of bytes sent in slow start.
- QuicByteCount slowstart_bytes_sent;
+ QuicByteCount slowstart_bytes_sent = 0;
// Number of packets lost exiting slow start.
- QuicPacketCount slowstart_packets_lost;
+ QuicPacketCount slowstart_packets_lost = 0;
// Number of bytes lost exiting slow start.
- QuicByteCount slowstart_bytes_lost;
- // Time spent in COMPLETED slow start phases.
- QuicTime::Delta slowstart_duration;
- // Start time of the last slow start phase.
- QuicTime slowstart_start_time;
+ QuicByteCount slowstart_bytes_lost = 0;
+ // Time spent in slow start. Populated for BBRv1 and BBRv2.
+ QuicTimeAccumulator slowstart_duration;
- QuicPacketCount packets_dropped; // Duplicate or less than least unacked.
+ QuicPacketCount packets_dropped = 0; // Duplicate or less than least unacked.
// Packets that failed to decrypt when they were first received,
// before the handshake was complete.
- QuicPacketCount undecryptable_packets_received_before_handshake_complete;
+ QuicPacketCount undecryptable_packets_received_before_handshake_complete = 0;
- size_t crypto_retransmit_count;
+ size_t crypto_retransmit_count = 0;
// Count of times the loss detection alarm fired. At least one packet should
// be lost when the alarm fires.
- size_t loss_timeout_count;
- size_t tlp_count;
- size_t rto_count; // Count of times the rto timer fired.
- size_t pto_count;
+ size_t loss_timeout_count = 0;
+ size_t tlp_count = 0;
+ size_t rto_count = 0; // Count of times the rto timer fired.
+ size_t pto_count = 0;
- int64_t min_rtt_us; // Minimum RTT in microseconds.
- int64_t srtt_us; // Smoothed RTT in microseconds.
- QuicByteCount max_packet_size;
- QuicByteCount max_received_packet_size;
- QuicBandwidth estimated_bandwidth;
+ int64_t min_rtt_us = 0; // Minimum RTT in microseconds.
+ int64_t srtt_us = 0; // Smoothed RTT in microseconds.
+ QuicByteCount max_packet_size = 0;
+ QuicByteCount max_received_packet_size = 0;
+ QuicBandwidth estimated_bandwidth = QuicBandwidth::Zero();
// Reordering stats for received packets.
// Number of packets received out of packet number order.
- QuicPacketCount packets_reordered;
+ QuicPacketCount packets_reordered = 0;
// Maximum reordering observed in packet number space.
- QuicPacketCount max_sequence_reordering;
+ QuicPacketCount max_sequence_reordering = 0;
// Maximum reordering observed in microseconds
- int64_t max_time_reordering_us;
+ int64_t max_time_reordering_us = 0;
// The following stats are used only in TcpCubicSender.
// The number of loss events from TCP's perspective. Each loss event includes
// one or more lost packets.
- uint32_t tcp_loss_events;
+ uint32_t tcp_loss_events = 0;
// Creation time, as reported by the QuicClock.
- QuicTime connection_creation_time;
+ QuicTime connection_creation_time = QuicTime::Zero();
- uint64_t blocked_frames_received;
- uint64_t blocked_frames_sent;
+ uint64_t blocked_frames_received = 0;
+ uint64_t blocked_frames_sent = 0;
// Number of connectivity probing packets received by this connection.
- uint64_t num_connectivity_probing_received;
+ uint64_t num_connectivity_probing_received = 0;
// Whether a RETRY packet was successfully processed.
- bool retry_packet_processed;
+ bool retry_packet_processed = false;
+
+ // Number of received coalesced packets.
+ uint64_t num_coalesced_packets_received = 0;
+ // Number of successfully processed coalesced packets.
+ uint64_t num_coalesced_packets_processed = 0;
+ // Number of ack aggregation epochs. For the same number of bytes acked, the
+ // smaller this value, the more ack aggregation is going on.
+ uint64_t num_ack_aggregation_epochs = 0;
};
} // 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 3d923a2deac..3babced88b6 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
@@ -36,7 +36,6 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h"
-#include "net/third_party/quiche/src/quic/test_tools/quic_packet_generator_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simple_data_producer.h"
@@ -338,6 +337,7 @@ class TestPacketWriter : public QuicPacketWriter {
final_bytes_of_previous_packet_(0),
use_tagging_decrypter_(false),
packets_write_attempts_(0),
+ connection_close_packets_(0),
clock_(clock),
write_pause_time_delta_(QuicTime::Delta::Zero()),
max_packet_size_(kMaxOutgoingPacketSize),
@@ -406,7 +406,9 @@ class TestPacketWriter : public QuicPacketWriter {
last_packet_size_ = packet.length();
last_packet_header_ = framer_.header();
-
+ if (!framer_.connection_close_frames().empty()) {
+ ++connection_close_packets_;
+ }
if (!write_pause_time_delta_.IsZero()) {
clock_->AdvanceTime(write_pause_time_delta_);
}
@@ -514,6 +516,10 @@ class TestPacketWriter : public QuicPacketWriter {
return framer_.path_response_frames();
}
+ const QuicEncryptedPacket* coalesced_packet() const {
+ return framer_.coalesced_packet();
+ }
+
size_t last_packet_size() { return last_packet_size_; }
const QuicPacketHeader& last_packet_header() const {
@@ -550,6 +556,10 @@ class TestPacketWriter : public QuicPacketWriter {
uint32_t packets_write_attempts() { return packets_write_attempts_; }
+ uint32_t connection_close_packets() const {
+ return connection_close_packets_;
+ }
+
void Reset() { framer_.Reset(); }
void SetSupportedVersions(const ParsedQuicVersionVector& versions) {
@@ -583,6 +593,7 @@ class TestPacketWriter : public QuicPacketWriter {
uint32_t final_bytes_of_previous_packet_;
bool use_tagging_decrypter_;
uint32_t packets_write_attempts_;
+ uint32_t connection_close_packets_;
MockClock* clock_;
// If non-zero, the clock will pause during WritePacket for this amount of
// time.
@@ -631,6 +642,7 @@ class TestConnection : public QuicConnection {
HasRetransmittableData retransmittable,
bool has_ack,
bool has_pending_frames) {
+ ScopedPacketFlusher flusher(this);
char buffer[kMaxOutgoingPacketSize];
size_t encrypted_length =
QuicConnectionPeer::GetFramer(this)->EncryptPayload(
@@ -641,7 +653,7 @@ class TestConnection : public QuicConnection {
encrypted_length, has_ack, has_pending_frames);
if (retransmittable == HAS_RETRANSMITTABLE_DATA) {
serialized_packet.retransmittable_frames.push_back(
- QuicFrame(QuicStreamFrame()));
+ QuicFrame(QuicPingFrame()));
}
OnSerializedPacket(&serialized_packet);
}
@@ -668,7 +680,7 @@ class TestConnection : public QuicConnection {
if (!QuicUtils::IsCryptoStreamId(transport_version(), id) &&
this->encryption_level() == ENCRYPTION_INITIAL) {
this->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
- if (perspective() == Perspective::IS_CLIENT && !IsHandshakeConfirmed()) {
+ if (perspective() == Perspective::IS_CLIENT && !IsHandshakeComplete()) {
OnHandshakeComplete();
}
if (version().SupportsAntiAmplificationLimit()) {
@@ -769,14 +781,14 @@ class TestConnection : public QuicConnection {
}
// Enable path MTU discovery. Assumes that the test is performed from the
- // client perspective and the higher value of MTU target is used.
+ // server perspective and the higher value of MTU target is used.
void EnablePathMtuDiscovery(MockSendAlgorithm* send_algorithm) {
- ASSERT_EQ(Perspective::IS_CLIENT, perspective());
+ ASSERT_EQ(Perspective::IS_SERVER, perspective());
QuicConfig config;
QuicTagVector connection_options;
connection_options.push_back(kMTUH);
- config.SetConnectionOptionsToSend(connection_options);
+ config.SetInitialReceivedConnectionOptions(connection_options);
EXPECT_CALL(*send_algorithm, SetFromConfig(_, _));
SetFromConfig(config);
@@ -964,7 +976,6 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
Perspective::IS_CLIENT,
version()),
creator_(QuicConnectionPeer::GetPacketCreator(&connection_)),
- generator_(QuicConnectionPeer::GetPacketGenerator(&connection_)),
manager_(QuicConnectionPeer::GetSentPacketManager(&connection_)),
frame1_(0, false, 0, QuicStringPiece(data1)),
frame2_(0, false, 3, QuicStringPiece(data2)),
@@ -1016,10 +1027,8 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
frame1_.stream_id = stream_id;
frame2_.stream_id = stream_id;
connection_.set_visitor(&visitor_);
- if (connection_.session_decides_what_to_write()) {
- connection_.SetSessionNotifier(&notifier_);
- connection_.set_notifier(&notifier_);
- }
+ connection_.SetSessionNotifier(&notifier_);
+ connection_.set_notifier(&notifier_);
connection_.SetSendAlgorithm(send_algorithm_);
connection_.SetLossAlgorithm(loss_algorithm_.get());
EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
@@ -1034,23 +1043,22 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
EXPECT_CALL(*send_algorithm_, BandwidthEstimate())
.Times(AnyNumber())
.WillRepeatedly(Return(QuicBandwidth::Zero()));
+ EXPECT_CALL(*send_algorithm_, PopulateConnectionStats(_))
+ .Times(AnyNumber());
EXPECT_CALL(*send_algorithm_, InSlowStart()).Times(AnyNumber());
EXPECT_CALL(*send_algorithm_, InRecovery()).Times(AnyNumber());
EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(AnyNumber());
EXPECT_CALL(visitor_, WillingAndAbleToWrite()).Times(AnyNumber());
+ EXPECT_CALL(visitor_, OnPacketDecrypted(_)).Times(AnyNumber());
EXPECT_CALL(visitor_, HasPendingHandshake()).Times(AnyNumber());
- if (connection_.session_decides_what_to_write()) {
- EXPECT_CALL(visitor_, OnCanWrite())
- .WillRepeatedly(
- Invoke(&notifier_, &SimpleSessionNotifier::OnCanWrite));
- } else {
- EXPECT_CALL(visitor_, OnCanWrite()).Times(AnyNumber());
- }
+ EXPECT_CALL(visitor_, OnCanWrite())
+ .WillRepeatedly(Invoke(&notifier_, &SimpleSessionNotifier::OnCanWrite));
EXPECT_CALL(visitor_, ShouldKeepConnectionAlive())
.WillRepeatedly(Return(false));
EXPECT_CALL(visitor_, OnCongestionWindowChange(_)).Times(AnyNumber());
EXPECT_CALL(visitor_, OnPacketReceived(_, _, _)).Times(AnyNumber());
EXPECT_CALL(visitor_, OnForwardProgressConfirmed()).Times(AnyNumber());
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)).Times(AnyNumber());
EXPECT_CALL(*loss_algorithm_, GetLossTimeout())
.WillRepeatedly(Return(QuicTime::Zero()));
@@ -1120,7 +1128,10 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
QuicFrames frames;
frames.push_back(QuicFrame(frame));
QuicPacketCreatorPeer::SetSendVersionInPacket(
- &peer_creator_, connection_.perspective() == Perspective::IS_SERVER);
+ &peer_creator_,
+ QuicPacketCreatorPeer::GetEncryptionLevel(&peer_creator_) <
+ ENCRYPTION_FORWARD_SECURE &&
+ connection_.perspective() == Perspective::IS_SERVER);
char buffer[kMaxOutgoingPacketSize];
SerializedPacket serialized_packet =
@@ -1329,26 +1340,11 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
void SendRstStream(QuicStreamId id,
QuicRstStreamErrorCode error,
QuicStreamOffset bytes_written) {
- if (connection_.session_decides_what_to_write()) {
- notifier_.WriteOrBufferRstStream(id, error, bytes_written);
- connection_.OnStreamReset(id, error);
- return;
- }
- std::unique_ptr<QuicRstStreamFrame> rst_stream =
- std::make_unique<QuicRstStreamFrame>(1, id, error, bytes_written);
- if (connection_.SendControlFrame(QuicFrame(rst_stream.get()))) {
- rst_stream.release();
- }
+ notifier_.WriteOrBufferRstStream(id, error, bytes_written);
connection_.OnStreamReset(id, error);
}
- void SendPing() {
- if (connection_.session_decides_what_to_write()) {
- notifier_.WriteOrBufferPing();
- } else {
- connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
- }
- }
+ void SendPing() { notifier_.WriteOrBufferPing(); }
void ProcessAckPacket(uint64_t packet_number, QuicAckFrame* frame) {
if (packet_number > 1) {
@@ -1536,8 +1532,8 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
EXPECT_FALSE(QuicConnectionPeer::GetConnectionClosePacket(&connection_) ==
nullptr);
EXPECT_EQ(1, connection_close_frame_count_);
- EXPECT_EQ(QUIC_INVALID_ACK_DATA,
- saved_connection_close_frame_.quic_error_code);
+ EXPECT_THAT(saved_connection_close_frame_.quic_error_code,
+ IsError(QUIC_INVALID_ACK_DATA));
}
void BlockOnNextWrite() {
@@ -1567,6 +1563,10 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
connection_.set_perspective(perspective);
if (perspective == Perspective::IS_SERVER) {
connection_.set_can_truncate_connection_ids(true);
+ QuicConnectionPeer::SetNegotiatedVersion(&connection_);
+ if (GetQuicReloadableFlag(quic_version_negotiated_by_default_at_server)) {
+ connection_.OnSuccessfulVersionNegotiation();
+ }
}
QuicFramerPeer::SetPerspective(&peer_framer_,
QuicUtils::InvertPerspective(perspective));
@@ -1574,16 +1574,9 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
void set_packets_between_probes_base(
const QuicPacketCount packets_between_probes_base) {
- if (GetQuicReloadableFlag(quic_mtu_discovery_v2)) {
- QuicConnectionPeer::ReInitializeMtuDiscoverer(
- &connection_, packets_between_probes_base,
- QuicPacketNumber(packets_between_probes_base));
- } else {
- QuicConnectionPeer::SetPacketsBetweenMtuProbes(
- &connection_, packets_between_probes_base);
- QuicConnectionPeer::SetNextMtuProbeAt(
- &connection_, QuicPacketNumber(packets_between_probes_base));
- }
+ QuicConnectionPeer::ReInitializeMtuDiscoverer(
+ &connection_, packets_between_probes_base,
+ QuicPacketNumber(packets_between_probes_base));
}
bool IsDefaultTestConfiguration() {
@@ -1627,6 +1620,24 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
}
}
+ void MtuDiscoveryTestInit() {
+ set_perspective(Perspective::IS_SERVER);
+ QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ peer_creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
+ // QuicFramer::GetMaxPlaintextSize uses the smallest max plaintext size
+ // across all encrypters. The initial encrypter used with IETF QUIC has a
+ // 16-byte overhead, while the NullEncrypter used throughout this test has a
+ // 12-byte overhead. This test tests behavior that relies on computing the
+ // packet size correctly, so by unsetting the initial encrypter, we avoid
+ // having a mismatch between the overheads for the encrypters used. In
+ // non-test scenarios all encrypters used for a given connection have the
+ // same overhead, either 12 bytes for ones using Google QUIC crypto, or 16
+ // bytes for ones using TLS.
+ connection_.SetEncrypter(ENCRYPTION_INITIAL, nullptr);
+ EXPECT_TRUE(connection_.connected());
+ }
+
QuicConnectionId connection_id_;
QuicFramer framer_;
@@ -1642,7 +1653,6 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
std::unique_ptr<TestPacketWriter> writer_;
TestConnection connection_;
QuicPacketCreator* creator_;
- QuicPacketGenerator* generator_;
QuicSentPacketManager* manager_;
StrictMock<MockQuicConnectionVisitor> visitor_;
@@ -1727,8 +1737,6 @@ TEST_P(QuicConnectionTest, SelfAddressChangeAtClient) {
}
TEST_P(QuicConnectionTest, SelfAddressChangeAtServer) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
@@ -1758,8 +1766,6 @@ TEST_P(QuicConnectionTest, SelfAddressChangeAtServer) {
}
TEST_P(QuicConnectionTest, AllowSelfAddressChangeToMappedIpv4AddressAtServer) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
@@ -1793,7 +1799,6 @@ TEST_P(QuicConnectionTest, AllowSelfAddressChangeToMappedIpv4AddressAtServer) {
}
TEST_P(QuicConnectionTest, ClientAddressChangeAndPacketReordered) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
@@ -1832,7 +1837,6 @@ TEST_P(QuicConnectionTest, ClientAddressChangeAndPacketReordered) {
}
TEST_P(QuicConnectionTest, PeerAddressChangeAtServer) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
@@ -1870,7 +1874,6 @@ TEST_P(QuicConnectionTest, PeerAddressChangeAtServer) {
}
TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
@@ -1956,7 +1959,6 @@ TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
}
TEST_P(QuicConnectionTest, ReceivePaddedPingAtServer) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
@@ -2032,29 +2034,17 @@ TEST_P(QuicConnectionTest, WriteOutOfOrderQueuedPackets) {
writer_->SetWritable();
connection_.SendConnectivityProbingPacket(writer_.get(),
connection_.peer_address());
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(visitor_, OnConnectionClosed(_, _)).Times(0);
- connection_.OnCanWrite();
- return;
- }
- EXPECT_CALL(visitor_,
- OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
- EXPECT_QUIC_BUG(connection_.OnCanWrite(),
- "Attempt to write packet:1 after:2");
- EXPECT_FALSE(connection_.connected());
- TestConnectionCloseQuicErrorCode(QUIC_INTERNAL_ERROR);
- const std::vector<QuicConnectionCloseFrame>& connection_close_frames =
- writer_->connection_close_frames();
- EXPECT_EQ("Packet written out of order.",
- connection_close_frames[0].error_details);
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _)).Times(0);
+ connection_.OnCanWrite();
}
TEST_P(QuicConnectionTest, DiscardQueuedPacketsAfterConnectionClose) {
// Regression test for b/74073386.
{
InSequence seq;
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- EXPECT_CALL(visitor_, OnConnectionClosed(_, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(AtLeast(1));
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _)).Times(AtLeast(1));
}
set_perspective(Perspective::IS_CLIENT);
@@ -2067,12 +2057,8 @@ TEST_P(QuicConnectionTest, DiscardQueuedPacketsAfterConnectionClose) {
connection_.SendStreamDataWithString(/*id=*/2, "foo", 0, NO_FIN);
EXPECT_FALSE(connection_.connected());
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- // No need to buffer packets.
- EXPECT_EQ(0u, connection_.NumQueuedPackets());
- } else {
- EXPECT_EQ(1u, connection_.NumQueuedPackets());
- }
+ // No need to buffer packets.
+ EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_EQ(0u, connection_.GetStats().packets_discarded);
connection_.OnCanWrite();
@@ -2080,7 +2066,6 @@ TEST_P(QuicConnectionTest, DiscardQueuedPacketsAfterConnectionClose) {
}
TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtServer) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
@@ -2139,7 +2124,6 @@ TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtServer) {
}
TEST_P(QuicConnectionTest, ReceiveReorderedConnectivityProbingAtServer) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
@@ -2196,7 +2180,6 @@ TEST_P(QuicConnectionTest, ReceiveReorderedConnectivityProbingAtServer) {
}
TEST_P(QuicConnectionTest, MigrateAfterProbingAtServer) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
@@ -2397,8 +2380,6 @@ TEST_P(QuicConnectionTest, SmallerServerMaxPacketSize) {
}
TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSize) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
set_perspective(Perspective::IS_SERVER);
connection_.SetMaxPacketLength(1000);
@@ -2443,8 +2424,6 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSize) {
}
TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSizeWhileWriterLimited) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
const QuicByteCount lower_max_packet_size = 1240;
writer_->set_max_packet_size(lower_max_packet_size);
set_perspective(Perspective::IS_SERVER);
@@ -2708,18 +2687,13 @@ TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) {
connection_.SendStreamDataWithString(3, "foofoofoo", 9, NO_FIN);
// Ack bundled.
if (GetParam().no_stop_waiting) {
- if (GetQuicReloadableFlag(quic_simplify_stop_waiting)) {
- // Do not ACK acks.
- EXPECT_EQ(1u, writer_->frame_count());
- } else {
- EXPECT_EQ(2u, writer_->frame_count());
- }
+ // Do not ACK acks.
+ EXPECT_EQ(1u, writer_->frame_count());
} else {
EXPECT_EQ(3u, writer_->frame_count());
}
EXPECT_EQ(1u, writer_->stream_frames().size());
- if (GetParam().no_stop_waiting &&
- GetQuicReloadableFlag(quic_simplify_stop_waiting)) {
+ if (GetParam().no_stop_waiting) {
EXPECT_TRUE(writer_->ack_frames().empty());
} else {
EXPECT_FALSE(writer_->ack_frames().empty());
@@ -2852,9 +2826,11 @@ TEST_P(QuicConnectionTest, LeastUnackedLower) {
// one. This should cause a connection error.
QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 7);
if (!GetParam().no_stop_waiting) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(AtLeast(1));
EXPECT_CALL(visitor_,
- OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
+ OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF))
+ .Times(AtLeast(1));
}
ProcessStopWaitingPacket(InitStopWaitingFrame(1));
if (!GetParam().no_stop_waiting) {
@@ -2907,7 +2883,7 @@ TEST_P(QuicConnectionTest, AckUnsentData) {
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
QuicAckFrame frame = InitAckFrame(1);
EXPECT_CALL(visitor_, OnCanWrite()).Times(0);
ProcessAckPacket(&frame);
@@ -3078,7 +3054,9 @@ TEST_P(QuicConnectionTest, FramePackingNonCryptoThenCrypto) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
QuicConnection::ScopedPacketFlusher flusher(&connection_);
connection_.SendStreamData3();
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
connection_.SendCryptoStreamData();
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
}
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_FALSE(connection_.HasQueuedData());
@@ -3366,11 +3344,6 @@ TEST_P(QuicConnectionTest, DoNotSendQueuedPacketForResetStream) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
writer_->SetWritable();
connection_.OnCanWrite();
- if (!connection_.session_decides_what_to_write()) {
- // OnCanWrite will cause RST_STREAM be sent again.
- connection_.SendControlFrame(QuicFrame(new QuicRstStreamFrame(
- 1, stream_id, QUIC_ERROR_PROCESSING_STREAM, 14)));
- }
size_t padding_frame_count = writer_->padding_frames().size();
EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
EXPECT_EQ(1u, writer_->rst_stream_frames().size());
@@ -3381,11 +3354,7 @@ TEST_P(QuicConnectionTest, SendQueuedPacketForQuicRstStreamNoError) {
BlockOnNextWrite();
QuicStreamId stream_id = 2;
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- } else {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
connection_.SendStreamDataWithString(stream_id, "foo", 0, NO_FIN);
// Now that there is a queued packet, reset the stream.
@@ -3393,20 +3362,9 @@ TEST_P(QuicConnectionTest, SendQueuedPacketForQuicRstStreamNoError) {
// Unblock the connection and verify that the RST_STREAM is sent and the data
// packet is sent.
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
- .Times(AtLeast(1));
- } else {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
- .Times(AtLeast(2));
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
writer_->SetWritable();
connection_.OnCanWrite();
- if (!connection_.session_decides_what_to_write()) {
- // OnCanWrite will cause RST_STREAM be sent again.
- connection_.SendControlFrame(QuicFrame(
- new QuicRstStreamFrame(1, stream_id, QUIC_STREAM_NO_ERROR, 14)));
- }
size_t padding_frame_count = writer_->padding_frames().size();
EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
EXPECT_EQ(1u, writer_->rst_stream_frames().size());
@@ -3495,12 +3453,7 @@ TEST_P(QuicConnectionTest, CancelRetransmissionAlarmAfterResetStream) {
// Ensure that the data is still in flight, but the retransmission alarm is no
// longer set.
EXPECT_GT(manager_->GetBytesInFlight(), 0u);
- if (QuicConnectionPeer::GetSentPacketManager(&connection_)
- ->fix_rto_retransmission()) {
- EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
- } else {
- EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
- }
+ EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
}
TEST_P(QuicConnectionTest, RetransmitForQuicRstStreamNoErrorOnRTO) {
@@ -3547,11 +3500,6 @@ TEST_P(QuicConnectionTest, DoNotSendPendingRetransmissionForResetStream) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
writer_->SetWritable();
connection_.OnCanWrite();
- if (!connection_.session_decides_what_to_write()) {
- // OnCanWrite will cause this RST_STREAM_FRAME be sent again.
- connection_.SendControlFrame(QuicFrame(new QuicRstStreamFrame(
- 1, stream_id, QUIC_ERROR_PROCESSING_STREAM, 14)));
- }
size_t padding_frame_count = writer_->padding_frames().size();
EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
ASSERT_EQ(1u, writer_->rst_stream_frames().size());
@@ -3613,12 +3561,8 @@ TEST_P(QuicConnectionTest, RetransmitAckedPacket) {
EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _))
.WillOnce(SetArgPointee<5>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(4), _, _))
- .Times(1);
- } else {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(4), _, _))
+ .Times(1);
ProcessAckPacket(&nack_two);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
@@ -3628,15 +3572,8 @@ TEST_P(QuicConnectionTest, RetransmitAckedPacket) {
QuicAckFrame ack_all = InitAckFrame(3);
ProcessAckPacket(&ack_all);
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(4), _, _))
- .Times(0);
- } else {
- // Unblock the socket and attempt to send the queued packets. We will always
- // send the retransmission.
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(4), _, _))
- .Times(1);
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(4), _, _))
+ .Times(0);
writer_->SetWritable();
connection_.OnCanWrite();
@@ -3674,8 +3611,7 @@ TEST_P(QuicConnectionTest, RetransmitNackedLargestObserved) {
}
TEST_P(QuicConnectionTest, QueueAfterTwoRTOs) {
- if (connection_.PtoEnabled() ||
- !connection_.session_decides_what_to_write()) {
+ if (connection_.PtoEnabled()) {
return;
}
connection_.SetMaxTailLossProbes(0);
@@ -3688,11 +3624,7 @@ TEST_P(QuicConnectionTest, QueueAfterTwoRTOs) {
// Block the writer and ensure they're queued.
BlockOnNextWrite();
clock_.AdvanceTime(DefaultRetransmissionTime());
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
- } else {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
connection_.GetRetransmissionAlarm()->Fire();
EXPECT_TRUE(connection_.HasQueuedData());
@@ -3700,12 +3632,7 @@ TEST_P(QuicConnectionTest, QueueAfterTwoRTOs) {
writer_->SetWritable();
clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(
2 * DefaultRetransmissionTime().ToMicroseconds()));
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
- } else {
- // 2 RTOs + 1 TLP, which is buggy.
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(3);
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
connection_.GetRetransmissionAlarm()->Fire();
connection_.OnCanWrite();
}
@@ -3725,36 +3652,20 @@ TEST_P(QuicConnectionTest, WriteBlockedBufferedThenSent) {
TEST_P(QuicConnectionTest, WriteBlockedThenSent) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
BlockOnNextWrite();
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- } else {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN);
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
- } else {
- EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
- }
+ EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
EXPECT_EQ(1u, connection_.NumQueuedPackets());
// The second packet should also be queued, in order to ensure packets are
// never sent out of order.
writer_->SetWritable();
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- } else {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN);
EXPECT_EQ(2u, connection_.NumQueuedPackets());
// Now both are sent in order when we unblock.
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
- } else {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
connection_.OnCanWrite();
EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
EXPECT_EQ(0u, connection_.NumQueuedPackets());
@@ -3779,12 +3690,7 @@ TEST_P(QuicConnectionTest, RetransmitWriteBlockedAckedOriginalThenSent) {
writer_->SetWritable();
connection_.OnCanWrite();
- if (QuicConnectionPeer::GetSentPacketManager(&connection_)
- ->fix_rto_retransmission()) {
- EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
- } else {
- EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
- }
+ EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
EXPECT_FALSE(QuicConnectionPeer::HasRetransmittableFrames(&connection_, 2));
}
@@ -3867,8 +3773,8 @@ TEST_P(QuicConnectionTest, DoNotAddToWriteBlockedListAfterDisconnect) {
writer_->SetWriteBlocked();
}
EXPECT_EQ(1, connection_close_frame_count_);
- EXPECT_EQ(QUIC_PEER_GOING_AWAY,
- saved_connection_close_frame_.quic_error_code);
+ EXPECT_THAT(saved_connection_close_frame_.quic_error_code,
+ IsError(QUIC_PEER_GOING_AWAY));
}
TEST_P(QuicConnectionTest, AddToWriteBlockedListIfBlockedOnFlushPackets) {
@@ -3906,11 +3812,7 @@ TEST_P(QuicConnectionTest, NoLimitPacketsPerNack) {
EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _))
.WillOnce(SetArgPointee<5>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- if (connection_.session_decides_what_to_write()) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- } else {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(14);
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
ProcessAckPacket(&nack);
}
@@ -4036,8 +3938,7 @@ TEST_P(QuicConnectionTest, TLP) {
}
TEST_P(QuicConnectionTest, TailLossProbeDelayForStreamDataInTLPR) {
- if (!connection_.session_decides_what_to_write() ||
- connection_.PtoEnabled()) {
+ if (connection_.PtoEnabled()) {
return;
}
@@ -4072,8 +3973,7 @@ TEST_P(QuicConnectionTest, TailLossProbeDelayForStreamDataInTLPR) {
}
TEST_P(QuicConnectionTest, TailLossProbeDelayForNonStreamDataInTLPR) {
- if (!connection_.session_decides_what_to_write() ||
- connection_.PtoEnabled()) {
+ if (connection_.PtoEnabled()) {
return;
}
@@ -4089,7 +3989,7 @@ TEST_P(QuicConnectionTest, TailLossProbeDelayForNonStreamDataInTLPR) {
// Sets retransmittable on wire.
const QuicTime::Delta retransmittable_on_wire_timeout =
QuicTime::Delta::FromMilliseconds(50);
- connection_.set_retransmittable_on_wire_timeout(
+ connection_.set_initial_retransmittable_on_wire_timeout(
retransmittable_on_wire_timeout);
EXPECT_TRUE(connection_.connected());
@@ -4129,7 +4029,7 @@ TEST_P(QuicConnectionTest, TailLossProbeDelayForNonStreamDataInTLPR) {
// The ping alarm is set for the ping timeout, not the shorter
// retransmittable_on_wire_timeout.
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
- EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs),
+ EXPECT_EQ(connection_.ping_timeout(),
connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
// Receive an ACK for the data packet.
@@ -4184,7 +4084,7 @@ TEST_P(QuicConnectionTest, TailLossProbeDelayForNonStreamDataInTLPR) {
// The ping alarm is set for the ping timeout, not the shorter
// retransmittable_on_wire_timeout.
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
- EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs),
+ EXPECT_EQ(connection_.ping_timeout(),
connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
// Advance a small period of time: 5ms. And receive a retransmitted ACK.
@@ -4227,8 +4127,7 @@ TEST_P(QuicConnectionTest, RTO) {
// Regression test of b/133771183.
TEST_P(QuicConnectionTest, RtoWithNoDataToRetransmit) {
- if (!connection_.session_decides_what_to_write() ||
- connection_.PtoEnabled()) {
+ if (connection_.PtoEnabled()) {
return;
}
connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
@@ -4243,31 +4142,14 @@ TEST_P(QuicConnectionTest, RtoWithNoDataToRetransmit) {
// Simulate the retransmission alarm firing.
clock_.AdvanceTime(DefaultRetransmissionTime());
// RTO fires, but there is no packet to be RTOed.
- if (GetQuicReloadableFlag(quic_fix_rto_retransmission3)) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- } else {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
connection_.GetRetransmissionAlarm()->Fire();
- if (GetQuicReloadableFlag(quic_fix_rto_retransmission3)) {
- EXPECT_EQ(1u, writer_->rst_stream_frames().size());
- }
+ EXPECT_EQ(1u, writer_->rst_stream_frames().size());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(40);
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(20);
- if (GetQuicReloadableFlag(quic_fix_rto_retransmission3)) {
- EXPECT_CALL(visitor_, WillingAndAbleToWrite())
- .WillRepeatedly(Return(false));
- } else {
- EXPECT_CALL(visitor_, WillingAndAbleToWrite()).WillRepeatedly(Return(true));
- }
- if (GetQuicReloadableFlag(quic_fix_rto_retransmission3)) {
- EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(1);
- } else {
- // Since there is a buffered RST_STREAM, no retransmittable frame is bundled
- // with ACKs.
- EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(0);
- }
+ EXPECT_CALL(visitor_, WillingAndAbleToWrite()).WillRepeatedly(Return(false));
+ EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(1);
// Receives packets 1 - 40.
for (size_t i = 1; i <= 40; ++i) {
ProcessDataPacket(i);
@@ -4304,9 +4186,12 @@ TEST_P(QuicConnectionTest, RetransmitWithSameEncryptionLevel) {
// Manually mark both packets for retransmission.
connection_.RetransmitUnackedPackets(ALL_UNACKED_RETRANSMISSION);
-
- // Packet should have been sent with ENCRYPTION_INITIAL.
- EXPECT_EQ(0x01010101u, writer_->final_bytes_of_previous_packet());
+ if (!connection_.version().CanSendCoalescedPackets()) {
+ // Packet should have been sent with ENCRYPTION_INITIAL.
+ // If connection can send coalesced packet, both retransmissions will be
+ // coalesced in the same UDP datagram.
+ EXPECT_EQ(0x01010101u, writer_->final_bytes_of_previous_packet());
+ }
// Packet should have been sent with ENCRYPTION_ZERO_RTT.
EXPECT_EQ(0x02020202u, writer_->final_bytes_of_last_packet());
@@ -4346,17 +4231,12 @@ TEST_P(QuicConnectionTest,
use_tagging_decrypter();
connection_.SetEncrypter(ENCRYPTION_INITIAL,
std::make_unique<TaggingEncrypter>(0x01));
- QuicPacketNumber packet_number;
connection_.SendCryptoStreamData();
// Simulate the retransmission alarm firing and the socket blocking.
BlockOnNextWrite();
clock_.AdvanceTime(DefaultRetransmissionTime());
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- } else {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
connection_.GetRetransmissionAlarm()->Fire();
EXPECT_EQ(1u, connection_.NumQueuedPackets());
@@ -4506,26 +4386,13 @@ TEST_P(QuicConnectionTest, Buffer100NonDecryptablePacketsThenKeyChange) {
TEST_P(QuicConnectionTest, SetRTOAfterWritingToSocket) {
BlockOnNextWrite();
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- } else {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN);
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
- } else {
- // Make sure that RTO is not started when the packet is queued.
- EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
- }
+ EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
// Test that RTO is started once we write to the socket.
writer_->SetWritable();
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
- } else {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
connection_.OnCanWrite();
EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
}
@@ -4542,8 +4409,8 @@ TEST_P(QuicConnectionTest, DelayRTOWithAckReceipt) {
connection_.SendStreamDataWithString(3, "bar", 0, NO_FIN);
QuicAlarm* retransmission_alarm = connection_.GetRetransmissionAlarm();
EXPECT_TRUE(retransmission_alarm->IsSet());
- EXPECT_EQ(clock_.Now() + DefaultRetransmissionTime(),
- retransmission_alarm->deadline());
+ EXPECT_EQ(DefaultRetransmissionTime(),
+ retransmission_alarm->deadline() - clock_.Now());
// Advance the time right before the RTO, then receive an ack for the first
// packet to delay the RTO.
@@ -4554,8 +4421,8 @@ TEST_P(QuicConnectionTest, DelayRTOWithAckReceipt) {
// Now we have an RTT sample of DefaultRetransmissionTime(500ms),
// so the RTO has increased to 2 * SRTT.
EXPECT_TRUE(retransmission_alarm->IsSet());
- EXPECT_EQ(retransmission_alarm->deadline(),
- clock_.Now() + 2 * DefaultRetransmissionTime());
+ EXPECT_EQ(retransmission_alarm->deadline() - clock_.Now(),
+ 2 * DefaultRetransmissionTime());
// Move forward past the original RTO and ensure the RTO is still pending.
clock_.AdvanceTime(2 * DefaultRetransmissionTime());
@@ -4780,8 +4647,8 @@ TEST_P(QuicConnectionTest, PingAfterSend) {
GetNthClientInitiatedStreamId(0, connection_.transport_version()),
"GET /", 0, FIN, nullptr);
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
- EXPECT_EQ(clock_.ApproximateNow() + QuicTime::Delta::FromSeconds(15),
- connection_.GetPingAlarm()->deadline());
+ EXPECT_EQ(QuicTime::Delta::FromSeconds(15),
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
// Now recevie an ACK of the previous packet, which will move the
// ping alarm forward.
@@ -4793,9 +4660,9 @@ TEST_P(QuicConnectionTest, PingAfterSend) {
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
// The ping timer is set slightly less than 15 seconds in the future, because
// of the 1s ping timer alarm granularity.
- EXPECT_EQ(clock_.ApproximateNow() + QuicTime::Delta::FromSeconds(15) -
- QuicTime::Delta::FromMilliseconds(5),
- connection_.GetPingAlarm()->deadline());
+ EXPECT_EQ(
+ QuicTime::Delta::FromSeconds(15) - QuicTime::Delta::FromMilliseconds(5),
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
writer_->Reset();
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(15));
@@ -4834,8 +4701,8 @@ TEST_P(QuicConnectionTest, ReducedPingTimeout) {
GetNthClientInitiatedStreamId(0, connection_.transport_version()),
"GET /", 0, FIN, nullptr);
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
- EXPECT_EQ(clock_.ApproximateNow() + QuicTime::Delta::FromSeconds(10),
- connection_.GetPingAlarm()->deadline());
+ EXPECT_EQ(QuicTime::Delta::FromSeconds(10),
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
// Now recevie an ACK of the previous packet, which will move the
// ping alarm forward.
@@ -4847,9 +4714,9 @@ TEST_P(QuicConnectionTest, ReducedPingTimeout) {
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
// The ping timer is set slightly less than 10 seconds in the future, because
// of the 1s ping timer alarm granularity.
- EXPECT_EQ(clock_.ApproximateNow() + QuicTime::Delta::FromSeconds(10) -
- QuicTime::Delta::FromMilliseconds(5),
- connection_.GetPingAlarm()->deadline());
+ EXPECT_EQ(
+ QuicTime::Delta::FromSeconds(10) - QuicTime::Delta::FromMilliseconds(5),
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
writer_->Reset();
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(10));
@@ -4873,10 +4740,7 @@ TEST_P(QuicConnectionTest, ReducedPingTimeout) {
// Tests whether sending an MTU discovery packet to peer successfully causes the
// maximum packet size to increase.
TEST_P(QuicConnectionTest, SendMtuDiscoveryPacket) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
- EXPECT_TRUE(connection_.connected());
+ MtuDiscoveryTestInit();
// Send an MTU probe.
const size_t new_mtu = kDefaultMaxPacketSize + 100;
@@ -4887,17 +4751,6 @@ TEST_P(QuicConnectionTest, SendMtuDiscoveryPacket) {
EXPECT_EQ(new_mtu, mtu_probe_size);
EXPECT_EQ(QuicPacketNumber(1u), creator_->packet_number());
- // QuicFramer::GetMaxPlaintextSize uses the smallest max plaintext size across
- // all encrypters. The initial encrypter used with IETF QUIC has a 16-byte
- // overhead, while the NullEncrypter used throughout this test has a 12-byte
- // overhead. This test tests behavior that relies on computing the packet size
- // correctly, so by unsetting the initial encrypter, we avoid having a
- // mismatch between the overheads for the encrypters used. In non-test
- // scenarios all encrypters used for a given connection have the same
- // overhead, either 12 bytes for ones using Google QUIC crypto, or 16 bytes
- // for ones using TLS.
- connection_.SetEncrypter(ENCRYPTION_INITIAL, nullptr);
-
// Send more than MTU worth of data. No acknowledgement was received so far,
// so the MTU should be at its old value.
const std::string data(kDefaultMaxPacketSize + 1, '.');
@@ -4912,7 +4765,6 @@ TEST_P(QuicConnectionTest, SendMtuDiscoveryPacket) {
// Acknowledge all packets so far.
QuicAckFrame probe_ack = InitAckFrame(3);
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
ProcessAckPacket(&probe_ack);
EXPECT_EQ(new_mtu, connection_.max_packet_length());
@@ -4926,7 +4778,7 @@ TEST_P(QuicConnectionTest, SendMtuDiscoveryPacket) {
// Tests whether MTU discovery does not happen when it is not explicitly enabled
// by the connection options.
TEST_P(QuicConnectionTest, MtuDiscoveryDisabled) {
- EXPECT_TRUE(connection_.connected());
+ MtuDiscoveryTestInit();
const QuicPacketCount packets_between_probes_base = 10;
set_packets_between_probes_base(packets_between_probes_base);
@@ -4942,18 +4794,7 @@ TEST_P(QuicConnectionTest, MtuDiscoveryDisabled) {
// Tests whether MTU discovery works when all probes are acknowledged on the
// first try.
TEST_P(QuicConnectionTest, MtuDiscoveryEnabled) {
- EXPECT_TRUE(connection_.connected());
-
- // QuicFramer::GetMaxPlaintextSize uses the smallest max plaintext size across
- // all encrypters. The initial encrypter used with IETF QUIC has a 16-byte
- // overhead, while the NullEncrypter used throughout this test has a 12-byte
- // overhead. This test tests behavior that relies on computing the packet size
- // correctly, so by unsetting the initial encrypter, we avoid having a
- // mismatch between the overheads for the encrypters used. In non-test
- // scenarios all encrypters used for a given connection have the same
- // overhead, either 12 bytes for ones using Google QUIC crypto, or 16 bytes
- // for ones using TLS.
- connection_.SetEncrypter(ENCRYPTION_INITIAL, nullptr);
+ MtuDiscoveryTestInit();
const QuicPacketCount packets_between_probes_base = 5;
set_packets_between_probes_base(packets_between_probes_base);
@@ -4974,12 +4815,9 @@ TEST_P(QuicConnectionTest, MtuDiscoveryEnabled) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
.WillOnce(SaveArg<3>(&probe_size));
connection_.GetMtuDiscoveryAlarm()->Fire();
- if (GetQuicReloadableFlag(quic_mtu_discovery_v2)) {
- EXPECT_THAT(probe_size, InRange(connection_.max_packet_length(),
- kMtuDiscoveryTargetPacketSizeHigh));
- } else {
- EXPECT_EQ(kMtuDiscoveryTargetPacketSizeHigh, probe_size);
- }
+
+ EXPECT_THAT(probe_size, InRange(connection_.max_packet_length(),
+ kMtuDiscoveryTargetPacketSizeHigh));
const QuicPacketNumber probe_packet_number =
FirstSendingPacketNumber() + packets_between_probes_base;
@@ -4987,7 +4825,6 @@ TEST_P(QuicConnectionTest, MtuDiscoveryEnabled) {
// Acknowledge all packets sent so far.
QuicAckFrame probe_ack = InitAckFrame(probe_packet_number);
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _))
.Times(AnyNumber());
ProcessAckPacket(&probe_ack);
@@ -4996,17 +4833,6 @@ TEST_P(QuicConnectionTest, MtuDiscoveryEnabled) {
EXPECT_EQ(1u, connection_.mtu_probe_count());
- if (!GetQuicReloadableFlag(quic_mtu_discovery_v2)) {
- // Send more packets, and ensure that none of them sets the alarm.
- for (QuicPacketCount i = 0; i < 4 * packets_between_probes_base; i++) {
- SendStreamDataToPeer(3, ".", packets_between_probes_base + i, NO_FIN,
- nullptr);
- ASSERT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet());
- }
-
- return;
- }
-
QuicStreamOffset stream_offset = packets_between_probes_base;
for (size_t num_probes = 1; num_probes < kMtuDiscoveryAttempts;
++num_probes) {
@@ -5044,9 +4870,7 @@ TEST_P(QuicConnectionTest, MtuDiscoveryEnabled) {
// Simulate the case where the first attempt to send a probe is write blocked,
// and after unblock, the second attempt returns a MSG_TOO_BIG error.
TEST_P(QuicConnectionTest, MtuDiscoveryWriteBlocked) {
- EXPECT_TRUE(connection_.connected());
-
- connection_.SetEncrypter(ENCRYPTION_INITIAL, nullptr);
+ MtuDiscoveryTestInit();
const QuicPacketCount packets_between_probes_base = 5;
set_packets_between_probes_base(packets_between_probes_base);
@@ -5065,9 +4889,7 @@ TEST_P(QuicConnectionTest, MtuDiscoveryWriteBlocked) {
SendStreamDataToPeer(3, "!", packets_between_probes_base - 1, NO_FIN,
nullptr);
ASSERT_TRUE(connection_.GetMtuDiscoveryAlarm()->IsSet());
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
BlockOnNextWrite();
EXPECT_EQ(0u, connection_.NumQueuedPackets());
connection_.GetMtuDiscoveryAlarm()->Fire();
@@ -5086,7 +4908,7 @@ TEST_P(QuicConnectionTest, MtuDiscoveryWriteBlocked) {
// Tests whether MTU discovery works correctly when the probes never get
// acknowledged.
TEST_P(QuicConnectionTest, MtuDiscoveryFailed) {
- EXPECT_TRUE(connection_.connected());
+ MtuDiscoveryTestInit();
// Lower the number of probes between packets in order to make the test go
// much faster.
@@ -5106,8 +4928,6 @@ TEST_P(QuicConnectionTest, MtuDiscoveryFailed) {
const QuicPacketCount number_of_packets =
packets_between_probes_base * (1 << (kMtuDiscoveryAttempts + 1));
std::vector<QuicPacketNumber> mtu_discovery_packets;
- // Called by the first ack.
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Called on many acks.
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _))
.Times(AnyNumber());
@@ -5168,21 +4988,7 @@ TEST_P(QuicConnectionTest, MtuDiscoveryFailed) {
// Probe 3 times, the first one succeeds, then fails, then succeeds again.
TEST_P(QuicConnectionTest, MtuDiscoverySecondProbeFailed) {
- if (!GetQuicReloadableFlag(quic_mtu_discovery_v2)) {
- return;
- }
- EXPECT_TRUE(connection_.connected());
-
- // QuicFramer::GetMaxPlaintextSize uses the smallest max plaintext size across
- // all encrypters. The initial encrypter used with IETF QUIC has a 16-byte
- // overhead, while the NullEncrypter used throughout this test has a 12-byte
- // overhead. This test tests behavior that relies on computing the packet size
- // correctly, so by unsetting the initial encrypter, we avoid having a
- // mismatch between the overheads for the encrypters used. In non-test
- // scenarios all encrypters used for a given connection have the same
- // overhead, either 12 bytes for ones using Google QUIC crypto, or 16 bytes
- // for ones using TLS.
- connection_.SetEncrypter(ENCRYPTION_INITIAL, nullptr);
+ MtuDiscoveryTestInit();
const QuicPacketCount packets_between_probes_base = 5;
set_packets_between_probes_base(packets_between_probes_base);
@@ -5213,7 +5019,6 @@ TEST_P(QuicConnectionTest, MtuDiscoverySecondProbeFailed) {
// Acknowledge all packets sent so far.
QuicAckFrame first_ack = InitAckFrame(probe_packet_number);
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _))
.Times(AnyNumber());
ProcessAckPacket(&first_ack);
@@ -5271,18 +5076,7 @@ TEST_P(QuicConnectionTest, MtuDiscoverySecondProbeFailed) {
// Tests whether MTU discovery works when the writer has a limit on how large a
// packet can be.
TEST_P(QuicConnectionTest, MtuDiscoveryWriterLimited) {
- EXPECT_TRUE(connection_.connected());
-
- // QuicFramer::GetMaxPlaintextSize uses the smallest max plaintext size across
- // all encrypters. The initial encrypter used with IETF QUIC has a 16-byte
- // overhead, while the NullEncrypter used throughout this test has a 12-byte
- // overhead. This test tests behavior that relies on computing the packet size
- // correctly, so by unsetting the initial encrypter, we avoid having a
- // mismatch between the overheads for the encrypters used. In non-test
- // scenarios all encrypters used for a given connection have the same
- // overhead, either 12 bytes for ones using Google QUIC crypto, or 16 bytes
- // for ones using TLS.
- connection_.SetEncrypter(ENCRYPTION_INITIAL, nullptr);
+ MtuDiscoveryTestInit();
const QuicByteCount mtu_limit = kMtuDiscoveryTargetPacketSizeHigh - 1;
writer_->set_max_packet_size(mtu_limit);
@@ -5306,12 +5100,8 @@ TEST_P(QuicConnectionTest, MtuDiscoveryWriterLimited) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
.WillOnce(SaveArg<3>(&probe_size));
connection_.GetMtuDiscoveryAlarm()->Fire();
- if (GetQuicReloadableFlag(quic_mtu_discovery_v2)) {
- EXPECT_THAT(probe_size,
- InRange(connection_.max_packet_length(), mtu_limit));
- } else {
- EXPECT_EQ(mtu_limit, probe_size);
- }
+
+ EXPECT_THAT(probe_size, InRange(connection_.max_packet_length(), mtu_limit));
const QuicPacketNumber probe_sequence_number =
FirstSendingPacketNumber() + packets_between_probes_base;
@@ -5319,7 +5109,6 @@ TEST_P(QuicConnectionTest, MtuDiscoveryWriterLimited) {
// Acknowledge all packets sent so far.
QuicAckFrame probe_ack = InitAckFrame(probe_sequence_number);
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _))
.Times(AnyNumber());
ProcessAckPacket(&probe_ack);
@@ -5328,17 +5117,6 @@ TEST_P(QuicConnectionTest, MtuDiscoveryWriterLimited) {
EXPECT_EQ(1u, connection_.mtu_probe_count());
- if (!GetQuicReloadableFlag(quic_mtu_discovery_v2)) {
- // Send more packets, and ensure that none of them sets the alarm.
- for (QuicPacketCount i = 0; i < 4 * packets_between_probes_base; i++) {
- SendStreamDataToPeer(3, ".", packets_between_probes_base + i, NO_FIN,
- nullptr);
- ASSERT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet());
- }
-
- return;
- }
-
QuicStreamOffset stream_offset = packets_between_probes_base;
for (size_t num_probes = 1; num_probes < kMtuDiscoveryAttempts;
++num_probes) {
@@ -5375,7 +5153,7 @@ TEST_P(QuicConnectionTest, MtuDiscoveryWriterLimited) {
// Tests whether MTU discovery works when the writer returns an error despite
// advertising higher packet length.
TEST_P(QuicConnectionTest, MtuDiscoveryWriterFailed) {
- EXPECT_TRUE(connection_.connected());
+ MtuDiscoveryTestInit();
const QuicByteCount mtu_limit = kMtuDiscoveryTargetPacketSizeHigh - 1;
const QuicByteCount initial_mtu = connection_.max_packet_length();
@@ -5412,7 +5190,6 @@ TEST_P(QuicConnectionTest, MtuDiscoveryWriterFailed) {
// Acknowledge all packets sent so far, except for the lost probe.
QuicAckFrame probe_ack =
ConstructAckFrame(creator_->packet_number(), probe_number);
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
ProcessAckPacket(&probe_ack);
EXPECT_EQ(initial_mtu, connection_.max_packet_length());
@@ -5428,7 +5205,7 @@ TEST_P(QuicConnectionTest, MtuDiscoveryWriterFailed) {
}
TEST_P(QuicConnectionTest, NoMtuDiscoveryAfterConnectionClosed) {
- EXPECT_TRUE(connection_.connected());
+ MtuDiscoveryTestInit();
const QuicPacketCount packets_between_probes_base = 10;
set_packets_between_probes_base(packets_between_probes_base);
@@ -5492,7 +5269,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterSend) {
// This time, we should time out.
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
clock_.AdvanceTime(five_ms);
EXPECT_EQ(default_timeout + five_ms, clock_.ApproximateNow());
connection_.GetTimeoutAlarm()->Fire();
@@ -5570,7 +5347,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterRetransmission) {
// This time, we should time out.
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
clock_.AdvanceTime(final_timeout - clock_.Now());
EXPECT_EQ(connection_.GetTimeoutAlarm()->deadline(), clock_.Now());
EXPECT_EQ(final_timeout, clock_.Now());
@@ -5601,7 +5378,7 @@ TEST_P(QuicConnectionTest, NewTimeoutAfterSendSilentClose) {
client_config.ToHandshakeMessage(&msg, connection_.transport_version());
const QuicErrorCode error =
config.ProcessPeerHello(msg, CLIENT, &error_details);
- EXPECT_EQ(QUIC_NO_ERROR, error);
+ EXPECT_THAT(error, IsQuicNoError());
connection_.SetFromConfig(config);
EXPECT_TRUE(QuicConnectionPeer::IsSilentCloseEnabled(&connection_));
@@ -5650,8 +5427,8 @@ TEST_P(QuicConnectionTest, NewTimeoutAfterSendSilentClose) {
EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_FALSE(connection_.connected());
EXPECT_EQ(1, connection_close_frame_count_);
- EXPECT_EQ(QUIC_NETWORK_IDLE_TIMEOUT,
- saved_connection_close_frame_.quic_error_code);
+ EXPECT_THAT(saved_connection_close_frame_.quic_error_code,
+ IsError(QUIC_NETWORK_IDLE_TIMEOUT));
}
TEST_P(QuicConnectionTest, TimeoutAfterSendSilentCloseAndTLP) {
@@ -5678,7 +5455,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterSendSilentCloseAndTLP) {
client_config.ToHandshakeMessage(&msg, connection_.transport_version());
const QuicErrorCode error =
config.ProcessPeerHello(msg, CLIENT, &error_details);
- EXPECT_EQ(QUIC_NO_ERROR, error);
+ EXPECT_THAT(error, IsQuicNoError());
connection_.SetFromConfig(config);
EXPECT_TRUE(QuicConnectionPeer::IsSilentCloseEnabled(&connection_));
@@ -5705,7 +5482,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterSendSilentCloseAndTLP) {
// This time, we should time out and send a connection close due to the TLP.
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
clock_.AdvanceTime(connection_.GetTimeoutAlarm()->deadline() -
clock_.ApproximateNow() + five_ms);
connection_.GetTimeoutAlarm()->Fire();
@@ -5735,7 +5512,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterSendSilentCloseWithOpenStreams) {
client_config.ToHandshakeMessage(&msg, connection_.transport_version());
const QuicErrorCode error =
config.ProcessPeerHello(msg, CLIENT, &error_details);
- EXPECT_EQ(QUIC_NO_ERROR, error);
+ EXPECT_THAT(error, IsQuicNoError());
connection_.SetFromConfig(config);
EXPECT_TRUE(QuicConnectionPeer::IsSilentCloseEnabled(&connection_));
@@ -5760,7 +5537,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterSendSilentCloseWithOpenStreams) {
// This time, we should time out and send a connection close due to the TLP.
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
clock_.AdvanceTime(connection_.GetTimeoutAlarm()->deadline() -
clock_.ApproximateNow() + five_ms);
connection_.GetTimeoutAlarm()->Fire();
@@ -5811,7 +5588,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceive) {
// This time, we should time out.
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
clock_.AdvanceTime(five_ms);
EXPECT_EQ(default_timeout + five_ms, clock_.ApproximateNow());
connection_.GetTimeoutAlarm()->Fire();
@@ -5914,7 +5691,7 @@ TEST_P(QuicConnectionTest, TimeoutAfter5ClientRTOs) {
// This time, we should time out.
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
connection_.GetRetransmissionAlarm()->Fire();
EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_FALSE(connection_.connected());
@@ -6567,7 +6344,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReordering) {
}
// Check that ack is sent and that delayed ack alarm is reset.
if (GetParam().no_stop_waiting) {
- EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_EQ(writer_->padding_frames().size() + 1u, writer_->frame_count());
EXPECT_TRUE(writer_->stop_waiting_frames().empty());
} else {
EXPECT_EQ(2u, writer_->frame_count());
@@ -6584,7 +6361,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReordering) {
ENCRYPTION_ZERO_RTT);
// Check that ack is sent and that delayed ack alarm is reset.
if (GetParam().no_stop_waiting) {
- EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_EQ(writer_->padding_frames().size() + 1u, writer_->frame_count());
EXPECT_TRUE(writer_->stop_waiting_frames().empty());
} else {
EXPECT_EQ(2u, writer_->frame_count());
@@ -6720,7 +6497,7 @@ TEST_P(QuicConnectionTest,
}
// Check that ack is sent and that delayed ack alarm is reset.
if (GetParam().no_stop_waiting) {
- EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_EQ(writer_->padding_frames().size() + 1u, writer_->frame_count());
EXPECT_TRUE(writer_->stop_waiting_frames().empty());
} else {
EXPECT_EQ(2u, writer_->frame_count());
@@ -6737,7 +6514,7 @@ TEST_P(QuicConnectionTest,
ENCRYPTION_ZERO_RTT);
// Check that ack is sent and that delayed ack alarm is reset.
if (GetParam().no_stop_waiting) {
- EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_EQ(writer_->padding_frames().size() + 1u, writer_->frame_count());
EXPECT_TRUE(writer_->stop_waiting_frames().empty());
} else {
EXPECT_EQ(2u, writer_->frame_count());
@@ -6997,19 +6774,13 @@ TEST_P(QuicConnectionTest, BundleAckWithDataOnIncomingAck) {
// Check that ack is bundled with outgoing data and the delayed ack
// alarm is reset.
if (GetParam().no_stop_waiting) {
- if (GetQuicReloadableFlag(quic_simplify_stop_waiting)) {
- // Do not ACK acks.
- EXPECT_EQ(1u, writer_->frame_count());
- } else {
- EXPECT_EQ(2u, writer_->frame_count());
- EXPECT_TRUE(writer_->stop_waiting_frames().empty());
- }
+ // Do not ACK acks.
+ EXPECT_EQ(1u, writer_->frame_count());
} else {
EXPECT_EQ(3u, writer_->frame_count());
EXPECT_FALSE(writer_->stop_waiting_frames().empty());
}
- if (GetParam().no_stop_waiting &&
- GetQuicReloadableFlag(quic_simplify_stop_waiting)) {
+ if (GetParam().no_stop_waiting) {
EXPECT_TRUE(writer_->ack_frames().empty());
} else {
EXPECT_FALSE(writer_->ack_frames().empty());
@@ -7028,8 +6799,8 @@ TEST_P(QuicConnectionTest, NoAckSentForClose) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
ProcessClosePacket(2);
EXPECT_EQ(1, connection_close_frame_count_);
- EXPECT_EQ(QUIC_PEER_GOING_AWAY,
- saved_connection_close_frame_.quic_error_code);
+ EXPECT_THAT(saved_connection_close_frame_.quic_error_code,
+ IsError(QUIC_PEER_GOING_AWAY));
}
TEST_P(QuicConnectionTest, SendWhenDisconnected) {
@@ -7047,8 +6818,8 @@ TEST_P(QuicConnectionTest, SendWhenDisconnected) {
connection_.SendPacket(ENCRYPTION_INITIAL, 1, std::move(packet),
HAS_RETRANSMITTABLE_DATA, false, false);
EXPECT_EQ(1, connection_close_frame_count_);
- EXPECT_EQ(QUIC_PEER_GOING_AWAY,
- saved_connection_close_frame_.quic_error_code);
+ EXPECT_THAT(saved_connection_close_frame_.quic_error_code,
+ IsError(QUIC_PEER_GOING_AWAY));
}
TEST_P(QuicConnectionTest, SendConnectivityProbingWhenDisconnected) {
@@ -7073,8 +6844,8 @@ TEST_P(QuicConnectionTest, SendConnectivityProbingWhenDisconnected) {
"Not sending connectivity probing packet as connection is "
"disconnected.");
EXPECT_EQ(1, connection_close_frame_count_);
- EXPECT_EQ(QUIC_PEER_GOING_AWAY,
- saved_connection_close_frame_.quic_error_code);
+ EXPECT_THAT(saved_connection_close_frame_.quic_error_code,
+ IsError(QUIC_PEER_GOING_AWAY));
}
TEST_P(QuicConnectionTest, WriteBlockedAfterClientSendsConnectivityProbe) {
@@ -7155,7 +6926,8 @@ TEST_P(QuicConnectionTest, PublicReset) {
.WillOnce(Invoke(this, &QuicConnectionTest::SaveConnectionCloseFrame));
connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received);
EXPECT_EQ(1, connection_close_frame_count_);
- EXPECT_EQ(QUIC_PUBLIC_RESET, saved_connection_close_frame_.quic_error_code);
+ EXPECT_THAT(saved_connection_close_frame_.quic_error_code,
+ IsError(QUIC_PUBLIC_RESET));
}
TEST_P(QuicConnectionTest, IetfStatelessReset) {
@@ -7177,7 +6949,8 @@ TEST_P(QuicConnectionTest, IetfStatelessReset) {
.WillOnce(Invoke(this, &QuicConnectionTest::SaveConnectionCloseFrame));
connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received);
EXPECT_EQ(1, connection_close_frame_count_);
- EXPECT_EQ(QUIC_PUBLIC_RESET, saved_connection_close_frame_.quic_error_code);
+ EXPECT_THAT(saved_connection_close_frame_.quic_error_code,
+ IsError(QUIC_PUBLIC_RESET));
}
TEST_P(QuicConnectionTest, GoAway) {
@@ -7201,7 +6974,7 @@ TEST_P(QuicConnectionTest, WindowUpdate) {
QuicWindowUpdateFrame window_update;
window_update.stream_id = 3;
- window_update.byte_offset = 1234;
+ window_update.max_data = 1234;
EXPECT_CALL(visitor_, OnWindowUpdateFrame(_));
ProcessFramePacket(QuicFrame(&window_update));
}
@@ -7259,8 +7032,8 @@ TEST_P(QuicConnectionTest, ClientHandlesVersionNegotiation) {
connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received);
EXPECT_FALSE(connection_.connected());
EXPECT_EQ(1, connection_close_frame_count_);
- EXPECT_EQ(QUIC_INVALID_VERSION,
- saved_connection_close_frame_.quic_error_code);
+ EXPECT_THAT(saved_connection_close_frame_.quic_error_code,
+ IsError(QUIC_INVALID_VERSION));
}
TEST_P(QuicConnectionTest, BadVersionNegotiation) {
@@ -7278,8 +7051,8 @@ TEST_P(QuicConnectionTest, BadVersionNegotiation) {
ConstructReceivedPacket(*encrypted, QuicTime::Zero()));
connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received);
EXPECT_EQ(1, connection_close_frame_count_);
- EXPECT_EQ(QUIC_INVALID_VERSION_NEGOTIATION_PACKET,
- saved_connection_close_frame_.quic_error_code);
+ EXPECT_THAT(saved_connection_close_frame_.quic_error_code,
+ IsError(QUIC_INVALID_VERSION_NEGOTIATION_PACKET));
}
TEST_P(QuicConnectionTest, CheckSendStats) {
@@ -7317,9 +7090,6 @@ TEST_P(QuicConnectionTest, CheckSendStats) {
EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _))
.WillOnce(SetArgPointee<5>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- if (!connection_.session_decides_what_to_write()) {
- EXPECT_CALL(visitor_, OnCanWrite());
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessAckPacket(&nack_three);
@@ -7387,8 +7157,8 @@ TEST_P(QuicConnectionTest, ProcessFramesIfPacketClosedConnection) {
kSelfAddress, kPeerAddress,
QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
EXPECT_EQ(1, connection_close_frame_count_);
- EXPECT_EQ(QUIC_PEER_GOING_AWAY,
- saved_connection_close_frame_.extracted_error_code);
+ EXPECT_THAT(saved_connection_close_frame_.extracted_error_code,
+ IsError(QUIC_PEER_GOING_AWAY));
}
TEST_P(QuicConnectionTest, SelectMutualVersion) {
@@ -7426,7 +7196,7 @@ TEST_P(QuicConnectionTest, ConnectionCloseWhenWritable) {
EXPECT_EQ(1u, writer_->packets_write_attempts());
TriggerConnectionClose();
- EXPECT_EQ(2u, writer_->packets_write_attempts());
+ EXPECT_LE(2u, writer_->packets_write_attempts());
}
TEST_P(QuicConnectionTest, ConnectionCloseGettingWriteBlocked) {
@@ -7450,10 +7220,10 @@ TEST_P(QuicConnectionTest, OnPacketSentDebugVisitor) {
MockQuicConnectionDebugVisitor debug_visitor;
connection_.set_debug_visitor(&debug_visitor);
- EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _)).Times(1);
+ EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(1);
connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN);
- EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _)).Times(1);
+ EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(1);
connection_.SendConnectivityProbingPacket(writer_.get(),
connection_.peer_address());
}
@@ -7494,7 +7264,7 @@ TEST_P(QuicConnectionTest, WindowUpdateInstigateAcks) {
// Send a WINDOW_UPDATE frame.
QuicWindowUpdateFrame window_update;
window_update.stream_id = 3;
- window_update.byte_offset = 1234;
+ window_update.max_data = 1234;
EXPECT_CALL(visitor_, OnWindowUpdateFrame(_));
ProcessFramePacket(QuicFrame(&window_update));
@@ -7582,7 +7352,7 @@ TEST_P(QuicConnectionTest, SendPingImmediately) {
CongestionBlockWrites();
connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _)).Times(1);
+ EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(1);
EXPECT_CALL(debug_visitor, OnPingSent()).Times(1);
connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
EXPECT_FALSE(connection_.HasQueuedData());
@@ -7594,7 +7364,7 @@ TEST_P(QuicConnectionTest, SendBlockedImmediately) {
connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _)).Times(1);
+ EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(1);
EXPECT_EQ(0u, connection_.GetStats().blocked_frames_sent);
connection_.SendControlFrame(QuicFrame(new QuicBlockedFrame(1, 3)));
EXPECT_EQ(1u, connection_.GetStats().blocked_frames_sent);
@@ -7610,7 +7380,7 @@ TEST_P(QuicConnectionTest, FailedToSendBlockedFrames) {
QuicBlockedFrame blocked(1, 3);
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
- EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _)).Times(0);
+ EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(0);
EXPECT_EQ(0u, connection_.GetStats().blocked_frames_sent);
connection_.SendControlFrame(QuicFrame(&blocked));
EXPECT_EQ(0u, connection_.GetStats().blocked_frames_sent);
@@ -7631,8 +7401,8 @@ TEST_P(QuicConnectionTest, SendingUnencryptedStreamDataFails) {
"Cannot send stream data with level: ENCRYPTION_INITIAL");
EXPECT_FALSE(connection_.connected());
EXPECT_EQ(1, connection_close_frame_count_);
- EXPECT_EQ(QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA,
- saved_connection_close_frame_.quic_error_code);
+ EXPECT_THAT(saved_connection_close_frame_.quic_error_code,
+ IsError(QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA));
}
TEST_P(QuicConnectionTest, SetRetransmissionAlarmForCryptoPacket) {
@@ -7668,8 +7438,8 @@ TEST_P(QuicConnectionTest, PathDegradingAlarmForCryptoPacket) {
EXPECT_FALSE(connection_.IsPathDegrading());
QuicTime::Delta delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
- EXPECT_EQ(clock_.ApproximateNow() + delay,
- connection_.GetPathDegradingAlarm()->deadline());
+ EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
+ clock_.ApproximateNow());
// Fire the path degrading alarm, path degrading signal should be sent to
// the visitor.
@@ -7702,8 +7472,8 @@ TEST_P(QuicConnectionTest, PathDegradingAlarmForNonCryptoPackets) {
QuicTime::Delta delay =
QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
- EXPECT_EQ(clock_.ApproximateNow() + delay,
- connection_.GetPathDegradingAlarm()->deadline());
+ EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
+ clock_.ApproximateNow());
// Send a second packet. The path degrading alarm's deadline should remain
// the same.
@@ -7731,8 +7501,8 @@ TEST_P(QuicConnectionTest, PathDegradingAlarmForNonCryptoPackets) {
// Check the deadline of the path degrading alarm.
delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
- EXPECT_EQ(clock_.ApproximateNow() + delay,
- connection_.GetPathDegradingAlarm()->deadline());
+ EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
+ clock_.ApproximateNow());
if (i == 0) {
// Now receive an ACK of the second packet. Since there are no more
@@ -7758,7 +7528,7 @@ TEST_P(QuicConnectionTest, PathDegradingAlarmForNonCryptoPackets) {
TEST_P(QuicConnectionTest, RetransmittableOnWireSetsPingAlarm) {
const QuicTime::Delta retransmittable_on_wire_timeout =
QuicTime::Delta::FromMilliseconds(50);
- connection_.set_retransmittable_on_wire_timeout(
+ connection_.set_initial_retransmittable_on_wire_timeout(
retransmittable_on_wire_timeout);
EXPECT_TRUE(connection_.connected());
@@ -7782,15 +7552,15 @@ TEST_P(QuicConnectionTest, RetransmittableOnWireSetsPingAlarm) {
EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
QuicTime::Delta delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
- EXPECT_EQ(clock_.ApproximateNow() + delay,
- connection_.GetPathDegradingAlarm()->deadline());
+ EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
+ clock_.ApproximateNow());
ASSERT_TRUE(connection_.sent_packet_manager().HasInFlightPackets());
// The ping alarm is set for the ping timeout, not the shorter
// retransmittable_on_wire_timeout.
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
QuicTime::Delta ping_delay = QuicTime::Delta::FromSeconds(kPingTimeoutSecs);
- EXPECT_EQ((clock_.ApproximateNow() + ping_delay),
- connection_.GetPingAlarm()->deadline());
+ EXPECT_EQ(ping_delay,
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
// Now receive an ACK of the packet.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
@@ -7804,8 +7574,8 @@ TEST_P(QuicConnectionTest, RetransmittableOnWireSetsPingAlarm) {
// retransmittable_on_wire_timeout.
EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
- EXPECT_EQ(clock_.ApproximateNow() + retransmittable_on_wire_timeout,
- connection_.GetPingAlarm()->deadline());
+ EXPECT_EQ(retransmittable_on_wire_timeout,
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
// Simulate firing the ping alarm and sending a PING.
clock_.AdvanceTime(retransmittable_on_wire_timeout);
@@ -7819,8 +7589,8 @@ TEST_P(QuicConnectionTest, RetransmittableOnWireSetsPingAlarm) {
EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
- EXPECT_EQ(clock_.ApproximateNow() + delay,
- connection_.GetPathDegradingAlarm()->deadline());
+ EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
+ clock_.ApproximateNow());
}
// This test verifies that the connection marks path as degrading and does not
@@ -7843,8 +7613,8 @@ TEST_P(QuicConnectionTest, NoPathDegradingAlarmIfPathIsDegrading) {
// Check the deadline of the path degrading alarm.
QuicTime::Delta delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
- EXPECT_EQ(clock_.ApproximateNow() + delay,
- connection_.GetPathDegradingAlarm()->deadline());
+ EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
+ clock_.ApproximateNow());
// Send a second packet. The path degrading alarm's deadline should remain
// the same.
@@ -7867,8 +7637,8 @@ TEST_P(QuicConnectionTest, NoPathDegradingAlarmIfPathIsDegrading) {
// Check the deadline of the path degrading alarm.
delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
- EXPECT_EQ(clock_.ApproximateNow() + delay,
- connection_.GetPathDegradingAlarm()->deadline());
+ EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
+ clock_.ApproximateNow());
// Advance time to the path degrading alarm's deadline and simulate
// firing the path degrading alarm. This path will be considered as
@@ -7909,8 +7679,8 @@ TEST_P(QuicConnectionTest, UnmarkPathDegradingOnForwardProgress) {
// Check the deadline of the path degrading alarm.
QuicTime::Delta delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
- EXPECT_EQ(clock_.ApproximateNow() + delay,
- connection_.GetPathDegradingAlarm()->deadline());
+ EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
+ clock_.ApproximateNow());
// Send a second packet. The path degrading alarm's deadline should remain
// the same.
@@ -7933,8 +7703,8 @@ TEST_P(QuicConnectionTest, UnmarkPathDegradingOnForwardProgress) {
// Check the deadline of the path degrading alarm.
delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
->GetPathDegradingDelay();
- EXPECT_EQ(clock_.ApproximateNow() + delay,
- connection_.GetPathDegradingAlarm()->deadline());
+ EXPECT_EQ(delay, connection_.GetPathDegradingAlarm()->deadline() -
+ clock_.ApproximateNow());
// Advance time to the path degrading alarm's deadline and simulate
// firing the alarm.
@@ -7981,7 +7751,6 @@ TEST_P(QuicConnectionTest, NoPathDegradingOnServer) {
// Ack data.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
QuicAckFrame frame =
InitAckFrame({{QuicPacketNumber(1u), QuicPacketNumber(2u)}});
@@ -8016,8 +7785,6 @@ TEST_P(QuicConnectionTest, MultipleCallsToCloseConnection) {
}
TEST_P(QuicConnectionTest, ServerReceivesChloOnNonCryptoStream) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
@@ -8133,11 +7900,7 @@ TEST_P(QuicConnectionTest, NotBecomeApplicationLimitedDueToWriteBlock) {
EXPECT_CALL(visitor_, WillingAndAbleToWrite()).WillRepeatedly(Return(true));
BlockOnNextWrite();
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- } else {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
connection_.SendStreamData3();
// Now unblock the writer, become congestion control blocked,
@@ -8145,11 +7908,7 @@ TEST_P(QuicConnectionTest, NotBecomeApplicationLimitedDueToWriteBlock) {
writer_->SetWritable();
CongestionBlockWrites();
EXPECT_CALL(visitor_, WillingAndAbleToWrite()).WillRepeatedly(Return(false));
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
- } else {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(1);
connection_.OnCanWrite();
}
@@ -8203,7 +7962,7 @@ TEST_P(QuicConnectionTest, SendDataWhenApplicationLimited) {
ProcessAckPacket(&ack);
}
-TEST_P(QuicConnectionTest, DonotForceSendingAckOnPacketTooLarge) {
+TEST_P(QuicConnectionTest, DoNotForceSendingAckOnPacketTooLarge) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Send an ack by simulating delayed ack alarm firing.
ProcessPacket(1);
@@ -8214,13 +7973,74 @@ TEST_P(QuicConnectionTest, DonotForceSendingAckOnPacketTooLarge) {
EXPECT_CALL(visitor_, OnConnectionClosed(_, _));
SimulateNextPacketTooLarge();
connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN);
- EXPECT_EQ(1u, writer_->frame_count());
- EXPECT_FALSE(writer_->connection_close_frames().empty());
+ EXPECT_EQ(1u, writer_->connection_close_frames().size());
// Ack frame is not bundled in connection close packet.
EXPECT_TRUE(writer_->ack_frames().empty());
+ if (writer_->padding_frames().empty()) {
+ EXPECT_EQ(1u, writer_->frame_count());
+ } else {
+ EXPECT_EQ(2u, writer_->frame_count());
+ }
+
TestConnectionCloseQuicErrorCode(QUIC_PACKET_WRITE_ERROR);
}
+TEST_P(QuicConnectionTest, CloseConnectionAllLevels) {
+ SetQuicReloadableFlag(quic_close_all_encryptions_levels2, true);
+
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _));
+ const QuicErrorCode kQuicErrorCode = QUIC_INTERNAL_ERROR;
+ connection_.CloseConnection(
+ kQuicErrorCode, "Some random error message",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+
+ EXPECT_EQ(2u, QuicConnectionPeer::GetNumEncryptionLevels(&connection_));
+
+ TestConnectionCloseQuicErrorCode(kQuicErrorCode);
+ EXPECT_EQ(1u, writer_->connection_close_frames().size());
+
+ if (!connection_.version().CanSendCoalescedPackets()) {
+ // Each connection close packet should be sent in distinct UDP packets.
+ EXPECT_EQ(QuicConnectionPeer::GetNumEncryptionLevels(&connection_),
+ writer_->connection_close_packets());
+ EXPECT_EQ(QuicConnectionPeer::GetNumEncryptionLevels(&connection_),
+ writer_->packets_write_attempts());
+ return;
+ }
+
+ // A single UDP packet should be sent with multiple connection close packets
+ // coalesced together.
+ EXPECT_EQ(1u, writer_->packets_write_attempts());
+
+ // Only the first packet has been processed yet.
+ EXPECT_EQ(1u, writer_->connection_close_packets());
+
+ // ProcessPacket resets the visitor and frees the coalesced packet.
+ ASSERT_TRUE(writer_->coalesced_packet() != nullptr);
+ auto packet = writer_->coalesced_packet()->Clone();
+ writer_->framer()->ProcessPacket(*packet);
+ EXPECT_EQ(1u, writer_->connection_close_packets());
+ ASSERT_TRUE(writer_->coalesced_packet() == nullptr);
+}
+
+TEST_P(QuicConnectionTest, CloseConnectionOneLevel) {
+ SetQuicReloadableFlag(quic_close_all_encryptions_levels2, false);
+
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _));
+ const QuicErrorCode kQuicErrorCode = QUIC_INTERNAL_ERROR;
+ connection_.CloseConnection(
+ kQuicErrorCode, "Some random error message",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+
+ EXPECT_EQ(2u, QuicConnectionPeer::GetNumEncryptionLevels(&connection_));
+
+ TestConnectionCloseQuicErrorCode(kQuicErrorCode);
+ EXPECT_EQ(1u, writer_->connection_close_frames().size());
+ EXPECT_EQ(1u, writer_->connection_close_packets());
+ EXPECT_EQ(1u, writer_->packets_write_attempts());
+ ASSERT_TRUE(writer_->coalesced_packet() == nullptr);
+}
+
// Regression test for b/63620844.
TEST_P(QuicConnectionTest, FailedToWriteHandshakePacket) {
SimulateNextPacketTooLarge();
@@ -8279,13 +8099,19 @@ TEST_P(QuicConnectionTest, SendProbingRetransmissions) {
}
// Expect them retransmitted in cyclic order (foo, bar, test, foo, bar...).
QuicPacketCount sent_count = 0;
- EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _))
+ EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _))
.WillRepeatedly(Invoke([this, &sent_count](const SerializedPacket&,
- QuicPacketNumber,
TransmissionType, QuicTime) {
ASSERT_EQ(1u, writer_->stream_frames().size());
- // Identify the frames by stream offset (0, 3, 6, 0, 3...).
- EXPECT_EQ(3 * (sent_count % 3), writer_->stream_frames()[0]->offset);
+ if (connection_.version().CanSendCoalescedPackets()) {
+ // There is a delay of sending coalesced packet, so (6, 0, 3, 6,
+ // 0...).
+ EXPECT_EQ(3 * ((sent_count + 2) % 3),
+ writer_->stream_frames()[0]->offset);
+ } else {
+ // Identify the frames by stream offset (0, 3, 6, 0, 3...).
+ EXPECT_EQ(3 * (sent_count % 3), writer_->stream_frames()[0]->offset);
+ }
sent_count++;
}));
EXPECT_CALL(*send_algorithm_, ShouldSendProbingPacket())
@@ -8311,7 +8137,7 @@ TEST_P(QuicConnectionTest,
MockQuicConnectionDebugVisitor debug_visitor;
connection_.set_debug_visitor(&debug_visitor);
- EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _)).Times(0);
+ EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _)).Times(0);
EXPECT_CALL(*send_algorithm_, ShouldSendProbingPacket())
.WillRepeatedly(Return(true));
EXPECT_CALL(visitor_, SendProbingData()).WillRepeatedly([this] {
@@ -8325,7 +8151,7 @@ TEST_P(QuicConnectionTest,
TEST_P(QuicConnectionTest, PingAfterLastRetransmittablePacketAcked) {
const QuicTime::Delta retransmittable_on_wire_timeout =
QuicTime::Delta::FromMilliseconds(50);
- connection_.set_retransmittable_on_wire_timeout(
+ connection_.set_initial_retransmittable_on_wire_timeout(
retransmittable_on_wire_timeout);
EXPECT_TRUE(connection_.connected());
@@ -8346,8 +8172,8 @@ TEST_P(QuicConnectionTest, PingAfterLastRetransmittablePacketAcked) {
// retransmittable_on_wire_timeout.
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
QuicTime::Delta ping_delay = QuicTime::Delta::FromSeconds(kPingTimeoutSecs);
- EXPECT_EQ((clock_.ApproximateNow() + ping_delay),
- connection_.GetPingAlarm()->deadline());
+ EXPECT_EQ(ping_delay,
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
// Advance 5ms, send a second retransmittable packet to the peer.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
@@ -8370,9 +8196,8 @@ TEST_P(QuicConnectionTest, PingAfterLastRetransmittablePacketAcked) {
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
// The ping alarm has a 1 second granularity, and the clock has been advanced
// 10ms since it was originally set.
- EXPECT_EQ((clock_.ApproximateNow() + ping_delay -
- QuicTime::Delta::FromMilliseconds(10)),
- connection_.GetPingAlarm()->deadline());
+ EXPECT_EQ(ping_delay - QuicTime::Delta::FromMilliseconds(10),
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
// Now receive an ACK of the second packet. This should set the
// retransmittable-on-wire alarm now that no retransmittable packets are on
@@ -8382,8 +8207,8 @@ TEST_P(QuicConnectionTest, PingAfterLastRetransmittablePacketAcked) {
frame = InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}});
ProcessAckPacket(&frame);
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
- EXPECT_EQ(clock_.ApproximateNow() + retransmittable_on_wire_timeout,
- connection_.GetPingAlarm()->deadline());
+ EXPECT_EQ(retransmittable_on_wire_timeout,
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
// Now receive a duplicate ACK of the second packet. This should not update
// the ping alarm.
@@ -8418,7 +8243,7 @@ TEST_P(QuicConnectionTest, PingAfterLastRetransmittablePacketAcked) {
TEST_P(QuicConnectionTest, NoPingIfRetransmittablePacketSent) {
const QuicTime::Delta retransmittable_on_wire_timeout =
QuicTime::Delta::FromMilliseconds(50);
- connection_.set_retransmittable_on_wire_timeout(
+ connection_.set_initial_retransmittable_on_wire_timeout(
retransmittable_on_wire_timeout);
EXPECT_TRUE(connection_.connected());
@@ -8439,8 +8264,8 @@ TEST_P(QuicConnectionTest, NoPingIfRetransmittablePacketSent) {
// retransmittable_on_wire_timeout.
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
QuicTime::Delta ping_delay = QuicTime::Delta::FromSeconds(kPingTimeoutSecs);
- EXPECT_EQ((clock_.ApproximateNow() + ping_delay),
- connection_.GetPingAlarm()->deadline());
+ EXPECT_EQ(ping_delay,
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
// Now receive an ACK of the first packet. This should set the
// retransmittable-on-wire alarm now that no retransmittable packets are on
@@ -8452,8 +8277,8 @@ TEST_P(QuicConnectionTest, NoPingIfRetransmittablePacketSent) {
InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}});
ProcessAckPacket(&frame);
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
- EXPECT_EQ(clock_.ApproximateNow() + retransmittable_on_wire_timeout,
- connection_.GetPingAlarm()->deadline());
+ EXPECT_EQ(retransmittable_on_wire_timeout,
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
// Before the alarm fires, send another retransmittable packet. This should
// cancel the retransmittable-on-wire alarm since now there's a
@@ -8470,8 +8295,8 @@ TEST_P(QuicConnectionTest, NoPingIfRetransmittablePacketSent) {
frame = InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}});
ProcessAckPacket(&frame);
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
- EXPECT_EQ(clock_.ApproximateNow() + retransmittable_on_wire_timeout,
- connection_.GetPingAlarm()->deadline());
+ EXPECT_EQ(retransmittable_on_wire_timeout,
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
// Simulate the alarm firing and check that a PING is sent.
writer_->Reset();
@@ -8481,18 +8306,233 @@ TEST_P(QuicConnectionTest, NoPingIfRetransmittablePacketSent) {
connection_.GetPingAlarm()->Fire();
size_t padding_frame_count = writer_->padding_frames().size();
if (GetParam().no_stop_waiting) {
- if (GetQuicReloadableFlag(quic_simplify_stop_waiting)) {
- // Do not ACK acks.
- EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
- } else {
- EXPECT_EQ(padding_frame_count + 2u, writer_->frame_count());
- }
+ // Do not ACK acks.
+ EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
} else {
EXPECT_EQ(padding_frame_count + 3u, writer_->frame_count());
}
ASSERT_EQ(1u, writer_->ping_frames().size());
}
+// When there is no stream data received but are open streams, send the
+// first few consecutive pings with aggressive retransmittable-on-wire
+// timeout. Exponentially back off the retransmittable-on-wire ping timeout
+// afterwards until it exceeds the default ping timeout.
+TEST_P(QuicConnectionTest, BackOffRetransmittableOnWireTimeout) {
+ int max_aggressive_retransmittable_on_wire_ping_count = 5;
+ SetQuicFlag(FLAGS_quic_max_aggressive_retransmittable_on_wire_ping_count,
+ max_aggressive_retransmittable_on_wire_ping_count);
+ const QuicTime::Delta initial_retransmittable_on_wire_timeout =
+ QuicTime::Delta::FromMilliseconds(200);
+ connection_.set_initial_retransmittable_on_wire_timeout(
+ initial_retransmittable_on_wire_timeout);
+
+ EXPECT_TRUE(connection_.connected());
+ EXPECT_CALL(visitor_, ShouldKeepConnectionAlive())
+ .WillRepeatedly(Return(true));
+
+ const char data[] = "data";
+ // Advance 5ms, send a retransmittable data packet to the peer.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ EXPECT_FALSE(connection_.GetPingAlarm()->IsSet());
+ connection_.SendStreamDataWithString(1, data, 0, NO_FIN);
+ EXPECT_TRUE(connection_.sent_packet_manager().HasInFlightPackets());
+ // The ping alarm is set for the ping timeout, not the shorter
+ // retransmittable_on_wire_timeout.
+ EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
+ EXPECT_EQ(connection_.ping_timeout(),
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)).Times(AnyNumber());
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _))
+ .Times(AnyNumber());
+
+ // Verify that the first few consecutive retransmittable on wire pings are
+ // sent with aggressive timeout.
+ for (int i = 0; i <= max_aggressive_retransmittable_on_wire_ping_count; i++) {
+ // Receive an ACK of the previous packet. This should set the ping alarm
+ // with the initial retransmittable-on-wire timeout.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ QuicPacketNumber ack_num = creator_->packet_number();
+ QuicAckFrame frame = InitAckFrame(
+ {{QuicPacketNumber(ack_num), QuicPacketNumber(ack_num + 1)}});
+ ProcessAckPacket(&frame);
+ EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
+ EXPECT_EQ(initial_retransmittable_on_wire_timeout,
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+ // Simulate the alarm firing and check that a PING is sent.
+ writer_->Reset();
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ SendPing();
+ }));
+ clock_.AdvanceTime(initial_retransmittable_on_wire_timeout);
+ connection_.GetPingAlarm()->Fire();
+ }
+
+ QuicTime::Delta retransmittable_on_wire_timeout =
+ initial_retransmittable_on_wire_timeout;
+
+ // Verify subsequent pings are sent with timeout that is exponentially backed
+ // off.
+ while (retransmittable_on_wire_timeout * 2 < connection_.ping_timeout()) {
+ // Receive an ACK for the previous PING. This should set the
+ // ping alarm with backed off retransmittable-on-wire timeout.
+ retransmittable_on_wire_timeout = retransmittable_on_wire_timeout * 2;
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ QuicPacketNumber ack_num = creator_->packet_number();
+ QuicAckFrame frame = InitAckFrame(
+ {{QuicPacketNumber(ack_num), QuicPacketNumber(ack_num + 1)}});
+ ProcessAckPacket(&frame);
+ EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
+ EXPECT_EQ(retransmittable_on_wire_timeout,
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+
+ // Simulate the alarm firing and check that a PING is sent.
+ writer_->Reset();
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ SendPing();
+ }));
+ clock_.AdvanceTime(retransmittable_on_wire_timeout);
+ connection_.GetPingAlarm()->Fire();
+ }
+
+ // The ping alarm is set with default ping timeout.
+ EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
+ EXPECT_EQ(connection_.ping_timeout(),
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+
+ // Receive an ACK for the previous PING. The ping alarm is set with an
+ // earlier deadline.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ QuicPacketNumber ack_num = creator_->packet_number();
+ QuicAckFrame frame = InitAckFrame(
+ {{QuicPacketNumber(ack_num), QuicPacketNumber(ack_num + 1)}});
+ ProcessAckPacket(&frame);
+ EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
+ EXPECT_EQ(connection_.ping_timeout() - QuicTime::Delta::FromMilliseconds(5),
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+}
+
+// This test verify that the count of consecutive aggressive pings is reset
+// when new data is received. And it also verifies the connection resets
+// the exponential back-off of the retransmittable-on-wire ping timeout
+// after receiving new stream data.
+TEST_P(QuicConnectionTest, ResetBackOffRetransmitableOnWireTimeout) {
+ int max_aggressive_retransmittable_on_wire_ping_count = 3;
+ SetQuicFlag(FLAGS_quic_max_aggressive_retransmittable_on_wire_ping_count, 3);
+ const QuicTime::Delta initial_retransmittable_on_wire_timeout =
+ QuicTime::Delta::FromMilliseconds(200);
+ connection_.set_initial_retransmittable_on_wire_timeout(
+ initial_retransmittable_on_wire_timeout);
+
+ EXPECT_TRUE(connection_.connected());
+ EXPECT_CALL(visitor_, ShouldKeepConnectionAlive())
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)).Times(AnyNumber());
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _))
+ .Times(AnyNumber());
+
+ const char data[] = "data";
+ // Advance 5ms, send a retransmittable data packet to the peer.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ EXPECT_FALSE(connection_.GetPingAlarm()->IsSet());
+ connection_.SendStreamDataWithString(1, data, 0, NO_FIN);
+ EXPECT_TRUE(connection_.sent_packet_manager().HasInFlightPackets());
+ // The ping alarm is set for the ping timeout, not the shorter
+ // retransmittable_on_wire_timeout.
+ EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
+ EXPECT_EQ(connection_.ping_timeout(),
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+
+ // Receive an ACK of the first packet. This should set the ping alarm with
+ // initial retransmittable-on-wire timeout since there is no retransmittable
+ // packet on the wire.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ QuicAckFrame frame =
+ InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}});
+ ProcessAckPacket(&frame);
+ EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
+ EXPECT_EQ(initial_retransmittable_on_wire_timeout,
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+
+ // Simulate the alarm firing and check that a PING is sent.
+ writer_->Reset();
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() { SendPing(); }));
+ clock_.AdvanceTime(initial_retransmittable_on_wire_timeout);
+ connection_.GetPingAlarm()->Fire();
+
+ // Receive an ACK for the previous PING. Ping alarm will be set with
+ // aggressive timeout.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ QuicPacketNumber ack_num = creator_->packet_number();
+ frame = InitAckFrame(
+ {{QuicPacketNumber(ack_num), QuicPacketNumber(ack_num + 1)}});
+ ProcessAckPacket(&frame);
+ EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
+ EXPECT_EQ(initial_retransmittable_on_wire_timeout,
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+
+ // Process a data packet.
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+ ProcessDataPacket(peer_creator_.packet_number() + 1);
+ QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_,
+ peer_creator_.packet_number() + 1);
+ EXPECT_EQ(initial_retransmittable_on_wire_timeout,
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+
+ // Verify the count of consecutive aggressive pings is reset.
+ for (int i = 0; i < max_aggressive_retransmittable_on_wire_ping_count; i++) {
+ // Receive an ACK of the previous packet. This should set the ping alarm
+ // with the initial retransmittable-on-wire timeout.
+ QuicPacketNumber ack_num = creator_->packet_number();
+ QuicAckFrame frame = InitAckFrame(
+ {{QuicPacketNumber(ack_num), QuicPacketNumber(ack_num + 1)}});
+ ProcessAckPacket(&frame);
+ EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
+ EXPECT_EQ(initial_retransmittable_on_wire_timeout,
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+ // Simulate the alarm firing and check that a PING is sent.
+ writer_->Reset();
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ SendPing();
+ }));
+ clock_.AdvanceTime(initial_retransmittable_on_wire_timeout);
+ connection_.GetPingAlarm()->Fire();
+ // Advance 5ms to receive next packet.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ }
+
+ // Receive another ACK for the previous PING. This should set the
+ // ping alarm with backed off retransmittable-on-wire timeout.
+ ack_num = creator_->packet_number();
+ frame = InitAckFrame(
+ {{QuicPacketNumber(ack_num), QuicPacketNumber(ack_num + 1)}});
+ ProcessAckPacket(&frame);
+ EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
+ EXPECT_EQ(initial_retransmittable_on_wire_timeout * 2,
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+
+ writer_->Reset();
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() { SendPing(); }));
+ clock_.AdvanceTime(2 * initial_retransmittable_on_wire_timeout);
+ connection_.GetPingAlarm()->Fire();
+
+ // Process another data packet and a new ACK packet. The ping alarm is set
+ // with aggressive ping timeout again.
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ ProcessDataPacket(peer_creator_.packet_number() + 1);
+ QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_,
+ peer_creator_.packet_number() + 1);
+ ack_num = creator_->packet_number();
+ frame = InitAckFrame(
+ {{QuicPacketNumber(ack_num), QuicPacketNumber(ack_num + 1)}});
+ ProcessAckPacket(&frame);
+ EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
+ EXPECT_EQ(initial_retransmittable_on_wire_timeout,
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+}
+
TEST_P(QuicConnectionTest, OnForwardProgressConfirmed) {
EXPECT_CALL(visitor_, OnForwardProgressConfirmed()).Times(Exactly(0));
EXPECT_TRUE(connection_.connected());
@@ -8552,32 +8592,15 @@ TEST_P(QuicConnectionTest, ValidStatelessResetToken) {
TEST_P(QuicConnectionTest, WriteBlockedWithInvalidAck) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(visitor_, OnConnectionClosed(_, _)).Times(0);
- } else {
- EXPECT_CALL(visitor_, OnConnectionClosed(_, _))
- .WillOnce(Invoke(this, &QuicConnectionTest::SaveConnectionCloseFrame));
- }
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _)).Times(0);
BlockOnNextWrite();
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- } else {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
connection_.SendStreamDataWithString(5, "foo", 0, FIN);
// This causes connection to be closed because packet 1 has not been sent yet.
QuicAckFrame frame = InitAckFrame(1);
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _));
- }
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _));
ProcessAckPacket(1, &frame);
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_EQ(0, connection_close_frame_count_);
- } else {
- EXPECT_EQ(1, connection_close_frame_count_);
- EXPECT_EQ(QUIC_INVALID_ACK_DATA,
- saved_connection_close_frame_.quic_error_code);
- }
+ EXPECT_EQ(0, connection_close_frame_count_);
}
TEST_P(QuicConnectionTest, SendMessage) {
@@ -8594,33 +8617,36 @@ TEST_P(QuicConnectionTest, SendMessage) {
// get sent, one contains stream frame, and the other only contains the
// message frame.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
- EXPECT_EQ(
- MESSAGE_STATUS_SUCCESS,
- connection_.SendMessage(
- 1, MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
- QuicStringPiece(
- message_data.data(),
- connection_.GetCurrentLargestMessagePayload()),
- &storage)));
+ EXPECT_EQ(MESSAGE_STATUS_SUCCESS,
+ connection_.SendMessage(
+ 1,
+ MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
+ QuicStringPiece(
+ message_data.data(),
+ connection_.GetCurrentLargestMessagePayload()),
+ &storage),
+ false));
}
// Fail to send a message if connection is congestion control blocked.
EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false));
- EXPECT_EQ(
- MESSAGE_STATUS_BLOCKED,
- connection_.SendMessage(
- 2, MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
- "message", &storage)));
+ EXPECT_EQ(MESSAGE_STATUS_BLOCKED,
+ connection_.SendMessage(
+ 2,
+ MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
+ "message", &storage),
+ false));
// Always fail to send a message which cannot fit into one packet.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
- EXPECT_EQ(
- MESSAGE_STATUS_TOO_LARGE,
- connection_.SendMessage(
- 3, MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
- QuicStringPiece(
- message_data.data(),
- connection_.GetCurrentLargestMessagePayload() + 1),
- &storage)));
+ EXPECT_EQ(MESSAGE_STATUS_TOO_LARGE,
+ connection_.SendMessage(
+ 3,
+ MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
+ QuicStringPiece(
+ message_data.data(),
+ connection_.GetCurrentLargestMessagePayload() + 1),
+ &storage),
+ false));
}
// Test to check that the path challenge/path response logic works
@@ -8743,7 +8769,6 @@ TEST_P(QuicConnectionTest, StopProcessingGQuicPacketInIetfQuicConnection) {
0u, QuicStringPiece()));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
}
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
// Let connection process a Google QUIC packet.
@@ -8832,6 +8857,8 @@ TEST_P(QuicConnectionTest, PeerAcksPacketsInWrongPacketNumberSpace) {
use_tagging_decrypter();
connection_.SetEncrypter(ENCRYPTION_INITIAL,
std::make_unique<TaggingEncrypter>(0x01));
+ connection_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<TaggingEncrypter>(0x01));
connection_.SendCryptoStreamData();
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -8853,7 +8880,7 @@ TEST_P(QuicConnectionTest, PeerAcksPacketsInWrongPacketNumberSpace) {
InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(4)}});
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
ProcessFramePacketAtLevel(300, QuicFrame(&invalid_ack), ENCRYPTION_INITIAL);
TestConnectionCloseQuicErrorCode(QUIC_INVALID_ACK_DATA);
}
@@ -9014,7 +9041,6 @@ TEST_P(QuicConnectionTest, UpdateClientConnectionIdFromFirstPacket) {
if (!framer_.version().SupportsClientConnectionIds()) {
return;
}
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
QuicPacketHeader header = ConstructPacketHeader(1, ENCRYPTION_INITIAL);
header.source_connection_id = TestConnectionId(0x33);
@@ -9185,10 +9211,6 @@ TEST_P(QuicConnectionTest, CoalescedPacketThatSavesFrames) {
// Regresstion test for b/138962304.
TEST_P(QuicConnectionTest, RtoAndWriteBlocked) {
- if (!QuicConnectionPeer::GetSentPacketManager(&connection_)
- ->fix_rto_retransmission()) {
- return;
- }
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
QuicStreamId stream_id = 2;
@@ -9215,10 +9237,6 @@ TEST_P(QuicConnectionTest, RtoAndWriteBlocked) {
// Regresstion test for b/138962304.
TEST_P(QuicConnectionTest, TlpAndWriteBlocked) {
- if (!QuicConnectionPeer::GetSentPacketManager(&connection_)
- ->fix_rto_retransmission()) {
- return;
- }
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
connection_.SetMaxTailLossProbes(1);
@@ -9236,11 +9254,7 @@ TEST_P(QuicConnectionTest, TlpAndWriteBlocked) {
EXPECT_CALL(visitor_, OnWriteBlocked()).Times(AtLeast(1));
SendRstStream(stream_id, QUIC_ERROR_PROCESSING_STREAM, 3);
- if (GetQuicReloadableFlag(quic_treat_queued_packets_as_sent)) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- } else {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
- }
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
// Retransmission timer fires in TLP mode.
connection_.GetRetransmissionAlarm()->Fire();
// Verify one packets is forced flushed when writer is blocked.
@@ -9249,9 +9263,7 @@ TEST_P(QuicConnectionTest, TlpAndWriteBlocked) {
// Regresstion test for b/139375344.
TEST_P(QuicConnectionTest, RtoForcesSendingPing) {
- if (!QuicConnectionPeer::GetSentPacketManager(&connection_)
- ->fix_rto_retransmission() ||
- connection_.PtoEnabled()) {
+ if (connection_.PtoEnabled()) {
return;
}
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -9289,12 +9301,7 @@ TEST_P(QuicConnectionTest, RtoForcesSendingPing) {
}
TEST_P(QuicConnectionTest, ProbeTimeout) {
- if (!connection_.session_decides_what_to_write() ||
- !GetQuicReloadableFlag(quic_fix_rto_retransmission3)) {
- return;
- }
SetQuicReloadableFlag(quic_enable_pto, true);
- SetQuicReloadableFlag(quic_fix_rto_retransmission3, true);
QuicConfig config;
QuicTagVector connection_options;
connection_options.push_back(k2PTO);
@@ -9322,10 +9329,6 @@ TEST_P(QuicConnectionTest, ProbeTimeout) {
}
TEST_P(QuicConnectionTest, CloseConnectionAfter6ClientPTOs) {
- if (!connection_.session_decides_what_to_write() ||
- !GetQuicReloadableFlag(quic_fix_rto_retransmission3)) {
- return;
- }
SetQuicReloadableFlag(quic_enable_pto, true);
QuicConfig config;
QuicTagVector connection_options;
@@ -9342,7 +9345,7 @@ TEST_P(QuicConnectionTest, CloseConnectionAfter6ClientPTOs) {
0, FIN, nullptr);
// 5PTO + 1 connection close.
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(6);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(6));
// Fire the retransmission alarm 5 times.
for (int i = 0; i < 5; ++i) {
@@ -9364,10 +9367,6 @@ TEST_P(QuicConnectionTest, CloseConnectionAfter6ClientPTOs) {
}
TEST_P(QuicConnectionTest, CloseConnectionAfter7ClientPTOs) {
- if (!connection_.session_decides_what_to_write() ||
- !GetQuicReloadableFlag(quic_fix_rto_retransmission3)) {
- return;
- }
SetQuicReloadableFlag(quic_enable_pto, true);
QuicConfig config;
QuicTagVector connection_options;
@@ -9397,7 +9396,7 @@ TEST_P(QuicConnectionTest, CloseConnectionAfter7ClientPTOs) {
// Closes connection on 7th PTO.
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
connection_.GetRetransmissionAlarm()->Fire();
EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_FALSE(connection_.connected());
@@ -9405,10 +9404,6 @@ TEST_P(QuicConnectionTest, CloseConnectionAfter7ClientPTOs) {
}
TEST_P(QuicConnectionTest, CloseConnectionAfter8ClientPTOs) {
- if (!connection_.session_decides_what_to_write() ||
- !GetQuicReloadableFlag(quic_fix_rto_retransmission3)) {
- return;
- }
SetQuicReloadableFlag(quic_enable_pto, true);
QuicConfig config;
QuicTagVector connection_options;
@@ -9438,7 +9433,7 @@ TEST_P(QuicConnectionTest, CloseConnectionAfter8ClientPTOs) {
// Closes connection on 8th PTO.
EXPECT_CALL(visitor_,
OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
connection_.GetRetransmissionAlarm()->Fire();
EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_FALSE(connection_.connected());
@@ -9482,7 +9477,6 @@ TEST_P(QuicConnectionTest, AntiAmplificationLimit) {
if (!connection_.version().SupportsAntiAmplificationLimit()) {
return;
}
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(AnyNumber());
set_perspective(Perspective::IS_SERVER);
@@ -9558,9 +9552,7 @@ TEST_P(QuicConnectionTest, ConnectionCloseFrameType) {
// Regression test for b/137401387 and b/138962304.
TEST_P(QuicConnectionTest, RtoPacketAsTwo) {
- if (!QuicConnectionPeer::GetSentPacketManager(&connection_)
- ->fix_rto_retransmission() ||
- connection_.PtoEnabled()) {
+ if (connection_.PtoEnabled()) {
return;
}
connection_.SetMaxTailLossProbes(1);
@@ -9603,10 +9595,6 @@ TEST_P(QuicConnectionTest, RtoPacketAsTwo) {
}
TEST_P(QuicConnectionTest, PtoSkipsPacketNumber) {
- if (!connection_.session_decides_what_to_write() ||
- !GetQuicReloadableFlag(quic_fix_rto_retransmission3)) {
- return;
- }
SetQuicReloadableFlag(quic_enable_pto, true);
SetQuicReloadableFlag(quic_skip_packet_number_for_pto, true);
QuicConfig config;
@@ -9633,6 +9621,44 @@ TEST_P(QuicConnectionTest, PtoSkipsPacketNumber) {
EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
}
+TEST_P(QuicConnectionTest, SendCoalescedPackets) {
+ if (!connection_.version().CanSendCoalescedPackets()) {
+ return;
+ }
+ {
+ QuicConnection::ScopedPacketFlusher flusher(&connection_);
+ use_tagging_decrypter();
+ connection_.SetEncrypter(ENCRYPTION_INITIAL,
+ std::make_unique<TaggingEncrypter>(0x01));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
+ connection_.SendCryptoDataWithString("foo", 0);
+ // Verify this packet is on hold.
+ EXPECT_EQ(0u, writer_->packets_write_attempts());
+
+ connection_.SetEncrypter(ENCRYPTION_HANDSHAKE,
+ std::make_unique<TaggingEncrypter>(0x02));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_HANDSHAKE);
+ connection_.SendCryptoDataWithString("bar", 3);
+ EXPECT_EQ(0u, writer_->packets_write_attempts());
+
+ connection_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<TaggingEncrypter>(0x03));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ SendStreamDataToPeer(2, "baz", 3, NO_FIN, nullptr);
+ }
+ // Verify all 3 packets are coalesced in the same UDP datagram.
+ EXPECT_EQ(1u, writer_->packets_write_attempts());
+ EXPECT_EQ(0x03030303u, writer_->final_bytes_of_last_packet());
+ // Verify the packet is padded to full.
+ EXPECT_EQ(connection_.max_packet_length(), writer_->last_packet_size());
+
+ // Verify packet process.
+ EXPECT_EQ(1u, writer_->crypto_frames().size());
+ EXPECT_EQ(0u, writer_->stream_frames().size());
+ // Verify there is coalesced packet.
+ EXPECT_NE(nullptr, writer_->coalesced_packet());
+}
+
} // 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 3dc462ccb87..3264c1532ff 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
@@ -47,6 +47,9 @@ const QuicByteCount kMaxIncomingPacketSize = kMaxV4PacketSize;
const QuicByteCount kMaxOutgoingPacketSize = kMaxV6PacketSize;
// ETH_MAX_MTU - MAX(sizeof(iphdr), sizeof(ip6_hdr)) - sizeof(udphdr).
const QuicByteCount kMaxGsoPacketSize = 65535 - 40 - 8;
+// The maximal IETF DATAGRAM frame size we'll accept. Choosing 2^16 ensures
+// that it is greater than the biggest frame we could ever fit in a QUIC packet.
+const QuicByteCount kMaxAcceptedDatagramFrameSize = 65536;
// Default maximum packet size used in the Linux TCP implementation.
// Used in QUIC for congestion window computations in bytes.
const QuicByteCount kDefaultTCPMSS = 1460;
@@ -245,6 +248,15 @@ const int kInitialRttMs = 100;
// packet is lost due to early retransmission by time based loss detection.
static const int kDefaultLossDelayShift = 2;
+// Maximum number of retransmittable packets received before sending an ack.
+const QuicPacketCount kDefaultRetransmittablePacketsBeforeAck = 2;
+// Wait for up to 10 retransmittable packets before sending an ack.
+const QuicPacketCount kMaxRetransmittablePacketsBeforeAck = 10;
+// Minimum number of packets received before ack decimation is enabled.
+// This intends to avoid the beginning of slow start, when CWNDs may be
+// rapidly increasing.
+const QuicPacketCount kMinReceivedBeforeAckDecimation = 100;
+
// Packet number of first sending packet of a connection. Please note, this
// cannot be used as first received packet because peer can choose its starting
// packet number.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc
index 11efae85892..3eed5e8d7ca 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
@@ -26,14 +26,7 @@ QuicControlFrameManager::QuicControlFrameManager(QuicSession* session)
: last_control_frame_id_(kInvalidControlFrameId),
least_unacked_(1),
least_unsent_(1),
- session_(session),
- add_upper_limit_(GetQuicReloadableFlag(
- quic_add_upper_limit_of_buffered_control_frames3)) {
- if (add_upper_limit_) {
- QUIC_RELOADABLE_FLAG_COUNT(
- quic_add_upper_limit_of_buffered_control_frames3);
- }
-}
+ session_(session) {}
QuicControlFrameManager::~QuicControlFrameManager() {
while (!control_frames_.empty()) {
@@ -45,7 +38,7 @@ QuicControlFrameManager::~QuicControlFrameManager() {
void QuicControlFrameManager::WriteOrBufferQuicFrame(QuicFrame frame) {
const bool had_buffered_frames = HasBufferedFrames();
control_frames_.emplace_back(frame);
- if (add_upper_limit_ && control_frames_.size() > kMaxNumControlFrames) {
+ if (control_frames_.size() > kMaxNumControlFrames) {
session_->connection()->CloseConnection(
QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES,
QuicStrCat("More than ", kMaxNumControlFrames,
@@ -125,7 +118,7 @@ void QuicControlFrameManager::WritePing() {
}
control_frames_.emplace_back(
QuicFrame(QuicPingFrame(++last_control_frame_id_)));
- if (add_upper_limit_ && control_frames_.size() > kMaxNumControlFrames) {
+ if (control_frames_.size() > kMaxNumControlFrames) {
session_->connection()->CloseConnection(
QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES,
QuicStrCat("More than ", kMaxNumControlFrames,
@@ -281,9 +274,7 @@ bool QuicControlFrameManager::RetransmitControlFrame(const QuicFrame& frame) {
void QuicControlFrameManager::WriteBufferedFrames() {
while (HasBufferedFrames()) {
- if (session_->session_decides_what_to_write()) {
- session_->SetTransmissionType(NOT_RETRANSMISSION);
- }
+ session_->SetTransmissionType(NOT_RETRANSMISSION);
QuicFrame frame_to_send =
control_frames_.at(least_unsent_ - least_unacked_);
QuicFrame copy = CopyRetransmittableControlFrame(frame_to_send);
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 735b73c07b2..a4c26780d40 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
@@ -146,9 +146,6 @@ class QUIC_EXPORT_PRIVATE QuicControlFrameManager {
// Last sent window update frame for each stream.
QuicSmallMap<QuicStreamId, QuicControlFrameId, 10> window_update_frames_;
-
- // Latched value of quic_add_upper_limit_of_buffered_control_frames3.
- const bool add_upper_limit_;
};
} // namespace quic
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 d1723a1828c..e76e09ffb9a 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
@@ -291,7 +291,6 @@ TEST_F(QuicControlFrameManagerTest, RetransmitWindowUpdateOfDifferentStreams) {
}
TEST_F(QuicControlFrameManagerTest, TooManyBufferedControlFrames) {
- SetQuicReloadableFlag(quic_add_upper_limit_of_buffered_control_frames3, true);
Initialize();
EXPECT_CALL(*connection_, SendControlFrame(_))
.Times(5)
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 1f63042d6ee..eaeabfec08f 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
@@ -56,6 +56,7 @@ QuicCryptoClientHandshaker::QuicCryptoClientHandshaker(
: QuicCryptoHandshaker(stream, session),
stream_(stream),
session_(session),
+ delegate_(session),
next_state_(STATE_IDLE),
num_client_hellos_(0),
crypto_config_(crypto_config),
@@ -116,6 +117,13 @@ int QuicCryptoClientHandshaker::num_sent_client_hellos() const {
return num_client_hellos_;
}
+bool QuicCryptoClientHandshaker::IsResumption() const {
+ QUIC_BUG_IF(!handshake_confirmed_);
+ // 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;
+}
+
int QuicCryptoClientHandshaker::num_scup_messages_received() const {
return num_scup_messages_received_;
}
@@ -310,6 +318,17 @@ void QuicCryptoClientHandshaker::DoSendCHLO(
crypto_config_->pad_full_hello());
SendHandshakeMessage(out);
// Be prepared to decrypt with the new server write key.
+ if (session()->use_handshake_delegate()) {
+ delegate_->OnNewKeysAvailable(
+ ENCRYPTION_ZERO_RTT,
+ std::move(crypto_negotiated_params_->initial_crypters.decrypter),
+ /*set_alternative_decrypter=*/true,
+ /*latch_once_used=*/true,
+ std::move(crypto_negotiated_params_->initial_crypters.encrypter));
+ encryption_established_ = true;
+ delegate_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ return;
+ }
if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
session()->connection()->InstallDecrypter(
ENCRYPTION_ZERO_RTT,
@@ -369,7 +388,11 @@ void QuicCryptoClientHandshaker::DoReceiveREJ(
// Receipt of a REJ message means that the server received the CHLO
// so we can cancel and retransmissions.
- session()->NeuterUnencryptedData();
+ if (session()->use_handshake_delegate()) {
+ delegate_->NeuterUnencryptedData();
+ } else {
+ session()->NeuterUnencryptedData();
+ }
std::string error_details;
QuicErrorCode error = crypto_config_->ProcessRejection(
@@ -529,6 +552,18 @@ void QuicCryptoClientHandshaker::DoReceiveSHLO(
// has been floated that the server shouldn't send packets encrypted
// with the FORWARD_SECURE key until it receives a FORWARD_SECURE
// packet from the client.
+ if (session()->use_handshake_delegate()) {
+ delegate_->OnNewKeysAvailable(
+ ENCRYPTION_FORWARD_SECURE, std::move(crypters->decrypter),
+ /*set_alternative_decrypter=*/true,
+ /*latch_once_used=*/false, std::move(crypters->encrypter));
+ handshake_confirmed_ = true;
+ delegate_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ delegate_->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
+ delegate_->NeuterHandshakeData();
+ return;
+ }
+
if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
session()->connection()->InstallDecrypter(ENCRYPTION_FORWARD_SECURE,
std::move(crypters->decrypter));
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.h b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.h
index d33ebfe32fe..467e5c87208 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.h
@@ -37,6 +37,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientHandshaker
// From QuicCryptoClientStream::HandshakerDelegate
bool CryptoConnect() override;
int num_sent_client_hellos() const override;
+ bool IsResumption() const override;
int num_scup_messages_received() const override;
std::string chlo_hash() const override;
bool encryption_established() const override;
@@ -60,7 +61,8 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientHandshaker
// ProofVerifierCallbackImpl is passed as the callback method to VerifyProof.
// The ProofVerifier calls this class with the result of proof verification
// when verification is performed asynchronously.
- class ProofVerifierCallbackImpl : public ProofVerifierCallback {
+ class QUIC_EXPORT_PRIVATE ProofVerifierCallbackImpl
+ : public ProofVerifierCallback {
public:
explicit ProofVerifierCallbackImpl(QuicCryptoClientHandshaker* parent);
~ProofVerifierCallbackImpl() override;
@@ -130,6 +132,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientHandshaker
QuicCryptoClientStream* stream_;
QuicSession* session_;
+ HandshakerDelegateInterface* delegate_;
State next_state_;
// num_client_hellos_ contains the number of client hello messages that this
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 12b538f7cab..b30cd3a5112 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
@@ -43,9 +43,8 @@ QuicCryptoClientStream::QuicCryptoClientStream(
break;
case PROTOCOL_TLS1_3:
handshaker_ = std::make_unique<TlsClientHandshaker>(
- this, session, server_id, crypto_config->proof_verifier(),
- crypto_config->ssl_ctx(), std::move(verify_context), proof_handler,
- crypto_config->user_agent_id());
+ server_id, this, session, std::move(verify_context), crypto_config,
+ proof_handler);
break;
case PROTOCOL_UNSUPPORTED:
QUIC_BUG << "Attempting to create QuicCryptoClientStream for unknown "
@@ -63,6 +62,10 @@ int QuicCryptoClientStream::num_sent_client_hellos() const {
return handshaker_->num_sent_client_hellos();
}
+bool QuicCryptoClientStream::IsResumption() const {
+ return handshaker_->IsResumption();
+}
+
int QuicCryptoClientStream::num_scup_messages_received() const {
return handshaker_->num_scup_messages_received();
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h
index 89f0d2e28b7..3f9b0af7747 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h
@@ -35,6 +35,13 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStreamBase : public QuicCryptoStream {
// than the number of round-trips needed for the handshake.
virtual int num_sent_client_hellos() const = 0;
+ // Returns true if the handshake performed was a resumption instead of a full
+ // handshake. Resumption only makes sense for TLS handshakes - there is no
+ // concept of resumption for QUIC crypto even though it supports a 0-RTT
+ // handshake. This function only returns valid results once the handshake is
+ // complete.
+ virtual bool IsResumption() const = 0;
+
// The number of server config update messages received by the
// client. Does not count update messages that were received prior
// to handshake confirmation.
@@ -79,6 +86,13 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
// than the number of round-trips needed for the handshake.
virtual int num_sent_client_hellos() const = 0;
+ // Returns true if the handshake performed was a resumption instead of a
+ // full handshake. Resumption only makes sense for TLS handshakes - there is
+ // no concept of resumption for QUIC crypto even though it supports a 0-RTT
+ // handshake. This function only returns valid results once the handshake is
+ // complete.
+ virtual bool IsResumption() const = 0;
+
// The number of server config update messages received by the
// client. Does not count update messages that were received prior
// to handshake confirmation.
@@ -137,6 +151,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
// From QuicCryptoClientStreamBase
bool CryptoConnect() override;
int num_sent_client_hellos() const override;
+ bool IsResumption() const override;
int num_scup_messages_received() const override;
@@ -146,6 +161,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
const override;
CryptoMessageParser* crypto_message_parser() override;
+ void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
size_t BufferSizeLimitForLevel(EncryptionLevel level) const override;
std::string chlo_hash() const;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream_test.cc
index 8e1ef25ea01..827cb03e3a3 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream_test.cc
@@ -22,6 +22,7 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_sequencer_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simple_quic_framer.h"
+#include "net/third_party/quiche/src/quic/test_tools/simple_session_cache.h"
using testing::_;
@@ -37,7 +38,10 @@ class QuicCryptoClientStreamTest : public QuicTest {
QuicCryptoClientStreamTest()
: supported_versions_(AllSupportedVersions()),
server_id_(kServerHostname, kServerPort, false),
- crypto_config_(crypto_test_utils::ProofVerifierForTesting()) {
+ crypto_config_(crypto_test_utils::ProofVerifierForTesting(),
+ std::make_unique<test::SimpleSessionCache>()),
+ server_crypto_config_(
+ crypto_test_utils::CryptoServerConfigForTesting()) {
CreateConnection();
}
@@ -56,17 +60,30 @@ class QuicCryptoClientStreamTest : public QuicTest {
{AlpnForVersion(connection_->version())})));
}
+ void UseTlsHandshake() {
+ SetQuicReloadableFlag(quic_supports_tls_handshake, true);
+ supported_versions_.clear();
+ for (ParsedQuicVersion version : AllSupportedVersions()) {
+ if (version.handshake_protocol != PROTOCOL_TLS1_3) {
+ continue;
+ }
+ supported_versions_.push_back(version);
+ }
+ }
+
void CompleteCryptoHandshake() {
+ int proof_verify_details_calls = 1;
if (stream()->handshake_protocol() != PROTOCOL_TLS1_3) {
EXPECT_CALL(*session_, OnProofValid(testing::_));
+ proof_verify_details_calls = 0;
}
EXPECT_CALL(*session_, OnProofVerifyDetailsAvailable(testing::_))
- .Times(testing::AnyNumber());
+ .Times(testing::AtLeast(proof_verify_details_calls));
stream()->CryptoConnect();
QuicConfig config;
crypto_test_utils::HandshakeWithFakeServer(
- &config, &server_helper_, &alarm_factory_, connection_, stream(),
- AlpnForVersion(connection_->version()));
+ &config, server_crypto_config_.get(), &server_helper_, &alarm_factory_,
+ connection_, stream(), AlpnForVersion(connection_->version()));
}
QuicCryptoClientStream* stream() {
@@ -82,6 +99,7 @@ class QuicCryptoClientStreamTest : public QuicTest {
QuicServerId server_id_;
CryptoHandshakeMessage message_;
QuicCryptoClientConfig crypto_config_;
+ std::unique_ptr<QuicCryptoServerConfig> server_crypto_config_;
};
TEST_F(QuicCryptoClientStreamTest, NotInitiallyConected) {
@@ -93,45 +111,57 @@ TEST_F(QuicCryptoClientStreamTest, ConnectedAfterSHLO) {
CompleteCryptoHandshake();
EXPECT_TRUE(stream()->encryption_established());
EXPECT_TRUE(stream()->handshake_confirmed());
+ EXPECT_FALSE(stream()->IsResumption());
}
TEST_F(QuicCryptoClientStreamTest, ConnectedAfterTlsHandshake) {
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
- supported_versions_.clear();
- for (ParsedQuicVersion version : AllSupportedVersions()) {
- if (version.handshake_protocol != PROTOCOL_TLS1_3) {
- continue;
- }
- supported_versions_.push_back(version);
- }
+ UseTlsHandshake();
CreateConnection();
CompleteCryptoHandshake();
EXPECT_EQ(PROTOCOL_TLS1_3, stream()->handshake_protocol());
EXPECT_TRUE(stream()->encryption_established());
EXPECT_TRUE(stream()->handshake_confirmed());
+ EXPECT_FALSE(stream()->IsResumption());
}
TEST_F(QuicCryptoClientStreamTest,
ProofVerifyDetailsAvailableAfterTlsHandshake) {
- SetQuicReloadableFlag(quic_supports_tls_handshake, true);
- supported_versions_.clear();
- for (ParsedQuicVersion version : AllSupportedVersions()) {
- if (version.handshake_protocol != PROTOCOL_TLS1_3) {
- continue;
- }
- supported_versions_.push_back(version);
- }
+ UseTlsHandshake();
CreateConnection();
EXPECT_CALL(*session_, OnProofVerifyDetailsAvailable(testing::_));
stream()->CryptoConnect();
QuicConfig config;
crypto_test_utils::HandshakeWithFakeServer(
- &config, &server_helper_, &alarm_factory_, connection_, stream(),
- AlpnForVersion(connection_->version()));
+ &config, server_crypto_config_.get(), &server_helper_, &alarm_factory_,
+ connection_, stream(), AlpnForVersion(connection_->version()));
+ EXPECT_EQ(PROTOCOL_TLS1_3, stream()->handshake_protocol());
+ EXPECT_TRUE(stream()->encryption_established());
+ EXPECT_TRUE(stream()->handshake_confirmed());
+}
+
+TEST_F(QuicCryptoClientStreamTest, TlsResumption) {
+ UseTlsHandshake();
+ // Enable resumption on the server:
+ SSL_CTX_clear_options(server_crypto_config_->ssl_ctx(), SSL_OP_NO_TICKET);
+ CreateConnection();
+
+ // Finish establishing the first connection:
+ CompleteCryptoHandshake();
+
+ EXPECT_EQ(PROTOCOL_TLS1_3, stream()->handshake_protocol());
+ EXPECT_TRUE(stream()->encryption_established());
+ EXPECT_TRUE(stream()->handshake_confirmed());
+ EXPECT_FALSE(stream()->IsResumption());
+
+ // Create a second connection
+ CreateConnection();
+ CompleteCryptoHandshake();
+
EXPECT_EQ(PROTOCOL_TLS1_3, stream()->handshake_protocol());
EXPECT_TRUE(stream()->encryption_established());
EXPECT_TRUE(stream()->handshake_confirmed());
+ EXPECT_TRUE(stream()->IsResumption());
}
TEST_F(QuicCryptoClientStreamTest, MessageAfterHandshake) {
@@ -359,14 +389,14 @@ TEST_F(QuicCryptoClientStreamTest, PreferredVersion) {
// Verify preferred version is the highest version that session supports, and
// is different from connection's version.
QuicVersionLabel client_version_label;
- EXPECT_EQ(QUIC_NO_ERROR,
- session_->sent_crypto_handshake_messages()[0].GetVersionLabel(
- kVER, &client_version_label));
+ EXPECT_THAT(session_->sent_crypto_handshake_messages()[0].GetVersionLabel(
+ kVER, &client_version_label),
+ IsQuicNoError());
EXPECT_EQ(CreateQuicVersionLabel(supported_versions_[0]),
client_version_label);
- EXPECT_EQ(QUIC_NO_ERROR,
- session_->sent_crypto_handshake_messages()[1].GetVersionLabel(
- kVER, &client_version_label));
+ EXPECT_THAT(session_->sent_crypto_handshake_messages()[1].GetVersionLabel(
+ kVER, &client_version_label),
+ IsQuicNoError());
EXPECT_EQ(CreateQuicVersionLabel(supported_versions_[0]),
client_version_label);
EXPECT_NE(CreateQuicVersionLabel(connection_->version()),
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.cc
index 964c8ac5a46..755e35eb400 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.cc
@@ -54,6 +54,7 @@ QuicCryptoServerHandshaker::QuicCryptoServerHandshaker(
: QuicCryptoHandshaker(stream, session),
stream_(stream),
session_(session),
+ delegate_(session),
crypto_config_(crypto_config),
compressed_certs_cache_(compressed_certs_cache),
signed_config_(new QuicSignedServerConfig),
@@ -197,27 +198,52 @@ void QuicCryptoServerHandshaker::
// write key.
//
// NOTE: the SHLO will be encrypted with the new server write key.
- session()->connection()->SetEncrypter(
- ENCRYPTION_ZERO_RTT,
- std::move(crypto_negotiated_params_->initial_crypters.encrypter));
- session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
- // Set the decrypter immediately so that we no longer accept unencrypted
- // packets.
- if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
- session()->connection()->InstallDecrypter(
+ if (session()->use_handshake_delegate()) {
+ delegate_->OnNewKeysAvailable(
ENCRYPTION_ZERO_RTT,
- std::move(crypto_negotiated_params_->initial_crypters.decrypter));
- session()->connection()->RemoveDecrypter(ENCRYPTION_INITIAL);
+ std::move(crypto_negotiated_params_->initial_crypters.decrypter),
+ /*set_alternative_decrypter=*/false,
+ /*latch_once_used=*/false,
+ std::move(crypto_negotiated_params_->initial_crypters.encrypter));
+ delegate_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ delegate_->DiscardOldDecryptionKey(ENCRYPTION_INITIAL);
} else {
- session()->connection()->SetDecrypter(
+ session()->connection()->SetEncrypter(
ENCRYPTION_ZERO_RTT,
- std::move(crypto_negotiated_params_->initial_crypters.decrypter));
+ std::move(crypto_negotiated_params_->initial_crypters.encrypter));
+ session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ // Set the decrypter immediately so that we no longer accept unencrypted
+ // packets.
+ if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
+ session()->connection()->InstallDecrypter(
+ ENCRYPTION_ZERO_RTT,
+ std::move(crypto_negotiated_params_->initial_crypters.decrypter));
+ session()->connection()->RemoveDecrypter(ENCRYPTION_INITIAL);
+ } else {
+ session()->connection()->SetDecrypter(
+ ENCRYPTION_ZERO_RTT,
+ std::move(crypto_negotiated_params_->initial_crypters.decrypter));
+ }
}
session()->connection()->SetDiversificationNonce(*diversification_nonce);
session()->connection()->set_fully_pad_crypto_handshake_packets(
crypto_config_->pad_shlo());
SendHandshakeMessage(*reply);
+ if (session()->use_handshake_delegate()) {
+ delegate_->OnNewKeysAvailable(
+ ENCRYPTION_FORWARD_SECURE,
+ std::move(crypto_negotiated_params_->forward_secure_crypters.decrypter),
+ /*set_alternative_decrypter=*/true,
+ /*latch_once_used=*/false,
+ std::move(
+ crypto_negotiated_params_->forward_secure_crypters.encrypter));
+ encryption_established_ = true;
+ handshake_confirmed_ = true;
+ delegate_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ delegate_->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
+ return;
+ }
session()->connection()->SetEncrypter(
ENCRYPTION_FORWARD_SECURE,
@@ -336,6 +362,12 @@ void QuicCryptoServerHandshaker::SetPreviousCachedNetworkParams(
new CachedNetworkParameters(cached_network_params));
}
+void QuicCryptoServerHandshaker::OnPacketDecrypted(EncryptionLevel level) {
+ if (level == ENCRYPTION_FORWARD_SECURE) {
+ delegate_->NeuterHandshakeData();
+ }
+}
+
bool QuicCryptoServerHandshaker::ShouldSendExpectCTHeader() const {
return signed_config_->proof.send_expect_ct_header;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.h b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.h
index b24e9e95e90..4e1a1b895fd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.h
@@ -50,6 +50,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerHandshaker
bool ZeroRttAttempted() const override;
void SetPreviousCachedNetworkParams(
CachedNetworkParameters cached_network_params) override;
+ void OnPacketDecrypted(EncryptionLevel level) override;
bool ShouldSendExpectCTHeader() const override;
// From QuicCryptoStream
@@ -91,7 +92,8 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerHandshaker
private:
friend class test::QuicCryptoServerStreamPeer;
- class ValidateCallback : public ValidateClientHelloResultCallback {
+ class QUIC_EXPORT_PRIVATE ValidateCallback
+ : public ValidateClientHelloResultCallback {
public:
explicit ValidateCallback(QuicCryptoServerHandshaker* parent);
ValidateCallback(const ValidateCallback&) = delete;
@@ -161,6 +163,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerHandshaker
QuicCryptoServerStream* stream_;
QuicSession* session_;
+ HandshakerDelegateInterface* delegate_;
// crypto_config_ contains crypto parameters for the handshake.
const QuicCryptoServerConfig* crypto_config_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc
index 170e53baf01..bbc3b09d5c9 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc
@@ -111,6 +111,10 @@ CryptoMessageParser* QuicCryptoServerStream::crypto_message_parser() {
return handshaker()->crypto_message_parser();
}
+void QuicCryptoServerStream::OnPacketDecrypted(EncryptionLevel level) {
+ handshaker()->OnPacketDecrypted(level);
+}
+
size_t QuicCryptoServerStream::BufferSizeLimitForLevel(
EncryptionLevel level) const {
return handshaker()->BufferSizeLimitForLevel(level);
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h
index 3a7d6e74b1a..d80c495e413 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h
@@ -98,6 +98,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream
virtual bool ZeroRttAttempted() const = 0;
virtual void SetPreviousCachedNetworkParams(
CachedNetworkParameters cached_network_params) = 0;
+ virtual void OnPacketDecrypted(EncryptionLevel level) = 0;
// NOTE: Indicating that the Expect-CT header should be sent here presents a
// layering violation to some extent. The Expect-CT header only applies to
@@ -125,7 +126,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream
virtual size_t BufferSizeLimitForLevel(EncryptionLevel level) const = 0;
};
- class Helper {
+ class QUIC_EXPORT_PRIVATE Helper {
public:
virtual ~Helper() {}
@@ -176,6 +177,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream
const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
const override;
CryptoMessageParser* crypto_message_parser() override;
+ void OnPacketDecrypted(EncryptionLevel level) override;
size_t BufferSizeLimitForLevel(EncryptionLevel level) const override;
void OnSuccessfulVersionNegotiation(
const ParsedQuicVersion& version) override;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_test.cc
index 360c2684fc5..2f7055da328 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_test.cc
@@ -100,8 +100,10 @@ class QuicCryptoServerStreamTest : public QuicTestWithParam<bool> {
crypto_test_utils::SetupCryptoServerConfigForTest(
server_connection_->clock(), server_connection_->random_generator(),
&server_crypto_config_);
- server_session_->GetMutableCryptoStream()->OnSuccessfulVersionNegotiation(
- supported_versions_.front());
+ if (!GetQuicReloadableFlag(quic_version_negotiated_by_default_at_server)) {
+ server_session_->GetMutableCryptoStream()->OnSuccessfulVersionNegotiation(
+ supported_versions_.front());
+ }
}
QuicCryptoServerStream* server_stream() {
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 d62417fbf51..e22e830d381 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
@@ -72,8 +72,15 @@ void QuicCryptoStream::OnCryptoFrame(const QuicCryptoFrame& frame) {
<< "Versions less than 47 shouldn't receive CRYPTO frames";
EncryptionLevel level = session()->connection()->last_decrypted_level();
substreams_[level].sequencer.OnCryptoFrame(frame);
+ EncryptionLevel frame_level;
+ if (GetQuicReloadableFlag(quic_use_connection_encryption_level)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_use_connection_encryption_level);
+ frame_level = level;
+ } else {
+ frame_level = frame.level;
+ }
if (substreams_[level].sequencer.NumBytesBuffered() >
- BufferSizeLimitForLevel(frame.level)) {
+ BufferSizeLimitForLevel(frame_level)) {
CloseConnectionWithDetails(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
"Too much crypto data received");
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.h b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.h
index 12a36f894b6..357303a65bb 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.h
@@ -80,6 +80,9 @@ class QUIC_EXPORT_PRIVATE QuicCryptoStream : public QuicStream {
// Provides the message parser to use when data is received on this stream.
virtual CryptoMessageParser* crypto_message_parser() = 0;
+ // Called when a packet of encryption |level| has been successfully decrypted.
+ virtual void OnPacketDecrypted(EncryptionLevel level) = 0;
+
// Returns the maximum number of bytes that can be buffered at a particular
// encryption level |level|.
virtual size_t BufferSizeLimitForLevel(EncryptionLevel level) const;
@@ -155,7 +158,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoStream : public QuicStream {
// levels. Some of the state for the single logical crypto stream is split
// across encryption levels, and a CryptoSubstream is used to manage that
// state for a particular encryption level.
- struct CryptoSubstream {
+ struct QUIC_EXPORT_PRIVATE CryptoSubstream {
CryptoSubstream(QuicCryptoStream* crypto_stream, EncryptionLevel);
QuicStreamSequencer sequencer;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream_test.cc
index f5933d2fd89..25d9cc17ae1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream_test.cc
@@ -56,6 +56,7 @@ class MockQuicCryptoStream : public QuicCryptoStream,
CryptoMessageParser* crypto_message_parser() override {
return QuicCryptoHandshaker::crypto_message_parser();
}
+ void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
private:
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_data_reader.cc b/chromium/net/third_party/quiche/src/quic/core/quic_data_reader.cc
index c9a76be8f57..17fb6cdafc3 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_data_reader.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_data_reader.cc
@@ -9,18 +9,19 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
QuicDataReader::QuicDataReader(QuicStringPiece data)
- : QuicDataReader(data.data(), data.length(), NETWORK_BYTE_ORDER) {}
+ : QuicDataReader(data.data(), data.length(), quiche::NETWORK_BYTE_ORDER) {}
QuicDataReader::QuicDataReader(const char* data, const size_t len)
- : QuicDataReader(data, len, NETWORK_BYTE_ORDER) {}
+ : QuicDataReader(data, len, quiche::NETWORK_BYTE_ORDER) {}
QuicDataReader::QuicDataReader(const char* data,
const size_t len,
- Endianness endianness)
+ quiche::Endianness endianness)
: data_(data), len_(len), pos_(0), endianness_(endianness) {}
bool QuicDataReader::ReadUInt8(uint8_t* result) {
@@ -31,8 +32,8 @@ bool QuicDataReader::ReadUInt16(uint16_t* result) {
if (!ReadBytes(result, sizeof(*result))) {
return false;
}
- if (endianness_ == NETWORK_BYTE_ORDER) {
- *result = QuicEndian::NetToHost16(*result);
+ if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
+ *result = quiche::QuicheEndian::NetToHost16(*result);
}
return true;
}
@@ -41,8 +42,8 @@ bool QuicDataReader::ReadUInt32(uint32_t* result) {
if (!ReadBytes(result, sizeof(*result))) {
return false;
}
- if (endianness_ == NETWORK_BYTE_ORDER) {
- *result = QuicEndian::NetToHost32(*result);
+ if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
+ *result = quiche::QuicheEndian::NetToHost32(*result);
}
return true;
}
@@ -51,8 +52,8 @@ bool QuicDataReader::ReadUInt64(uint64_t* result) {
if (!ReadBytes(result, sizeof(*result))) {
return false;
}
- if (endianness_ == NETWORK_BYTE_ORDER) {
- *result = QuicEndian::NetToHost64(*result);
+ if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
+ *result = quiche::QuicheEndian::NetToHost64(*result);
}
return true;
}
@@ -62,7 +63,7 @@ bool QuicDataReader::ReadBytesToUInt64(size_t num_bytes, uint64_t* result) {
if (num_bytes > sizeof(*result)) {
return false;
}
- if (endianness_ == HOST_BYTE_ORDER) {
+ if (endianness_ == quiche::HOST_BYTE_ORDER) {
return ReadBytes(result, num_bytes);
}
@@ -70,7 +71,7 @@ bool QuicDataReader::ReadBytesToUInt64(size_t num_bytes, uint64_t* result) {
num_bytes)) {
return false;
}
- *result = QuicEndian::NetToHost64(*result);
+ *result = quiche::QuicheEndian::NetToHost64(*result);
return true;
}
@@ -217,7 +218,7 @@ bool QuicDataReader::IsDoneReading() const {
}
QuicVariableLengthIntegerLength QuicDataReader::PeekVarInt62Length() {
- DCHECK_EQ(endianness_, NETWORK_BYTE_ORDER);
+ DCHECK_EQ(endianness_, quiche::NETWORK_BYTE_ORDER);
const unsigned char* next =
reinterpret_cast<const unsigned char*>(data_ + pos_);
if (BytesRemaining() == 0) {
@@ -275,7 +276,7 @@ uint8_t QuicDataReader::PeekByte() const {
// Low-level optimization is useful here because this function will be
// called frequently, leading to outsize benefits.
bool QuicDataReader::ReadVarInt62(uint64_t* result) {
- DCHECK_EQ(endianness_, NETWORK_BYTE_ORDER);
+ DCHECK_EQ(endianness_, quiche::NETWORK_BYTE_ORDER);
size_t remaining = BytesRemaining();
const unsigned char* next =
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_data_reader.h b/chromium/net/third_party/quiche/src/quic/core/quic_data_reader.h
index 74ed2269d0c..acd30fda100 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_data_reader.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_data_reader.h
@@ -9,9 +9,9 @@
#include <cstdint>
#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
@@ -39,7 +39,9 @@ class QUIC_EXPORT_PRIVATE QuicDataReader {
QuicDataReader(const char* data, const size_t len);
// Constructs a reader using the specified endianness.
// Caller must provide an underlying buffer to work on.
- QuicDataReader(const char* data, const size_t len, Endianness endianness);
+ QuicDataReader(const char* data,
+ const size_t len,
+ quiche::Endianness endianness);
QuicDataReader(const QuicDataReader&) = delete;
QuicDataReader& operator=(const QuicDataReader&) = delete;
@@ -152,8 +154,6 @@ class QUIC_EXPORT_PRIVATE QuicDataReader {
// DOES NOT forward the internal iterator.
uint8_t PeekByte() const;
- void set_endianness(Endianness endianness) { endianness_ = endianness; }
-
// Read an IETF-encoded Variable Length Integer and place the result
// in |*result|.
// Returns true if it works, false if not. The only error is that
@@ -190,7 +190,7 @@ class QUIC_EXPORT_PRIVATE QuicDataReader {
size_t pos_;
// The endianness to read integers and floating numbers.
- Endianness endianness_;
+ quiche::Endianness endianness_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_data_writer.cc b/chromium/net/third_party/quiche/src/quic/core/quic_data_writer.cc
index e01eb6c4d24..d2d71133fe7 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
@@ -12,13 +12,16 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
QuicDataWriter::QuicDataWriter(size_t size, char* buffer)
- : QuicDataWriter(size, buffer, NETWORK_BYTE_ORDER) {}
+ : QuicDataWriter(size, buffer, quiche::NETWORK_BYTE_ORDER) {}
-QuicDataWriter::QuicDataWriter(size_t size, char* buffer, Endianness endianness)
+QuicDataWriter::QuicDataWriter(size_t size,
+ char* buffer,
+ quiche::Endianness endianness)
: buffer_(buffer), capacity_(size), length_(0), endianness_(endianness) {}
QuicDataWriter::~QuicDataWriter() {}
@@ -32,22 +35,22 @@ bool QuicDataWriter::WriteUInt8(uint8_t value) {
}
bool QuicDataWriter::WriteUInt16(uint16_t value) {
- if (endianness_ == NETWORK_BYTE_ORDER) {
- value = QuicEndian::HostToNet16(value);
+ if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
+ value = quiche::QuicheEndian::HostToNet16(value);
}
return WriteBytes(&value, sizeof(value));
}
bool QuicDataWriter::WriteUInt32(uint32_t value) {
- if (endianness_ == NETWORK_BYTE_ORDER) {
- value = QuicEndian::HostToNet32(value);
+ if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
+ value = quiche::QuicheEndian::HostToNet32(value);
}
return WriteBytes(&value, sizeof(value));
}
bool QuicDataWriter::WriteUInt64(uint64_t value) {
- if (endianness_ == NETWORK_BYTE_ORDER) {
- value = QuicEndian::HostToNet64(value);
+ if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
+ value = quiche::QuicheEndian::HostToNet64(value);
}
return WriteBytes(&value, sizeof(value));
}
@@ -56,11 +59,11 @@ bool QuicDataWriter::WriteBytesToUInt64(size_t num_bytes, uint64_t value) {
if (num_bytes > sizeof(value)) {
return false;
}
- if (endianness_ == HOST_BYTE_ORDER) {
+ if (endianness_ == quiche::HOST_BYTE_ORDER) {
return WriteBytes(&value, num_bytes);
}
- value = QuicEndian::HostToNet64(value);
+ value = quiche::QuicheEndian::HostToNet64(value);
return WriteBytes(reinterpret_cast<char*>(&value) + sizeof(value) - num_bytes,
num_bytes);
}
@@ -101,8 +104,8 @@ bool QuicDataWriter::WriteUFloat16(uint64_t value) {
result = static_cast<uint16_t>(value + (exponent << kUFloat16MantissaBits));
}
- if (endianness_ == NETWORK_BYTE_ORDER) {
- result = QuicEndian::HostToNet16(result);
+ if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
+ result = quiche::QuicheEndian::HostToNet16(result);
}
return WriteBytes(&result, sizeof(result));
}
@@ -227,7 +230,7 @@ bool QuicDataWriter::Seek(size_t length) {
// Low-level optimization is useful here because this function will be
// called frequently, leading to outsize benefits.
bool QuicDataWriter::WriteVarInt62(uint64_t value) {
- DCHECK_EQ(endianness_, NETWORK_BYTE_ORDER);
+ DCHECK_EQ(endianness_, quiche::NETWORK_BYTE_ORDER);
size_t remaining = capacity_ - length_;
char* next = buffer_ + length_;
@@ -298,7 +301,7 @@ bool QuicDataWriter::WriteVarInt62(uint64_t value) {
bool QuicDataWriter::WriteVarInt62(
uint64_t value,
QuicVariableLengthIntegerLength write_length) {
- DCHECK_EQ(endianness_, NETWORK_BYTE_ORDER);
+ DCHECK_EQ(endianness_, quiche::NETWORK_BYTE_ORDER);
size_t remaining = capacity_ - length_;
if (remaining < write_length) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_data_writer.h b/chromium/net/third_party/quiche/src/quic/core/quic_data_writer.h
index c43d0ffc743..8f1b21defd5 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_data_writer.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_data_writer.h
@@ -9,9 +9,9 @@
#include <cstdint>
#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
@@ -42,7 +42,7 @@ class QUIC_EXPORT_PRIVATE QuicDataWriter {
QuicDataWriter(size_t size, char* buffer);
// Creates a QuicDataWriter where |buffer| is not owned
// using the specified endianness.
- QuicDataWriter(size_t size, char* buffer, Endianness endianness);
+ QuicDataWriter(size_t size, char* buffer, quiche::Endianness endianness);
QuicDataWriter(const QuicDataWriter&) = delete;
QuicDataWriter& operator=(const QuicDataWriter&) = delete;
@@ -144,7 +144,7 @@ class QUIC_EXPORT_PRIVATE QuicDataWriter {
size_t length_; // Current length of the buffer.
// The endianness to write integers and floating numbers.
- Endianness endianness_;
+ quiche::Endianness endianness_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_data_writer_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_data_writer_test.cc
index 60abf961bc1..104df8d42ee 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_data_writer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_data_writer_test.cc
@@ -15,6 +15,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
namespace test {
@@ -25,20 +26,22 @@ char* AsChars(unsigned char* data) {
}
struct TestParams {
- explicit TestParams(Endianness endianness) : endianness(endianness) {}
+ explicit TestParams(quiche::Endianness endianness) : endianness(endianness) {}
- Endianness endianness;
+ quiche::Endianness endianness;
};
// Used by ::testing::PrintToStringParamName().
std::string PrintToString(const TestParams& p) {
- return QuicStrCat((p.endianness == NETWORK_BYTE_ORDER ? "Network" : "Host"),
- "ByteOrder");
+ return QuicStrCat(
+ (p.endianness == quiche::NETWORK_BYTE_ORDER ? "Network" : "Host"),
+ "ByteOrder");
}
std::vector<TestParams> GetTestParams() {
std::vector<TestParams> params;
- for (Endianness endianness : {NETWORK_BYTE_ORDER, HOST_BYTE_ORDER}) {
+ for (quiche::Endianness endianness :
+ {quiche::NETWORK_BYTE_ORDER, quiche::HOST_BYTE_ORDER}) {
params.push_back(TestParams(endianness));
}
return params;
@@ -135,8 +138,8 @@ TEST_P(QuicDataWriterTest, WriteUFloat16) {
QuicDataWriter writer(2, buffer, GetParam().endianness);
EXPECT_TRUE(writer.WriteUFloat16(test_cases[i].decoded));
uint16_t result = *reinterpret_cast<uint16_t*>(writer.data());
- if (GetParam().endianness == NETWORK_BYTE_ORDER) {
- result = QuicEndian::HostToNet16(result);
+ if (GetParam().endianness == quiche::NETWORK_BYTE_ORDER) {
+ result = quiche::QuicheEndian::HostToNet16(result);
}
EXPECT_EQ(test_cases[i].encoded, result);
}
@@ -196,8 +199,8 @@ TEST_P(QuicDataWriterTest, ReadUFloat16) {
for (int i = 0; i < num_test_cases; ++i) {
uint16_t encoded_ufloat = test_cases[i].encoded;
- if (GetParam().endianness == NETWORK_BYTE_ORDER) {
- encoded_ufloat = QuicEndian::HostToNet16(encoded_ufloat);
+ if (GetParam().endianness == quiche::NETWORK_BYTE_ORDER) {
+ encoded_ufloat = quiche::QuicheEndian::HostToNet16(encoded_ufloat);
}
QuicDataReader reader(reinterpret_cast<char*>(&encoded_ufloat), 2,
GetParam().endianness);
@@ -213,8 +216,8 @@ TEST_P(QuicDataWriterTest, RoundTripUFloat16) {
for (uint16_t i = 1; i < 0xFFFF; ++i) {
// Read the two bytes.
uint16_t read_number = i;
- if (GetParam().endianness == NETWORK_BYTE_ORDER) {
- read_number = QuicEndian::HostToNet16(read_number);
+ if (GetParam().endianness == quiche::NETWORK_BYTE_ORDER) {
+ read_number = quiche::QuicheEndian::HostToNet16(read_number);
}
QuicDataReader reader(reinterpret_cast<char*>(&read_number), 2,
GetParam().endianness);
@@ -243,10 +246,10 @@ TEST_P(QuicDataWriterTest, RoundTripUFloat16) {
uint16_t encoded1 = *reinterpret_cast<uint16_t*>(writer.data());
uint16_t encoded2 = *reinterpret_cast<uint16_t*>(writer.data() + 2);
uint16_t encoded3 = *reinterpret_cast<uint16_t*>(writer.data() + 4);
- if (GetParam().endianness == NETWORK_BYTE_ORDER) {
- encoded1 = QuicEndian::NetToHost16(encoded1);
- encoded2 = QuicEndian::NetToHost16(encoded2);
- encoded3 = QuicEndian::NetToHost16(encoded3);
+ if (GetParam().endianness == quiche::NETWORK_BYTE_ORDER) {
+ encoded1 = quiche::QuicheEndian::NetToHost16(encoded1);
+ encoded2 = quiche::QuicheEndian::NetToHost16(encoded2);
+ encoded3 = quiche::QuicheEndian::NetToHost16(encoded3);
}
EXPECT_EQ(i - 1, encoded1);
// Check roundtrip.
@@ -384,8 +387,8 @@ TEST_P(QuicDataWriterTest, Write16BitUnsignedIntegers) {
writer.WriteUInt16(in_memory16);
test::CompareCharArraysWithHexError(
"uint16_t", buffer16, 2,
- GetParam().endianness == NETWORK_BYTE_ORDER ? big_endian16
- : little_endian16,
+ GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian16
+ : little_endian16,
2);
uint16_t read_number16;
@@ -400,8 +403,8 @@ TEST_P(QuicDataWriterTest, Write16BitUnsignedIntegers) {
writer.WriteBytesToUInt64(2, in_memory16);
test::CompareCharArraysWithHexError(
"uint16_t", buffer16, 2,
- GetParam().endianness == NETWORK_BYTE_ORDER ? big_endian16
- : little_endian16,
+ GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian16
+ : little_endian16,
2);
uint64_t read_number16;
@@ -420,8 +423,8 @@ TEST_P(QuicDataWriterTest, Write24BitUnsignedIntegers) {
writer.WriteBytesToUInt64(3, in_memory24);
test::CompareCharArraysWithHexError(
"uint24", buffer24, 3,
- GetParam().endianness == NETWORK_BYTE_ORDER ? big_endian24
- : little_endian24,
+ GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian24
+ : little_endian24,
3);
uint64_t read_number24;
@@ -440,8 +443,8 @@ TEST_P(QuicDataWriterTest, Write32BitUnsignedIntegers) {
writer.WriteUInt32(in_memory32);
test::CompareCharArraysWithHexError(
"uint32_t", buffer32, 4,
- GetParam().endianness == NETWORK_BYTE_ORDER ? big_endian32
- : little_endian32,
+ GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian32
+ : little_endian32,
4);
uint32_t read_number32;
@@ -456,8 +459,8 @@ TEST_P(QuicDataWriterTest, Write32BitUnsignedIntegers) {
writer.WriteBytesToUInt64(4, in_memory32);
test::CompareCharArraysWithHexError(
"uint32_t", buffer32, 4,
- GetParam().endianness == NETWORK_BYTE_ORDER ? big_endian32
- : little_endian32,
+ GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian32
+ : little_endian32,
4);
uint64_t read_number32;
@@ -476,8 +479,8 @@ TEST_P(QuicDataWriterTest, Write40BitUnsignedIntegers) {
writer.WriteBytesToUInt64(5, in_memory40);
test::CompareCharArraysWithHexError(
"uint40", buffer40, 5,
- GetParam().endianness == NETWORK_BYTE_ORDER ? big_endian40
- : little_endian40,
+ GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian40
+ : little_endian40,
5);
uint64_t read_number40;
@@ -495,8 +498,8 @@ TEST_P(QuicDataWriterTest, Write48BitUnsignedIntegers) {
writer.WriteBytesToUInt64(6, in_memory48);
test::CompareCharArraysWithHexError(
"uint48", buffer48, 6,
- GetParam().endianness == NETWORK_BYTE_ORDER ? big_endian48
- : little_endian48,
+ GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian48
+ : little_endian48,
6);
uint64_t read_number48;
@@ -514,8 +517,8 @@ TEST_P(QuicDataWriterTest, Write56BitUnsignedIntegers) {
writer.WriteBytesToUInt64(7, in_memory56);
test::CompareCharArraysWithHexError(
"uint56", buffer56, 7,
- GetParam().endianness == NETWORK_BYTE_ORDER ? big_endian56
- : little_endian56,
+ GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian56
+ : little_endian56,
7);
uint64_t read_number56;
@@ -535,8 +538,9 @@ TEST_P(QuicDataWriterTest, Write64BitUnsignedIntegers) {
writer.WriteBytesToUInt64(8, in_memory64);
test::CompareCharArraysWithHexError(
"uint64_t", buffer64, 8,
- GetParam().endianness == NETWORK_BYTE_ORDER ? AsChars(big_endian64)
- : AsChars(little_endian64),
+ GetParam().endianness == quiche::NETWORK_BYTE_ORDER
+ ? AsChars(big_endian64)
+ : AsChars(little_endian64),
8);
uint64_t read_number64;
@@ -548,8 +552,9 @@ TEST_P(QuicDataWriterTest, Write64BitUnsignedIntegers) {
writer2.WriteUInt64(in_memory64);
test::CompareCharArraysWithHexError(
"uint64_t", buffer64, 8,
- GetParam().endianness == NETWORK_BYTE_ORDER ? AsChars(big_endian64)
- : AsChars(little_endian64),
+ GetParam().endianness == quiche::NETWORK_BYTE_ORDER
+ ? AsChars(big_endian64)
+ : AsChars(little_endian64),
8);
read_number64 = 0u;
QuicDataReader reader2(buffer64, 8, GetParam().endianness);
@@ -674,7 +679,8 @@ bool EncodeDecodeValue(uint64_t value_in, char* buffer, size_t size_of_buffer) {
// make a writer. Note that for IETF encoding
// we do not care about endianness... It's always big-endian,
// but the c'tor expects to be told what endianness is in force...
- QuicDataWriter writer(size_of_buffer, buffer, Endianness::NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(size_of_buffer, buffer,
+ quiche::Endianness::NETWORK_BYTE_ORDER);
// Try to write the value.
if (writer.WriteVarInt62(value_in) != true) {
@@ -699,7 +705,7 @@ bool EncodeDecodeValue(uint64_t value_in, char* buffer, size_t size_of_buffer) {
// set up a reader, just the length we've used, no more, no less.
QuicDataReader reader(buffer, expected_length,
- Endianness::NETWORK_BYTE_ORDER);
+ quiche::Endianness::NETWORK_BYTE_ORDER);
uint64_t value_out;
if (reader.ReadVarInt62(&value_out) == false) {
@@ -721,7 +727,7 @@ TEST_P(QuicDataWriterTest, VarInt8Layout) {
// are always encoded big endian...
memset(buffer, 0, sizeof(buffer));
QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
- Endianness::NETWORK_BYTE_ORDER);
+ quiche::Endianness::NETWORK_BYTE_ORDER);
EXPECT_TRUE(writer.WriteVarInt62(UINT64_C(0x3142f3e4d5c6b7a8)));
EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 0)),
(0x31 + 0xc0)); // 0xc0 for encoding
@@ -743,7 +749,7 @@ TEST_P(QuicDataWriterTest, VarInt4Layout) {
// are always encoded big endian...
memset(buffer, 0, sizeof(buffer));
QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
- Endianness::NETWORK_BYTE_ORDER);
+ quiche::Endianness::NETWORK_BYTE_ORDER);
EXPECT_TRUE(writer.WriteVarInt62(0x3243f4e5));
EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 0)),
(0x32 + 0x80)); // 0x80 for encoding
@@ -761,7 +767,7 @@ TEST_P(QuicDataWriterTest, VarInt2Layout) {
// are always encoded big endian...
memset(buffer, 0, sizeof(buffer));
QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
- Endianness::NETWORK_BYTE_ORDER);
+ quiche::Endianness::NETWORK_BYTE_ORDER);
EXPECT_TRUE(writer.WriteVarInt62(0x3647));
EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 0)),
(0x36 + 0x40)); // 0x40 for encoding
@@ -777,7 +783,7 @@ TEST_P(QuicDataWriterTest, VarInt1Layout) {
// is correct. Bytes are always encoded big endian...
memset(buffer, 0, sizeof(buffer));
QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
- Endianness::NETWORK_BYTE_ORDER);
+ quiche::Endianness::NETWORK_BYTE_ORDER);
EXPECT_TRUE(writer.WriteVarInt62(0x3f));
EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 0)), 0x3f);
}
@@ -883,7 +889,7 @@ TEST_P(QuicDataWriterTest, MultiVarInt8) {
char buffer[8 * kMultiVarCount];
memset(buffer, 0, sizeof(buffer));
QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
- Endianness::NETWORK_BYTE_ORDER);
+ quiche::Endianness::NETWORK_BYTE_ORDER);
// Put N values into the buffer. Adding i to the value ensures that
// each value is different so we can detect if we overwrite values,
// or read the same value over and over.
@@ -897,7 +903,8 @@ TEST_P(QuicDataWriterTest, MultiVarInt8) {
// Now we should be able to read out the N values that were
// successfully encoded.
- QuicDataReader reader(buffer, sizeof(buffer), Endianness::NETWORK_BYTE_ORDER);
+ QuicDataReader reader(buffer, sizeof(buffer),
+ quiche::Endianness::NETWORK_BYTE_ORDER);
for (int i = 0; i < kMultiVarCount; i++) {
EXPECT_TRUE(reader.ReadVarInt62(&test_val));
EXPECT_EQ(test_val, (UINT64_C(0x3142f3e4d5c6b7a8) + i));
@@ -912,7 +919,7 @@ TEST_P(QuicDataWriterTest, MultiVarInt4) {
char buffer[4 * kMultiVarCount];
memset(buffer, 0, sizeof(buffer));
QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
- Endianness::NETWORK_BYTE_ORDER);
+ quiche::Endianness::NETWORK_BYTE_ORDER);
// Put N values into the buffer. Adding i to the value ensures that
// each value is different so we can detect if we overwrite values,
// or read the same value over and over.
@@ -926,7 +933,8 @@ TEST_P(QuicDataWriterTest, MultiVarInt4) {
// Now we should be able to read out the N values that were
// successfully encoded.
- QuicDataReader reader(buffer, sizeof(buffer), Endianness::NETWORK_BYTE_ORDER);
+ QuicDataReader reader(buffer, sizeof(buffer),
+ quiche::Endianness::NETWORK_BYTE_ORDER);
for (int i = 0; i < kMultiVarCount; i++) {
EXPECT_TRUE(reader.ReadVarInt62(&test_val));
EXPECT_EQ(test_val, (UINT64_C(0x3142f3e4) + i));
@@ -941,7 +949,7 @@ TEST_P(QuicDataWriterTest, MultiVarInt2) {
char buffer[2 * kMultiVarCount];
memset(buffer, 0, sizeof(buffer));
QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
- Endianness::NETWORK_BYTE_ORDER);
+ quiche::Endianness::NETWORK_BYTE_ORDER);
// Put N values into the buffer. Adding i to the value ensures that
// each value is different so we can detect if we overwrite values,
// or read the same value over and over.
@@ -955,7 +963,8 @@ TEST_P(QuicDataWriterTest, MultiVarInt2) {
// Now we should be able to read out the N values that were
// successfully encoded.
- QuicDataReader reader(buffer, sizeof(buffer), Endianness::NETWORK_BYTE_ORDER);
+ QuicDataReader reader(buffer, sizeof(buffer),
+ quiche::Endianness::NETWORK_BYTE_ORDER);
for (int i = 0; i < kMultiVarCount; i++) {
EXPECT_TRUE(reader.ReadVarInt62(&test_val));
EXPECT_EQ(test_val, (UINT64_C(0x3142) + i));
@@ -970,7 +979,7 @@ TEST_P(QuicDataWriterTest, MultiVarInt1) {
char buffer[1 * kMultiVarCount];
memset(buffer, 0, sizeof(buffer));
QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
- Endianness::NETWORK_BYTE_ORDER);
+ quiche::Endianness::NETWORK_BYTE_ORDER);
// Put N values into the buffer. Adding i to the value ensures that
// each value is different so we can detect if we overwrite values,
// or read the same value over and over. &0xf ensures we do not
@@ -985,7 +994,8 @@ TEST_P(QuicDataWriterTest, MultiVarInt1) {
// Now we should be able to read out the N values that were
// successfully encoded.
- QuicDataReader reader(buffer, sizeof(buffer), Endianness::NETWORK_BYTE_ORDER);
+ QuicDataReader reader(buffer, sizeof(buffer),
+ quiche::Endianness::NETWORK_BYTE_ORDER);
for (int i = 0; i < kMultiVarCount; i++) {
EXPECT_TRUE(reader.ReadVarInt62(&test_val));
EXPECT_EQ(test_val, (UINT64_C(0x30) + (i & 0xf)));
@@ -999,7 +1009,7 @@ TEST_P(QuicDataWriterTest, VarIntFixedLength) {
char buffer[90];
memset(buffer, 0, sizeof(buffer));
QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
- Endianness::NETWORK_BYTE_ORDER);
+ quiche::Endianness::NETWORK_BYTE_ORDER);
writer.WriteVarInt62(1, VARIABLE_LENGTH_INTEGER_LENGTH_1);
writer.WriteVarInt62(1, VARIABLE_LENGTH_INTEGER_LENGTH_2);
@@ -1027,7 +1037,8 @@ TEST_P(QuicDataWriterTest, VarIntFixedLength) {
writer.WriteVarInt62(1073741824, VARIABLE_LENGTH_INTEGER_LENGTH_8);
- QuicDataReader reader(buffer, sizeof(buffer), Endianness::NETWORK_BYTE_ORDER);
+ QuicDataReader reader(buffer, sizeof(buffer),
+ quiche::Endianness::NETWORK_BYTE_ORDER);
uint64_t test_val = 0;
for (int i = 0; i < 4; ++i) {
@@ -1071,10 +1082,11 @@ void EncodeDecodeStreamId(uint64_t value_in, bool expected_decode_result) {
// Encode the given Stream ID.
QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
- Endianness::NETWORK_BYTE_ORDER);
+ quiche::Endianness::NETWORK_BYTE_ORDER);
EXPECT_TRUE(writer.WriteVarInt62(value_in));
- QuicDataReader reader(buffer, sizeof(buffer), Endianness::NETWORK_BYTE_ORDER);
+ QuicDataReader reader(buffer, sizeof(buffer),
+ quiche::Endianness::NETWORK_BYTE_ORDER);
QuicStreamId received_stream_id;
bool read_result = reader.ReadVarIntU32(&received_stream_id);
EXPECT_EQ(expected_decode_result, read_result);
@@ -1124,28 +1136,28 @@ TEST_P(QuicDataWriterTest, WriteRandomBytes) {
TEST_P(QuicDataWriterTest, PeekVarInt62Length) {
// In range [0, 63], variable length should be 1 byte.
char buffer[20];
- QuicDataWriter writer(20, buffer, NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(20, buffer, quiche::NETWORK_BYTE_ORDER);
EXPECT_TRUE(writer.WriteVarInt62(50));
- QuicDataReader reader(buffer, 20, NETWORK_BYTE_ORDER);
+ QuicDataReader reader(buffer, 20, quiche::NETWORK_BYTE_ORDER);
EXPECT_EQ(1, reader.PeekVarInt62Length());
// In range (63-16383], variable length should be 2 byte2.
char buffer2[20];
- QuicDataWriter writer2(20, buffer2, NETWORK_BYTE_ORDER);
+ QuicDataWriter writer2(20, buffer2, quiche::NETWORK_BYTE_ORDER);
EXPECT_TRUE(writer2.WriteVarInt62(100));
- QuicDataReader reader2(buffer2, 20, NETWORK_BYTE_ORDER);
+ QuicDataReader reader2(buffer2, 20, quiche::NETWORK_BYTE_ORDER);
EXPECT_EQ(2, reader2.PeekVarInt62Length());
// In range (16383, 1073741823], variable length should be 4 bytes.
char buffer3[20];
- QuicDataWriter writer3(20, buffer3, NETWORK_BYTE_ORDER);
+ QuicDataWriter writer3(20, buffer3, quiche::NETWORK_BYTE_ORDER);
EXPECT_TRUE(writer3.WriteVarInt62(20000));
- QuicDataReader reader3(buffer3, 20, NETWORK_BYTE_ORDER);
+ QuicDataReader reader3(buffer3, 20, quiche::NETWORK_BYTE_ORDER);
EXPECT_EQ(4, reader3.PeekVarInt62Length());
// In range (1073741823, 4611686018427387903], variable length should be 8
// bytes.
char buffer4[20];
- QuicDataWriter writer4(20, buffer4, NETWORK_BYTE_ORDER);
+ QuicDataWriter writer4(20, buffer4, quiche::NETWORK_BYTE_ORDER);
EXPECT_TRUE(writer4.WriteVarInt62(2000000000));
- QuicDataReader reader4(buffer4, 20, NETWORK_BYTE_ORDER);
+ QuicDataReader reader4(buffer4, 20, quiche::NETWORK_BYTE_ORDER);
EXPECT_EQ(8, reader4.PeekVarInt62Length());
}
@@ -1171,7 +1183,7 @@ TEST_P(QuicDataWriterTest, ValidU32) {
char buffer[1024];
memset(buffer, 0, sizeof(buffer));
QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
- Endianness::NETWORK_BYTE_ORDER);
+ quiche::Endianness::NETWORK_BYTE_ORDER);
QuicDataReader reader(buffer, sizeof(buffer));
const QuicStreamCount write_stream_count = 0xffeeddcc;
EXPECT_TRUE(writer.WriteVarInt62(write_stream_count));
@@ -1184,7 +1196,7 @@ TEST_P(QuicDataWriterTest, InvalidU32) {
char buffer[1024];
memset(buffer, 0, sizeof(buffer));
QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
- Endianness::NETWORK_BYTE_ORDER);
+ quiche::Endianness::NETWORK_BYTE_ORDER);
QuicDataReader reader(buffer, sizeof(buffer));
EXPECT_TRUE(writer.WriteVarInt62(UINT64_C(0x1ffeeddcc)));
QuicStreamCount read_stream_count = 123456;
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 acc5cb3bbdb..a1adda4c1b6 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
@@ -135,10 +135,7 @@ class StatelessConnectionTerminator {
creator_(server_connection_id, &framer_, &collector_),
time_wait_list_manager_(time_wait_list_manager) {
framer_.set_data_producer(&collector_);
- if (framer_.framer_doesnt_create_initial_encrypter() ||
- version.UsesInitialObfuscators()) {
- framer_.SetInitialObfuscators(server_connection_id);
- }
+ framer_.SetInitialObfuscators(server_connection_id);
}
~StatelessConnectionTerminator() {
@@ -179,7 +176,7 @@ class StatelessConnectionTerminator {
framer_.transport_version(), error_code, error_details,
/*transport_close_frame_type=*/0);
- if (!creator_.AddSavedFrame(QuicFrame(frame), NOT_RETRANSMISSION)) {
+ if (!creator_.AddFrame(QuicFrame(frame), NOT_RETRANSMISSION)) {
QUIC_BUG << "Unable to add frame to an empty packet";
delete frame;
return;
@@ -454,12 +451,10 @@ bool QuicDispatcher::MaybeDispatchPacket(
return true;
}
- if (GetQuicReloadableFlag(quic_donot_process_small_initial_packets) &&
- crypto_config()->validate_chlo_size() &&
+ if (crypto_config()->validate_chlo_size() &&
packet_info.form == IETF_QUIC_LONG_HEADER_PACKET &&
packet_info.long_packet_type == INITIAL &&
packet_info.packet.length() < kMinClientInitialPacketLength) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_donot_process_small_initial_packets);
StatelessConnectionTerminator terminator(
packet_info.destination_connection_id, packet_info.version,
helper_.get(), time_wait_list_manager_.get());
@@ -530,8 +525,6 @@ void QuicDispatcher::ProcessHeader(ReceivedPacketInfo* packet_info) {
QuicDispatcher::QuicPacketFate QuicDispatcher::ValidityChecks(
const ReceivedPacketInfo& packet_info) {
if (!packet_info.version_flag) {
- if (GetQuicReloadableFlag(quic_reply_to_old_android_conformance_test)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_reply_to_old_android_conformance_test);
// The Android network conformance test contains a UDP test that sends a
// 12-byte packet with the following format:
// - 0x0c (public flags: 8-byte connection ID, 1-byte packet number)
@@ -559,17 +552,12 @@ QuicDispatcher::QuicPacketFate QuicDispatcher::ValidityChecks(
/*ietf_quic=*/false, GetPerPacketContext());
return kFateDrop;
}
- }
QUIC_DLOG(INFO)
<< "Packet without version arrived for unknown connection ID "
<< packet_info.destination_connection_id;
- if (GetQuicReloadableFlag(quic_reject_unprocessable_packets_statelessly)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_reject_unprocessable_packets_statelessly);
- MaybeResetPacketsWithNoVersion(packet_info);
- return kFateDrop;
- }
- return kFateTimeWait;
+ MaybeResetPacketsWithNoVersion(packet_info);
+ return kFateDrop;
}
// Let the connection parse and validate packet number.
@@ -586,7 +574,7 @@ void QuicDispatcher::CleanUpSession(SessionMap::iterator it,
!connection->termination_packets()->empty()) {
action = QuicTimeWaitListManager::SEND_TERMINATION_PACKETS;
} else {
- if (!connection->IsHandshakeConfirmed()) {
+ if (!connection->IsHandshakeComplete()) {
if (!VersionHasIetfInvariantHeader(connection->transport_version())) {
QUIC_CODE_COUNT(gquic_add_to_time_wait_list_with_handshake_failed);
} else {
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 abcd4f2f733..7dbdea65339 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
@@ -34,9 +34,10 @@ class QuicDispatcherPeer;
class QuicConfig;
class QuicCryptoServerConfig;
-class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
- public ProcessPacketInterface,
- public QuicBufferedPacketStore::VisitorInterface {
+class QUIC_NO_EXPORT QuicDispatcher
+ : public QuicTimeWaitListManager::Visitor,
+ public ProcessPacketInterface,
+ public QuicBufferedPacketStore::VisitorInterface {
public:
// Ideally we'd have a linked_hash_set: the boolean is unused.
typedef QuicLinkedHashMap<QuicBlockedWriterInterface*, bool> WriteBlockedList;
@@ -313,11 +314,6 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
// connection ID according to the packet's size.
void MaybeResetPacketsWithNoVersion(const ReceivedPacketInfo& packet_info);
- void set_new_sessions_allowed_per_event_loop(
- int16_t new_sessions_allowed_per_event_loop) {
- new_sessions_allowed_per_event_loop_ = new_sessions_allowed_per_event_loop;
- }
-
const QuicConfig* config_;
const QuicCryptoServerConfig* crypto_config_;
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 3240ceb2557..896438a2b73 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
@@ -417,7 +417,7 @@ class QuicDispatcherTest : public QuicTest {
TEST_F(QuicDispatcherTest, TlsClientHelloCreatesSession) {
if (!QuicVersionUsesCryptoFrames(
CurrentSupportedVersions().front().transport_version)) {
- // TLS is only supported in versions 47 and greater.
+ // TLS is only supported in versions with crypto frames.
return;
}
SetQuicReloadableFlag(quic_supports_tls_handshake, true);
@@ -684,23 +684,14 @@ TEST_F(QuicDispatcherTest, NoVersionPacketToTimeWaitListManager) {
// list manager.
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, QuicStringPiece("hq"), _))
.Times(0);
- if (GetQuicReloadableFlag(quic_reject_unprocessable_packets_statelessly)) {
- EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, _, connection_id, _, _))
- .Times(0);
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(_, _, _, _, _))
- .Times(0);
- EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
- .Times(1);
- } else {
- EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, _, connection_id, _, _))
- .Times(1);
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(_, _, _, _, _))
- .Times(1);
- }
+ EXPECT_CALL(*time_wait_list_manager_,
+ ProcessPacket(_, _, connection_id, _, _))
+ .Times(0);
+ EXPECT_CALL(*time_wait_list_manager_,
+ AddConnectionIdToTimeWait(_, _, _, _, _))
+ .Times(0);
+ EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
+ .Times(1);
ProcessPacket(client_address, connection_id, false, SerializeCHLO());
}
@@ -714,29 +705,16 @@ TEST_F(QuicDispatcherTest,
char valid_size_packet[23] = {0x70, 0xa7, 0x02, 0x6c};
QuicReceivedPacket packet2(valid_size_packet, 23, QuicTime::Zero());
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
- if (GetQuicReloadableFlag(quic_reject_unprocessable_packets_statelessly)) {
- EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
- .Times(0);
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(_, _, _, _, _))
- .Times(0);
- } else {
- EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
- .Times(2);
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(_, _, _, _, _))
- .Times(2);
- }
- if (GetQuicReloadableFlag(quic_reject_unprocessable_packets_statelessly)) {
- // Verify small packet is silently dropped.
- EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
- .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(_, _, _, _, _))
+ .Times(0);
dispatcher_->ProcessPacket(server_address_, client_address, packet);
- if (GetQuicReloadableFlag(quic_reject_unprocessable_packets_statelessly)) {
- EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
- .Times(1);
- }
+ EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
+ .Times(1);
dispatcher_->ProcessPacket(server_address_, client_address, packet2);
}
@@ -886,8 +864,8 @@ TEST_F(QuicDispatcherTest, ProcessPacketWithZeroPort) {
}
TEST_F(QuicDispatcherTest, ProcessPacketWithInvalidShortInitialConnectionId) {
- // Enable v47 otherwise we cannot create a packet with a short connection ID.
- SetQuicReloadableFlag(quic_enable_version_47, true);
+ // Enable a version that supports connection IDs of length different than 8.
+ SetQuicReloadableFlag(quic_enable_version_50, true);
CreateTimeWaitListManager();
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
@@ -931,12 +909,8 @@ TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) {
}
TEST_F(QuicDispatcherTest, SupportedTransportVersionsChangeInFlight) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
"Supported versions out of sync");
- SetQuicReloadableFlag(quic_disable_version_39, false);
- SetQuicReloadableFlag(quic_enable_version_47, true);
- SetQuicReloadableFlag(quic_enable_version_48_2, true);
- SetQuicReloadableFlag(quic_enable_version_49, true);
SetQuicReloadableFlag(quic_enable_version_50, true);
SetQuicReloadableFlag(quic_enable_version_99, true);
@@ -955,73 +929,52 @@ TEST_F(QuicDispatcherTest, SupportedTransportVersionsChangeInFlight) {
SetQuicReloadableFlag(quic_enable_version_50, true);
VerifyVersionSupported(
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50));
-
- // Turn off version 49.
- SetQuicReloadableFlag(quic_enable_version_49, false);
- VerifyVersionNotSupported(
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_49));
-
- // Turn on version 49.
- SetQuicReloadableFlag(quic_enable_version_49, true);
- VerifyVersionSupported(
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_49));
-
- // Turn off version 48.
- SetQuicReloadableFlag(quic_enable_version_48_2, false);
- VerifyVersionNotSupported(
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48));
-
- // Turn on version 48.
- SetQuicReloadableFlag(quic_enable_version_48_2, true);
- VerifyVersionSupported(
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48));
-
- // Turn off version 47.
- SetQuicReloadableFlag(quic_enable_version_47, false);
- VerifyVersionNotSupported(
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47));
-
- // Turn on version 47.
- SetQuicReloadableFlag(quic_enable_version_47, true);
- VerifyVersionSupported(
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47));
-
- // Turn off version 39.
- SetQuicReloadableFlag(quic_disable_version_39, true);
- VerifyVersionNotSupported(
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39));
-
- // Turn on version 39.
- SetQuicReloadableFlag(quic_disable_version_39, false);
- VerifyVersionSupported(
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39));
}
TEST_F(QuicDispatcherTest, RejectDeprecatedVersionsWithVersionNegotiation) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
"Please add deprecated versions to this test");
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
CreateTimeWaitListManager();
- char packet45[kMinPacketSizeForVersionNegotiation] = {
- 0xC0, 'Q', '0', '4', '5', /*connection ID length byte*/ 0x50};
- QuicReceivedPacket packet(packet45, kMinPacketSizeForVersionNegotiation,
- QuicTime::Zero());
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
- EXPECT_CALL(*time_wait_list_manager_,
- SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
- .Times(1);
- dispatcher_->ProcessPacket(server_address_, client_address, packet);
+ {
+ char packet47[kMinPacketSizeForVersionNegotiation] = {
+ 0xC0, 'Q', '0', '4', '7', /*connection ID length byte*/ 0x50};
+ QuicReceivedPacket received_packet47(
+ packet47, kMinPacketSizeForVersionNegotiation, QuicTime::Zero());
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
+ EXPECT_CALL(*time_wait_list_manager_,
+ SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
+ .Times(1);
+ dispatcher_->ProcessPacket(server_address_, client_address,
+ received_packet47);
+ }
- char packet44[kMinPacketSizeForVersionNegotiation] = {
- 0xFF, 'Q', '0', '4', '4', /*connection ID length byte*/ 0x50};
- QuicReceivedPacket packet2(packet44, kMinPacketSizeForVersionNegotiation,
- QuicTime::Zero());
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
- EXPECT_CALL(*time_wait_list_manager_,
- SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
- .Times(1);
- dispatcher_->ProcessPacket(server_address_, client_address, packet2);
+ {
+ char packet45[kMinPacketSizeForVersionNegotiation] = {
+ 0xC0, 'Q', '0', '4', '5', /*connection ID length byte*/ 0x50};
+ QuicReceivedPacket received_packet45(
+ packet45, kMinPacketSizeForVersionNegotiation, QuicTime::Zero());
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
+ EXPECT_CALL(*time_wait_list_manager_,
+ SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
+ .Times(1);
+ dispatcher_->ProcessPacket(server_address_, client_address,
+ received_packet45);
+ }
+
+ {
+ char packet44[kMinPacketSizeForVersionNegotiation] = {
+ 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(*time_wait_list_manager_,
+ SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
+ .Times(1);
+ dispatcher_->ProcessPacket(server_address_, client_address,
+ received_packet44);
+ }
}
TEST_F(QuicDispatcherTest, VersionNegotiationProbeOld) {
@@ -1196,8 +1149,6 @@ TEST_F(QuicDispatcherTest, VersionNegotiationProbeEndToEnd) {
TEST_F(QuicDispatcherTest, AndroidConformanceTestOld) {
// TODO(b/139691956) Remove this test once the workaround is removed.
- // This test requires the workaround behind this flag to pass.
- SetQuicReloadableFlag(quic_reply_to_old_android_conformance_test, true);
SavingWriter* saving_writer = new SavingWriter();
// dispatcher_ takes ownership of saving_writer.
QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
@@ -1242,63 +1193,9 @@ TEST_F(QuicDispatcherTest, AndroidConformanceTestOld) {
sizeof(connection_id_bytes));
}
-TEST_F(QuicDispatcherTest, AndroidConformanceTestNewWithWorkaround) {
- // TODO(b/139691956) Remove this test once the workaround is removed.
- // This test doesn't need the workaround but we make sure that it passes even
- // when the flag is true, also see AndroidConformanceTest below.
- SetQuicReloadableFlag(quic_reply_to_old_android_conformance_test, true);
- SavingWriter* saving_writer = new SavingWriter();
- // dispatcher_ takes ownership of saving_writer.
- QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
-
- QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
- saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
- &mock_alarm_factory_);
- // dispatcher_ takes ownership of time_wait_list_manager.
- QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
- time_wait_list_manager);
- // clang-format off
- static const unsigned char packet[1200] = {
- // Android UDP network conformance test packet as it was after this change:
- // https://android-review.googlesource.com/c/platform/cts/+/1104285
- 0x0d, // public flags: version, 8-byte connection ID, 1-byte packet number
- 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, // 8-byte connection ID
- 0xaa, 0xda, 0xca, 0xaa, // reserved-space version number
- 0x01, // 1-byte packet number
- 0x00, // private flags
- 0x07, // PING frame
- };
- // clang-format on
-
- QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet),
- sizeof(packet), false);
- std::unique_ptr<QuicReceivedPacket> received_packet(
- ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
- EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
-
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
- ASSERT_EQ(1u, saving_writer->packets()->size());
-
- // The Android UDP network conformance test directly checks that bytes 1-9
- // of the response match the connection ID that was sent.
- static const char connection_id_bytes[] = {0x71, 0x72, 0x73, 0x74,
- 0x75, 0x76, 0x77, 0x78};
- ASSERT_GE((*(saving_writer->packets()))[0]->length(),
- 1u + sizeof(connection_id_bytes));
- test::CompareCharArraysWithHexError(
- "response connection ID", &(*(saving_writer->packets()))[0]->data()[1],
- sizeof(connection_id_bytes), connection_id_bytes,
- sizeof(connection_id_bytes));
-}
-
TEST_F(QuicDispatcherTest, AndroidConformanceTest) {
// WARNING: do not remove or modify this test without making sure that we
// still have adequate coverage for the Android conformance test.
-
- // Set the flag to false to make sure this test passes even when the
- // workaround is disabled.
- SetQuicReloadableFlag(quic_reply_to_old_android_conformance_test, false);
SavingWriter* saving_writer = new SavingWriter();
// dispatcher_ takes ownership of saving_writer.
QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
@@ -1345,7 +1242,6 @@ TEST_F(QuicDispatcherTest, AndroidConformanceTest) {
}
TEST_F(QuicDispatcherTest, DoNotProcessSmallPacket) {
- SetQuicReloadableFlag(quic_donot_process_small_initial_packets, true);
CreateTimeWaitListManager();
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
@@ -2161,8 +2057,8 @@ TEST_F(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) {
/*connection_id=*/TestConnectionId(1)));
// CHLO on connection 1 should still be buffered.
- ProcessPacket(client_addr_, /*connection_id=*/TestConnectionId(1), true,
- SerializeFullCHLO());
+ ProcessPacket(client_addr_, /*server_connection_id=*/TestConnectionId(1),
+ true, SerializeFullCHLO());
EXPECT_TRUE(store->HasChloForConnection(
/*connection_id=*/TestConnectionId(1)));
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_epoll_alarm_factory.h b/chromium/net/third_party/quiche/src/quic/core/quic_epoll_alarm_factory.h
index fc9b45c393f..5c04e3d4cd5 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_epoll_alarm_factory.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_epoll_alarm_factory.h
@@ -13,7 +13,7 @@
namespace quic {
// Creates alarms that use the supplied EpollServer for timing and firing.
-class QuicEpollAlarmFactory : public QuicAlarmFactory {
+class QUIC_EXPORT_PRIVATE QuicEpollAlarmFactory : public QuicAlarmFactory {
public:
explicit QuicEpollAlarmFactory(QuicEpollServer* eps);
QuicEpollAlarmFactory(const QuicEpollAlarmFactory&) = delete;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h b/chromium/net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h
index 7041454f907..ce68cfbb756 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h
@@ -27,7 +27,8 @@ class QuicRandom;
enum class QuicAllocator { SIMPLE, BUFFER_POOL };
-class QuicEpollConnectionHelper : public QuicConnectionHelperInterface {
+class QUIC_EXPORT_PRIVATE QuicEpollConnectionHelper
+ : public QuicConnectionHelperInterface {
public:
QuicEpollConnectionHelper(QuicEpollServer* eps, QuicAllocator allocator);
QuicEpollConnectionHelper(const QuicEpollConnectionHelper&) = delete;
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 b1e8ed298f9..ae17f099a96 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
@@ -160,6 +160,11 @@ const char* QuicErrorCodeToString(QuicErrorCode error) {
QUIC_WINDOW_UPDATE_RECEIVED_ON_READ_UNIDIRECTIONAL_STREAM);
RETURN_STRING_LITERAL(QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES);
RETURN_STRING_LITERAL(QUIC_TRANSPORT_INVALID_CLIENT_INDICATION);
+ RETURN_STRING_LITERAL(QUIC_QPACK_DECOMPRESSION_FAILED);
+ RETURN_STRING_LITERAL(QUIC_QPACK_ENCODER_STREAM_ERROR);
+ RETURN_STRING_LITERAL(QUIC_QPACK_DECODER_STREAM_ERROR);
+ RETURN_STRING_LITERAL(QUIC_STREAM_DATA_BEYOND_CLOSE_OFFSET);
+ RETURN_STRING_LITERAL(QUIC_STREAM_MULTIPLE_OFFSET);
RETURN_STRING_LITERAL(QUIC_LAST_ERROR);
// Intentionally have no default case, so we'll break the build
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h b/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h
index ce5c7216b31..b6c2d50ca5f 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
@@ -342,8 +342,19 @@ enum QuicErrorCode {
// QuicTransport received invalid client indication.
QUIC_TRANSPORT_INVALID_CLIENT_INDICATION = 125,
+ // Internal error codes for QPACK errors.
+ QUIC_QPACK_DECOMPRESSION_FAILED = 126,
+ QUIC_QPACK_ENCODER_STREAM_ERROR = 127,
+ QUIC_QPACK_DECODER_STREAM_ERROR = 128,
+
+ // Received stream data beyond close offset.
+ QUIC_STREAM_DATA_BEYOND_CLOSE_OFFSET = 129,
+
+ // Received multiple close offset.
+ QUIC_STREAM_MULTIPLE_OFFSET = 130,
+
// No error. Used as bound while iterating.
- QUIC_LAST_ERROR = 126,
+ QUIC_LAST_ERROR = 131,
};
// QuicErrorCodes is encoded as four octets on-the-wire when doing Google QUIC,
// or a varint62 when doing IETF QUIC. Ensure that its value does not exceed
@@ -357,7 +368,15 @@ QUIC_EXPORT_PRIVATE const char* QuicRstStreamErrorCodeToString(
QuicRstStreamErrorCode error);
// Returns the name of the QuicErrorCode as a char*
-QUIC_EXPORT const char* QuicErrorCodeToString(QuicErrorCode error);
+QUIC_EXPORT_PRIVATE const char* QuicErrorCodeToString(QuicErrorCode error);
+
+// Wire values for QPACK errors.
+// https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#error-code-registration
+enum QuicHttpQpackErrorCode {
+ IETF_QUIC_HTTP_QPACK_DECOMPRESSION_FAILED = 0x200,
+ IETF_QUIC_HTTP_QPACK_ENCODER_STREAM_ERROR = 0x201,
+ IETF_QUIC_HTTP_QPACK_DECODER_STREAM_ERROR = 0x202
+};
QUIC_EXPORT_PRIVATE inline std::string HistogramEnumString(
QuicErrorCode enum_value) {
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 2d4d4a5af82..c5708b94995 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
@@ -148,14 +148,6 @@ uint64_t ClosestTo(uint64_t target, uint64_t a, uint64_t b) {
return (Delta(target, a) < Delta(target, b)) ? a : b;
}
-uint64_t PacketNumberIntervalLength(
- const QuicInterval<QuicPacketNumber>& interval) {
- if (interval.Empty()) {
- return 0u;
- }
- return interval.max() - interval.min();
-}
-
QuicPacketNumberLength ReadSequenceNumberLength(uint8_t flags) {
switch (flags & PACKET_FLAGS_8BYTE_PACKET) {
case PACKET_FLAGS_8BYTE_PACKET:
@@ -424,22 +416,12 @@ QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions,
expected_server_connection_id_length),
expected_client_connection_id_length_(0),
supports_multiple_packet_number_spaces_(false),
- framer_doesnt_create_initial_encrypter_(
- GetQuicReloadableFlag(quic_framer_doesnt_create_initial_encrypter)),
last_written_packet_number_length_(0),
peer_ack_delay_exponent_(kDefaultAckDelayExponent),
local_ack_delay_exponent_(kDefaultAckDelayExponent),
current_received_frame_type_(0) {
DCHECK(!supported_versions.empty());
version_ = supported_versions_[0];
- if (!framer_doesnt_create_initial_encrypter_) {
- decrypter_[ENCRYPTION_INITIAL] =
- std::make_unique<NullDecrypter>(perspective);
- encrypter_[ENCRYPTION_INITIAL] =
- std::make_unique<NullEncrypter>(perspective);
- } else {
- QUIC_RELOADABLE_FLAG_COUNT(quic_framer_doesnt_create_initial_encrypter);
- }
}
QuicFramer::~QuicFramer() {}
@@ -449,7 +431,7 @@ size_t QuicFramer::GetMinStreamFrameSize(QuicTransportVersion version,
QuicStreamId stream_id,
QuicStreamOffset offset,
bool last_frame_in_packet,
- QuicPacketLength data_length) {
+ size_t data_length) {
if (VersionHasIetfQuicFrames(version)) {
return kQuicFrameTypeSize + QuicDataWriter::GetVarInt62Len(stream_id) +
(last_frame_in_packet
@@ -564,13 +546,11 @@ size_t QuicFramer::GetWindowUpdateFrameSize(
}
if (frame.stream_id == QuicUtils::GetInvalidStreamId(version)) {
// Frame would be a MAX DATA frame, which has only a Maximum Data field.
- return kQuicFrameTypeSize +
- QuicDataWriter::GetVarInt62Len(frame.byte_offset);
+ return kQuicFrameTypeSize + QuicDataWriter::GetVarInt62Len(frame.max_data);
}
// Frame would be MAX STREAM DATA, has Maximum Stream Data and Stream ID
// fields.
- return kQuicFrameTypeSize +
- QuicDataWriter::GetVarInt62Len(frame.byte_offset) +
+ return kQuicFrameTypeSize + QuicDataWriter::GetVarInt62Len(frame.max_data) +
QuicDataWriter::GetVarInt62Len(frame.stream_id);
}
@@ -1275,33 +1255,26 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildVersionNegotiationPacket(
bool use_length_prefix,
const ParsedQuicVersionVector& versions) {
ParsedQuicVersionVector wire_versions = versions;
- if (!GetQuicReloadableFlag(quic_version_negotiation_grease)) {
- if (wire_versions.empty()) {
- wire_versions = {QuicVersionReservedForNegotiation()};
- }
+ // Add a version reserved for negotiation as suggested by the
+ // "Using Reserved Versions" section of draft-ietf-quic-transport.
+ if (wire_versions.empty()) {
+ // Ensure that version negotiation packets we send have at least two
+ // versions. This guarantees that, under all circumstances, all QUIC
+ // packets we send are at least 14 bytes long.
+ wire_versions = {QuicVersionReservedForNegotiation(),
+ QuicVersionReservedForNegotiation()};
} else {
- // Add a version reserved for negotiation as suggested by the
- // "Using Reserved Versions" section of draft-ietf-quic-transport.
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_version_negotiation_grease, 1, 2);
- if (wire_versions.empty()) {
- // Ensure that version negotiation packets we send have at least two
- // versions. This guarantees that, under all circumstances, all QUIC
- // packets we send are at least 14 bytes long.
- wire_versions = {QuicVersionReservedForNegotiation(),
- QuicVersionReservedForNegotiation()};
- } else {
- // This is not uniformely distributed but is acceptable since no security
- // depends on this randomness.
- size_t version_index = 0;
- const bool disable_randomness =
- GetQuicFlag(FLAGS_quic_disable_version_negotiation_grease_randomness);
- if (!disable_randomness) {
- version_index = QuicRandom::GetInstance()->RandUint64() %
- (wire_versions.size() + 1);
- }
- wire_versions.insert(wire_versions.begin() + version_index,
- QuicVersionReservedForNegotiation());
- }
+ // This is not uniformely distributed but is acceptable since no security
+ // depends on this randomness.
+ size_t version_index = 0;
+ const bool disable_randomness =
+ GetQuicFlag(FLAGS_quic_disable_version_negotiation_grease_randomness);
+ if (!disable_randomness) {
+ version_index =
+ QuicRandom::GetInstance()->RandUint64() % (wire_versions.size() + 1);
+ }
+ wire_versions.insert(wire_versions.begin() + version_index,
+ QuicVersionReservedForNegotiation());
}
if (ietf_quic) {
return BuildIetfVersionNegotiationPacket(
@@ -1322,7 +1295,6 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildVersionNegotiationPacket(
uint8_t flags = static_cast<uint8_t>(
PACKET_PUBLIC_FLAGS_VERSION | PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID |
- // TODO(rch): Remove this QUIC_VERSION_32 is retired.
PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID_OLD);
if (!writer.WriteUInt8(flags)) {
return nullptr;
@@ -1699,12 +1671,11 @@ bool QuicFramer::ProcessIetfDataPacket(QuicDataReader* encrypted_reader,
return true;
}
if (hp_removal_failed) {
- const EncryptionLevel decryption_level = GetEncryptionLevel(*header);
- const bool has_decryption_key =
- decrypter_[decryption_level] != nullptr;
- visitor_->OnUndecryptablePacket(
- QuicEncryptedPacket(encrypted_reader->FullPayload()),
- decryption_level, has_decryption_key);
+ const EncryptionLevel decryption_level = GetEncryptionLevel(*header);
+ const bool has_decryption_key = decrypter_[decryption_level] != nullptr;
+ visitor_->OnUndecryptablePacket(
+ QuicEncryptedPacket(encrypted_reader->FullPayload()),
+ decryption_level, has_decryption_key);
set_detailed_error("Unable to decrypt header protection.");
return RaiseError(QUIC_DECRYPTION_FAILURE);
}
@@ -1763,12 +1734,12 @@ bool QuicFramer::ProcessIetfDataPacket(QuicDataReader* encrypted_reader,
visitor_->OnAuthenticatedIetfStatelessResetPacket(packet);
return true;
}
- const EncryptionLevel decryption_level = GetEncryptionLevel(*header);
- const bool has_decryption_key = version_.KnowsWhichDecrypterToUse() &&
- decrypter_[decryption_level] != nullptr;
- visitor_->OnUndecryptablePacket(
- QuicEncryptedPacket(encrypted_reader->FullPayload()),
- decryption_level, has_decryption_key);
+ const EncryptionLevel decryption_level = GetEncryptionLevel(*header);
+ const bool has_decryption_key = version_.KnowsWhichDecrypterToUse() &&
+ decrypter_[decryption_level] != nullptr;
+ visitor_->OnUndecryptablePacket(
+ QuicEncryptedPacket(encrypted_reader->FullPayload()), decryption_level,
+ has_decryption_key);
set_detailed_error("Unable to decrypt payload.");
RecordDroppedPacketReason(DroppedPacketReason::DECRYPTION_FAILURE);
return RaiseError(QUIC_DECRYPTION_FAILURE);
@@ -1850,13 +1821,13 @@ bool QuicFramer::ProcessDataPacket(QuicDataReader* encrypted_reader,
EncryptionLevel decrypted_level;
if (!DecryptPayload(encrypted, associated_data, *header, decrypted_buffer,
buffer_length, &decrypted_length, &decrypted_level)) {
- const EncryptionLevel decryption_level = decrypter_level_;
- // This version uses trial decryption so we always report to our visitor
- // that we are not certain we have the correct decryption key.
- const bool has_decryption_key = false;
- visitor_->OnUndecryptablePacket(
- QuicEncryptedPacket(encrypted_reader->FullPayload()),
- decryption_level, has_decryption_key);
+ const EncryptionLevel decryption_level = decrypter_level_;
+ // This version uses trial decryption so we always report to our visitor
+ // that we are not certain we have the correct decryption key.
+ const bool has_decryption_key = false;
+ visitor_->OnUndecryptablePacket(
+ QuicEncryptedPacket(encrypted_reader->FullPayload()), decryption_level,
+ has_decryption_key);
RecordDroppedPacketReason(DroppedPacketReason::DECRYPTION_FAILURE);
set_detailed_error("Unable to decrypt payload.");
return RaiseError(QUIC_DECRYPTION_FAILURE);
@@ -1904,7 +1875,7 @@ bool QuicFramer::ProcessPublicResetPacket(QuicDataReader* reader,
std::unique_ptr<CryptoHandshakeMessage> reset(
CryptoFramer::ParseMessage(reader->ReadRemainingPayload()));
- if (!reset.get()) {
+ if (!reset) {
set_detailed_error("Unable to read reset message.");
RecordDroppedPacketReason(DroppedPacketReason::INVALID_PUBLIC_RESET_PACKET);
return RaiseError(QUIC_INVALID_PUBLIC_RST_PACKET);
@@ -2346,7 +2317,7 @@ QuicFramer::AckFrameInfo QuicFramer::GetAckFrameInfo(
new_ack_info.first_block_length = frame.packets.LastIntervalLength();
auto itr = frame.packets.rbegin();
QuicPacketNumber previous_start = itr->min();
- new_ack_info.max_block_length = PacketNumberIntervalLength(*itr);
+ new_ack_info.max_block_length = itr->Length();
++itr;
// Don't do any more work after getting information for 256 ACK blocks; any
@@ -2359,8 +2330,8 @@ QuicFramer::AckFrameInfo QuicFramer::GetAckFrameInfo(
new_ack_info.num_ack_blocks +=
(total_gap + std::numeric_limits<uint8_t>::max() - 1) /
std::numeric_limits<uint8_t>::max();
- new_ack_info.max_block_length = std::max(
- new_ack_info.max_block_length, PacketNumberIntervalLength(interval));
+ new_ack_info.max_block_length =
+ std::max(new_ack_info.max_block_length, interval.Length());
}
return new_ack_info;
}
@@ -3246,12 +3217,12 @@ bool QuicFramer::ProcessIetfFrameData(QuicDataReader* reader,
}
break;
}
- case IETF_EXTENSION_MESSAGE_NO_LENGTH:
+ case IETF_EXTENSION_MESSAGE_NO_LENGTH_V99:
QUIC_FALLTHROUGH_INTENDED;
- case IETF_EXTENSION_MESSAGE: {
+ case IETF_EXTENSION_MESSAGE_V99: {
QuicMessageFrame message_frame;
if (!ProcessMessageFrame(
- reader, frame_type == IETF_EXTENSION_MESSAGE_NO_LENGTH,
+ reader, frame_type == IETF_EXTENSION_MESSAGE_NO_LENGTH_V99,
&message_frame)) {
return RaiseError(QUIC_INVALID_MESSAGE_DATA);
}
@@ -3685,7 +3656,7 @@ bool QuicFramer::ProcessIetfAckFrame(QuicDataReader* reader,
return false;
}
- if (ack_delay_time_in_us == kVarInt62MaxValue) {
+ if (ack_delay_time_in_us >= (kVarInt62MaxValue >> peer_ack_delay_exponent_)) {
ack_frame->ack_delay_time = QuicTime::Delta::Infinite();
} else {
ack_delay_time_in_us = (ack_delay_time_in_us << peer_ack_delay_exponent_);
@@ -3941,7 +3912,7 @@ bool QuicFramer::ProcessWindowUpdateFrame(QuicDataReader* reader,
return false;
}
- if (!reader->ReadUInt64(&frame->byte_offset)) {
+ if (!reader->ReadUInt64(&frame->max_data)) {
set_detailed_error("Unable to read window byte_offset.");
return false;
}
@@ -5190,8 +5161,8 @@ bool QuicFramer::AppendAckFrameAndTypeByte(const QuicAckFrame& frame,
total_gap -
(num_encoded_gaps - 1) * std::numeric_limits<uint8_t>::max();
// Append the final ACK block with a non-empty size.
- if (!AppendAckBlock(last_gap, ack_block_length,
- PacketNumberIntervalLength(interval), writer)) {
+ if (!AppendAckBlock(last_gap, ack_block_length, interval.Length(),
+ writer)) {
return false;
}
++num_ack_blocks_written;
@@ -5541,7 +5512,7 @@ bool QuicFramer::AppendWindowUpdateFrame(const QuicWindowUpdateFrame& frame,
if (!writer->WriteUInt32(stream_id)) {
return false;
}
- if (!writer->WriteUInt64(frame.byte_offset)) {
+ if (!writer->WriteUInt64(frame.max_data)) {
return false;
}
return true;
@@ -5579,8 +5550,14 @@ bool QuicFramer::AppendPaddingFrame(const QuicPaddingFrame& frame,
bool QuicFramer::AppendMessageFrameAndTypeByte(const QuicMessageFrame& frame,
bool last_frame_in_packet,
QuicDataWriter* writer) {
- uint8_t type_byte = last_frame_in_packet ? IETF_EXTENSION_MESSAGE_NO_LENGTH
- : IETF_EXTENSION_MESSAGE;
+ uint8_t type_byte;
+ if (VersionHasIetfQuicFrames(version_.transport_version)) {
+ type_byte = last_frame_in_packet ? IETF_EXTENSION_MESSAGE_NO_LENGTH_V99
+ : IETF_EXTENSION_MESSAGE_V99;
+ } else {
+ type_byte = last_frame_in_packet ? IETF_EXTENSION_MESSAGE_NO_LENGTH
+ : IETF_EXTENSION_MESSAGE;
+ }
if (!writer->WriteUInt8(type_byte)) {
return false;
}
@@ -5840,7 +5817,7 @@ bool QuicFramer::AppendStopSendingFrame(
// Append/process IETF-Format MAX_DATA Frame
bool QuicFramer::AppendMaxDataFrame(const QuicWindowUpdateFrame& frame,
QuicDataWriter* writer) {
- if (!writer->WriteVarInt62(frame.byte_offset)) {
+ if (!writer->WriteVarInt62(frame.max_data)) {
set_detailed_error("Can not write MAX_DATA byte-offset");
return false;
}
@@ -5850,7 +5827,7 @@ bool QuicFramer::AppendMaxDataFrame(const QuicWindowUpdateFrame& frame,
bool QuicFramer::ProcessMaxDataFrame(QuicDataReader* reader,
QuicWindowUpdateFrame* frame) {
frame->stream_id = QuicUtils::GetInvalidStreamId(transport_version());
- if (!reader->ReadVarInt62(&frame->byte_offset)) {
+ if (!reader->ReadVarInt62(&frame->max_data)) {
set_detailed_error("Can not read MAX_DATA byte-offset");
return false;
}
@@ -5864,7 +5841,7 @@ bool QuicFramer::AppendMaxStreamDataFrame(const QuicWindowUpdateFrame& frame,
set_detailed_error("Can not write MAX_STREAM_DATA stream id");
return false;
}
- if (!writer->WriteVarInt62(frame.byte_offset)) {
+ if (!writer->WriteVarInt62(frame.max_data)) {
set_detailed_error("Can not write MAX_STREAM_DATA byte-offset");
return false;
}
@@ -5877,7 +5854,7 @@ bool QuicFramer::ProcessMaxStreamDataFrame(QuicDataReader* reader,
set_detailed_error("Can not read MAX_STREAM_DATA stream id");
return false;
}
- if (!reader->ReadVarInt62(&frame->byte_offset)) {
+ if (!reader->ReadVarInt62(&frame->max_data)) {
set_detailed_error("Can not read MAX_STREAM_DATA byte-count");
return false;
}
@@ -6256,9 +6233,7 @@ inline bool ParseLongHeaderConnectionIds(
return false;
}
if (!reader->ReadLengthPrefixedConnectionId(source_connection_id)) {
- if (GetQuicReloadableFlag(quic_parse_prox_source_connection_id) &&
- version_label == kProxVersionLabel) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_parse_prox_source_connection_id);
+ if (version_label == kProxVersionLabel) {
// The "PROX" version does not follow the length-prefixed invariants,
// and can therefore attempt to read a payload byte and interpret it
// as the source connection ID length, which could fail to parse.
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 65a0b3becb3..cd2e2c7c438 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
@@ -288,7 +288,7 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
QuicStreamId stream_id,
QuicStreamOffset offset,
bool last_frame_in_packet,
- QuicPacketLength data_length);
+ size_t data_length);
// Returns the overhead of framing a CRYPTO frame with the specific offset and
// data length provided, but not counting the size of the data payload.
static size_t GetMinCryptoFrameSize(QuicStreamOffset offset,
@@ -636,16 +636,12 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
}
uint32_t peer_ack_delay_exponent() const { return peer_ack_delay_exponent_; }
- bool framer_doesnt_create_initial_encrypter() const {
- return framer_doesnt_create_initial_encrypter_;
- }
-
private:
friend class test::QuicFramerPeer;
typedef std::map<QuicPacketNumber, uint8_t> NackRangeMap;
- struct AckFrameInfo {
+ struct QUIC_EXPORT_PRIVATE AckFrameInfo {
AckFrameInfo();
AckFrameInfo(const AckFrameInfo& other);
~AckFrameInfo();
@@ -1056,10 +1052,6 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
// Indicates whether this framer supports multiple packet number spaces.
bool supports_multiple_packet_number_spaces_;
- // Latched value of reloadable flag
- // quic_framer_doesnt_create_initial_encrypter.
- const bool framer_doesnt_create_initial_encrypter_;
-
// 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 8aa96152875..ff9653d3827 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
@@ -365,9 +365,9 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
message_frames_.push_back(
std::make_unique<QuicMessageFrame>(frame.data, frame.message_length));
if (VersionHasIetfQuicFrames(transport_version_)) {
- EXPECT_TRUE(IETF_EXTENSION_MESSAGE_NO_LENGTH ==
+ EXPECT_TRUE(IETF_EXTENSION_MESSAGE_NO_LENGTH_V99 ==
framer_->current_received_frame_type() ||
- IETF_EXTENSION_MESSAGE ==
+ IETF_EXTENSION_MESSAGE_V99 ==
framer_->current_received_frame_type());
} else {
EXPECT_EQ(0u, framer_->current_received_frame_type());
@@ -929,7 +929,7 @@ TEST_P(QuicFramerTest, EmptyPacket) {
char packet[] = {0x00};
QuicEncryptedPacket encrypted(packet, 0, false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_PACKET_HEADER));
}
TEST_P(QuicFramerTest, LargePacket) {
@@ -977,7 +977,7 @@ TEST_P(QuicFramerTest, LargePacket) {
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
// Make sure the correct error is propagated.
- EXPECT_EQ(QUIC_PACKET_TOO_LARGE, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_PACKET_TOO_LARGE));
EXPECT_EQ("Packet too large.", framer_.detailed_error());
}
@@ -1006,7 +1006,7 @@ TEST_P(QuicFramerTest, PacketHeader) {
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_MISSING_PAYLOAD));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
@@ -1032,7 +1032,7 @@ TEST_P(QuicFramerTest, PacketHeader) {
&retry_token, &detailed_error);
EXPECT_FALSE(retry_token_present);
EXPECT_FALSE(use_length_prefix);
- EXPECT_EQ(QUIC_NO_ERROR, error_code);
+ EXPECT_THAT(error_code, IsQuicNoError());
EXPECT_EQ(GOOGLE_QUIC_PACKET, format);
EXPECT_FALSE(version_flag);
EXPECT_EQ(kQuicDefaultConnectionIdLength, destination_connection_id.length());
@@ -1071,7 +1071,7 @@ TEST_P(QuicFramerTest, LongPacketHeader) {
AssemblePacketFromFragments(packet46));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_MISSING_PAYLOAD));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
@@ -1095,7 +1095,7 @@ TEST_P(QuicFramerTest, LongPacketHeader) {
&version_flag, &use_length_prefix, &version_label, &parsed_version,
&destination_connection_id, &source_connection_id, &retry_token_present,
&retry_token, &detailed_error);
- EXPECT_EQ(QUIC_NO_ERROR, error_code);
+ EXPECT_THAT(error_code, IsQuicNoError());
EXPECT_EQ("", detailed_error);
EXPECT_FALSE(retry_token_present);
EXPECT_FALSE(use_length_prefix);
@@ -1175,7 +1175,7 @@ TEST_P(QuicFramerTest, LongPacketHeaderWithBothConnectionIds) {
&version_flag, &use_length_prefix, &version_label, &parsed_version,
&destination_connection_id, &source_connection_id, &retry_token_present,
&retry_token, &detailed_error);
- EXPECT_EQ(QUIC_NO_ERROR, error_code);
+ EXPECT_THAT(error_code, IsQuicNoError());
EXPECT_FALSE(retry_token_present);
EXPECT_EQ(framer_.version().HasLengthPrefixedConnectionIds(),
use_length_prefix);
@@ -1270,7 +1270,7 @@ TEST_P(QuicFramerTest, ParsePublicHeader) {
&parsed_version, &destination_connection_id, &source_connection_id,
&long_packet_type, &retry_token_length_length, &retry_token,
&detailed_error);
- EXPECT_EQ(QUIC_NO_ERROR, parse_error);
+ EXPECT_THAT(parse_error, IsQuicNoError());
EXPECT_EQ("", detailed_error);
EXPECT_EQ(p[0], first_byte);
EXPECT_TRUE(version_present);
@@ -1294,7 +1294,6 @@ TEST_P(QuicFramerTest, ParsePublicHeaderProxBadSourceConnectionIdLength) {
if (!framer_.version().HasLengthPrefixedConnectionIds()) {
return;
}
- SetQuicReloadableFlag(quic_parse_prox_source_connection_id, true);
// clang-format off
unsigned char packet[] = {
// public flags (long header with packet type HANDSHAKE and
@@ -1339,7 +1338,7 @@ TEST_P(QuicFramerTest, ParsePublicHeaderProxBadSourceConnectionIdLength) {
&has_length_prefix, &version_label, &parsed_version,
&destination_connection_id, &source_connection_id, &long_packet_type,
&retry_token_length_length, &retry_token, &detailed_error);
- EXPECT_EQ(QUIC_NO_ERROR, parse_error);
+ EXPECT_THAT(parse_error, IsQuicNoError());
EXPECT_EQ("", detailed_error);
EXPECT_EQ(p[0], first_byte);
EXPECT_TRUE(version_present);
@@ -1376,7 +1375,7 @@ TEST_P(QuicFramerTest, ClientConnectionIdFromShortHeaderToClient) {
// clang-format on
QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
EXPECT_EQ("", framer_.detailed_error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
@@ -1410,7 +1409,7 @@ TEST_P(QuicFramerTest, ClientConnectionIdFromShortHeaderToServer) {
// clang-format on
QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
EXPECT_EQ("", framer_.detailed_error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
@@ -1464,7 +1463,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) {
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_MISSING_PAYLOAD));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(), visitor_.header_->source_connection_id);
EXPECT_FALSE(visitor_.header_->reset_flag);
@@ -1545,7 +1544,7 @@ TEST_P(QuicFramerTest, PacketHeaderWithVersionFlag) {
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_MISSING_PAYLOAD));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
@@ -1607,7 +1606,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith4BytePacketNumber) {
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_MISSING_PAYLOAD));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
@@ -1671,10 +1670,10 @@ TEST_P(QuicFramerTest, PacketHeaderWith2BytePacketNumber) {
AssemblePacketFromFragments(fragments));
if (framer_.version().HasHeaderProtection()) {
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
} else {
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_MISSING_PAYLOAD));
}
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
@@ -1741,10 +1740,10 @@ TEST_P(QuicFramerTest, PacketHeaderWith1BytePacketNumber) {
AssemblePacketFromFragments(fragments));
if (framer_.version().HasHeaderProtection()) {
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
} else {
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_MISSING_PAYLOAD));
}
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
@@ -1986,7 +1985,7 @@ TEST_P(QuicFramerTest, LargePublicFlagWithMismatchedVersions) {
}
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(0, visitor_.frame_count_);
EXPECT_EQ(1, visitor_.version_mismatch_);
@@ -2090,7 +2089,7 @@ TEST_P(QuicFramerTest, PaddingFrame) {
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -2210,7 +2209,7 @@ TEST_P(QuicFramerTest, StreamFrame) {
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -2265,7 +2264,7 @@ TEST_P(QuicFramerTest, EmptyStreamFrame) {
AssemblePacketFromFragments(packet));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -2360,14 +2359,14 @@ TEST_P(QuicFramerTest, MissingDiversificationNonce) {
QuicEncryptedPacket encrypted(AsChars(p), p_length, false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
if (framer_.version().HasHeaderProtection()) {
- EXPECT_EQ(QUIC_DECRYPTION_FAILURE, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_DECRYPTION_FAILURE));
EXPECT_EQ("Unable to decrypt header protection.", framer_.detailed_error());
} else if (framer_.transport_version() >= QUIC_VERSION_46) {
// Cannot read diversification nonce.
- EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_PACKET_HEADER));
EXPECT_EQ("Unable to read nonce.", framer_.detailed_error());
} else {
- EXPECT_EQ(QUIC_DECRYPTION_FAILURE, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_DECRYPTION_FAILURE));
}
}
@@ -2413,7 +2412,7 @@ TEST_P(QuicFramerTest, StreamFrame3ByteStreamId) {
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -2533,7 +2532,7 @@ TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) {
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -2653,7 +2652,7 @@ TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) {
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -2855,7 +2854,7 @@ TEST_P(QuicFramerTest, StreamFrameWithVersion) {
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, kIncludeVersion, !kIncludeDiversificationNonce,
@@ -2939,7 +2938,7 @@ TEST_P(QuicFramerTest, RejectPacket) {
false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -2978,7 +2977,7 @@ TEST_P(QuicFramerTest, RejectPublicHeader) {
false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_FALSE(visitor_.header_->packet_number.IsInitialized());
}
@@ -3087,7 +3086,7 @@ TEST_P(QuicFramerTest, AckFrameOneAckBlock) {
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -3580,7 +3579,7 @@ TEST_P(QuicFramerTest, AckFrameFirstAckBlockLengthZero) {
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_INVALID_ACK_DATA, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_ACK_DATA));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
@@ -3689,7 +3688,7 @@ TEST_P(QuicFramerTest, AckFrameOneAckBlockMaxLength) {
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -3914,7 +3913,7 @@ TEST_P(QuicFramerTest, AckFrameTwoTimeStampsMultipleAckBlocks) {
framer_.set_process_timestamps(true);
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -4126,7 +4125,7 @@ TEST_P(QuicFramerTest, NewStopWaitingFrame) {
if (GetQuicReloadableFlag(quic_do_not_accept_stop_waiting) &&
version_.transport_version >= QUIC_VERSION_46) {
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_INVALID_STOP_WAITING_DATA, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_STOP_WAITING_DATA));
EXPECT_EQ("STOP WAITING not supported in version 44+.",
framer_.detailed_error());
return;
@@ -4134,7 +4133,7 @@ TEST_P(QuicFramerTest, NewStopWaitingFrame) {
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -4192,7 +4191,7 @@ TEST_P(QuicFramerTest, InvalidNewStopWaitingFrame) {
: QUIC_ARRAYSIZE(packet),
false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_INVALID_STOP_WAITING_DATA, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_STOP_WAITING_DATA));
EXPECT_EQ("Invalid unacked delta.", framer_.detailed_error());
}
@@ -4283,7 +4282,7 @@ TEST_P(QuicFramerTest, RstStreamFrame) {
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -4394,7 +4393,7 @@ TEST_P(QuicFramerTest, ConnectionCloseFrame) {
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -4407,8 +4406,8 @@ TEST_P(QuicFramerTest, ConnectionCloseFrame) {
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
EXPECT_EQ(0x1234u,
visitor_.connection_close_frame_.transport_close_frame_type);
- EXPECT_EQ(QUIC_IETF_GQUIC_ERROR_MISSING,
- visitor_.connection_close_frame_.extracted_error_code);
+ EXPECT_THAT(visitor_.connection_close_frame_.extracted_error_code,
+ IsError(QUIC_IETF_GQUIC_ERROR_MISSING));
} else {
// For Google QUIC closes, the error code is copied into
// extracted_error_code.
@@ -4528,7 +4527,7 @@ TEST_P(QuicFramerTest, ConnectionCloseFrameWithExtractedInfoIgnoreGCuic) {
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -4598,7 +4597,7 @@ TEST_P(QuicFramerTest, ApplicationCloseFrame) {
AssemblePacketFromFragments(packet99));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -4660,7 +4659,7 @@ TEST_P(QuicFramerTest, ApplicationCloseFrameExtract) {
AssemblePacketFromFragments(packet99));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -4757,7 +4756,7 @@ TEST_P(QuicFramerTest, GoAwayFrame) {
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -4830,14 +4829,14 @@ TEST_P(QuicFramerTest, WindowUpdateFrame) {
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
EXPECT_EQ(kStreamId, visitor_.window_update_frame_.stream_id);
- EXPECT_EQ(kStreamOffset, visitor_.window_update_frame_.byte_offset);
+ EXPECT_EQ(kStreamOffset, visitor_.window_update_frame_.max_data);
CheckFramingBoundaries(fragments, QUIC_INVALID_WINDOW_UPDATE_DATA);
}
@@ -4873,7 +4872,7 @@ TEST_P(QuicFramerTest, MaxDataFrame) {
AssemblePacketFromFragments(packet99));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -4881,7 +4880,7 @@ TEST_P(QuicFramerTest, MaxDataFrame) {
EXPECT_EQ(QuicUtils::GetInvalidStreamId(framer_.transport_version()),
visitor_.window_update_frame_.stream_id);
- EXPECT_EQ(kStreamOffset, visitor_.window_update_frame_.byte_offset);
+ EXPECT_EQ(kStreamOffset, visitor_.window_update_frame_.max_data);
CheckFramingBoundaries(packet99, QUIC_INVALID_MAX_DATA_FRAME_DATA);
}
@@ -4920,14 +4919,14 @@ TEST_P(QuicFramerTest, MaxStreamDataFrame) {
AssemblePacketFromFragments(packet99));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
EXPECT_EQ(kStreamId, visitor_.window_update_frame_.stream_id);
- EXPECT_EQ(kStreamOffset, visitor_.window_update_frame_.byte_offset);
+ EXPECT_EQ(kStreamOffset, visitor_.window_update_frame_.max_data);
CheckFramingBoundaries(packet99, QUIC_INVALID_MAX_STREAM_DATA_FRAME_DATA);
}
@@ -5002,7 +5001,7 @@ TEST_P(QuicFramerTest, BlockedFrame) {
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -5075,7 +5074,7 @@ TEST_P(QuicFramerTest, PingFrame) {
false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -5087,7 +5086,7 @@ TEST_P(QuicFramerTest, PingFrame) {
}
TEST_P(QuicFramerTest, MessageFrame) {
- if (framer_.transport_version() <= QUIC_VERSION_43) {
+ if (!VersionSupportsMessageFrames(framer_.transport_version())) {
return;
}
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
@@ -5118,13 +5117,43 @@ TEST_P(QuicFramerTest, MessageFrame) {
{{},
{'m', 'e', 's', 's', 'a', 'g', 'e', '2'}},
};
+ PacketFragments packet99 = {
+ // type (short header, 4 byte packet number)
+ {"",
+ {0x43}},
+ // connection_id
+ {"",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x12, 0x34, 0x56, 0x78}},
+ // message frame type.
+ {"",
+ { 0x31 }},
+ // message length
+ {"Unable to read message length",
+ {0x07}},
+ // message data
+ {"Unable to read message data",
+ {'m', 'e', 's', 's', 'a', 'g', 'e'}},
+ // message frame no length.
+ {"",
+ { 0x30 }},
+ // message data
+ {{},
+ {'m', 'e', 's', 's', 'a', 'g', 'e', '2'}},
+ };
// clang-format on
- std::unique_ptr<QuicEncryptedPacket> encrypted(
- AssemblePacketFromFragments(packet46));
+ std::unique_ptr<QuicEncryptedPacket> encrypted;
+ if (VersionHasIetfQuicFrames(framer_.transport_version())) {
+ encrypted = AssemblePacketFromFragments(packet99);
+ } else {
+ encrypted = AssemblePacketFromFragments(packet46);
+ }
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -5134,7 +5163,11 @@ TEST_P(QuicFramerTest, MessageFrame) {
EXPECT_EQ(7u, visitor_.message_frames_[0]->message_length);
EXPECT_EQ(8u, visitor_.message_frames_[1]->message_length);
- CheckFramingBoundaries(packet46, QUIC_INVALID_MESSAGE_DATA);
+ if (VersionHasIetfQuicFrames(framer_.transport_version())) {
+ CheckFramingBoundaries(packet99, QUIC_INVALID_MESSAGE_DATA);
+ } else {
+ CheckFramingBoundaries(packet46, QUIC_INVALID_MESSAGE_DATA);
+ }
}
TEST_P(QuicFramerTest, PublicResetPacketV33) {
@@ -5177,7 +5210,7 @@ TEST_P(QuicFramerTest, PublicResetPacketV33) {
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(packet));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- ASSERT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.public_reset_packet_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.public_reset_packet_->connection_id);
@@ -5232,7 +5265,7 @@ TEST_P(QuicFramerTest, PublicResetPacket) {
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(packet));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- ASSERT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.public_reset_packet_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.public_reset_packet_->connection_id);
@@ -5279,7 +5312,7 @@ TEST_P(QuicFramerTest, PublicResetPacketWithTrailingJunk) {
QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
- ASSERT_EQ(QUIC_INVALID_PUBLIC_RST_PACKET, framer_.error());
+ ASSERT_THAT(framer_.error(), IsError(QUIC_INVALID_PUBLIC_RST_PACKET));
EXPECT_EQ("Unable to read reset message.", framer_.detailed_error());
}
@@ -5331,7 +5364,7 @@ TEST_P(QuicFramerTest, PublicResetPacketWithClientAddress) {
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(packet));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- ASSERT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.public_reset_packet_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.public_reset_packet_->connection_id);
@@ -5380,7 +5413,7 @@ TEST_P(QuicFramerTest, IetfStatelessResetPacket) {
// This packet cannot be decrypted because diversification nonce is missing.
QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- ASSERT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.stateless_reset_packet_.get());
EXPECT_EQ(kTestStatelessResetToken,
visitor_.stateless_reset_packet_->stateless_reset_token);
@@ -5423,7 +5456,7 @@ TEST_P(QuicFramerTest, IetfStatelessResetPacketInvalidStatelessResetToken) {
// This packet cannot be decrypted because diversification nonce is missing.
QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_DECRYPTION_FAILURE, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_DECRYPTION_FAILURE));
ASSERT_FALSE(visitor_.stateless_reset_packet_);
}
@@ -5490,7 +5523,7 @@ TEST_P(QuicFramerTest, VersionNegotiationPacketClient) {
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- ASSERT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.version_negotiation_packet_.get());
EXPECT_EQ(1u, visitor_.version_negotiation_packet_->versions.size());
EXPECT_EQ(GetParam(), visitor_.version_negotiation_packet_->versions[0]);
@@ -5549,7 +5582,8 @@ TEST_P(QuicFramerTest, VersionNegotiationPacketServer) {
QuicEncryptedPacket encrypted(AsChars(p), p_length, false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_INVALID_VERSION_NEGOTIATION_PACKET, framer_.error());
+ EXPECT_THAT(framer_.error(),
+ IsError(QUIC_INVALID_VERSION_NEGOTIATION_PACKET));
EXPECT_EQ("Server received version negotiation packet.",
framer_.detailed_error());
EXPECT_FALSE(visitor_.version_negotiation_packet_.get());
@@ -5580,7 +5614,7 @@ TEST_P(QuicFramerTest, OldVersionNegotiationPacket) {
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(packet));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- ASSERT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.version_negotiation_packet_.get());
EXPECT_EQ(1u, visitor_.version_negotiation_packet_->versions.size());
EXPECT_EQ(GetParam(), visitor_.version_negotiation_packet_->versions[0]);
@@ -5646,7 +5680,7 @@ TEST_P(QuicFramerTest, ParseIetfRetryPacket) {
QuicEncryptedPacket encrypted(AsChars(p), p_length, false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
ASSERT_TRUE(visitor_.retry_original_connection_id_.get());
@@ -5687,7 +5721,7 @@ TEST_P(QuicFramerTest, RejectIetfRetryPacketAsServer) {
QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_PACKET_HEADER));
EXPECT_EQ("Client-initiated RETRY is invalid.", framer_.detailed_error());
}
@@ -6483,7 +6517,7 @@ TEST_P(QuicFramerTest, CryptoFrame) {
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -6498,7 +6532,6 @@ TEST_P(QuicFramerTest, CryptoFrame) {
}
TEST_P(QuicFramerTest, BuildVersionNegotiationPacket) {
- SetQuicReloadableFlag(quic_version_negotiation_grease, true);
SetQuicFlag(FLAGS_quic_disable_version_negotiation_grease_randomness, true);
// clang-format off
unsigned char packet[] = {
@@ -6565,7 +6598,6 @@ TEST_P(QuicFramerTest, BuildVersionNegotiationPacketWithClientConnectionId) {
return;
}
- SetQuicReloadableFlag(quic_version_negotiation_grease, true);
SetQuicFlag(FLAGS_quic_disable_version_negotiation_grease_randomness, true);
// clang-format off
@@ -8131,7 +8163,7 @@ TEST_P(QuicFramerTest, BuildWindowUpdatePacket) {
QuicWindowUpdateFrame window_update_frame;
window_update_frame.stream_id = kStreamId;
- window_update_frame.byte_offset = 0x1122334455667788;
+ window_update_frame.max_data = 0x1122334455667788;
QuicFrames frames = {QuicFrame(&window_update_frame)};
@@ -8219,7 +8251,7 @@ TEST_P(QuicFramerTest, BuildMaxStreamDataPacket) {
QuicWindowUpdateFrame window_update_frame;
window_update_frame.stream_id = kStreamId;
- window_update_frame.byte_offset = 0x1122334455667788;
+ window_update_frame.max_data = 0x1122334455667788;
QuicFrames frames = {QuicFrame(&window_update_frame)};
@@ -8265,7 +8297,7 @@ TEST_P(QuicFramerTest, BuildMaxDataPacket) {
QuicWindowUpdateFrame window_update_frame;
window_update_frame.stream_id =
QuicUtils::GetInvalidStreamId(framer_.transport_version());
- window_update_frame.byte_offset = 0x1122334455667788;
+ window_update_frame.max_data = 0x1122334455667788;
QuicFrames frames = {QuicFrame(&window_update_frame)};
@@ -8442,7 +8474,7 @@ TEST_P(QuicFramerTest, BuildPingPacket) {
}
TEST_P(QuicFramerTest, BuildMessagePacket) {
- if (framer_.transport_version() <= QUIC_VERSION_43) {
+ if (!VersionSupportsMessageFrames(framer_.transport_version())) {
return;
}
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
@@ -8487,13 +8519,13 @@ TEST_P(QuicFramerTest, BuildMessagePacket) {
0x12, 0x34, 0x56, 0x78,
// frame type (IETF_MESSAGE frame)
- 0x21,
+ 0x31,
// Length
0x07,
// Message Data
'm', 'e', 's', 's', 'a', 'g', 'e',
// frame type (message frame no length)
- 0x20,
+ 0x30,
// Message Data
'm', 'e', 's', 's', 'a', 'g', 'e', '2'
};
@@ -9205,7 +9237,7 @@ TEST_P(QuicFramerTest, StopPacketProcessing) {
}
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
}
static char kTestString[] = "At least 20 characters.";
@@ -9260,7 +9292,7 @@ TEST_P(QuicFramerTest, ConstructEncryptedPacket) {
EXPECT_CALL(visitor, OnPacketComplete()).Times(1);
EXPECT_TRUE(framer_.ProcessPacket(*packet));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
}
// Verify that the packet returned by ConstructMisFramedEncryptedPacket()
@@ -9278,12 +9310,10 @@ TEST_P(QuicFramerTest, ConstructMisFramedEncryptedPacket) {
}
framer_.SetEncrypter(ENCRYPTION_INITIAL,
std::make_unique<NullEncrypter>(framer_.perspective()));
- ParsedQuicVersionVector versions;
- versions.push_back(framer_.version());
std::unique_ptr<QuicEncryptedPacket> packet(ConstructMisFramedEncryptedPacket(
TestConnectionId(), EmptyQuicConnectionId(), false, false,
kTestQuicStreamId, kTestString, CONNECTION_ID_PRESENT,
- CONNECTION_ID_ABSENT, PACKET_4BYTE_PACKET_NUMBER, &versions,
+ CONNECTION_ID_ABSENT, PACKET_4BYTE_PACKET_NUMBER, framer_.version(),
Perspective::IS_CLIENT));
MockFramerVisitor visitor;
@@ -9302,7 +9332,7 @@ TEST_P(QuicFramerTest, ConstructMisFramedEncryptedPacket) {
EXPECT_CALL(visitor, OnPacketComplete()).Times(0);
EXPECT_FALSE(framer_.ProcessPacket(*packet));
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_FRAME_DATA));
}
TEST_P(QuicFramerTest, IetfBlockedFrame) {
@@ -9336,7 +9366,7 @@ TEST_P(QuicFramerTest, IetfBlockedFrame) {
AssemblePacketFromFragments(packet99));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -9421,7 +9451,7 @@ TEST_P(QuicFramerTest, IetfStreamBlockedFrame) {
AssemblePacketFromFragments(packet99));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -9507,7 +9537,7 @@ TEST_P(QuicFramerTest, BiDiMaxStreamsFrame) {
AssemblePacketFromFragments(packet99));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -9548,7 +9578,7 @@ TEST_P(QuicFramerTest, UniDiMaxStreamsFrame) {
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -9590,7 +9620,7 @@ TEST_P(QuicFramerTest, ServerUniDiMaxStreamsFrame) {
AssemblePacketFromFragments(packet99));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -9631,7 +9661,7 @@ TEST_P(QuicFramerTest, ClientUniDiMaxStreamsFrame) {
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -9676,7 +9706,7 @@ TEST_P(QuicFramerTest, BiDiMaxStreamsFrameTooBig) {
QuicEncryptedPacket encrypted(AsChars(packet99), QUIC_ARRAYSIZE(packet99),
false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -9715,7 +9745,7 @@ TEST_P(QuicFramerTest, ClientBiDiMaxStreamsFrameTooBig) {
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -9754,7 +9784,7 @@ TEST_P(QuicFramerTest, ServerUniDiMaxStreamsFrameTooBig) {
false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -9793,7 +9823,7 @@ TEST_P(QuicFramerTest, ClientUniDiMaxStreamsFrameTooBig) {
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -9862,7 +9892,7 @@ TEST_P(QuicFramerTest, ServerBiDiStreamsBlockedFrame) {
AssemblePacketFromFragments(packet99));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -9905,7 +9935,7 @@ TEST_P(QuicFramerTest, BiDiStreamsBlockedFrame) {
AssemblePacketFromFragments(packet99));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -9948,7 +9978,7 @@ TEST_P(QuicFramerTest, UniDiStreamsBlockedFrame) {
AssemblePacketFromFragments(packet99));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -9989,7 +10019,7 @@ TEST_P(QuicFramerTest, ClientUniDiStreamsBlockedFrame) {
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -10033,7 +10063,7 @@ TEST_P(QuicFramerTest, StreamsBlockedFrameTooBig) {
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_STREAMS_BLOCKED_DATA, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_STREAMS_BLOCKED_DATA));
EXPECT_EQ(framer_.detailed_error(),
"STREAMS_BLOCKED stream count exceeds implementation limit.");
}
@@ -10071,7 +10101,7 @@ TEST_P(QuicFramerTest, StreamsBlockedFrameZeroCount) {
AssemblePacketFromFragments(packet99));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -10293,7 +10323,7 @@ TEST_P(QuicFramerTest, NewConnectionIdFrame) {
AssemblePacketFromFragments(packet99));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -10352,7 +10382,7 @@ TEST_P(QuicFramerTest, NewConnectionIdFrameVariableLength) {
AssemblePacketFromFragments(packet99));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -10419,7 +10449,7 @@ TEST_P(QuicFramerTest, InvalidLongNewConnectionIdFrame) {
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(packet99));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_INVALID_NEW_CONNECTION_ID_DATA, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_NEW_CONNECTION_ID_DATA));
EXPECT_EQ("Unable to read new connection ID frame connection id.",
framer_.detailed_error());
}
@@ -10464,7 +10494,7 @@ TEST_P(QuicFramerTest, InvalidRetirePriorToNewConnectionIdFrame) {
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(packet99));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_INVALID_NEW_CONNECTION_ID_DATA, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_NEW_CONNECTION_ID_DATA));
EXPECT_EQ("Retire_prior_to > sequence_number.", framer_.detailed_error());
}
@@ -10557,7 +10587,7 @@ TEST_P(QuicFramerTest, NewTokenFrame) {
AssemblePacketFromFragments(packet));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -10650,7 +10680,7 @@ TEST_P(QuicFramerTest, IetfStopSendingFrame) {
AssemblePacketFromFragments(packet99));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -10736,7 +10766,7 @@ TEST_P(QuicFramerTest, IetfPathChallengeFrame) {
AssemblePacketFromFragments(packet99));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -10819,7 +10849,7 @@ TEST_P(QuicFramerTest, IetfPathResponseFrame) {
AssemblePacketFromFragments(packet99));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -10981,7 +11011,7 @@ TEST_P(QuicFramerTest, IetfFrameTypeEncodingErrorUnknown1Byte) {
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_FRAME_DATA));
EXPECT_EQ("Illegal frame type.", framer_.detailed_error());
}
@@ -11014,7 +11044,7 @@ TEST_P(QuicFramerTest, IetfFrameTypeEncodingErrorUnknown2Bytes) {
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_FRAME_DATA));
EXPECT_EQ("Illegal frame type.", framer_.detailed_error());
}
@@ -11047,7 +11077,7 @@ TEST_P(QuicFramerTest, IetfFrameTypeEncodingErrorUnknown4Bytes) {
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_FRAME_DATA));
EXPECT_EQ("Illegal frame type.", framer_.detailed_error());
}
@@ -11079,7 +11109,7 @@ TEST_P(QuicFramerTest, IetfFrameTypeEncodingErrorUnknown8Bytes) {
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_INVALID_FRAME_DATA, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_FRAME_DATA));
EXPECT_EQ("Illegal frame type.", framer_.detailed_error());
}
@@ -11116,7 +11146,7 @@ TEST_P(QuicFramerTest, IetfFrameTypeEncodingErrorKnown2Bytes) {
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(IETF_QUIC_PROTOCOL_VIOLATION, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(IETF_QUIC_PROTOCOL_VIOLATION));
EXPECT_EQ("Frame type not minimally encoded.", framer_.detailed_error());
}
@@ -11149,7 +11179,7 @@ TEST_P(QuicFramerTest, IetfFrameTypeEncodingErrorKnown4Bytes) {
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(IETF_QUIC_PROTOCOL_VIOLATION, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(IETF_QUIC_PROTOCOL_VIOLATION));
EXPECT_EQ("Frame type not minimally encoded.", framer_.detailed_error());
}
@@ -11181,7 +11211,7 @@ TEST_P(QuicFramerTest, IetfFrameTypeEncodingErrorKnown8Bytes) {
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(IETF_QUIC_PROTOCOL_VIOLATION, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(IETF_QUIC_PROTOCOL_VIOLATION));
EXPECT_EQ("Frame type not minimally encoded.", framer_.detailed_error());
}
@@ -11585,7 +11615,7 @@ TEST_P(QuicFramerTest, IetfFrameTypeEncodingErrorKnown2BytesAllTypes) {
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(IETF_QUIC_PROTOCOL_VIOLATION, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(IETF_QUIC_PROTOCOL_VIOLATION));
EXPECT_EQ("Frame type not minimally encoded.", framer_.detailed_error());
}
}
@@ -11620,7 +11650,7 @@ TEST_P(QuicFramerTest, RetireConnectionIdFrame) {
AssemblePacketFromFragments(packet99));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
@@ -12083,7 +12113,7 @@ TEST_P(QuicFramerTest, CoalescedPacket) {
QuicEncryptedPacket encrypted(AsChars(p), p_length, false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
ASSERT_EQ(1u, visitor_.stream_frames_.size());
@@ -12098,7 +12128,7 @@ TEST_P(QuicFramerTest, CoalescedPacket) {
ASSERT_EQ(visitor_.coalesced_packets_.size(), 1u);
EXPECT_TRUE(framer_.ProcessPacket(*visitor_.coalesced_packets_[0].get()));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
ASSERT_EQ(2u, visitor_.stream_frames_.size());
@@ -12197,18 +12227,18 @@ TEST_P(QuicFramerTest, UndecryptablePacketWithoutDecrypter) {
// First attempt decryption without the handshake crypter.
EXPECT_FALSE(
framer_.ProcessPacket(QuicEncryptedPacket(AsChars(p), p_length, false)));
- EXPECT_EQ(QUIC_DECRYPTION_FAILURE, framer_.error());
- ASSERT_EQ(1u, visitor_.undecryptable_packets_.size());
- ASSERT_EQ(1u, visitor_.undecryptable_decryption_levels_.size());
- ASSERT_EQ(1u, visitor_.undecryptable_has_decryption_keys_.size());
- CompareCharArraysWithHexError(
- "undecryptable packet", visitor_.undecryptable_packets_[0]->data(),
- visitor_.undecryptable_packets_[0]->length(), AsChars(p), p_length);
- if (framer_.version().KnowsWhichDecrypterToUse()) {
- EXPECT_EQ(ENCRYPTION_HANDSHAKE,
- visitor_.undecryptable_decryption_levels_[0]);
- }
- EXPECT_FALSE(visitor_.undecryptable_has_decryption_keys_[0]);
+ EXPECT_THAT(framer_.error(), IsError(QUIC_DECRYPTION_FAILURE));
+ ASSERT_EQ(1u, visitor_.undecryptable_packets_.size());
+ ASSERT_EQ(1u, visitor_.undecryptable_decryption_levels_.size());
+ ASSERT_EQ(1u, visitor_.undecryptable_has_decryption_keys_.size());
+ CompareCharArraysWithHexError(
+ "undecryptable packet", visitor_.undecryptable_packets_[0]->data(),
+ visitor_.undecryptable_packets_[0]->length(), AsChars(p), p_length);
+ if (framer_.version().KnowsWhichDecrypterToUse()) {
+ EXPECT_EQ(ENCRYPTION_HANDSHAKE,
+ visitor_.undecryptable_decryption_levels_[0]);
+ }
+ EXPECT_FALSE(visitor_.undecryptable_has_decryption_keys_[0]);
}
TEST_P(QuicFramerTest, UndecryptablePacketWithDecrypter) {
@@ -12299,19 +12329,19 @@ TEST_P(QuicFramerTest, UndecryptablePacketWithDecrypter) {
EXPECT_FALSE(
framer_.ProcessPacket(QuicEncryptedPacket(AsChars(p), p_length, false)));
- EXPECT_EQ(QUIC_DECRYPTION_FAILURE, framer_.error());
- ASSERT_EQ(1u, visitor_.undecryptable_packets_.size());
- ASSERT_EQ(1u, visitor_.undecryptable_decryption_levels_.size());
- ASSERT_EQ(1u, visitor_.undecryptable_has_decryption_keys_.size());
- CompareCharArraysWithHexError(
- "undecryptable packet", visitor_.undecryptable_packets_[0]->data(),
- visitor_.undecryptable_packets_[0]->length(), AsChars(p), p_length);
- if (framer_.version().KnowsWhichDecrypterToUse()) {
- EXPECT_EQ(ENCRYPTION_HANDSHAKE,
- visitor_.undecryptable_decryption_levels_[0]);
- }
- EXPECT_EQ(framer_.version().KnowsWhichDecrypterToUse(),
- visitor_.undecryptable_has_decryption_keys_[0]);
+ EXPECT_THAT(framer_.error(), IsError(QUIC_DECRYPTION_FAILURE));
+ ASSERT_EQ(1u, visitor_.undecryptable_packets_.size());
+ ASSERT_EQ(1u, visitor_.undecryptable_decryption_levels_.size());
+ ASSERT_EQ(1u, visitor_.undecryptable_has_decryption_keys_.size());
+ CompareCharArraysWithHexError(
+ "undecryptable packet", visitor_.undecryptable_packets_[0]->data(),
+ visitor_.undecryptable_packets_[0]->length(), AsChars(p), p_length);
+ if (framer_.version().KnowsWhichDecrypterToUse()) {
+ EXPECT_EQ(ENCRYPTION_HANDSHAKE,
+ visitor_.undecryptable_decryption_levels_[0]);
+ }
+ EXPECT_EQ(framer_.version().KnowsWhichDecrypterToUse(),
+ visitor_.undecryptable_has_decryption_keys_[0]);
}
TEST_P(QuicFramerTest, UndecryptableCoalescedPacket) {
@@ -12462,20 +12492,19 @@ TEST_P(QuicFramerTest, UndecryptableCoalescedPacket) {
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_DECRYPTION_FAILURE, framer_.error());
-
- ASSERT_EQ(1u, visitor_.undecryptable_packets_.size());
- ASSERT_EQ(1u, visitor_.undecryptable_decryption_levels_.size());
- ASSERT_EQ(1u, visitor_.undecryptable_has_decryption_keys_.size());
- // Make sure we only receive the first undecryptable packet and not the
- // full packet including the second coalesced packet.
- CompareCharArraysWithHexError("undecryptable packet",
- visitor_.undecryptable_packets_[0]->data(),
- visitor_.undecryptable_packets_[0]->length(),
- AsChars(p), length_of_first_coalesced_packet);
- EXPECT_EQ(ENCRYPTION_HANDSHAKE,
- visitor_.undecryptable_decryption_levels_[0]);
- EXPECT_TRUE(visitor_.undecryptable_has_decryption_keys_[0]);
+ EXPECT_THAT(framer_.error(), IsError(QUIC_DECRYPTION_FAILURE));
+
+ ASSERT_EQ(1u, visitor_.undecryptable_packets_.size());
+ ASSERT_EQ(1u, visitor_.undecryptable_decryption_levels_.size());
+ ASSERT_EQ(1u, visitor_.undecryptable_has_decryption_keys_.size());
+ // Make sure we only receive the first undecryptable packet and not the
+ // full packet including the second coalesced packet.
+ CompareCharArraysWithHexError("undecryptable packet",
+ visitor_.undecryptable_packets_[0]->data(),
+ visitor_.undecryptable_packets_[0]->length(),
+ AsChars(p), length_of_first_coalesced_packet);
+ EXPECT_EQ(ENCRYPTION_HANDSHAKE, visitor_.undecryptable_decryption_levels_[0]);
+ EXPECT_TRUE(visitor_.undecryptable_has_decryption_keys_[0]);
// Make sure the second coalesced packet is parsed correctly.
ASSERT_EQ(visitor_.coalesced_packets_.size(), 1u);
@@ -12631,7 +12660,7 @@ TEST_P(QuicFramerTest, MismatchedCoalescedPacket) {
EXPECT_QUIC_PEER_BUG(EXPECT_TRUE(framer_.ProcessPacket(encrypted)),
"Server: Received mismatched coalesced header.*");
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
ASSERT_EQ(1u, visitor_.stream_frames_.size());
@@ -12737,7 +12766,7 @@ TEST_P(QuicFramerTest, InvalidCoalescedPacket) {
EXPECT_QUIC_PEER_BUG(EXPECT_TRUE(framer_.ProcessPacket(encrypted)),
"Server: Failed to parse received coalesced header.*");
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
ASSERT_EQ(1u, visitor_.stream_frames_.size());
@@ -12835,7 +12864,7 @@ TEST_P(QuicFramerTest, ClientReceivesInvalidVersion) {
QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_INVALID_VERSION, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_VERSION));
EXPECT_EQ("Client received unexpected version.", framer_.detailed_error());
}
@@ -12887,10 +12916,10 @@ TEST_P(QuicFramerTest, PacketHeaderWithVariableLengthConnectionId) {
AssemblePacketFromFragments(fragments));
if (framer_.version().HasHeaderProtection()) {
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
} else {
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_MISSING_PAYLOAD));
}
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(connection_id, visitor_.header_->destination_connection_id);
@@ -12963,7 +12992,7 @@ TEST_P(QuicFramerTest, MultiplePacketNumberSpaces) {
QUIC_ARRAYSIZE(long_header_packet99), false)));
}
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
EXPECT_FALSE(
QuicFramerPeer::GetLargestDecryptedPacketNumber(&framer_, INITIAL_DATA)
.IsInitialized());
@@ -12998,7 +13027,7 @@ TEST_P(QuicFramerTest, MultiplePacketNumberSpaces) {
}
EXPECT_TRUE(framer_.ProcessPacket(short_header_encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
EXPECT_FALSE(
QuicFramerPeer::GetLargestDecryptedPacketNumber(&framer_, INITIAL_DATA)
.IsInitialized());
@@ -13033,7 +13062,7 @@ TEST_P(QuicFramerTest, IetfRetryPacketRejected) {
AssemblePacketFromFragments(packet46));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_PACKET_HEADER));
CheckFramingBoundaries(packet46, QUIC_INVALID_PACKET_HEADER);
}
@@ -13062,7 +13091,7 @@ TEST_P(QuicFramerTest, RetryPacketRejectedWithMultiplePacketNumberSpaces) {
AssemblePacketFromFragments(packet));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_PACKET_HEADER));
CheckFramingBoundaries(packet, QUIC_INVALID_PACKET_HEADER);
}
@@ -13101,7 +13130,7 @@ TEST_P(QuicFramerTest, ProcessPublicHeaderNoVersionInferredType) {
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_PACKET_HEADER));
EXPECT_EQ("Invalid public header type for expected version.",
framer_.detailed_error());
CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER);
@@ -13138,7 +13167,7 @@ TEST_P(QuicFramerTest, ProcessMismatchedHeaderVersion) {
framer_.ProcessPacket(*encrypted);
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_PACKET_HEADER));
EXPECT_EQ("Invalid public header type for expected version.",
framer_.detailed_error());
CheckFramingBoundaries(packet, QUIC_INVALID_PACKET_HEADER);
@@ -13229,7 +13258,7 @@ TEST_P(QuicFramerTest, WriteClientVersionNegotiationProbePacketOld) {
&version_present, &has_length_prefix, &version_label, &parsed_version,
&destination_connection_id, &source_connection_id, &retry_token_present,
&retry_token, &detailed_error);
- EXPECT_EQ(QUIC_NO_ERROR, parse_result);
+ EXPECT_THAT(parse_result, IsQuicNoError());
EXPECT_EQ(IETF_QUIC_LONG_HEADER_PACKET, format);
EXPECT_TRUE(version_present);
EXPECT_FALSE(has_length_prefix);
@@ -13380,7 +13409,7 @@ TEST_P(QuicFramerTest, DispatcherParseOldClientVersionNegotiationProbePacket) {
&version_present, &has_length_prefix, &version_label, &parsed_version,
&destination_connection_id, &source_connection_id, &retry_token_present,
&retry_token, &detailed_error);
- EXPECT_EQ(QUIC_NO_ERROR, header_parse_result);
+ EXPECT_THAT(header_parse_result, IsQuicNoError());
EXPECT_EQ(IETF_QUIC_LONG_HEADER_PACKET, format);
EXPECT_TRUE(version_present);
EXPECT_FALSE(has_length_prefix);
@@ -13459,7 +13488,7 @@ TEST_P(QuicFramerTest, DispatcherParseClientVersionNegotiationProbePacket) {
&version_present, &has_length_prefix, &version_label, &parsed_version,
&destination_connection_id, &source_connection_id, &retry_token_present,
&retry_token, &detailed_error);
- EXPECT_EQ(QUIC_NO_ERROR, header_parse_result);
+ EXPECT_THAT(header_parse_result, IsQuicNoError());
EXPECT_EQ(IETF_QUIC_LONG_HEADER_PACKET, format);
EXPECT_TRUE(version_present);
EXPECT_TRUE(has_length_prefix);
@@ -13587,12 +13616,12 @@ TEST_P(QuicFramerTest, ClientConnectionIdFromLongHeaderToClient) {
if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
framer_.transport_version())) {
EXPECT_FALSE(parse_success);
- EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_PACKET_HEADER));
EXPECT_EQ("Invalid ConnectionId length.", framer_.detailed_error());
return;
}
EXPECT_TRUE(parse_success);
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
EXPECT_EQ("", framer_.detailed_error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
@@ -13653,19 +13682,19 @@ TEST_P(QuicFramerTest, ClientConnectionIdFromLongHeaderToServer) {
if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
framer_.transport_version())) {
EXPECT_FALSE(parse_success);
- EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_PACKET_HEADER));
EXPECT_EQ("Invalid ConnectionId length.", framer_.detailed_error());
return;
}
if (!framer_.version().SupportsClientConnectionIds()) {
EXPECT_FALSE(parse_success);
- EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_PACKET_HEADER));
EXPECT_EQ("Client connection ID not supported in this version.",
framer_.detailed_error());
return;
}
EXPECT_TRUE(parse_success);
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ EXPECT_THAT(framer_.error(), IsQuicNoError());
EXPECT_EQ("", framer_.detailed_error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
@@ -13757,17 +13786,20 @@ TEST_P(QuicFramerTest, TestExtendedErrorCodeParser) {
frame.error_details = "this has no error code info in it";
MaybeExtractQuicErrorCode(&frame);
- EXPECT_EQ(QUIC_IETF_GQUIC_ERROR_MISSING, frame.extracted_error_code);
+ EXPECT_THAT(frame.extracted_error_code,
+ IsError(QUIC_IETF_GQUIC_ERROR_MISSING));
EXPECT_EQ("this has no error code info in it", frame.error_details);
frame.error_details = "1234this does not have the colon in it";
MaybeExtractQuicErrorCode(&frame);
- EXPECT_EQ(QUIC_IETF_GQUIC_ERROR_MISSING, frame.extracted_error_code);
+ EXPECT_THAT(frame.extracted_error_code,
+ IsError(QUIC_IETF_GQUIC_ERROR_MISSING));
EXPECT_EQ("1234this does not have the colon in it", frame.error_details);
frame.error_details = "1a234:this has a colon, but a malformed error number";
MaybeExtractQuicErrorCode(&frame);
- EXPECT_EQ(QUIC_IETF_GQUIC_ERROR_MISSING, frame.extracted_error_code);
+ EXPECT_THAT(frame.extracted_error_code,
+ IsError(QUIC_IETF_GQUIC_ERROR_MISSING));
EXPECT_EQ("1a234:this has a colon, but a malformed error number",
frame.error_details);
@@ -13779,14 +13811,16 @@ TEST_P(QuicFramerTest, TestExtendedErrorCodeParser) {
frame.error_details =
"1234 :this is not good, space between last digit and colon";
MaybeExtractQuicErrorCode(&frame);
- EXPECT_EQ(QUIC_IETF_GQUIC_ERROR_MISSING, frame.extracted_error_code);
+ EXPECT_THAT(frame.extracted_error_code,
+ IsError(QUIC_IETF_GQUIC_ERROR_MISSING));
EXPECT_EQ("1234 :this is not good, space between last digit and colon",
frame.error_details);
frame.error_details = "123456789";
MaybeExtractQuicErrorCode(&frame);
- EXPECT_EQ(QUIC_IETF_GQUIC_ERROR_MISSING,
- frame.extracted_error_code); // Not good, all numbers, no :
+ EXPECT_THAT(
+ frame.extracted_error_code,
+ IsError(QUIC_IETF_GQUIC_ERROR_MISSING)); // Not good, all numbers, no :
EXPECT_EQ("123456789", frame.error_details);
frame.error_details = "1234:";
@@ -13803,23 +13837,26 @@ TEST_P(QuicFramerTest, TestExtendedErrorCodeParser) {
frame.error_details = "12345 6789:";
MaybeExtractQuicErrorCode(&frame);
- EXPECT_EQ(QUIC_IETF_GQUIC_ERROR_MISSING,
- frame.extracted_error_code); // Not good
+ EXPECT_THAT(frame.extracted_error_code,
+ IsError(QUIC_IETF_GQUIC_ERROR_MISSING)); // Not good
EXPECT_EQ("12345 6789:", frame.error_details);
frame.error_details = ":no numbers, is not good";
MaybeExtractQuicErrorCode(&frame);
- EXPECT_EQ(QUIC_IETF_GQUIC_ERROR_MISSING, frame.extracted_error_code);
+ EXPECT_THAT(frame.extracted_error_code,
+ IsError(QUIC_IETF_GQUIC_ERROR_MISSING));
EXPECT_EQ(":no numbers, is not good", frame.error_details);
frame.error_details = "qwer:also no numbers, is not good";
MaybeExtractQuicErrorCode(&frame);
- EXPECT_EQ(QUIC_IETF_GQUIC_ERROR_MISSING, frame.extracted_error_code);
+ EXPECT_THAT(frame.extracted_error_code,
+ IsError(QUIC_IETF_GQUIC_ERROR_MISSING));
EXPECT_EQ("qwer:also no numbers, is not good", frame.error_details);
frame.error_details = " 1234:this is not good, space before first digit";
MaybeExtractQuicErrorCode(&frame);
- EXPECT_EQ(QUIC_IETF_GQUIC_ERROR_MISSING, frame.extracted_error_code);
+ EXPECT_THAT(frame.extracted_error_code,
+ IsError(QUIC_IETF_GQUIC_ERROR_MISSING));
EXPECT_EQ(" 1234:this is not good, space before first digit",
frame.error_details);
@@ -13830,6 +13867,42 @@ TEST_P(QuicFramerTest, TestExtendedErrorCodeParser) {
EXPECT_EQ("", frame.error_details);
}
+// Regression test for crbug/1029636.
+TEST_P(QuicFramerTest, OverlyLargeAckDelay) {
+ if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
+ return;
+ }
+ SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
+ // clang-format off
+ unsigned char packet99[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (IETF_ACK frame)
+ 0x02,
+ // largest acked
+ kVarInt62FourBytes + 0x12, 0x34, 0x56, 0x78,
+ // ack delay time.
+ kVarInt62EightBytes + 0x31, 0x00, 0x00, 0x00, 0xF3, 0xA0, 0x81, 0xE0,
+ // Nr. of additional ack blocks
+ kVarInt62OneByte + 0x00,
+ // first ack block length.
+ kVarInt62FourBytes + 0x12, 0x34, 0x56, 0x77,
+ };
+ // clang-format on
+
+ framer_.ProcessPacket(
+ QuicEncryptedPacket(AsChars(packet99), QUIC_ARRAYSIZE(packet99), false));
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ // Verify ack_delay_time is set correctly.
+ EXPECT_EQ(QuicTime::Delta::Infinite(),
+ visitor_.ack_frames_[0]->ack_delay_time);
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_ietf_framer_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_ietf_framer_test.cc
index 90ae8b9d8d7..e4feb471131 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_ietf_framer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_ietf_framer_test.cc
@@ -247,8 +247,8 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
// initialize a writer so that the serialized packet is placed in
// packet_buffer.
QuicDataWriter writer(packet_buffer_size, packet_buffer,
- NETWORK_BYTE_ORDER); // do not really care
- // about endianness.
+ quiche::NETWORK_BYTE_ORDER); // do not really care
+ // about endianness.
// set up to define the source frame we wish to send.
QuicStreamFrame source_stream_frame(
stream_id, fin_bit, offset, xmit_packet_data, xmit_packet_data_size);
@@ -259,7 +259,8 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
// Better have something in the packet buffer.
EXPECT_NE(0u, writer.length());
// Now set up a reader to read in the frame.
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicDataReader reader(packet_buffer, writer.length(),
+ quiche::NETWORK_BYTE_ORDER);
// A StreamFrame to hold the results... we know the frame type,
// put it into the QuicIetfStreamFrame
@@ -323,7 +324,8 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
// Make a writer so that the serialized packet is placed in
// packet_buffer.
- QuicDataWriter writer(expected_size, packet_buffer, NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(expected_size, packet_buffer,
+ quiche::NETWORK_BYTE_ORDER);
// Write the frame to the packet buffer.
EXPECT_TRUE(QuicFramerPeer::AppendIetfAckFrameAndTypeByte(
@@ -338,7 +340,8 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
// and what is in the buffer should be the expected size.
EXPECT_EQ(expected_size, writer.length()) << "Frame is " << transmit_frame;
// Now set up a reader to read in the frame.
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicDataReader reader(packet_buffer, writer.length(),
+ quiche::NETWORK_BYTE_ORDER);
// read in the frame type
uint8_t received_frame_type;
@@ -384,7 +387,7 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
// Make a writer so that the serialized packet is placed in
// packet_buffer.
QuicDataWriter writer(packet_buffer_size, packet_buffer,
- NETWORK_BYTE_ORDER);
+ quiche::NETWORK_BYTE_ORDER);
QuicPathChallengeFrame transmit_frame(0, data);
@@ -396,7 +399,8 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
EXPECT_EQ(kQuicPathChallengeFrameSize, writer.length());
// now set up a reader to read in the frame.
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicDataReader reader(packet_buffer, writer.length(),
+ quiche::NETWORK_BYTE_ORDER);
QuicPathChallengeFrame receive_frame;
@@ -417,7 +421,7 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
// Make a writer so that the serialized packet is placed in
// packet_buffer.
QuicDataWriter writer(packet_buffer_size, packet_buffer,
- NETWORK_BYTE_ORDER);
+ quiche::NETWORK_BYTE_ORDER);
QuicPathResponseFrame transmit_frame(0, data);
@@ -429,7 +433,8 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
EXPECT_EQ(kQuicPathResponseFrameSize, writer.length());
// Set up a reader to read in the frame.
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicDataReader reader(packet_buffer, writer.length(),
+ quiche::NETWORK_BYTE_ORDER);
QuicPathResponseFrame receive_frame;
@@ -452,7 +457,7 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
// Initialize a writer so that the serialized packet is placed in
// packet_buffer.
QuicDataWriter writer(packet_buffer_size, packet_buffer,
- NETWORK_BYTE_ORDER);
+ quiche::NETWORK_BYTE_ORDER);
QuicRstStreamFrame transmit_frame(static_cast<QuicControlFrameId>(1),
stream_id, error_code, final_offset);
@@ -465,7 +470,8 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
EXPECT_LT(2u, writer.length());
EXPECT_GT(25u, writer.length());
// Now set up a reader to read in the thing in.
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicDataReader reader(packet_buffer, writer.length(),
+ quiche::NETWORK_BYTE_ORDER);
// A QuicRstStreamFrame to hold the results
QuicRstStreamFrame receive_frame;
@@ -487,7 +493,7 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
Perspective old_perspective = framer_.perspective();
// Set up the writer and transmit QuicMaxStreamsFrame
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- NETWORK_BYTE_ORDER);
+ quiche::NETWORK_BYTE_ORDER);
// Set the perspective of the sender. If the stream id is supposed to
// be server-initiated, then the sender of the MAX_STREAMS should be
@@ -512,7 +518,8 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
: Perspective::IS_CLIENT);
// Set up reader and empty receive QuicPaddingFrame.
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicDataReader reader(packet_buffer, writer.length(),
+ quiche::NETWORK_BYTE_ORDER);
QuicMaxStreamsFrame receive_frame;
// Deframe it
@@ -537,7 +544,7 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
Perspective old_perspective = framer_.perspective();
// Set up the writer and transmit QuicStreamsBlockedFrame
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- NETWORK_BYTE_ORDER);
+ quiche::NETWORK_BYTE_ORDER);
// Set the perspective of the sender. If the stream id is supposed to
// be server-initiated, then the sender of the STREAMS_BLOCKED should be
@@ -562,7 +569,8 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
: Perspective::IS_SERVER);
// Set up reader and empty receive QuicPaddingFrame.
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicDataReader reader(packet_buffer, writer.length(),
+ quiche::NETWORK_BYTE_ORDER);
QuicStreamsBlockedFrame receive_frame;
// Deframe it
@@ -762,13 +770,14 @@ TEST_F(QuicIetfFramerTest, CryptoFrame) {
data_producer.SaveCryptoData(ENCRYPTION_INITIAL, offset, frame_data);
QuicDataWriter writer(QUIC_ARRAYSIZE(packet_buffer), packet_buffer,
- NETWORK_BYTE_ORDER);
+ quiche::NETWORK_BYTE_ORDER);
// Write the frame.
EXPECT_TRUE(QuicFramerPeer::AppendCryptoFrame(&framer_, frame, &writer));
EXPECT_NE(0u, writer.length());
// Read it back.
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicDataReader reader(packet_buffer, writer.length(),
+ quiche::NETWORK_BYTE_ORDER);
QuicCryptoFrame read_frame;
EXPECT_TRUE(
QuicFramerPeer::ProcessCryptoFrame(&framer_, &reader, &read_frame));
@@ -787,7 +796,7 @@ TEST_F(QuicIetfFramerTest, ConnectionClose) {
// initialize a writer so that the serialized packet is placed in
// packet_buffer.
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- NETWORK_BYTE_ORDER);
+ quiche::NETWORK_BYTE_ORDER);
std::string test_string = "Ich Bin Ein Jelly Donut?";
QuicConnectionCloseFrame sent_frame(QUIC_VERSION_99, QUIC_NO_ERROR,
@@ -802,7 +811,8 @@ TEST_F(QuicIetfFramerTest, ConnectionClose) {
EXPECT_NE(0u, writer.length());
// now set up a reader to read in the frame.
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicDataReader reader(packet_buffer, writer.length(),
+ quiche::NETWORK_BYTE_ORDER);
// a QuicConnectionCloseFrame to hold the results.
QuicConnectionCloseFrame sink_frame;
@@ -812,7 +822,7 @@ TEST_F(QuicIetfFramerTest, ConnectionClose) {
// Now check that received == sent
EXPECT_EQ(sent_frame.quic_error_code, sink_frame.quic_error_code);
- EXPECT_EQ(sink_frame.quic_error_code, QUIC_NO_ERROR);
+ EXPECT_THAT(sink_frame.quic_error_code, IsQuicNoError());
EXPECT_EQ(sink_frame.error_details, test_string);
EXPECT_EQ(sink_frame.close_type, sent_frame.close_type);
EXPECT_EQ(sent_frame.close_type, IETF_QUIC_TRANSPORT_CONNECTION_CLOSE);
@@ -824,7 +834,7 @@ TEST_F(QuicIetfFramerTest, ApplicationClose) {
// initialize a writer so that the serialized packet is placed in
// packet_buffer.
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- NETWORK_BYTE_ORDER);
+ quiche::NETWORK_BYTE_ORDER);
std::string test_string = "Ich Bin Ein Jelly Donut?";
QuicConnectionCloseFrame sent_frame(QUIC_VERSION_99, QUIC_LAST_ERROR,
@@ -839,7 +849,8 @@ TEST_F(QuicIetfFramerTest, ApplicationClose) {
EXPECT_NE(0u, writer.length());
// now set up a reader to read in the frame.
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicDataReader reader(packet_buffer, writer.length(),
+ quiche::NETWORK_BYTE_ORDER);
// a QuicConnectionCloseFrame to hold the results.
QuicConnectionCloseFrame sink_frame;
@@ -1061,7 +1072,7 @@ TEST_F(QuicIetfFramerTest, AckFrameNoRanges) {
// Make a writer so that the serialized packet is placed in
// packet_buffer.
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- NETWORK_BYTE_ORDER);
+ quiche::NETWORK_BYTE_ORDER);
QuicAckFrame transmit_frame;
transmit_frame.largest_acked = QuicPacketNumber(1);
@@ -1085,7 +1096,8 @@ TEST_F(QuicIetfFramerTest, AckFrameNoRanges) {
EXPECT_EQ(0, memcmp(packet, packet_buffer, writer.length()));
// Now set up a reader to read in the frame.
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicDataReader reader(packet_buffer, writer.length(),
+ quiche::NETWORK_BYTE_ORDER);
// an AckFrame to hold the results
QuicAckFrame receive_frame;
@@ -1150,7 +1162,7 @@ TEST_F(QuicIetfFramerTest, StopSendingFrame) {
// Make a writer so that the serialized packet is placed in
// packet_buffer.
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- NETWORK_BYTE_ORDER);
+ quiche::NETWORK_BYTE_ORDER);
QuicStopSendingFrame transmit_frame;
transmit_frame.stream_id = 12345;
@@ -1164,7 +1176,8 @@ TEST_F(QuicIetfFramerTest, StopSendingFrame) {
EXPECT_LE(3u, writer.length());
EXPECT_GE(10u, writer.length());
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicDataReader reader(packet_buffer, writer.length(),
+ quiche::NETWORK_BYTE_ORDER);
// A frame to hold the results
QuicStopSendingFrame receive_frame;
@@ -1190,7 +1203,7 @@ TEST_F(QuicIetfFramerTest, MaxDataFrame) {
// Set up the writer and transmit QuicWindowUpdateFrame
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- NETWORK_BYTE_ORDER);
+ quiche::NETWORK_BYTE_ORDER);
QuicWindowUpdateFrame transmit_frame(0, 99, window_size);
// Add the frame.
@@ -1202,7 +1215,8 @@ TEST_F(QuicIetfFramerTest, MaxDataFrame) {
EXPECT_GE(8u, writer.length());
// Set up reader and an empty QuicWindowUpdateFrame
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicDataReader reader(packet_buffer, writer.length(),
+ quiche::NETWORK_BYTE_ORDER);
QuicWindowUpdateFrame receive_frame;
// Deframe it
@@ -1210,8 +1224,8 @@ TEST_F(QuicIetfFramerTest, MaxDataFrame) {
QuicFramerPeer::ProcessMaxDataFrame(&framer_, &reader, &receive_frame));
// Now check that the received data equals the sent data.
- EXPECT_EQ(transmit_frame.byte_offset, window_size);
- EXPECT_EQ(transmit_frame.byte_offset, receive_frame.byte_offset);
+ EXPECT_EQ(transmit_frame.max_data, window_size);
+ EXPECT_EQ(transmit_frame.max_data, receive_frame.max_data);
EXPECT_EQ(QuicUtils::GetInvalidStreamId(framer_.transport_version()),
receive_frame.stream_id);
}
@@ -1231,7 +1245,7 @@ TEST_F(QuicIetfFramerTest, MaxStreamDataFrame) {
// Set up the writer and transmit QuicWindowUpdateFrame
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- NETWORK_BYTE_ORDER);
+ quiche::NETWORK_BYTE_ORDER);
QuicWindowUpdateFrame transmit_frame(0, stream_id, window_size);
// Add the frame.
@@ -1243,7 +1257,8 @@ TEST_F(QuicIetfFramerTest, MaxStreamDataFrame) {
EXPECT_GE(16u, writer.length());
// Set up reader and empty receive QuicPaddingFrame.
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicDataReader reader(packet_buffer, writer.length(),
+ quiche::NETWORK_BYTE_ORDER);
QuicWindowUpdateFrame receive_frame;
// Deframe it
@@ -1251,8 +1266,8 @@ TEST_F(QuicIetfFramerTest, MaxStreamDataFrame) {
&receive_frame));
// Now check that received data and sent data are equal.
- EXPECT_EQ(transmit_frame.byte_offset, window_size);
- EXPECT_EQ(transmit_frame.byte_offset, receive_frame.byte_offset);
+ EXPECT_EQ(transmit_frame.max_data, window_size);
+ EXPECT_EQ(transmit_frame.max_data, receive_frame.max_data);
EXPECT_EQ(stream_id, receive_frame.stream_id);
EXPECT_EQ(transmit_frame.stream_id, receive_frame.stream_id);
}
@@ -1286,7 +1301,7 @@ TEST_F(QuicIetfFramerTest, BlockedFrame) {
// Set up the writer and transmit QuicBlockedFrame
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- NETWORK_BYTE_ORDER);
+ quiche::NETWORK_BYTE_ORDER);
QuicBlockedFrame transmit_frame(
0, QuicUtils::GetInvalidStreamId(framer_.transport_version()), offset);
@@ -1299,7 +1314,8 @@ TEST_F(QuicIetfFramerTest, BlockedFrame) {
EXPECT_GE(8u, writer.length());
// Set up reader and empty receive QuicFrame.
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicDataReader reader(packet_buffer, writer.length(),
+ quiche::NETWORK_BYTE_ORDER);
QuicBlockedFrame receive_frame;
// Deframe it
@@ -1328,7 +1344,7 @@ TEST_F(QuicIetfFramerTest, StreamBlockedFrame) {
// Set up the writer and transmit QuicWindowUpdateFrame
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- NETWORK_BYTE_ORDER);
+ quiche::NETWORK_BYTE_ORDER);
QuicBlockedFrame transmit_frame(0, stream_id, offset);
// Add the frame.
@@ -1340,7 +1356,8 @@ TEST_F(QuicIetfFramerTest, StreamBlockedFrame) {
EXPECT_GE(16u, writer.length());
// Set up reader and empty receive QuicPaddingFrame.
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicDataReader reader(packet_buffer, writer.length(),
+ quiche::NETWORK_BYTE_ORDER);
QuicBlockedFrame receive_frame;
// Deframe it
@@ -1398,7 +1415,7 @@ TEST_F(QuicIetfFramerTest, NewConnectionIdFrame) {
// Set up the writer and transmit a QuicNewConnectionIdFrame
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- NETWORK_BYTE_ORDER);
+ quiche::NETWORK_BYTE_ORDER);
// Add the frame.
EXPECT_TRUE(QuicFramerPeer::AppendNewConnectionIdFrame(
@@ -1424,7 +1441,8 @@ TEST_F(QuicIetfFramerTest, NewConnectionIdFrame) {
EXPECT_EQ(0, memcmp(packet_buffer, packet, sizeof(packet)));
// Set up reader and empty receive QuicPaddingFrame.
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicDataReader reader(packet_buffer, writer.length(),
+ quiche::NETWORK_BYTE_ORDER);
QuicNewConnectionIdFrame receive_frame;
// Deframe it
@@ -1449,7 +1467,7 @@ TEST_F(QuicIetfFramerTest, RetireConnectionIdFrame) {
// Set up the writer and transmit QuicRetireConnectionIdFrame
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- NETWORK_BYTE_ORDER);
+ quiche::NETWORK_BYTE_ORDER);
// Add the frame.
EXPECT_TRUE(QuicFramerPeer::AppendRetireConnectionIdFrame(
@@ -1466,7 +1484,8 @@ TEST_F(QuicIetfFramerTest, RetireConnectionIdFrame) {
EXPECT_EQ(0, memcmp(packet_buffer, packet, sizeof(packet)));
// Set up reader and empty receive QuicPaddingFrame.
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicDataReader reader(packet_buffer, writer.length(),
+ quiche::NETWORK_BYTE_ORDER);
QuicRetireConnectionIdFrame receive_frame;
// Deframe it
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_interval.h b/chromium/net/third_party/quiche/src/quic/core/quic_interval.h
index c860e88e15e..9e87ecd051f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_interval.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_interval.h
@@ -63,17 +63,19 @@
#include <utility>
#include <vector>
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+
namespace quic {
template <typename T>
-class QuicInterval {
+class QUIC_NO_EXPORT QuicInterval {
private:
// Type trait for deriving the return type for QuicInterval::Length. If
// operator-() is not defined for T, then the return type is void. This makes
// the signature for Length compile so that the class can be used for such T,
// but code that calls Length would still generate a compilation error.
template <typename U>
- class DiffTypeOrVoid {
+ class QUIC_NO_EXPORT DiffTypeOrVoid {
private:
template <typename V>
static auto f(const V* v) -> decltype(*v - *v);
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_interval_set.h b/chromium/net/third_party/quiche/src/quic/core/quic_interval_set.h
index 47225287120..28153c19088 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_interval_set.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_interval_set.h
@@ -65,14 +65,15 @@
namespace quic {
template <typename T>
-class QuicIntervalSet {
+class QUIC_NO_EXPORT QuicIntervalSet {
public:
typedef QuicInterval<T> value_type;
private:
- struct IntervalLess {
+ struct QUIC_NO_EXPORT IntervalLess {
bool operator()(const value_type& a, const value_type& b) const;
};
+ // TODO(wub): Switch to absl::btree_set when it is available in Chromium.
typedef std::set<value_type, IntervalLess> Set;
public:
@@ -152,6 +153,49 @@ class QuicIntervalSet {
// TODO(wub): Similar to AddOptimizedForAppend, we can also have a
// AddOptimizedForPrepend if there is a use case.
+ // Remove the first interval.
+ // REQUIRES: !Empty()
+ void PopFront() {
+ DCHECK(!Empty());
+ intervals_.erase(intervals_.begin());
+ }
+
+ // Trim all values that is smaller than |value|. Which means
+ // a) If all values in an interval is smaller than |value|, the entire
+ // interval is removed.
+ // b) If some but not all values in an interval is smaller than |value|, the
+ // min of that interval is raised to |value|.
+ // Returns true if some intervals are trimmed.
+ bool TrimLessThan(const T& value) {
+ // Number of intervals that are fully or partially trimmed.
+ size_t num_intervals_trimmed = 0;
+
+ while (!intervals_.empty()) {
+ const_iterator first_interval = intervals_.begin();
+ if (first_interval->min() >= value) {
+ break;
+ }
+
+ ++num_intervals_trimmed;
+
+ if (first_interval->max() <= value) {
+ // a) Trim the entire interval.
+ intervals_.erase(first_interval);
+ continue;
+ }
+
+ // b) Trim a prefix of the interval.
+ //
+ // Set does not allow in-place updates due to the potential of violating
+ // its ordering requirements. But increasing the min of the first interval
+ // will not break the ordering, hence the const_cast.
+ const_cast<value_type*>(&(*first_interval))->SetMin(value);
+ break;
+ }
+
+ return num_intervals_trimmed != 0;
+ }
+
// Returns true if this QuicIntervalSet is empty.
bool Empty() const { return intervals_.empty(); }
@@ -320,7 +364,7 @@ class QuicIntervalSet {
private:
// Simple member-wise equality, since all intervals are non-empty.
- struct NonemptyIntervalEq {
+ struct QUIC_NO_EXPORT NonemptyIntervalEq {
bool operator()(const value_type& a, const value_type& b) const {
return a.min() == b.min() && a.max() == b.max();
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_interval_set_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_interval_set_test.cc
index 3fb483aa82a..efa8fe7e960 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_interval_set_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_interval_set_test.cc
@@ -191,6 +191,47 @@ TEST_F(QuicIntervalSetTest, AddOptimizedForAppend) {
EXPECT_TRUE(Check(iset, 3, 100, 150, 199, 250, 251, 350));
}
+TEST_F(QuicIntervalSetTest, PopFront) {
+ QuicIntervalSet<int> iset{{100, 200}, {400, 500}, {700, 800}};
+ EXPECT_TRUE(Check(iset, 3, 100, 200, 400, 500, 700, 800));
+
+ iset.PopFront();
+ EXPECT_TRUE(Check(iset, 2, 400, 500, 700, 800));
+
+ iset.PopFront();
+ EXPECT_TRUE(Check(iset, 1, 700, 800));
+
+ iset.PopFront();
+ EXPECT_TRUE(iset.Empty());
+}
+
+TEST_F(QuicIntervalSetTest, TrimLessThan) {
+ QuicIntervalSet<int> iset{{100, 200}, {400, 500}, {700, 800}};
+ EXPECT_TRUE(Check(iset, 3, 100, 200, 400, 500, 700, 800));
+
+ EXPECT_FALSE(iset.TrimLessThan(99));
+ EXPECT_FALSE(iset.TrimLessThan(100));
+ EXPECT_TRUE(Check(iset, 3, 100, 200, 400, 500, 700, 800));
+
+ EXPECT_TRUE(iset.TrimLessThan(101));
+ EXPECT_TRUE(Check(iset, 3, 101, 200, 400, 500, 700, 800));
+
+ EXPECT_TRUE(iset.TrimLessThan(199));
+ EXPECT_TRUE(Check(iset, 3, 199, 200, 400, 500, 700, 800));
+
+ EXPECT_TRUE(iset.TrimLessThan(450));
+ EXPECT_TRUE(Check(iset, 2, 450, 500, 700, 800));
+
+ EXPECT_TRUE(iset.TrimLessThan(500));
+ EXPECT_TRUE(Check(iset, 1, 700, 800));
+
+ EXPECT_TRUE(iset.TrimLessThan(801));
+ EXPECT_TRUE(iset.Empty());
+
+ EXPECT_FALSE(iset.TrimLessThan(900));
+ EXPECT_TRUE(iset.Empty());
+}
+
TEST_F(QuicIntervalSetTest, QuicIntervalSetBasic) {
// Test Add, Get, Contains and Find
QuicIntervalSet<int> iset;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_lru_cache.h b/chromium/net/third_party/quiche/src/quic/core/quic_lru_cache.h
index b8c78c6fd58..2ec089c820c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_lru_cache.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_lru_cache.h
@@ -8,6 +8,7 @@
#include <memory>
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
@@ -18,7 +19,7 @@ namespace quic {
// Value* returned by Lookup() can be invalid if the entry is evicted by other
// threads.
template <class K, class V>
-class QuicLRUCache {
+class QUIC_NO_EXPORT QuicLRUCache {
public:
explicit QuicLRUCache(size_t capacity) : capacity_(capacity) {}
QuicLRUCache(const QuicLRUCache&) = delete;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_mtu_discovery.cc b/chromium/net/third_party/quiche/src/quic/core/quic_mtu_discovery.cc
index c89b41a92b4..bbf18b6d7a6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_mtu_discovery.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_mtu_discovery.cc
@@ -77,10 +77,8 @@ QuicPacketLength QuicConnectionMtuDiscoverer::GetUpdatedMtuProbeSize(
// The next probe packet is as big as the previous one. Assuming the
// previous one exceeded MTU, we need to decrease the probe packet length.
max_probe_length_ = probe_packet_length;
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_mtu_discovery_v2, 1, 3);
} else {
DCHECK_GT(probe_packet_length, last_probe_length_);
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_mtu_discovery_v2, 2, 3);
}
last_probe_length_ = next_probe_packet_length();
@@ -125,7 +123,6 @@ void QuicConnectionMtuDiscoverer::OnMaxPacketLengthUpdated(
DCHECK_EQ(old_value, min_probe_length_);
min_probe_length_ = new_value;
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_mtu_discovery_v2, 3, 3);
}
std::ostream& operator<<(std::ostream& os,
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 c76a70f2f8a..41842f35963 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
@@ -20,7 +20,7 @@
namespace quic {
template <uint32_t ArenaSize>
-class QuicOneBlockArena {
+class QUIC_EXPORT_PRIVATE QuicOneBlockArena {
static const uint32_t kMaxAlign = 8;
public:
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 07fa4b15a5c..f95fe638ada 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
@@ -11,7 +11,9 @@
#include <utility>
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_frame.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_path_challenge_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
@@ -51,6 +53,38 @@ QuicLongHeaderType EncryptionlevelToLongHeaderType(EncryptionLevel level) {
}
}
+// ScopedPacketContextSwitcher saves |packet|'s states and change states
+// during its construction. When the switcher goes out of scope, it restores
+// saved states.
+class ScopedPacketContextSwitcher {
+ public:
+ ScopedPacketContextSwitcher(QuicPacketNumber packet_number,
+ QuicPacketNumberLength packet_number_length,
+ EncryptionLevel encryption_level,
+ SerializedPacket* packet)
+
+ : saved_packet_number_(packet->packet_number),
+ saved_packet_number_length_(packet->packet_number_length),
+ saved_encryption_level_(packet->encryption_level),
+ packet_(packet) {
+ packet_->packet_number = packet_number,
+ packet_->packet_number_length = packet_number_length;
+ packet_->encryption_level = encryption_level;
+ }
+
+ ~ScopedPacketContextSwitcher() {
+ packet_->packet_number = saved_packet_number_;
+ packet_->packet_number_length = saved_packet_number_length_;
+ packet_->encryption_level = saved_encryption_level_;
+ }
+
+ private:
+ const QuicPacketNumber saved_packet_number_;
+ const QuicPacketNumberLength saved_packet_number_length_;
+ const EncryptionLevel saved_encryption_level_;
+ SerializedPacket* packet_;
+};
+
} // namespace
#define ENDPOINT \
@@ -87,16 +121,11 @@ QuicPacketCreator::QuicPacketCreator(QuicConnectionId server_connection_id,
false),
pending_padding_bytes_(0),
needs_full_padding_(false),
- can_set_transmission_type_(false),
next_transmission_type_(NOT_RETRANSMISSION),
flusher_attached_(false),
fully_pad_crypto_handshake_packets_(true),
- combine_generator_and_creator_(
- GetQuicReloadableFlag(quic_combine_generator_and_creator)) {
+ latched_hard_max_packet_length_(0) {
SetMaxPacketLength(kDefaultMaxPacketSize);
- if (combine_generator_and_creator_) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_combine_generator_and_creator);
- }
}
QuicPacketCreator::~QuicPacketCreator() {
@@ -130,6 +159,25 @@ void QuicPacketCreator::SetMaxPacketLength(QuicByteCount length) {
<< "Attempted to set max packet length too small";
}
+void QuicPacketCreator::SetSoftMaxPacketLength(QuicByteCount length) {
+ DCHECK(CanSetMaxPacketLength());
+ if (length > max_packet_length_) {
+ QUIC_BUG << ENDPOINT
+ << "Try to increase max_packet_length_ in "
+ "SetSoftMaxPacketLength, use SetMaxPacketLength instead.";
+ return;
+ }
+ if (framer_->GetMaxPlaintextSize(length) <
+ PacketHeaderSize() + MinPlaintextPacketSize(framer_->version())) {
+ QUIC_DLOG(INFO) << length << " is too small to fit packet header";
+ return;
+ }
+ QUIC_DVLOG(1) << "Setting soft max packet length to: " << length;
+ latched_hard_max_packet_length_ = max_packet_length_;
+ max_packet_length_ = length;
+ max_plaintext_size_ = framer_->GetMaxPlaintextSize(length);
+}
+
// Stops serializing version of the protocol in packets sent after this call.
// A packet that is already open might send kQuicVersionSize bytes less than the
// maximum packet size if we stop sending version before it is serialized.
@@ -216,8 +264,7 @@ bool QuicPacketCreator::ConsumeCryptoDataToFillCurrentPacket(
if (needs_full_padding) {
needs_full_padding_ = true;
}
- return AddFrame(*frame, /*save_retransmittable_frames*/ true,
- transmission_type);
+ return AddFrame(*frame, transmission_type);
}
bool QuicPacketCreator::ConsumeDataToFillCurrentPacket(
@@ -244,8 +291,7 @@ bool QuicPacketCreator::ConsumeDataToFillCurrentPacket(
delegate_->OnUnrecoverableError(QUIC_CRYPTO_CHLO_TOO_LARGE, error_details);
return false;
}
- if (!AddFrame(*frame, /*save_retransmittable_frames=*/true,
- transmission_type)) {
+ if (!AddFrame(*frame, transmission_type)) {
// Fails if we try to write unencrypted stream data.
return false;
}
@@ -259,14 +305,28 @@ bool QuicPacketCreator::ConsumeDataToFillCurrentPacket(
bool QuicPacketCreator::HasRoomForStreamFrame(QuicStreamId id,
QuicStreamOffset offset,
size_t data_size) {
- return BytesFree() >
- QuicFramer::GetMinStreamFrameSize(framer_->transport_version(), id,
- offset, true, data_size);
+ const size_t min_stream_frame_size = QuicFramer::GetMinStreamFrameSize(
+ framer_->transport_version(), id, offset, /*last_frame_in_packet=*/true,
+ data_size);
+ if (BytesFree() > min_stream_frame_size) {
+ return true;
+ }
+ if (!RemoveSoftMaxPacketLength()) {
+ return false;
+ }
+ return BytesFree() > min_stream_frame_size;
}
bool QuicPacketCreator::HasRoomForMessageFrame(QuicByteCount length) {
- return BytesFree() >= QuicFramer::GetMessageFrameSize(
- framer_->transport_version(), true, length);
+ const size_t message_frame_size = QuicFramer::GetMessageFrameSize(
+ framer_->transport_version(), /*last_frame_in_packet=*/true, length);
+ if (BytesFree() >= message_frame_size) {
+ return true;
+ }
+ if (!RemoveSoftMaxPacketLength()) {
+ return false;
+ }
+ return BytesFree() >= message_frame_size;
}
// TODO(fkastenholz): this method should not use constant values for
@@ -352,7 +412,8 @@ bool QuicPacketCreator::CreateCryptoFrame(EncryptionLevel level,
QuicFrame* frame) {
size_t min_frame_size =
QuicFramer::GetMinCryptoFrameSize(write_length, offset);
- if (BytesFree() <= min_frame_size) {
+ if (BytesFree() <= min_frame_size &&
+ (!RemoveSoftMaxPacketLength() || BytesFree() <= min_frame_size)) {
return false;
}
size_t max_write_length = BytesFree() - min_frame_size;
@@ -361,49 +422,6 @@ bool QuicPacketCreator::CreateCryptoFrame(EncryptionLevel level,
return true;
}
-void QuicPacketCreator::ReserializeAllFrames(
- const QuicPendingRetransmission& retransmission,
- char* buffer,
- size_t buffer_len) {
- DCHECK(queued_frames_.empty());
- DCHECK_EQ(0, packet_.num_padding_bytes);
- QUIC_BUG_IF(retransmission.retransmittable_frames.empty())
- << "Attempt to serialize empty packet";
- const EncryptionLevel default_encryption_level = packet_.encryption_level;
-
- // Temporarily set the packet number length and change the encryption level.
- packet_.packet_number_length = retransmission.packet_number_length;
- if (retransmission.num_padding_bytes == -1) {
- // Only retransmit padding when original packet needs full padding. Padding
- // from pending_padding_bytes_ are not retransmitted.
- needs_full_padding_ = true;
- }
- // Only preserve the original encryption level if it's a handshake packet or
- // if we haven't gone forward secure.
- if (retransmission.has_crypto_handshake ||
- packet_.encryption_level != ENCRYPTION_FORWARD_SECURE) {
- packet_.encryption_level = retransmission.encryption_level;
- }
-
- // Serialize the packet and restore packet number length state.
- for (const QuicFrame& frame : retransmission.retransmittable_frames) {
- bool success = AddFrame(frame, false, retransmission.transmission_type);
- QUIC_BUG_IF(!success) << " Failed to add frame of type:" << frame.type
- << " num_frames:"
- << retransmission.retransmittable_frames.size()
- << " retransmission.packet_number_length:"
- << retransmission.packet_number_length
- << " packet_.packet_number_length:"
- << packet_.packet_number_length;
- }
- packet_.transmission_type = retransmission.transmission_type;
- SerializePacket(buffer, buffer_len);
- packet_.original_packet_number = retransmission.packet_number;
- OnSerializedPacket();
- // Restore old values.
- packet_.encryption_level = default_encryption_level;
-}
-
void QuicPacketCreator::FlushCurrentPacket() {
if (!HasPendingFrames() && pending_padding_bytes_ == 0) {
return;
@@ -430,6 +448,7 @@ void QuicPacketCreator::OnSerializedPacket() {
SerializedPacket packet(std::move(packet_));
ClearPacket();
+ RemoveSoftMaxPacketLength();
delegate_->OnSerializedPacket(&packet);
}
@@ -438,15 +457,62 @@ void QuicPacketCreator::ClearPacket() {
packet_.has_stop_waiting = false;
packet_.has_crypto_handshake = NOT_HANDSHAKE;
packet_.num_padding_bytes = 0;
- packet_.original_packet_number.Clear();
packet_.transmission_type = NOT_RETRANSMISSION;
packet_.encrypted_buffer = nullptr;
packet_.encrypted_length = 0;
DCHECK(packet_.retransmittable_frames.empty());
+ DCHECK(packet_.nonretransmittable_frames.empty());
packet_.largest_acked.Clear();
needs_full_padding_ = false;
}
+size_t QuicPacketCreator::ReserializeInitialPacketInCoalescedPacket(
+ const SerializedPacket& packet,
+ 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())
+ << "Attempt to serialize empty ENCRYPTION_INITIAL packet in coalesced "
+ "packet";
+ ScopedPacketContextSwitcher switcher(
+ packet.packet_number -
+ 1, // -1 because serialize packet increase packet number.
+ 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;
+ return 0;
+ }
+ }
+ for (const QuicFrame& frame : packet.retransmittable_frames) {
+ if (!AddFrame(frame, packet.transmission_type)) {
+ QUIC_BUG << "Failed to serialize frame: " << frame;
+ return 0;
+ }
+ }
+ // Add necessary padding.
+ if (padding_size > 0) {
+ 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";
+ return 0;
+ }
+ }
+ SerializePacket(buffer, buffer_len);
+ const size_t encrypted_length = packet_.encrypted_length;
+ // Clear frames in packet_. No need to DeleteFrames since frames are owned by
+ // initial_packet.
+ packet_.retransmittable_frames.clear();
+ packet_.nonretransmittable_frames.clear();
+ ClearPacket();
+ return encrypted_length;
+}
+
void QuicPacketCreator::CreateAndSerializeStreamFrame(
QuicStreamId id,
size_t write_length,
@@ -530,9 +596,7 @@ void QuicPacketCreator::CreateAndSerializeStreamFrame(
return;
}
- if (can_set_transmission_type()) {
- packet_.transmission_type = transmission_type;
- }
+ packet_.transmission_type = transmission_type;
size_t encrypted_length = framer_->EncryptInPlace(
packet_.encryption_level, packet_.packet_number,
@@ -606,17 +670,10 @@ size_t QuicPacketCreator::PacketSize() {
return packet_size_;
}
-bool QuicPacketCreator::AddSavedFrame(const QuicFrame& frame,
- TransmissionType transmission_type) {
- return AddFrame(frame, /*save_retransmittable_frames=*/true,
- transmission_type);
-}
-
bool QuicPacketCreator::AddPaddedSavedFrame(
const QuicFrame& frame,
TransmissionType transmission_type) {
- if (AddFrame(frame, /*save_retransmittable_frames=*/true,
- transmission_type)) {
+ if (AddFrame(frame, transmission_type)) {
needs_full_padding_ = true;
return true;
}
@@ -635,7 +692,8 @@ void QuicPacketCreator::SerializePacket(char* encrypted_buffer,
MaybeAddPadding();
QUIC_DVLOG(2) << ENDPOINT << "Serializing packet " << header
- << QuicFramesToString(queued_frames_);
+ << QuicFramesToString(queued_frames_) << " at encryption_level "
+ << EncryptionLevelToString(packet_.encryption_level);
DCHECK_GE(max_plaintext_size_, packet_size_);
// Use the packet_size_ instead of the buffer size to ensure smaller
@@ -694,6 +752,7 @@ OwningSerializedPacketPointer
QuicPacketCreator::SerializeConnectivityProbingPacket() {
QUIC_BUG_IF(VersionHasIetfQuicFrames(framer_->transport_version()))
<< "Must not be version 99 to serialize padded ping connectivity probe";
+ RemoveSoftMaxPacketLength();
QuicPacketHeader header;
// FillPacketHeader increments packet_number_.
FillPacketHeader(&header);
@@ -729,6 +788,7 @@ QuicPacketCreator::SerializePathChallengeConnectivityProbingPacket(
<< "Must be version 99 to serialize path challenge connectivity probe, "
"is version "
<< framer_->transport_version();
+ RemoveSoftMaxPacketLength();
QuicPacketHeader header;
// FillPacketHeader increments packet_number_.
FillPacketHeader(&header);
@@ -765,6 +825,7 @@ QuicPacketCreator::SerializePathResponseConnectivityProbingPacket(
<< "Must be version 99 to serialize path response connectivity probe, is "
"version "
<< framer_->transport_version();
+ RemoveSoftMaxPacketLength();
QuicPacketHeader header;
// FillPacketHeader increments packet_number_.
FillPacketHeader(&header);
@@ -879,6 +940,44 @@ size_t QuicPacketCreator::BuildConnectivityProbingPacket(
return framer_->BuildDataPacket(header, frames, buffer, packet_length, level);
}
+size_t QuicPacketCreator::SerializeCoalescedPacket(
+ const QuicCoalescedPacket& coalesced,
+ char* buffer,
+ size_t buffer_len) {
+ QUIC_BUG_IF(packet_.num_padding_bytes != 0);
+ if (HasPendingFrames()) {
+ QUIC_BUG << "Try to serialize coalesced packet with pending frames";
+ return 0;
+ }
+ RemoveSoftMaxPacketLength();
+ QUIC_BUG_IF(coalesced.length() == 0)
+ << "Attempt to serialize empty coalesced packet";
+ size_t packet_length = 0;
+ if (coalesced.initial_packet() != nullptr) {
+ size_t initial_length = ReserializeInitialPacketInCoalescedPacket(
+ *coalesced.initial_packet(),
+ /*padding_size=*/coalesced.max_packet_length() - coalesced.length(),
+ buffer, buffer_len);
+ if (initial_length == 0) {
+ QUIC_BUG << "Failed to reserialize ENCRYPTION_INITIAL packet in "
+ "coalesced packet";
+ return 0;
+ }
+ buffer += initial_length;
+ buffer_len -= initial_length;
+ packet_length += initial_length;
+ }
+ size_t length_copied = 0;
+ if (!coalesced.CopyEncryptedBuffers(buffer, buffer_len, &length_copied)) {
+ return 0;
+ }
+ packet_length += length_copied;
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Successfully serialized coalesced packet of length: "
+ << packet_length;
+ return packet_length;
+}
+
// TODO(b/74062209): Make this a public method of framer?
SerializedPacket QuicPacketCreator::NoPacket() {
return SerializedPacket(QuicPacketNumber(), PACKET_1BYTE_PACKET_NUMBER,
@@ -985,13 +1084,12 @@ void QuicPacketCreator::SetRetryToken(QuicStringPiece retry_token) {
bool QuicPacketCreator::ConsumeRetransmittableControlFrame(
const QuicFrame& frame) {
- DCHECK(combine_generator_and_creator_);
QUIC_BUG_IF(IsControlFrame(frame.type) && !GetControlFrameId(frame))
<< "Adding a control frame with no control frame id: " << frame;
DCHECK(QuicUtils::IsRetransmittableFrame(frame.type)) << frame;
MaybeBundleAckOpportunistically();
if (HasPendingFrames()) {
- if (AddSavedFrame(frame, next_transmission_type_)) {
+ if (AddFrame(frame, next_transmission_type_)) {
// There is pending frames and current frame fits.
return true;
}
@@ -1003,7 +1101,7 @@ bool QuicPacketCreator::ConsumeRetransmittableControlFrame(
// Do not check congestion window for ping or connection close frames.
return false;
}
- const bool success = AddSavedFrame(frame, next_transmission_type_);
+ const bool success = AddFrame(frame, next_transmission_type_);
QUIC_BUG_IF(!success) << "Failed to add frame:" << frame
<< " transmission_type:" << next_transmission_type_;
return success;
@@ -1013,7 +1111,6 @@ QuicConsumedData QuicPacketCreator::ConsumeData(QuicStreamId id,
size_t write_length,
QuicStreamOffset offset,
StreamSendingState state) {
- DCHECK(combine_generator_and_creator_);
QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
"generator tries to write stream data.";
bool has_handshake = QuicUtils::IsCryptoStreamId(transport_version(), id);
@@ -1042,7 +1139,8 @@ QuicConsumedData QuicPacketCreator::ConsumeData(QuicStreamId id,
// the slow path loop.
bool run_fast_path =
!has_handshake && state != FIN_AND_PADDING && !HasPendingFrames() &&
- write_length - total_bytes_consumed > kMaxOutgoingPacketSize;
+ write_length - total_bytes_consumed > kMaxOutgoingPacketSize &&
+ latched_hard_max_packet_length_ == 0;
while (!run_fast_path && delegate_->ShouldGeneratePacket(
HAS_RETRANSMITTABLE_DATA,
@@ -1081,7 +1179,8 @@ QuicConsumedData QuicPacketCreator::ConsumeData(QuicStreamId id,
run_fast_path =
!has_handshake && state != FIN_AND_PADDING && !HasPendingFrames() &&
- write_length - total_bytes_consumed > kMaxOutgoingPacketSize;
+ write_length - total_bytes_consumed > kMaxOutgoingPacketSize &&
+ latched_hard_max_packet_length_ == 0;
}
if (run_fast_path) {
@@ -1103,7 +1202,6 @@ QuicConsumedData QuicPacketCreator::ConsumeDataFastPath(
QuicStreamOffset offset,
bool fin,
size_t total_bytes_consumed) {
- DCHECK(combine_generator_and_creator_);
DCHECK(!QuicUtils::IsCryptoStreamId(transport_version(), id));
while (total_bytes_consumed < write_length &&
@@ -1114,6 +1212,19 @@ QuicConsumedData QuicPacketCreator::ConsumeDataFastPath(
CreateAndSerializeStreamFrame(id, write_length, total_bytes_consumed,
offset + total_bytes_consumed, fin,
next_transmission_type_, &bytes_consumed);
+ if (GetQuicReloadableFlag(
+ quic_close_connection_on_failed_consume_data_fast_path)) {
+ QUIC_RELOADABLE_FLAG_COUNT(
+ quic_close_connection_on_failed_consume_data_fast_path);
+ if (bytes_consumed == 0) {
+ const std::string error_details =
+ "Failed in CreateAndSerializeStreamFrame.";
+ QUIC_BUG << error_details;
+ delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET,
+ error_details);
+ break;
+ }
+ }
total_bytes_consumed += bytes_consumed;
}
@@ -1124,7 +1235,6 @@ QuicConsumedData QuicPacketCreator::ConsumeDataFastPath(
size_t QuicPacketCreator::ConsumeCryptoData(EncryptionLevel level,
size_t write_length,
QuicStreamOffset offset) {
- DCHECK(combine_generator_and_creator_);
QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
"generator tries to write crypto data.";
MaybeBundleAckOpportunistically();
@@ -1162,7 +1272,6 @@ size_t QuicPacketCreator::ConsumeCryptoData(EncryptionLevel level,
}
void QuicPacketCreator::GenerateMtuDiscoveryPacket(QuicByteCount target_mtu) {
- DCHECK(combine_generator_and_creator_);
// MTU discovery frames must be sent by themselves.
if (!CanSetMaxPacketLength()) {
QUIC_BUG << "MTU discovery packets should only be sent when no other "
@@ -1190,7 +1299,6 @@ void QuicPacketCreator::GenerateMtuDiscoveryPacket(QuicByteCount target_mtu) {
}
void QuicPacketCreator::MaybeBundleAckOpportunistically() {
- DCHECK(combine_generator_and_creator_);
if (has_ack()) {
// Ack already queued, nothing to do.
return;
@@ -1206,13 +1314,12 @@ void QuicPacketCreator::MaybeBundleAckOpportunistically() {
}
bool QuicPacketCreator::FlushAckFrame(const QuicFrames& frames) {
- DCHECK(combine_generator_and_creator_);
QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
"generator tries to send ACK frame.";
for (const auto& frame : frames) {
DCHECK(frame.type == ACK_FRAME || frame.type == STOP_WAITING_FRAME);
if (HasPendingFrames()) {
- if (AddSavedFrame(frame, next_transmission_type_)) {
+ if (AddFrame(frame, next_transmission_type_)) {
// There is pending frames and current frame fits.
continue;
}
@@ -1224,19 +1331,17 @@ bool QuicPacketCreator::FlushAckFrame(const QuicFrames& frames) {
NOT_HANDSHAKE)) {
return false;
}
- const bool success = AddSavedFrame(frame, next_transmission_type_);
+ const bool success = AddFrame(frame, next_transmission_type_);
QUIC_BUG_IF(!success) << "Failed to flush " << frame;
}
return true;
}
void QuicPacketCreator::AddRandomPadding() {
- DCHECK(combine_generator_and_creator_);
AddPendingPadding(random_->RandUint64() % kMaxNumRandomPaddingBytes + 1);
}
void QuicPacketCreator::AttachPacketFlusher() {
- DCHECK(combine_generator_and_creator_);
flusher_attached_ = true;
if (!write_start_packet_number_.IsInitialized()) {
write_start_packet_number_ = NextSendingPacketNumber();
@@ -1244,7 +1349,6 @@ void QuicPacketCreator::AttachPacketFlusher() {
}
void QuicPacketCreator::Flush() {
- DCHECK(combine_generator_and_creator_);
FlushCurrentPacket();
SendRemainingPendingPadding();
flusher_attached_ = false;
@@ -1262,7 +1366,6 @@ void QuicPacketCreator::Flush() {
}
void QuicPacketCreator::SendRemainingPendingPadding() {
- DCHECK(combine_generator_and_creator_);
while (
pending_padding_bytes() > 0 && !HasPendingFrames() &&
delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)) {
@@ -1271,7 +1374,6 @@ void QuicPacketCreator::SendRemainingPendingPadding() {
}
void QuicPacketCreator::SetServerConnectionIdLength(uint32_t length) {
- DCHECK(combine_generator_and_creator_);
if (length == 0) {
SetServerConnectionIdIncluded(CONNECTION_ID_ABSENT);
} else {
@@ -1280,16 +1382,11 @@ void QuicPacketCreator::SetServerConnectionIdLength(uint32_t length) {
}
void QuicPacketCreator::SetTransmissionType(TransmissionType type) {
- DCHECK(combine_generator_and_creator_);
- SetTransmissionTypeOfNextPackets(type);
- if (can_set_transmission_type()) {
- next_transmission_type_ = type;
- }
+ next_transmission_type_ = type;
}
MessageStatus QuicPacketCreator::AddMessageFrame(QuicMessageId message_id,
QuicMemSliceSpan message) {
- DCHECK(combine_generator_and_creator_);
QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
"generator tries to add message frame.";
MaybeBundleAckOpportunistically();
@@ -1301,7 +1398,7 @@ MessageStatus QuicPacketCreator::AddMessageFrame(QuicMessageId message_id,
FlushCurrentPacket();
}
QuicMessageFrame* frame = new QuicMessageFrame(message_id, message);
- const bool success = AddSavedFrame(QuicFrame(frame), next_transmission_type_);
+ const bool success = AddFrame(QuicFrame(frame), next_transmission_type_);
if (!success) {
QUIC_BUG << "Failed to send message " << message_id;
delete frame;
@@ -1352,7 +1449,6 @@ void QuicPacketCreator::FillPacketHeader(QuicPacketHeader* header) {
}
bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
- bool save_retransmittable_frames,
TransmissionType transmission_type) {
QUIC_DVLOG(1) << ENDPOINT << "Adding frame with transmission type "
<< TransmissionTypeToString(transmission_type) << ": " << frame;
@@ -1369,9 +1465,23 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA, error_details);
return false;
}
+
+ if (GetQuicRestartFlag(quic_coalesce_stream_frames_2) &&
+ frame.type == STREAM_FRAME &&
+ MaybeCoalesceStreamFrame(frame.stream_frame)) {
+ QUIC_RESTART_FLAG_COUNT_N(quic_coalesce_stream_frames_2, 1, 3);
+ return true;
+ }
+
size_t frame_len = framer_->GetSerializedFrameLength(
frame, BytesFree(), queued_frames_.empty(),
/* last_frame_in_packet= */ true, GetPacketNumberLength());
+ if (frame_len == 0 && RemoveSoftMaxPacketLength()) {
+ // Remove soft max_packet_length and retry.
+ frame_len = framer_->GetSerializedFrameLength(
+ frame, BytesFree(), queued_frames_.empty(),
+ /* last_frame_in_packet= */ true, GetPacketNumberLength());
+ }
if (frame_len == 0) {
// Current open packet is full.
FlushCurrentPacket();
@@ -1381,14 +1491,22 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
packet_size_ += ExpansionOnNewFrame() + frame_len;
- if (save_retransmittable_frames &&
- QuicUtils::IsRetransmittableFrame(frame.type)) {
+ if (QuicUtils::IsRetransmittableFrame(frame.type)) {
packet_.retransmittable_frames.push_back(frame);
queued_frames_.push_back(frame);
if (QuicUtils::IsHandshakeFrame(frame, framer_->transport_version())) {
packet_.has_crypto_handshake = IS_HANDSHAKE;
}
} else {
+ if (frame.type == PADDING_FRAME &&
+ frame.padding_frame.num_padding_bytes == -1) {
+ // Populate the actual length of full padding frame, such that one can
+ // know how much padding is actually added.
+ packet_.nonretransmittable_frames.push_back(
+ QuicFrame(QuicPaddingFrame(frame_len)));
+ } else {
+ packet_.nonretransmittable_frames.push_back(frame);
+ }
queued_frames_.push_back(frame);
}
@@ -1405,13 +1523,57 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
// Packet transmission type is determined by the last added retransmittable
// frame.
- if (can_set_transmission_type() &&
- QuicUtils::IsRetransmittableFrame(frame.type)) {
+ if (QuicUtils::IsRetransmittableFrame(frame.type)) {
packet_.transmission_type = transmission_type;
}
return true;
}
+bool QuicPacketCreator::MaybeCoalesceStreamFrame(const QuicStreamFrame& frame) {
+ if (queued_frames_.empty() || queued_frames_.back().type != STREAM_FRAME) {
+ return false;
+ }
+ QuicStreamFrame* candidate = &queued_frames_.back().stream_frame;
+ if (candidate->stream_id != frame.stream_id ||
+ candidate->offset + candidate->data_length != frame.offset ||
+ frame.data_length > BytesFree()) {
+ return false;
+ }
+ candidate->data_length += frame.data_length;
+ candidate->fin = frame.fin;
+
+ // The back of retransmittable frames must be the same as the original
+ // queued frames' back.
+ DCHECK_EQ(packet_.retransmittable_frames.back().type, STREAM_FRAME);
+ QuicStreamFrame* retransmittable =
+ &packet_.retransmittable_frames.back().stream_frame;
+ DCHECK_EQ(retransmittable->stream_id, frame.stream_id);
+ DCHECK_EQ(retransmittable->offset + retransmittable->data_length,
+ frame.offset);
+ retransmittable->data_length = candidate->data_length;
+ retransmittable->fin = candidate->fin;
+ packet_size_ += frame.data_length;
+ if (debug_delegate_ != nullptr) {
+ debug_delegate_->OnStreamFrameCoalesced(*candidate);
+ }
+ return true;
+}
+
+bool QuicPacketCreator::RemoveSoftMaxPacketLength() {
+ if (latched_hard_max_packet_length_ == 0) {
+ return false;
+ }
+ if (!CanSetMaxPacketLength()) {
+ return false;
+ }
+ QUIC_DVLOG(1) << "Restoring max packet length to: "
+ << latched_hard_max_packet_length_;
+ SetMaxPacketLength(latched_hard_max_packet_length_);
+ // Reset latched_max_packet_length_.
+ latched_hard_max_packet_length_ = 0;
+ return true;
+}
+
void QuicPacketCreator::MaybeAddPadding() {
// The current packet should have no padding bytes because padding is only
// added when this method is called just before the packet is serialized.
@@ -1425,6 +1587,25 @@ void QuicPacketCreator::MaybeAddPadding() {
needs_full_padding_ = true;
}
+ // Packet coalescer pads INITIAL packets, so the creator should not.
+ if (framer_->version().CanSendCoalescedPackets() &&
+ (packet_.encryption_level == ENCRYPTION_INITIAL ||
+ packet_.encryption_level == ENCRYPTION_HANDSHAKE)) {
+ // TODO(fayang): MTU discovery packets should not ever be sent as
+ // ENCRYPTION_INITIAL or ENCRYPTION_HANDSHAKE.
+ bool is_mtu_discovery = false;
+ for (const auto& frame : packet_.nonretransmittable_frames) {
+ if (frame.type == MTU_DISCOVERY_FRAME) {
+ is_mtu_discovery = true;
+ break;
+ }
+ }
+ if (!is_mtu_discovery) {
+ // Do not add full padding if connection tries to coalesce packet.
+ needs_full_padding_ = false;
+ }
+ }
+
// Header protection requires a minimum plaintext packet size.
size_t extra_padding_bytes = 0;
if (framer_->version().HasHeaderProtection()) {
@@ -1456,7 +1637,7 @@ void QuicPacketCreator::MaybeAddPadding() {
std::max<int16_t>(packet_.num_padding_bytes, extra_padding_bytes);
}
- bool success = AddFrame(QuicFrame(QuicPaddingFrame(padding_bytes)), false,
+ bool success = AddFrame(QuicFrame(QuicPaddingFrame(padding_bytes)),
packet_.transmission_type);
QUIC_BUG_IF(!success) << "Failed to add padding_bytes: " << padding_bytes
<< " transmission_type: "
@@ -1511,19 +1692,6 @@ void QuicPacketCreator::SetClientConnectionId(
client_connection_id_ = client_connection_id;
}
-void QuicPacketCreator::SetTransmissionTypeOfNextPackets(
- TransmissionType type) {
- DCHECK(can_set_transmission_type_);
-
- if (!can_set_transmission_type()) {
- QUIC_DVLOG_IF(1, type != packet_.transmission_type)
- << ENDPOINT << "Setting Transmission type to "
- << TransmissionTypeToString(type);
-
- packet_.transmission_type = type;
- }
-}
-
QuicPacketLength QuicPacketCreator::GetCurrentLargestMessagePayload() const {
if (!VersionSupportsMessageFrames(framer_->transport_version())) {
return 0;
@@ -1536,8 +1704,12 @@ QuicPacketLength QuicPacketCreator::GetCurrentLargestMessagePayload() const {
VARIABLE_LENGTH_INTEGER_LENGTH_0, 0, GetLengthLength());
// This is the largest possible message payload when the length field is
// omitted.
- return max_plaintext_size_ -
- std::min(max_plaintext_size_, packet_header_size + kQuicFrameTypeSize);
+ size_t max_plaintext_size =
+ latched_hard_max_packet_length_ == 0
+ ? max_plaintext_size_
+ : framer_->GetMaxPlaintextSize(latched_hard_max_packet_length_);
+ return max_plaintext_size -
+ std::min(max_plaintext_size, packet_header_size + kQuicFrameTypeSize);
}
QuicPacketLength QuicPacketCreator::GetGuaranteedLargestMessagePayload() const {
@@ -1566,9 +1738,13 @@ QuicPacketLength QuicPacketCreator::GetGuaranteedLargestMessagePayload() const {
VARIABLE_LENGTH_INTEGER_LENGTH_0, 0, length_length);
// This is the largest possible message payload when the length field is
// omitted.
+ size_t max_plaintext_size =
+ latched_hard_max_packet_length_ == 0
+ ? max_plaintext_size_
+ : framer_->GetMaxPlaintextSize(latched_hard_max_packet_length_);
const QuicPacketLength largest_payload =
- max_plaintext_size_ -
- std::min(max_plaintext_size_, packet_header_size + kQuicFrameTypeSize);
+ max_plaintext_size -
+ std::min(max_plaintext_size, packet_header_size + kQuicFrameTypeSize);
// This must always be less than or equal to GetCurrentLargestMessagePayload.
DCHECK_LE(largest_payload, GetCurrentLargestMessagePayload());
return largest_payload;
@@ -1615,7 +1791,6 @@ QuicPacketNumber QuicPacketCreator::NextSendingPacketNumber() const {
}
bool QuicPacketCreator::PacketFlusherAttached() const {
- DCHECK(combine_generator_and_creator_);
return flusher_attached_;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.h b/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.h
index f202af0cc47..eb7b6274af3 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.h
@@ -2,8 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Accumulates frames for the next packet until more frames no longer fit or
-// it's time to create a packet from them.
+// Responsible for creating packets on behalf of a QuicConnection.
+// Packets are serialized just-in-time. Stream data and control frames will be
+// requested from the Connection just-in-time. Frames are accumulated into
+// "current" packet until no more frames can fit, then current packet gets
+// serialized and passed to connection via OnSerializedPacket().
+//
+// Whether a packet should be serialized is determined by whether delegate is
+// writable. If the Delegate is not writable, then no operations will cause
+// a packet to be serialized.
#ifndef QUICHE_QUIC_CORE_QUIC_PACKET_CREATOR_H_
#define QUICHE_QUIC_CORE_QUIC_PACKET_CREATOR_H_
@@ -13,9 +20,10 @@
#include <utility>
#include <vector>
+#include "net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_coalesced_packet.h"
#include "net/third_party/quiche/src/quic/core/quic_framer.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
-#include "net/third_party/quiche/src/quic/core/quic_pending_retransmission.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
@@ -60,6 +68,10 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// Called when a frame has been added to the current packet.
virtual void OnFrameAddedToPacket(const QuicFrame& /*frame*/) {}
+
+ // Called when a stream frame is coalesced with an existing stream frame.
+ // |frame| is the new stream frame.
+ virtual void OnStreamFrameCoalesced(const QuicStreamFrame& /*frame*/) {}
};
QuicPacketCreator(QuicConnectionId server_connection_id,
@@ -137,12 +149,6 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// |length|.
bool HasRoomForMessageFrame(QuicByteCount length);
- // Re-serializes frames with the original packet's packet number length.
- // Used for retransmitting packets to ensure they aren't too long.
- void ReserializeAllFrames(const QuicPendingRetransmission& retransmission,
- char* buffer,
- size_t buffer_len);
-
// Serializes all added frames into a single packet and invokes the delegate_
// to further process the SerializedPacket.
void FlushCurrentPacket();
@@ -189,8 +195,7 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// Tries to add |frame| to the packet creator's list of frames to be
// serialized. If the frame does not fit into the current packet, flushes the
// packet and returns false.
- bool AddSavedFrame(const QuicFrame& frame,
- TransmissionType transmission_type);
+ bool AddFrame(const QuicFrame& frame, TransmissionType transmission_type);
// Identical to AddSavedFrame, but allows the frame to be padded.
bool AddPaddedSavedFrame(const QuicFrame& frame,
@@ -271,13 +276,15 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// Sets the maximum packet length.
void SetMaxPacketLength(QuicByteCount length);
+ // Set a soft maximum packet length in the creator. If a packet cannot be
+ // successfully created, creator will remove the soft limit and use the actual
+ // max packet length.
+ void SetSoftMaxPacketLength(QuicByteCount length);
+
// Increases pending_padding_bytes by |size|. Pending padding will be sent by
// MaybeAddPadding().
void AddPendingPadding(QuicByteCount size);
- // Sets transmission type of next constructed packets.
- void SetTransmissionTypeOfNextPackets(TransmissionType type);
-
// Sets the retry token to be sent over the wire in IETF Initial packets.
void SetRetryToken(QuicStringPiece retry_token);
@@ -363,12 +370,6 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
debug_delegate_ = debug_delegate;
}
- void set_can_set_transmission_type(bool can_set_transmission_type) {
- can_set_transmission_type_ = can_set_transmission_type;
- }
-
- bool can_set_transmission_type() const { return can_set_transmission_type_; }
-
QuicByteCount pending_padding_bytes() const { return pending_padding_bytes_; }
QuicTransportVersion transport_version() const {
@@ -382,19 +383,13 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
bool PacketFlusherAttached() const;
void set_fully_pad_crypto_handshake_packets(bool new_value) {
- DCHECK(combine_generator_and_creator_);
fully_pad_crypto_handshake_packets_ = new_value;
}
bool fully_pad_crypto_handshake_packets() const {
- DCHECK(combine_generator_and_creator_);
return fully_pad_crypto_handshake_packets_;
}
- bool combine_generator_and_creator() const {
- return combine_generator_and_creator_;
- }
-
// Serialize a probing packet that uses IETF QUIC's PATH CHALLENGE frame. Also
// fills the packet with padding.
size_t BuildPaddedPathChallengePacket(const QuicPacketHeader& header,
@@ -422,6 +417,12 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
size_t packet_length,
EncryptionLevel level);
+ // Serializes |coalesced| to provided |buffer|, returns coalesced packet
+ // length if serialization succeeds. Otherwise, returns 0.
+ size_t SerializeCoalescedPacket(const QuicCoalescedPacket& coalesced,
+ char* buffer,
+ size_t buffer_len);
+
private:
friend class test::QuicPacketCreatorPeer;
@@ -444,13 +445,6 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
void FillPacketHeader(QuicPacketHeader* header);
- // Adds a |frame| if there is space and returns false and flushes all pending
- // frames if there isn't room. If |save_retransmittable_frames| is true,
- // saves the |frame| in the next SerializedPacket.
- bool AddFrame(const QuicFrame& frame,
- bool save_retransmittable_frames,
- TransmissionType transmission_type);
-
// Adds a padding frame to the current packet (if there is space) when (1)
// current packet needs full padding or (2) there are pending paddings.
void MaybeAddPadding();
@@ -468,6 +462,27 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// Clears all fields of packet_ that should be cleared between serializations.
void ClearPacket();
+ // Re-serialzes frames of ENCRYPTION_INITIAL packet in coalesced packet with
+ // the original packet's packet number and packet number length.
+ // |padding_size| indicates the size of necessary padding. Returns 0 if
+ // serialization fails.
+ size_t ReserializeInitialPacketInCoalescedPacket(
+ const SerializedPacket& packet,
+ size_t padding_size,
+ char* buffer,
+ size_t buffer_len);
+
+ // Tries to coalesce |frame| with the back of |queued_frames_|.
+ // Returns true on success.
+ bool MaybeCoalesceStreamFrame(const QuicStreamFrame& frame);
+
+ // Called to remove the soft max_packet_length and restores
+ // latched_hard_max_packet_length_ if the packet cannot accommodate a single
+ // frame. Returns true if the soft limit is successfully removed. Returns
+ // false if either there is no current soft limit or there are queued frames
+ // (such that the packet length cannot be changed).
+ bool RemoveSoftMaxPacketLength();
+
// Returns true if a diversification nonce should be included in the current
// packet's header.
bool IncludeNonceInPublicHeader() const;
@@ -553,10 +568,6 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// bytes.
bool needs_full_padding_;
- // If true, packet_'s transmission type is only set by
- // SetPacketTransmissionType and does not get cleared in ClearPacket.
- bool can_set_transmission_type_;
-
// Transmission type of the next serialized packet.
TransmissionType next_transmission_type_;
@@ -571,8 +582,10 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// flusher detaches.
QuicPacketNumber write_start_packet_number_;
- // Latched value of quic_combine_generator_and_creator.
- const bool combine_generator_and_creator_;
+ // If not 0, this latches the actual max_packet_length when
+ // SetSoftMaxPacketLength is called and max_packet_length_ gets
+ // set to a soft value.
+ QuicByteCount latched_hard_max_packet_length_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator_test.cc
index a647994fc8a..6ca369cd5ec 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
@@ -5,6 +5,7 @@
#include "net/third_party/quiche/src/quic/core/quic_packet_creator.h"
#include <cstdint>
+#include <limits>
#include <memory>
#include <ostream>
#include <string>
@@ -14,13 +15,15 @@
#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
-#include "net/third_party/quiche/src/quic/core/quic_pending_retransmission.h"
#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
@@ -28,6 +31,7 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simple_data_producer.h"
+#include "net/third_party/quiche/src/quic/test_tools/simple_quic_framer.h"
using testing::_;
using testing::DoAll;
@@ -44,8 +48,9 @@ namespace {
const QuicPacketNumber kPacketNumber = QuicPacketNumber(UINT64_C(0x12345678));
// Use fields in which each byte is distinct to ensure that every byte is
// framed correctly. The values are otherwise arbitrary.
-const QuicConnectionId kTestConnectionId =
- TestConnectionId(UINT64_C(0xFEDCBA9876543210));
+QuicConnectionId CreateTestConnectionId() {
+ return TestConnectionId(UINT64_C(0xFEDCBA9876543210));
+}
// Run tests with combinations of {ParsedQuicVersion,
// ToggleVersionSerialization}.
@@ -79,6 +84,8 @@ class MockDebugDelegate : public QuicPacketCreator::DebugDelegate {
~MockDebugDelegate() override = default;
MOCK_METHOD1(OnFrameAddedToPacket, void(const QuicFrame& frame));
+
+ MOCK_METHOD1(OnStreamFrameCoalesced, void(const QuicStreamFrame& frame));
};
class TestPacketCreator : public QuicPacketCreator {
@@ -222,7 +229,7 @@ class QuicPacketCreatorTest : public QuicTestWithParam<TestParams> {
EXPECT_EQ(STREAM_FRAME, frame.type);
EXPECT_EQ(stream_id, frame.stream_frame.stream_id);
char buf[kMaxOutgoingPacketSize];
- QuicDataWriter writer(kMaxOutgoingPacketSize, buf, HOST_BYTE_ORDER);
+ QuicDataWriter writer(kMaxOutgoingPacketSize, buf, quiche::HOST_BYTE_ORDER);
if (frame.stream_frame.data_length > 0) {
producer_.WriteStreamData(stream_id, frame.stream_frame.offset,
frame.stream_frame.data_length, &writer);
@@ -260,18 +267,6 @@ class QuicPacketCreatorTest : public QuicTestWithParam<TestParams> {
/* data_length= */ 0);
}
- QuicPendingRetransmission CreateRetransmission(
- const QuicFrames& retransmittable_frames,
- bool has_crypto_handshake,
- int num_padding_bytes,
- EncryptionLevel encryption_level,
- QuicPacketNumberLength packet_number_length) {
- return QuicPendingRetransmission(QuicPacketNumber(1u), NOT_RETRANSMISSION,
- retransmittable_frames,
- has_crypto_handshake, num_padding_bytes,
- encryption_level, packet_number_length);
- }
-
bool IsDefaultTestConfiguration() {
TestParams p = GetParam();
return p.version == AllSupportedVersions()[0] && p.version_serialization;
@@ -318,8 +313,10 @@ TEST_P(QuicPacketCreatorTest, SerializeFrames) {
if (level != ENCRYPTION_INITIAL && level != ENCRYPTION_HANDSHAKE) {
frames_.push_back(
QuicFrame(QuicStreamFrame(stream_id, false, 0u, QuicStringPiece())));
- frames_.push_back(
- QuicFrame(QuicStreamFrame(stream_id, true, 0u, QuicStringPiece())));
+ if (!GetQuicRestartFlag(quic_coalesce_stream_frames_2)) {
+ frames_.push_back(
+ QuicFrame(QuicStreamFrame(stream_id, true, 0u, QuicStringPiece())));
+ }
}
SerializedPacket serialized = SerializeAllFrames(frames_);
EXPECT_EQ(level, serialized.encryption_level);
@@ -342,7 +339,9 @@ TEST_P(QuicPacketCreatorTest, SerializeFrames) {
.WillOnce(Return(true));
if (level != ENCRYPTION_INITIAL && level != ENCRYPTION_HANDSHAKE) {
EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
+ if (!GetQuicRestartFlag(quic_coalesce_stream_frames_2)) {
+ EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
+ }
}
if (client_framer_.version().HasHeaderProtection()) {
EXPECT_CALL(framer_visitor_, OnPaddingFrame(_))
@@ -354,248 +353,6 @@ TEST_P(QuicPacketCreatorTest, SerializeFrames) {
}
}
-TEST_P(QuicPacketCreatorTest, ReserializeFramesWithSequenceNumberLength) {
- if (VersionHasIetfInvariantHeader(client_framer_.transport_version())) {
- creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
- }
- // If the original packet number length, the current packet number
- // length, and the configured send packet number length are different, the
- // retransmit must sent with the original length and the others do not change.
- QuicPacketCreatorPeer::SetPacketNumberLength(&creator_,
- PACKET_2BYTE_PACKET_NUMBER);
- QuicFrames frames;
- std::string data("a");
- if (!QuicVersionUsesCryptoFrames(client_framer_.transport_version())) {
- QuicStreamFrame stream_frame(
- QuicUtils::GetCryptoStreamId(client_framer_.transport_version()),
- /*fin=*/false, 0u, QuicStringPiece());
- frames.push_back(QuicFrame(stream_frame));
- } else {
- producer_.SaveCryptoData(ENCRYPTION_INITIAL, 0, data);
- frames.push_back(
- QuicFrame(new QuicCryptoFrame(ENCRYPTION_INITIAL, 0, data.length())));
- }
- char buffer[kMaxOutgoingPacketSize];
- QuicPendingRetransmission retransmission(CreateRetransmission(
- frames, true /* has_crypto_handshake */, -1 /* needs full padding */,
- ENCRYPTION_INITIAL, PACKET_4BYTE_PACKET_NUMBER));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- creator_.ReserializeAllFrames(retransmission, buffer, kMaxOutgoingPacketSize);
- // The packet number length is updated after every packet is sent,
- // so there is no need to restore the old length after sending.
- EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER,
- QuicPacketCreatorPeer::GetPacketNumberLength(&creator_));
- EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER,
- serialized_packet_.packet_number_length);
-
- {
- InSequence s;
- EXPECT_CALL(framer_visitor_, OnPacket());
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_));
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
- EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- if (!QuicVersionUsesCryptoFrames(client_framer_.transport_version())) {
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- } else {
- EXPECT_CALL(framer_visitor_, OnCryptoFrame(_));
- }
- EXPECT_CALL(framer_visitor_, OnPaddingFrame(_));
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
- }
- ProcessPacket(serialized_packet_);
- DeleteFrames(&frames);
-}
-
-TEST_P(QuicPacketCreatorTest, ReserializeCryptoFrameWithForwardSecurity) {
- QuicFrames frames;
- std::string data("a");
- if (!QuicVersionUsesCryptoFrames(client_framer_.transport_version())) {
- QuicStreamFrame stream_frame(
- QuicUtils::GetCryptoStreamId(client_framer_.transport_version()),
- /*fin=*/false, 0u, QuicStringPiece());
- frames.push_back(QuicFrame(stream_frame));
- } else {
- producer_.SaveCryptoData(ENCRYPTION_INITIAL, 0, data);
- frames.push_back(
- QuicFrame(new QuicCryptoFrame(ENCRYPTION_INITIAL, 0, data.length())));
- }
- creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
- char buffer[kMaxOutgoingPacketSize];
- QuicPendingRetransmission retransmission(CreateRetransmission(
- frames, true /* has_crypto_handshake */, -1 /* needs full padding */,
- ENCRYPTION_INITIAL,
- QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- creator_.ReserializeAllFrames(retransmission, buffer, kMaxOutgoingPacketSize);
- EXPECT_EQ(ENCRYPTION_INITIAL, serialized_packet_.encryption_level);
- DeleteFrames(&frames);
-}
-
-TEST_P(QuicPacketCreatorTest, ReserializeFrameWithForwardSecurity) {
- QuicStreamFrame stream_frame(0u, /*fin=*/false, 0u, QuicStringPiece());
- QuicFrames frames;
- frames.push_back(QuicFrame(stream_frame));
- creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
- char buffer[kMaxOutgoingPacketSize];
- QuicPendingRetransmission retransmission(CreateRetransmission(
- frames, false /* has_crypto_handshake */, 0 /* no padding */,
- ENCRYPTION_INITIAL,
- QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- creator_.ReserializeAllFrames(retransmission, buffer, kMaxOutgoingPacketSize);
- EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, serialized_packet_.encryption_level);
-}
-
-TEST_P(QuicPacketCreatorTest, ReserializeFramesWithFullPadding) {
- QuicFrame frame;
- std::string data = "fake handshake message data";
- if (!QuicVersionUsesCryptoFrames(client_framer_.transport_version())) {
- MakeIOVector(data, &iov_);
- producer_.SaveStreamData(
- QuicUtils::GetCryptoStreamId(client_framer_.transport_version()), &iov_,
- 1u, 0u, iov_.iov_len);
- QuicPacketCreatorPeer::CreateStreamFrame(
- &creator_,
- QuicUtils::GetCryptoStreamId(client_framer_.transport_version()),
- iov_.iov_len, 0u, false, &frame);
- } else {
- producer_.SaveCryptoData(ENCRYPTION_INITIAL, 0, data);
- EXPECT_TRUE(QuicPacketCreatorPeer::CreateCryptoFrame(
- &creator_, ENCRYPTION_INITIAL, data.length(), 0, &frame));
- }
- QuicFrames frames;
- frames.push_back(frame);
- char buffer[kMaxOutgoingPacketSize];
- QuicPendingRetransmission retransmission(CreateRetransmission(
- frames, true /* has_crypto_handshake */, -1 /* needs full padding */,
- ENCRYPTION_INITIAL,
- QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- creator_.ReserializeAllFrames(retransmission, buffer, kMaxOutgoingPacketSize);
- EXPECT_EQ(kDefaultMaxPacketSize, serialized_packet_.encrypted_length);
- DeleteFrames(&frames);
-}
-
-TEST_P(QuicPacketCreatorTest, DoNotRetransmitPendingPadding) {
- QuicFrame frame;
- std::string data = "fake message data";
- if (!QuicVersionUsesCryptoFrames(client_framer_.transport_version())) {
- MakeIOVector(data, &iov_);
- producer_.SaveStreamData(
- QuicUtils::GetCryptoStreamId(client_framer_.transport_version()), &iov_,
- 1u, 0u, iov_.iov_len);
- QuicPacketCreatorPeer::CreateStreamFrame(
- &creator_,
- QuicUtils::GetCryptoStreamId(client_framer_.transport_version()),
- iov_.iov_len, 0u, false, &frame);
- } else {
- producer_.SaveCryptoData(ENCRYPTION_INITIAL, 0, data);
- EXPECT_TRUE(QuicPacketCreatorPeer::CreateCryptoFrame(
- &creator_, ENCRYPTION_INITIAL, data.length(), 0, &frame));
- }
-
- const int kNumPaddingBytes1 = 4;
- int packet_size = 0;
- {
- QuicFrames frames;
- frames.push_back(frame);
- char buffer[kMaxOutgoingPacketSize];
- QuicPendingRetransmission retransmission(CreateRetransmission(
- frames, false /* has_crypto_handshake */,
- kNumPaddingBytes1 /* padding bytes */, ENCRYPTION_INITIAL,
- QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- creator_.ReserializeAllFrames(retransmission, buffer,
- kMaxOutgoingPacketSize);
- packet_size = serialized_packet_.encrypted_length;
- }
-
- {
- InSequence s;
- EXPECT_CALL(framer_visitor_, OnPacket());
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_));
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
- EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- if (QuicVersionUsesCryptoFrames(client_framer_.transport_version())) {
- EXPECT_CALL(framer_visitor_, OnCryptoFrame(_));
- } else {
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- }
- // Pending paddings are not retransmitted.
- EXPECT_CALL(framer_visitor_, OnPaddingFrame(_)).Times(0);
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
- }
- ProcessPacket(serialized_packet_);
-
- const int kNumPaddingBytes2 = 44;
- QuicFrames frames;
- frames.push_back(frame);
- char buffer[kMaxOutgoingPacketSize];
- QuicPendingRetransmission retransmission(CreateRetransmission(
- frames, false /* has_crypto_handshake */,
- kNumPaddingBytes2 /* padding bytes */, ENCRYPTION_INITIAL,
- QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- creator_.ReserializeAllFrames(retransmission, buffer, kMaxOutgoingPacketSize);
-
- EXPECT_EQ(packet_size, serialized_packet_.encrypted_length);
- DeleteFrames(&frames);
-}
-
-TEST_P(QuicPacketCreatorTest, ReserializeFramesWithFullPacketAndPadding) {
- creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
- const size_t overhead =
- GetPacketHeaderOverhead(client_framer_.transport_version()) +
- GetEncryptionOverhead() +
- GetStreamFrameOverhead(client_framer_.transport_version());
- size_t capacity = kDefaultMaxPacketSize - overhead;
- for (int delta = -5; delta <= 0; ++delta) {
- std::string data(capacity + delta, 'A');
- size_t bytes_free = 0 - delta;
-
- QuicFrame frame;
- SimpleDataProducer producer;
- QuicPacketCreatorPeer::framer(&creator_)->set_data_producer(&producer);
- MakeIOVector(data, &iov_);
- QuicStreamId stream_id = QuicUtils::GetFirstBidirectionalStreamId(
- client_framer_.transport_version(), Perspective::IS_CLIENT);
- producer.SaveStreamData(stream_id, &iov_, 1u, 0u, iov_.iov_len);
- QuicPacketCreatorPeer::CreateStreamFrame(&creator_, stream_id, iov_.iov_len,
- kOffset, false, &frame);
- QuicFrames frames;
- frames.push_back(frame);
- char buffer[kMaxOutgoingPacketSize];
- QuicPendingRetransmission retransmission(CreateRetransmission(
- frames, false /* has_crypto_handshake */, -1 /* needs full padding */,
- ENCRYPTION_FORWARD_SECURE,
- QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- creator_.ReserializeAllFrames(retransmission, buffer,
- kMaxOutgoingPacketSize);
-
- // If there is not enough space in the packet to fit a padding frame
- // (1 byte) and to expand the stream frame (another 2 bytes) the packet
- // will not be padded.
- if (bytes_free < 3) {
- EXPECT_EQ(kDefaultMaxPacketSize - bytes_free,
- serialized_packet_.encrypted_length);
- } else {
- EXPECT_EQ(kDefaultMaxPacketSize, serialized_packet_.encrypted_length);
- }
-
- frames_.clear();
- }
-}
-
TEST_P(QuicPacketCreatorTest, SerializeConnectionClose) {
QuicConnectionCloseFrame frame(creator_.transport_version(), QUIC_NO_ERROR,
"error",
@@ -784,8 +541,10 @@ TEST_P(QuicPacketCreatorTest, CryptoStreamFramePacketPadding) {
// If there is not enough space in the packet to fit a padding frame
// (1 byte) and to expand the stream frame (another 2 bytes) the packet
// will not be padded.
- if (bytes_free < 3 &&
- !QuicVersionUsesCryptoFrames(client_framer_.transport_version())) {
+ // Padding is skipped when we try to send coalesced packets.
+ if ((bytes_free < 3 &&
+ !QuicVersionUsesCryptoFrames(client_framer_.transport_version())) ||
+ client_framer_.version().CanSendCoalescedPackets()) {
EXPECT_EQ(kDefaultMaxPacketSize - bytes_free,
serialized_packet_.encrypted_length);
} else {
@@ -861,7 +620,7 @@ TEST_P(QuicPacketCreatorTest, BuildPathChallengePacket) {
}
QuicPacketHeader header;
- header.destination_connection_id = kTestConnectionId;
+ header.destination_connection_id = CreateTestConnectionId();
header.reset_flag = false;
header.version_flag = false;
header.packet_number = kPacketNumber;
@@ -908,7 +667,7 @@ TEST_P(QuicPacketCreatorTest, BuildPathChallengePacket) {
TEST_P(QuicPacketCreatorTest, BuildConnectivityProbingPacket) {
QuicPacketHeader header;
- header.destination_connection_id = kTestConnectionId;
+ header.destination_connection_id = CreateTestConnectionId();
header.reset_flag = false;
header.version_flag = false;
header.packet_number = kPacketNumber;
@@ -995,7 +754,7 @@ TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket1ResponseUnpadded) {
}
QuicPacketHeader header;
- header.destination_connection_id = kTestConnectionId;
+ header.destination_connection_id = CreateTestConnectionId();
header.reset_flag = false;
header.version_flag = false;
header.packet_number = kPacketNumber;
@@ -1040,7 +799,7 @@ TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket1ResponsePadded) {
}
QuicPacketHeader header;
- header.destination_connection_id = kTestConnectionId;
+ header.destination_connection_id = CreateTestConnectionId();
header.reset_flag = false;
header.version_flag = false;
header.packet_number = kPacketNumber;
@@ -1087,7 +846,7 @@ TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket3ResponsesUnpadded) {
}
QuicPacketHeader header;
- header.destination_connection_id = kTestConnectionId;
+ header.destination_connection_id = CreateTestConnectionId();
header.reset_flag = false;
header.version_flag = false;
header.packet_number = kPacketNumber;
@@ -1139,7 +898,7 @@ TEST_P(QuicPacketCreatorTest, BuildPathResponsePacket3ResponsesPadded) {
}
QuicPacketHeader header;
- header.destination_connection_id = kTestConnectionId;
+ header.destination_connection_id = CreateTestConnectionId();
header.reset_flag = false;
header.version_flag = false;
header.packet_number = kPacketNumber;
@@ -1705,8 +1464,7 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndFlush) {
// Add a variety of frame types and then a padding frame.
QuicAckFrame ack_frame(InitAckFrame(10u));
EXPECT_CALL(debug, OnFrameAddedToPacket(_));
- EXPECT_TRUE(
- creator_.AddSavedFrame(QuicFrame(&ack_frame), NOT_RETRANSMISSION));
+ EXPECT_TRUE(creator_.AddFrame(QuicFrame(&ack_frame), NOT_RETRANSMISSION));
EXPECT_TRUE(creator_.HasPendingFrames());
EXPECT_FALSE(creator_.HasPendingStreamFramesOfStream(stream_id));
@@ -1723,16 +1481,14 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndFlush) {
QuicPaddingFrame padding_frame;
EXPECT_CALL(debug, OnFrameAddedToPacket(_));
- EXPECT_TRUE(
- creator_.AddSavedFrame(QuicFrame(padding_frame), NOT_RETRANSMISSION));
+ EXPECT_TRUE(creator_.AddFrame(QuicFrame(padding_frame), NOT_RETRANSMISSION));
EXPECT_TRUE(creator_.HasPendingFrames());
EXPECT_EQ(0u, creator_.BytesFree());
// Packet is full. Creator will flush.
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- EXPECT_FALSE(
- creator_.AddSavedFrame(QuicFrame(&ack_frame), NOT_RETRANSMISSION));
+ EXPECT_FALSE(creator_.AddFrame(QuicFrame(&ack_frame), NOT_RETRANSMISSION));
// Ensure the packet is successfully created.
ASSERT_TRUE(serialized_packet_.encrypted_buffer);
@@ -1841,7 +1597,7 @@ TEST_P(QuicPacketCreatorTest, AddUnencryptedStreamDataClosesConnection) {
QuicStreamFrame stream_frame(GetNthClientInitiatedStreamId(0),
/*fin=*/false, 0u, QuicStringPiece());
EXPECT_QUIC_BUG(
- creator_.AddSavedFrame(QuicFrame(stream_frame), NOT_RETRANSMISSION),
+ creator_.AddFrame(QuicFrame(stream_frame), NOT_RETRANSMISSION),
"Cannot send stream data with level: ENCRYPTION_INITIAL");
}
@@ -1856,7 +1612,7 @@ TEST_P(QuicPacketCreatorTest, SendStreamDataWithEncryptionHandshake) {
QuicStreamFrame stream_frame(GetNthClientInitiatedStreamId(0),
/*fin=*/false, 0u, QuicStringPiece());
EXPECT_QUIC_BUG(
- creator_.AddSavedFrame(QuicFrame(stream_frame), NOT_RETRANSMISSION),
+ creator_.AddFrame(QuicFrame(stream_frame), NOT_RETRANSMISSION),
"Cannot send stream data with level: ENCRYPTION_HANDSHAKE");
}
@@ -1936,99 +1692,6 @@ TEST_P(QuicPacketCreatorTest, FullPaddingDoesNotConsumePendingPadding) {
EXPECT_EQ(kMaxNumRandomPaddingBytes, creator_.pending_padding_bytes());
}
-TEST_P(QuicPacketCreatorTest, SendPendingPaddingInRetransmission) {
- creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
- QuicStreamId stream_id = QuicUtils::GetFirstBidirectionalStreamId(
- client_framer_.transport_version(), Perspective::IS_CLIENT);
- QuicStreamFrame stream_frame(stream_id,
- /*fin=*/false, 0u, QuicStringPiece());
- QuicFrames frames;
- frames.push_back(QuicFrame(stream_frame));
- char buffer[kMaxOutgoingPacketSize];
- QuicPendingRetransmission retransmission(CreateRetransmission(
- frames, true, /*num_padding_bytes=*/0, ENCRYPTION_FORWARD_SECURE,
- QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- creator_.AddPendingPadding(kMaxNumRandomPaddingBytes);
- creator_.ReserializeAllFrames(retransmission, buffer, kMaxOutgoingPacketSize);
- EXPECT_EQ(0u, creator_.pending_padding_bytes());
- {
- InSequence s;
- EXPECT_CALL(framer_visitor_, OnPacket());
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_));
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
- EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- EXPECT_CALL(framer_visitor_, OnPaddingFrame(_));
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
- }
- ProcessPacket(serialized_packet_);
-}
-
-TEST_P(QuicPacketCreatorTest, SendPacketAfterFullPaddingRetransmission) {
- // Making sure needs_full_padding gets reset after a full padding
- // retransmission.
- EXPECT_EQ(0u, creator_.pending_padding_bytes());
- creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
- QuicFrame frame;
- std::string data = "fake handshake message data";
- MakeIOVector(data, &iov_);
- QuicStreamId stream_id = QuicUtils::GetFirstBidirectionalStreamId(
- client_framer_.transport_version(), Perspective::IS_CLIENT);
- if (!QuicVersionUsesCryptoFrames(client_framer_.transport_version())) {
- stream_id =
- QuicUtils::GetCryptoStreamId(client_framer_.transport_version());
- }
- producer_.SaveStreamData(stream_id, &iov_, 1u, 0u, iov_.iov_len);
- QuicPacketCreatorPeer::CreateStreamFrame(&creator_, stream_id, iov_.iov_len,
- 0u, false, &frame);
- QuicFrames frames;
- frames.push_back(frame);
- char buffer[kMaxOutgoingPacketSize];
- QuicPendingRetransmission retransmission(CreateRetransmission(
- frames, true, /*num_padding_bytes=*/-1, ENCRYPTION_FORWARD_SECURE,
- QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillRepeatedly(
- Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- creator_.ReserializeAllFrames(retransmission, buffer, kMaxOutgoingPacketSize);
- EXPECT_EQ(kDefaultMaxPacketSize, serialized_packet_.encrypted_length);
- {
- InSequence s;
- EXPECT_CALL(framer_visitor_, OnPacket());
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_));
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
- EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- // Full padding.
- EXPECT_CALL(framer_visitor_, OnPaddingFrame(_));
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
- }
- ProcessPacket(serialized_packet_);
-
- creator_.ConsumeDataToFillCurrentPacket(stream_id, &iov_, 1u, iov_.iov_len,
- 0u, 0u, false, false,
- NOT_RETRANSMISSION, &frame);
- creator_.FlushCurrentPacket();
- {
- InSequence s;
- EXPECT_CALL(framer_visitor_, OnPacket());
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_));
- EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
- EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_));
- EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
- // needs_full_padding gets reset.
- EXPECT_CALL(framer_visitor_, OnPaddingFrame(_)).Times(0);
- EXPECT_CALL(framer_visitor_, OnPacketComplete());
- }
- ProcessPacket(serialized_packet_);
- DeleteFrames(&frames);
-}
-
TEST_P(QuicPacketCreatorTest, ConsumeDataAndRandomPadding) {
creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
const QuicByteCount kStreamFramePayloadSize = 100u;
@@ -2125,20 +1788,19 @@ TEST_P(QuicPacketCreatorTest, AddMessageFrame) {
std::string message(creator_.GetCurrentLargestMessagePayload(), 'a');
QuicMessageFrame* message_frame =
new QuicMessageFrame(1, MakeSpan(&allocator_, message, &storage));
- EXPECT_TRUE(
- creator_.AddSavedFrame(QuicFrame(message_frame), NOT_RETRANSMISSION));
+ EXPECT_TRUE(creator_.AddFrame(QuicFrame(message_frame), NOT_RETRANSMISSION));
EXPECT_TRUE(creator_.HasPendingFrames());
creator_.FlushCurrentPacket();
QuicMessageFrame* frame2 =
new QuicMessageFrame(2, MakeSpan(&allocator_, "message", &storage));
- EXPECT_TRUE(creator_.AddSavedFrame(QuicFrame(frame2), NOT_RETRANSMISSION));
+ EXPECT_TRUE(creator_.AddFrame(QuicFrame(frame2), NOT_RETRANSMISSION));
EXPECT_TRUE(creator_.HasPendingFrames());
// Verify if a new frame is added, 1 byte message length will be added.
EXPECT_EQ(1u, creator_.ExpansionOnNewFrame());
QuicMessageFrame* frame3 =
new QuicMessageFrame(3, MakeSpan(&allocator_, "message2", &storage));
- EXPECT_TRUE(creator_.AddSavedFrame(QuicFrame(frame3), NOT_RETRANSMISSION));
+ EXPECT_TRUE(creator_.AddFrame(QuicFrame(frame3), NOT_RETRANSMISSION));
EXPECT_EQ(1u, creator_.ExpansionOnNewFrame());
creator_.FlushCurrentPacket();
@@ -2151,14 +1813,14 @@ TEST_P(QuicPacketCreatorTest, AddMessageFrame) {
NOT_RETRANSMISSION, &frame));
QuicMessageFrame* frame4 =
new QuicMessageFrame(4, MakeSpan(&allocator_, "message", &storage));
- EXPECT_TRUE(creator_.AddSavedFrame(QuicFrame(frame4), NOT_RETRANSMISSION));
+ EXPECT_TRUE(creator_.AddFrame(QuicFrame(frame4), NOT_RETRANSMISSION));
EXPECT_TRUE(creator_.HasPendingFrames());
// Verify there is not enough room for largest payload.
EXPECT_FALSE(creator_.HasRoomForMessageFrame(
creator_.GetCurrentLargestMessagePayload()));
// Add largest message will causes the flush of the stream frame.
QuicMessageFrame frame5(5, MakeSpan(&allocator_, message, &storage));
- EXPECT_FALSE(creator_.AddSavedFrame(QuicFrame(&frame5), NOT_RETRANSMISSION));
+ EXPECT_FALSE(creator_.AddFrame(QuicFrame(&frame5), NOT_RETRANSMISSION));
EXPECT_FALSE(creator_.HasPendingFrames());
}
@@ -2181,7 +1843,7 @@ TEST_P(QuicPacketCreatorTest, MessageFrameConsumption) {
0, MakeSpan(&allocator_,
QuicStringPiece(message_buffer.data(), message_size),
&storage));
- EXPECT_TRUE(creator_.AddSavedFrame(QuicFrame(frame), NOT_RETRANSMISSION));
+ EXPECT_TRUE(creator_.AddFrame(QuicFrame(frame), NOT_RETRANSMISSION));
EXPECT_TRUE(creator_.HasPendingFrames());
size_t expansion_bytes = message_size >= 64 ? 2 : 1;
@@ -2225,8 +1887,6 @@ TEST_P(QuicPacketCreatorTest, GetGuaranteedLargestMessagePayload) {
TEST_P(QuicPacketCreatorTest, PacketTransmissionType) {
creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
- creator_.set_can_set_transmission_type(true);
- creator_.SetTransmissionTypeOfNextPackets(NOT_RETRANSMISSION);
QuicAckFrame temp_ack_frame = InitAckFrame(1);
QuicFrame ack_frame(&temp_ack_frame);
@@ -2244,23 +1904,19 @@ TEST_P(QuicPacketCreatorTest, PacketTransmissionType) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
- EXPECT_TRUE(creator_.AddSavedFrame(ack_frame, LOSS_RETRANSMISSION));
+ EXPECT_TRUE(creator_.AddFrame(ack_frame, LOSS_RETRANSMISSION));
ASSERT_FALSE(serialized_packet_.encrypted_buffer);
- EXPECT_TRUE(creator_.AddSavedFrame(stream_frame, RTO_RETRANSMISSION));
+ EXPECT_TRUE(creator_.AddFrame(stream_frame, RTO_RETRANSMISSION));
ASSERT_FALSE(serialized_packet_.encrypted_buffer);
- EXPECT_TRUE(creator_.AddSavedFrame(padding_frame, TLP_RETRANSMISSION));
+ EXPECT_TRUE(creator_.AddFrame(padding_frame, TLP_RETRANSMISSION));
creator_.FlushCurrentPacket();
ASSERT_TRUE(serialized_packet_.encrypted_buffer);
- if (creator_.can_set_transmission_type()) {
- // The last retransmittable frame on packet is a stream frame, the packet's
- // transmission type should be the same as the stream frame's.
- EXPECT_EQ(serialized_packet_.transmission_type, RTO_RETRANSMISSION);
- } else {
- EXPECT_EQ(serialized_packet_.transmission_type, NOT_RETRANSMISSION);
- }
+ // The last retransmittable frame on packet is a stream frame, the packet's
+ // transmission type should be the same as the stream frame's.
+ EXPECT_EQ(serialized_packet_.transmission_type, RTO_RETRANSMISSION);
DeleteSerializedPacket();
}
@@ -2334,6 +1990,1732 @@ TEST_P(QuicPacketCreatorTest, ClientConnectionId) {
EXPECT_EQ(TestConnectionId(0x33), creator_.GetSourceConnectionId());
}
+TEST_P(QuicPacketCreatorTest, CoalesceStreamFrames) {
+ InSequence s;
+ if (!GetParam().version_serialization) {
+ creator_.StopSendingVersion();
+ }
+ SetQuicRestartFlag(quic_coalesce_stream_frames_2, true);
+ const size_t max_plaintext_size =
+ client_framer_.GetMaxPlaintextSize(creator_.max_packet_length());
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
+ QuicStreamId stream_id1 = QuicUtils::GetFirstBidirectionalStreamId(
+ client_framer_.transport_version(), Perspective::IS_CLIENT);
+ QuicStreamId stream_id2 = GetNthClientInitiatedStreamId(1);
+ EXPECT_FALSE(creator_.HasPendingStreamFramesOfStream(stream_id1));
+ EXPECT_EQ(max_plaintext_size -
+ GetPacketHeaderSize(
+ client_framer_.transport_version(),
+ creator_.GetDestinationConnectionIdLength(),
+ creator_.GetSourceConnectionIdLength(),
+ QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
+ !kIncludeDiversificationNonce,
+ QuicPacketCreatorPeer::GetPacketNumberLength(&creator_),
+ QuicPacketCreatorPeer::GetRetryTokenLengthLength(&creator_),
+ 0, QuicPacketCreatorPeer::GetLengthLength(&creator_)),
+ creator_.BytesFree());
+ StrictMock<MockDebugDelegate> debug;
+ creator_.set_debug_delegate(&debug);
+
+ MakeIOVector("test", &iov_);
+ QuicFrame frame;
+ EXPECT_CALL(debug, OnFrameAddedToPacket(_));
+ ASSERT_TRUE(creator_.ConsumeDataToFillCurrentPacket(
+ stream_id1, &iov_, 1u, iov_.iov_len, 0u, 0u, false, false,
+ NOT_RETRANSMISSION, &frame));
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingStreamFramesOfStream(stream_id1));
+
+ MakeIOVector("coalesce", &iov_);
+ // frame will be coalesced with the first frame.
+ const auto previous_size = creator_.PacketSize();
+ QuicStreamFrame target(stream_id1, true, 0, 12);
+ EXPECT_CALL(debug, OnStreamFrameCoalesced(target));
+ ASSERT_TRUE(creator_.ConsumeDataToFillCurrentPacket(
+ stream_id1, &iov_, 1u, iov_.iov_len, 0u, 4u, true, false,
+ NOT_RETRANSMISSION, &frame));
+ EXPECT_EQ(frame.stream_frame.data_length,
+ creator_.PacketSize() - previous_size);
+
+ // frame is for another stream, so it won't be coalesced.
+ const auto length = creator_.BytesFree() - 10u;
+ std::string large_data(length, 'x');
+ MakeIOVector(large_data, &iov_);
+ EXPECT_CALL(debug, OnFrameAddedToPacket(_));
+ ASSERT_TRUE(creator_.ConsumeDataToFillCurrentPacket(
+ stream_id2, &iov_, 1u, iov_.iov_len, 0u, 0u, false, false,
+ NOT_RETRANSMISSION, &frame));
+ EXPECT_TRUE(creator_.HasPendingStreamFramesOfStream(stream_id2));
+
+ // The packet doesn't have enough free bytes for all data, but will still be
+ // able to consume and coalesce part of them.
+ EXPECT_CALL(debug, OnStreamFrameCoalesced(_));
+ MakeIOVector("somerandomdata", &iov_);
+ ASSERT_TRUE(creator_.ConsumeDataToFillCurrentPacket(
+ stream_id2, &iov_, 1u, iov_.iov_len, 0u, length, false, false,
+ NOT_RETRANSMISSION, &frame));
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
+ creator_.FlushCurrentPacket();
+ EXPECT_CALL(framer_visitor_, OnPacket());
+ EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_));
+ EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
+ EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_));
+ EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
+ // The packet should only have 2 stream frames.
+ EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
+ EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
+ EXPECT_CALL(framer_visitor_, OnPacketComplete());
+ ProcessPacket(serialized_packet_);
+}
+
+TEST_P(QuicPacketCreatorTest, SaveNonRetransmittableFrames) {
+ QuicAckFrame ack_frame(InitAckFrame(1));
+ frames_.push_back(QuicFrame(&ack_frame));
+ frames_.push_back(QuicFrame(QuicPaddingFrame(-1)));
+ SerializedPacket serialized = SerializeAllFrames(frames_);
+ ASSERT_EQ(2u, serialized.nonretransmittable_frames.size());
+ EXPECT_EQ(ACK_FRAME, serialized.nonretransmittable_frames[0].type);
+ EXPECT_EQ(PADDING_FRAME, serialized.nonretransmittable_frames[1].type);
+ // Verify full padding frame is translated to a padding frame with actual
+ // bytes of padding.
+ EXPECT_LT(
+ 0,
+ serialized.nonretransmittable_frames[1].padding_frame.num_padding_bytes);
+ frames_.clear();
+
+ // Serialize another packet with the same frames.
+ SerializedPacket packet = QuicPacketCreatorPeer::SerializeAllFrames(
+ &creator_, serialized.nonretransmittable_frames, buffer_,
+ kMaxOutgoingPacketSize);
+ // Verify the packet length of both packets are equal.
+ EXPECT_EQ(serialized.encrypted_length, packet.encrypted_length);
+}
+
+TEST_P(QuicPacketCreatorTest, SerializeCoalescedPacket) {
+ QuicCoalescedPacket coalesced;
+ SimpleBufferAllocator allocator;
+ QuicSocketAddress self_address(QuicIpAddress::Loopback4(), 1);
+ QuicSocketAddress peer_address(QuicIpAddress::Loopback4(), 2);
+ for (size_t i = ENCRYPTION_INITIAL; i < NUM_ENCRYPTION_LEVELS; ++i) {
+ 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_INITIAL && level != ENCRYPTION_HANDSHAKE) {
+ frames_.push_back(
+ QuicFrame(QuicStreamFrame(1, false, 0u, QuicStringPiece())));
+ }
+ SerializedPacket serialized = SerializeAllFrames(frames_);
+ EXPECT_EQ(level, serialized.encryption_level);
+ frames_.clear();
+ ASSERT_TRUE(coalesced.MaybeCoalescePacket(serialized, self_address,
+ peer_address, &allocator,
+ creator_.max_packet_length()));
+ }
+ char buffer[kMaxOutgoingPacketSize];
+ size_t coalesced_length = creator_.SerializeCoalescedPacket(
+ coalesced, buffer, kMaxOutgoingPacketSize);
+ // Verify packet is padded to full.
+ ASSERT_EQ(coalesced.max_packet_length(), coalesced_length);
+ if (!QuicVersionHasLongHeaderLengths(server_framer_.transport_version())) {
+ return;
+ }
+ // Verify packet process.
+ std::unique_ptr<QuicEncryptedPacket> packets[NUM_ENCRYPTION_LEVELS];
+ packets[ENCRYPTION_INITIAL] =
+ std::make_unique<QuicEncryptedPacket>(buffer, coalesced_length);
+ for (size_t i = ENCRYPTION_INITIAL; i < NUM_ENCRYPTION_LEVELS; ++i) {
+ InSequence s;
+ EXPECT_CALL(framer_visitor_, OnPacket());
+ EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_));
+ if (i < ENCRYPTION_FORWARD_SECURE) {
+ // Save coalesced packet.
+ EXPECT_CALL(framer_visitor_, OnCoalescedPacket(_))
+ .WillOnce(Invoke([i, &packets](const QuicEncryptedPacket& packet) {
+ packets[i + 1] = packet.Clone();
+ }));
+ }
+ 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_INITIAL) {
+ // Verify padding is added.
+ EXPECT_CALL(framer_visitor_, OnPaddingFrame(_));
+ } else {
+ EXPECT_CALL(framer_visitor_, OnPaddingFrame(_)).Times(testing::AtMost(1));
+ }
+ if (i != ENCRYPTION_INITIAL && i != ENCRYPTION_HANDSHAKE) {
+ EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
+ }
+ EXPECT_CALL(framer_visitor_, OnPacketComplete());
+
+ server_framer_.ProcessPacket(*packets[i]);
+ }
+}
+
+TEST_P(QuicPacketCreatorTest, SoftMaxPacketLength) {
+ creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
+ QuicByteCount previous_max_packet_length = creator_.max_packet_length();
+ const size_t overhead =
+ GetPacketHeaderOverhead(client_framer_.transport_version()) +
+ QuicPacketCreator::MinPlaintextPacketSize(client_framer_.version()) +
+ GetEncryptionOverhead();
+ // Make sure a length which cannot accommodate header (includes header
+ // protection minimal length) gets rejected.
+ creator_.SetSoftMaxPacketLength(overhead - 1);
+ EXPECT_EQ(previous_max_packet_length, creator_.max_packet_length());
+
+ creator_.SetSoftMaxPacketLength(overhead);
+ EXPECT_EQ(overhead, creator_.max_packet_length());
+
+ // Verify creator has room for stream frame because max_packet_length_ gets
+ // restored.
+ ASSERT_TRUE(creator_.HasRoomForStreamFrame(
+ GetNthClientInitiatedStreamId(1), kMaxIetfVarInt,
+ std::numeric_limits<uint32_t>::max()));
+ EXPECT_EQ(previous_max_packet_length, creator_.max_packet_length());
+
+ // Same for message frame.
+ if (VersionSupportsMessageFrames(client_framer_.transport_version())) {
+ creator_.SetSoftMaxPacketLength(overhead);
+ // Verify GetCurrentLargestMessagePayload is based on the actual
+ // max_packet_length.
+ EXPECT_LT(1u, creator_.GetCurrentLargestMessagePayload());
+ EXPECT_EQ(overhead, creator_.max_packet_length());
+ ASSERT_TRUE(creator_.HasRoomForMessageFrame(
+ creator_.GetCurrentLargestMessagePayload()));
+ EXPECT_EQ(previous_max_packet_length, creator_.max_packet_length());
+ }
+
+ // Verify creator can consume crypto data because max_packet_length_ gets
+ // restored.
+ creator_.SetSoftMaxPacketLength(overhead);
+ EXPECT_EQ(overhead, creator_.max_packet_length());
+ std::string data = "crypto data";
+ MakeIOVector(data, &iov_);
+ QuicFrame frame;
+ if (!QuicVersionUsesCryptoFrames(client_framer_.transport_version())) {
+ ASSERT_TRUE(creator_.ConsumeDataToFillCurrentPacket(
+ QuicUtils::GetCryptoStreamId(client_framer_.transport_version()), &iov_,
+ 1u, iov_.iov_len, 0u, kOffset, false, true, NOT_RETRANSMISSION,
+ &frame));
+ size_t bytes_consumed = frame.stream_frame.data_length;
+ EXPECT_LT(0u, bytes_consumed);
+ } else {
+ producer_.SaveCryptoData(ENCRYPTION_INITIAL, kOffset, data);
+ ASSERT_TRUE(creator_.ConsumeCryptoDataToFillCurrentPacket(
+ ENCRYPTION_INITIAL, data.length(), kOffset,
+ /*needs_full_padding=*/true, NOT_RETRANSMISSION, &frame));
+ size_t bytes_consumed = frame.crypto_frame->data_length;
+ EXPECT_LT(0u, bytes_consumed);
+ }
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
+ creator_.FlushCurrentPacket();
+
+ // Verify ACK frame can be consumed.
+ creator_.SetSoftMaxPacketLength(overhead);
+ EXPECT_EQ(overhead, creator_.max_packet_length());
+ QuicAckFrame ack_frame(InitAckFrame(10u));
+ EXPECT_TRUE(creator_.AddFrame(QuicFrame(&ack_frame), NOT_RETRANSMISSION));
+ EXPECT_TRUE(creator_.HasPendingFrames());
+}
+
+class MockDelegate : public QuicPacketCreator::DelegateInterface {
+ public:
+ MockDelegate() {}
+ MockDelegate(const MockDelegate&) = delete;
+ MockDelegate& operator=(const MockDelegate&) = delete;
+ ~MockDelegate() override {}
+
+ MOCK_METHOD2(ShouldGeneratePacket,
+ bool(HasRetransmittableData retransmittable,
+ IsHandshake handshake));
+ MOCK_METHOD0(MaybeBundleAckOpportunistically, const QuicFrames());
+ MOCK_METHOD0(GetPacketBuffer, char*());
+ MOCK_METHOD1(OnSerializedPacket, void(SerializedPacket* packet));
+ MOCK_METHOD2(OnUnrecoverableError, void(QuicErrorCode, const std::string&));
+
+ void SetCanWriteAnything() {
+ EXPECT_CALL(*this, ShouldGeneratePacket(_, _)).WillRepeatedly(Return(true));
+ EXPECT_CALL(*this, ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, _))
+ .WillRepeatedly(Return(true));
+ }
+
+ void SetCanNotWrite() {
+ EXPECT_CALL(*this, ShouldGeneratePacket(_, _))
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(*this, ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, _))
+ .WillRepeatedly(Return(false));
+ }
+
+ // Use this when only ack frames should be allowed to be written.
+ void SetCanWriteOnlyNonRetransmittable() {
+ EXPECT_CALL(*this, ShouldGeneratePacket(_, _))
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(*this, ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, _))
+ .WillRepeatedly(Return(true));
+ }
+};
+
+// Simple struct for describing the contents of a packet.
+// Useful in conjunction with a SimpleQuicFrame for validating that a packet
+// contains the expected frames.
+struct PacketContents {
+ PacketContents()
+ : num_ack_frames(0),
+ num_connection_close_frames(0),
+ num_goaway_frames(0),
+ num_rst_stream_frames(0),
+ num_stop_waiting_frames(0),
+ num_stream_frames(0),
+ num_crypto_frames(0),
+ num_ping_frames(0),
+ num_mtu_discovery_frames(0),
+ num_padding_frames(0) {}
+
+ size_t num_ack_frames;
+ size_t num_connection_close_frames;
+ size_t num_goaway_frames;
+ size_t num_rst_stream_frames;
+ size_t num_stop_waiting_frames;
+ size_t num_stream_frames;
+ size_t num_crypto_frames;
+ size_t num_ping_frames;
+ size_t num_mtu_discovery_frames;
+ size_t num_padding_frames;
+};
+
+class MultiplePacketsTestPacketCreator : public QuicPacketCreator {
+ public:
+ MultiplePacketsTestPacketCreator(
+ QuicConnectionId connection_id,
+ QuicFramer* framer,
+ QuicRandom* random_generator,
+ QuicPacketCreator::DelegateInterface* delegate,
+ SimpleDataProducer* producer)
+ : QuicPacketCreator(connection_id, framer, random_generator, delegate),
+ ack_frame_(InitAckFrame(1)),
+ delegate_(static_cast<MockDelegate*>(delegate)),
+ producer_(producer) {}
+
+ bool ConsumeRetransmittableControlFrame(const QuicFrame& frame,
+ bool bundle_ack) {
+ if (!has_ack()) {
+ QuicFrames frames;
+ if (bundle_ack) {
+ frames.push_back(QuicFrame(&ack_frame_));
+ }
+ if (delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE)) {
+ EXPECT_CALL(*delegate_, MaybeBundleAckOpportunistically())
+ .WillOnce(Return(frames));
+ }
+ }
+ return QuicPacketCreator::ConsumeRetransmittableControlFrame(frame);
+ }
+
+ QuicConsumedData ConsumeDataFastPath(QuicStreamId id,
+ const struct iovec* iov,
+ int iov_count,
+ size_t total_length,
+ QuicStreamOffset offset,
+ bool fin) {
+ // Save data before data is consumed.
+ if (total_length > 0) {
+ producer_->SaveStreamData(id, iov, iov_count, 0, total_length);
+ }
+ return QuicPacketCreator::ConsumeDataFastPath(id, total_length, offset, fin,
+ 0);
+ }
+
+ QuicConsumedData ConsumeData(QuicStreamId id,
+ const struct iovec* iov,
+ int iov_count,
+ size_t total_length,
+ QuicStreamOffset offset,
+ StreamSendingState state) {
+ // Save data before data is consumed.
+ if (total_length > 0) {
+ producer_->SaveStreamData(id, iov, iov_count, 0, total_length);
+ }
+ if (!has_ack() && delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE)) {
+ EXPECT_CALL(*delegate_, MaybeBundleAckOpportunistically()).Times(1);
+ }
+ return QuicPacketCreator::ConsumeData(id, total_length, offset, state);
+ }
+
+ MessageStatus AddMessageFrame(QuicMessageId message_id,
+ QuicMemSliceSpan message) {
+ if (!has_ack() && delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE)) {
+ EXPECT_CALL(*delegate_, MaybeBundleAckOpportunistically()).Times(1);
+ }
+ return QuicPacketCreator::AddMessageFrame(message_id, message);
+ }
+
+ size_t ConsumeCryptoData(EncryptionLevel level,
+ QuicStringPiece data,
+ QuicStreamOffset offset) {
+ producer_->SaveCryptoData(level, offset, data);
+ if (!has_ack() && delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE)) {
+ EXPECT_CALL(*delegate_, MaybeBundleAckOpportunistically()).Times(1);
+ }
+ return QuicPacketCreator::ConsumeCryptoData(level, data.length(), offset);
+ }
+
+ QuicAckFrame ack_frame_;
+ MockDelegate* delegate_;
+ SimpleDataProducer* producer_;
+};
+
+class QuicPacketCreatorMultiplePacketsTest : public QuicTest {
+ public:
+ QuicPacketCreatorMultiplePacketsTest()
+ : framer_(AllSupportedVersions(),
+ QuicTime::Zero(),
+ Perspective::IS_CLIENT,
+ kQuicDefaultConnectionIdLength),
+ creator_(TestConnectionId(),
+ &framer_,
+ &random_creator_,
+ &delegate_,
+ &producer_),
+ ack_frame_(InitAckFrame(1)) {
+ EXPECT_CALL(delegate_, GetPacketBuffer()).WillRepeatedly(Return(nullptr));
+ creator_.SetEncrypter(
+ ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<NullEncrypter>(Perspective::IS_CLIENT));
+ creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
+ framer_.set_data_producer(&producer_);
+ if (simple_framer_.framer()->version().KnowsWhichDecrypterToUse()) {
+ simple_framer_.framer()->InstallDecrypter(
+ ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<NullDecrypter>(Perspective::IS_SERVER));
+ }
+ creator_.AttachPacketFlusher();
+ }
+
+ ~QuicPacketCreatorMultiplePacketsTest() override {
+ for (SerializedPacket& packet : packets_) {
+ delete[] packet.encrypted_buffer;
+ ClearSerializedPacket(&packet);
+ }
+ }
+
+ void SavePacket(SerializedPacket* packet) {
+ packet->encrypted_buffer = CopyBuffer(*packet);
+ packets_.push_back(*packet);
+ packet->encrypted_buffer = nullptr;
+ packet->retransmittable_frames.clear();
+ }
+
+ protected:
+ QuicRstStreamFrame* CreateRstStreamFrame() {
+ return new QuicRstStreamFrame(1, 1, QUIC_STREAM_NO_ERROR, 0);
+ }
+
+ QuicGoAwayFrame* CreateGoAwayFrame() {
+ return new QuicGoAwayFrame(2, QUIC_NO_ERROR, 1, std::string());
+ }
+
+ void CheckPacketContains(const PacketContents& contents,
+ size_t packet_index) {
+ ASSERT_GT(packets_.size(), packet_index);
+ const SerializedPacket& packet = packets_[packet_index];
+ size_t num_retransmittable_frames =
+ contents.num_connection_close_frames + contents.num_goaway_frames +
+ contents.num_rst_stream_frames + contents.num_stream_frames +
+ contents.num_crypto_frames + contents.num_ping_frames;
+ size_t num_frames =
+ contents.num_ack_frames + contents.num_stop_waiting_frames +
+ contents.num_mtu_discovery_frames + contents.num_padding_frames +
+ num_retransmittable_frames;
+
+ if (num_retransmittable_frames == 0) {
+ ASSERT_TRUE(packet.retransmittable_frames.empty());
+ } else {
+ ASSERT_FALSE(packet.retransmittable_frames.empty());
+ EXPECT_EQ(num_retransmittable_frames,
+ packet.retransmittable_frames.size());
+ }
+
+ ASSERT_TRUE(packet.encrypted_buffer != nullptr);
+ ASSERT_TRUE(simple_framer_.ProcessPacket(
+ QuicEncryptedPacket(packet.encrypted_buffer, packet.encrypted_length)));
+ size_t num_padding_frames = 0;
+ if (contents.num_padding_frames == 0) {
+ num_padding_frames = simple_framer_.padding_frames().size();
+ }
+ EXPECT_EQ(num_frames + num_padding_frames, simple_framer_.num_frames());
+ EXPECT_EQ(contents.num_ack_frames, simple_framer_.ack_frames().size());
+ EXPECT_EQ(contents.num_connection_close_frames,
+ simple_framer_.connection_close_frames().size());
+ EXPECT_EQ(contents.num_goaway_frames,
+ simple_framer_.goaway_frames().size());
+ EXPECT_EQ(contents.num_rst_stream_frames,
+ simple_framer_.rst_stream_frames().size());
+ EXPECT_EQ(contents.num_stream_frames,
+ simple_framer_.stream_frames().size());
+ EXPECT_EQ(contents.num_crypto_frames,
+ simple_framer_.crypto_frames().size());
+ EXPECT_EQ(contents.num_stop_waiting_frames,
+ simple_framer_.stop_waiting_frames().size());
+ if (contents.num_padding_frames != 0) {
+ EXPECT_EQ(contents.num_padding_frames,
+ simple_framer_.padding_frames().size());
+ }
+
+ // From the receiver's perspective, MTU discovery frames are ping frames.
+ EXPECT_EQ(contents.num_ping_frames + contents.num_mtu_discovery_frames,
+ simple_framer_.ping_frames().size());
+ }
+
+ void CheckPacketHasSingleStreamFrame(size_t packet_index) {
+ ASSERT_GT(packets_.size(), packet_index);
+ const SerializedPacket& packet = packets_[packet_index];
+ ASSERT_FALSE(packet.retransmittable_frames.empty());
+ EXPECT_EQ(1u, packet.retransmittable_frames.size());
+ ASSERT_TRUE(packet.encrypted_buffer != nullptr);
+ ASSERT_TRUE(simple_framer_.ProcessPacket(
+ QuicEncryptedPacket(packet.encrypted_buffer, packet.encrypted_length)));
+ EXPECT_EQ(1u, simple_framer_.num_frames());
+ EXPECT_EQ(1u, simple_framer_.stream_frames().size());
+ }
+
+ void CheckAllPacketsHaveSingleStreamFrame() {
+ for (size_t i = 0; i < packets_.size(); i++) {
+ CheckPacketHasSingleStreamFrame(i);
+ }
+ }
+
+ void CreateData(size_t len) {
+ data_array_.reset(new char[len]);
+ memset(data_array_.get(), '?', len);
+ iov_.iov_base = data_array_.get();
+ iov_.iov_len = len;
+ }
+
+ QuicFramer framer_;
+ MockRandom random_creator_;
+ StrictMock<MockDelegate> delegate_;
+ MultiplePacketsTestPacketCreator creator_;
+ SimpleQuicFramer simple_framer_;
+ std::vector<SerializedPacket> packets_;
+ QuicAckFrame ack_frame_;
+ struct iovec iov_;
+ SimpleBufferAllocator allocator_;
+
+ private:
+ std::unique_ptr<char[]> data_array_;
+ SimpleDataProducer producer_;
+};
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, AddControlFrame_NotWritable) {
+ delegate_.SetCanNotWrite();
+
+ QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
+ const bool consumed =
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/false);
+ EXPECT_FALSE(consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+ delete rst_frame;
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, AddControlFrame_OnlyAckWritable) {
+ delegate_.SetCanWriteOnlyNonRetransmittable();
+
+ QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
+ const bool consumed =
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/false);
+ EXPECT_FALSE(consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+ delete rst_frame;
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ AddControlFrame_WritableAndShouldNotFlush) {
+ delegate_.SetCanWriteAnything();
+
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(CreateRstStreamFrame()),
+ /*bundle_ack=*/false);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ AddControlFrame_NotWritableBatchThenFlush) {
+ delegate_.SetCanNotWrite();
+
+ QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
+ const bool consumed =
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/false);
+ EXPECT_FALSE(consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+ delete rst_frame;
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ AddControlFrame_WritableAndShouldFlush) {
+ delegate_.SetCanWriteAnything();
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(CreateRstStreamFrame()),
+ /*bundle_ack=*/false);
+ creator_.Flush();
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ PacketContents contents;
+ contents.num_rst_stream_frames = 1;
+ CheckPacketContains(contents, 0);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeCryptoData) {
+ delegate_.SetCanWriteAnything();
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ std::string data = "crypto data";
+ size_t consumed_bytes =
+ creator_.ConsumeCryptoData(ENCRYPTION_INITIAL, data, 0);
+ creator_.Flush();
+ EXPECT_EQ(data.length(), consumed_bytes);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ PacketContents contents;
+ contents.num_crypto_frames = 1;
+ contents.num_padding_frames = 1;
+ CheckPacketContains(contents, 0);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeData_NotWritable) {
+ delegate_.SetCanNotWrite();
+
+ MakeIOVector("foo", &iov_);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, FIN);
+ EXPECT_EQ(0u, consumed.bytes_consumed);
+ EXPECT_FALSE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ ConsumeData_WritableAndShouldNotFlush) {
+ delegate_.SetCanWriteAnything();
+
+ MakeIOVector("foo", &iov_);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, FIN);
+ EXPECT_EQ(3u, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ ConsumeData_WritableAndShouldFlush) {
+ delegate_.SetCanWriteAnything();
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ MakeIOVector("foo", &iov_);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, FIN);
+ creator_.Flush();
+ EXPECT_EQ(3u, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ PacketContents contents;
+ contents.num_stream_frames = 1;
+ CheckPacketContains(contents, 0);
+}
+
+// Test the behavior of ConsumeData when the data consumed is for the crypto
+// handshake stream. Ensure that the packet is always sent and padded even if
+// the creator operates in batch mode.
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeData_Handshake) {
+ delegate_.SetCanWriteAnything();
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ std::string data = "foo bar";
+ MakeIOVector(data, &iov_);
+ size_t consumed_bytes = 0;
+ if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
+ consumed_bytes = creator_.ConsumeCryptoData(ENCRYPTION_INITIAL, data, 0);
+ } else {
+ consumed_bytes =
+ creator_
+ .ConsumeData(
+ QuicUtils::GetCryptoStreamId(framer_.transport_version()),
+ &iov_, 1u, iov_.iov_len, 0, NO_FIN)
+ .bytes_consumed;
+ }
+ EXPECT_EQ(7u, consumed_bytes);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ PacketContents contents;
+ if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
+ contents.num_crypto_frames = 1;
+ } else {
+ contents.num_stream_frames = 1;
+ }
+ contents.num_padding_frames = 1;
+ CheckPacketContains(contents, 0);
+
+ ASSERT_EQ(1u, packets_.size());
+ ASSERT_EQ(kDefaultMaxPacketSize, creator_.max_packet_length());
+ EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length);
+}
+
+// Test the behavior of ConsumeData when the data is for the crypto handshake
+// stream, but padding is disabled.
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ ConsumeData_Handshake_PaddingDisabled) {
+ creator_.set_fully_pad_crypto_handshake_packets(false);
+
+ delegate_.SetCanWriteAnything();
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ std::string data = "foo";
+ MakeIOVector(data, &iov_);
+ size_t bytes_consumed = 0;
+ if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
+ bytes_consumed = creator_.ConsumeCryptoData(ENCRYPTION_INITIAL, data, 0);
+ } else {
+ bytes_consumed =
+ creator_
+ .ConsumeData(
+ QuicUtils::GetCryptoStreamId(framer_.transport_version()),
+ &iov_, 1u, iov_.iov_len, 0, NO_FIN)
+ .bytes_consumed;
+ }
+ EXPECT_EQ(3u, bytes_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ PacketContents contents;
+ if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
+ contents.num_crypto_frames = 1;
+ } else {
+ contents.num_stream_frames = 1;
+ }
+ contents.num_padding_frames = 0;
+ CheckPacketContains(contents, 0);
+
+ ASSERT_EQ(1u, packets_.size());
+
+ // Packet is not fully padded, but we want to future packets to be larger.
+ ASSERT_EQ(kDefaultMaxPacketSize, creator_.max_packet_length());
+ size_t expected_packet_length = 27;
+ if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
+ // The framing of CRYPTO frames is slightly different than that of stream
+ // frames, so the expected packet length differs slightly.
+ expected_packet_length = 28;
+ }
+ if (framer_.version().HasHeaderProtection()) {
+ expected_packet_length = 29;
+ }
+ EXPECT_EQ(expected_packet_length, packets_[0].encrypted_length);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeData_EmptyData) {
+ delegate_.SetCanWriteAnything();
+
+ EXPECT_QUIC_BUG(creator_.ConsumeData(
+ QuicUtils::QuicUtils::GetFirstBidirectionalStreamId(
+ framer_.transport_version(), Perspective::IS_CLIENT),
+ nullptr, 0, 0, 0, NO_FIN),
+ "Attempt to consume empty data without FIN.");
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ ConsumeDataMultipleTimes_WritableAndShouldNotFlush) {
+ delegate_.SetCanWriteAnything();
+
+ MakeIOVector("foo", &iov_);
+ creator_.ConsumeData(QuicUtils::GetFirstBidirectionalStreamId(
+ framer_.transport_version(), Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, FIN);
+ MakeIOVector("quux", &iov_);
+ QuicConsumedData consumed =
+ creator_.ConsumeData(3, &iov_, 1u, iov_.iov_len, 3, NO_FIN);
+ EXPECT_EQ(4u, consumed.bytes_consumed);
+ EXPECT_FALSE(consumed.fin_consumed);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeData_BatchOperations) {
+ delegate_.SetCanWriteAnything();
+
+ MakeIOVector("foo", &iov_);
+ creator_.ConsumeData(QuicUtils::GetFirstBidirectionalStreamId(
+ framer_.transport_version(), Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, NO_FIN);
+ MakeIOVector("quux", &iov_);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 3, FIN);
+ EXPECT_EQ(4u, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+
+ // Now both frames will be flushed out.
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ creator_.Flush();
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ PacketContents contents;
+ contents.num_stream_frames =
+ GetQuicRestartFlag(quic_coalesce_stream_frames_2) ? 1 : 2;
+ CheckPacketContains(contents, 0);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ ConsumeData_FramesPreviouslyQueued) {
+ // Set the packet size be enough for two stream frames with 0 stream offset,
+ // but not enough for a stream frame of 0 offset and one with non-zero offset.
+ size_t length =
+ NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
+ GetPacketHeaderSize(
+ framer_.transport_version(),
+ creator_.GetDestinationConnectionIdLength(),
+ creator_.GetSourceConnectionIdLength(),
+ QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
+ !kIncludeDiversificationNonce,
+ QuicPacketCreatorPeer::GetPacketNumberLength(&creator_),
+ QuicPacketCreatorPeer::GetRetryTokenLengthLength(&creator_), 0,
+ QuicPacketCreatorPeer::GetLengthLength(&creator_)) +
+ // Add an extra 3 bytes for the payload and 1 byte so
+ // BytesFree is larger than the GetMinStreamFrameSize.
+ QuicFramer::GetMinStreamFrameSize(framer_.transport_version(), 1, 0,
+ false, 3) +
+ 3 +
+ QuicFramer::GetMinStreamFrameSize(framer_.transport_version(), 1, 0, true,
+ 1) +
+ 1;
+ creator_.SetMaxPacketLength(length);
+ delegate_.SetCanWriteAnything();
+ {
+ InSequence dummy;
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ }
+ // Queue enough data to prevent a stream frame with a non-zero offset from
+ // fitting.
+ MakeIOVector("foo", &iov_);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, NO_FIN);
+ EXPECT_EQ(3u, consumed.bytes_consumed);
+ EXPECT_FALSE(consumed.fin_consumed);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+
+ // This frame will not fit with the existing frame, causing the queued frame
+ // to be serialized, and it will be added to a new open packet.
+ MakeIOVector("bar", &iov_);
+ consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 3, FIN);
+ EXPECT_EQ(3u, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+
+ creator_.FlushCurrentPacket();
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ PacketContents contents;
+ contents.num_stream_frames = 1;
+ CheckPacketContains(contents, 0);
+ CheckPacketContains(contents, 1);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeDataFastPath) {
+ delegate_.SetCanWriteAnything();
+ creator_.SetTransmissionType(LOSS_RETRANSMISSION);
+
+ // Create a 10000 byte IOVector.
+ CreateData(10000);
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillRepeatedly(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ QuicConsumedData consumed = creator_.ConsumeDataFastPath(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, true);
+ EXPECT_EQ(10000u, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ PacketContents contents;
+ contents.num_stream_frames = 1;
+ CheckPacketContains(contents, 0);
+ EXPECT_FALSE(packets_.empty());
+ SerializedPacket packet = packets_.back();
+ EXPECT_TRUE(!packet.retransmittable_frames.empty());
+ EXPECT_EQ(LOSS_RETRANSMISSION, packet.transmission_type);
+ EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
+ const QuicStreamFrame& stream_frame =
+ packet.retransmittable_frames.front().stream_frame;
+ EXPECT_EQ(10000u, stream_frame.data_length + stream_frame.offset);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeDataLarge) {
+ delegate_.SetCanWriteAnything();
+
+ // Create a 10000 byte IOVector.
+ CreateData(10000);
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillRepeatedly(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, FIN);
+ EXPECT_EQ(10000u, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ PacketContents contents;
+ contents.num_stream_frames = 1;
+ CheckPacketContains(contents, 0);
+ EXPECT_FALSE(packets_.empty());
+ SerializedPacket packet = packets_.back();
+ EXPECT_TRUE(!packet.retransmittable_frames.empty());
+ EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
+ const QuicStreamFrame& stream_frame =
+ packet.retransmittable_frames.front().stream_frame;
+ EXPECT_EQ(10000u, stream_frame.data_length + stream_frame.offset);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeDataLargeSendAckFalse) {
+ delegate_.SetCanNotWrite();
+
+ QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
+ const bool success =
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/true);
+ EXPECT_FALSE(success);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ delegate_.SetCanWriteAnything();
+
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/false);
+
+ // Create a 10000 byte IOVector.
+ CreateData(10000);
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillRepeatedly(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(CreateRstStreamFrame()),
+ /*bundle_ack=*/true);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, FIN);
+ creator_.Flush();
+
+ EXPECT_EQ(10000u, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ EXPECT_FALSE(packets_.empty());
+ SerializedPacket packet = packets_.back();
+ EXPECT_TRUE(!packet.retransmittable_frames.empty());
+ EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
+ const QuicStreamFrame& stream_frame =
+ packet.retransmittable_frames.front().stream_frame;
+ EXPECT_EQ(10000u, stream_frame.data_length + stream_frame.offset);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeDataLargeSendAckTrue) {
+ delegate_.SetCanNotWrite();
+ delegate_.SetCanWriteAnything();
+
+ // Create a 10000 byte IOVector.
+ CreateData(10000);
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillRepeatedly(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, FIN);
+ creator_.Flush();
+
+ EXPECT_EQ(10000u, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ EXPECT_FALSE(packets_.empty());
+ SerializedPacket packet = packets_.back();
+ EXPECT_TRUE(!packet.retransmittable_frames.empty());
+ EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
+ const QuicStreamFrame& stream_frame =
+ packet.retransmittable_frames.front().stream_frame;
+ EXPECT_EQ(10000u, stream_frame.data_length + stream_frame.offset);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, NotWritableThenBatchOperations) {
+ delegate_.SetCanNotWrite();
+
+ QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
+ const bool consumed =
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/true);
+ EXPECT_FALSE(consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+ EXPECT_FALSE(creator_.HasPendingStreamFramesOfStream(3));
+
+ delegate_.SetCanWriteAnything();
+
+ EXPECT_TRUE(
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/false));
+ // Send some data and a control frame
+ MakeIOVector("quux", &iov_);
+ creator_.ConsumeData(3, &iov_, 1u, iov_.iov_len, 0, NO_FIN);
+ if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(CreateGoAwayFrame()),
+ /*bundle_ack=*/false);
+ }
+ EXPECT_TRUE(creator_.HasPendingStreamFramesOfStream(3));
+
+ // All five frames will be flushed out in a single packet.
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ creator_.Flush();
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+ EXPECT_FALSE(creator_.HasPendingStreamFramesOfStream(3));
+
+ PacketContents contents;
+ // ACK will be flushed by connection.
+ contents.num_ack_frames = 0;
+ if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
+ contents.num_goaway_frames = 1;
+ } else {
+ contents.num_goaway_frames = 0;
+ }
+ contents.num_rst_stream_frames = 1;
+ contents.num_stream_frames = 1;
+ CheckPacketContains(contents, 0);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, NotWritableThenBatchOperations2) {
+ delegate_.SetCanNotWrite();
+
+ QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
+ const bool success =
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/true);
+ EXPECT_FALSE(success);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ delegate_.SetCanWriteAnything();
+
+ {
+ InSequence dummy;
+ // All five frames will be flushed out in a single packet
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ }
+ EXPECT_TRUE(
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/false));
+ // Send enough data to exceed one packet
+ size_t data_len = kDefaultMaxPacketSize + 100;
+ CreateData(data_len);
+ QuicConsumedData consumed =
+ creator_.ConsumeData(3, &iov_, 1u, iov_.iov_len, 0, FIN);
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(CreateGoAwayFrame()),
+ /*bundle_ack=*/false);
+ }
+
+ creator_.Flush();
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ // The first packet should have the queued data and part of the stream data.
+ PacketContents contents;
+ // ACK will be sent by connection.
+ contents.num_ack_frames = 0;
+ contents.num_rst_stream_frames = 1;
+ contents.num_stream_frames = 1;
+ CheckPacketContains(contents, 0);
+
+ // The second should have the remainder of the stream data.
+ PacketContents contents2;
+ if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
+ contents2.num_goaway_frames = 1;
+ } else {
+ contents2.num_goaway_frames = 0;
+ }
+ contents2.num_stream_frames = 1;
+ CheckPacketContains(contents2, 1);
+}
+
+// Regression test of b/120493795.
+TEST_F(QuicPacketCreatorMultiplePacketsTest, PacketTransmissionType) {
+ delegate_.SetCanWriteAnything();
+
+ // The first ConsumeData will fill the packet without flush.
+ creator_.SetTransmissionType(LOSS_RETRANSMISSION);
+
+ size_t data_len = 1324;
+ CreateData(data_len);
+ QuicStreamId stream1_id = QuicUtils::GetFirstBidirectionalStreamId(
+ framer_.transport_version(), Perspective::IS_CLIENT);
+ QuicConsumedData consumed =
+ creator_.ConsumeData(stream1_id, &iov_, 1u, iov_.iov_len, 0, NO_FIN);
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+ ASSERT_EQ(0u, creator_.BytesFree())
+ << "Test setup failed: Please increase data_len to "
+ << data_len + creator_.BytesFree() << " bytes.";
+
+ // The second ConsumeData can not be added to the packet and will flush.
+ creator_.SetTransmissionType(NOT_RETRANSMISSION);
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+
+ QuicStreamId stream2_id = stream1_id + 4;
+
+ consumed =
+ creator_.ConsumeData(stream2_id, &iov_, 1u, iov_.iov_len, 0, NO_FIN);
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+
+ // Ensure the packet is successfully created.
+ ASSERT_EQ(1u, packets_.size());
+ ASSERT_TRUE(packets_[0].encrypted_buffer);
+ ASSERT_EQ(1u, packets_[0].retransmittable_frames.size());
+ EXPECT_EQ(stream1_id,
+ packets_[0].retransmittable_frames[0].stream_frame.stream_id);
+
+ // Since the second frame was not added, the packet's transmission type
+ // should be the first frame's type.
+ EXPECT_EQ(packets_[0].transmission_type, LOSS_RETRANSMISSION);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, TestConnectionIdLength) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
+ creator_.SetServerConnectionIdLength(0);
+ EXPECT_EQ(PACKET_0BYTE_CONNECTION_ID,
+ creator_.GetDestinationConnectionIdLength());
+
+ for (size_t i = 1; i < 10; i++) {
+ creator_.SetServerConnectionIdLength(i);
+ if (VersionHasIetfInvariantHeader(framer_.transport_version())) {
+ EXPECT_EQ(PACKET_0BYTE_CONNECTION_ID,
+ creator_.GetDestinationConnectionIdLength());
+ } else {
+ EXPECT_EQ(PACKET_8BYTE_CONNECTION_ID,
+ creator_.GetDestinationConnectionIdLength());
+ }
+ }
+}
+
+// Test whether SetMaxPacketLength() works in the situation when the queue is
+// empty, and we send three packets worth of data.
+TEST_F(QuicPacketCreatorMultiplePacketsTest, SetMaxPacketLength_Initial) {
+ delegate_.SetCanWriteAnything();
+
+ // Send enough data for three packets.
+ size_t data_len = 3 * kDefaultMaxPacketSize + 1;
+ size_t packet_len = kDefaultMaxPacketSize + 100;
+ ASSERT_LE(packet_len, kMaxOutgoingPacketSize);
+ creator_.SetMaxPacketLength(packet_len);
+ EXPECT_EQ(packet_len, creator_.max_packet_length());
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .Times(3)
+ .WillRepeatedly(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ CreateData(data_len);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len,
+ /*offset=*/0, FIN);
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ // We expect three packets, and first two of them have to be of packet_len
+ // size. We check multiple packets (instead of just one) because we want to
+ // ensure that |max_packet_length_| does not get changed incorrectly by the
+ // creator after first packet is serialized.
+ ASSERT_EQ(3u, packets_.size());
+ EXPECT_EQ(packet_len, packets_[0].encrypted_length);
+ EXPECT_EQ(packet_len, packets_[1].encrypted_length);
+ CheckAllPacketsHaveSingleStreamFrame();
+}
+
+// Test whether SetMaxPacketLength() works in the situation when we first write
+// data, then change packet size, then write data again.
+TEST_F(QuicPacketCreatorMultiplePacketsTest, SetMaxPacketLength_Middle) {
+ delegate_.SetCanWriteAnything();
+
+ // We send enough data to overflow default packet length, but not the altered
+ // one.
+ size_t data_len = kDefaultMaxPacketSize;
+ size_t packet_len = kDefaultMaxPacketSize + 100;
+ ASSERT_LE(packet_len, kMaxOutgoingPacketSize);
+
+ // We expect to see three packets in total.
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .Times(3)
+ .WillRepeatedly(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+
+ // Send two packets before packet size change.
+ CreateData(data_len);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len,
+ /*offset=*/0, NO_FIN);
+ creator_.Flush();
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+ EXPECT_FALSE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ // Make sure we already have two packets.
+ ASSERT_EQ(2u, packets_.size());
+
+ // Increase packet size.
+ creator_.SetMaxPacketLength(packet_len);
+ EXPECT_EQ(packet_len, creator_.max_packet_length());
+
+ // Send a packet after packet size change.
+ CreateData(data_len);
+ creator_.AttachPacketFlusher();
+ consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, data_len, FIN);
+ creator_.Flush();
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ // We expect first data chunk to get fragmented, but the second one to fit
+ // into a single packet.
+ ASSERT_EQ(3u, packets_.size());
+ EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length);
+ EXPECT_LE(kDefaultMaxPacketSize, packets_[2].encrypted_length);
+ CheckAllPacketsHaveSingleStreamFrame();
+}
+
+// Test whether SetMaxPacketLength() works correctly when we force the change of
+// the packet size in the middle of the batched packet.
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ SetMaxPacketLength_MidpacketFlush) {
+ delegate_.SetCanWriteAnything();
+
+ size_t first_write_len = kDefaultMaxPacketSize / 2;
+ size_t packet_len = kDefaultMaxPacketSize + 100;
+ size_t second_write_len = packet_len + 1;
+ ASSERT_LE(packet_len, kMaxOutgoingPacketSize);
+
+ // First send half of the packet worth of data. We are in the batch mode, so
+ // should not cause packet serialization.
+ CreateData(first_write_len);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len,
+ /*offset=*/0, NO_FIN);
+ EXPECT_EQ(first_write_len, consumed.bytes_consumed);
+ EXPECT_FALSE(consumed.fin_consumed);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+
+ // Make sure we have no packets so far.
+ ASSERT_EQ(0u, packets_.size());
+
+ // Expect a packet to be flushed.
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+
+ // Increase packet size after flushing all frames.
+ // Ensure it's immediately enacted.
+ creator_.FlushCurrentPacket();
+ creator_.SetMaxPacketLength(packet_len);
+ EXPECT_EQ(packet_len, creator_.max_packet_length());
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ // We expect to see exactly one packet serialized after that, because we send
+ // a value somewhat exceeding new max packet size, and the tail data does not
+ // get serialized because we are still in the batch mode.
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+
+ // Send a more than a packet worth of data to the same stream. This should
+ // trigger serialization of one packet, and queue another one.
+ CreateData(second_write_len);
+ consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len,
+ /*offset=*/first_write_len, FIN);
+ EXPECT_EQ(second_write_len, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+
+ // We expect the first packet to be underfilled, and the second packet be up
+ // to the new max packet size.
+ ASSERT_EQ(2u, packets_.size());
+ EXPECT_GT(kDefaultMaxPacketSize, packets_[0].encrypted_length);
+ EXPECT_EQ(packet_len, packets_[1].encrypted_length);
+
+ CheckAllPacketsHaveSingleStreamFrame();
+}
+
+// Test sending a connectivity probing packet.
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ GenerateConnectivityProbingPacket) {
+ delegate_.SetCanWriteAnything();
+
+ OwningSerializedPacketPointer probing_packet;
+ if (VersionHasIetfQuicFrames(framer_.transport_version())) {
+ QuicPathFrameBuffer payload = {
+ {0xde, 0xad, 0xbe, 0xef, 0xba, 0xdc, 0x0f, 0xfe}};
+ probing_packet =
+ creator_.SerializePathChallengeConnectivityProbingPacket(&payload);
+ } else {
+ probing_packet = creator_.SerializeConnectivityProbingPacket();
+ }
+
+ ASSERT_TRUE(simple_framer_.ProcessPacket(QuicEncryptedPacket(
+ probing_packet->encrypted_buffer, probing_packet->encrypted_length)));
+
+ EXPECT_EQ(2u, simple_framer_.num_frames());
+ if (VersionHasIetfQuicFrames(framer_.transport_version())) {
+ EXPECT_EQ(1u, simple_framer_.path_challenge_frames().size());
+ } else {
+ EXPECT_EQ(1u, simple_framer_.ping_frames().size());
+ }
+ EXPECT_EQ(1u, simple_framer_.padding_frames().size());
+}
+
+// Test sending an MTU probe, without any surrounding data.
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ GenerateMtuDiscoveryPacket_Simple) {
+ delegate_.SetCanWriteAnything();
+
+ const size_t target_mtu = kDefaultMaxPacketSize + 100;
+ static_assert(target_mtu < kMaxOutgoingPacketSize,
+ "The MTU probe used by the test exceeds maximum packet size");
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+
+ creator_.GenerateMtuDiscoveryPacket(target_mtu);
+
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+ ASSERT_EQ(1u, packets_.size());
+ EXPECT_EQ(target_mtu, packets_[0].encrypted_length);
+
+ PacketContents contents;
+ contents.num_mtu_discovery_frames = 1;
+ contents.num_padding_frames = 1;
+ CheckPacketContains(contents, 0);
+}
+
+// Test sending an MTU probe. Surround it with data, to ensure that it resets
+// the MTU to the value before the probe was sent.
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ GenerateMtuDiscoveryPacket_SurroundedByData) {
+ delegate_.SetCanWriteAnything();
+
+ const size_t target_mtu = kDefaultMaxPacketSize + 100;
+ static_assert(target_mtu < kMaxOutgoingPacketSize,
+ "The MTU probe used by the test exceeds maximum packet size");
+
+ // Send enough data so it would always cause two packets to be sent.
+ const size_t data_len = target_mtu + 1;
+
+ // Send a total of five packets: two packets before the probe, the probe
+ // itself, and two packets after the probe.
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .Times(5)
+ .WillRepeatedly(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+
+ // Send data before the MTU probe.
+ CreateData(data_len);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len,
+ /*offset=*/0, NO_FIN);
+ creator_.Flush();
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+ EXPECT_FALSE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ // Send the MTU probe.
+ creator_.GenerateMtuDiscoveryPacket(target_mtu);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ // Send data after the MTU probe.
+ CreateData(data_len);
+ creator_.AttachPacketFlusher();
+ consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len,
+ /*offset=*/data_len, FIN);
+ creator_.Flush();
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ ASSERT_EQ(5u, packets_.size());
+ EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length);
+ EXPECT_EQ(target_mtu, packets_[2].encrypted_length);
+ EXPECT_EQ(kDefaultMaxPacketSize, packets_[3].encrypted_length);
+
+ PacketContents probe_contents;
+ probe_contents.num_mtu_discovery_frames = 1;
+ probe_contents.num_padding_frames = 1;
+
+ CheckPacketHasSingleStreamFrame(0);
+ CheckPacketHasSingleStreamFrame(1);
+ CheckPacketContains(probe_contents, 2);
+ CheckPacketHasSingleStreamFrame(3);
+ CheckPacketHasSingleStreamFrame(4);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, DontCrashOnInvalidStopWaiting) {
+ if (VersionSupportsMessageFrames(framer_.transport_version())) {
+ return;
+ }
+ // Test added to ensure the creator does not crash when an invalid frame is
+ // added. Because this is an indication of internal programming errors,
+ // DFATALs are expected.
+ // A 1 byte packet number length can't encode a gap of 1000.
+ QuicPacketCreatorPeer::SetPacketNumber(&creator_, 1000);
+
+ delegate_.SetCanNotWrite();
+ delegate_.SetCanWriteAnything();
+
+ // This will not serialize any packets, because of the invalid frame.
+ EXPECT_CALL(delegate_,
+ OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET, _));
+ EXPECT_QUIC_BUG(creator_.Flush(),
+ "packet_number_length 1 is too small "
+ "for least_unacked_delta: 1001");
+}
+
+// Regression test for b/31486443.
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ ConnectionCloseFrameLargerThanPacketSize) {
+ delegate_.SetCanWriteAnything();
+ char buf[2000] = {};
+ QuicStringPiece error_details(buf, 2000);
+ const QuicErrorCode kQuicErrorCode = QUIC_PACKET_WRITE_ERROR;
+
+ QuicConnectionCloseFrame* frame = new QuicConnectionCloseFrame(
+ framer_.transport_version(), kQuicErrorCode, std::string(error_details),
+ /*transport_close_frame_type=*/0);
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(frame),
+ /*bundle_ack=*/false);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ RandomPaddingAfterFinSingleStreamSinglePacket) {
+ const QuicByteCount kStreamFramePayloadSize = 100u;
+ char buf[kStreamFramePayloadSize] = {};
+ const QuicStreamId kDataStreamId = 5;
+ // Set the packet size be enough for one stream frame with 0 stream offset and
+ // max size of random padding.
+ size_t length =
+ NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
+ GetPacketHeaderSize(
+ framer_.transport_version(),
+ creator_.GetDestinationConnectionIdLength(),
+ creator_.GetSourceConnectionIdLength(),
+ QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
+ !kIncludeDiversificationNonce,
+ QuicPacketCreatorPeer::GetPacketNumberLength(&creator_),
+ QuicPacketCreatorPeer::GetRetryTokenLengthLength(&creator_), 0,
+ QuicPacketCreatorPeer::GetLengthLength(&creator_)) +
+ QuicFramer::GetMinStreamFrameSize(
+ framer_.transport_version(), kDataStreamId, 0,
+ /*last_frame_in_packet=*/false,
+ kStreamFramePayloadSize + kMaxNumRandomPaddingBytes) +
+ kStreamFramePayloadSize + kMaxNumRandomPaddingBytes;
+ creator_.SetMaxPacketLength(length);
+ delegate_.SetCanWriteAnything();
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ kDataStreamId, &iov_, 1u, iov_.iov_len, 0, FIN_AND_PADDING);
+ creator_.Flush();
+ EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ EXPECT_EQ(1u, packets_.size());
+ PacketContents contents;
+ // The packet has both stream and padding frames.
+ contents.num_padding_frames = 1;
+ contents.num_stream_frames = 1;
+ CheckPacketContains(contents, 0);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ RandomPaddingAfterFinSingleStreamMultiplePackets) {
+ const QuicByteCount kStreamFramePayloadSize = 100u;
+ char buf[kStreamFramePayloadSize] = {};
+ const QuicStreamId kDataStreamId = 5;
+ // Set the packet size be enough for one stream frame with 0 stream offset +
+ // 1. One or more packets will accommodate.
+ size_t length =
+ NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
+ GetPacketHeaderSize(
+ framer_.transport_version(),
+ creator_.GetDestinationConnectionIdLength(),
+ creator_.GetSourceConnectionIdLength(),
+ QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
+ !kIncludeDiversificationNonce,
+ QuicPacketCreatorPeer::GetPacketNumberLength(&creator_),
+ QuicPacketCreatorPeer::GetRetryTokenLengthLength(&creator_), 0,
+ QuicPacketCreatorPeer::GetLengthLength(&creator_)) +
+ QuicFramer::GetMinStreamFrameSize(
+ framer_.transport_version(), kDataStreamId, 0,
+ /*last_frame_in_packet=*/false, kStreamFramePayloadSize + 1) +
+ kStreamFramePayloadSize + 1;
+ creator_.SetMaxPacketLength(length);
+ delegate_.SetCanWriteAnything();
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillRepeatedly(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ kDataStreamId, &iov_, 1u, iov_.iov_len, 0, FIN_AND_PADDING);
+ creator_.Flush();
+ EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ EXPECT_LE(1u, packets_.size());
+ PacketContents contents;
+ // The first packet has both stream and padding frames.
+ contents.num_stream_frames = 1;
+ contents.num_padding_frames = 1;
+ CheckPacketContains(contents, 0);
+
+ for (size_t i = 1; i < packets_.size(); ++i) {
+ // Following packets only have paddings.
+ contents.num_stream_frames = 0;
+ contents.num_padding_frames = 1;
+ CheckPacketContains(contents, i);
+ }
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ RandomPaddingAfterFinMultipleStreamsMultiplePackets) {
+ const QuicByteCount kStreamFramePayloadSize = 100u;
+ char buf[kStreamFramePayloadSize] = {};
+ const QuicStreamId kDataStreamId1 = 5;
+ const QuicStreamId kDataStreamId2 = 6;
+ // Set the packet size be enough for first frame with 0 stream offset + second
+ // frame + 1 byte payload. two or more packets will accommodate.
+ size_t length =
+ NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
+ GetPacketHeaderSize(
+ framer_.transport_version(),
+ creator_.GetDestinationConnectionIdLength(),
+ creator_.GetSourceConnectionIdLength(),
+ QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
+ !kIncludeDiversificationNonce,
+ QuicPacketCreatorPeer::GetPacketNumberLength(&creator_),
+ QuicPacketCreatorPeer::GetRetryTokenLengthLength(&creator_), 0,
+ QuicPacketCreatorPeer::GetLengthLength(&creator_)) +
+ QuicFramer::GetMinStreamFrameSize(
+ framer_.transport_version(), kDataStreamId1, 0,
+ /*last_frame_in_packet=*/false, kStreamFramePayloadSize) +
+ kStreamFramePayloadSize +
+ QuicFramer::GetMinStreamFrameSize(framer_.transport_version(),
+ kDataStreamId1, 0,
+ /*last_frame_in_packet=*/false, 1) +
+ 1;
+ creator_.SetMaxPacketLength(length);
+ delegate_.SetCanWriteAnything();
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillRepeatedly(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ kDataStreamId1, &iov_, 1u, iov_.iov_len, 0, FIN_AND_PADDING);
+ EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
+ MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
+ consumed = creator_.ConsumeData(kDataStreamId2, &iov_, 1u, iov_.iov_len, 0,
+ FIN_AND_PADDING);
+ EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
+ creator_.Flush();
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ EXPECT_LE(2u, packets_.size());
+ PacketContents contents;
+ // The first packet has two stream frames.
+ contents.num_stream_frames = 2;
+ CheckPacketContains(contents, 0);
+
+ // The second packet has one stream frame and padding frames.
+ contents.num_stream_frames = 1;
+ contents.num_padding_frames = 1;
+ CheckPacketContains(contents, 1);
+
+ for (size_t i = 2; i < packets_.size(); ++i) {
+ // Following packets only have paddings.
+ contents.num_stream_frames = 0;
+ contents.num_padding_frames = 1;
+ CheckPacketContains(contents, i);
+ }
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, AddMessageFrame) {
+ if (!VersionSupportsMessageFrames(framer_.transport_version())) {
+ return;
+ }
+ quic::QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
+ delegate_.SetCanWriteAnything();
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+
+ MakeIOVector("foo", &iov_);
+ creator_.ConsumeData(QuicUtils::GetFirstBidirectionalStreamId(
+ framer_.transport_version(), Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, FIN);
+ EXPECT_EQ(
+ MESSAGE_STATUS_SUCCESS,
+ creator_.AddMessageFrame(1, MakeSpan(&allocator_, "message", &storage)));
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+
+ // Add a message which causes the flush of current packet.
+ EXPECT_EQ(
+ MESSAGE_STATUS_SUCCESS,
+ creator_.AddMessageFrame(
+ 2,
+ MakeSpan(&allocator_,
+ std::string(creator_.GetCurrentLargestMessagePayload(), 'a'),
+ &storage)));
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+
+ // Failed to send messages which cannot fit into one packet.
+ EXPECT_EQ(
+ MESSAGE_STATUS_TOO_LARGE,
+ creator_.AddMessageFrame(
+ 3, MakeSpan(&allocator_,
+ std::string(
+ creator_.GetCurrentLargestMessagePayload() + 10, 'a'),
+ &storage)));
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConnectionId) {
+ creator_.SetServerConnectionId(TestConnectionId(0x1337));
+ EXPECT_EQ(TestConnectionId(0x1337), creator_.GetDestinationConnectionId());
+ EXPECT_EQ(EmptyQuicConnectionId(), creator_.GetSourceConnectionId());
+ if (!framer_.version().SupportsClientConnectionIds()) {
+ return;
+ }
+ creator_.SetClientConnectionId(TestConnectionId(0x33));
+ EXPECT_EQ(TestConnectionId(0x1337), creator_.GetDestinationConnectionId());
+ EXPECT_EQ(TestConnectionId(0x33), creator_.GetSourceConnectionId());
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_generator.cc b/chromium/net/third_party/quiche/src/quic/core/quic_packet_generator.cc
deleted file mode 100644
index fbb7894d0da..00000000000
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_generator.cc
+++ /dev/null
@@ -1,556 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/third_party/quiche/src/quic/core/quic_packet_generator.h"
-
-#include <cstdint>
-
-#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
-#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
-#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_server_stats.h"
-
-namespace quic {
-
-QuicPacketGenerator::QuicPacketGenerator(
- QuicConnectionId server_connection_id,
- QuicFramer* framer,
- QuicRandom* random_generator,
- QuicPacketCreator::DelegateInterface* delegate)
- : delegate_(delegate),
- packet_creator_(server_connection_id, framer, random_generator, delegate),
- next_transmission_type_(NOT_RETRANSMISSION),
- flusher_attached_(false),
- random_generator_(random_generator),
- fully_pad_crypto_handshake_packets_(true) {}
-
-QuicPacketGenerator::~QuicPacketGenerator() {}
-
-bool QuicPacketGenerator::ConsumeRetransmittableControlFrame(
- const QuicFrame& frame) {
- if (packet_creator_.combine_generator_and_creator()) {
- return packet_creator_.ConsumeRetransmittableControlFrame(frame);
- }
- QUIC_BUG_IF(IsControlFrame(frame.type) && !GetControlFrameId(frame))
- << "Adding a control frame with no control frame id: " << frame;
- DCHECK(QuicUtils::IsRetransmittableFrame(frame.type)) << frame;
- MaybeBundleAckOpportunistically();
- if (packet_creator_.HasPendingFrames()) {
- if (packet_creator_.AddSavedFrame(frame, next_transmission_type_)) {
- // There is pending frames and current frame fits.
- return true;
- }
- }
- DCHECK(!packet_creator_.HasPendingFrames());
- if (frame.type != PING_FRAME && frame.type != CONNECTION_CLOSE_FRAME &&
- !delegate_->ShouldGeneratePacket(HAS_RETRANSMITTABLE_DATA,
- NOT_HANDSHAKE)) {
- // Do not check congestion window for ping or connection close frames.
- return false;
- }
- const bool success =
- packet_creator_.AddSavedFrame(frame, next_transmission_type_);
- DCHECK(success);
- return success;
-}
-
-size_t QuicPacketGenerator::ConsumeCryptoData(EncryptionLevel level,
- size_t write_length,
- QuicStreamOffset offset) {
- if (packet_creator_.combine_generator_and_creator()) {
- return packet_creator_.ConsumeCryptoData(level, write_length, offset);
- }
- QUIC_BUG_IF(!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.
- // TODO(nharper): Once we have separate packet number spaces, everything
- // should be driven by encryption level, and we should stop flushing in this
- // spot.
- if (packet_creator_.HasPendingRetransmittableFrames()) {
- packet_creator_.FlushCurrentPacket();
- }
-
- size_t total_bytes_consumed = 0;
-
- while (total_bytes_consumed < write_length) {
- QuicFrame frame;
- if (!packet_creator_.ConsumeCryptoDataToFillCurrentPacket(
- level, write_length - total_bytes_consumed,
- offset + total_bytes_consumed, fully_pad_crypto_handshake_packets_,
- next_transmission_type_, &frame)) {
- // 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;
- return 0;
- }
- total_bytes_consumed += frame.crypto_frame->data_length;
-
- // TODO(ianswett): Move to having the creator flush itself when it's full.
- packet_creator_.FlushCurrentPacket();
- }
-
- // Don't allow the handshake to be bundled with other retransmittable frames.
- packet_creator_.FlushCurrentPacket();
-
- return total_bytes_consumed;
-}
-
-QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state) {
- if (packet_creator_.combine_generator_and_creator()) {
- return packet_creator_.ConsumeData(id, write_length, offset, state);
- }
- QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
- "generator tries to write stream data.";
- bool has_handshake =
- QuicUtils::IsCryptoStreamId(packet_creator_.transport_version(), id);
- MaybeBundleAckOpportunistically();
- bool fin = state != NO_FIN;
- QUIC_BUG_IF(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.
- if (has_handshake && packet_creator_.HasPendingRetransmittableFrames()) {
- packet_creator_.FlushCurrentPacket();
- }
-
- size_t total_bytes_consumed = 0;
- bool fin_consumed = false;
-
- if (!packet_creator_.HasRoomForStreamFrame(id, offset, write_length)) {
- packet_creator_.FlushCurrentPacket();
- }
-
- if (!fin && (write_length == 0)) {
- QUIC_BUG << "Attempt to consume empty data without FIN.";
- return QuicConsumedData(0, false);
- }
- // We determine if we can enter the fast path before executing
- // the slow path loop.
- bool run_fast_path =
- !has_handshake && state != FIN_AND_PADDING && !HasPendingFrames() &&
- write_length - total_bytes_consumed > kMaxOutgoingPacketSize;
-
- while (!run_fast_path && delegate_->ShouldGeneratePacket(
- HAS_RETRANSMITTABLE_DATA,
- has_handshake ? IS_HANDSHAKE : NOT_HANDSHAKE)) {
- QuicFrame frame;
- bool needs_full_padding =
- has_handshake && fully_pad_crypto_handshake_packets_;
-
- if (!packet_creator_.ConsumeDataToFillCurrentPacket(
- id, write_length - total_bytes_consumed,
- offset + total_bytes_consumed, fin, needs_full_padding,
- 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;
- return QuicConsumedData(0, false);
- }
-
- // A stream frame is created and added.
- size_t bytes_consumed = frame.stream_frame.data_length;
- total_bytes_consumed += bytes_consumed;
- fin_consumed = fin && total_bytes_consumed == write_length;
- if (fin_consumed && state == FIN_AND_PADDING) {
- AddRandomPadding();
- }
- DCHECK(total_bytes_consumed == write_length ||
- (bytes_consumed > 0 && packet_creator_.HasPendingFrames()));
-
- if (total_bytes_consumed == write_length) {
- // We're done writing the data. Exit the loop.
- // We don't make this a precondition because we could have 0 bytes of data
- // if we're simply writing a fin.
- break;
- }
- // TODO(ianswett): Move to having the creator flush itself when it's full.
- packet_creator_.FlushCurrentPacket();
-
- run_fast_path =
- !has_handshake && state != FIN_AND_PADDING && !HasPendingFrames() &&
- write_length - total_bytes_consumed > kMaxOutgoingPacketSize;
- }
-
- if (run_fast_path) {
- return ConsumeDataFastPath(id, write_length, offset, state != NO_FIN,
- total_bytes_consumed);
- }
-
- // Don't allow the handshake to be bundled with other retransmittable frames.
- if (has_handshake) {
- packet_creator_.FlushCurrentPacket();
- }
-
- return QuicConsumedData(total_bytes_consumed, fin_consumed);
-}
-
-QuicConsumedData QuicPacketGenerator::ConsumeDataFastPath(
- QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- bool fin,
- size_t total_bytes_consumed) {
- if (packet_creator_.combine_generator_and_creator()) {
- return packet_creator_.ConsumeDataFastPath(id, write_length, offset, fin,
- total_bytes_consumed);
- }
- DCHECK(!QuicUtils::IsCryptoStreamId(packet_creator_.transport_version(), id));
-
- while (total_bytes_consumed < write_length &&
- delegate_->ShouldGeneratePacket(HAS_RETRANSMITTABLE_DATA,
- NOT_HANDSHAKE)) {
- // Serialize and encrypt the packet.
- size_t bytes_consumed = 0;
- packet_creator_.CreateAndSerializeStreamFrame(
- id, write_length, total_bytes_consumed, offset + total_bytes_consumed,
- fin, next_transmission_type_, &bytes_consumed);
- total_bytes_consumed += bytes_consumed;
- }
-
- return QuicConsumedData(total_bytes_consumed,
- fin && (total_bytes_consumed == write_length));
-}
-
-void QuicPacketGenerator::GenerateMtuDiscoveryPacket(QuicByteCount target_mtu) {
- if (packet_creator_.combine_generator_and_creator()) {
- packet_creator_.GenerateMtuDiscoveryPacket(target_mtu);
- return;
- }
- // MTU discovery frames must be sent by themselves.
- if (!packet_creator_.CanSetMaxPacketLength()) {
- QUIC_BUG << "MTU discovery packets should only be sent when no other "
- << "frames needs to be sent.";
- return;
- }
- const QuicByteCount current_mtu = GetCurrentMaxPacketLength();
-
- // The MTU discovery frame is allocated on the stack, since it is going to be
- // serialized within this function.
- QuicMtuDiscoveryFrame mtu_discovery_frame;
- QuicFrame frame(mtu_discovery_frame);
-
- // Send the probe packet with the new length.
- SetMaxPacketLength(target_mtu);
- const bool success =
- packet_creator_.AddPaddedSavedFrame(frame, next_transmission_type_);
- packet_creator_.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.
- DCHECK(success);
-
- // Reset the packet length back.
- SetMaxPacketLength(current_mtu);
-}
-
-bool QuicPacketGenerator::PacketFlusherAttached() const {
- if (packet_creator_.combine_generator_and_creator()) {
- return packet_creator_.PacketFlusherAttached();
- }
- return flusher_attached_;
-}
-
-void QuicPacketGenerator::AttachPacketFlusher() {
- if (packet_creator_.combine_generator_and_creator()) {
- packet_creator_.AttachPacketFlusher();
- return;
- }
- flusher_attached_ = true;
- if (!write_start_packet_number_.IsInitialized()) {
- write_start_packet_number_ = packet_creator_.NextSendingPacketNumber();
- }
-}
-
-void QuicPacketGenerator::Flush() {
- if (packet_creator_.combine_generator_and_creator()) {
- packet_creator_.Flush();
- return;
- }
- packet_creator_.FlushCurrentPacket();
- SendRemainingPendingPadding();
- flusher_attached_ = false;
- if (GetQuicFlag(FLAGS_quic_export_server_num_packets_per_write_histogram)) {
- if (!write_start_packet_number_.IsInitialized()) {
- QUIC_BUG << "write_start_packet_number is not initialized";
- return;
- }
- QUIC_SERVER_HISTOGRAM_COUNTS(
- "quic_server_num_written_packets_per_write",
- packet_creator_.NextSendingPacketNumber() - write_start_packet_number_,
- 1, 200, 50, "Number of QUIC packets written per write operation");
- }
- write_start_packet_number_.Clear();
-}
-
-void QuicPacketGenerator::FlushAllQueuedFrames() {
- packet_creator_.FlushCurrentPacket();
-}
-
-bool QuicPacketGenerator::HasPendingFrames() const {
- return packet_creator_.HasPendingFrames();
-}
-
-void QuicPacketGenerator::StopSendingVersion() {
- packet_creator_.StopSendingVersion();
-}
-
-void QuicPacketGenerator::SetDiversificationNonce(
- const DiversificationNonce& nonce) {
- packet_creator_.SetDiversificationNonce(nonce);
-}
-
-QuicPacketNumber QuicPacketGenerator::packet_number() const {
- return packet_creator_.packet_number();
-}
-
-QuicByteCount QuicPacketGenerator::GetCurrentMaxPacketLength() const {
- return packet_creator_.max_packet_length();
-}
-
-void QuicPacketGenerator::SetMaxPacketLength(QuicByteCount length) {
- DCHECK(packet_creator_.CanSetMaxPacketLength());
- packet_creator_.SetMaxPacketLength(length);
-}
-
-std::unique_ptr<QuicEncryptedPacket>
-QuicPacketGenerator::SerializeVersionNegotiationPacket(
- bool ietf_quic,
- bool use_length_prefix,
- const ParsedQuicVersionVector& supported_versions) {
- return packet_creator_.SerializeVersionNegotiationPacket(
- ietf_quic, use_length_prefix, supported_versions);
-}
-
-OwningSerializedPacketPointer
-QuicPacketGenerator::SerializeConnectivityProbingPacket() {
- return packet_creator_.SerializeConnectivityProbingPacket();
-}
-
-OwningSerializedPacketPointer
-QuicPacketGenerator::SerializePathChallengeConnectivityProbingPacket(
- QuicPathFrameBuffer* payload) {
- return packet_creator_.SerializePathChallengeConnectivityProbingPacket(
- payload);
-}
-
-OwningSerializedPacketPointer
-QuicPacketGenerator::SerializePathResponseConnectivityProbingPacket(
- const QuicDeque<QuicPathFrameBuffer>& payloads,
- const bool is_padded) {
- return packet_creator_.SerializePathResponseConnectivityProbingPacket(
- payloads, is_padded);
-}
-
-void QuicPacketGenerator::ReserializeAllFrames(
- const QuicPendingRetransmission& retransmission,
- char* buffer,
- size_t buffer_len) {
- packet_creator_.ReserializeAllFrames(retransmission, buffer, buffer_len);
-}
-
-void QuicPacketGenerator::UpdatePacketNumberLength(
- QuicPacketNumber least_packet_awaited_by_peer,
- QuicPacketCount max_packets_in_flight) {
- return packet_creator_.UpdatePacketNumberLength(least_packet_awaited_by_peer,
- max_packets_in_flight);
-}
-
-void QuicPacketGenerator::SkipNPacketNumbers(
- QuicPacketCount count,
- QuicPacketNumber least_packet_awaited_by_peer,
- QuicPacketCount max_packets_in_flight) {
- packet_creator_.SkipNPacketNumbers(count, least_packet_awaited_by_peer,
- max_packets_in_flight);
-}
-
-void QuicPacketGenerator::SetServerConnectionIdLength(uint32_t length) {
- if (packet_creator_.combine_generator_and_creator()) {
- packet_creator_.SetServerConnectionIdLength(length);
- return;
- }
- if (length == 0) {
- packet_creator_.SetServerConnectionIdIncluded(CONNECTION_ID_ABSENT);
- } else {
- packet_creator_.SetServerConnectionIdIncluded(CONNECTION_ID_PRESENT);
- }
-}
-
-void QuicPacketGenerator::set_encryption_level(EncryptionLevel level) {
- packet_creator_.set_encryption_level(level);
-}
-
-void QuicPacketGenerator::SetEncrypter(
- EncryptionLevel level,
- std::unique_ptr<QuicEncrypter> encrypter) {
- packet_creator_.SetEncrypter(level, std::move(encrypter));
-}
-
-void QuicPacketGenerator::AddRandomPadding() {
- if (packet_creator_.combine_generator_and_creator()) {
- packet_creator_.AddRandomPadding();
- return;
- }
- packet_creator_.AddPendingPadding(
- random_generator_->RandUint64() % kMaxNumRandomPaddingBytes + 1);
-}
-
-void QuicPacketGenerator::SendRemainingPendingPadding() {
- if (packet_creator_.combine_generator_and_creator()) {
- packet_creator_.SendRemainingPendingPadding();
- return;
- }
- while (
- packet_creator_.pending_padding_bytes() > 0 && !HasPendingFrames() &&
- delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)) {
- packet_creator_.FlushCurrentPacket();
- }
-}
-
-bool QuicPacketGenerator::HasRetransmittableFrames() const {
- return packet_creator_.HasPendingRetransmittableFrames();
-}
-
-bool QuicPacketGenerator::HasPendingStreamFramesOfStream(
- QuicStreamId id) const {
- return packet_creator_.HasPendingStreamFramesOfStream(id);
-}
-
-void QuicPacketGenerator::SetTransmissionType(TransmissionType type) {
- if (packet_creator_.combine_generator_and_creator()) {
- packet_creator_.SetTransmissionType(type);
- return;
- }
- packet_creator_.SetTransmissionTypeOfNextPackets(type);
- if (packet_creator_.can_set_transmission_type()) {
- next_transmission_type_ = type;
- }
-}
-
-void QuicPacketGenerator::SetRetryToken(QuicStringPiece retry_token) {
- packet_creator_.SetRetryToken(retry_token);
-}
-
-void QuicPacketGenerator::SetCanSetTransmissionType(
- bool can_set_transmission_type) {
- packet_creator_.set_can_set_transmission_type(can_set_transmission_type);
-}
-
-MessageStatus QuicPacketGenerator::AddMessageFrame(QuicMessageId message_id,
- QuicMemSliceSpan message) {
- if (packet_creator_.combine_generator_and_creator()) {
- return packet_creator_.AddMessageFrame(message_id, message);
- }
- QUIC_BUG_IF(!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()) {
- return MESSAGE_STATUS_TOO_LARGE;
- }
- if (!packet_creator_.HasRoomForMessageFrame(message_length)) {
- packet_creator_.FlushCurrentPacket();
- }
- QuicMessageFrame* frame = new QuicMessageFrame(message_id, message);
- const bool success =
- packet_creator_.AddSavedFrame(QuicFrame(frame), next_transmission_type_);
- if (!success) {
- QUIC_BUG << "Failed to send message " << message_id;
- delete frame;
- return MESSAGE_STATUS_INTERNAL_ERROR;
- }
- return MESSAGE_STATUS_SUCCESS;
-}
-
-void QuicPacketGenerator::MaybeBundleAckOpportunistically() {
- if (packet_creator_.combine_generator_and_creator()) {
- packet_creator_.MaybeBundleAckOpportunistically();
- return;
- }
- if (packet_creator_.has_ack()) {
- // Ack already queued, nothing to do.
- return;
- }
- if (!delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
- NOT_HANDSHAKE)) {
- return;
- }
- const bool flushed =
- FlushAckFrame(delegate_->MaybeBundleAckOpportunistically());
- DCHECK(flushed);
-}
-
-bool QuicPacketGenerator::FlushAckFrame(const QuicFrames& frames) {
- if (packet_creator_.combine_generator_and_creator()) {
- return packet_creator_.FlushAckFrame(frames);
- }
- QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
- "generator tries to send ACK frame.";
- for (const auto& frame : frames) {
- DCHECK(frame.type == ACK_FRAME || frame.type == STOP_WAITING_FRAME);
- if (packet_creator_.HasPendingFrames()) {
- if (packet_creator_.AddSavedFrame(frame, next_transmission_type_)) {
- // There is pending frames and current frame fits.
- continue;
- }
- }
- DCHECK(!packet_creator_.HasPendingFrames());
- // There is no pending frames, consult the delegate whether a packet can be
- // generated.
- if (!delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
- NOT_HANDSHAKE)) {
- return false;
- }
- const bool success =
- packet_creator_.AddSavedFrame(frame, next_transmission_type_);
- QUIC_BUG_IF(!success) << "Failed to flush " << frame;
- }
- return true;
-}
-
-QuicPacketLength QuicPacketGenerator::GetCurrentLargestMessagePayload() const {
- return packet_creator_.GetCurrentLargestMessagePayload();
-}
-
-QuicPacketLength QuicPacketGenerator::GetGuaranteedLargestMessagePayload()
- const {
- return packet_creator_.GetGuaranteedLargestMessagePayload();
-}
-
-void QuicPacketGenerator::SetServerConnectionId(
- QuicConnectionId server_connection_id) {
- packet_creator_.SetServerConnectionId(server_connection_id);
-}
-
-void QuicPacketGenerator::SetClientConnectionId(
- QuicConnectionId client_connection_id) {
- packet_creator_.SetClientConnectionId(client_connection_id);
-}
-
-void QuicPacketGenerator::set_fully_pad_crypto_handshake_packets(
- bool new_value) {
- if (packet_creator_.combine_generator_and_creator()) {
- packet_creator_.set_fully_pad_crypto_handshake_packets(new_value);
- return;
- }
- fully_pad_crypto_handshake_packets_ = new_value;
-}
-
-bool QuicPacketGenerator::fully_pad_crypto_handshake_packets() const {
- if (packet_creator_.combine_generator_and_creator()) {
- return packet_creator_.fully_pad_crypto_handshake_packets();
- }
- return fully_pad_crypto_handshake_packets_;
-}
-
-} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_generator.h b/chromium/net/third_party/quiche/src/quic/core/quic_packet_generator.h
deleted file mode 100644
index 7d8df7e778e..00000000000
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_generator.h
+++ /dev/null
@@ -1,269 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Responsible for generating packets on behalf of a QuicConnection.
-// Packets are serialized just-in-time.
-// Ack and Feedback frames will be requested from the Connection
-// just-in-time. When a packet needs to be sent, the Generator
-// will serialize a packet and pass it to QuicConnection::SendOrQueuePacket()
-//
-// The Generator's mode of operation is controlled by two conditions:
-//
-// 1) Is the Delegate writable?
-//
-// If the Delegate is not writable, then no operations will cause
-// a packet to be serialized. In particular:
-// * SetShouldSendAck will simply record that an ack is to be sent.
-// * AddControlFrame will enqueue the control frame.
-// * ConsumeData will do nothing.
-//
-// If the Delegate is writable, then the behavior depends on the second
-// condition:
-//
-// 2) Is the Generator in batch mode?
-//
-// If the Generator is NOT in batch mode, then each call to a write
-// operation will serialize one or more packets. The contents will
-// include any previous queued frames. If an ack should be sent
-// but has not been sent, then the Delegate will be asked to create
-// an Ack frame which will then be included in the packet. When
-// the write call completes, the current packet will be serialized
-// and sent to the Delegate, even if it is not full.
-//
-// If the Generator is in batch mode, then each write operation will
-// add data to the "current" packet. When the current packet becomes
-// full, it will be serialized and sent to the packet. When batch
-// mode is ended via |FinishBatchOperations|, the current packet
-// will be serialzied, even if it is not full.
-
-#ifndef QUICHE_QUIC_CORE_QUIC_PACKET_GENERATOR_H_
-#define QUICHE_QUIC_CORE_QUIC_PACKET_GENERATOR_H_
-
-#include <cstddef>
-#include <cstdint>
-#include <list>
-
-#include "net/third_party/quiche/src/quic/core/quic_packet_creator.h"
-#include "net/third_party/quiche/src/quic/core/quic_pending_retransmission.h"
-#include "net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h"
-#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h"
-
-namespace quic {
-
-namespace test {
-class QuicPacketGeneratorPeer;
-} // namespace test
-
-class QUIC_EXPORT_PRIVATE QuicPacketGenerator {
- public:
- QuicPacketGenerator(QuicConnectionId server_connection_id,
- QuicFramer* framer,
- QuicRandom* random_generator,
- QuicPacketCreator::DelegateInterface* delegate);
- QuicPacketGenerator(const QuicPacketGenerator&) = delete;
- QuicPacketGenerator& operator=(const QuicPacketGenerator&) = delete;
-
- ~QuicPacketGenerator();
-
- // Consumes retransmittable control |frame|. Returns true if the frame is
- // successfully consumed. Returns false otherwise.
- bool ConsumeRetransmittableControlFrame(const QuicFrame& frame);
-
- // Given some data, may consume part or all of it and pass it to the
- // packet creator to be serialized into packets. If not in batch
- // mode, these packets will also be sent during this call.
- // When |state| is FIN_AND_PADDING, random padding of size [1, 256] will be
- // added after stream frames. If current constructed packet cannot
- // accommodate, the padding will overflow to the next packet(s).
- QuicConsumedData ConsumeData(QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state);
-
- // Consumes data for CRYPTO frames sent at |level| starting at |offset| for a
- // total of |write_length| bytes, and returns the number of bytes consumed.
- // The data is passed into the packet creator and serialized into one or more
- // packets.
- size_t ConsumeCryptoData(EncryptionLevel level,
- size_t write_length,
- QuicStreamOffset offset);
-
- // Sends as many data only packets as allowed by the send algorithm and the
- // available iov.
- // This path does not support padding, or bundling pending frames.
- // In case we access this method from ConsumeData, total_bytes_consumed
- // keeps track of how many bytes have already been consumed.
- QuicConsumedData ConsumeDataFastPath(QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- bool fin,
- size_t total_bytes_consumed);
-
- // Generates an MTU discovery packet of specified size.
- void GenerateMtuDiscoveryPacket(QuicByteCount target_mtu);
-
- // Indicates whether packet flusher is currently attached.
- bool PacketFlusherAttached() const;
- // Attaches packet flusher.
- void AttachPacketFlusher();
- // Flushes everything, including current open packet and pending padding.
- void Flush();
-
- // Flushes current open packet.
- void FlushAllQueuedFrames();
-
- // Returns true if there are frames pending to be serialized.
- bool HasPendingFrames() const;
-
- // Makes the framer not serialize the protocol version in sent packets.
- void StopSendingVersion();
-
- // SetDiversificationNonce sets the nonce that will be sent in each public
- // header of packets encrypted at the initial encryption level. Should only
- // be called by servers.
- void SetDiversificationNonce(const DiversificationNonce& nonce);
-
- // Creates a version negotiation packet which supports |supported_versions|.
- std::unique_ptr<QuicEncryptedPacket> SerializeVersionNegotiationPacket(
- bool ietf_quic,
- bool use_length_prefix,
- const ParsedQuicVersionVector& supported_versions);
-
- // Creates a connectivity probing packet.
- OwningSerializedPacketPointer SerializeConnectivityProbingPacket();
-
- // Create connectivity probing request and response packets using PATH
- // CHALLENGE and PATH RESPONSE frames, respectively.
- // SerializePathChallengeConnectivityProbingPacket will pad the packet to be
- // MTU bytes long.
- OwningSerializedPacketPointer SerializePathChallengeConnectivityProbingPacket(
- QuicPathFrameBuffer* payload);
-
- // If |is_padded| is true then SerializePathResponseConnectivityProbingPacket
- // will pad the packet to be MTU bytes long, else it will not pad the packet.
- // |payloads| is cleared.
- OwningSerializedPacketPointer SerializePathResponseConnectivityProbingPacket(
- const QuicDeque<QuicPathFrameBuffer>& payloads,
- const bool is_padded);
-
- // Re-serializes frames with the original packet's packet number length.
- // Used for retransmitting packets to ensure they aren't too long.
- void ReserializeAllFrames(const QuicPendingRetransmission& retransmission,
- char* buffer,
- size_t buffer_len);
-
- // Update the packet number length to use in future packets as soon as it
- // can be safely changed.
- void UpdatePacketNumberLength(QuicPacketNumber least_packet_awaited_by_peer,
- QuicPacketCount max_packets_in_flight);
-
- // Skip |count| packet numbers.
- void SkipNPacketNumbers(QuicPacketCount count,
- QuicPacketNumber least_packet_awaited_by_peer,
- QuicPacketCount max_packets_in_flight);
-
- // Set the minimum number of bytes for the server connection id length;
- void SetServerConnectionIdLength(uint32_t length);
-
- // Sets the encrypter to use for the encryption level.
- void SetEncrypter(EncryptionLevel level,
- std::unique_ptr<QuicEncrypter> encrypter);
-
- // Returns true if there are control frames or current constructed packet has
- // pending retransmittable frames.
- bool HasRetransmittableFrames() const;
-
- // Returns true if current constructed packet has pending stream frames for
- // stream |id|.
- bool HasPendingStreamFramesOfStream(QuicStreamId id) const;
-
- // Sets the encryption level that will be applied to new packets.
- void set_encryption_level(EncryptionLevel level);
-
- // packet number of the last created packet, or 0 if no packets have been
- // created.
- QuicPacketNumber packet_number() const;
-
- // Returns the maximum length a current packet can actually have.
- QuicByteCount GetCurrentMaxPacketLength() const;
-
- // Set maximum packet length in the creator immediately. May not be called
- // when there are frames queued in the creator.
- void SetMaxPacketLength(QuicByteCount length);
-
- // Set transmission type of next constructed packets.
- void SetTransmissionType(TransmissionType type);
-
- // Sets the retry token to be sent over the wire in IETF Initial packets.
- void SetRetryToken(QuicStringPiece retry_token);
-
- // Allow/Disallow setting transmission type of next constructed packets.
- void SetCanSetTransmissionType(bool can_set_transmission_type);
-
- // Tries to add a message frame containing |message| and returns the status.
- MessageStatus AddMessageFrame(QuicMessageId message_id,
- QuicMemSliceSpan message);
-
- // Called to flush ACK and STOP_WAITING frames, returns false if the flush
- // fails.
- bool FlushAckFrame(const QuicFrames& frames);
-
- // Returns the largest payload that will fit into a single MESSAGE frame.
- QuicPacketLength GetCurrentLargestMessagePayload() const;
- QuicPacketLength GetGuaranteedLargestMessagePayload() const;
-
- // Update the server connection ID used in outgoing packets.
- void SetServerConnectionId(QuicConnectionId server_connection_id);
-
- // Update the client connection ID used in outgoing packets.
- void SetClientConnectionId(QuicConnectionId client_connection_id);
-
- void set_debug_delegate(QuicPacketCreator::DebugDelegate* debug_delegate) {
- packet_creator_.set_debug_delegate(debug_delegate);
- }
-
- void set_fully_pad_crypto_handshake_packets(bool new_value);
-
- bool fully_pad_crypto_handshake_packets() const;
-
- private:
- friend class test::QuicPacketGeneratorPeer;
-
- // Adds a random amount of padding (between 1 to 256 bytes).
- void AddRandomPadding();
-
- // Sends remaining pending padding.
- // Pending paddings should only be sent when there is nothing else to send.
- void SendRemainingPendingPadding();
-
- // Called when there is data to be sent, Retrieves updated ACK frame from
- // delegate_ and flushes it.
- void MaybeBundleAckOpportunistically();
-
- QuicPacketCreator::DelegateInterface* delegate_;
-
- QuicPacketCreator packet_creator_;
-
- // Transmission type of the next serialized packet.
- TransmissionType next_transmission_type_;
-
- // True if packet flusher is currently attached.
- bool flusher_attached_;
-
- QuicRandom* random_generator_;
-
- // Whether crypto handshake packets should be fully padded.
- bool fully_pad_crypto_handshake_packets_;
-
- // Packet number of the first packet of a write operation. This gets set
- // when the out-most flusher attaches and gets cleared when the out-most
- // flusher detaches.
- QuicPacketNumber write_start_packet_number_;
-};
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_CORE_QUIC_PACKET_GENERATOR_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_generator_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_packet_generator_test.cc
deleted file mode 100644
index b098958cb52..00000000000
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_generator_test.cc
+++ /dev/null
@@ -1,1512 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/third_party/quiche/src/quic/core/quic_packet_generator.h"
-
-#include <cstdint>
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
-#include "net/third_party/quiche/src/quic/core/crypto/null_decrypter.h"
-#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
-#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
-#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
-#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
-#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
-#include "net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h"
-#include "net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h"
-#include "net/third_party/quiche/src/quic/test_tools/quic_packet_generator_peer.h"
-#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
-#include "net/third_party/quiche/src/quic/test_tools/simple_data_producer.h"
-#include "net/third_party/quiche/src/quic/test_tools/simple_quic_framer.h"
-
-using testing::_;
-using testing::InSequence;
-using testing::Return;
-using testing::StrictMock;
-
-namespace quic {
-namespace test {
-namespace {
-
-class MockDelegate : public QuicPacketCreator::DelegateInterface {
- public:
- MockDelegate() {}
- MockDelegate(const MockDelegate&) = delete;
- MockDelegate& operator=(const MockDelegate&) = delete;
- ~MockDelegate() override {}
-
- MOCK_METHOD2(ShouldGeneratePacket,
- bool(HasRetransmittableData retransmittable,
- IsHandshake handshake));
- MOCK_METHOD0(MaybeBundleAckOpportunistically, const QuicFrames());
- MOCK_METHOD0(GetPacketBuffer, char*());
- MOCK_METHOD1(OnSerializedPacket, void(SerializedPacket* packet));
- MOCK_METHOD2(OnUnrecoverableError, void(QuicErrorCode, const std::string&));
-
- void SetCanWriteAnything() {
- EXPECT_CALL(*this, ShouldGeneratePacket(_, _)).WillRepeatedly(Return(true));
- EXPECT_CALL(*this, ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, _))
- .WillRepeatedly(Return(true));
- }
-
- void SetCanNotWrite() {
- EXPECT_CALL(*this, ShouldGeneratePacket(_, _))
- .WillRepeatedly(Return(false));
- EXPECT_CALL(*this, ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, _))
- .WillRepeatedly(Return(false));
- }
-
- // Use this when only ack frames should be allowed to be written.
- void SetCanWriteOnlyNonRetransmittable() {
- EXPECT_CALL(*this, ShouldGeneratePacket(_, _))
- .WillRepeatedly(Return(false));
- EXPECT_CALL(*this, ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, _))
- .WillRepeatedly(Return(true));
- }
-};
-
-// Simple struct for describing the contents of a packet.
-// Useful in conjunction with a SimpleQuicFrame for validating that a packet
-// contains the expected frames.
-struct PacketContents {
- PacketContents()
- : num_ack_frames(0),
- num_connection_close_frames(0),
- num_goaway_frames(0),
- num_rst_stream_frames(0),
- num_stop_waiting_frames(0),
- num_stream_frames(0),
- num_crypto_frames(0),
- num_ping_frames(0),
- num_mtu_discovery_frames(0),
- num_padding_frames(0) {}
-
- size_t num_ack_frames;
- size_t num_connection_close_frames;
- size_t num_goaway_frames;
- size_t num_rst_stream_frames;
- size_t num_stop_waiting_frames;
- size_t num_stream_frames;
- size_t num_crypto_frames;
- size_t num_ping_frames;
- size_t num_mtu_discovery_frames;
- size_t num_padding_frames;
-};
-
-} // namespace
-
-class TestPacketGenerator : public QuicPacketGenerator {
- public:
- TestPacketGenerator(QuicConnectionId connection_id,
- QuicFramer* framer,
- QuicRandom* random_generator,
- QuicPacketCreator::DelegateInterface* delegate,
- SimpleDataProducer* producer)
- : QuicPacketGenerator(connection_id, framer, random_generator, delegate),
- ack_frame_(InitAckFrame(1)),
- delegate_(static_cast<MockDelegate*>(delegate)),
- producer_(producer) {}
-
- bool ConsumeRetransmittableControlFrame(const QuicFrame& frame,
- bool bundle_ack) {
- if (!QuicPacketGeneratorPeer::GetPacketCreator(this)->has_ack()) {
- QuicFrames frames;
- if (bundle_ack) {
- frames.push_back(QuicFrame(&ack_frame_));
- }
- if (delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
- NOT_HANDSHAKE)) {
- EXPECT_CALL(*delegate_, MaybeBundleAckOpportunistically())
- .WillOnce(Return(frames));
- }
- }
- return QuicPacketGenerator::ConsumeRetransmittableControlFrame(frame);
- }
-
- QuicConsumedData ConsumeDataFastPath(QuicStreamId id,
- const struct iovec* iov,
- int iov_count,
- size_t total_length,
- QuicStreamOffset offset,
- bool fin) {
- // Save data before data is consumed.
- if (total_length > 0) {
- producer_->SaveStreamData(id, iov, iov_count, 0, total_length);
- }
- return QuicPacketGenerator::ConsumeDataFastPath(id, total_length, offset,
- fin, 0);
- }
-
- QuicConsumedData ConsumeData(QuicStreamId id,
- const struct iovec* iov,
- int iov_count,
- size_t total_length,
- QuicStreamOffset offset,
- StreamSendingState state) {
- // Save data before data is consumed.
- if (total_length > 0) {
- producer_->SaveStreamData(id, iov, iov_count, 0, total_length);
- }
- if (!QuicPacketGeneratorPeer::GetPacketCreator(this)->has_ack() &&
- delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
- NOT_HANDSHAKE)) {
- EXPECT_CALL(*delegate_, MaybeBundleAckOpportunistically()).Times(1);
- }
- return QuicPacketGenerator::ConsumeData(id, total_length, offset, state);
- }
-
- MessageStatus AddMessageFrame(QuicMessageId message_id,
- QuicMemSliceSpan message) {
- if (!QuicPacketGeneratorPeer::GetPacketCreator(this)->has_ack() &&
- delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
- NOT_HANDSHAKE)) {
- EXPECT_CALL(*delegate_, MaybeBundleAckOpportunistically()).Times(1);
- }
- return QuicPacketGenerator::AddMessageFrame(message_id, message);
- }
-
- size_t ConsumeCryptoData(EncryptionLevel level,
- QuicStringPiece data,
- QuicStreamOffset offset) {
- producer_->SaveCryptoData(level, offset, data);
- if (!QuicPacketGeneratorPeer::GetPacketCreator(this)->has_ack() &&
- delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
- NOT_HANDSHAKE)) {
- EXPECT_CALL(*delegate_, MaybeBundleAckOpportunistically()).Times(1);
- }
- return QuicPacketGenerator::ConsumeCryptoData(level, data.length(), offset);
- }
-
- QuicAckFrame ack_frame_;
- MockDelegate* delegate_;
- SimpleDataProducer* producer_;
-};
-
-class QuicPacketGeneratorTest : public QuicTest {
- public:
- QuicPacketGeneratorTest()
- : framer_(AllSupportedVersions(),
- QuicTime::Zero(),
- Perspective::IS_CLIENT,
- kQuicDefaultConnectionIdLength),
- generator_(TestConnectionId(),
- &framer_,
- &random_generator_,
- &delegate_,
- &producer_),
- creator_(QuicPacketGeneratorPeer::GetPacketCreator(&generator_)),
- ack_frame_(InitAckFrame(1)) {
- EXPECT_CALL(delegate_, GetPacketBuffer()).WillRepeatedly(Return(nullptr));
- creator_->SetEncrypter(
- ENCRYPTION_FORWARD_SECURE,
- std::make_unique<NullEncrypter>(Perspective::IS_CLIENT));
- creator_->set_encryption_level(ENCRYPTION_FORWARD_SECURE);
- framer_.set_data_producer(&producer_);
- if (simple_framer_.framer()->version().KnowsWhichDecrypterToUse()) {
- simple_framer_.framer()->InstallDecrypter(
- ENCRYPTION_FORWARD_SECURE,
- std::make_unique<NullDecrypter>(Perspective::IS_SERVER));
- }
- generator_.AttachPacketFlusher();
- }
-
- ~QuicPacketGeneratorTest() override {
- for (SerializedPacket& packet : packets_) {
- delete[] packet.encrypted_buffer;
- ClearSerializedPacket(&packet);
- }
- }
-
- void SavePacket(SerializedPacket* packet) {
- packet->encrypted_buffer = CopyBuffer(*packet);
- packets_.push_back(*packet);
- packet->encrypted_buffer = nullptr;
- packet->retransmittable_frames.clear();
- }
-
- protected:
- QuicRstStreamFrame* CreateRstStreamFrame() {
- return new QuicRstStreamFrame(1, 1, QUIC_STREAM_NO_ERROR, 0);
- }
-
- QuicGoAwayFrame* CreateGoAwayFrame() {
- return new QuicGoAwayFrame(2, QUIC_NO_ERROR, 1, std::string());
- }
-
- void CheckPacketContains(const PacketContents& contents,
- size_t packet_index) {
- ASSERT_GT(packets_.size(), packet_index);
- const SerializedPacket& packet = packets_[packet_index];
- size_t num_retransmittable_frames =
- contents.num_connection_close_frames + contents.num_goaway_frames +
- contents.num_rst_stream_frames + contents.num_stream_frames +
- contents.num_crypto_frames + contents.num_ping_frames;
- size_t num_frames =
- contents.num_ack_frames + contents.num_stop_waiting_frames +
- contents.num_mtu_discovery_frames + contents.num_padding_frames +
- num_retransmittable_frames;
-
- if (num_retransmittable_frames == 0) {
- ASSERT_TRUE(packet.retransmittable_frames.empty());
- } else {
- ASSERT_FALSE(packet.retransmittable_frames.empty());
- EXPECT_EQ(num_retransmittable_frames,
- packet.retransmittable_frames.size());
- }
-
- ASSERT_TRUE(packet.encrypted_buffer != nullptr);
- ASSERT_TRUE(simple_framer_.ProcessPacket(
- QuicEncryptedPacket(packet.encrypted_buffer, packet.encrypted_length)));
- size_t num_padding_frames = 0;
- if (contents.num_padding_frames == 0) {
- num_padding_frames = simple_framer_.padding_frames().size();
- }
- EXPECT_EQ(num_frames + num_padding_frames, simple_framer_.num_frames());
- EXPECT_EQ(contents.num_ack_frames, simple_framer_.ack_frames().size());
- EXPECT_EQ(contents.num_connection_close_frames,
- simple_framer_.connection_close_frames().size());
- EXPECT_EQ(contents.num_goaway_frames,
- simple_framer_.goaway_frames().size());
- EXPECT_EQ(contents.num_rst_stream_frames,
- simple_framer_.rst_stream_frames().size());
- EXPECT_EQ(contents.num_stream_frames,
- simple_framer_.stream_frames().size());
- EXPECT_EQ(contents.num_crypto_frames,
- simple_framer_.crypto_frames().size());
- EXPECT_EQ(contents.num_stop_waiting_frames,
- simple_framer_.stop_waiting_frames().size());
- if (contents.num_padding_frames != 0) {
- EXPECT_EQ(contents.num_padding_frames,
- simple_framer_.padding_frames().size());
- }
-
- // From the receiver's perspective, MTU discovery frames are ping frames.
- EXPECT_EQ(contents.num_ping_frames + contents.num_mtu_discovery_frames,
- simple_framer_.ping_frames().size());
- }
-
- void CheckPacketHasSingleStreamFrame(size_t packet_index) {
- ASSERT_GT(packets_.size(), packet_index);
- const SerializedPacket& packet = packets_[packet_index];
- ASSERT_FALSE(packet.retransmittable_frames.empty());
- EXPECT_EQ(1u, packet.retransmittable_frames.size());
- ASSERT_TRUE(packet.encrypted_buffer != nullptr);
- ASSERT_TRUE(simple_framer_.ProcessPacket(
- QuicEncryptedPacket(packet.encrypted_buffer, packet.encrypted_length)));
- EXPECT_EQ(1u, simple_framer_.num_frames());
- EXPECT_EQ(1u, simple_framer_.stream_frames().size());
- }
-
- void CheckAllPacketsHaveSingleStreamFrame() {
- for (size_t i = 0; i < packets_.size(); i++) {
- CheckPacketHasSingleStreamFrame(i);
- }
- }
-
- void CreateData(size_t len) {
- data_array_.reset(new char[len]);
- memset(data_array_.get(), '?', len);
- iov_.iov_base = data_array_.get();
- iov_.iov_len = len;
- }
-
- QuicFramer framer_;
- MockRandom random_generator_;
- StrictMock<MockDelegate> delegate_;
- TestPacketGenerator generator_;
- QuicPacketCreator* creator_;
- SimpleQuicFramer simple_framer_;
- std::vector<SerializedPacket> packets_;
- QuicAckFrame ack_frame_;
- struct iovec iov_;
- SimpleBufferAllocator allocator_;
-
- private:
- std::unique_ptr<char[]> data_array_;
- SimpleDataProducer producer_;
-};
-
-class MockDebugDelegate : public QuicPacketCreator::DebugDelegate {
- public:
- MOCK_METHOD1(OnFrameAddedToPacket, void(const QuicFrame&));
-};
-
-TEST_F(QuicPacketGeneratorTest, AddControlFrame_NotWritable) {
- delegate_.SetCanNotWrite();
-
- QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
- const bool consumed =
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
- /*bundle_ack=*/false);
- EXPECT_FALSE(consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
- delete rst_frame;
-}
-
-TEST_F(QuicPacketGeneratorTest, AddControlFrame_OnlyAckWritable) {
- delegate_.SetCanWriteOnlyNonRetransmittable();
-
- QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
- const bool consumed =
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
- /*bundle_ack=*/false);
- EXPECT_FALSE(consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
- delete rst_frame;
-}
-
-TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldNotFlush) {
- delegate_.SetCanWriteAnything();
-
- generator_.ConsumeRetransmittableControlFrame(
- QuicFrame(CreateRstStreamFrame()),
- /*bundle_ack=*/false);
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-}
-
-TEST_F(QuicPacketGeneratorTest, AddControlFrame_NotWritableBatchThenFlush) {
- delegate_.SetCanNotWrite();
-
- QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
- const bool consumed =
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
- /*bundle_ack=*/false);
- EXPECT_FALSE(consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
- delete rst_frame;
-}
-
-TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldFlush) {
- delegate_.SetCanWriteAnything();
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
-
- generator_.ConsumeRetransmittableControlFrame(
- QuicFrame(CreateRstStreamFrame()),
- /*bundle_ack=*/false);
- generator_.Flush();
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- PacketContents contents;
- contents.num_rst_stream_frames = 1;
- CheckPacketContains(contents, 0);
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeCryptoData) {
- delegate_.SetCanWriteAnything();
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- std::string data = "crypto data";
- size_t consumed_bytes =
- generator_.ConsumeCryptoData(ENCRYPTION_INITIAL, data, 0);
- generator_.Flush();
- EXPECT_EQ(data.length(), consumed_bytes);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- PacketContents contents;
- contents.num_crypto_frames = 1;
- contents.num_padding_frames = 1;
- CheckPacketContains(contents, 0);
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeData_NotWritable) {
- delegate_.SetCanNotWrite();
-
- MakeIOVector("foo", &iov_);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, FIN);
- EXPECT_EQ(0u, consumed.bytes_consumed);
- EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldNotFlush) {
- delegate_.SetCanWriteAnything();
-
- MakeIOVector("foo", &iov_);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, FIN);
- EXPECT_EQ(3u, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldFlush) {
- delegate_.SetCanWriteAnything();
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- MakeIOVector("foo", &iov_);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, FIN);
- generator_.Flush();
- EXPECT_EQ(3u, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- PacketContents contents;
- contents.num_stream_frames = 1;
- CheckPacketContains(contents, 0);
-}
-
-// Test the behavior of ConsumeData when the data consumed is for the crypto
-// handshake stream. Ensure that the packet is always sent and padded even if
-// the generator operates in batch mode.
-TEST_F(QuicPacketGeneratorTest, ConsumeData_Handshake) {
- delegate_.SetCanWriteAnything();
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- std::string data = "foo bar";
- MakeIOVector(data, &iov_);
- size_t consumed_bytes = 0;
- if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
- consumed_bytes = generator_.ConsumeCryptoData(ENCRYPTION_INITIAL, data, 0);
- } else {
- consumed_bytes =
- generator_
- .ConsumeData(
- QuicUtils::GetCryptoStreamId(framer_.transport_version()),
- &iov_, 1u, iov_.iov_len, 0, NO_FIN)
- .bytes_consumed;
- }
- EXPECT_EQ(7u, consumed_bytes);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- PacketContents contents;
- if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
- contents.num_crypto_frames = 1;
- } else {
- contents.num_stream_frames = 1;
- }
- contents.num_padding_frames = 1;
- CheckPacketContains(contents, 0);
-
- ASSERT_EQ(1u, packets_.size());
- ASSERT_EQ(kDefaultMaxPacketSize, generator_.GetCurrentMaxPacketLength());
- EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length);
-}
-
-// Test the behavior of ConsumeData when the data is for the crypto handshake
-// stream, but padding is disabled.
-TEST_F(QuicPacketGeneratorTest, ConsumeData_Handshake_PaddingDisabled) {
- generator_.set_fully_pad_crypto_handshake_packets(false);
-
- delegate_.SetCanWriteAnything();
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- std::string data = "foo";
- MakeIOVector(data, &iov_);
- size_t bytes_consumed = 0;
- if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
- bytes_consumed = generator_.ConsumeCryptoData(ENCRYPTION_INITIAL, data, 0);
- } else {
- bytes_consumed =
- generator_
- .ConsumeData(
- QuicUtils::GetCryptoStreamId(framer_.transport_version()),
- &iov_, 1u, iov_.iov_len, 0, NO_FIN)
- .bytes_consumed;
- }
- EXPECT_EQ(3u, bytes_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- PacketContents contents;
- if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
- contents.num_crypto_frames = 1;
- } else {
- contents.num_stream_frames = 1;
- }
- contents.num_padding_frames = 0;
- CheckPacketContains(contents, 0);
-
- ASSERT_EQ(1u, packets_.size());
-
- // Packet is not fully padded, but we want to future packets to be larger.
- ASSERT_EQ(kDefaultMaxPacketSize, generator_.GetCurrentMaxPacketLength());
- size_t expected_packet_length = 27;
- if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
- // The framing of CRYPTO frames is slightly different than that of stream
- // frames, so the expected packet length differs slightly.
- expected_packet_length = 28;
- }
- if (framer_.version().HasHeaderProtection()) {
- expected_packet_length = 29;
- }
- EXPECT_EQ(expected_packet_length, packets_[0].encrypted_length);
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeData_EmptyData) {
- delegate_.SetCanWriteAnything();
-
- EXPECT_QUIC_BUG(generator_.ConsumeData(
- QuicUtils::QuicUtils::GetFirstBidirectionalStreamId(
- framer_.transport_version(), Perspective::IS_CLIENT),
- nullptr, 0, 0, 0, NO_FIN),
- "Attempt to consume empty data without FIN.");
-}
-
-TEST_F(QuicPacketGeneratorTest,
- ConsumeDataMultipleTimes_WritableAndShouldNotFlush) {
- delegate_.SetCanWriteAnything();
-
- MakeIOVector("foo", &iov_);
- generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, FIN);
- MakeIOVector("quux", &iov_);
- QuicConsumedData consumed =
- generator_.ConsumeData(3, &iov_, 1u, iov_.iov_len, 3, NO_FIN);
- EXPECT_EQ(4u, consumed.bytes_consumed);
- EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeData_BatchOperations) {
- delegate_.SetCanWriteAnything();
-
- MakeIOVector("foo", &iov_);
- generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, FIN);
- MakeIOVector("quux", &iov_);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 3, NO_FIN);
- EXPECT_EQ(4u, consumed.bytes_consumed);
- EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-
- // Now both frames will be flushed out.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- generator_.Flush();
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- PacketContents contents;
- contents.num_stream_frames = 2;
- CheckPacketContains(contents, 0);
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) {
- // Set the packet size be enough for two stream frames with 0 stream offset,
- // but not enough for a stream frame of 0 offset and one with non-zero offset.
- size_t length =
- NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
- GetPacketHeaderSize(
- framer_.transport_version(),
- creator_->GetDestinationConnectionIdLength(),
- creator_->GetSourceConnectionIdLength(),
- QuicPacketCreatorPeer::SendVersionInPacket(creator_),
- !kIncludeDiversificationNonce,
- QuicPacketCreatorPeer::GetPacketNumberLength(creator_),
- QuicPacketCreatorPeer::GetRetryTokenLengthLength(creator_), 0,
- QuicPacketCreatorPeer::GetLengthLength(creator_)) +
- // Add an extra 3 bytes for the payload and 1 byte so
- // BytesFree is larger than the GetMinStreamFrameSize.
- QuicFramer::GetMinStreamFrameSize(framer_.transport_version(), 1, 0,
- false, 3) +
- 3 +
- QuicFramer::GetMinStreamFrameSize(framer_.transport_version(), 1, 0, true,
- 1) +
- 1;
- generator_.SetMaxPacketLength(length);
- delegate_.SetCanWriteAnything();
- {
- InSequence dummy;
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- // Queue enough data to prevent a stream frame with a non-zero offset from
- // fitting.
- MakeIOVector("foo", &iov_);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, NO_FIN);
- EXPECT_EQ(3u, consumed.bytes_consumed);
- EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-
- // This frame will not fit with the existing frame, causing the queued frame
- // to be serialized, and it will be added to a new open packet.
- MakeIOVector("bar", &iov_);
- consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 3, FIN);
- EXPECT_EQ(3u, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-
- creator_->FlushCurrentPacket();
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- PacketContents contents;
- contents.num_stream_frames = 1;
- CheckPacketContains(contents, 0);
- CheckPacketContains(contents, 1);
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeDataFastPath) {
- delegate_.SetCanWriteAnything();
- generator_.SetCanSetTransmissionType(true);
- generator_.SetTransmissionType(LOSS_RETRANSMISSION);
-
- // Create a 10000 byte IOVector.
- CreateData(10000);
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- QuicConsumedData consumed = generator_.ConsumeDataFastPath(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, true);
- EXPECT_EQ(10000u, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- PacketContents contents;
- contents.num_stream_frames = 1;
- CheckPacketContains(contents, 0);
- EXPECT_FALSE(packets_.empty());
- SerializedPacket packet = packets_.back();
- EXPECT_TRUE(!packet.retransmittable_frames.empty());
- EXPECT_EQ(LOSS_RETRANSMISSION, packet.transmission_type);
- EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
- const QuicStreamFrame& stream_frame =
- packet.retransmittable_frames.front().stream_frame;
- EXPECT_EQ(10000u, stream_frame.data_length + stream_frame.offset);
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeDataLarge) {
- delegate_.SetCanWriteAnything();
-
- // Create a 10000 byte IOVector.
- CreateData(10000);
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, FIN);
- EXPECT_EQ(10000u, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- PacketContents contents;
- contents.num_stream_frames = 1;
- CheckPacketContains(contents, 0);
- EXPECT_FALSE(packets_.empty());
- SerializedPacket packet = packets_.back();
- EXPECT_TRUE(!packet.retransmittable_frames.empty());
- EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
- const QuicStreamFrame& stream_frame =
- packet.retransmittable_frames.front().stream_frame;
- EXPECT_EQ(10000u, stream_frame.data_length + stream_frame.offset);
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeDataLargeSendAckFalse) {
- delegate_.SetCanNotWrite();
-
- QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
- const bool success =
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
- /*bundle_ack=*/true);
- EXPECT_FALSE(success);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- delegate_.SetCanWriteAnything();
-
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
- /*bundle_ack=*/false);
-
- // Create a 10000 byte IOVector.
- CreateData(10000);
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- generator_.ConsumeRetransmittableControlFrame(
- QuicFrame(CreateRstStreamFrame()),
- /*bundle_ack=*/true);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, FIN);
- generator_.Flush();
-
- EXPECT_EQ(10000u, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- EXPECT_FALSE(packets_.empty());
- SerializedPacket packet = packets_.back();
- EXPECT_TRUE(!packet.retransmittable_frames.empty());
- EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
- const QuicStreamFrame& stream_frame =
- packet.retransmittable_frames.front().stream_frame;
- EXPECT_EQ(10000u, stream_frame.data_length + stream_frame.offset);
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeDataLargeSendAckTrue) {
- if (VersionHasIetfInvariantHeader(framer_.transport_version())) {
- return;
- }
- delegate_.SetCanNotWrite();
- delegate_.SetCanWriteAnything();
-
- // Create a 10000 byte IOVector.
- CreateData(10000);
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, FIN);
- generator_.Flush();
-
- EXPECT_EQ(10000u, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- EXPECT_FALSE(packets_.empty());
- SerializedPacket packet = packets_.back();
- EXPECT_TRUE(!packet.retransmittable_frames.empty());
- EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
- const QuicStreamFrame& stream_frame =
- packet.retransmittable_frames.front().stream_frame;
- EXPECT_EQ(10000u, stream_frame.data_length + stream_frame.offset);
-}
-
-TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations) {
- delegate_.SetCanNotWrite();
-
- QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
- const bool consumed =
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
- /*bundle_ack=*/true);
- EXPECT_FALSE(consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
- EXPECT_FALSE(generator_.HasPendingStreamFramesOfStream(3));
-
- delegate_.SetCanWriteAnything();
-
- EXPECT_TRUE(
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
- /*bundle_ack=*/false));
- // Send some data and a control frame
- MakeIOVector("quux", &iov_);
- generator_.ConsumeData(3, &iov_, 1u, iov_.iov_len, 0, NO_FIN);
- if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
- generator_.ConsumeRetransmittableControlFrame(
- QuicFrame(CreateGoAwayFrame()),
- /*bundle_ack=*/false);
- }
- EXPECT_TRUE(generator_.HasPendingStreamFramesOfStream(3));
-
- // All five frames will be flushed out in a single packet.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- generator_.Flush();
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
- EXPECT_FALSE(generator_.HasPendingStreamFramesOfStream(3));
-
- PacketContents contents;
- // ACK will be flushed by connection.
- contents.num_ack_frames = 0;
- if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
- contents.num_goaway_frames = 1;
- } else {
- contents.num_goaway_frames = 0;
- }
- contents.num_rst_stream_frames = 1;
- contents.num_stream_frames = 1;
- CheckPacketContains(contents, 0);
-}
-
-TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) {
- delegate_.SetCanNotWrite();
-
- QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
- const bool success =
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
- /*bundle_ack=*/true);
- EXPECT_FALSE(success);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- delegate_.SetCanWriteAnything();
-
- {
- InSequence dummy;
- // All five frames will be flushed out in a single packet
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- EXPECT_TRUE(
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
- /*bundle_ack=*/false));
- // Send enough data to exceed one packet
- size_t data_len = kDefaultMaxPacketSize + 100;
- CreateData(data_len);
- QuicConsumedData consumed =
- generator_.ConsumeData(3, &iov_, 1u, iov_.iov_len, 0, FIN);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
- generator_.ConsumeRetransmittableControlFrame(
- QuicFrame(CreateGoAwayFrame()),
- /*bundle_ack=*/false);
- }
-
- generator_.Flush();
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- // The first packet should have the queued data and part of the stream data.
- PacketContents contents;
- // ACK will be sent by connection.
- contents.num_ack_frames = 0;
- contents.num_rst_stream_frames = 1;
- contents.num_stream_frames = 1;
- CheckPacketContains(contents, 0);
-
- // The second should have the remainder of the stream data.
- PacketContents contents2;
- if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
- contents2.num_goaway_frames = 1;
- } else {
- contents2.num_goaway_frames = 0;
- }
- contents2.num_stream_frames = 1;
- CheckPacketContains(contents2, 1);
-}
-
-// Regression test of b/120493795.
-TEST_F(QuicPacketGeneratorTest, PacketTransmissionType) {
- delegate_.SetCanWriteAnything();
- generator_.SetCanSetTransmissionType(true);
-
- // The first ConsumeData will fill the packet without flush.
- generator_.SetTransmissionType(LOSS_RETRANSMISSION);
-
- size_t data_len = 1324;
- CreateData(data_len);
- QuicStreamId stream1_id = QuicUtils::GetFirstBidirectionalStreamId(
- framer_.transport_version(), Perspective::IS_CLIENT);
- QuicConsumedData consumed =
- generator_.ConsumeData(stream1_id, &iov_, 1u, iov_.iov_len, 0, NO_FIN);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- ASSERT_EQ(0u, creator_->BytesFree())
- << "Test setup failed: Please increase data_len to "
- << data_len + creator_->BytesFree() << " bytes.";
-
- // The second ConsumeData can not be added to the packet and will flush.
- generator_.SetTransmissionType(NOT_RETRANSMISSION);
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
-
- QuicStreamId stream2_id = stream1_id + 4;
-
- consumed =
- generator_.ConsumeData(stream2_id, &iov_, 1u, iov_.iov_len, 0, NO_FIN);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
-
- // Ensure the packet is successfully created.
- ASSERT_EQ(1u, packets_.size());
- ASSERT_TRUE(packets_[0].encrypted_buffer);
- ASSERT_EQ(1u, packets_[0].retransmittable_frames.size());
- EXPECT_EQ(stream1_id,
- packets_[0].retransmittable_frames[0].stream_frame.stream_id);
-
- // Since the second frame was not added, the packet's transmission type
- // should be the first frame's type.
- EXPECT_EQ(packets_[0].transmission_type, LOSS_RETRANSMISSION);
-}
-
-TEST_F(QuicPacketGeneratorTest, TestConnectionIdLength) {
- QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
- generator_.SetServerConnectionIdLength(0);
- EXPECT_EQ(PACKET_0BYTE_CONNECTION_ID,
- creator_->GetDestinationConnectionIdLength());
-
- for (size_t i = 1; i < 10; i++) {
- generator_.SetServerConnectionIdLength(i);
- if (VersionHasIetfInvariantHeader(framer_.transport_version())) {
- EXPECT_EQ(PACKET_0BYTE_CONNECTION_ID,
- creator_->GetDestinationConnectionIdLength());
- } else {
- EXPECT_EQ(PACKET_8BYTE_CONNECTION_ID,
- creator_->GetDestinationConnectionIdLength());
- }
- }
-}
-
-// Test whether SetMaxPacketLength() works in the situation when the queue is
-// empty, and we send three packets worth of data.
-TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_Initial) {
- delegate_.SetCanWriteAnything();
-
- // Send enough data for three packets.
- size_t data_len = 3 * kDefaultMaxPacketSize + 1;
- size_t packet_len = kDefaultMaxPacketSize + 100;
- ASSERT_LE(packet_len, kMaxOutgoingPacketSize);
- generator_.SetMaxPacketLength(packet_len);
- EXPECT_EQ(packet_len, generator_.GetCurrentMaxPacketLength());
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .Times(3)
- .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- CreateData(data_len);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len,
- /*offset=*/0, FIN);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- // We expect three packets, and first two of them have to be of packet_len
- // size. We check multiple packets (instead of just one) because we want to
- // ensure that |max_packet_length_| does not get changed incorrectly by the
- // generator after first packet is serialized.
- ASSERT_EQ(3u, packets_.size());
- EXPECT_EQ(packet_len, packets_[0].encrypted_length);
- EXPECT_EQ(packet_len, packets_[1].encrypted_length);
- CheckAllPacketsHaveSingleStreamFrame();
-}
-
-// Test whether SetMaxPacketLength() works in the situation when we first write
-// data, then change packet size, then write data again.
-TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_Middle) {
- delegate_.SetCanWriteAnything();
-
- // We send enough data to overflow default packet length, but not the altered
- // one.
- size_t data_len = kDefaultMaxPacketSize;
- size_t packet_len = kDefaultMaxPacketSize + 100;
- ASSERT_LE(packet_len, kMaxOutgoingPacketSize);
-
- // We expect to see three packets in total.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .Times(3)
- .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
-
- // Send two packets before packet size change.
- CreateData(data_len);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len,
- /*offset=*/0, NO_FIN);
- generator_.Flush();
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- // Make sure we already have two packets.
- ASSERT_EQ(2u, packets_.size());
-
- // Increase packet size.
- generator_.SetMaxPacketLength(packet_len);
- EXPECT_EQ(packet_len, generator_.GetCurrentMaxPacketLength());
-
- // Send a packet after packet size change.
- CreateData(data_len);
- generator_.AttachPacketFlusher();
- consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, data_len, FIN);
- generator_.Flush();
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- // We expect first data chunk to get fragmented, but the second one to fit
- // into a single packet.
- ASSERT_EQ(3u, packets_.size());
- EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length);
- EXPECT_LE(kDefaultMaxPacketSize, packets_[2].encrypted_length);
- CheckAllPacketsHaveSingleStreamFrame();
-}
-
-// Test whether SetMaxPacketLength() works correctly when we force the change of
-// the packet size in the middle of the batched packet.
-TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_MidpacketFlush) {
- delegate_.SetCanWriteAnything();
-
- size_t first_write_len = kDefaultMaxPacketSize / 2;
- size_t packet_len = kDefaultMaxPacketSize + 100;
- size_t second_write_len = packet_len + 1;
- ASSERT_LE(packet_len, kMaxOutgoingPacketSize);
-
- // First send half of the packet worth of data. We are in the batch mode, so
- // should not cause packet serialization.
- CreateData(first_write_len);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len,
- /*offset=*/0, NO_FIN);
- EXPECT_EQ(first_write_len, consumed.bytes_consumed);
- EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-
- // Make sure we have no packets so far.
- ASSERT_EQ(0u, packets_.size());
-
- // Expect a packet to be flushed.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
-
- // Increase packet size after flushing all frames.
- // Ensure it's immediately enacted.
- generator_.FlushAllQueuedFrames();
- generator_.SetMaxPacketLength(packet_len);
- EXPECT_EQ(packet_len, generator_.GetCurrentMaxPacketLength());
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- // We expect to see exactly one packet serialized after that, because we send
- // a value somewhat exceeding new max packet size, and the tail data does not
- // get serialized because we are still in the batch mode.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
-
- // Send a more than a packet worth of data to the same stream. This should
- // trigger serialization of one packet, and queue another one.
- CreateData(second_write_len);
- consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len,
- /*offset=*/first_write_len, FIN);
- EXPECT_EQ(second_write_len, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-
- // We expect the first packet to be underfilled, and the second packet be up
- // to the new max packet size.
- ASSERT_EQ(2u, packets_.size());
- EXPECT_GT(kDefaultMaxPacketSize, packets_[0].encrypted_length);
- EXPECT_EQ(packet_len, packets_[1].encrypted_length);
-
- CheckAllPacketsHaveSingleStreamFrame();
-}
-
-// Test sending a connectivity probing packet.
-TEST_F(QuicPacketGeneratorTest, GenerateConnectivityProbingPacket) {
- delegate_.SetCanWriteAnything();
-
- OwningSerializedPacketPointer probing_packet;
- if (VersionHasIetfQuicFrames(framer_.transport_version())) {
- QuicPathFrameBuffer payload = {
- {0xde, 0xad, 0xbe, 0xef, 0xba, 0xdc, 0x0f, 0xfe}};
- probing_packet =
- generator_.SerializePathChallengeConnectivityProbingPacket(&payload);
- } else {
- probing_packet = generator_.SerializeConnectivityProbingPacket();
- }
-
- ASSERT_TRUE(simple_framer_.ProcessPacket(QuicEncryptedPacket(
- probing_packet->encrypted_buffer, probing_packet->encrypted_length)));
-
- EXPECT_EQ(2u, simple_framer_.num_frames());
- if (VersionHasIetfQuicFrames(framer_.transport_version())) {
- EXPECT_EQ(1u, simple_framer_.path_challenge_frames().size());
- } else {
- EXPECT_EQ(1u, simple_framer_.ping_frames().size());
- }
- EXPECT_EQ(1u, simple_framer_.padding_frames().size());
-}
-
-// Test sending an MTU probe, without any surrounding data.
-TEST_F(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_Simple) {
- delegate_.SetCanWriteAnything();
-
- const size_t target_mtu = kDefaultMaxPacketSize + 100;
- static_assert(target_mtu < kMaxOutgoingPacketSize,
- "The MTU probe used by the test exceeds maximum packet size");
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
-
- generator_.GenerateMtuDiscoveryPacket(target_mtu);
-
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
- ASSERT_EQ(1u, packets_.size());
- EXPECT_EQ(target_mtu, packets_[0].encrypted_length);
-
- PacketContents contents;
- contents.num_mtu_discovery_frames = 1;
- contents.num_padding_frames = 1;
- CheckPacketContains(contents, 0);
-}
-
-// Test sending an MTU probe. Surround it with data, to ensure that it resets
-// the MTU to the value before the probe was sent.
-TEST_F(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_SurroundedByData) {
- delegate_.SetCanWriteAnything();
-
- const size_t target_mtu = kDefaultMaxPacketSize + 100;
- static_assert(target_mtu < kMaxOutgoingPacketSize,
- "The MTU probe used by the test exceeds maximum packet size");
-
- // Send enough data so it would always cause two packets to be sent.
- const size_t data_len = target_mtu + 1;
-
- // Send a total of five packets: two packets before the probe, the probe
- // itself, and two packets after the probe.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .Times(5)
- .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
-
- // Send data before the MTU probe.
- CreateData(data_len);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len,
- /*offset=*/0, NO_FIN);
- generator_.Flush();
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- // Send the MTU probe.
- generator_.GenerateMtuDiscoveryPacket(target_mtu);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- // Send data after the MTU probe.
- CreateData(data_len);
- generator_.AttachPacketFlusher();
- consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len,
- /*offset=*/data_len, FIN);
- generator_.Flush();
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- ASSERT_EQ(5u, packets_.size());
- EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length);
- EXPECT_EQ(target_mtu, packets_[2].encrypted_length);
- EXPECT_EQ(kDefaultMaxPacketSize, packets_[3].encrypted_length);
-
- PacketContents probe_contents;
- probe_contents.num_mtu_discovery_frames = 1;
- probe_contents.num_padding_frames = 1;
-
- CheckPacketHasSingleStreamFrame(0);
- CheckPacketHasSingleStreamFrame(1);
- CheckPacketContains(probe_contents, 2);
- CheckPacketHasSingleStreamFrame(3);
- CheckPacketHasSingleStreamFrame(4);
-}
-
-TEST_F(QuicPacketGeneratorTest, DontCrashOnInvalidStopWaiting) {
- if (VersionSupportsMessageFrames(framer_.transport_version())) {
- return;
- }
- // Test added to ensure the generator does not crash when an invalid frame is
- // added. Because this is an indication of internal programming errors,
- // DFATALs are expected.
- // A 1 byte packet number length can't encode a gap of 1000.
- QuicPacketCreatorPeer::SetPacketNumber(creator_, 1000);
-
- delegate_.SetCanNotWrite();
- delegate_.SetCanWriteAnything();
-
- // This will not serialize any packets, because of the invalid frame.
- EXPECT_CALL(delegate_,
- OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET, _));
- EXPECT_QUIC_BUG(generator_.Flush(),
- "packet_number_length 1 is too small "
- "for least_unacked_delta: 1001");
-}
-
-// Regression test for b/31486443.
-TEST_F(QuicPacketGeneratorTest, ConnectionCloseFrameLargerThanPacketSize) {
- delegate_.SetCanWriteAnything();
- char buf[2000] = {};
- QuicStringPiece error_details(buf, 2000);
- const QuicErrorCode kQuicErrorCode = QUIC_PACKET_WRITE_ERROR;
-
- QuicConnectionCloseFrame* frame = new QuicConnectionCloseFrame(
- framer_.transport_version(), kQuicErrorCode, std::string(error_details),
- /*transport_close_frame_type=*/0);
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(frame),
- /*bundle_ack=*/false);
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-}
-
-TEST_F(QuicPacketGeneratorTest, RandomPaddingAfterFinSingleStreamSinglePacket) {
- const QuicByteCount kStreamFramePayloadSize = 100u;
- char buf[kStreamFramePayloadSize] = {};
- const QuicStreamId kDataStreamId = 5;
- // Set the packet size be enough for one stream frame with 0 stream offset and
- // max size of random padding.
- size_t length =
- NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
- GetPacketHeaderSize(
- framer_.transport_version(),
- creator_->GetDestinationConnectionIdLength(),
- creator_->GetSourceConnectionIdLength(),
- QuicPacketCreatorPeer::SendVersionInPacket(creator_),
- !kIncludeDiversificationNonce,
- QuicPacketCreatorPeer::GetPacketNumberLength(creator_),
- QuicPacketCreatorPeer::GetRetryTokenLengthLength(creator_), 0,
- QuicPacketCreatorPeer::GetLengthLength(creator_)) +
- QuicFramer::GetMinStreamFrameSize(
- framer_.transport_version(), kDataStreamId, 0,
- /*last_frame_in_packet=*/false,
- kStreamFramePayloadSize + kMaxNumRandomPaddingBytes) +
- kStreamFramePayloadSize + kMaxNumRandomPaddingBytes;
- generator_.SetMaxPacketLength(length);
- delegate_.SetCanWriteAnything();
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
- QuicConsumedData consumed = generator_.ConsumeData(
- kDataStreamId, &iov_, 1u, iov_.iov_len, 0, FIN_AND_PADDING);
- generator_.Flush();
- EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- EXPECT_EQ(1u, packets_.size());
- PacketContents contents;
- // The packet has both stream and padding frames.
- contents.num_padding_frames = 1;
- contents.num_stream_frames = 1;
- CheckPacketContains(contents, 0);
-}
-
-TEST_F(QuicPacketGeneratorTest,
- RandomPaddingAfterFinSingleStreamMultiplePackets) {
- const QuicByteCount kStreamFramePayloadSize = 100u;
- char buf[kStreamFramePayloadSize] = {};
- const QuicStreamId kDataStreamId = 5;
- // Set the packet size be enough for one stream frame with 0 stream offset +
- // 1. One or more packets will accommodate.
- size_t length =
- NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
- GetPacketHeaderSize(
- framer_.transport_version(),
- creator_->GetDestinationConnectionIdLength(),
- creator_->GetSourceConnectionIdLength(),
- QuicPacketCreatorPeer::SendVersionInPacket(creator_),
- !kIncludeDiversificationNonce,
- QuicPacketCreatorPeer::GetPacketNumberLength(creator_),
- QuicPacketCreatorPeer::GetRetryTokenLengthLength(creator_), 0,
- QuicPacketCreatorPeer::GetLengthLength(creator_)) +
- QuicFramer::GetMinStreamFrameSize(
- framer_.transport_version(), kDataStreamId, 0,
- /*last_frame_in_packet=*/false, kStreamFramePayloadSize + 1) +
- kStreamFramePayloadSize + 1;
- generator_.SetMaxPacketLength(length);
- delegate_.SetCanWriteAnything();
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
- QuicConsumedData consumed = generator_.ConsumeData(
- kDataStreamId, &iov_, 1u, iov_.iov_len, 0, FIN_AND_PADDING);
- generator_.Flush();
- EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- EXPECT_LE(1u, packets_.size());
- PacketContents contents;
- // The first packet has both stream and padding frames.
- contents.num_stream_frames = 1;
- contents.num_padding_frames = 1;
- CheckPacketContains(contents, 0);
-
- for (size_t i = 1; i < packets_.size(); ++i) {
- // Following packets only have paddings.
- contents.num_stream_frames = 0;
- contents.num_padding_frames = 1;
- CheckPacketContains(contents, i);
- }
-}
-
-TEST_F(QuicPacketGeneratorTest,
- RandomPaddingAfterFinMultipleStreamsMultiplePackets) {
- const QuicByteCount kStreamFramePayloadSize = 100u;
- char buf[kStreamFramePayloadSize] = {};
- const QuicStreamId kDataStreamId1 = 5;
- const QuicStreamId kDataStreamId2 = 6;
- // Set the packet size be enough for first frame with 0 stream offset + second
- // frame + 1 byte payload. two or more packets will accommodate.
- size_t length =
- NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
- GetPacketHeaderSize(
- framer_.transport_version(),
- creator_->GetDestinationConnectionIdLength(),
- creator_->GetSourceConnectionIdLength(),
- QuicPacketCreatorPeer::SendVersionInPacket(creator_),
- !kIncludeDiversificationNonce,
- QuicPacketCreatorPeer::GetPacketNumberLength(creator_),
- QuicPacketCreatorPeer::GetRetryTokenLengthLength(creator_), 0,
- QuicPacketCreatorPeer::GetLengthLength(creator_)) +
- QuicFramer::GetMinStreamFrameSize(
- framer_.transport_version(), kDataStreamId1, 0,
- /*last_frame_in_packet=*/false, kStreamFramePayloadSize) +
- kStreamFramePayloadSize +
- QuicFramer::GetMinStreamFrameSize(framer_.transport_version(),
- kDataStreamId1, 0,
- /*last_frame_in_packet=*/false, 1) +
- 1;
- generator_.SetMaxPacketLength(length);
- delegate_.SetCanWriteAnything();
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
- QuicConsumedData consumed = generator_.ConsumeData(
- kDataStreamId1, &iov_, 1u, iov_.iov_len, 0, FIN_AND_PADDING);
- EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
- MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
- consumed = generator_.ConsumeData(kDataStreamId2, &iov_, 1u, iov_.iov_len, 0,
- FIN_AND_PADDING);
- EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
- generator_.Flush();
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- EXPECT_LE(2u, packets_.size());
- PacketContents contents;
- // The first packet has two stream frames.
- contents.num_stream_frames = 2;
- CheckPacketContains(contents, 0);
-
- // The second packet has one stream frame and padding frames.
- contents.num_stream_frames = 1;
- contents.num_padding_frames = 1;
- CheckPacketContains(contents, 1);
-
- for (size_t i = 2; i < packets_.size(); ++i) {
- // Following packets only have paddings.
- contents.num_stream_frames = 0;
- contents.num_padding_frames = 1;
- CheckPacketContains(contents, i);
- }
-}
-
-TEST_F(QuicPacketGeneratorTest, AddMessageFrame) {
- if (!VersionSupportsMessageFrames(framer_.transport_version())) {
- return;
- }
- quic::QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
- delegate_.SetCanWriteAnything();
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
-
- MakeIOVector("foo", &iov_);
- generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, FIN);
- EXPECT_EQ(MESSAGE_STATUS_SUCCESS,
- generator_.AddMessageFrame(
- 1, MakeSpan(&allocator_, "message", &storage)));
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-
- // Add a message which causes the flush of current packet.
- EXPECT_EQ(
- MESSAGE_STATUS_SUCCESS,
- generator_.AddMessageFrame(
- 2, MakeSpan(
- &allocator_,
- std::string(generator_.GetCurrentLargestMessagePayload(), 'a'),
- &storage)));
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-
- // Failed to send messages which cannot fit into one packet.
- EXPECT_EQ(
- MESSAGE_STATUS_TOO_LARGE,
- generator_.AddMessageFrame(
- 3,
- MakeSpan(&allocator_,
- std::string(
- generator_.GetCurrentLargestMessagePayload() + 10, 'a'),
- &storage)));
-}
-
-TEST_F(QuicPacketGeneratorTest, ConnectionId) {
- generator_.SetServerConnectionId(TestConnectionId(0x1337));
- EXPECT_EQ(TestConnectionId(0x1337), creator_->GetDestinationConnectionId());
- EXPECT_EQ(EmptyQuicConnectionId(), creator_->GetSourceConnectionId());
- if (!framer_.version().SupportsClientConnectionIds()) {
- return;
- }
- generator_.SetClientConnectionId(TestConnectionId(0x33));
- EXPECT_EQ(TestConnectionId(0x1337), creator_->GetDestinationConnectionId());
- EXPECT_EQ(TestConnectionId(0x33), creator_->GetSourceConnectionId());
-}
-
-} // namespace test
-} // namespace quic
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 b3009ce5c7a..6e6804b2a29 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
@@ -8,15 +8,6 @@
namespace quic {
-QuicPacketNumber::QuicPacketNumber()
- : packet_number_(UninitializedPacketNumber()) {}
-
-QuicPacketNumber::QuicPacketNumber(uint64_t packet_number)
- : packet_number_(packet_number) {
- DCHECK_NE(UninitializedPacketNumber(), packet_number)
- << "Use default constructor for uninitialized packet number";
-}
-
void QuicPacketNumber::Clear() {
packet_number_ = UninitializedPacketNumber();
}
@@ -111,9 +102,4 @@ std::ostream& operator<<(std::ostream& os, const QuicPacketNumber& p) {
return os;
}
-// static
-uint64_t QuicPacketNumber::UninitializedPacketNumber() {
- return std::numeric_limits<uint64_t>::max();
-}
-
} // namespace quic
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 0cf7f15d9f7..18e78bbf1bb 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
@@ -21,10 +21,20 @@ namespace quic {
class QUIC_EXPORT_PRIVATE QuicPacketNumber {
public:
// Construct an uninitialized packet number.
- QuicPacketNumber();
+ constexpr QuicPacketNumber() : packet_number_(UninitializedPacketNumber()) {}
+
// Construct a packet number from uint64_t. |packet_number| cannot equal the
// sentinel value.
- explicit QuicPacketNumber(uint64_t packet_number);
+ explicit constexpr QuicPacketNumber(uint64_t packet_number)
+ : packet_number_(packet_number) {
+ DCHECK_NE(UninitializedPacketNumber(), packet_number)
+ << "Use default constructor for uninitialized packet number";
+ }
+
+ // The sentinel value representing an uninitialized packet number.
+ static constexpr uint64_t UninitializedPacketNumber() {
+ return std::numeric_limits<uint64_t>::max();
+ }
// Packet number becomes uninitialized after calling this function.
void Clear();
@@ -79,13 +89,10 @@ class QUIC_EXPORT_PRIVATE QuicPacketNumber {
// REQUIRES: lhs >= rhs.
friend inline uint64_t operator-(QuicPacketNumber lhs, QuicPacketNumber rhs);
- // The sentinel value representing an uninitialized packet number.
- static uint64_t UninitializedPacketNumber();
-
uint64_t packet_number_;
};
-class QuicPacketNumberHash {
+class QUIC_EXPORT_PRIVATE QuicPacketNumberHash {
public:
uint64_t operator()(QuicPacketNumber packet_number) const noexcept {
return packet_number.Hash();
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.h b/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.h
index 1826ef3573b..1e644aaa07a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.h
@@ -25,7 +25,7 @@ namespace quic {
const int kNumPacketsPerReadMmsgCall = 16;
#endif
-class QuicPacketReader {
+class QUIC_EXPORT_PRIVATE QuicPacketReader {
public:
QuicPacketReader();
QuicPacketReader(const QuicPacketReader&) = delete;
@@ -70,7 +70,7 @@ class QuicPacketReader {
// from exceeding maximum allowed frame size.
// packets_ and mmsg_hdr_ are used to supply cbuf and buf to the recvmmsg
// call.
- struct PacketData {
+ struct QUIC_EXPORT_PRIVATE PacketData {
iovec iov;
// raw_address is used for address information provided by the recvmmsg
// call on the packets.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_writer_wrapper.h b/chromium/net/third_party/quiche/src/quic/core/quic_packet_writer_wrapper.h
index cc3dbc29543..0b331aec6f8 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_writer_wrapper.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packet_writer_wrapper.h
@@ -15,7 +15,7 @@ namespace quic {
// Wraps a writer object to allow dynamically extending functionality. Use
// cases: replace writer while dispatcher and connections hold on to the
// wrapper; mix in monitoring; mix in mocks in unit tests.
-class QuicPacketWriterWrapper : public QuicPacketWriter {
+class QUIC_NO_EXPORT QuicPacketWriterWrapper : public QuicPacketWriter {
public:
QuicPacketWriterWrapper();
QuicPacketWriterWrapper(const QuicPacketWriterWrapper&) = delete;
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 dfe80cf9d00..87b310e3a26 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
@@ -456,7 +456,8 @@ SerializedPacket::SerializedPacket(QuicPacketNumber packet_number,
encryption_level(ENCRYPTION_INITIAL),
has_ack(has_ack),
has_stop_waiting(has_stop_waiting),
- transmission_type(NOT_RETRANSMISSION) {}
+ transmission_type(NOT_RETRANSMISSION),
+ has_ack_frame_copy(false) {}
SerializedPacket::SerializedPacket(const SerializedPacket& other) = default;
@@ -474,17 +475,46 @@ SerializedPacket::SerializedPacket(SerializedPacket&& other)
has_ack(other.has_ack),
has_stop_waiting(other.has_stop_waiting),
transmission_type(other.transmission_type),
- original_packet_number(other.original_packet_number),
- largest_acked(other.largest_acked) {
+ largest_acked(other.largest_acked),
+ has_ack_frame_copy(other.has_ack_frame_copy) {
retransmittable_frames.swap(other.retransmittable_frames);
+ nonretransmittable_frames.swap(other.nonretransmittable_frames);
}
SerializedPacket::~SerializedPacket() {}
+SerializedPacket* CopySerializedPacket(const SerializedPacket& serialized,
+ QuicBufferAllocator* allocator,
+ bool copy_buffer) {
+ SerializedPacket* copy = new SerializedPacket(serialized);
+ if (copy_buffer) {
+ copy->encrypted_buffer = CopyBuffer(serialized);
+ }
+ // Copy underlying frames.
+ copy->retransmittable_frames =
+ CopyQuicFrames(allocator, serialized.retransmittable_frames);
+ copy->nonretransmittable_frames.clear();
+ for (const auto& frame : serialized.nonretransmittable_frames) {
+ if (frame.type == ACK_FRAME) {
+ copy->has_ack_frame_copy = true;
+ }
+ copy->nonretransmittable_frames.push_back(CopyQuicFrame(allocator, frame));
+ }
+ return copy;
+}
+
void ClearSerializedPacket(SerializedPacket* serialized_packet) {
if (!serialized_packet->retransmittable_frames.empty()) {
DeleteFrames(&serialized_packet->retransmittable_frames);
}
+ for (auto& frame : serialized_packet->nonretransmittable_frames) {
+ if (!serialized_packet->has_ack_frame_copy && frame.type == ACK_FRAME) {
+ // Do not delete ack frame if the packet does not own a copy of it.
+ continue;
+ }
+ DeleteFrame(&frame);
+ }
+ serialized_packet->nonretransmittable_frames.clear();
serialized_packet->encrypted_buffer = nullptr;
serialized_packet->encrypted_length = 0;
serialized_packet->largest_acked.Clear();
@@ -496,6 +526,13 @@ char* CopyBuffer(const SerializedPacket& packet) {
return dst_buffer;
}
+char* CopyBuffer(const char* encrypted_buffer,
+ QuicPacketLength encrypted_length) {
+ char* dst_buffer = new char[encrypted_length];
+ memcpy(dst_buffer, encrypted_buffer, encrypted_length);
+ return dst_buffer;
+}
+
ReceivedPacketInfo::ReceivedPacketInfo(const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
const QuicReceivedPacket& packet)
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 82647c6e91e..93417ac1d48 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
@@ -370,6 +370,7 @@ struct QUIC_EXPORT_PRIVATE SerializedPacket {
const char* encrypted_buffer;
QuicPacketLength encrypted_length;
QuicFrames retransmittable_frames;
+ QuicFrames nonretransmittable_frames;
IsHandshake has_crypto_handshake;
// -1: full padding to the end of a max-sized packet
// 0: no padding
@@ -378,15 +379,25 @@ struct QUIC_EXPORT_PRIVATE SerializedPacket {
QuicPacketNumber packet_number;
QuicPacketNumberLength packet_number_length;
EncryptionLevel encryption_level;
+ // TODO(fayang): Remove has_ack and has_stop_waiting.
bool has_ack;
bool has_stop_waiting;
TransmissionType transmission_type;
- QuicPacketNumber original_packet_number;
// The largest acked of the AckFrame in this packet if has_ack is true,
// 0 otherwise.
QuicPacketNumber largest_acked;
+ // Indicates whether this packet has a copy of ack frame in
+ // nonretransmittable_frames.
+ bool has_ack_frame_copy;
};
+// Make a copy of |serialized| (including the underlying frames). |copy_buffer|
+// indicates whether the encrypted buffer should be copied.
+QUIC_EXPORT_PRIVATE SerializedPacket* CopySerializedPacket(
+ const SerializedPacket& serialized,
+ QuicBufferAllocator* allocator,
+ bool copy_buffer);
+
// Deletes and clears all the frames and the packet from serialized packet.
QUIC_EXPORT_PRIVATE void ClearSerializedPacket(
SerializedPacket* serialized_packet);
@@ -394,6 +405,10 @@ QUIC_EXPORT_PRIVATE void ClearSerializedPacket(
// Allocates a new char[] of size |packet.encrypted_length| and copies in
// |packet.encrypted_buffer|.
QUIC_EXPORT_PRIVATE char* CopyBuffer(const SerializedPacket& packet);
+// Allocates a new char[] of size |encrypted_length| and copies in
+// |encrypted_buffer|.
+QUIC_EXPORT_PRIVATE char* CopyBuffer(const char* encrypted_buffer,
+ QuicPacketLength encrypted_length);
struct QUIC_EXPORT_PRIVATE SerializedPacketDeleter {
void operator()(SerializedPacket* packet) {
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 7ee77979a0c..e080cd8265a 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,6 +4,7 @@
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
@@ -70,6 +71,46 @@ TEST_F(QuicPacketsTest, GetClientConnectionIdAsSender) {
GetClientConnectionIdAsSender(header, Perspective::IS_CLIENT));
}
+TEST_F(QuicPacketsTest, CopySerializedPacket) {
+ std::string buffer(1000, 'a');
+ SimpleBufferAllocator allocator;
+ SerializedPacket packet(QuicPacketNumber(1), PACKET_1BYTE_PACKET_NUMBER,
+ buffer.data(), buffer.length(), /*has_ack=*/false,
+ /*has_stop_waiting=*/false);
+ packet.retransmittable_frames.push_back(
+ QuicFrame(new QuicWindowUpdateFrame()));
+ packet.retransmittable_frames.push_back(QuicFrame(QuicStreamFrame()));
+
+ QuicAckFrame ack_frame(InitAckFrame(1));
+ packet.nonretransmittable_frames.push_back(QuicFrame(&ack_frame));
+ packet.nonretransmittable_frames.push_back(QuicFrame(QuicPaddingFrame(-1)));
+
+ std::unique_ptr<SerializedPacket> copy = QuicWrapUnique<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);
+ ASSERT_EQ(2u, copy->retransmittable_frames.size());
+ EXPECT_EQ(WINDOW_UPDATE_FRAME, copy->retransmittable_frames[0].type);
+ EXPECT_EQ(STREAM_FRAME, copy->retransmittable_frames[1].type);
+
+ ASSERT_EQ(2u, copy->nonretransmittable_frames.size());
+ EXPECT_EQ(ACK_FRAME, copy->nonretransmittable_frames[0].type);
+ EXPECT_EQ(PADDING_FRAME, copy->nonretransmittable_frames[1].type);
+ EXPECT_EQ(1000u, copy->encrypted_length);
+ test::CompareCharArraysWithHexError(
+ "encrypted_buffer", copy->encrypted_buffer, copy->encrypted_length,
+ packet.encrypted_buffer, packet.encrypted_length);
+
+ std::unique_ptr<SerializedPacket> copy2 = QuicWrapUnique<SerializedPacket>(
+ CopySerializedPacket(packet, &allocator, /*copy_buffer=*/false));
+ EXPECT_EQ(packet.encrypted_buffer, copy2->encrypted_buffer);
+ EXPECT_EQ(1000u, copy2->encrypted_length);
+ ClearSerializedPacket(&packet);
+ delete[] copy->encrypted_buffer;
+ ClearSerializedPacket(copy.get());
+ ClearSerializedPacket(copy2.get());
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_pending_retransmission.h b/chromium/net/third_party/quiche/src/quic/core/quic_pending_retransmission.h
deleted file mode 100644
index d1e9657a093..00000000000
--- a/chromium/net/third_party/quiche/src/quic/core/quic_pending_retransmission.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_QUIC_CORE_QUIC_PENDING_RETRANSMISSION_H_
-#define QUICHE_QUIC_CORE_QUIC_PENDING_RETRANSMISSION_H_
-
-#include "net/third_party/quiche/src/quic/core/frames/quic_frame.h"
-#include "net/third_party/quiche/src/quic/core/quic_transmission_info.h"
-#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-
-namespace quic {
-
-// Struct to store the pending retransmission information.
-struct QUIC_EXPORT_PRIVATE QuicPendingRetransmission {
- QuicPendingRetransmission(QuicPacketNumber packet_number,
- TransmissionType transmission_type,
- const QuicFrames& retransmittable_frames,
- bool has_crypto_handshake,
- int num_padding_bytes,
- EncryptionLevel encryption_level,
- QuicPacketNumberLength packet_number_length)
- : packet_number(packet_number),
- retransmittable_frames(retransmittable_frames),
- transmission_type(transmission_type),
- has_crypto_handshake(has_crypto_handshake),
- num_padding_bytes(num_padding_bytes),
- encryption_level(encryption_level),
- packet_number_length(packet_number_length) {}
-
- QuicPendingRetransmission(QuicPacketNumber packet_number,
- TransmissionType transmission_type,
- const QuicTransmissionInfo& tranmission_info)
- : packet_number(packet_number),
- retransmittable_frames(tranmission_info.retransmittable_frames),
- transmission_type(transmission_type),
- has_crypto_handshake(tranmission_info.has_crypto_handshake),
- num_padding_bytes(tranmission_info.num_padding_bytes),
- encryption_level(tranmission_info.encryption_level),
- packet_number_length(tranmission_info.packet_number_length) {}
-
- QuicPacketNumber packet_number;
- const QuicFrames& retransmittable_frames;
- TransmissionType transmission_type;
- bool has_crypto_handshake;
- int num_padding_bytes;
- EncryptionLevel encryption_level;
- QuicPacketNumberLength packet_number_length;
-};
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_CORE_QUIC_PENDING_RETRANSMISSION_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_process_packet_interface.h b/chromium/net/third_party/quiche/src/quic/core/quic_process_packet_interface.h
index fc4257e9927..3cd87ef33c0 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_process_packet_interface.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_process_packet_interface.h
@@ -11,7 +11,7 @@
namespace quic {
// A class to process each incoming packet.
-class ProcessPacketInterface {
+class QUIC_NO_EXPORT ProcessPacketInterface {
public:
virtual ~ProcessPacketInterface() {}
virtual void ProcessPacket(const QuicSocketAddress& self_address,
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 e21f4c48b8e..908d04fb228 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
@@ -25,14 +25,6 @@ namespace {
// against an ack loss
const size_t kMaxPacketsAfterNewMissing = 4;
-// Maximum number of retransmittable packets received before sending an ack.
-const QuicPacketCount kDefaultRetransmittablePacketsBeforeAck = 2;
-// Minimum number of packets received before ack decimation is enabled.
-// This intends to avoid the beginning of slow start, when CWNDs may be
-// rapidly increasing.
-const QuicPacketCount kMinReceivedBeforeAckDecimation = 100;
-// Wait for up to 10 retransmittable packets before sending an ack.
-const QuicPacketCount kMaxRetransmittablePacketsBeforeAck = 10;
// One quarter RTT delay when doing ack decimation.
const float kAckDecimationDelay = 0.25;
// One eighth RTT delay when doing ack decimation.
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 a747f0b2cd2..bd0343bdb51 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
@@ -12,7 +12,6 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters_proto.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_stats.h"
-#include "net/third_party/quiche/src/quic/core/quic_pending_retransmission.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
@@ -41,19 +40,14 @@ static const int64_t kMinHandshakeTimeoutMs = 10;
// per draft RFC draft-dukkipati-tcpm-tcp-loss-probe.
static const size_t kDefaultMaxTailLossProbes = 2;
-inline bool HasCryptoHandshake(const QuicTransmissionInfo& transmission_info) {
- DCHECK(!transmission_info.has_crypto_handshake ||
- !transmission_info.retransmittable_frames.empty());
- return transmission_info.has_crypto_handshake;
-}
-
// Returns true of retransmissions of the specified type should retransmit
// the frames directly (as opposed to resulting in a loss notification).
inline bool ShouldForceRetransmission(TransmissionType transmission_type) {
return transmission_type == HANDSHAKE_RETRANSMISSION ||
transmission_type == TLP_RETRANSMISSION ||
transmission_type == PROBING_RETRANSMISSION ||
- transmission_type == RTO_RETRANSMISSION;
+ transmission_type == RTO_RETRANSMISSION ||
+ transmission_type == PTO_RETRANSMISSION;
}
// If pacing rate is accurate, > 2 burst token is not likely to help first ACK
@@ -97,10 +91,8 @@ QuicSentPacketManager::QuicSentPacketManager(
QuicTime::Delta::FromMilliseconds(kMinTailLossProbeTimeoutMs)),
min_rto_timeout_(
QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs)),
- ietf_style_tlp_(false),
- ietf_style_2x_tlp_(false),
largest_mtu_acked_(0),
- handshake_confirmed_(false),
+ handshake_state_(HANDSHAKE_START),
peer_max_ack_delay_(
QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs)),
rtt_updated_(false),
@@ -108,11 +100,13 @@ QuicSentPacketManager::QuicSentPacketManager(
pto_enabled_(false),
max_probe_packets_per_pto_(2),
consecutive_pto_count_(0),
- fix_rto_retransmission_(false),
handshake_mode_disabled_(false),
- detect_spurious_losses_(GetQuicReloadableFlag(quic_detect_spurious_loss)),
+ skip_packet_number_for_pto_(false),
+ always_include_max_ack_delay_for_pto_timeout_(true),
+ pto_exponential_backoff_start_point_(0),
+ pto_rttvar_multiplier_(4),
neuter_handshake_packets_once_(
- GetQuicReloadableFlag(quic_neuter_handshake_packets_once)) {
+ GetQuicReloadableFlag(quic_neuter_handshake_packets_once2)) {
SetSendAlgorithm(congestion_control_type);
}
@@ -145,40 +139,55 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
if (config.HasClientSentConnectionOption(kMAD1, perspective)) {
rtt_stats_.set_initial_max_ack_delay(peer_max_ack_delay_);
}
- if (GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_sent_packet_manager_cleanup);
- if (config.HasClientSentConnectionOption(kMAD2, perspective)) {
- // Set the minimum to the alarm granularity.
- min_tlp_timeout_ = QuicTime::Delta::FromMilliseconds(1);
- }
- if (config.HasClientSentConnectionOption(kMAD3, perspective)) {
- // Set the minimum to the alarm granularity.
- min_rto_timeout_ = QuicTime::Delta::FromMilliseconds(1);
- }
- } else {
- if (config.HasClientSentConnectionOption(kMAD2, perspective)) {
- min_tlp_timeout_ = QuicTime::Delta::Zero();
- }
- if (config.HasClientSentConnectionOption(kMAD3, perspective)) {
- min_rto_timeout_ = QuicTime::Delta::Zero();
- }
- if (config.HasClientSentConnectionOption(kMAD4, perspective)) {
- ietf_style_tlp_ = true;
- }
- if (config.HasClientSentConnectionOption(kMAD5, perspective)) {
- ietf_style_2x_tlp_ = true;
- }
+ if (config.HasClientSentConnectionOption(kMAD2, perspective)) {
+ // Set the minimum to the alarm granularity.
+ min_tlp_timeout_ = QuicTime::Delta::FromMilliseconds(1);
+ }
+ if (config.HasClientSentConnectionOption(kMAD3, perspective)) {
+ // Set the minimum to the alarm granularity.
+ min_rto_timeout_ = QuicTime::Delta::FromMilliseconds(1);
}
- if (GetQuicReloadableFlag(quic_enable_pto) && fix_rto_retransmission_) {
+ if (GetQuicReloadableFlag(quic_enable_pto)) {
if (config.HasClientSentConnectionOption(k2PTO, perspective)) {
pto_enabled_ = true;
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 2, 4);
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 2, 8);
}
if (config.HasClientSentConnectionOption(k1PTO, perspective)) {
pto_enabled_ = true;
max_probe_packets_per_pto_ = 1;
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 1, 4);
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 1, 8);
+ }
+ }
+
+ if (GetQuicReloadableFlag(quic_skip_packet_number_for_pto) &&
+ config.HasClientSentConnectionOption(kPTOS, perspective)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_skip_packet_number_for_pto);
+ if (!pto_enabled_) {
+ QUIC_PEER_BUG
+ << "PTO is not enabled when receiving PTOS connection option.";
+ pto_enabled_ = true;
+ max_probe_packets_per_pto_ = 1;
+ }
+ skip_packet_number_for_pto_ = true;
+ }
+
+ if (pto_enabled_) {
+ if (config.HasClientSentConnectionOption(kPTOA, perspective)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 5, 8);
+ always_include_max_ack_delay_for_pto_timeout_ = false;
+ }
+ if (config.HasClientSentConnectionOption(kPEB1, perspective)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 6, 8);
+ StartExponentialBackoffAfterNthPto(1);
+ }
+ if (config.HasClientSentConnectionOption(kPEB2, perspective)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 7, 8);
+ StartExponentialBackoffAfterNthPto(2);
+ }
+ if (config.HasClientSentConnectionOption(kPVS1, perspective)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_pto, 8, 8);
+ pto_rttvar_multiplier_ = 2;
}
}
@@ -252,26 +261,31 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
}
if (GetQuicReloadableFlag(quic_enable_ietf_loss_detection)) {
if (config.HasClientRequestedIndependentOption(kILD0, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_ietf_loss_detection, 1, 4);
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_ietf_loss_detection, 1, 5);
uber_loss_algorithm_.SetLossDetectionType(kIetfLossDetection);
}
if (config.HasClientRequestedIndependentOption(kILD1, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_ietf_loss_detection, 2, 4);
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_ietf_loss_detection, 2, 5);
uber_loss_algorithm_.SetLossDetectionType(kIetfLossDetection);
uber_loss_algorithm_.SetReorderingShift(kDefaultLossDelayShift);
}
- if (GetQuicReloadableFlag(quic_detect_spurious_loss)) {
- if (config.HasClientRequestedIndependentOption(kILD2, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_ietf_loss_detection, 3, 4);
- uber_loss_algorithm_.SetLossDetectionType(kIetfLossDetection);
- uber_loss_algorithm_.EnableAdaptiveReorderingThreshold();
- }
- if (config.HasClientRequestedIndependentOption(kILD3, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_ietf_loss_detection, 4, 4);
- uber_loss_algorithm_.SetLossDetectionType(kIetfLossDetection);
- uber_loss_algorithm_.SetReorderingShift(kDefaultLossDelayShift);
- uber_loss_algorithm_.EnableAdaptiveReorderingThreshold();
- }
+ if (config.HasClientRequestedIndependentOption(kILD2, perspective)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_ietf_loss_detection, 3, 5);
+ uber_loss_algorithm_.SetLossDetectionType(kIetfLossDetection);
+ uber_loss_algorithm_.EnableAdaptiveReorderingThreshold();
+ }
+ if (config.HasClientRequestedIndependentOption(kILD3, perspective)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_ietf_loss_detection, 4, 5);
+ uber_loss_algorithm_.SetLossDetectionType(kIetfLossDetection);
+ uber_loss_algorithm_.SetReorderingShift(kDefaultLossDelayShift);
+ uber_loss_algorithm_.EnableAdaptiveReorderingThreshold();
+ }
+ if (config.HasClientRequestedIndependentOption(kILD4, perspective)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_enable_ietf_loss_detection, 5, 5);
+ uber_loss_algorithm_.SetLossDetectionType(kIetfLossDetection);
+ uber_loss_algorithm_.SetReorderingShift(kDefaultLossDelayShift);
+ uber_loss_algorithm_.EnableAdaptiveReorderingThreshold();
+ uber_loss_algorithm_.EnableAdaptiveTimeThreshold();
}
}
if (config.HasClientSentConnectionOption(kCONH, perspective)) {
@@ -293,13 +307,17 @@ void QuicSentPacketManager::ResumeConnectionState(
: cached_network_params.bandwidth_estimate_bytes_per_second());
QuicTime::Delta rtt =
QuicTime::Delta::FromMilliseconds(cached_network_params.min_rtt_ms());
- AdjustNetworkParameters(bandwidth, rtt, /*allow_cwnd_to_decrease=*/false);
+ // This calls the old AdjustNetworkParameters interface, and fills certain
+ // fields in SendAlgorithmInterface::NetworkParams
+ // (e.g., quic_bbr_fix_pacing_rate) using GFE flags.
+ AdjustNetworkParameters(SendAlgorithmInterface::NetworkParams(
+ bandwidth, rtt, /*allow_cwnd_to_decrease = */ false));
}
void QuicSentPacketManager::AdjustNetworkParameters(
- QuicBandwidth bandwidth,
- QuicTime::Delta rtt,
- bool allow_cwnd_to_decrease) {
+ const SendAlgorithmInterface::NetworkParams& params) {
+ const QuicBandwidth& bandwidth = params.bandwidth;
+ const QuicTime::Delta& rtt = params.rtt;
if (!rtt.IsZero()) {
SetInitialRtt(rtt);
}
@@ -309,8 +327,7 @@ void QuicSentPacketManager::AdjustNetworkParameters(
QUIC_RELOADABLE_FLAG_COUNT(quic_conservative_bursts);
pacing_sender_.SetBurstTokens(kConservativeUnpacedBurst);
}
- send_algorithm_->AdjustNetworkParameters(bandwidth, rtt,
- allow_cwnd_to_decrease);
+ send_algorithm_->AdjustNetworkParameters(params);
if (debug_delegate_ != nullptr) {
debug_delegate_->OnAdjustNetworkParameters(
bandwidth, rtt.IsZero() ? rtt_stats_.SmoothedOrInitialRtt() : rtt,
@@ -319,11 +336,12 @@ void QuicSentPacketManager::AdjustNetworkParameters(
}
void QuicSentPacketManager::SetHandshakeConfirmed() {
- if (!neuter_handshake_packets_once_ || !handshake_confirmed_) {
+ if (!neuter_handshake_packets_once_ ||
+ handshake_state_ < HANDSHAKE_COMPLETE) {
if (neuter_handshake_packets_once_) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_neuter_handshake_packets_once);
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_neuter_handshake_packets_once2, 1, 3);
}
- handshake_confirmed_ = true;
+ handshake_state_ = HANDSHAKE_COMPLETE;
NeuterHandshakePackets();
}
}
@@ -334,10 +352,8 @@ void QuicSentPacketManager::PostProcessNewlyAckedPackets(
QuicTime ack_receive_time,
bool rtt_updated,
QuicByteCount prior_bytes_in_flight) {
- if (session_decides_what_to_write()) {
- unacked_packets_.NotifyAggregatedStreamFrameAcked(
- last_ack_frame_.ack_delay_time);
- }
+ unacked_packets_.NotifyAggregatedStreamFrameAcked(
+ last_ack_frame_.ack_delay_time);
InvokeLossDetection(ack_receive_time);
// Ignore losses in RTO mode.
if (consecutive_rto_count_ > 0 && !use_new_rto_) {
@@ -435,53 +451,72 @@ void QuicSentPacketManager::RetransmitUnackedPackets(
void QuicSentPacketManager::NeuterUnencryptedPackets() {
QuicPacketNumber packet_number = unacked_packets_.GetLeastUnacked();
- if (session_decides_what_to_write()) {
- for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
- it != unacked_packets_.end(); ++it, ++packet_number) {
- if (!it->retransmittable_frames.empty() &&
- it->encryption_level == ENCRYPTION_INITIAL) {
- // Once the connection swithes to forward secure, no unencrypted packets
- // will be sent. The data has been abandoned in the cryto stream. Remove
- // it from in flight.
- unacked_packets_.RemoveFromInFlight(packet_number);
- }
- }
- return;
- }
- for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
+ for (QuicUnackedPacketMap::iterator it = unacked_packets_.begin();
it != unacked_packets_.end(); ++it, ++packet_number) {
- if (it->encryption_level == ENCRYPTION_INITIAL) {
- // Once you're forward secure, no unencrypted packets will be sent,
- // crypto or otherwise. Unencrypted packets are neutered and abandoned,
- // to ensure they are not retransmitted or considered lost from a
- // congestion control perspective.
- pending_retransmissions_.erase(packet_number);
+ if (!it->retransmittable_frames.empty() &&
+ it->encryption_level == ENCRYPTION_INITIAL) {
+ // Once the connection swithes to forward secure, no unencrypted packets
+ // will be sent. The data has been abandoned in the cryto stream. Remove
+ // it from in flight.
unacked_packets_.RemoveFromInFlight(packet_number);
- unacked_packets_.RemoveRetransmittability(packet_number);
+ if (neuter_handshake_packets_once_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_neuter_handshake_packets_once2, 2, 3);
+ it->state = NEUTERED;
+ DCHECK(!unacked_packets_.HasRetransmittableFrames(*it));
+ }
}
}
}
void QuicSentPacketManager::NeuterHandshakePackets() {
QuicPacketNumber packet_number = unacked_packets_.GetLeastUnacked();
- for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
+ for (QuicUnackedPacketMap::iterator it = unacked_packets_.begin();
it != unacked_packets_.end(); ++it, ++packet_number) {
- if (session_decides_what_to_write()) {
- if (!it->retransmittable_frames.empty() &&
- unacked_packets_.GetPacketNumberSpace(it->encryption_level) ==
- HANDSHAKE_DATA) {
- unacked_packets_.RemoveFromInFlight(packet_number);
+ if (!it->retransmittable_frames.empty() &&
+ unacked_packets_.GetPacketNumberSpace(it->encryption_level) ==
+ HANDSHAKE_DATA) {
+ unacked_packets_.RemoveFromInFlight(packet_number);
+ if (neuter_handshake_packets_once_) {
+ // Notify session that the data has been delivered (but do not notify
+ // send algorithm).
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_neuter_handshake_packets_once2, 3, 3);
+ it->state = NEUTERED;
+ unacked_packets_.NotifyFramesAcked(*it, QuicTime::Delta::Zero(),
+ QuicTime::Zero());
}
- continue;
}
- if (unacked_packets_.GetPacketNumberSpace(it->encryption_level) ==
- HANDSHAKE_DATA &&
- unacked_packets_.HasRetransmittableFrames(*it)) {
- pending_retransmissions_.erase(packet_number);
- unacked_packets_.RemoveFromInFlight(packet_number);
- unacked_packets_.RemoveRetransmittability(packet_number);
+ }
+}
+
+bool QuicSentPacketManager::ShouldAddMaxAckDelay() const {
+ DCHECK(pto_enabled_);
+ if (always_include_max_ack_delay_for_pto_timeout_) {
+ return true;
+ }
+ if (!unacked_packets_
+ .GetLargestSentRetransmittableOfPacketNumberSpace(APPLICATION_DATA)
+ .IsInitialized() ||
+ unacked_packets_.GetLargestSentRetransmittableOfPacketNumberSpace(
+ APPLICATION_DATA) <
+ FirstSendingPacketNumber() + kMinReceivedBeforeAckDecimation - 1) {
+ // Peer is doing TCP style acking. Expect an immediate ACK if more than 1
+ // packet are outstanding.
+ if (unacked_packets_.packets_in_flight() >=
+ kDefaultRetransmittablePacketsBeforeAck) {
+ return false;
}
+ } else if (unacked_packets_.packets_in_flight() >=
+ kMaxRetransmittablePacketsBeforeAck) {
+ // Peer is doing ack decimation. Expect an immediate ACK if >= 10
+ // packets are outstanding.
+ return false;
+ }
+ if (skip_packet_number_for_pto_ && consecutive_pto_count_ > 0) {
+ // An immediate ACK is expected when doing PTOS. Please note, this will miss
+ // cases when PTO fires and turns out to be spurious.
+ return false;
}
+ return true;
}
void QuicSentPacketManager::MarkForRetransmission(
@@ -489,26 +524,15 @@ void QuicSentPacketManager::MarkForRetransmission(
TransmissionType transmission_type) {
QuicTransmissionInfo* transmission_info =
unacked_packets_.GetMutableTransmissionInfo(packet_number);
- // When session decides what to write, 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 &&
- (!session_decides_what_to_write() ||
- transmission_type != RTO_RETRANSMISSION)) &&
+ // 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))
<< "transmission_type: " << TransmissionTypeToString(transmission_type);
// Handshake packets should never be sent as probing retransmissions.
- DCHECK(pto_enabled_ || !transmission_info->has_crypto_handshake ||
+ DCHECK(!transmission_info->has_crypto_handshake ||
transmission_type != PROBING_RETRANSMISSION);
- if (!session_decides_what_to_write()) {
- if (!unacked_packets_.HasRetransmittableFrames(*transmission_info)) {
- return;
- }
- if (!QuicContainsKey(pending_retransmissions_, packet_number)) {
- pending_retransmissions_[packet_number] = transmission_type;
- }
- return;
- }
HandleRetransmission(transmission_type, transmission_info);
@@ -520,7 +544,6 @@ void QuicSentPacketManager::MarkForRetransmission(
void QuicSentPacketManager::HandleRetransmission(
TransmissionType transmission_type,
QuicTransmissionInfo* transmission_info) {
- DCHECK(session_decides_what_to_write());
if (ShouldForceRetransmission(transmission_type)) {
// TODO(fayang): Consider to make RTO and PROBING retransmission
// strategies be configurable by applications. Today, TLP, RTO and PROBING
@@ -561,149 +584,47 @@ void QuicSentPacketManager::RecordOneSpuriousRetransmission(
}
}
-void QuicSentPacketManager::RecordSpuriousRetransmissions(
- const QuicTransmissionInfo& info,
- QuicPacketNumber acked_packet_number) {
- if (session_decides_what_to_write()) {
- RecordOneSpuriousRetransmission(info);
- if (!detect_spurious_losses_ &&
- info.transmission_type == LOSS_RETRANSMISSION) {
- // Only inform the loss detection of spurious retransmits it caused.
- loss_algorithm_->SpuriousRetransmitDetected(
- unacked_packets_, clock_->Now(), rtt_stats_, acked_packet_number);
- }
- return;
- }
- QuicPacketNumber retransmission = info.retransmission;
- while (retransmission.IsInitialized()) {
- const QuicTransmissionInfo& retransmit_info =
- unacked_packets_.GetTransmissionInfo(retransmission);
- retransmission = retransmit_info.retransmission;
- RecordOneSpuriousRetransmission(retransmit_info);
- }
- // Only inform the loss detection of spurious retransmits it caused.
- if (unacked_packets_.GetTransmissionInfo(info.retransmission)
- .transmission_type == LOSS_RETRANSMISSION) {
- loss_algorithm_->SpuriousRetransmitDetected(
- unacked_packets_, clock_->Now(), rtt_stats_, info.retransmission);
- }
-}
-
-QuicPendingRetransmission QuicSentPacketManager::NextPendingRetransmission() {
- QUIC_BUG_IF(pending_retransmissions_.empty())
- << "Unexpected call to NextPendingRetransmission() with empty pending "
- << "retransmission list. Corrupted memory usage imminent.";
- QUIC_BUG_IF(session_decides_what_to_write())
- << "Unexpected call to NextPendingRetransmission() when session handles "
- "retransmissions";
- QuicPacketNumber packet_number = pending_retransmissions_.begin()->first;
- TransmissionType transmission_type = pending_retransmissions_.begin()->second;
- if (unacked_packets_.HasPendingCryptoPackets()) {
- // Ensure crypto packets are retransmitted before other packets.
- for (const auto& pair : pending_retransmissions_) {
- if (HasCryptoHandshake(
- unacked_packets_.GetTransmissionInfo(pair.first))) {
- packet_number = pair.first;
- transmission_type = pair.second;
- break;
- }
- }
- }
- DCHECK(unacked_packets_.IsUnacked(packet_number)) << packet_number;
- const QuicTransmissionInfo& transmission_info =
- unacked_packets_.GetTransmissionInfo(packet_number);
- DCHECK(unacked_packets_.HasRetransmittableFrames(transmission_info));
-
- return QuicPendingRetransmission(packet_number, transmission_type,
- transmission_info);
-}
-
-QuicPacketNumber QuicSentPacketManager::GetNewestRetransmission(
- QuicPacketNumber packet_number,
- const QuicTransmissionInfo& transmission_info) const {
- if (session_decides_what_to_write()) {
- return packet_number;
- }
- QuicPacketNumber retransmission = transmission_info.retransmission;
- while (retransmission.IsInitialized()) {
- packet_number = retransmission;
- retransmission =
- unacked_packets_.GetTransmissionInfo(retransmission).retransmission;
- }
- return packet_number;
-}
-
void QuicSentPacketManager::MarkPacketHandled(QuicPacketNumber packet_number,
QuicTransmissionInfo* info,
QuicTime ack_receive_time,
QuicTime::Delta ack_delay_time,
QuicTime receive_timestamp) {
- QuicPacketNumber newest_transmission =
- GetNewestRetransmission(packet_number, *info);
- // Remove the most recent packet, if it is pending retransmission.
- pending_retransmissions_.erase(newest_transmission);
-
- if (newest_transmission == packet_number) {
- // Try to aggregate acked stream frames if acked packet is not a
- // retransmission.
- const bool fast_path = session_decides_what_to_write() &&
- info->transmission_type == NOT_RETRANSMISSION;
- if (fast_path) {
- unacked_packets_.MaybeAggregateAckedStreamFrame(*info, ack_delay_time,
- receive_timestamp);
- } else {
- if (session_decides_what_to_write()) {
- unacked_packets_.NotifyAggregatedStreamFrameAcked(ack_delay_time);
- }
- const bool new_data_acked = unacked_packets_.NotifyFramesAcked(
- *info, ack_delay_time, receive_timestamp);
- if (session_decides_what_to_write() && !new_data_acked &&
- info->transmission_type != NOT_RETRANSMISSION) {
- // Record as a spurious retransmission if this packet is a
- // retransmission and no new data gets acked.
- QUIC_DVLOG(1) << "Detect spurious retransmitted packet "
- << packet_number << " transmission type: "
- << TransmissionTypeToString(info->transmission_type);
- RecordSpuriousRetransmissions(*info, packet_number);
- }
- }
- if (detect_spurious_losses_ && session_decides_what_to_write() &&
- info->state == LOST) {
- // Record as a spurious loss as a packet previously declared lost gets
- // acked.
- QUIC_RELOADABLE_FLAG_COUNT(quic_detect_spurious_loss);
- const PacketNumberSpace packet_number_space =
- unacked_packets_.GetPacketNumberSpace(info->encryption_level);
- const QuicPacketNumber previous_largest_acked =
- supports_multiple_packet_number_spaces()
- ? unacked_packets_.GetLargestAckedOfPacketNumberSpace(
- packet_number_space)
- : unacked_packets_.largest_acked();
- QUIC_DVLOG(1) << "Packet " << packet_number
- << " was detected lost spuriously, "
- "previous_largest_acked: "
- << previous_largest_acked;
- loss_algorithm_->SpuriousLossDetected(unacked_packets_, rtt_stats_,
- ack_receive_time, packet_number,
- previous_largest_acked);
- }
+ // Try to aggregate acked stream frames if acked packet is not a
+ // retransmission.
+ if (info->transmission_type == NOT_RETRANSMISSION) {
+ unacked_packets_.MaybeAggregateAckedStreamFrame(*info, ack_delay_time,
+ receive_timestamp);
} else {
- DCHECK(!session_decides_what_to_write());
- RecordSpuriousRetransmissions(*info, packet_number);
- // Remove the most recent packet from flight if it's a crypto handshake
- // packet, since they won't be acked now that one has been processed.
- // Other crypto handshake packets won't be in flight, only the newest
- // transmission of a crypto packet is in flight at once.
- // TODO(ianswett): Instead of handling all crypto packets special,
- // only handle null encrypted packets in a special way.
- const QuicTransmissionInfo& newest_transmission_info =
- unacked_packets_.GetTransmissionInfo(newest_transmission);
- unacked_packets_.NotifyFramesAcked(newest_transmission_info, ack_delay_time,
- receive_timestamp);
- if (HasCryptoHandshake(newest_transmission_info)) {
- unacked_packets_.RemoveFromInFlight(newest_transmission);
+ unacked_packets_.NotifyAggregatedStreamFrameAcked(ack_delay_time);
+ const bool new_data_acked = unacked_packets_.NotifyFramesAcked(
+ *info, ack_delay_time, receive_timestamp);
+ if (!new_data_acked && info->transmission_type != NOT_RETRANSMISSION) {
+ // Record as a spurious retransmission if this packet is a
+ // retransmission and no new data gets acked.
+ QUIC_DVLOG(1) << "Detect spurious retransmitted packet " << packet_number
+ << " transmission type: "
+ << TransmissionTypeToString(info->transmission_type);
+ RecordOneSpuriousRetransmission(*info);
}
}
+ if (info->state == LOST) {
+ // Record as a spurious loss as a packet previously declared lost gets
+ // acked.
+ const PacketNumberSpace packet_number_space =
+ unacked_packets_.GetPacketNumberSpace(info->encryption_level);
+ const QuicPacketNumber previous_largest_acked =
+ supports_multiple_packet_number_spaces()
+ ? unacked_packets_.GetLargestAckedOfPacketNumberSpace(
+ packet_number_space)
+ : unacked_packets_.largest_acked();
+ QUIC_DVLOG(1) << "Packet " << packet_number
+ << " was detected lost spuriously, "
+ "previous_largest_acked: "
+ << previous_largest_acked;
+ loss_algorithm_->SpuriousLossDetected(unacked_packets_, rtt_stats_,
+ ack_receive_time, packet_number,
+ previous_largest_acked);
+ }
if (network_change_visitor_ != nullptr &&
info->bytes_sent > largest_mtu_acked_) {
@@ -717,7 +638,6 @@ void QuicSentPacketManager::MarkPacketHandled(QuicPacketNumber packet_number,
bool QuicSentPacketManager::OnPacketSent(
SerializedPacket* serialized_packet,
- QuicPacketNumber original_packet_number,
QuicTime sent_time,
TransmissionType transmission_type,
HasRetransmittableData has_retransmittable_data) {
@@ -726,11 +646,6 @@ bool QuicSentPacketManager::OnPacketSent(
DCHECK(!unacked_packets_.IsUnacked(packet_number));
QUIC_BUG_IF(serialized_packet->encrypted_length == 0)
<< "Cannot send empty packets.";
-
- if (original_packet_number.IsInitialized()) {
- pending_retransmissions_.erase(original_packet_number);
- }
-
if (pending_timer_transmission_count_ > 0) {
--pending_timer_transmission_count_;
}
@@ -746,8 +661,8 @@ bool QuicSentPacketManager::OnPacketSent(
serialized_packet->encrypted_length, has_retransmittable_data);
}
- unacked_packets_.AddSentPacket(serialized_packet, original_packet_number,
- transmission_type, sent_time, in_flight);
+ unacked_packets_.AddSentPacket(serialized_packet, transmission_type,
+ sent_time, in_flight);
// Reset the retransmission timer anytime a pending packet is sent.
return in_flight;
}
@@ -755,7 +670,7 @@ bool QuicSentPacketManager::OnPacketSent(
QuicSentPacketManager::RetransmissionTimeoutMode
QuicSentPacketManager::OnRetransmissionTimeout() {
DCHECK(unacked_packets_.HasInFlightPackets() ||
- (handshake_mode_disabled_ && !handshake_confirmed_));
+ (handshake_mode_disabled_ && handshake_state_ < HANDSHAKE_COMPLETE));
DCHECK_EQ(0u, pending_timer_transmission_count_);
// Handshake retransmission, timer based loss detection, TLP, and RTO are
// implemented with a single alarm. The handshake alarm is set when the
@@ -805,25 +720,18 @@ void QuicSentPacketManager::RetransmitCryptoPackets() {
for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
it != unacked_packets_.end(); ++it, ++packet_number) {
// Only retransmit frames which are in flight, and therefore have been sent.
- if (!it->in_flight ||
- (session_decides_what_to_write() && it->state != OUTSTANDING) ||
+ if (!it->in_flight || it->state != OUTSTANDING ||
!it->has_crypto_handshake ||
!unacked_packets_.HasRetransmittableFrames(*it)) {
continue;
}
packet_retransmitted = true;
- if (session_decides_what_to_write()) {
- crypto_retransmissions.push_back(packet_number);
- } else {
- MarkForRetransmission(packet_number, HANDSHAKE_RETRANSMISSION);
- }
+ crypto_retransmissions.push_back(packet_number);
++pending_timer_transmission_count_;
}
DCHECK(packet_retransmitted) << "No crypto packets found to retransmit.";
- if (session_decides_what_to_write()) {
- for (QuicPacketNumber retransmission : crypto_retransmissions) {
- MarkForRetransmission(retransmission, HANDSHAKE_RETRANSMISSION);
- }
+ for (QuicPacketNumber retransmission : crypto_retransmissions) {
+ MarkForRetransmission(retransmission, HANDSHAKE_RETRANSMISSION);
}
}
@@ -843,8 +751,7 @@ bool QuicSentPacketManager::MaybeRetransmitOldestPacket(TransmissionType type) {
for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
it != unacked_packets_.end(); ++it, ++packet_number) {
// Only retransmit frames which are in flight, and therefore have been sent.
- if (!it->in_flight ||
- (session_decides_what_to_write() && it->state != OUTSTANDING) ||
+ if (!it->in_flight || it->state != OUTSTANDING ||
!unacked_packets_.HasRetransmittableFrames(*it)) {
continue;
}
@@ -865,33 +772,13 @@ void QuicSentPacketManager::RetransmitRtoPackets() {
std::vector<QuicPacketNumber> retransmissions;
for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
it != unacked_packets_.end(); ++it, ++packet_number) {
- if ((!session_decides_what_to_write() || it->state == OUTSTANDING) &&
+ if (it->state == OUTSTANDING &&
unacked_packets_.HasRetransmittableFrames(*it) &&
pending_timer_transmission_count_ < max_rto_packets_) {
- if (session_decides_what_to_write()) {
- retransmissions.push_back(packet_number);
- } else {
- MarkForRetransmission(packet_number, RTO_RETRANSMISSION);
- }
+ DCHECK(!neuter_handshake_packets_once_ || it->in_flight);
+ retransmissions.push_back(packet_number);
++pending_timer_transmission_count_;
}
- // Abandon non-retransmittable data that's in flight to ensure it doesn't
- // fill up the congestion window.
- bool has_retransmissions = it->retransmission.IsInitialized();
- if (session_decides_what_to_write()) {
- has_retransmissions = it->state != OUTSTANDING;
- }
- if (!fix_rto_retransmission_ && it->in_flight && !has_retransmissions &&
- !unacked_packets_.HasRetransmittableFrames(*it)) {
- // Log only for non-retransmittable data.
- // Retransmittable data is marked as lost during loss detection, and will
- // be logged later.
- unacked_packets_.RemoveFromInFlight(packet_number);
- if (debug_delegate_ != nullptr) {
- debug_delegate_->OnPacketLoss(packet_number, RTO_RETRANSMISSION,
- clock_->Now());
- }
- }
}
if (pending_timer_transmission_count_ > 0) {
if (consecutive_rto_count_ == 0) {
@@ -899,17 +786,15 @@ void QuicSentPacketManager::RetransmitRtoPackets() {
}
++consecutive_rto_count_;
}
- if (session_decides_what_to_write()) {
- for (QuicPacketNumber retransmission : retransmissions) {
- MarkForRetransmission(retransmission, RTO_RETRANSMISSION);
- }
- if (fix_rto_retransmission_ && retransmissions.empty()) {
- QUIC_BUG_IF(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);
- pending_timer_transmission_count_ = 1;
- }
+ for (QuicPacketNumber retransmission : retransmissions) {
+ MarkForRetransmission(retransmission, RTO_RETRANSMISSION);
+ }
+ if (retransmissions.empty()) {
+ QUIC_BUG_IF(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);
+ pending_timer_transmission_count_ = 1;
}
}
@@ -923,6 +808,7 @@ void QuicSentPacketManager::MaybeSendProbePackets() {
it != unacked_packets_.end(); ++it, ++packet_number) {
if (it->state == OUTSTANDING &&
unacked_packets_.HasRetransmittableFrames(*it)) {
+ DCHECK(!neuter_handshake_packets_once_ || it->in_flight);
probing_packets.push_back(packet_number);
if (probing_packets.size() == pending_timer_transmission_count_) {
break;
@@ -933,7 +819,7 @@ void QuicSentPacketManager::MaybeSendProbePackets() {
for (QuicPacketNumber retransmission : probing_packets) {
QUIC_DVLOG(1) << ENDPOINT << "Marking " << retransmission
<< " for probing retransmission";
- MarkForRetransmission(retransmission, PROBING_RETRANSMISSION);
+ MarkForRetransmission(retransmission, PTO_RETRANSMISSION);
}
// It is possible that there is not enough outstanding data for probing.
}
@@ -949,18 +835,21 @@ void QuicSentPacketManager::AdjustPendingTimerTransmissions() {
}
void QuicSentPacketManager::EnableIetfPtoAndLossDetection() {
- DCHECK(session_decides_what_to_write());
- fix_rto_retransmission_ = true;
pto_enabled_ = true;
handshake_mode_disabled_ = true;
uber_loss_algorithm_.SetLossDetectionType(kIetfLossDetection);
}
+void QuicSentPacketManager::StartExponentialBackoffAfterNthPto(
+ size_t exponential_backoff_start_point) {
+ pto_exponential_backoff_start_point_ = exponential_backoff_start_point;
+}
+
QuicSentPacketManager::RetransmissionTimeoutMode
QuicSentPacketManager::GetRetransmissionMode() const {
DCHECK(unacked_packets_.HasInFlightPackets() ||
- (handshake_mode_disabled_ && !handshake_confirmed_));
- if (!handshake_mode_disabled_ && !handshake_confirmed_ &&
+ (handshake_mode_disabled_ && handshake_state_ < HANDSHAKE_COMPLETE));
+ if (!handshake_mode_disabled_ && handshake_state_ < HANDSHAKE_COMPLETE &&
unacked_packets_.HasPendingCryptoPackets()) {
return HANDSHAKE_MODE;
}
@@ -1045,7 +934,7 @@ QuicTime::Delta QuicSentPacketManager::TimeUntilSend(QuicTime now) const {
const QuicTime QuicSentPacketManager::GetRetransmissionTime() const {
if (!unacked_packets_.HasInFlightPackets() &&
- (!handshake_mode_disabled_ || handshake_confirmed_ ||
+ (!handshake_mode_disabled_ || handshake_state_ >= HANDSHAKE_COMPLETE ||
unacked_packets_.perspective() == Perspective::IS_SERVER)) {
// Do not set the timer if there is nothing in flight. However, to avoid
// handshake deadlock due to anti-amplification limit, client needs to set
@@ -1057,10 +946,6 @@ const QuicTime QuicSentPacketManager::GetRetransmissionTime() const {
// Do not set the timer if there is any credit left.
return QuicTime::Zero();
}
- if (!fix_rto_retransmission_ &&
- !unacked_packets_.HasUnackedRetransmittableFrames()) {
- return QuicTime::Zero();
- }
switch (GetRetransmissionMode()) {
case HANDSHAKE_MODE:
return unacked_packets_.GetLastCryptoPacketSentTime() +
@@ -1089,14 +974,6 @@ const QuicTime QuicSentPacketManager::GetRetransmissionTime() const {
return std::max(tlp_time, rto_time);
}
case PTO_MODE: {
- if (!unacked_packets().simple_inflight_time() &&
- handshake_mode_disabled_ && !handshake_confirmed_ &&
- !unacked_packets_.HasInFlightPackets()) {
- DCHECK_EQ(Perspective::IS_CLIENT, unacked_packets_.perspective());
- return std::max(clock_->ApproximateNow(),
- unacked_packets_.GetLastCryptoPacketSentTime() +
- GetProbeTimeoutDelay());
- }
// Ensure PTO never gets set to a time in the past.
return std::max(clock_->ApproximateNow(),
unacked_packets_.GetLastInFlightPacketSentTime() +
@@ -1141,20 +1018,11 @@ const QuicTime::Delta QuicSentPacketManager::GetTailLossProbeDelay(
size_t consecutive_tlp_count) const {
QuicTime::Delta srtt = rtt_stats_.SmoothedOrInitialRtt();
if (enable_half_rtt_tail_loss_probe_ && consecutive_tlp_count == 0u) {
- if (!session_decides_what_to_write()) {
- return std::max(min_tlp_timeout_, srtt * 0.5);
- }
if (unacked_packets().HasUnackedStreamData()) {
// Enable TLPR if there are pending data packets.
return std::max(min_tlp_timeout_, srtt * 0.5);
}
}
- if (ietf_style_tlp_) {
- return std::max(min_tlp_timeout_, 1.5 * srtt + rtt_stats_.max_ack_delay());
- }
- if (ietf_style_2x_tlp_) {
- return std::max(min_tlp_timeout_, 2 * srtt + rtt_stats_.max_ack_delay());
- }
if (!unacked_packets_.HasMultipleInFlightPackets()) {
// This expression really should be using the delayed ack time, but in TCP
// MinRTO was traditionally set to 2x the delayed ack timer and this
@@ -1200,45 +1068,27 @@ const QuicTime::Delta QuicSentPacketManager::GetProbeTimeoutDelay() const {
}
const QuicTime::Delta pto_delay =
rtt_stats_.smoothed_rtt() +
- std::max(4 * rtt_stats_.mean_deviation(),
+ std::max(pto_rttvar_multiplier_ * rtt_stats_.mean_deviation(),
QuicTime::Delta::FromMilliseconds(1)) +
- peer_max_ack_delay_;
- return pto_delay * (1 << consecutive_pto_count_);
+ (ShouldAddMaxAckDelay() ? peer_max_ack_delay_ : QuicTime::Delta::Zero());
+ return pto_delay * (1 << (consecutive_pto_count_ -
+ std::min(consecutive_pto_count_,
+ pto_exponential_backoff_start_point_)));
}
QuicTime::Delta QuicSentPacketManager::GetSlowStartDuration() const {
- if (send_algorithm_->GetCongestionControlType() != kBBR) {
- return QuicTime::Delta::Infinite();
- }
-
- if (!send_algorithm_->InSlowStart()) {
- return stats_->slowstart_duration;
+ if (send_algorithm_->GetCongestionControlType() == kBBR ||
+ send_algorithm_->GetCongestionControlType() == kBBRv2) {
+ return stats_->slowstart_duration.GetTotalElapsedTime(
+ clock_->ApproximateNow());
}
-
- return clock_->ApproximateNow() - stats_->slowstart_start_time +
- stats_->slowstart_duration;
+ return QuicTime::Delta::Infinite();
}
std::string QuicSentPacketManager::GetDebugState() const {
return send_algorithm_->GetDebugState();
}
-void QuicSentPacketManager::CancelRetransmissionsForStream(
- QuicStreamId stream_id) {
- if (session_decides_what_to_write()) {
- return;
- }
- unacked_packets_.CancelRetransmissionsForStream(stream_id);
- auto it = pending_retransmissions_.begin();
- while (it != pending_retransmissions_.end()) {
- if (unacked_packets_.HasRetransmittableFrames(it->first)) {
- ++it;
- continue;
- }
- it = pending_retransmissions_.erase(it);
- }
-}
-
void QuicSentPacketManager::SetSendAlgorithm(
CongestionControlType congestion_control_type) {
SetSendAlgorithm(SendAlgorithmInterface::Create(
@@ -1331,7 +1181,7 @@ AckResult QuicSentPacketManager::OnAckFrameEnd(
EncryptionLevel ack_decrypted_level) {
QuicByteCount prior_bytes_in_flight = unacked_packets_.bytes_in_flight();
// Reverse packets_acked_ so that it is in ascending order.
- reverse(packets_acked_.begin(), packets_acked_.end());
+ std::reverse(packets_acked_.begin(), packets_acked_.end());
for (AckedPacket& acked_packet : packets_acked_) {
QuicTransmissionInfo* info =
unacked_packets_.GetMutableTransmissionInfo(acked_packet.packet_number);
@@ -1370,6 +1220,9 @@ AckResult QuicSentPacketManager::OnAckFrameEnd(
return PACKETS_ACKED_IN_WRONG_PACKET_NUMBER_SPACE;
}
last_ack_frame_.packets.Add(acked_packet.packet_number);
+ if (info->encryption_level == ENCRYPTION_FORWARD_SECURE) {
+ handshake_state_ = HANDSHAKE_CONFIRMED;
+ }
largest_packet_peer_knows_is_acked_.UpdateMax(info->largest_acked);
if (supports_multiple_packet_number_spaces()) {
largest_packets_peer_knows_is_acked_[packet_number_space].UpdateMax(
@@ -1424,16 +1277,6 @@ void QuicSentPacketManager::SetInitialRtt(QuicTime::Delta rtt) {
rtt_stats_.set_initial_rtt(std::max(min_rtt, std::min(max_rtt, rtt)));
}
-void QuicSentPacketManager::SetSessionDecideWhatToWrite(
- bool session_decides_what_to_write) {
- if (GetQuicReloadableFlag(quic_fix_rto_retransmission3) &&
- session_decides_what_to_write) {
- fix_rto_retransmission_ = true;
- QUIC_RELOADABLE_FLAG_COUNT(quic_fix_rto_retransmission3);
- }
- unacked_packets_.SetSessionDecideWhatToWrite(session_decides_what_to_write);
-}
-
void QuicSentPacketManager::EnableMultiplePacketNumberSpacesSupport() {
unacked_packets_.EnableMultiplePacketNumberSpacesSupport();
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h
index 9e903fdfa2d..5a3f2ca05d7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h
@@ -19,7 +19,6 @@
#include "net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.h"
#include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters_proto.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
-#include "net/third_party/quiche/src/quic/core/quic_pending_retransmission.h"
#include "net/third_party/quiche/src/quic/core/quic_sustained_bandwidth_recorder.h"
#include "net/third_party/quiche/src/quic/core/quic_transmission_info.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
@@ -108,6 +107,25 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
PTO_MODE,
};
+ // Handshake state of this connection.
+ enum HandshakeState {
+ // Initial state.
+ HANDSHAKE_START,
+ // Only used in IETF QUIC with TLS handshake. State proceeds to
+ // HANDSHAKE_PROCESSED after a packet of HANDSHAKE packet number space
+ // gets successfully processed, and the initial key can be dropped.
+ HANDSHAKE_PROCESSED,
+ // In QUIC crypto, state proceeds to HANDSHAKE_COMPLETE if client receives
+ // SHLO or server successfully processes an ENCRYPTION_FORWARD_SECURE
+ // packet, such that the handshake packets can be neutered. In IETF QUIC
+ // with TLS handshake, state proceeds to HANDSHAKE_COMPLETE once the
+ // endpoint has both 1-RTT send and receive keys.
+ HANDSHAKE_COMPLETE,
+ // Only used in IETF QUIC with TLS handshake. State proceeds to
+ // HANDSHAKE_CONFIRMED if a 1-RTT packet gets acknowledged.
+ HANDSHAKE_CONFIRMED,
+ };
+
QuicSentPacketManager(Perspective perspective,
const QuicClock* clock,
QuicRandom* random,
@@ -133,8 +151,9 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
return pacing_sender_.max_pacing_rate();
}
- // Set handshake_confirmed_ to true and neuter packets in HANDSHAKE packet
- // number space.
+ // Called to mark the handshake state complete, and all handshake packets are
+ // neutered.
+ // TODO(fayang): Rename this function to OnHandshakeComplete.
void SetHandshakeConfirmed();
// Requests retransmission of all unacked packets of |retransmission_type|.
@@ -149,9 +168,8 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// Notify the sent packet manager of an external network measurement or
// prediction for either |bandwidth| or |rtt|; either can be empty.
- void AdjustNetworkParameters(QuicBandwidth bandwidth,
- QuicTime::Delta rtt,
- bool allow_cwnd_to_decrease);
+ void AdjustNetworkParameters(
+ const SendAlgorithmInterface::NetworkParams& params);
// Retransmits the oldest pending packet there is still a tail loss probe
// pending. Invoked after OnRetransmissionTimeout.
@@ -165,16 +183,6 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// TODO(fayang): Consider replace this function with NeuterHandshakePackets.
void NeuterUnencryptedPackets();
- // Returns true if there are pending retransmissions.
- // Not const because retransmissions may be cancelled before returning.
- bool HasPendingRetransmissions() const {
- return !pending_retransmissions_.empty();
- }
-
- // Retrieves the next pending retransmission. You must ensure that
- // there are pending retransmissions prior to calling this function.
- QuicPendingRetransmission NextPendingRetransmission();
-
// Returns true if there's outstanding crypto data.
bool HasUnackedCryptoPackets() const {
return unacked_packets_.HasPendingCryptoPackets();
@@ -195,7 +203,6 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// the number of bytes sent and if they were retransmitted. Returns true if
// the sender should reset the retransmission timer.
bool OnPacketSent(SerializedPacket* serialized_packet,
- QuicPacketNumber original_packet_number,
QuicTime sent_time,
TransmissionType transmission_type,
HasRetransmittableData has_retransmittable_data);
@@ -276,9 +283,6 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
return unacked_packets_.bytes_in_flight();
}
- // No longer retransmit data for |stream_id|.
- void CancelRetransmissionsForStream(QuicStreamId stream_id);
-
// Called when peer address changes and the connection migrates.
void OnConnectionMigration(AddressChangeType type);
@@ -300,9 +304,6 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
QuicPacketNumber ack_packet_number,
EncryptionLevel ack_decrypted_level);
- // Called to enable/disable letting session decide what to write.
- void SetSessionDecideWhatToWrite(bool session_decides_what_to_write);
-
void EnableMultiplePacketNumberSpacesSupport();
void SetDebugDelegate(DebugDelegate* debug_delegate);
@@ -363,11 +364,7 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
return largest_packet_peer_knows_is_acked_;
}
- bool handshake_confirmed() const { return handshake_confirmed_; }
-
- bool session_decides_what_to_write() const {
- return unacked_packets_.session_decides_what_to_write();
- }
+ HandshakeState handshake_state() const { return handshake_state_; }
size_t pending_timer_transmission_count() const {
return pending_timer_transmission_count_;
@@ -405,25 +402,27 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// Also enable IETF loss detection.
void EnableIetfPtoAndLossDetection();
+ // Called to set the start point of doing exponential backoff when calculating
+ // PTO timeout.
+ void StartExponentialBackoffAfterNthPto(
+ size_t exponential_backoff_start_point);
+
bool supports_multiple_packet_number_spaces() const {
return unacked_packets_.supports_multiple_packet_number_spaces();
}
- bool fix_rto_retransmission() const { return fix_rto_retransmission_; }
-
bool pto_enabled() const { return pto_enabled_; }
bool handshake_mode_disabled() const { return handshake_mode_disabled_; }
+ bool skip_packet_number_for_pto() const {
+ return skip_packet_number_for_pto_;
+ }
+
private:
friend class test::QuicConnectionPeer;
friend class test::QuicSentPacketManagerPeer;
- typedef QuicLinkedHashMap<QuicPacketNumber,
- TransmissionType,
- QuicPacketNumberHash>
- PendingRetransmissionMap;
-
// Returns the current retransmission mode.
RetransmissionTimeoutMode GetRetransmissionMode() const;
@@ -463,11 +462,6 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// Returns the probe timeout.
const QuicTime::Delta GetProbeTimeoutDelay() const;
- // Returns the newest transmission associated with a packet.
- QuicPacketNumber GetNewestRetransmission(
- QuicPacketNumber packet_number,
- const QuicTransmissionInfo& transmission_info) const;
-
// Update the RTT if the ack is for the largest acked packet number.
// Returns true if the rtt was updated.
bool MaybeUpdateRTT(QuicPacketNumber largest_acked,
@@ -521,11 +515,6 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// this function.
void RecordOneSpuriousRetransmission(const QuicTransmissionInfo& info);
- // Notify observers about spurious retransmits of packet with
- // QuicTransmissionInfo |info|.
- void RecordSpuriousRetransmissions(const QuicTransmissionInfo& info,
- QuicPacketNumber acked_packet_number);
-
// Sets the initial RTT of the connection.
void SetInitialRtt(QuicTime::Delta rtt);
@@ -539,6 +528,10 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// switches to IETF QUIC with QUIC TLS.
void NeuterHandshakePackets();
+ // Indicates whether including peer_max_ack_delay_ when calculating PTO
+ // timeout.
+ bool ShouldAddMaxAckDelay() const;
+
// Newly serialized retransmittable packets are added to this map, which
// contains owning pointers to any contained frames. If a packet is
// retransmitted, this map will contain entries for both the old and the new
@@ -549,9 +542,6 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// set to nullptr.
QuicUnackedPacketMap unacked_packets_;
- // Pending retransmissions which have not been packetized and sent yet.
- PendingRetransmissionMap pending_retransmissions_;
-
const QuicClock* clock_;
QuicRandom* random_;
QuicConnectionStats* stats_;
@@ -592,10 +582,6 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
QuicTime::Delta min_tlp_timeout_;
// The minimum RTO.
QuicTime::Delta min_rto_timeout_;
- // Whether to use IETF style TLP that includes the max ack delay.
- bool ietf_style_tlp_;
- // IETF style TLP, but with a 2x multiplier instead of 1.5x.
- bool ietf_style_2x_tlp_;
// Vectors packets acked and lost as a result of the last congestion event.
AckedPacketVector packets_acked_;
@@ -609,11 +595,8 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// Calls into |send_algorithm_| for the underlying congestion control.
PacingSender pacing_sender_;
- // Set to true after the crypto handshake has successfully completed. After
- // this is true we no longer use HANDSHAKE_MODE, and further frames sent on
- // the crypto stream (i.e. SCUP messages) are treated like normal
- // retransmittable frames.
- bool handshake_confirmed_;
+ // Indicates current handshake state.
+ HandshakeState handshake_state_;
// Records bandwidth from server to client in normal operation, over periods
// of time with no loss events.
@@ -652,17 +635,24 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// Number of times the PTO timer has fired in a row without receiving an ack.
size_t consecutive_pto_count_;
- // Latched value of quic_fix_rto_retransmission3 and
- // session_decides_what_to_write.
- bool fix_rto_retransmission_;
-
// True if HANDSHAKE mode has been disabled.
bool handshake_mode_disabled_;
- // Latched value of quic_detect_spurious_loss.
- const bool detect_spurious_losses_;
+ // If true, skip packet number before sending the last PTO retransmission.
+ bool skip_packet_number_for_pto_;
+
+ // If true, always include peer_max_ack_delay_ when calculating PTO timeout.
+ bool always_include_max_ack_delay_for_pto_timeout_;
+
+ // When calculating PTO timeout, the start point of doing exponential backoff.
+ // For example, 0 : always do exponential backoff. n : do exponential backoff
+ // since nth PTO.
+ size_t pto_exponential_backoff_start_point_;
+
+ // The multiplier of rttvar when calculating PTO timeout.
+ int pto_rttvar_multiplier_;
- // Latched value of quic_neuter_handshake_packets_once.
+ // Latched value of quic_neuter_handshake_packets_once2.
const bool neuter_handshake_packets_once_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc
index 4ee9fd31d86..8dd0c30faea 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc
@@ -7,7 +7,6 @@
#include <memory>
#include <utility>
-#include "net/third_party/quiche/src/quic/core/quic_pending_retransmission.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
@@ -53,7 +52,7 @@ class MockDebugDelegate : public QuicSentPacketManager::DebugDelegate {
QuicTime detection_time));
};
-class QuicSentPacketManagerTest : public QuicTestWithParam<bool> {
+class QuicSentPacketManagerTest : public QuicTest {
public:
void RetransmitCryptoPacket(uint64_t packet_number) {
EXPECT_CALL(
@@ -64,8 +63,8 @@ class QuicSentPacketManagerTest : public QuicTestWithParam<bool> {
packet.retransmittable_frames.push_back(
QuicFrame(QuicStreamFrame(1, false, 0, QuicStringPiece())));
packet.has_crypto_handshake = IS_HANDSHAKE;
- manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(),
- HANDSHAKE_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ manager_.OnPacketSent(&packet, clock_.Now(), HANDSHAKE_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA);
}
void RetransmitDataPacket(uint64_t packet_number,
@@ -77,7 +76,7 @@ class QuicSentPacketManagerTest : public QuicTestWithParam<bool> {
kDefaultLength, HAS_RETRANSMITTABLE_DATA));
SerializedPacket packet(CreatePacket(packet_number, true));
packet.encryption_level = level;
- manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(), type,
+ manager_.OnPacketSent(&packet, clock_.Now(), type,
HAS_RETRANSMITTABLE_DATA);
}
@@ -102,7 +101,6 @@ class QuicSentPacketManagerTest : public QuicTestWithParam<bool> {
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1000));
manager_.SetNetworkChangeVisitor(network_change_visitor_.get());
manager_.SetSessionNotifier(&notifier_);
- manager_.SetSessionDecideWhatToWrite(GetParam());
EXPECT_CALL(*send_algorithm_, HasReliableBandwidthEstimate())
.Times(AnyNumber());
@@ -210,53 +208,31 @@ class QuicSentPacketManagerTest : public QuicTestWithParam<bool> {
uint64_t new_packet_number,
TransmissionType transmission_type) {
bool is_lost = false;
- if (manager_.session_decides_what_to_write()) {
- if (transmission_type == HANDSHAKE_RETRANSMISSION ||
- transmission_type == TLP_RETRANSMISSION ||
- transmission_type == RTO_RETRANSMISSION ||
- transmission_type == PROBING_RETRANSMISSION) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(WithArgs<1>(
- Invoke([this, new_packet_number](TransmissionType type) {
- RetransmitDataPacket(new_packet_number, type);
- })));
- } else {
- EXPECT_CALL(notifier_, OnFrameLost(_)).Times(1);
- is_lost = true;
- }
+ if (transmission_type == HANDSHAKE_RETRANSMISSION ||
+ transmission_type == TLP_RETRANSMISSION ||
+ transmission_type == RTO_RETRANSMISSION ||
+ transmission_type == PROBING_RETRANSMISSION) {
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(
+ Invoke([this, new_packet_number](TransmissionType type) {
+ RetransmitDataPacket(new_packet_number, type);
+ })));
+ } else {
+ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(1);
+ is_lost = true;
}
QuicSentPacketManagerPeer::MarkForRetransmission(
&manager_, old_packet_number, transmission_type);
- if (manager_.session_decides_what_to_write()) {
- if (!is_lost) {
- return;
- }
- EXPECT_CALL(
- *send_algorithm_,
- OnPacketSent(_, BytesInFlight(), QuicPacketNumber(new_packet_number),
- kDefaultLength, HAS_RETRANSMITTABLE_DATA));
- SerializedPacket packet(CreatePacket(new_packet_number, true));
- manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(),
- transmission_type, HAS_RETRANSMITTABLE_DATA);
+ if (!is_lost) {
return;
}
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
- QuicPendingRetransmission next_retransmission =
- manager_.NextPendingRetransmission();
- EXPECT_EQ(QuicPacketNumber(old_packet_number),
- next_retransmission.packet_number);
- EXPECT_EQ(transmission_type, next_retransmission.transmission_type);
-
EXPECT_CALL(
*send_algorithm_,
OnPacketSent(_, BytesInFlight(), QuicPacketNumber(new_packet_number),
kDefaultLength, HAS_RETRANSMITTABLE_DATA));
- SerializedPacket packet(CreatePacket(new_packet_number, false));
- manager_.OnPacketSent(&packet, QuicPacketNumber(old_packet_number),
- clock_.Now(), transmission_type,
+ SerializedPacket packet(CreatePacket(new_packet_number, true));
+ manager_.OnPacketSent(&packet, clock_.Now(), transmission_type,
HAS_RETRANSMITTABLE_DATA);
- EXPECT_TRUE(QuicSentPacketManagerPeer::IsRetransmission(&manager_,
- new_packet_number));
}
SerializedPacket CreateDataPacket(uint64_t packet_number) {
@@ -293,8 +269,8 @@ class QuicSentPacketManagerTest : public QuicTestWithParam<bool> {
QuicPacketNumber(packet_number), _, _));
SerializedPacket packet(CreateDataPacket(packet_number));
packet.encryption_level = encryption_level;
- manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ manager_.OnPacketSent(&packet, clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA);
}
void SendPingPacket(uint64_t packet_number,
@@ -304,8 +280,8 @@ class QuicSentPacketManagerTest : public QuicTestWithParam<bool> {
QuicPacketNumber(packet_number), _, _));
SerializedPacket packet(CreatePingPacket(packet_number));
packet.encryption_level = encryption_level;
- manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ manager_.OnPacketSent(&packet, clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA);
}
void SendCryptoPacket(uint64_t packet_number) {
@@ -317,12 +293,9 @@ class QuicSentPacketManagerTest : public QuicTestWithParam<bool> {
packet.retransmittable_frames.push_back(
QuicFrame(QuicStreamFrame(1, false, 0, QuicStringPiece())));
packet.has_crypto_handshake = IS_HANDSHAKE;
- manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, HasUnackedCryptoData())
- .WillRepeatedly(Return(true));
- }
+ manager_.OnPacketSent(&packet, clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA);
+ EXPECT_CALL(notifier_, HasUnackedCryptoData()).WillRepeatedly(Return(true));
}
void SendAckPacket(uint64_t packet_number, uint64_t largest_acked) {
@@ -339,27 +312,11 @@ class QuicSentPacketManagerTest : public QuicTestWithParam<bool> {
SerializedPacket packet(CreatePacket(packet_number, false));
packet.largest_acked = QuicPacketNumber(largest_acked);
packet.encryption_level = level;
- manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(),
- NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA);
- }
-
- // Based on QuicConnection's WritePendingRetransmissions.
- void RetransmitNextPacket(uint64_t retransmission_packet_number) {
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
- EXPECT_CALL(
- *send_algorithm_,
- OnPacketSent(_, _, QuicPacketNumber(retransmission_packet_number),
- kDefaultLength, HAS_RETRANSMITTABLE_DATA));
- const QuicPendingRetransmission pending =
- manager_.NextPendingRetransmission();
- SerializedPacket packet(CreatePacket(retransmission_packet_number, false));
- manager_.OnPacketSent(&packet, pending.packet_number, clock_.Now(),
- pending.transmission_type, HAS_RETRANSMITTABLE_DATA);
+ manager_.OnPacketSent(&packet, clock_.Now(), NOT_RETRANSMISSION,
+ NO_RETRANSMITTABLE_DATA);
}
void EnablePto(QuicTag tag) {
- SetQuicReloadableFlag(quic_fix_rto_retransmission3, true);
- manager_.SetSessionDecideWhatToWrite(true);
SetQuicReloadableFlag(quic_enable_pto, true);
QuicConfig config;
QuicTagVector options;
@@ -379,12 +336,7 @@ class QuicSentPacketManagerTest : public QuicTestWithParam<bool> {
StrictMock<MockSessionNotifier> notifier_;
};
-INSTANTIATE_TEST_SUITE_P(Tests,
- QuicSentPacketManagerTest,
- ::testing::Bool(),
- ::testing::PrintToStringParamName());
-
-TEST_P(QuicSentPacketManagerTest, IsUnacked) {
+TEST_F(QuicSentPacketManagerTest, IsUnacked) {
VerifyUnackedPackets(nullptr, 0);
SendDataPacket(1);
@@ -395,23 +347,18 @@ TEST_P(QuicSentPacketManagerTest, IsUnacked) {
QUIC_ARRAYSIZE(retransmittable));
}
-TEST_P(QuicSentPacketManagerTest, IsUnAckedRetransmit) {
+TEST_F(QuicSentPacketManagerTest, IsUnAckedRetransmit) {
SendDataPacket(1);
RetransmitAndSendPacket(1, 2);
EXPECT_TRUE(QuicSentPacketManagerPeer::IsRetransmission(&manager_, 2));
uint64_t unacked[] = {1, 2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- std::vector<uint64_t> retransmittable;
- if (manager_.session_decides_what_to_write()) {
- retransmittable = {1, 2};
- } else {
- retransmittable = {2};
- }
+ std::vector<uint64_t> retransmittable = {1, 2};
VerifyRetransmittablePackets(&retransmittable[0], retransmittable.size());
}
-TEST_P(QuicSentPacketManagerTest, RetransmitThenAck) {
+TEST_F(QuicSentPacketManagerTest, RetransmitThenAck) {
SendDataPacket(1);
RetransmitAndSendPacket(1, 2);
@@ -423,9 +370,7 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAck) {
EXPECT_EQ(PACKETS_NEWLY_ACKED,
manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
ENCRYPTION_INITIAL));
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
- }
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
// Packet 1 is unacked, pending, but not retransmittable.
uint64_t unacked[] = {1};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
@@ -433,21 +378,13 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAck) {
VerifyRetransmittablePackets(nullptr, 0);
}
-TEST_P(QuicSentPacketManagerTest, RetransmitThenAckBeforeSend) {
+TEST_F(QuicSentPacketManagerTest, RetransmitThenAckBeforeSend) {
SendDataPacket(1);
- if (manager_.session_decides_what_to_write()) {
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
- RetransmitDataPacket(2, type);
- })));
- }
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(2, type); })));
QuicSentPacketManagerPeer::MarkForRetransmission(&manager_, 1,
TLP_RETRANSMISSION);
- if (!manager_.session_decides_what_to_write()) {
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
- }
// Ack 1.
ExpectAck(1);
manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(),
@@ -457,40 +394,21 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAckBeforeSend) {
manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
ENCRYPTION_INITIAL));
- // There should no longer be a pending retransmission.
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
-
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
- uint64_t unacked[] = {2};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- // We do not know packet 2 is a spurious retransmission until it gets acked.
- } else {
- // No unacked packets remain.
- VerifyUnackedPackets(nullptr, 0);
- }
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
+ uint64_t unacked[] = {2};
+ VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ // We do not know packet 2 is a spurious retransmission until it gets acked.
VerifyRetransmittablePackets(nullptr, 0);
EXPECT_EQ(0u, stats_.packets_spuriously_retransmitted);
}
-TEST_P(QuicSentPacketManagerTest, RetransmitThenStopRetransmittingBeforeSend) {
+TEST_F(QuicSentPacketManagerTest, RetransmitThenStopRetransmittingBeforeSend) {
SendDataPacket(1);
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _));
QuicSentPacketManagerPeer::MarkForRetransmission(&manager_, 1,
TLP_RETRANSMISSION);
- if (!manager_.session_decides_what_to_write()) {
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
- }
- manager_.CancelRetransmissionsForStream(kStreamId);
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
- }
-
- // There should no longer be a pending retransmission.
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
uint64_t unacked[] = {1};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
@@ -498,7 +416,7 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenStopRetransmittingBeforeSend) {
EXPECT_EQ(0u, stats_.packets_spuriously_retransmitted);
}
-TEST_P(QuicSentPacketManagerTest, RetransmitThenAckPrevious) {
+TEST_F(QuicSentPacketManagerTest, RetransmitThenAckPrevious) {
SendDataPacket(1);
RetransmitAndSendPacket(1, 2);
QuicTime::Delta rtt = QuicTime::Delta::FromMilliseconds(15);
@@ -512,30 +430,26 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAckPrevious) {
EXPECT_EQ(PACKETS_NEWLY_ACKED,
manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
ENCRYPTION_INITIAL));
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
- }
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
// 2 remains unacked, but no packets have retransmittable data.
uint64_t unacked[] = {2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
EXPECT_TRUE(manager_.HasInFlightPackets());
VerifyRetransmittablePackets(nullptr, 0);
- if (manager_.session_decides_what_to_write()) {
- // Ack 2 causes 2 be considered as spurious retransmission.
- EXPECT_CALL(notifier_, OnFrameAcked(_, _, _)).WillOnce(Return(false));
- ExpectAck(2);
- manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
- clock_.Now());
- manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(3));
- EXPECT_EQ(PACKETS_NEWLY_ACKED,
- manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(2),
- ENCRYPTION_INITIAL));
- }
+ // Ack 2 causes 2 be considered as spurious retransmission.
+ EXPECT_CALL(notifier_, OnFrameAcked(_, _, _)).WillOnce(Return(false));
+ ExpectAck(2);
+ manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(3));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(2),
+ ENCRYPTION_INITIAL));
EXPECT_EQ(1u, stats_.packets_spuriously_retransmitted);
}
-TEST_P(QuicSentPacketManagerTest, RetransmitThenAckPreviousThenNackRetransmit) {
+TEST_F(QuicSentPacketManagerTest, RetransmitThenAckPreviousThenNackRetransmit) {
SendDataPacket(1);
RetransmitAndSendPacket(1, 2);
QuicTime::Delta rtt = QuicTime::Delta::FromMilliseconds(15);
@@ -575,13 +489,11 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAckPreviousThenNackRetransmit) {
ENCRYPTION_INITIAL));
ExpectAckAndLoss(true, 5, 2);
- if (manager_.session_decides_what_to_write()) {
- // Frames in all packets are acked.
- EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
- // Notify session that stream frame in packet 2 gets lost although it is
- // not outstanding.
- EXPECT_CALL(notifier_, OnFrameLost(_)).Times(1);
- }
+ // Frames in all packets are acked.
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
+ // Notify session that stream frame in packet 2 gets lost although it is
+ // not outstanding.
+ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(1);
manager_.OnAckFrameStart(QuicPacketNumber(5), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(6));
@@ -590,13 +502,8 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAckPreviousThenNackRetransmit) {
manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(4),
ENCRYPTION_INITIAL));
- if (manager_.session_decides_what_to_write()) {
- uint64_t unacked[] = {2};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- } else {
- // No packets remain unacked.
- VerifyUnackedPackets(nullptr, 0);
- }
+ uint64_t unacked[] = {2};
+ VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
EXPECT_FALSE(manager_.HasInFlightPackets());
VerifyRetransmittablePackets(nullptr, 0);
@@ -605,7 +512,7 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAckPreviousThenNackRetransmit) {
EXPECT_EQ(QuicTime::Zero(), manager_.GetRetransmissionTime());
}
-TEST_P(QuicSentPacketManagerTest,
+TEST_F(QuicSentPacketManagerTest,
DISABLED_RetransmitTwiceThenAckPreviousBeforeSend) {
SendDataPacket(1);
RetransmitAndSendPacket(1, 2);
@@ -614,7 +521,6 @@ TEST_P(QuicSentPacketManagerTest,
EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
manager_.OnRetransmissionTimeout();
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
// Ack 1 but not 2, before 2 is able to be sent.
// Since 1 has been retransmitted, it has already been lost, and so the
@@ -639,17 +545,11 @@ TEST_P(QuicSentPacketManagerTest,
EXPECT_EQ(QuicTime::Zero(), manager_.GetRetransmissionTime());
}
-TEST_P(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
+TEST_F(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
StrictMock<MockDebugDelegate> debug_delegate;
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(debug_delegate, OnSpuriousPacketRetransmission(
- TLP_RETRANSMISSION, kDefaultLength))
- .Times(1);
- } else {
- EXPECT_CALL(debug_delegate, OnSpuriousPacketRetransmission(
- TLP_RETRANSMISSION, kDefaultLength))
- .Times(2);
- }
+ EXPECT_CALL(debug_delegate, OnSpuriousPacketRetransmission(TLP_RETRANSMISSION,
+ kDefaultLength))
+ .Times(1);
manager_.SetDebugDelegate(&debug_delegate);
SendDataPacket(1);
@@ -666,12 +566,10 @@ TEST_P(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
EXPECT_EQ(PACKETS_NEWLY_ACKED,
manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
ENCRYPTION_INITIAL));
- if (manager_.session_decides_what_to_write()) {
- // Frames in packets 2 and 3 are acked.
- EXPECT_CALL(notifier_, IsFrameOutstanding(_))
- .Times(2)
- .WillRepeatedly(Return(false));
- }
+ // Frames in packets 2 and 3 are acked.
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_))
+ .Times(2)
+ .WillRepeatedly(Return(false));
// 2 and 3 remain unacked, but no packets have retransmittable data.
uint64_t unacked[] = {2, 3};
@@ -681,12 +579,10 @@ TEST_P(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
// Ensure packet 2 is lost when 4 is sent and 3 and 4 are acked.
SendDataPacket(4);
- if (manager_.session_decides_what_to_write()) {
- // No new data gets acked in packet 3.
- EXPECT_CALL(notifier_, OnFrameAcked(_, _, _))
- .WillOnce(Return(false))
- .WillRepeatedly(Return(true));
- }
+ // No new data gets acked in packet 3.
+ EXPECT_CALL(notifier_, OnFrameAcked(_, _, _))
+ .WillOnce(Return(false))
+ .WillRepeatedly(Return(true));
uint64_t acked[] = {3, 4};
ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
manager_.OnAckFrameStart(QuicPacketNumber(4), QuicTime::Delta::Infinite(),
@@ -705,13 +601,11 @@ TEST_P(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
ExpectAckAndLoss(true, 5, 2);
EXPECT_CALL(debug_delegate,
OnPacketLoss(QuicPacketNumber(2), LOSS_RETRANSMISSION, _));
- if (manager_.session_decides_what_to_write()) {
- // Frames in all packets are acked.
- EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
- // Notify session that stream frame in packet 2 gets lost although it is
- // not outstanding.
- EXPECT_CALL(notifier_, OnFrameLost(_)).Times(1);
- }
+ // Frames in all packets are acked.
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
+ // Notify session that stream frame in packet 2 gets lost although it is
+ // not outstanding.
+ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(1);
manager_.OnAckFrameStart(QuicPacketNumber(5), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(6));
@@ -720,23 +614,15 @@ TEST_P(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(3),
ENCRYPTION_INITIAL));
- if (manager_.session_decides_what_to_write()) {
- uint64_t unacked[] = {2};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- } else {
- VerifyUnackedPackets(nullptr, 0);
- }
+ uint64_t unacked3[] = {2};
+ VerifyUnackedPackets(unacked3, QUIC_ARRAYSIZE(unacked3));
EXPECT_FALSE(manager_.HasInFlightPackets());
- if (manager_.session_decides_what_to_write()) {
- // Spurious retransmission is detected when packet 3 gets acked. We cannot
- // know packet 2 is a spurious until it gets acked.
- EXPECT_EQ(1u, stats_.packets_spuriously_retransmitted);
- } else {
- EXPECT_EQ(2u, stats_.packets_spuriously_retransmitted);
- }
+ // Spurious retransmission is detected when packet 3 gets acked. We cannot
+ // know packet 2 is a spurious until it gets acked.
+ EXPECT_EQ(1u, stats_.packets_spuriously_retransmitted);
}
-TEST_P(QuicSentPacketManagerTest, AckOriginalTransmission) {
+TEST_F(QuicSentPacketManagerTest, AckOriginalTransmission) {
auto loss_algorithm = std::make_unique<MockLossAlgorithm>();
QuicSentPacketManagerPeer::SetLossAlgorithm(&manager_, loss_algorithm.get());
@@ -777,15 +663,9 @@ TEST_P(QuicSentPacketManagerTest, AckOriginalTransmission) {
uint64_t acked[] = {3};
ExpectAcksAndLosses(false, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _, _));
- if (GetQuicReloadableFlag(quic_detect_spurious_loss) &&
- manager_.session_decides_what_to_write()) {
- EXPECT_CALL(*loss_algorithm,
- SpuriousLossDetected(_, _, _, QuicPacketNumber(3),
- QuicPacketNumber(4)));
- } else {
- EXPECT_CALL(*loss_algorithm,
- SpuriousRetransmitDetected(_, _, _, QuicPacketNumber(5)));
- }
+ EXPECT_CALL(*loss_algorithm,
+ SpuriousLossDetected(_, _, _, QuicPacketNumber(3),
+ QuicPacketNumber(4)));
manager_.OnAckFrameStart(QuicPacketNumber(4), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(5));
@@ -793,34 +673,32 @@ TEST_P(QuicSentPacketManagerTest, AckOriginalTransmission) {
EXPECT_EQ(PACKETS_NEWLY_ACKED,
manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(3),
ENCRYPTION_INITIAL));
- if (manager_.session_decides_what_to_write()) {
- // Ack 3 will not cause 5 be considered as a spurious retransmission. Ack
- // 5 will cause 5 be considered as a spurious retransmission as no new
- // data gets acked.
- ExpectAck(5);
- EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _, _));
- EXPECT_CALL(notifier_, OnFrameAcked(_, _, _)).WillOnce(Return(false));
- manager_.OnAckFrameStart(QuicPacketNumber(5), QuicTime::Delta::Infinite(),
- clock_.Now());
- manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(6));
- manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
- EXPECT_EQ(PACKETS_NEWLY_ACKED,
- manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(4),
- ENCRYPTION_INITIAL));
- }
+ // Ack 3 will not cause 5 be considered as a spurious retransmission. Ack
+ // 5 will cause 5 be considered as a spurious retransmission as no new
+ // data gets acked.
+ ExpectAck(5);
+ EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _, _));
+ EXPECT_CALL(notifier_, OnFrameAcked(_, _, _)).WillOnce(Return(false));
+ manager_.OnAckFrameStart(QuicPacketNumber(5), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(6));
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(4),
+ ENCRYPTION_INITIAL));
}
}
-TEST_P(QuicSentPacketManagerTest, GetLeastUnacked) {
+TEST_F(QuicSentPacketManagerTest, GetLeastUnacked) {
EXPECT_EQ(QuicPacketNumber(1u), manager_.GetLeastUnacked());
}
-TEST_P(QuicSentPacketManagerTest, GetLeastUnackedUnacked) {
+TEST_F(QuicSentPacketManagerTest, GetLeastUnackedUnacked) {
SendDataPacket(1);
EXPECT_EQ(QuicPacketNumber(1u), manager_.GetLeastUnacked());
}
-TEST_P(QuicSentPacketManagerTest, AckAckAndUpdateRtt) {
+TEST_F(QuicSentPacketManagerTest, AckAckAndUpdateRtt) {
EXPECT_FALSE(manager_.largest_packet_peer_knows_is_acked().IsInitialized());
SendDataPacket(1);
SendAckPacket(2, 1);
@@ -851,7 +729,7 @@ TEST_P(QuicSentPacketManagerTest, AckAckAndUpdateRtt) {
manager_.largest_packet_peer_knows_is_acked());
}
-TEST_P(QuicSentPacketManagerTest, Rtt) {
+TEST_F(QuicSentPacketManagerTest, Rtt) {
QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(20);
SendDataPacket(1);
clock_.AdvanceTime(expected_rtt);
@@ -866,7 +744,7 @@ TEST_P(QuicSentPacketManagerTest, Rtt) {
EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
}
-TEST_P(QuicSentPacketManagerTest, RttWithInvalidDelta) {
+TEST_F(QuicSentPacketManagerTest, RttWithInvalidDelta) {
// Expect that the RTT is equal to the local time elapsed, since the
// ack_delay_time is larger than the local time elapsed
// and is hence invalid.
@@ -884,7 +762,7 @@ TEST_P(QuicSentPacketManagerTest, RttWithInvalidDelta) {
EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
}
-TEST_P(QuicSentPacketManagerTest, RttWithInfiniteDelta) {
+TEST_F(QuicSentPacketManagerTest, RttWithInfiniteDelta) {
// Expect that the RTT is equal to the local time elapsed, since the
// ack_delay_time is infinite, and is hence invalid.
QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10);
@@ -901,7 +779,7 @@ TEST_P(QuicSentPacketManagerTest, RttWithInfiniteDelta) {
EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
}
-TEST_P(QuicSentPacketManagerTest, RttZeroDelta) {
+TEST_F(QuicSentPacketManagerTest, RttZeroDelta) {
// Expect that the RTT is the time between send and receive since the
// ack_delay_time is zero.
QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10);
@@ -918,7 +796,7 @@ TEST_P(QuicSentPacketManagerTest, RttZeroDelta) {
EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
}
-TEST_P(QuicSentPacketManagerTest, TailLossProbeTimeout) {
+TEST_F(QuicSentPacketManagerTest, TailLossProbeTimeout) {
QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2);
// Send 1 packet.
@@ -927,36 +805,20 @@ TEST_P(QuicSentPacketManagerTest, TailLossProbeTimeout) {
// The first tail loss probe retransmits 1 packet.
manager_.OnRetransmissionTimeout();
EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(WithArgs<1>(Invoke(
- [this](TransmissionType type) { RetransmitDataPacket(2, type); })));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(2, type); })));
manager_.MaybeRetransmitTailLossProbe();
- if (!manager_.session_decides_what_to_write()) {
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
- RetransmitNextPacket(2);
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- }
// The second tail loss probe retransmits 1 packet.
manager_.OnRetransmissionTimeout();
EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(WithArgs<1>(Invoke(
- [this](TransmissionType type) { RetransmitDataPacket(3, type); })));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(3, type); })));
manager_.MaybeRetransmitTailLossProbe();
- if (!manager_.session_decides_what_to_write()) {
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
- RetransmitNextPacket(3);
- }
EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false));
EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now()));
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
// Ack the third and ensure the first two are still pending.
ExpectAck(3);
@@ -977,13 +839,11 @@ TEST_P(QuicSentPacketManagerTest, TailLossProbeTimeout) {
uint64_t lost[] = {1, 2};
ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), lost,
QUIC_ARRAYSIZE(lost));
- if (manager_.session_decides_what_to_write()) {
- // Frames in all packets are acked.
- EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
- // Notify session that stream frame in packets 1 and 2 get lost although
- // they are not outstanding.
- EXPECT_CALL(notifier_, OnFrameLost(_)).Times(2);
- }
+ // Frames in all packets are acked.
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
+ // Notify session that stream frame in packets 1 and 2 get lost although
+ // they are not outstanding.
+ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(2);
manager_.OnAckFrameStart(QuicPacketNumber(5), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(6));
@@ -991,13 +851,12 @@ TEST_P(QuicSentPacketManagerTest, TailLossProbeTimeout) {
manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(2),
ENCRYPTION_INITIAL));
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
EXPECT_FALSE(manager_.HasInFlightPackets());
EXPECT_EQ(2u, stats_.tlp_count);
EXPECT_EQ(0u, stats_.rto_count);
}
-TEST_P(QuicSentPacketManagerTest, TailLossProbeThenRTO) {
+TEST_F(QuicSentPacketManagerTest, TailLossProbeThenRTO) {
QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2);
// Send 100 packets.
@@ -1012,38 +871,21 @@ TEST_P(QuicSentPacketManagerTest, TailLossProbeThenRTO) {
// The first tail loss probe retransmits 1 packet.
manager_.OnRetransmissionTimeout();
EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
- RetransmitDataPacket(101, type);
- })));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(101, type); })));
manager_.MaybeRetransmitTailLossProbe();
- if (!manager_.session_decides_what_to_write()) {
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
- RetransmitNextPacket(101);
- }
EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false));
EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now()));
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
clock_.AdvanceTime(manager_.GetRetransmissionTime() - clock_.Now());
// The second tail loss probe retransmits 1 packet.
manager_.OnRetransmissionTimeout();
EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
- RetransmitDataPacket(102, type);
- })));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(102, type); })));
EXPECT_TRUE(manager_.MaybeRetransmitTailLossProbe());
- if (!manager_.session_decides_what_to_write()) {
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
- RetransmitNextPacket(102);
- }
EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false));
EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now()));
@@ -1055,43 +897,29 @@ TEST_P(QuicSentPacketManagerTest, TailLossProbeThenRTO) {
// Advance the time enough to ensure all packets are RTO'd.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1000));
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .Times(2)
- .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
- RetransmitDataPacket(103, type);
- })))
- .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
- RetransmitDataPacket(104, type);
- })));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .Times(2)
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(103, type); })))
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(104, type); })));
manager_.OnRetransmissionTimeout();
EXPECT_EQ(2u, stats_.tlp_count);
EXPECT_EQ(1u, stats_.rto_count);
- if (manager_.session_decides_what_to_write()) {
- // There are 2 RTO retransmissions.
- EXPECT_EQ(104 * kDefaultLength, manager_.GetBytesInFlight());
- }
- if (!manager_.session_decides_what_to_write()) {
- // Send and Ack the RTO and ensure OnRetransmissionTimeout is called.
- EXPECT_EQ(102 * kDefaultLength, manager_.GetBytesInFlight());
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
- RetransmitNextPacket(103);
- }
+ // There are 2 RTO retransmissions.
+ EXPECT_EQ(104 * kDefaultLength, manager_.GetBytesInFlight());
QuicPacketNumber largest_acked = QuicPacketNumber(103);
EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
EXPECT_CALL(*send_algorithm_,
OnCongestionEvent(
true, _, _, Pointwise(PacketNumberEq(), {largest_acked}), _));
EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
- if (manager_.session_decides_what_to_write()) {
- // Although frames in packet 3 gets acked, it would be kept for another
- // RTT.
- EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(true));
- // Packets [1, 102] are lost, although stream frame in packet 3 is not
- // outstanding.
- EXPECT_CALL(notifier_, OnFrameLost(_)).Times(102);
- }
+ // Although frames in packet 3 gets acked, it would be kept for another
+ // RTT.
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(true));
+ // Packets [1, 102] are lost, although stream frame in packet 3 is not
+ // outstanding.
+ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(102);
manager_.OnAckFrameStart(QuicPacketNumber(103), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(103), QuicPacketNumber(104));
@@ -1099,15 +927,11 @@ TEST_P(QuicSentPacketManagerTest, TailLossProbeThenRTO) {
manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
ENCRYPTION_INITIAL));
// All packets before 103 should be lost.
- if (manager_.session_decides_what_to_write()) {
- // Packet 104 is still in flight.
- EXPECT_EQ(1000u, manager_.GetBytesInFlight());
- } else {
- EXPECT_EQ(0u, manager_.GetBytesInFlight());
- }
+ // Packet 104 is still in flight.
+ EXPECT_EQ(1000u, manager_.GetBytesInFlight());
}
-TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeout) {
+TEST_F(QuicSentPacketManagerTest, CryptoHandshakeTimeout) {
// Send 2 crypto packets and 3 data packets.
const size_t kNumSentCryptoPackets = 2;
for (size_t i = 1; i <= kNumSentCryptoPackets; ++i) {
@@ -1121,37 +945,21 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeout) {
EXPECT_EQ(5 * kDefaultLength, manager_.GetBytesInFlight());
// The first retransmits 2 packets.
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .Times(2)
- .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(6); }))
- .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(7); }));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .Times(2)
+ .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(6); }))
+ .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(7); }));
manager_.OnRetransmissionTimeout();
- if (!manager_.session_decides_what_to_write()) {
- EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
- RetransmitNextPacket(6);
- RetransmitNextPacket(7);
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- }
// Expect all 4 handshake packets to be in flight and 3 data packets.
EXPECT_EQ(7 * kDefaultLength, manager_.GetBytesInFlight());
EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
// The second retransmits 2 packets.
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .Times(2)
- .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(8); }))
- .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(9); }));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .Times(2)
+ .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(8); }))
+ .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(9); }));
manager_.OnRetransmissionTimeout();
- if (!manager_.session_decides_what_to_write()) {
- EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
- RetransmitNextPacket(8);
- RetransmitNextPacket(9);
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- }
EXPECT_EQ(9 * kDefaultLength, manager_.GetBytesInFlight());
EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
@@ -1162,13 +970,8 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeout) {
uint64_t lost[] = {1, 2, 6};
ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), lost,
QUIC_ARRAYSIZE(lost));
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, OnFrameLost(_)).Times(3);
- }
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, HasUnackedCryptoData())
- .WillRepeatedly(Return(false));
- }
+ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(3);
+ EXPECT_CALL(notifier_, HasUnackedCryptoData()).WillRepeatedly(Return(false));
manager_.OnAckFrameStart(QuicPacketNumber(9), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(8), QuicPacketNumber(10));
@@ -1180,7 +983,7 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeout) {
EXPECT_FALSE(manager_.HasUnackedCryptoPackets());
}
-TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeoutVersionNegotiation) {
+TEST_F(QuicSentPacketManagerTest, CryptoHandshakeTimeoutVersionNegotiation) {
// Send 2 crypto packets and 3 data packets.
const size_t kNumSentCryptoPackets = 2;
for (size_t i = 1; i <= kNumSentCryptoPackets; ++i) {
@@ -1192,51 +995,26 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeoutVersionNegotiation) {
}
EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .Times(2)
- .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(6); }))
- .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(7); }));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .Times(2)
+ .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(6); }))
+ .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(7); }));
manager_.OnRetransmissionTimeout();
- if (!manager_.session_decides_what_to_write()) {
- RetransmitNextPacket(6);
- RetransmitNextPacket(7);
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- }
EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
// Now act like a version negotiation packet arrived, which would cause all
// unacked packets to be retransmitted.
- if (manager_.session_decides_what_to_write()) {
- // Mark packets [1, 7] lost. And the frames in 6 and 7 are same as packets 1
- // and 2, respectively.
- EXPECT_CALL(notifier_, OnFrameLost(_)).Times(7);
- }
+ // Mark packets [1, 7] lost. And the frames in 6 and 7 are same as packets 1
+ // and 2, respectively.
+ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(7);
manager_.RetransmitUnackedPackets(ALL_UNACKED_RETRANSMISSION);
// Ensure the first two pending packets are the crypto retransmits.
- if (manager_.session_decides_what_to_write()) {
- RetransmitCryptoPacket(8);
- RetransmitCryptoPacket(9);
- RetransmitDataPacket(10, ALL_UNACKED_RETRANSMISSION);
- RetransmitDataPacket(11, ALL_UNACKED_RETRANSMISSION);
- RetransmitDataPacket(12, ALL_UNACKED_RETRANSMISSION);
- } else {
- ASSERT_TRUE(manager_.HasPendingRetransmissions());
- EXPECT_EQ(QuicPacketNumber(6u),
- manager_.NextPendingRetransmission().packet_number);
- RetransmitNextPacket(8);
- EXPECT_EQ(QuicPacketNumber(7u),
- manager_.NextPendingRetransmission().packet_number);
- RetransmitNextPacket(9);
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
- // Send 3 more data packets and ensure the least unacked is raised.
- RetransmitNextPacket(10);
- RetransmitNextPacket(11);
- RetransmitNextPacket(12);
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- }
+ RetransmitCryptoPacket(8);
+ RetransmitCryptoPacket(9);
+ RetransmitDataPacket(10, ALL_UNACKED_RETRANSMISSION);
+ RetransmitDataPacket(11, ALL_UNACKED_RETRANSMISSION);
+ RetransmitDataPacket(12, ALL_UNACKED_RETRANSMISSION);
EXPECT_EQ(QuicPacketNumber(1u), manager_.GetLeastUnacked());
// Least unacked isn't raised until an ack is received, so ack the
@@ -1249,47 +1027,31 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeoutVersionNegotiation) {
EXPECT_EQ(PACKETS_NEWLY_ACKED,
manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
ENCRYPTION_INITIAL));
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, HasUnackedCryptoData())
- .WillRepeatedly(Return(false));
- }
+ EXPECT_CALL(notifier_, HasUnackedCryptoData()).WillRepeatedly(Return(false));
EXPECT_EQ(QuicPacketNumber(10u), manager_.GetLeastUnacked());
}
-TEST_P(QuicSentPacketManagerTest, CryptoHandshakeSpuriousRetransmission) {
+TEST_F(QuicSentPacketManagerTest, CryptoHandshakeSpuriousRetransmission) {
// Send 1 crypto packet.
SendCryptoPacket(1);
EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
// Retransmit the crypto packet as 2.
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(2); }));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(2); }));
manager_.OnRetransmissionTimeout();
- if (!manager_.session_decides_what_to_write()) {
- RetransmitNextPacket(2);
- }
// Retransmit the crypto packet as 3.
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(3); }));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(3); }));
manager_.OnRetransmissionTimeout();
- if (!manager_.session_decides_what_to_write()) {
- RetransmitNextPacket(3);
- }
// Now ack the second crypto packet, and ensure the first gets removed, but
// the third does not.
uint64_t acked[] = {2};
ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, HasUnackedCryptoData())
- .WillRepeatedly(Return(false));
- EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
- }
+ EXPECT_CALL(notifier_, HasUnackedCryptoData()).WillRepeatedly(Return(false));
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(3));
@@ -1302,7 +1064,7 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeSpuriousRetransmission) {
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
}
-TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeoutUnsentDataPacket) {
+TEST_F(QuicSentPacketManagerTest, CryptoHandshakeTimeoutUnsentDataPacket) {
// Send 2 crypto packets and 1 data packet.
const size_t kNumSentCryptoPackets = 2;
for (size_t i = 1; i <= kNumSentCryptoPackets; ++i) {
@@ -1312,22 +1074,15 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeoutUnsentDataPacket) {
EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
// Retransmit 2 crypto packets, but not the serialized packet.
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .Times(2)
- .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(4); }))
- .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(5); }));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .Times(2)
+ .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(4); }))
+ .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(5); }));
manager_.OnRetransmissionTimeout();
- if (!manager_.session_decides_what_to_write()) {
- RetransmitNextPacket(4);
- RetransmitNextPacket(5);
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- }
EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
}
-TEST_P(QuicSentPacketManagerTest,
+TEST_F(QuicSentPacketManagerTest,
CryptoHandshakeRetransmissionThenRetransmitAll) {
// Send 1 crypto packet.
SendCryptoPacket(1);
@@ -1335,36 +1090,21 @@ TEST_P(QuicSentPacketManagerTest,
EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
// Retransmit the crypto packet as 2.
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(2); }));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(2); }));
manager_.OnRetransmissionTimeout();
- if (!manager_.session_decides_what_to_write()) {
- RetransmitNextPacket(2);
- }
// Now retransmit all the unacked packets, which occurs when there is a
// version negotiation.
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, OnFrameLost(_)).Times(2);
- }
+ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(2);
manager_.RetransmitUnackedPackets(ALL_UNACKED_RETRANSMISSION);
- if (manager_.session_decides_what_to_write()) {
- // Both packets 1 and 2 are unackable.
- EXPECT_FALSE(manager_.unacked_packets().IsUnacked(QuicPacketNumber(1)));
- EXPECT_FALSE(manager_.unacked_packets().IsUnacked(QuicPacketNumber(2)));
- } else {
- // Packet 2 is useful because it does not get retransmitted and still has
- // retransmittable frames.
- uint64_t unacked[] = {1, 2};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
- }
+ // Both packets 1 and 2 are unackable.
+ EXPECT_FALSE(manager_.unacked_packets().IsUnacked(QuicPacketNumber(1)));
+ EXPECT_FALSE(manager_.unacked_packets().IsUnacked(QuicPacketNumber(2)));
EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
EXPECT_FALSE(manager_.HasInFlightPackets());
}
-TEST_P(QuicSentPacketManagerTest,
+TEST_F(QuicSentPacketManagerTest,
CryptoHandshakeRetransmissionThenNeuterAndAck) {
// Send 1 crypto packet.
SendCryptoPacket(1);
@@ -1372,40 +1112,26 @@ TEST_P(QuicSentPacketManagerTest,
EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
// Retransmit the crypto packet as 2.
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(2); }));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(2); }));
manager_.OnRetransmissionTimeout();
- if (!manager_.session_decides_what_to_write()) {
- RetransmitNextPacket(2);
- }
EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
// Retransmit the crypto packet as 3.
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(3); }));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(3); }));
manager_.OnRetransmissionTimeout();
- if (!manager_.session_decides_what_to_write()) {
- RetransmitNextPacket(3);
- }
EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
// Now neuter all unacked unencrypted packets, which occurs when the
// connection goes forward secure.
+ EXPECT_CALL(notifier_, HasUnackedCryptoData()).WillRepeatedly(Return(false));
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
manager_.NeuterUnencryptedPackets();
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, HasUnackedCryptoData())
- .WillRepeatedly(Return(false));
- EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
- }
EXPECT_FALSE(manager_.HasUnackedCryptoPackets());
uint64_t unacked[] = {1, 2, 3};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(nullptr, 0);
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
EXPECT_FALSE(manager_.HasUnackedCryptoPackets());
EXPECT_FALSE(manager_.HasInFlightPackets());
@@ -1422,7 +1148,7 @@ TEST_P(QuicSentPacketManagerTest,
VerifyRetransmittablePackets(nullptr, 0);
}
-TEST_P(QuicSentPacketManagerTest, RetransmissionTimeout) {
+TEST_F(QuicSentPacketManagerTest, RetransmissionTimeout) {
StrictMock<MockDebugDelegate> debug_delegate;
manager_.SetDebugDelegate(&debug_delegate);
@@ -1433,27 +1159,14 @@ TEST_P(QuicSentPacketManagerTest, RetransmissionTimeout) {
}
EXPECT_FALSE(manager_.MaybeRetransmitTailLossProbe());
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .Times(2)
- .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
- RetransmitDataPacket(101, type);
- })))
- .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
- RetransmitDataPacket(102, type);
- })));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .Times(2)
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(101, type); })))
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(102, type); })));
manager_.OnRetransmissionTimeout();
- if (manager_.session_decides_what_to_write()) {
- EXPECT_EQ(102 * kDefaultLength, manager_.GetBytesInFlight());
- } else {
- ASSERT_TRUE(manager_.HasPendingRetransmissions());
- EXPECT_EQ(100 * kDefaultLength, manager_.GetBytesInFlight());
- RetransmitNextPacket(101);
- ASSERT_TRUE(manager_.HasPendingRetransmissions());
- RetransmitNextPacket(102);
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- }
+ EXPECT_EQ(102 * kDefaultLength, manager_.GetBytesInFlight());
// Ack a retransmission.
// Ensure no packets are lost.
@@ -1470,12 +1183,10 @@ TEST_P(QuicSentPacketManagerTest, RetransmissionTimeout) {
EXPECT_CALL(debug_delegate,
OnPacketLoss(QuicPacketNumber(i), LOSS_RETRANSMISSION, _));
}
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(true));
- // Packets [1, 99] are considered as lost, although stream frame in packet
- // 2 is not outstanding.
- EXPECT_CALL(notifier_, OnFrameLost(_)).Times(99);
- }
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(true));
+ // Packets [1, 99] are considered as lost, although stream frame in packet
+ // 2 is not outstanding.
+ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(99);
manager_.OnAckFrameStart(QuicPacketNumber(102), QuicTime::Delta::Zero(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(102), QuicPacketNumber(103));
@@ -1484,7 +1195,7 @@ TEST_P(QuicSentPacketManagerTest, RetransmissionTimeout) {
ENCRYPTION_INITIAL));
}
-TEST_P(QuicSentPacketManagerTest, RetransmissionTimeoutOnePacket) {
+TEST_F(QuicSentPacketManagerTest, RetransmissionTimeoutOnePacket) {
// Set the 1RTO connection option.
QuicConfig client_config;
QuicTagVector options;
@@ -1510,25 +1221,15 @@ TEST_P(QuicSentPacketManagerTest, RetransmissionTimeoutOnePacket) {
}
EXPECT_FALSE(manager_.MaybeRetransmitTailLossProbe());
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .Times(1)
- .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
- RetransmitDataPacket(101, type);
- })));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .Times(1)
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(101, type); })));
manager_.OnRetransmissionTimeout();
- if (manager_.session_decides_what_to_write()) {
- EXPECT_EQ(101 * kDefaultLength, manager_.GetBytesInFlight());
- } else {
- ASSERT_TRUE(manager_.HasPendingRetransmissions());
- EXPECT_EQ(100 * kDefaultLength, manager_.GetBytesInFlight());
- RetransmitNextPacket(101);
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- }
+ EXPECT_EQ(101 * kDefaultLength, manager_.GetBytesInFlight());
}
-TEST_P(QuicSentPacketManagerTest, NewRetransmissionTimeout) {
+TEST_F(QuicSentPacketManagerTest, NewRetransmissionTimeout) {
QuicConfig client_config;
QuicTagVector options;
options.push_back(kNRTO);
@@ -1551,26 +1252,14 @@ TEST_P(QuicSentPacketManagerTest, NewRetransmissionTimeout) {
}
EXPECT_FALSE(manager_.MaybeRetransmitTailLossProbe());
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .Times(2)
- .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
- RetransmitDataPacket(101, type);
- })))
- .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
- RetransmitDataPacket(102, type);
- })));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .Times(2)
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(101, type); })))
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(102, type); })));
manager_.OnRetransmissionTimeout();
- if (manager_.session_decides_what_to_write()) {
- EXPECT_EQ(102 * kDefaultLength, manager_.GetBytesInFlight());
- } else {
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
- EXPECT_EQ(100 * kDefaultLength, manager_.GetBytesInFlight());
- RetransmitNextPacket(101);
- RetransmitNextPacket(102);
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- }
+ EXPECT_EQ(102 * kDefaultLength, manager_.GetBytesInFlight());
// Ack a retransmission and expect no call to OnRetransmissionTimeout.
// This will include packets in the lost packet map.
@@ -1580,12 +1269,10 @@ TEST_P(QuicSentPacketManagerTest, NewRetransmissionTimeout) {
Pointwise(PacketNumberEq(), {largest_acked}),
/*lost_packets=*/Not(IsEmpty())));
EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(true));
- // Packets [1, 99] are considered as lost, although stream frame in packet
- // 2 is not outstanding.
- EXPECT_CALL(notifier_, OnFrameLost(_)).Times(99);
- }
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(true));
+ // Packets [1, 99] are considered as lost, although stream frame in packet
+ // 2 is not outstanding.
+ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(99);
manager_.OnAckFrameStart(QuicPacketNumber(102), QuicTime::Delta::Zero(),
clock_.Now());
manager_.OnAckRange(QuicPacketNumber(102), QuicPacketNumber(103));
@@ -1594,40 +1281,22 @@ TEST_P(QuicSentPacketManagerTest, NewRetransmissionTimeout) {
ENCRYPTION_INITIAL));
}
-TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckSecond) {
+TEST_F(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckSecond) {
// Send 1 packet.
SendDataPacket(1);
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(WithArgs<1>(Invoke(
- [this](TransmissionType type) { RetransmitDataPacket(2, type); })));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(2, type); })));
manager_.OnRetransmissionTimeout();
- if (manager_.session_decides_what_to_write()) {
- EXPECT_EQ(2 * kDefaultLength, manager_.GetBytesInFlight());
- } else {
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
- EXPECT_EQ(kDefaultLength, manager_.GetBytesInFlight());
- RetransmitNextPacket(2);
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- }
+ EXPECT_EQ(2 * kDefaultLength, manager_.GetBytesInFlight());
// Rto a second time.
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(WithArgs<1>(Invoke(
- [this](TransmissionType type) { RetransmitDataPacket(3, type); })));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(3, type); })));
manager_.OnRetransmissionTimeout();
- if (manager_.session_decides_what_to_write()) {
- EXPECT_EQ(3 * kDefaultLength, manager_.GetBytesInFlight());
- } else {
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
- EXPECT_EQ(2 * kDefaultLength, manager_.GetBytesInFlight());
- RetransmitNextPacket(3);
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- }
+ EXPECT_EQ(3 * kDefaultLength, manager_.GetBytesInFlight());
// Ack a retransmission and ensure OnRetransmissionTimeout is called.
EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
@@ -1643,40 +1312,22 @@ TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckSecond) {
EXPECT_EQ(2 * kDefaultLength, manager_.GetBytesInFlight());
}
-TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckFirst) {
+TEST_F(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckFirst) {
// Send 1 packet.
SendDataPacket(1);
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(WithArgs<1>(Invoke(
- [this](TransmissionType type) { RetransmitDataPacket(2, type); })));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(2, type); })));
manager_.OnRetransmissionTimeout();
- if (manager_.session_decides_what_to_write()) {
- EXPECT_EQ(2 * kDefaultLength, manager_.GetBytesInFlight());
- } else {
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
- EXPECT_EQ(kDefaultLength, manager_.GetBytesInFlight());
- RetransmitNextPacket(2);
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- }
+ EXPECT_EQ(2 * kDefaultLength, manager_.GetBytesInFlight());
// Rto a second time.
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(WithArgs<1>(Invoke(
- [this](TransmissionType type) { RetransmitDataPacket(3, type); })));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(3, type); })));
manager_.OnRetransmissionTimeout();
- if (manager_.session_decides_what_to_write()) {
- EXPECT_EQ(3 * kDefaultLength, manager_.GetBytesInFlight());
- } else {
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
- EXPECT_EQ(2 * kDefaultLength, manager_.GetBytesInFlight());
- RetransmitNextPacket(3);
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- }
+ EXPECT_EQ(3 * kDefaultLength, manager_.GetBytesInFlight());
// Ack a retransmission and ensure OnRetransmissionTimeout is called.
EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
@@ -1692,11 +1343,11 @@ TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckFirst) {
EXPECT_EQ(2 * kDefaultLength, manager_.GetBytesInFlight());
}
-TEST_P(QuicSentPacketManagerTest, GetTransmissionTime) {
+TEST_F(QuicSentPacketManagerTest, GetTransmissionTime) {
EXPECT_EQ(QuicTime::Zero(), manager_.GetRetransmissionTime());
}
-TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeCryptoHandshake) {
+TEST_F(QuicSentPacketManagerTest, GetTransmissionTimeCryptoHandshake) {
QuicTime crypto_packet_send_time = clock_.Now();
SendCryptoPacket(1);
@@ -1715,16 +1366,11 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeCryptoHandshake) {
// Retransmit the packet by invoking the retransmission timeout.
clock_.AdvanceTime(1.5 * srtt);
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(2); }));
- // When session decides what to write, crypto_packet_send_time gets updated.
- crypto_packet_send_time = clock_.Now();
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(2); }));
+ // When session decides what to write, crypto_packet_send_time gets updated.
+ crypto_packet_send_time = clock_.Now();
manager_.OnRetransmissionTimeout();
- if (!manager_.session_decides_what_to_write()) {
- RetransmitNextPacket(2);
- }
// The retransmission time should now be twice as far in the future.
expected_time = crypto_packet_send_time + srtt * 2 * 1.5;
@@ -1732,23 +1378,18 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeCryptoHandshake) {
// Retransmit the packet for the 2nd time.
clock_.AdvanceTime(2 * 1.5 * srtt);
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(3); }));
- // When session decides what to write, crypto_packet_send_time gets updated.
- crypto_packet_send_time = clock_.Now();
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(3); }));
+ // When session decides what to write, crypto_packet_send_time gets updated.
+ crypto_packet_send_time = clock_.Now();
manager_.OnRetransmissionTimeout();
- if (!manager_.session_decides_what_to_write()) {
- RetransmitNextPacket(3);
- }
// Verify exponential backoff of the retransmission timeout.
expected_time = crypto_packet_send_time + srtt * 4 * 1.5;
EXPECT_EQ(expected_time, manager_.GetRetransmissionTime());
}
-TEST_P(QuicSentPacketManagerTest,
+TEST_F(QuicSentPacketManagerTest,
GetConservativeTransmissionTimeCryptoHandshake) {
QuicConfig config;
QuicTagVector options;
@@ -1781,22 +1422,17 @@ TEST_P(QuicSentPacketManagerTest,
// Retransmit the packet by invoking the retransmission timeout.
clock_.AdvanceTime(2 * srtt);
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(2); }));
- crypto_packet_send_time = clock_.Now();
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(2); }));
+ crypto_packet_send_time = clock_.Now();
manager_.OnRetransmissionTimeout();
- if (!manager_.session_decides_what_to_write()) {
- RetransmitNextPacket(2);
- }
// The retransmission time should now be twice as far in the future.
expected_time = crypto_packet_send_time + srtt * 2 * 2;
EXPECT_EQ(expected_time, manager_.GetRetransmissionTime());
}
-TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeTailLossProbe) {
+TEST_F(QuicSentPacketManagerTest, GetTransmissionTimeTailLossProbe) {
QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2);
SendDataPacket(1);
SendDataPacket(2);
@@ -1818,30 +1454,18 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeTailLossProbe) {
clock_.AdvanceTime(expected_tlp_delay);
manager_.OnRetransmissionTimeout();
EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(WithArgs<1>(Invoke(
- [this](TransmissionType type) { RetransmitDataPacket(3, type); })));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(3, type); })));
EXPECT_TRUE(manager_.MaybeRetransmitTailLossProbe());
- if (!manager_.session_decides_what_to_write()) {
- EXPECT_TRUE(manager_.HasPendingRetransmissions());
- RetransmitNextPacket(3);
- }
EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false));
EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now()));
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
expected_time = clock_.Now() + expected_tlp_delay;
EXPECT_EQ(expected_time, manager_.GetRetransmissionTime());
}
-TEST_P(QuicSentPacketManagerTest, TLPRWithPendingStreamData) {
- if (!manager_.session_decides_what_to_write()) {
- return;
- }
-
+TEST_F(QuicSentPacketManagerTest, TLPRWithPendingStreamData) {
QuicConfig config;
QuicTagVector options;
@@ -1877,7 +1501,6 @@ TEST_P(QuicSentPacketManagerTest, TLPRWithPendingStreamData) {
clock_.AdvanceTime(expected_tlp_delay);
manager_.OnRetransmissionTimeout();
EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
EXPECT_CALL(notifier_, RetransmitFrames(_, _))
.WillOnce(WithArgs<1>(Invoke(
[this](TransmissionType type) { RetransmitDataPacket(3, type); })));
@@ -1885,7 +1508,6 @@ TEST_P(QuicSentPacketManagerTest, TLPRWithPendingStreamData) {
EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false));
EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now()));
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
// 2nd TLP.
expected_tlp_delay = 2 * srtt;
@@ -1893,11 +1515,7 @@ TEST_P(QuicSentPacketManagerTest, TLPRWithPendingStreamData) {
manager_.GetRetransmissionTime() - clock_.Now());
}
-TEST_P(QuicSentPacketManagerTest, TLPRWithoutPendingStreamData) {
- if (!manager_.session_decides_what_to_write()) {
- return;
- }
-
+TEST_F(QuicSentPacketManagerTest, TLPRWithoutPendingStreamData) {
QuicConfig config;
QuicTagVector options;
@@ -1932,14 +1550,12 @@ TEST_P(QuicSentPacketManagerTest, TLPRWithoutPendingStreamData) {
clock_.AdvanceTime(expected_tlp_delay);
manager_.OnRetransmissionTimeout();
EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
EXPECT_CALL(notifier_, RetransmitFrames(_, _))
.WillOnce(WithArgs<1>(Invoke(
[this](TransmissionType type) { RetransmitDataPacket(3, type); })));
EXPECT_TRUE(manager_.MaybeRetransmitTailLossProbe());
EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false));
EXPECT_EQ(QuicTime::Delta::Infinite(), manager_.TimeUntilSend(clock_.Now()));
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
// 2nd TLP.
expected_tlp_delay = 2 * srtt;
@@ -1947,7 +1563,7 @@ TEST_P(QuicSentPacketManagerTest, TLPRWithoutPendingStreamData) {
manager_.GetRetransmissionTime() - clock_.Now());
}
-TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeSpuriousRTO) {
+TEST_F(QuicSentPacketManagerTest, GetTransmissionTimeSpuriousRTO) {
RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
QuicTime::Delta::Zero(), QuicTime::Zero());
@@ -1964,24 +1580,15 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeSpuriousRTO) {
// Retransmit the packet by invoking the retransmission timeout.
clock_.AdvanceTime(expected_rto_delay);
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .Times(2)
- .WillOnce(WithArgs<1>(Invoke(
- [this](TransmissionType type) { RetransmitDataPacket(5, type); })))
- .WillOnce(WithArgs<1>(Invoke(
- [this](TransmissionType type) { RetransmitDataPacket(6, type); })));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .Times(2)
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(5, type); })))
+ .WillOnce(WithArgs<1>(Invoke(
+ [this](TransmissionType type) { RetransmitDataPacket(6, type); })));
manager_.OnRetransmissionTimeout();
- if (!manager_.session_decides_what_to_write()) {
- // All packets are still considered inflight.
- EXPECT_EQ(4 * kDefaultLength, manager_.GetBytesInFlight());
- RetransmitNextPacket(5);
- RetransmitNextPacket(6);
- }
// All previous packets are inflight, plus two rto retransmissions.
EXPECT_EQ(6 * kDefaultLength, manager_.GetBytesInFlight());
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
// The delay should double the second time.
expected_time = clock_.Now() + expected_rto_delay + expected_rto_delay;
@@ -1998,7 +1605,6 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeSpuriousRTO) {
EXPECT_EQ(PACKETS_NEWLY_ACKED,
manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
ENCRYPTION_INITIAL));
- EXPECT_FALSE(manager_.HasPendingRetransmissions());
EXPECT_EQ(5 * kDefaultLength, manager_.GetBytesInFlight());
// Wait 2RTTs from now for the RTO, since it's the max of the RTO time
@@ -2011,7 +1617,7 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeSpuriousRTO) {
EXPECT_EQ(expected_time, manager_.GetRetransmissionTime());
}
-TEST_P(QuicSentPacketManagerTest, GetTransmissionDelayMin) {
+TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayMin) {
SendDataPacket(1);
// Provide a 1ms RTT sample.
const_cast<RttStats*>(manager_.GetRttStats())
@@ -2027,20 +1633,15 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionDelayMin) {
EXPECT_EQ(delay,
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, i));
delay = delay + delay;
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(WithArgs<1>(Invoke([this, i](TransmissionType type) {
- RetransmitDataPacket(i + 2, type);
- })));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke([this, i](TransmissionType type) {
+ RetransmitDataPacket(i + 2, type);
+ })));
manager_.OnRetransmissionTimeout();
- if (!manager_.session_decides_what_to_write()) {
- RetransmitNextPacket(i + 2);
- }
}
}
-TEST_P(QuicSentPacketManagerTest, GetTransmissionDelayMax) {
+TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayMax) {
SendDataPacket(1);
// Provide a 60s RTT sample.
const_cast<RttStats*>(manager_.GetRttStats())
@@ -2053,7 +1654,7 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionDelayMax) {
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, 0));
}
-TEST_P(QuicSentPacketManagerTest, GetTransmissionDelayExponentialBackoff) {
+TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayExponentialBackoff) {
SendDataPacket(1);
QuicTime::Delta delay = QuicTime::Delta::FromMilliseconds(500);
@@ -2064,20 +1665,15 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionDelayExponentialBackoff) {
EXPECT_EQ(delay,
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, i));
delay = delay + delay;
- if (manager_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, RetransmitFrames(_, _))
- .WillOnce(WithArgs<1>(Invoke([this, i](TransmissionType type) {
- RetransmitDataPacket(i + 2, type);
- })));
- }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke([this, i](TransmissionType type) {
+ RetransmitDataPacket(i + 2, type);
+ })));
manager_.OnRetransmissionTimeout();
- if (!manager_.session_decides_what_to_write()) {
- RetransmitNextPacket(i + 2);
- }
}
}
-TEST_P(QuicSentPacketManagerTest, RetransmissionDelay) {
+TEST_F(QuicSentPacketManagerTest, RetransmissionDelay) {
RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
const int64_t kRttMs = 250;
const int64_t kDeviationMs = 5;
@@ -2115,7 +1711,7 @@ TEST_P(QuicSentPacketManagerTest, RetransmissionDelay) {
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, GetLossDelay) {
+TEST_F(QuicSentPacketManagerTest, GetLossDelay) {
auto loss_algorithm = std::make_unique<MockLossAlgorithm>();
QuicSentPacketManagerPeer::SetLossAlgorithm(&manager_, loss_algorithm.get());
@@ -2146,7 +1742,7 @@ TEST_P(QuicSentPacketManagerTest, GetLossDelay) {
manager_.OnRetransmissionTimeout();
}
-TEST_P(QuicSentPacketManagerTest, NegotiateTimeLossDetectionFromOptions) {
+TEST_F(QuicSentPacketManagerTest, NegotiateTimeLossDetectionFromOptions) {
EXPECT_EQ(kNack, QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
->GetLossDetectionType());
@@ -2162,7 +1758,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateTimeLossDetectionFromOptions) {
->GetLossDetectionType());
}
-TEST_P(QuicSentPacketManagerTest, NegotiateIetfLossDetectionFromOptions) {
+TEST_F(QuicSentPacketManagerTest, NegotiateIetfLossDetectionFromOptions) {
SetQuicReloadableFlag(quic_enable_ietf_loss_detection, true);
EXPECT_EQ(kNack, QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
->GetLossDetectionType());
@@ -2183,7 +1779,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateIetfLossDetectionFromOptions) {
QuicSentPacketManagerPeer::AdaptiveReorderingThresholdEnabled(&manager_));
}
-TEST_P(QuicSentPacketManagerTest,
+TEST_F(QuicSentPacketManagerTest,
NegotiateIetfLossDetectionOneFourthRttFromOptions) {
SetQuicReloadableFlag(quic_enable_ietf_loss_detection, true);
EXPECT_EQ(kNack, QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
@@ -2206,10 +1802,9 @@ TEST_P(QuicSentPacketManagerTest,
QuicSentPacketManagerPeer::AdaptiveReorderingThresholdEnabled(&manager_));
}
-TEST_P(QuicSentPacketManagerTest,
+TEST_F(QuicSentPacketManagerTest,
NegotiateIetfLossDetectionAdaptiveReorderingThreshold) {
SetQuicReloadableFlag(quic_enable_ietf_loss_detection, true);
- SetQuicReloadableFlag(quic_detect_spurious_loss, true);
EXPECT_EQ(kNack, QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
->GetLossDetectionType());
EXPECT_FALSE(
@@ -2231,10 +1826,9 @@ TEST_P(QuicSentPacketManagerTest,
QuicSentPacketManagerPeer::AdaptiveReorderingThresholdEnabled(&manager_));
}
-TEST_P(QuicSentPacketManagerTest,
+TEST_F(QuicSentPacketManagerTest,
NegotiateIetfLossDetectionAdaptiveReorderingThreshold2) {
SetQuicReloadableFlag(quic_enable_ietf_loss_detection, true);
- SetQuicReloadableFlag(quic_detect_spurious_loss, true);
EXPECT_EQ(kNack, QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
->GetLossDetectionType());
EXPECT_FALSE(
@@ -2257,7 +1851,36 @@ TEST_P(QuicSentPacketManagerTest,
QuicSentPacketManagerPeer::AdaptiveReorderingThresholdEnabled(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, NegotiateCongestionControlFromOptions) {
+TEST_F(QuicSentPacketManagerTest,
+ NegotiateIetfLossDetectionAdaptiveReorderingAndTimeThreshold) {
+ SetQuicReloadableFlag(quic_enable_ietf_loss_detection, true);
+ EXPECT_EQ(kNack, QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
+ ->GetLossDetectionType());
+ EXPECT_FALSE(
+ QuicSentPacketManagerPeer::AdaptiveReorderingThresholdEnabled(&manager_));
+ EXPECT_FALSE(
+ QuicSentPacketManagerPeer::AdaptiveTimeThresholdEnabled(&manager_));
+
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kILD4);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+
+ EXPECT_EQ(kIetfLossDetection,
+ QuicSentPacketManagerPeer::GetLossAlgorithm(&manager_)
+ ->GetLossDetectionType());
+ EXPECT_EQ(kDefaultLossDelayShift,
+ QuicSentPacketManagerPeer::GetReorderingShift(&manager_));
+ EXPECT_TRUE(
+ QuicSentPacketManagerPeer::AdaptiveReorderingThresholdEnabled(&manager_));
+ EXPECT_TRUE(
+ QuicSentPacketManagerPeer::AdaptiveTimeThresholdEnabled(&manager_));
+}
+
+TEST_F(QuicSentPacketManagerTest, NegotiateCongestionControlFromOptions) {
QuicConfig config;
QuicTagVector options;
@@ -2293,7 +1916,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateCongestionControlFromOptions) {
->GetCongestionControlType());
}
-TEST_P(QuicSentPacketManagerTest, NegotiateClientCongestionControlFromOptions) {
+TEST_F(QuicSentPacketManagerTest, NegotiateClientCongestionControlFromOptions) {
QuicConfig config;
QuicTagVector options;
@@ -2340,7 +1963,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateClientCongestionControlFromOptions) {
->GetCongestionControlType());
}
-TEST_P(QuicSentPacketManagerTest, NegotiateNoMinTLPFromOptionsAtServer) {
+TEST_F(QuicSentPacketManagerTest, NegotiateNoMinTLPFromOptionsAtServer) {
QuicConfig config;
QuicTagVector options;
@@ -2362,11 +1985,8 @@ TEST_P(QuicSentPacketManagerTest, NegotiateNoMinTLPFromOptionsAtServer) {
EXPECT_EQ(QuicTime::Delta::FromMicroseconds(100002),
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
- // Send two packets, and the TLP should be 2 us or 1ms.
- QuicTime::Delta expected_tlp_delay =
- GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)
- ? QuicTime::Delta::FromMilliseconds(1)
- : QuicTime::Delta::FromMicroseconds(2);
+ // Send two packets, and the TLP should be 1ms.
+ QuicTime::Delta expected_tlp_delay = QuicTime::Delta::FromMilliseconds(1);
SendDataPacket(1);
SendDataPacket(2);
EXPECT_EQ(expected_tlp_delay,
@@ -2375,7 +1995,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateNoMinTLPFromOptionsAtServer) {
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
}
-TEST_P(QuicSentPacketManagerTest, NegotiateNoMinTLPFromOptionsAtClient) {
+TEST_F(QuicSentPacketManagerTest, NegotiateNoMinTLPFromOptionsAtClient) {
QuicConfig client_config;
QuicTagVector options;
@@ -2397,11 +2017,8 @@ TEST_P(QuicSentPacketManagerTest, NegotiateNoMinTLPFromOptionsAtClient) {
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
EXPECT_EQ(QuicTime::Delta::FromMicroseconds(100002),
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
- // Send two packets, and the TLP should be 2 us or 1ms.
- QuicTime::Delta expected_tlp_delay =
- GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)
- ? QuicTime::Delta::FromMilliseconds(1)
- : QuicTime::Delta::FromMicroseconds(2);
+ // Send two packets, and the TLP should be 1ms.
+ QuicTime::Delta expected_tlp_delay = QuicTime::Delta::FromMilliseconds(1);
SendDataPacket(1);
SendDataPacket(2);
EXPECT_EQ(expected_tlp_delay,
@@ -2410,70 +2027,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateNoMinTLPFromOptionsAtClient) {
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
}
-TEST_P(QuicSentPacketManagerTest, NegotiateIETFTLPFromOptionsAtServer) {
- if (GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)) {
- return;
- }
- QuicConfig config;
- QuicTagVector options;
-
- options.push_back(kMAD4);
- QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
- EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
- EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
- manager_.SetFromConfig(config);
- // Provide an RTT measurement of 100ms.
- RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
- rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
- QuicTime::Delta::Zero(), QuicTime::Zero());
- // Expect 1.5x * SRTT + 0ms MAD
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(150),
- QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(150),
- QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
- // Expect 1.5x * SRTT + 50ms MAD
- rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(150),
- QuicTime::Delta::FromMilliseconds(50), QuicTime::Zero());
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100), rtt_stats->smoothed_rtt());
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200),
- QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200),
- QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
-}
-
-TEST_P(QuicSentPacketManagerTest, NegotiateIETFTLPFromOptionsAtClient) {
- if (GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)) {
- return;
- }
- QuicConfig client_config;
- QuicTagVector options;
-
- options.push_back(kMAD4);
- QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT);
- client_config.SetConnectionOptionsToSend(options);
- EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
- EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
- manager_.SetFromConfig(client_config);
- // Provide an RTT measurement of 100ms.
- RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
- rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
- QuicTime::Delta::Zero(), QuicTime::Zero());
- // Expect 1.5x * SRTT + 0ms MAD
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(150),
- QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(150),
- QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
- // Expect 1.5x * SRTT + 50ms MAD
- rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(150),
- QuicTime::Delta::FromMilliseconds(50), QuicTime::Zero());
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100), rtt_stats->smoothed_rtt());
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200),
- QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200),
- QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
-}
-
-TEST_P(QuicSentPacketManagerTest, NegotiateNoMinRTOFromOptionsAtServer) {
+TEST_F(QuicSentPacketManagerTest, NegotiateNoMinRTOFromOptionsAtServer) {
QuicConfig config;
QuicTagVector options;
@@ -2486,26 +2040,20 @@ TEST_P(QuicSentPacketManagerTest, NegotiateNoMinRTOFromOptionsAtServer) {
RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
rtt_stats->UpdateRtt(QuicTime::Delta::FromMicroseconds(1),
QuicTime::Delta::Zero(), QuicTime::Zero());
- QuicTime::Delta expected_rto_delay =
- GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)
- ? QuicTime::Delta::FromMilliseconds(1)
- : QuicTime::Delta::FromMicroseconds(1);
+ QuicTime::Delta expected_rto_delay = QuicTime::Delta::FromMilliseconds(1);
EXPECT_EQ(expected_rto_delay,
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
EXPECT_EQ(expected_rto_delay,
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, 0));
// The TLP with fewer than 2 packets outstanding includes 1/2 min RTO(0ms).
- QuicTime::Delta expected_tlp_delay =
- GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)
- ? QuicTime::Delta::FromMicroseconds(502)
- : QuicTime::Delta::FromMicroseconds(2);
+ QuicTime::Delta expected_tlp_delay = QuicTime::Delta::FromMicroseconds(502);
EXPECT_EQ(expected_tlp_delay,
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
EXPECT_EQ(expected_tlp_delay,
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
}
-TEST_P(QuicSentPacketManagerTest, NegotiateNoMinRTOFromOptionsAtClient) {
+TEST_F(QuicSentPacketManagerTest, NegotiateNoMinRTOFromOptionsAtClient) {
QuicConfig client_config;
QuicTagVector options;
@@ -2519,26 +2067,20 @@ TEST_P(QuicSentPacketManagerTest, NegotiateNoMinRTOFromOptionsAtClient) {
RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
rtt_stats->UpdateRtt(QuicTime::Delta::FromMicroseconds(1),
QuicTime::Delta::Zero(), QuicTime::Zero());
- QuicTime::Delta expected_rto_delay =
- GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)
- ? QuicTime::Delta::FromMilliseconds(1)
- : QuicTime::Delta::FromMicroseconds(1);
+ QuicTime::Delta expected_rto_delay = QuicTime::Delta::FromMilliseconds(1);
EXPECT_EQ(expected_rto_delay,
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
EXPECT_EQ(expected_rto_delay,
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, 0));
// The TLP with fewer than 2 packets outstanding includes 1/2 min RTO(0ms).
- QuicTime::Delta expected_tlp_delay =
- GetQuicReloadableFlag(quic_sent_packet_manager_cleanup)
- ? QuicTime::Delta::FromMicroseconds(502)
- : QuicTime::Delta::FromMicroseconds(2);
+ QuicTime::Delta expected_tlp_delay = QuicTime::Delta::FromMicroseconds(502);
EXPECT_EQ(expected_tlp_delay,
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
EXPECT_EQ(expected_tlp_delay,
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
}
-TEST_P(QuicSentPacketManagerTest, NegotiateNoTLPFromOptionsAtServer) {
+TEST_F(QuicSentPacketManagerTest, NegotiateNoTLPFromOptionsAtServer) {
QuicConfig config;
QuicTagVector options;
@@ -2550,7 +2092,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateNoTLPFromOptionsAtServer) {
EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetMaxTailLossProbes(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, NegotiateNoTLPFromOptionsAtClient) {
+TEST_F(QuicSentPacketManagerTest, NegotiateNoTLPFromOptionsAtClient) {
QuicConfig client_config;
QuicTagVector options;
@@ -2563,7 +2105,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateNoTLPFromOptionsAtClient) {
EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetMaxTailLossProbes(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, Negotiate1TLPFromOptionsAtServer) {
+TEST_F(QuicSentPacketManagerTest, Negotiate1TLPFromOptionsAtServer) {
QuicConfig config;
QuicTagVector options;
@@ -2575,7 +2117,7 @@ TEST_P(QuicSentPacketManagerTest, Negotiate1TLPFromOptionsAtServer) {
EXPECT_EQ(1u, QuicSentPacketManagerPeer::GetMaxTailLossProbes(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, Negotiate1TLPFromOptionsAtClient) {
+TEST_F(QuicSentPacketManagerTest, Negotiate1TLPFromOptionsAtClient) {
QuicConfig client_config;
QuicTagVector options;
@@ -2588,7 +2130,7 @@ TEST_P(QuicSentPacketManagerTest, Negotiate1TLPFromOptionsAtClient) {
EXPECT_EQ(1u, QuicSentPacketManagerPeer::GetMaxTailLossProbes(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, NegotiateTLPRttFromOptionsAtServer) {
+TEST_F(QuicSentPacketManagerTest, NegotiateTLPRttFromOptionsAtServer) {
QuicConfig config;
QuicTagVector options;
@@ -2601,7 +2143,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateTLPRttFromOptionsAtServer) {
QuicSentPacketManagerPeer::GetEnableHalfRttTailLossProbe(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, NegotiateTLPRttFromOptionsAtClient) {
+TEST_F(QuicSentPacketManagerTest, NegotiateTLPRttFromOptionsAtClient) {
QuicConfig client_config;
QuicTagVector options;
@@ -2615,7 +2157,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateTLPRttFromOptionsAtClient) {
QuicSentPacketManagerPeer::GetEnableHalfRttTailLossProbe(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtServer) {
+TEST_F(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtServer) {
EXPECT_FALSE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_));
QuicConfig config;
QuicTagVector options;
@@ -2628,7 +2170,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtServer) {
EXPECT_TRUE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtClient) {
+TEST_F(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtClient) {
EXPECT_FALSE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_));
QuicConfig client_config;
QuicTagVector options;
@@ -2642,7 +2184,7 @@ TEST_P(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtClient) {
EXPECT_TRUE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_));
}
-TEST_P(QuicSentPacketManagerTest, UseInitialRoundTripTimeToSend) {
+TEST_F(QuicSentPacketManagerTest, UseInitialRoundTripTimeToSend) {
QuicTime::Delta initial_rtt = QuicTime::Delta::FromMilliseconds(325);
EXPECT_NE(initial_rtt, manager_.GetRttStats()->smoothed_rtt());
@@ -2656,22 +2198,26 @@ TEST_P(QuicSentPacketManagerTest, UseInitialRoundTripTimeToSend) {
EXPECT_EQ(initial_rtt, manager_.GetRttStats()->initial_rtt());
}
-TEST_P(QuicSentPacketManagerTest, ResumeConnectionState) {
+TEST_F(QuicSentPacketManagerTest, ResumeConnectionState) {
// The sent packet manager should use the RTT from CachedNetworkParameters if
// it is provided.
const QuicTime::Delta kRtt = QuicTime::Delta::FromMilliseconds(1234);
CachedNetworkParameters cached_network_params;
cached_network_params.set_min_rtt_ms(kRtt.ToMilliseconds());
- EXPECT_CALL(*send_algorithm_,
- AdjustNetworkParameters(QuicBandwidth::Zero(), kRtt, false));
+ SendAlgorithmInterface::NetworkParams params;
+ params.bandwidth = QuicBandwidth::Zero();
+ params.allow_cwnd_to_decrease = false;
+ params.rtt = kRtt;
+
+ EXPECT_CALL(*send_algorithm_, AdjustNetworkParameters(params));
EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
.Times(testing::AnyNumber());
manager_.ResumeConnectionState(cached_network_params, false);
EXPECT_EQ(kRtt, manager_.GetRttStats()->initial_rtt());
}
-TEST_P(QuicSentPacketManagerTest, ConnectionMigrationUnspecifiedChange) {
+TEST_F(QuicSentPacketManagerTest, ConnectionMigrationUnspecifiedChange) {
RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
QuicTime::Delta default_init_rtt = rtt_stats->initial_rtt();
rtt_stats->set_initial_rtt(default_init_rtt * 2);
@@ -2690,7 +2236,7 @@ TEST_P(QuicSentPacketManagerTest, ConnectionMigrationUnspecifiedChange) {
EXPECT_EQ(0u, manager_.GetConsecutiveTlpCount());
}
-TEST_P(QuicSentPacketManagerTest, ConnectionMigrationIPSubnetChange) {
+TEST_F(QuicSentPacketManagerTest, ConnectionMigrationIPSubnetChange) {
RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
QuicTime::Delta default_init_rtt = rtt_stats->initial_rtt();
rtt_stats->set_initial_rtt(default_init_rtt * 2);
@@ -2708,7 +2254,7 @@ TEST_P(QuicSentPacketManagerTest, ConnectionMigrationIPSubnetChange) {
EXPECT_EQ(2u, manager_.GetConsecutiveTlpCount());
}
-TEST_P(QuicSentPacketManagerTest, ConnectionMigrationPortChange) {
+TEST_F(QuicSentPacketManagerTest, ConnectionMigrationPortChange) {
RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
QuicTime::Delta default_init_rtt = rtt_stats->initial_rtt();
rtt_stats->set_initial_rtt(default_init_rtt * 2);
@@ -2726,13 +2272,13 @@ TEST_P(QuicSentPacketManagerTest, ConnectionMigrationPortChange) {
EXPECT_EQ(2u, manager_.GetConsecutiveTlpCount());
}
-TEST_P(QuicSentPacketManagerTest, PathMtuIncreased) {
+TEST_F(QuicSentPacketManagerTest, PathMtuIncreased) {
EXPECT_CALL(*send_algorithm_,
OnPacketSent(_, BytesInFlight(), QuicPacketNumber(1), _, _));
SerializedPacket packet(QuicPacketNumber(1), PACKET_4BYTE_PACKET_NUMBER,
nullptr, kDefaultLength + 100, false, false);
- manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ manager_.OnPacketSent(&packet, clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA);
// Ack the large packet and expect the path MTU to increase.
ExpectAck(1);
@@ -2747,7 +2293,7 @@ TEST_P(QuicSentPacketManagerTest, PathMtuIncreased) {
ENCRYPTION_INITIAL));
}
-TEST_P(QuicSentPacketManagerTest, OnAckRangeSlowPath) {
+TEST_F(QuicSentPacketManagerTest, OnAckRangeSlowPath) {
// Send packets 1 - 20.
for (size_t i = 1; i <= 20; ++i) {
SendDataPacket(i);
@@ -2782,7 +2328,7 @@ TEST_P(QuicSentPacketManagerTest, OnAckRangeSlowPath) {
ENCRYPTION_INITIAL));
}
-TEST_P(QuicSentPacketManagerTest, TolerateReneging) {
+TEST_F(QuicSentPacketManagerTest, TolerateReneging) {
// Send packets 1 - 20.
for (size_t i = 1; i <= 20; ++i) {
SendDataPacket(i);
@@ -2815,7 +2361,7 @@ TEST_P(QuicSentPacketManagerTest, TolerateReneging) {
EXPECT_EQ(QuicPacketNumber(16), manager_.GetLargestObserved());
}
-TEST_P(QuicSentPacketManagerTest, MultiplePacketNumberSpaces) {
+TEST_F(QuicSentPacketManagerTest, MultiplePacketNumberSpaces) {
manager_.EnableMultiplePacketNumberSpacesSupport();
EXPECT_FALSE(
manager_.GetLargestSentPacket(ENCRYPTION_INITIAL).IsInitialized());
@@ -2927,7 +2473,7 @@ TEST_P(QuicSentPacketManagerTest, MultiplePacketNumberSpaces) {
manager_.GetLargestAckedPacket(ENCRYPTION_FORWARD_SECURE));
}
-TEST_P(QuicSentPacketManagerTest, PacketsGetAckedInWrongPacketNumberSpace) {
+TEST_F(QuicSentPacketManagerTest, PacketsGetAckedInWrongPacketNumberSpace) {
manager_.EnableMultiplePacketNumberSpacesSupport();
// Send packet 1.
SendDataPacket(1, ENCRYPTION_INITIAL);
@@ -2944,7 +2490,7 @@ TEST_P(QuicSentPacketManagerTest, PacketsGetAckedInWrongPacketNumberSpace) {
ENCRYPTION_INITIAL));
}
-TEST_P(QuicSentPacketManagerTest, PacketsGetAckedInWrongPacketNumberSpace2) {
+TEST_F(QuicSentPacketManagerTest, PacketsGetAckedInWrongPacketNumberSpace2) {
manager_.EnableMultiplePacketNumberSpacesSupport();
// Send packet 1.
SendDataPacket(1, ENCRYPTION_INITIAL);
@@ -2961,7 +2507,7 @@ TEST_P(QuicSentPacketManagerTest, PacketsGetAckedInWrongPacketNumberSpace2) {
ENCRYPTION_HANDSHAKE));
}
-TEST_P(QuicSentPacketManagerTest,
+TEST_F(QuicSentPacketManagerTest,
ToleratePacketsGetAckedInWrongPacketNumberSpace) {
manager_.EnableMultiplePacketNumberSpacesSupport();
// Send packet 1.
@@ -2992,10 +2538,7 @@ TEST_P(QuicSentPacketManagerTest,
}
// Regression test for b/133771183.
-TEST_P(QuicSentPacketManagerTest, PacketInLimbo) {
- if (!manager_.session_decides_what_to_write()) {
- return;
- }
+TEST_F(QuicSentPacketManagerTest, PacketInLimbo) {
QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2);
// Send SHLO.
SendCryptoPacket(1);
@@ -3047,10 +2590,7 @@ TEST_P(QuicSentPacketManagerTest, PacketInLimbo) {
ENCRYPTION_INITIAL));
}
-TEST_P(QuicSentPacketManagerTest, RtoFiresNoPacketToRetransmit) {
- if (!manager_.session_decides_what_to_write()) {
- return;
- }
+TEST_F(QuicSentPacketManagerTest, RtoFiresNoPacketToRetransmit) {
// Send 10 packets.
for (size_t i = 1; i <= 10; ++i) {
SendDataPacket(i);
@@ -3070,15 +2610,11 @@ TEST_P(QuicSentPacketManagerTest, RtoFiresNoPacketToRetransmit) {
EXPECT_CALL(notifier_, RetransmitFrames(_, _)).Times(0);
manager_.OnRetransmissionTimeout();
EXPECT_EQ(2u, stats_.rto_count);
- if (GetQuicReloadableFlag(quic_fix_rto_retransmission3)) {
- // Verify a credit is raised up.
- EXPECT_EQ(1u, manager_.pending_timer_transmission_count());
- } else {
- EXPECT_EQ(0u, manager_.pending_timer_transmission_count());
- }
+ // Verify a credit is raised up.
+ EXPECT_EQ(1u, manager_.pending_timer_transmission_count());
}
-TEST_P(QuicSentPacketManagerTest, ComputingProbeTimeout) {
+TEST_F(QuicSentPacketManagerTest, ComputingProbeTimeout) {
EnablePto(k2PTO);
EXPECT_CALL(*send_algorithm_, PacingRate(_))
.WillRepeatedly(Return(QuicBandwidth::Zero()));
@@ -3144,7 +2680,7 @@ TEST_P(QuicSentPacketManagerTest, ComputingProbeTimeout) {
EXPECT_EQ(sent_time + expected_pto_delay, manager_.GetRetransmissionTime());
}
-TEST_P(QuicSentPacketManagerTest, SendOneProbePacket) {
+TEST_F(QuicSentPacketManagerTest, SendOneProbePacket) {
EnablePto(k1PTO);
EXPECT_CALL(*send_algorithm_, PacingRate(_))
.WillRepeatedly(Return(QuicBandwidth::Zero()));
@@ -3179,9 +2715,8 @@ TEST_P(QuicSentPacketManagerTest, SendOneProbePacket) {
manager_.MaybeSendProbePackets();
}
-TEST_P(QuicSentPacketManagerTest, DisableHandshakeModeClient) {
+TEST_F(QuicSentPacketManagerTest, DisableHandshakeModeClient) {
QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT);
- manager_.SetSessionDecideWhatToWrite(true);
manager_.EnableIetfPtoAndLossDetection();
// Send CHLO.
SendCryptoPacket(1);
@@ -3203,8 +2738,7 @@ TEST_P(QuicSentPacketManagerTest, DisableHandshakeModeClient) {
manager_.OnRetransmissionTimeout());
}
-TEST_P(QuicSentPacketManagerTest, DisableHandshakeModeServer) {
- manager_.SetSessionDecideWhatToWrite(true);
+TEST_F(QuicSentPacketManagerTest, DisableHandshakeModeServer) {
manager_.EnableIetfPtoAndLossDetection();
// Send SHLO.
SendCryptoPacket(1);
@@ -3223,6 +2757,363 @@ TEST_P(QuicSentPacketManagerTest, DisableHandshakeModeServer) {
EXPECT_EQ(QuicTime::Zero(), manager_.GetRetransmissionTime());
}
+TEST_F(QuicSentPacketManagerTest, ForwardSecurePacketAcked) {
+ EXPECT_LT(manager_.handshake_state(),
+ QuicSentPacketManager::HANDSHAKE_CONFIRMED);
+ SendDataPacket(1, ENCRYPTION_INITIAL);
+ // Ack packet 1.
+ ExpectAck(1);
+ manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
+ ENCRYPTION_INITIAL));
+ EXPECT_LT(manager_.handshake_state(),
+ QuicSentPacketManager::HANDSHAKE_CONFIRMED);
+
+ SendDataPacket(2, ENCRYPTION_ZERO_RTT);
+ // Ack packet 2.
+ ExpectAck(2);
+ manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(3));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(2),
+ ENCRYPTION_FORWARD_SECURE));
+ EXPECT_LT(manager_.handshake_state(),
+ QuicSentPacketManager::HANDSHAKE_CONFIRMED);
+
+ SendDataPacket(3, ENCRYPTION_FORWARD_SECURE);
+ // Ack packet 3.
+ ExpectAck(3);
+ manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(4));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(3),
+ ENCRYPTION_FORWARD_SECURE));
+ EXPECT_EQ(manager_.handshake_state(),
+ QuicSentPacketManager::HANDSHAKE_CONFIRMED);
+}
+
+TEST_F(QuicSentPacketManagerTest, PtoTimeoutIncludesMaxAckDelay) {
+ EnablePto(k1PTO);
+ // Use PTOS and PTOA.
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kPTOS);
+ options.push_back(kPTOA);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+ EXPECT_TRUE(manager_.skip_packet_number_for_pto());
+ EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
+
+ EXPECT_CALL(*send_algorithm_, PacingRate(_))
+ .WillRepeatedly(Return(QuicBandwidth::Zero()));
+ EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+ .WillRepeatedly(Return(10 * kDefaultTCPMSS));
+ RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ QuicTime::Delta srtt = rtt_stats->smoothed_rtt();
+
+ SendDataPacket(1, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO is correctly set and ack delay is included.
+ QuicTime::Delta expected_pto_delay =
+ srtt + 4 * rtt_stats->mean_deviation() +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ SendDataPacket(2, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO is correctly set based on sent time of packet 2 but ack delay is
+ // not included as an immediate ACK is expected.
+ expected_pto_delay = expected_pto_delay - QuicTime::Delta::FromMilliseconds(
+ kDefaultDelayedAckTimeMs);
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+ EXPECT_EQ(0u, stats_.pto_count);
+
+ // Invoke PTO.
+ clock_.AdvanceTime(expected_pto_delay);
+ manager_.OnRetransmissionTimeout();
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
+ EXPECT_EQ(1u, stats_.pto_count);
+
+ // Verify 1 probe packets get sent and packet number gets skipped.
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(4, type, ENCRYPTION_FORWARD_SECURE);
+ })));
+ manager_.MaybeSendProbePackets();
+ // Verify PTO period gets set to twice the current value. Also, ack delay is
+ // not included.
+ QuicTime sent_time = clock_.Now();
+ EXPECT_EQ(sent_time + expected_pto_delay * 2,
+ manager_.GetRetransmissionTime());
+
+ // Received ACK for packets 1 and 2.
+ uint64_t acked[] = {1, 2};
+ ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+ manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(3));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
+ ENCRYPTION_FORWARD_SECURE));
+ expected_pto_delay =
+ rtt_stats->SmoothedOrInitialRtt() +
+ std::max(4 * rtt_stats->mean_deviation(),
+ QuicTime::Delta::FromMilliseconds(1)) +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+
+ // Verify PTO is correctly re-armed based on sent time of packet 4. Because of
+ // PTOS turns out to be spurious, ACK delay is included.
+ EXPECT_EQ(sent_time + expected_pto_delay, manager_.GetRetransmissionTime());
+
+ // Received ACK for packets 4.
+ ExpectAck(4);
+ manager_.OnAckFrameStart(QuicPacketNumber(4), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(4), QuicPacketNumber(5));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(4),
+ ENCRYPTION_FORWARD_SECURE));
+ EXPECT_EQ(QuicTime::Zero(), manager_.GetRetransmissionTime());
+ // Send more packets, such that peer will do ack decimation.
+ std::vector<uint64_t> acked2;
+ for (size_t i = 5; i <= 100; ++i) {
+ SendDataPacket(i, ENCRYPTION_FORWARD_SECURE);
+ acked2.push_back(i);
+ }
+ // Received ACK for all sent packets.
+ ExpectAcksAndLosses(true, &acked2[0], acked2.size(), nullptr, 0);
+ manager_.OnAckFrameStart(QuicPacketNumber(100), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(5), QuicPacketNumber(101));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(100),
+ ENCRYPTION_FORWARD_SECURE));
+
+ expected_pto_delay =
+ rtt_stats->SmoothedOrInitialRtt() +
+ std::max(4 * rtt_stats->mean_deviation(),
+ QuicTime::Delta::FromMilliseconds(1)) +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+ for (size_t i = 101; i < 110; i++) {
+ SendDataPacket(i, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO timeout includes ACK delay as there are less than 10 packets
+ // outstanding.
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+ }
+ expected_pto_delay = expected_pto_delay - QuicTime::Delta::FromMilliseconds(
+ kDefaultDelayedAckTimeMs);
+ SendDataPacket(110, ENCRYPTION_FORWARD_SECURE);
+ // Verify ACK delay is excluded.
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+}
+
+TEST_F(QuicSentPacketManagerTest, StartExponentialBackoffSince2ndPto) {
+ EnablePto(k2PTO);
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kPEB2);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+
+ EXPECT_CALL(*send_algorithm_, PacingRate(_))
+ .WillRepeatedly(Return(QuicBandwidth::Zero()));
+ EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+ .WillRepeatedly(Return(10 * kDefaultTCPMSS));
+ RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ QuicTime::Delta srtt = rtt_stats->smoothed_rtt();
+
+ SendDataPacket(1, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO is correctly set.
+ QuicTime::Delta expected_pto_delay =
+ srtt + 4 * rtt_stats->mean_deviation() +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ SendDataPacket(2, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO is correctly set based on sent time of packet 2.
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+ EXPECT_EQ(0u, stats_.pto_count);
+
+ // Invoke PTO.
+ clock_.AdvanceTime(expected_pto_delay);
+ manager_.OnRetransmissionTimeout();
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
+ EXPECT_EQ(1u, stats_.pto_count);
+
+ // Verify two probe packets get sent.
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .Times(2)
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE);
+ })))
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(4, type, ENCRYPTION_FORWARD_SECURE);
+ })));
+ manager_.MaybeSendProbePackets();
+ // Verify no exponential backoff.
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Invoke 2nd PTO.
+ clock_.AdvanceTime(expected_pto_delay);
+ manager_.OnRetransmissionTimeout();
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
+ EXPECT_EQ(2u, stats_.pto_count);
+
+ // Verify two probe packets get sent.
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .Times(2)
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(5, type, ENCRYPTION_FORWARD_SECURE);
+ })))
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(6, type, ENCRYPTION_FORWARD_SECURE);
+ })));
+ manager_.MaybeSendProbePackets();
+ // Verify still no exponential backoff.
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Invoke 3rd PTO.
+ clock_.AdvanceTime(expected_pto_delay);
+ manager_.OnRetransmissionTimeout();
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
+ EXPECT_EQ(3u, stats_.pto_count);
+
+ // Verify two probe packets get sent.
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .Times(2)
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(7, type, ENCRYPTION_FORWARD_SECURE);
+ })))
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(8, type, ENCRYPTION_FORWARD_SECURE);
+ })));
+ manager_.MaybeSendProbePackets();
+ // Verify exponential backoff starts.
+ EXPECT_EQ(clock_.Now() + expected_pto_delay * 2,
+ manager_.GetRetransmissionTime());
+
+ // Invoke 4th PTO.
+ clock_.AdvanceTime(expected_pto_delay * 2);
+ manager_.OnRetransmissionTimeout();
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
+ EXPECT_EQ(4u, stats_.pto_count);
+
+ // Verify two probe packets get sent.
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .Times(2)
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(9, type, ENCRYPTION_FORWARD_SECURE);
+ })))
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(10, type, ENCRYPTION_FORWARD_SECURE);
+ })));
+ manager_.MaybeSendProbePackets();
+ // Verify exponential backoff continues.
+ EXPECT_EQ(clock_.Now() + expected_pto_delay * 4,
+ manager_.GetRetransmissionTime());
+}
+
+TEST_F(QuicSentPacketManagerTest, PtoTimeoutRttVarMultiple) {
+ EnablePto(k1PTO);
+ // Use 2 * rttvar
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kPVS1);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+
+ EXPECT_CALL(*send_algorithm_, PacingRate(_))
+ .WillRepeatedly(Return(QuicBandwidth::Zero()));
+ EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+ .WillRepeatedly(Return(10 * kDefaultTCPMSS));
+ RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ QuicTime::Delta srtt = rtt_stats->smoothed_rtt();
+
+ SendDataPacket(1, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO is correctly set based on 2 times rtt var.
+ QuicTime::Delta expected_pto_delay =
+ srtt + 2 * rtt_stats->mean_deviation() +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+}
+
+// Regression test for b/143962153
+TEST_F(QuicSentPacketManagerTest, RtoNotInFlightPacket) {
+ QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2);
+ // Send SHLO.
+ QuicStreamFrame crypto_frame(1, false, 0, QuicStringPiece());
+ SendCryptoPacket(1);
+ // Send data packet.
+ SendDataPacket(2, ENCRYPTION_FORWARD_SECURE);
+
+ // Successfully decrypt a forward secure packet.
+ if (GetQuicReloadableFlag(quic_neuter_handshake_packets_once2)) {
+ EXPECT_CALL(notifier_, OnFrameAcked(_, _, _)).Times(1);
+ } else {
+ EXPECT_CALL(notifier_, OnFrameAcked(_, _, _)).Times(0);
+ }
+ manager_.SetHandshakeConfirmed();
+
+ // 1st TLP.
+ manager_.OnRetransmissionTimeout();
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE);
+ })));
+ manager_.MaybeRetransmitTailLossProbe();
+
+ // 2nd TLP.
+ manager_.OnRetransmissionTimeout();
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(4, type, ENCRYPTION_FORWARD_SECURE);
+ })));
+ manager_.MaybeRetransmitTailLossProbe();
+
+ // RTO retransmits SHLO although it is not in flight.
+ size_t num_rto_packets = 2;
+ if (GetQuicReloadableFlag(quic_neuter_handshake_packets_once2)) {
+ num_rto_packets = 1;
+ }
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .Times(num_rto_packets)
+ .WillOnce(WithArgs<0>(Invoke([&crypto_frame](const QuicFrames& frames) {
+ EXPECT_EQ(1u, frames.size());
+ if (GetQuicReloadableFlag(quic_neuter_handshake_packets_once2)) {
+ EXPECT_NE(crypto_frame, frames[0].stream_frame);
+ } else {
+ EXPECT_EQ(crypto_frame, frames[0].stream_frame);
+ }
+ })));
+ manager_.OnRetransmissionTimeout();
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_session.cc b/chromium/net/third_party/quiche/src/quic/core/quic_session.cc
index b6e4b83dd0b..ada8bf41d9d 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
@@ -9,6 +9,7 @@
#include <utility>
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_flow_controller.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
@@ -87,7 +88,6 @@ QuicSession::QuicSession(
perspective() == Perspective::IS_SERVER,
nullptr),
currently_writing_stream_id_(0),
- is_handshake_confirmed_(false),
goaway_sent_(false),
goaway_received_(false),
control_frame_manager_(this),
@@ -114,6 +114,13 @@ void QuicSession::Initialize() {
connection_->SetDataProducer(this);
connection_->SetFromConfig(config_);
+ // On the server side, version negotiation has been done by the dispatcher,
+ // and the server session is created with the right version.
+ if (connection_->quic_version_negotiated_by_default_at_server() &&
+ perspective() == Perspective::IS_SERVER) {
+ connection_->OnSuccessfulVersionNegotiation();
+ }
+
if (QuicVersionUsesCryptoFrames(transport_version())) {
return;
}
@@ -200,11 +207,8 @@ void QuicSession::OnCryptoFrame(const QuicCryptoFrame& frame) {
GetMutableCryptoStream()->OnCryptoFrame(frame);
}
-bool QuicSession::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
- // We are not version 99. In theory, if not in version 99 then the framer
- // could not call OnStopSending... This is just a check that is good when
- // both a new protocol and a new implementation of that protocol are both
- // being developed.
+void QuicSession::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
+ // STOP_SENDING is in IETF QUIC only.
DCHECK(VersionHasIetfQuicFrames(transport_version()));
QuicStreamId stream_id = frame.stream_id;
@@ -216,21 +220,7 @@ bool QuicSession::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
connection()->CloseConnection(
QUIC_INVALID_STREAM_ID, "Received STOP_SENDING for an invalid stream",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return false;
- }
-
- // Ignore STOP_SENDING for static streams.
- // TODO(fkastenholz): IETF Quic does not have static streams and does not
- // make exceptions for them with respect to processing things like
- // STOP_SENDING.
- if (QuicUtils::IsCryptoStreamId(transport_version(), stream_id)) {
- QUIC_DVLOG(1) << ENDPOINT
- << "Received STOP_SENDING for a static stream, id: "
- << stream_id << " Closing connection";
- connection()->CloseConnection(
- QUIC_INVALID_STREAM_ID, "Received STOP_SENDING for a static stream",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return false;
+ return;
}
if (visitor_) {
@@ -243,7 +233,7 @@ bool QuicSession::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
<< ENDPOINT
<< "Received STOP_SENDING for closed or non-existent stream, id: "
<< stream_id << " Ignoring.";
- return true; // Continue processing the packet.
+ return;
}
// If stream is non-existent, close the connection
StreamMap::iterator it = stream_map_.find(stream_id);
@@ -255,20 +245,15 @@ bool QuicSession::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
IETF_QUIC_PROTOCOL_VIOLATION,
"Received STOP_SENDING for a non-existent stream",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return false;
+ return;
}
- // Get the QuicStream for this stream. Ignore the STOP_SENDING
- // if the QuicStream pointer is NULL
- // QUESTION(fkastenholz): IS THIS THE RIGHT THING TO DO? (that is, this would
- // happen IFF there was an entry in the map, but the pointer is null. sounds
- // more like a deep programming error rather than a simple protocol problem).
QuicStream* stream = it->second.get();
if (stream == nullptr) {
QUIC_BUG << ENDPOINT
<< "Received STOP_SENDING for NULL QuicStream, stream_id: "
<< stream_id << ". Ignoring.";
- return true;
+ return;
}
if (stream->is_static()) {
@@ -278,20 +263,28 @@ bool QuicSession::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
connection()->CloseConnection(
QUIC_INVALID_STREAM_ID, "Received STOP_SENDING for a static stream",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return false;
+ return;
}
stream->OnStopSending(frame.application_error_code);
stream->set_stream_error(
static_cast<QuicRstStreamErrorCode>(frame.application_error_code));
- SendRstStreamInner(
- stream->id(),
- static_cast<quic::QuicRstStreamErrorCode>(frame.application_error_code),
- stream->stream_bytes_written(),
- /*close_write_side_only=*/true);
+ if (connection()->connected()) {
+ MaybeSendRstStreamFrame(
+ stream->id(),
+ static_cast<quic::QuicRstStreamErrorCode>(frame.application_error_code),
+ stream->stream_bytes_written());
+ connection_->OnStreamReset(stream->id(),
+ static_cast<quic::QuicRstStreamErrorCode>(
+ frame.application_error_code));
+ }
+ stream->set_rst_sent(true);
+ stream->CloseWriteSide();
+}
- return true;
+void QuicSession::OnPacketDecrypted(EncryptionLevel level) {
+ GetMutableCryptoStream()->OnPacketDecrypted(level);
}
void QuicSession::PendingStreamOnRstStream(const QuicRstStreamFrame& frame) {
@@ -306,7 +299,10 @@ void QuicSession::PendingStreamOnRstStream(const QuicRstStreamFrame& frame) {
}
pending->OnRstStreamFrame(frame);
- SendRstStream(stream_id, QUIC_RST_ACKNOWLEDGEMENT, 0);
+ // Pending stream is currently read only. We can safely close the stream.
+ DCHECK_EQ(READ_UNIDIRECTIONAL,
+ QuicUtils::GetStreamType(pending->id(), perspective(),
+ /*peer_initiated = */ true));
ClosePendingStream(stream_id);
}
@@ -319,6 +315,16 @@ void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) {
return;
}
+ if (VersionHasIetfQuicFrames(transport_version()) &&
+ QuicUtils::GetStreamType(stream_id, perspective(),
+ IsIncomingStream(stream_id)) ==
+ WRITE_UNIDIRECTIONAL) {
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Received RESET_STREAM for a write-only stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
+
if (visitor_) {
visitor_->OnRstStreamReceived(frame);
}
@@ -458,9 +464,9 @@ void QuicSession::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
// individual stream.
QUIC_DVLOG(1) << ENDPOINT
<< "Received connection level flow control window "
- "update with byte offset: "
- << frame.byte_offset;
- flow_controller_.UpdateSendWindowOffset(frame.byte_offset);
+ "update with max data: "
+ << frame.max_data;
+ flow_controller_.UpdateSendWindowOffset(frame.max_data);
return;
}
@@ -541,9 +547,7 @@ void QuicSession::OnCanWrite() {
"write blocked.";
return;
}
- if (session_decides_what_to_write()) {
- SetTransmissionType(NOT_RETRANSMISSION);
- }
+ SetTransmissionType(NOT_RETRANSMISSION);
// We limit the number of writes to the number of pending streams. If more
// streams become pending, WillingAndAbleToWrite will be true, which will
// cause the connection to request resumption before yielding to other
@@ -700,7 +704,24 @@ bool QuicSession::WriteControlFrame(const QuicFrame& frame) {
void QuicSession::SendRstStream(QuicStreamId id,
QuicRstStreamErrorCode error,
QuicStreamOffset bytes_written) {
- SendRstStreamInner(id, error, bytes_written, /*close_write_side_only=*/false);
+ if (!GetQuicReloadableFlag(quic_delete_send_rst_stream_inner)) {
+ SendRstStreamInner(id, error, bytes_written, false);
+ return;
+ }
+ QUIC_RELOADABLE_FLAG_COUNT(quic_delete_send_rst_stream_inner);
+ if (connection()->connected()) {
+ QuicConnection::ScopedPacketFlusher flusher(connection());
+ MaybeSendRstStreamFrame(id, error, bytes_written);
+ MaybeSendStopSendingFrame(id, error);
+
+ connection_->OnStreamReset(id, error);
+ }
+
+ if (error != QUIC_STREAM_NO_ERROR && QuicContainsKey(zombie_streams_, id)) {
+ OnStreamDoneWaitingForAcks(id);
+ return;
+ }
+ CloseStreamInner(id, true);
}
void QuicSession::SendRstStreamInner(QuicStreamId id,
@@ -709,21 +730,23 @@ void QuicSession::SendRstStreamInner(QuicStreamId id,
bool close_write_side_only) {
if (connection()->connected()) {
// Only send if still connected.
- if (close_write_side_only) {
- DCHECK(VersionHasIetfQuicFrames(transport_version()));
- // Send a RST_STREAM frame.
- control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written);
- } else {
+ if (VersionHasIetfQuicFrames(transport_version())) {
// Send a RST_STREAM frame plus, if version 99, an IETF
// QUIC STOP_SENDING frame. Both sre sent to emulate
// the two-way close that Google QUIC's RST_STREAM does.
- if (VersionHasIetfQuicFrames(transport_version())) {
- QuicConnection::ScopedPacketFlusher flusher(connection());
+ QuicConnection::ScopedPacketFlusher flusher(connection());
+ if (QuicUtils::GetStreamType(id, perspective(), IsIncomingStream(id)) !=
+ READ_UNIDIRECTIONAL) {
control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written);
+ }
+ if (!close_write_side_only &&
+ QuicUtils::GetStreamType(id, perspective(), IsIncomingStream(id)) !=
+ WRITE_UNIDIRECTIONAL) {
control_frame_manager_.WriteOrBufferStopSending(error, id);
- } else {
- control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written);
}
+ } else {
+ DCHECK(!close_write_side_only);
+ control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written);
}
connection_->OnStreamReset(id, error);
}
@@ -734,26 +757,27 @@ void QuicSession::SendRstStreamInner(QuicStreamId id,
if (!close_write_side_only) {
CloseStreamInner(id, true);
- return;
}
- DCHECK(VersionHasIetfQuicFrames(transport_version()));
+}
- StreamMap::iterator it = stream_map_.find(id);
- if (it != stream_map_.end()) {
- if (it->second->is_static()) {
- QUIC_DVLOG(1) << ENDPOINT
- << "Try to send rst for a static stream, id: " << id
- << " Closing connection";
- connection()->CloseConnection(
- QUIC_INVALID_STREAM_ID, "Sending rst for a static stream",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return;
- }
- QuicStream* stream = it->second.get();
- if (stream) {
- stream->set_rst_sent(true);
- stream->CloseWriteSide();
- }
+void QuicSession::MaybeSendRstStreamFrame(QuicStreamId id,
+ QuicRstStreamErrorCode error,
+ QuicStreamOffset bytes_written) {
+ DCHECK(connection()->connected());
+ if (!VersionHasIetfQuicFrames(transport_version()) ||
+ QuicUtils::GetStreamType(id, perspective(), IsIncomingStream(id)) !=
+ READ_UNIDIRECTIONAL) {
+ control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written);
+ }
+}
+
+void QuicSession::MaybeSendStopSendingFrame(QuicStreamId id,
+ QuicRstStreamErrorCode error) {
+ DCHECK(connection()->connected());
+ if (VersionHasIetfQuicFrames(transport_version()) &&
+ QuicUtils::GetStreamType(id, perspective(), IsIncomingStream(id)) !=
+ WRITE_UNIDIRECTIONAL) {
+ control_frame_manager_.WriteOrBufferStopSending(error, id);
}
}
@@ -840,9 +864,7 @@ void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool locally_reset) {
zombie_streams_[stream->id()] = std::move(it->second);
} else {
// Clean up the stream since it is no longer waiting for acks.
- if (session_decides_what_to_write()) {
- streams_waiting_for_acks_.erase(stream->id());
- }
+ streams_waiting_for_acks_.erase(stream->id());
closed_streams_.push_back(std::move(it->second));
// Do not retransmit data of a closed stream.
streams_with_pending_retransmission_.erase(stream_id);
@@ -855,7 +877,7 @@ void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool locally_reset) {
// If we haven't received a FIN or RST for this stream, we need to keep track
// of the how many bytes the stream's flow controller believes it has
// received, for accurate connection level flow control accounting.
- const bool had_fin_or_rst = stream->HasFinalReceivedByteOffset();
+ const bool had_fin_or_rst = stream->HasReceivedFinalOffset();
if (!had_fin_or_rst) {
InsertLocallyClosedStreamsHighestOffset(
stream_id, stream->flow_controller()->highest_received_byte_offset());
@@ -935,14 +957,16 @@ void QuicSession::OnFinalByteOffsetReceived(
}
bool QuicSession::IsEncryptionEstablished() const {
- // Once the handshake is confirmed, it never becomes un-confirmed.
- if (is_handshake_confirmed_) {
- return true;
+ if (GetCryptoStream() == nullptr) {
+ return false;
}
return GetCryptoStream()->encryption_established();
}
bool QuicSession::IsCryptoHandshakeConfirmed() const {
+ if (GetCryptoStream() == nullptr) {
+ return false;
+ }
return GetCryptoStream()->handshake_confirmed();
}
@@ -1249,6 +1273,7 @@ void QuicSession::OnNewSessionFlowControlWindow(QuicStreamOffset new_window) {
}
void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
+ DCHECK(!use_handshake_delegate());
switch (event) {
case ENCRYPTION_ESTABLISHED:
// Retransmit originally packets that were sent, since they can't be
@@ -1264,7 +1289,6 @@ void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
// Discard originally encrypted packets, since they can't be decrypted by
// the peer.
NeuterUnencryptedData();
- is_handshake_confirmed_ = true;
break;
default:
@@ -1272,6 +1296,93 @@ void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
}
}
+void QuicSession::OnNewKeysAvailable(EncryptionLevel level,
+ std::unique_ptr<QuicDecrypter> decrypter,
+ bool set_alternative_decrypter,
+ bool latch_once_used,
+ std::unique_ptr<QuicEncrypter> encrypter) {
+ DCHECK(use_handshake_delegate());
+ // Install new keys.
+ connection()->SetEncrypter(level, std::move(encrypter));
+ if (connection()->version().KnowsWhichDecrypterToUse()) {
+ connection()->InstallDecrypter(level, std::move(decrypter));
+ return;
+ }
+ if (set_alternative_decrypter) {
+ connection()->SetAlternativeDecrypter(level, std::move(decrypter),
+ latch_once_used);
+ return;
+ }
+ connection()->SetDecrypter(level, std::move(decrypter));
+}
+
+void QuicSession::SetDefaultEncryptionLevel(EncryptionLevel level) {
+ DCHECK(use_handshake_delegate());
+ QUIC_DVLOG(1) << ENDPOINT << "Set default encryption level to "
+ << EncryptionLevelToString(level);
+ connection()->SetDefaultEncryptionLevel(level);
+
+ switch (level) {
+ case ENCRYPTION_INITIAL:
+ break;
+ case ENCRYPTION_ZERO_RTT:
+ // Retransmit old 0-RTT data (if any) with the new 0-RTT keys, since they
+ // can't be decrypted by the peer.
+ connection_->RetransmitUnackedPackets(ALL_INITIAL_RETRANSMISSION);
+ // Given any streams blocked by encryption a chance to write.
+ OnCanWrite();
+ break;
+ case ENCRYPTION_HANDSHAKE:
+ break;
+ case ENCRYPTION_FORWARD_SECURE:
+ QUIC_BUG_IF(!config_.negotiated())
+ << ENDPOINT << "Handshake confirmed without parameter negotiation.";
+ break;
+ default:
+ QUIC_BUG << "Unknown encryption level: "
+ << EncryptionLevelToString(level);
+ }
+}
+
+void QuicSession::DiscardOldDecryptionKey(EncryptionLevel level) {
+ DCHECK(use_handshake_delegate());
+ if (!connection()->version().KnowsWhichDecrypterToUse()) {
+ // TODO(fayang): actually discard keys.
+ return;
+ }
+ connection()->RemoveDecrypter(level);
+}
+
+void QuicSession::DiscardOldEncryptionKey(EncryptionLevel level) {
+ DCHECK(use_handshake_delegate());
+ QUIC_DVLOG(1) << ENDPOINT << "Discard keys of "
+ << EncryptionLevelToString(level);
+ // TODO(fayang): actually discard keys.
+ switch (level) {
+ case ENCRYPTION_INITIAL:
+ NeuterUnencryptedData();
+ break;
+ case ENCRYPTION_HANDSHAKE:
+ DCHECK(false);
+ // TODO(fayang): implement this when handshake keys discarding settles
+ // down.
+ break;
+ case ENCRYPTION_ZERO_RTT:
+ break;
+ case ENCRYPTION_FORWARD_SECURE:
+ QUIC_BUG << "Tries to drop 1-RTT keys";
+ break;
+ default:
+ QUIC_BUG << "Unknown encryption level: "
+ << EncryptionLevelToString(level);
+ }
+}
+
+void QuicSession::NeuterHandshakeData() {
+ DCHECK(use_handshake_delegate());
+ connection()->OnHandshakeComplete();
+}
+
void QuicSession::OnCryptoHandshakeMessageSent(
const CryptoHandshakeMessage& /*message*/) {}
@@ -1476,6 +1587,13 @@ void QuicSession::set_largest_peer_created_stream_id(
largest_peer_created_stream_id);
}
+QuicStreamId QuicSession::GetLargestPeerCreatedStreamId(
+ bool unidirectional) const {
+ // This method is only used in IETF QUIC.
+ DCHECK(VersionHasIetfQuicFrames(transport_version()));
+ return v99_streamid_manager_.GetLargestPeerCreatedStreamId(unidirectional);
+}
+
bool QuicSession::IsClosedStream(QuicStreamId id) {
DCHECK_NE(QuicUtils::GetInvalidStreamId(transport_version()), id);
if (IsOpenStream(id)) {
@@ -1621,9 +1739,7 @@ bool QuicSession::IsIncomingStream(QuicStreamId id) const {
}
void QuicSession::OnStreamDoneWaitingForAcks(QuicStreamId id) {
- if (session_decides_what_to_write()) {
- streams_waiting_for_acks_.erase(id);
- }
+ streams_waiting_for_acks_.erase(id);
auto it = zombie_streams_.find(id);
if (it == zombie_streams_.end()) {
@@ -1640,10 +1756,6 @@ void QuicSession::OnStreamDoneWaitingForAcks(QuicStreamId id) {
}
void QuicSession::OnStreamWaitingForAcks(QuicStreamId id) {
- if (!session_decides_what_to_write()) {
- return;
- }
-
// Exclude crypto stream's status since it is counted in HasUnackedCryptoData.
if (GetCryptoStream() != nullptr && id == GetCryptoStream()->id()) {
return;
@@ -1903,14 +2015,12 @@ bool QuicSession::RetransmitLostData() {
}
void QuicSession::NeuterUnencryptedData() {
- if (connection_->session_decides_what_to_write()) {
- QuicCryptoStream* crypto_stream = GetMutableCryptoStream();
- crypto_stream->NeuterUnencryptedStreamData();
- if (!crypto_stream->HasPendingRetransmission() &&
- !QuicVersionUsesCryptoFrames(transport_version())) {
- streams_with_pending_retransmission_.erase(
- QuicUtils::GetCryptoStreamId(transport_version()));
- }
+ QuicCryptoStream* crypto_stream = GetMutableCryptoStream();
+ crypto_stream->NeuterUnencryptedStreamData();
+ if (!crypto_stream->HasPendingRetransmission() &&
+ !QuicVersionUsesCryptoFrames(transport_version())) {
+ streams_with_pending_retransmission_.erase(
+ QuicUtils::GetCryptoStreamId(transport_version()));
}
connection_->NeuterUnencryptedPackets();
}
@@ -1920,11 +2030,15 @@ void QuicSession::SetTransmissionType(TransmissionType type) {
}
MessageResult QuicSession::SendMessage(QuicMemSliceSpan message) {
+ return SendMessage(message, /*flush=*/false);
+}
+
+MessageResult QuicSession::SendMessage(QuicMemSliceSpan message, bool flush) {
if (!IsEncryptionEstablished()) {
return {MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED, 0};
}
MessageStatus result =
- connection_->SendMessage(last_message_id_ + 1, message);
+ connection_->SendMessage(last_message_id_ + 1, message, flush);
if (result == MESSAGE_STATUS_SUCCESS) {
return {result, ++last_message_id_};
}
@@ -1945,10 +2059,6 @@ void QuicSession::CleanUpClosedStreams() {
closed_streams_.clear();
}
-bool QuicSession::session_decides_what_to_write() const {
- return connection_->session_decides_what_to_write();
-}
-
QuicPacketLength QuicSession::GetCurrentLargestMessagePayload() const {
return connection_->GetCurrentLargestMessagePayload();
}
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 9a2f3aaeffc..c6861f93ca5 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
@@ -14,6 +14,7 @@
#include <string>
#include <vector>
+#include "net/third_party/quiche/src/quic/core/handshaker_delegate_interface.h"
#include "net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_control_frame_manager.h"
@@ -23,6 +24,7 @@
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_stream_frame_data_producer.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
#include "net/third_party/quiche/src/quic/core/session_notifier_interface.h"
#include "net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.h"
@@ -45,12 +47,13 @@ class QUIC_EXPORT_PRIVATE QuicSession
: public QuicConnectionVisitorInterface,
public SessionNotifierInterface,
public QuicStreamFrameDataProducer,
- public QuicStreamIdManager::DelegateInterface {
+ public QuicStreamIdManager::DelegateInterface,
+ public HandshakerDelegateInterface {
public:
// An interface from the session to the entity owning the session.
// This lets the session notify its owner (the Dispatcher) when the connection
// is closed, blocked, or added/removed from the time-wait list.
- class Visitor {
+ class QUIC_EXPORT_PRIVATE Visitor {
public:
virtual ~Visitor() {}
@@ -72,6 +75,7 @@ class QUIC_EXPORT_PRIVATE QuicSession
};
// CryptoHandshakeEvent enumerates the events generated by a QuicCryptoStream.
+ // TODO(fayang): Replace this enum and with HandshakeState.
enum CryptoHandshakeEvent {
// ENCRYPTION_ESTABLISHED indicates that a client hello has been sent and
// subsequent packets will be encrypted. (Client only.)
@@ -125,7 +129,8 @@ class QUIC_EXPORT_PRIVATE QuicSession
void OnForwardProgressConfirmed() override;
bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override;
bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
- bool OnStopSendingFrame(const QuicStopSendingFrame& frame) override;
+ void OnStopSendingFrame(const QuicStopSendingFrame& frame) override;
+ void OnPacketDecrypted(EncryptionLevel level) override;
// QuicStreamFrameDataProducer
WriteStreamDataResult WriteStreamData(QuicStreamId id,
@@ -197,6 +202,10 @@ class QUIC_EXPORT_PRIVATE QuicSession
// callback.
MessageResult SendMessage(QuicMemSliceSpan message);
+ // Same as above SendMessage, except caller can specify if the given |message|
+ // should be flushed even if the underlying connection is deemed unwritable.
+ MessageResult SendMessage(QuicMemSliceSpan message, bool flush);
+
// Called when message with |message_id| gets acked.
virtual void OnMessageAcked(QuicMessageId message_id,
QuicTime receive_timestamp);
@@ -208,7 +217,9 @@ class QUIC_EXPORT_PRIVATE QuicSession
// the peer. Returns true if |frame| is consumed, false otherwise.
virtual bool WriteControlFrame(const QuicFrame& frame);
- // Called by streams when they want to close the stream in both directions.
+ // Close the stream in both directions.
+ // TODO(renjietang): rename this method as it sends both RST_STREAM and
+ // STOP_SENDING in IETF QUIC.
virtual void SendRstStream(QuicStreamId id,
QuicRstStreamErrorCode error,
QuicStreamOffset bytes_written);
@@ -248,6 +259,18 @@ class QUIC_EXPORT_PRIVATE QuicSession
// Servers will simply call it once with HANDSHAKE_CONFIRMED.
virtual void OnCryptoHandshakeEvent(CryptoHandshakeEvent event);
+ // From HandshakerDelegateInterface
+ void OnNewKeysAvailable(EncryptionLevel level,
+ std::unique_ptr<QuicDecrypter> decrypter,
+ bool set_alternative_decrypter,
+ bool latch_once_used,
+ std::unique_ptr<QuicEncrypter> encrypter) override;
+ void SetDefaultEncryptionLevel(EncryptionLevel level) override;
+ void DiscardOldDecryptionKey(EncryptionLevel level) override;
+ void DiscardOldEncryptionKey(EncryptionLevel level) override;
+ void NeuterUnencryptedData() override;
+ void NeuterHandshakeData() override;
+
// Called by the QuicCryptoStream when a handshake message is sent.
virtual void OnCryptoHandshakeMessageSent(
const CryptoHandshakeMessage& message);
@@ -330,9 +353,6 @@ class QUIC_EXPORT_PRIVATE QuicSession
// Called when stream |id| is newly waiting for acks.
void OnStreamWaitingForAcks(QuicStreamId id);
- // Called to cancel retransmission of unencypted crypto stream data.
- void NeuterUnencryptedData();
-
// Returns true if the session has data to be sent, either queued in the
// connection, or in a write-blocked stream.
bool HasDataToWrite() const;
@@ -404,8 +424,6 @@ class QUIC_EXPORT_PRIVATE QuicSession
// Clean up closed_streams_.
void CleanUpClosedStreams();
- bool session_decides_what_to_write() const;
-
const ParsedQuicVersionVector& supported_versions() const {
return supported_versions_;
}
@@ -447,6 +465,10 @@ class QUIC_EXPORT_PRIVATE QuicSession
return use_http2_priority_write_scheduler_;
}
+ bool use_handshake_delegate() const {
+ return connection_->use_handshake_delegate();
+ }
+
bool is_configured() const { return is_configured_; }
QuicStreamCount num_expected_unidirectional_static_streams() const {
@@ -539,6 +561,10 @@ class QUIC_EXPORT_PRIVATE QuicSession
StreamMap& stream_map() { return stream_map_; }
const StreamMap& stream_map() const { return stream_map_; }
+ const PendingStreamMap& pending_streams() const {
+ return pending_stream_map_;
+ }
+
ClosedStreams* closed_streams() { return &closed_streams_; }
const ZombieStreamMap& zombie_streams() const { return zombie_streams_; }
@@ -596,7 +622,9 @@ class QUIC_EXPORT_PRIVATE QuicSession
return false;
}
- bool IsHandshakeConfirmed() const { return is_handshake_confirmed_; }
+ // Return the largest peer created stream id depending on directionality
+ // indicated by |unidirectional|.
+ QuicStreamId GetLargestPeerCreatedStreamId(bool unidirectional) const;
private:
friend class test::QuicSessionPeer;
@@ -659,6 +687,14 @@ class QUIC_EXPORT_PRIVATE QuicSession
// stream.
void PendingStreamOnRstStream(const QuicRstStreamFrame& frame);
+ // Does actual work of sending RESET_STREAM, if the stream type allows.
+ void MaybeSendRstStreamFrame(QuicStreamId id,
+ QuicRstStreamErrorCode error,
+ QuicStreamOffset bytes_written);
+
+ // Sends a STOP_SENDING frame if the stream type allows.
+ void MaybeSendStopSendingFrame(QuicStreamId id, QuicRstStreamErrorCode error);
+
// Keep track of highest received byte offset of locally closed streams, while
// waiting for a definitive final highest offset from the peer.
std::map<QuicStreamId, QuicStreamOffset>
@@ -732,9 +768,6 @@ class QUIC_EXPORT_PRIVATE QuicSession
// call stack of OnCanWrite.
QuicStreamId currently_writing_stream_id_;
- // Cached value of whether the crypto handshake has been confirmed.
- bool is_handshake_confirmed_;
-
// Whether a GoAway has been sent.
bool goaway_sent_;
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 9eb4fed3de9..afb5641d8f9 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
@@ -85,11 +85,16 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
error =
session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
}
- EXPECT_EQ(QUIC_NO_ERROR, error);
+ EXPECT_THAT(error, IsQuicNoError());
session()->OnConfigNegotiated();
- session()->connection()->SetDefaultEncryptionLevel(
- ENCRYPTION_FORWARD_SECURE);
- session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
+ if (session()->use_handshake_delegate()) {
+ session()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
+ } else {
+ session()->connection()->SetDefaultEncryptionLevel(
+ ENCRYPTION_FORWARD_SECURE);
+ session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
+ }
}
// QuicCryptoStream implementation
@@ -104,6 +109,7 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
CryptoMessageParser* crypto_message_parser() override {
return QuicCryptoHandshaker::crypto_message_parser();
}
+ void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
MOCK_METHOD0(OnCanWrite, void());
bool HasPendingCryptoRetransmission() const override { return false; }
@@ -135,7 +141,6 @@ class TestStream : public QuicStream {
using QuicStream::CloseReadSide;
using QuicStream::CloseWriteSide;
using QuicStream::WriteMemSlices;
- using QuicStream::WritevData;
void OnDataAvailable() override {}
@@ -144,7 +149,6 @@ class TestStream : public QuicStream {
bool(QuicStreamOffset, QuicByteCount, bool));
MOCK_CONST_METHOD0(HasPendingRetransmission, bool());
- MOCK_METHOD1(OnStopSending, void(uint16_t code));
};
class TestSession : public QuicSession {
@@ -391,24 +395,33 @@ class QuicSessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
}
void CloseStream(QuicStreamId id) {
- if (VersionHasIetfQuicFrames(session_.transport_version()) &&
- QuicUtils::GetStreamType(id, session_.perspective(),
- session_.IsIncomingStream(id)) ==
- READ_UNIDIRECTIONAL) {
- // Verify reset is not sent for READ_UNIDIRECTIONAL streams.
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
- EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(0);
- } else {
- // Verify reset IS sent for BIDIRECTIONAL streams.
- if (VersionHasIetfQuicFrames(session_.transport_version())) {
- // Once for the RST_STREAM, Once for the STOP_SENDING
+ if (VersionHasIetfQuicFrames(transport_version())) {
+ if (QuicUtils::GetStreamType(id, session_.perspective(),
+ session_.IsIncomingStream(id)) ==
+ READ_UNIDIRECTIONAL) {
+ // Verify reset is not sent for READ_UNIDIRECTIONAL streams.
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
+ EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(0);
+ } else if (QuicUtils::GetStreamType(id, session_.perspective(),
+ session_.IsIncomingStream(id)) ==
+ WRITE_UNIDIRECTIONAL) {
+ // Verify RESET_STREAM but not STOP_SENDING is sent for write-only
+ // stream.
EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(2)
- .WillRepeatedly(Invoke(&ClearControlFrame));
+ .Times(1)
+ .WillOnce(Invoke(&ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(id, _));
} else {
+ // Verify RESET_STREAM and STOP_SENDING are sent for BIDIRECTIONAL
+ // streams.
EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillOnce(Invoke(&ClearControlFrame));
+ .Times(2)
+ .WillRepeatedly(Invoke(&ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(id, _));
}
+ } else {
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&ClearControlFrame));
EXPECT_CALL(*connection_, OnStreamReset(id, _));
}
session_.CloseStream(id);
@@ -1309,7 +1322,7 @@ TEST_P(QuicSessionTestServer, OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
TEST_P(QuicSessionTestServer, SendGoAway) {
if (VersionHasIetfQuicFrames(transport_version())) {
- // GoAway frames are not in version 99
+ // In IETF QUIC, GOAWAY lives up in the HTTP layer.
return;
}
connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
@@ -1334,8 +1347,7 @@ TEST_P(QuicSessionTestServer, SendGoAway) {
TEST_P(QuicSessionTestServer, DoNotSendGoAwayTwice) {
if (VersionHasIetfQuicFrames(transport_version())) {
- // TODO(b/118808809): Enable this test for version 99 when GOAWAY is
- // supported.
+ // In IETF QUIC, GOAWAY lives up in the HTTP layer.
return;
}
EXPECT_CALL(*connection_, SendControlFrame(_))
@@ -1347,8 +1359,7 @@ TEST_P(QuicSessionTestServer, DoNotSendGoAwayTwice) {
TEST_P(QuicSessionTestServer, InvalidGoAway) {
if (VersionHasIetfQuicFrames(transport_version())) {
- // TODO(b/118808809): Enable this test for version 99 when GOAWAY is
- // supported.
+ // In IETF QUIC, GOAWAY lives up in the HTTP layer.
return;
}
QuicGoAwayFrame go_away(kInvalidControlFrameId, QUIC_PEER_GOING_AWAY,
@@ -1558,7 +1569,7 @@ TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedCryptoStream) {
config.ToHandshakeMessage(&crypto_message, transport_version());
crypto_stream->SendHandshakeMessage(crypto_message);
char buf[1000];
- QuicDataWriter writer(1000, buf, NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(1000, buf, quiche::NETWORK_BYTE_ORDER);
crypto_stream->WriteStreamData(offset, crypto_message.size(), &writer);
}
EXPECT_TRUE(crypto_stream->flow_controller()->IsBlocked());
@@ -1605,7 +1616,8 @@ TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstOutOfOrder) {
// stream and therefore fulfill all of the expects.
QuicStopSendingFrame frame(kInvalidControlFrameId, stream->id(),
QUIC_STREAM_CANCELLED);
- EXPECT_TRUE(session_.OnStopSendingFrame(frame));
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
+ session_.OnStopSendingFrame(frame);
}
EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed());
}
@@ -1886,9 +1898,6 @@ TEST_P(QuicSessionTestServer, RstPendingStreams) {
EXPECT_EQ(0, session_.num_incoming_streams_created());
EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
- EXPECT_CALL(*connection_, OnStreamReset(stream_id, QUIC_RST_ACKNOWLEDGEMENT))
- .Times(1);
QuicRstStreamFrame rst1(kInvalidControlFrameId, stream_id,
QUIC_ERROR_PROCESSING_STREAM, 12);
session_.OnRstStream(rst1);
@@ -2119,7 +2128,8 @@ TEST_P(QuicSessionTestServer, TestZombieStreams) {
// stream and therefore fulfill all of the expects.
QuicStopSendingFrame frame(kInvalidControlFrameId, stream2->id(),
QUIC_STREAM_CANCELLED);
- EXPECT_TRUE(session_.OnStopSendingFrame(frame));
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
+ session_.OnStopSendingFrame(frame);
}
EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
ASSERT_EQ(1u, session_.closed_streams()->size());
@@ -2148,7 +2158,6 @@ TEST_P(QuicSessionTestServer, TestZombieStreams) {
}
TEST_P(QuicSessionTestServer, OnStreamFrameLost) {
- QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
InSequence s;
// Drive congestion control manually.
@@ -2225,7 +2234,6 @@ TEST_P(QuicSessionTestServer, OnStreamFrameLost) {
}
TEST_P(QuicSessionTestServer, DonotRetransmitDataOfClosedStreams) {
- QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
InSequence s;
TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
@@ -2265,7 +2273,6 @@ TEST_P(QuicSessionTestServer, DonotRetransmitDataOfClosedStreams) {
}
TEST_P(QuicSessionTestServer, RetransmitFrames) {
- QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
InSequence s;
@@ -2301,7 +2308,6 @@ TEST_P(QuicSessionTestServer, RetransmitFrames) {
TEST_P(QuicSessionTestServer, RetransmitLostDataCausesConnectionClose) {
// This test mimics the scenario when a dynamic stream retransmits lost data
// and causes connection close.
- QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
TestStream* stream = session_.CreateOutgoingBidirectionalStream();
QuicStreamFrame frame(stream->id(), false, 0, 9);
@@ -2343,21 +2349,21 @@ TEST_P(QuicSessionTestServer, SendMessage) {
EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed());
QuicStringPiece message;
- EXPECT_CALL(*connection_, SendMessage(1, _))
+ EXPECT_CALL(*connection_, SendMessage(1, _, false))
.WillOnce(Return(MESSAGE_STATUS_SUCCESS));
EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 1),
session_.SendMessage(
MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
message, &storage)));
// Verify message_id increases.
- EXPECT_CALL(*connection_, SendMessage(2, _))
+ EXPECT_CALL(*connection_, SendMessage(2, _, false))
.WillOnce(Return(MESSAGE_STATUS_TOO_LARGE));
EXPECT_EQ(MessageResult(MESSAGE_STATUS_TOO_LARGE, 0),
session_.SendMessage(
MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
message, &storage)));
// Verify unsent message does not consume a message_id.
- EXPECT_CALL(*connection_, SendMessage(2, _))
+ EXPECT_CALL(*connection_, SendMessage(2, _, false))
.WillOnce(Return(MESSAGE_STATUS_SUCCESS));
EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 2),
session_.SendMessage(
@@ -2380,8 +2386,6 @@ TEST_P(QuicSessionTestServer, SendMessage) {
// Regression test of b/115323618.
TEST_P(QuicSessionTestServer, LocallyResetZombieStreams) {
- QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
-
session_.set_writev_consumes_all_data(true);
TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
std::string body(100, '.');
@@ -2632,7 +2636,7 @@ TEST_P(QuicSessionTestServer, OnStopSendingInputInvalidStreamId) {
*connection_,
CloseConnection(QUIC_INVALID_STREAM_ID,
"Received STOP_SENDING for an invalid stream", _));
- EXPECT_FALSE(session_.OnStopSendingFrame(frame));
+ session_.OnStopSendingFrame(frame);
}
// Second test, streams in the static stream map are not subject to
@@ -2652,7 +2656,7 @@ TEST_P(QuicSessionTestServer, OnStopSendingInputStaticStreams) {
EXPECT_CALL(*connection_,
CloseConnection(QUIC_INVALID_STREAM_ID,
"Received STOP_SENDING for a static stream", _));
- EXPECT_FALSE(session_.OnStopSendingFrame(frame));
+ session_.OnStopSendingFrame(frame);
}
// Third test, if stream id specifies a closed stream:
@@ -2672,7 +2676,7 @@ TEST_P(QuicSessionTestServer, OnStopSendingInputClosedStream) {
stream->CloseReadSide();
QuicStopSendingFrame frame(1, stream_id, 123);
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
- EXPECT_TRUE(session_.OnStopSendingFrame(frame));
+ session_.OnStopSendingFrame(frame);
}
// Fourth test, if stream id specifies a nonexistent stream, return false and
@@ -2690,7 +2694,7 @@ TEST_P(QuicSessionTestServer, OnStopSendingInputNonExistentStream) {
CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION,
"Received STOP_SENDING for a non-existent stream", _))
.Times(1);
- EXPECT_FALSE(session_.OnStopSendingFrame(frame));
+ session_.OnStopSendingFrame(frame);
}
// For a valid stream, ensure that all works
@@ -2708,15 +2712,14 @@ TEST_P(QuicSessionTestServer, OnStopSendingInputValidStream) {
QuicStreamId stream_id = stream->id();
QuicStopSendingFrame frame(1, stream_id, 123);
- EXPECT_CALL(*stream, OnStopSending(123));
// Expect a reset to come back out.
EXPECT_CALL(*connection_, SendControlFrame(_));
EXPECT_CALL(
*connection_,
OnStreamReset(stream_id, static_cast<QuicRstStreamErrorCode>(123)));
- EXPECT_TRUE(session_.OnStopSendingFrame(frame));
- // When the STOP_SENDING is received, the node generates a RST_STREAM,
- // which closes the stream in the write direction. Ensure this.
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
+ session_.OnStopSendingFrame(frame);
+
EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream));
EXPECT_TRUE(stream->write_side_closed());
}
@@ -2754,17 +2757,43 @@ TEST_P(QuicSessionTestServer, StreamFrameReceivedAfterFin) {
session_.OnStreamFrame(frame);
QuicStreamFrame frame1(stream->id(), false, 1, ",");
- if (GetQuicReloadableFlag(quic_rst_if_stream_frame_beyond_close_offset)) {
+ if (!GetQuicReloadableFlag(quic_close_connection_on_wrong_offset)) {
EXPECT_CALL(*connection_, SendControlFrame(_));
EXPECT_CALL(*connection_,
OnStreamReset(stream->id(), QUIC_DATA_AFTER_CLOSE_OFFSET));
- session_.OnStreamFrame(frame1);
- EXPECT_TRUE(connection_->connected());
} else {
-#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
- EXPECT_DEBUG_DEATH(session_.OnStreamFrame(frame1), "Check failed");
-#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_STREAM_DATA_BEYOND_CLOSE_OFFSET, _, _));
+ }
+ session_.OnStreamFrame(frame1);
+}
+
+TEST_P(QuicSessionTestServer, ResetForIETFStreamTypes) {
+ if (!VersionHasIetfQuicFrames(transport_version())) {
+ return;
}
+
+ QuicStreamId read_only = GetNthClientInitiatedUnidirectionalId(0);
+
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(1)
+ .WillOnce(Invoke(&ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(read_only, _));
+ session_.SendRstStream(read_only, QUIC_STREAM_CANCELLED, 0);
+
+ QuicStreamId write_only = GetNthServerInitiatedUnidirectionalId(0);
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(1)
+ .WillOnce(Invoke(&ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(write_only, _));
+ session_.SendRstStream(write_only, QUIC_STREAM_CANCELLED, 0);
+
+ QuicStreamId bidirectional = GetNthClientInitiatedBidirectionalId(0);
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(2)
+ .WillRepeatedly(Invoke(&ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(bidirectional, _));
+ session_.SendRstStream(bidirectional, QUIC_STREAM_CANCELLED, 0);
}
// A client test class that can be used when the automatic configuration is not
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 d708b13cfcf..20373272d4f 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
@@ -9,6 +9,7 @@
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_flow_controller.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
@@ -21,7 +22,7 @@ using spdy::SpdyPriority;
namespace quic {
#define ENDPOINT \
- (perspective_ == Perspective::IS_SERVER ? "Server: " : "Client: ")
+ (session_->perspective() == Perspective::IS_SERVER ? "Server: " : "Client: ")
namespace {
@@ -135,9 +136,13 @@ void PendingStream::AddBytesConsumed(QuicByteCount bytes) {
connection_flow_controller_->AddBytesConsumed(bytes);
}
-void PendingStream::Reset(QuicRstStreamErrorCode error) {
- // TODO: RESET_STREAM must not be sent for READ_UNIDIRECTIONAL stream.
- session_->SendRstStream(id_, error, 0);
+void PendingStream::Reset(QuicRstStreamErrorCode /*error*/) {
+ // Currently PendingStream is only read-unidirectional. It shouldn't send
+ // Reset.
+ DCHECK_EQ(READ_UNIDIRECTIONAL,
+ QuicUtils::GetStreamType(id_, session_->perspective(),
+ /*peer_initiated = */ true));
+ QUIC_NOTREACHED();
}
void PendingStream::CloseConnectionWithDetails(QuicErrorCode error,
@@ -171,9 +176,13 @@ void PendingStream::OnStreamFrame(const QuicStreamFrame& frame) {
return;
}
- if (GetQuicReloadableFlag(quic_rst_if_stream_frame_beyond_close_offset) &&
- frame.offset + frame.data_length > sequencer_.close_offset()) {
- Reset(QUIC_DATA_AFTER_CLOSE_OFFSET);
+ if (frame.offset + frame.data_length > sequencer_.close_offset()) {
+ CloseConnectionWithDetails(
+ QUIC_STREAM_DATA_BEYOND_CLOSE_OFFSET,
+ QuicStrCat(
+ "Stream ", id_,
+ " received data with offset: ", frame.offset + frame.data_length,
+ ", which is beyond close offset: ", sequencer()->close_offset()));
return;
}
@@ -212,6 +221,20 @@ void PendingStream::OnRstStreamFrame(const QuicRstStreamFrame& frame) {
"Reset frame stream offset overflow.");
return;
}
+
+ const QuicStreamOffset kMaxOffset =
+ std::numeric_limits<QuicStreamOffset>::max();
+ if (sequencer()->close_offset() != kMaxOffset &&
+ frame.byte_offset != sequencer()->close_offset()) {
+ CloseConnectionWithDetails(
+ QUIC_STREAM_MULTIPLE_OFFSET,
+ QuicStrCat("Stream ", id_,
+ " received new final offset: ", frame.byte_offset,
+ ", which is different from close offset: ",
+ sequencer()->close_offset()));
+ return;
+ }
+
MaybeIncreaseHighestReceivedOffset(frame.byte_offset);
if (flow_controller_.FlowControlViolation() ||
connection_flow_controller_->FlowControlViolation()) {
@@ -328,7 +351,6 @@ QuicStream::QuicStream(QuicStreamId id,
fin_received_(fin_received),
rst_sent_(false),
rst_received_(false),
- perspective_(session_->perspective()),
flow_controller_(std::move(flow_controller)),
connection_flow_controller_(connection_flow_controller),
stream_contributes_to_connection_flow_control_(true),
@@ -342,7 +364,7 @@ QuicStream::QuicStream(QuicStreamId id,
type_(VersionHasIetfQuicFrames(session->transport_version()) &&
type != CRYPTO
? QuicUtils::GetStreamType(id_,
- perspective_,
+ session->perspective(),
session->IsIncomingStream(id_))
: type) {
if (type_ == WRITE_UNIDIRECTIONAL) {
@@ -352,7 +374,6 @@ QuicStream::QuicStream(QuicStreamId id,
set_fin_sent(true);
CloseWriteSide();
}
- SetFromConfig();
if (type_ != CRYPTO) {
session_->RegisterStreamPriority(id, is_static_, precedence_);
}
@@ -371,8 +392,6 @@ QuicStream::~QuicStream() {
}
}
-void QuicStream::SetFromConfig() {}
-
void QuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
DCHECK_EQ(frame.stream_id, id_);
@@ -402,12 +421,19 @@ void QuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
return;
}
- if (GetQuicReloadableFlag(quic_rst_if_stream_frame_beyond_close_offset)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_rst_if_stream_frame_beyond_close_offset);
- if (frame.offset + frame.data_length > sequencer_.close_offset()) {
+ if (frame.offset + frame.data_length > sequencer_.close_offset()) {
+ if (!GetQuicReloadableFlag(quic_close_connection_on_wrong_offset)) {
Reset(QUIC_DATA_AFTER_CLOSE_OFFSET);
return;
}
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_close_connection_on_wrong_offset, 1, 2);
+ CloseConnectionWithDetails(
+ QUIC_STREAM_DATA_BEYOND_CLOSE_OFFSET,
+ QuicStrCat(
+ "Stream ", id_,
+ " received data with offset: ", frame.offset + frame.data_length,
+ ", which is beyond close offset: ", sequencer_.close_offset()));
+ return;
}
if (frame.fin) {
@@ -463,6 +489,23 @@ void QuicStream::OnStreamReset(const QuicRstStreamFrame& frame) {
"Reset frame stream offset overflow.");
return;
}
+
+ if (GetQuicReloadableFlag(quic_close_connection_on_wrong_offset)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_close_connection_on_wrong_offset, 2, 2);
+ const QuicStreamOffset kMaxOffset =
+ std::numeric_limits<QuicStreamOffset>::max();
+ if (sequencer()->close_offset() != kMaxOffset &&
+ frame.byte_offset != sequencer()->close_offset()) {
+ CloseConnectionWithDetails(
+ QUIC_STREAM_MULTIPLE_OFFSET,
+ QuicStrCat("Stream ", id_,
+ " received new final offset: ", frame.byte_offset,
+ ", which is different from close offset: ",
+ sequencer_.close_offset()));
+ return;
+ }
+ }
+
MaybeIncreaseHighestReceivedOffset(frame.byte_offset);
if (flow_controller_->FlowControlViolation() ||
connection_flow_controller_->FlowControlViolation()) {
@@ -624,64 +667,6 @@ void QuicStream::MaybeSendBlocked() {
}
}
-QuicConsumedData QuicStream::WritevData(const struct iovec* iov,
- int iov_count,
- bool fin) {
- if (write_side_closed_) {
- QUIC_DLOG(ERROR) << ENDPOINT << "Stream " << id()
- << "attempting to write when the write side is closed";
- if (type_ == READ_UNIDIRECTIONAL) {
- CloseConnectionWithDetails(
- QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM,
- "Try to send data on read unidirectional stream");
- }
- return QuicConsumedData(0, false);
- }
-
- // How much data was provided.
- size_t write_length = 0;
- if (iov != nullptr) {
- for (int i = 0; i < iov_count; ++i) {
- write_length += iov[i].iov_len;
- }
- }
-
- QuicConsumedData consumed_data(0, false);
- if (fin_buffered_) {
- QUIC_BUG << "Fin already buffered";
- return consumed_data;
- }
-
- if (kMaxStreamLength - send_buffer_.stream_offset() < write_length) {
- QUIC_BUG << "Write too many data via stream " << id_;
- CloseConnectionWithDetails(
- QUIC_STREAM_LENGTH_OVERFLOW,
- QuicStrCat("Write too many data via stream ", id_));
- return consumed_data;
- }
-
- bool had_buffered_data = HasBufferedData();
- if (CanWriteNewData()) {
- // Save all data if buffered data size is below low water mark.
- consumed_data.bytes_consumed = write_length;
- if (consumed_data.bytes_consumed > 0) {
- QuicStreamOffset offset = send_buffer_.stream_offset();
- send_buffer_.SaveStreamData(iov, iov_count, 0, write_length);
- OnDataBuffered(offset, write_length, nullptr);
- }
- }
- consumed_data.fin_consumed =
- consumed_data.bytes_consumed == write_length && fin;
- fin_buffered_ = consumed_data.fin_consumed;
-
- if (!had_buffered_data && (HasBufferedData() || fin_buffered_)) {
- // Write data if there is no buffered data before.
- WriteBufferedData();
- }
-
- return consumed_data;
-}
-
QuicConsumedData QuicStream::WriteMemSlices(QuicMemSliceSpan span, bool fin) {
QuicConsumedData consumed_data(0, false);
if (span.empty() && !fin) {
@@ -831,7 +816,7 @@ void QuicStream::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
return;
}
- if (flow_controller_->UpdateSendWindowOffset(frame.byte_offset)) {
+ if (flow_controller_->UpdateSendWindowOffset(frame.max_data)) {
// Let session unblock this stream.
session_->MarkConnectionLevelWriteBlocked(id_);
}
@@ -1055,9 +1040,7 @@ void QuicStream::WriteBufferedData() {
QUIC_DVLOG(1) << "stream " << id() << " shortens write length to "
<< write_length << " due to flow control";
}
- if (session_->session_decides_what_to_write()) {
- session_->SetTransmissionType(NOT_RETRANSMISSION);
- }
+ session_->SetTransmissionType(NOT_RETRANSMISSION);
StreamSendingState state = fin ? FIN : NO_FIN;
if (fin && add_random_padding_after_fin_) {
@@ -1180,10 +1163,6 @@ bool QuicStream::MaybeSetTtl(QuicTime::Delta ttl) {
QUIC_DLOG(WARNING) << "Deadline has already been set.";
return false;
}
- if (!session()->session_decides_what_to_write()) {
- QUIC_DLOG(WARNING) << "This session does not support stream TTL yet.";
- return false;
- }
QuicTime now = session()->connection()->clock()->ApproximateNow();
deadline_ = now + ttl;
return true;
@@ -1194,7 +1173,6 @@ bool QuicStream::HasDeadlinePassed() const {
// No deadline has been set.
return false;
}
- DCHECK(session()->session_decides_what_to_write());
QuicTime now = session()->connection()->clock()->ApproximateNow();
if (now < deadline_) {
return false;
@@ -1218,6 +1196,4 @@ void QuicStream::SendStopSending(uint16_t code) {
session_->SendStopSending(code, id_);
}
-void QuicStream::OnStopSending(uint16_t /*code*/) {}
-
} // 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 c8e5012767a..c936bc71264 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
@@ -136,9 +136,6 @@ class QUIC_EXPORT_PRIVATE QuicStream
virtual ~QuicStream();
- // Not in use currently.
- void SetFromConfig();
-
// QuicStreamSequencer::StreamInterface implementation.
QuicStreamId id() const override { return id_; }
// Called by the stream subclass after it has consumed the final incoming
@@ -247,9 +244,7 @@ class QUIC_EXPORT_PRIVATE QuicStream
// sent. If this is not true on deletion of the stream object, the session
// must keep track of the stream's byte offset until a definitive final value
// arrives.
- bool HasFinalReceivedByteOffset() const {
- return fin_received_ || rst_received_;
- }
+ bool HasReceivedFinalOffset() const { return fin_received_ || rst_received_; }
// Returns true if the stream has queued data waiting to write.
bool HasBufferedData() const;
@@ -341,11 +336,8 @@ class QUIC_EXPORT_PRIVATE QuicStream
// this method or not.
void SendStopSending(uint16_t code);
- // Invoked when QUIC receives a STOP_SENDING frame for this stream, informing
- // the application that the peer has sent a STOP_SENDING. The default
- // implementation is a noop. Is to be overridden by the application-specific
- // QuicStream class.
- virtual void OnStopSending(uint16_t code);
+ // Handle received StopSending frame.
+ virtual void OnStopSending(uint16_t /*code*/) {}
// Close the write side of the socket. Further writes will fail.
// Can be called by the subclass or internally.
@@ -356,16 +348,6 @@ class QUIC_EXPORT_PRIVATE QuicStream
bool is_static() const { return is_static_; }
protected:
- // Sends as many bytes in the first |count| buffers of |iov| to the connection
- // as the connection will consume. If FIN is consumed, the write side is
- // immediately closed.
- // Returns the number of bytes consumed by the connection.
- // Please note: Returned consumed data is the amount of data saved in send
- // buffer. The data is not necessarily consumed by the connection. So write
- // side is closed when FIN is sent.
- // TODO(fayang): Let WritevData return boolean.
- QuicConsumedData WritevData(const struct iovec* iov, int iov_count, bool fin);
-
// Close the read side of the socket. May cause the stream to be closed.
// Subclasses and consumers should use StopReading to terminate reading early
// if expecting a FIN. Can be used directly by subclasses if not expecting a
@@ -437,9 +419,6 @@ class QUIC_EXPORT_PRIVATE QuicStream
QuicOptional<QuicFlowController> flow_controller,
QuicFlowController* connection_flow_controller);
- // Subclasses and consumers should use reading_stopped.
- bool read_side_closed() const { return read_side_closed_; }
-
// Calls MaybeSendBlocked on the stream's flow controller and the connection
// level flow controller. If the stream is flow control blocked by the
// connection-level flow controller but not by the stream-level flow
@@ -501,10 +480,6 @@ class QUIC_EXPORT_PRIVATE QuicStream
// True if this stream has received a RST_STREAM frame.
bool rst_received_;
- // Tracks if the session this stream is running under was created by a
- // server or a client.
- Perspective perspective_;
-
QuicOptional<QuicFlowController> flow_controller_;
// The connection level flow controller. Not owned.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.h b/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.h
index 1ac2947fca7..e39e14fcf85 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.h
@@ -29,7 +29,7 @@ const int kMaxStreamsWindowDivisor = 2;
// This class manages the stream ids for Version 99/IETF QUIC.
class QUIC_EXPORT_PRIVATE QuicStreamIdManager {
public:
- class DelegateInterface {
+ class QUIC_EXPORT_PRIVATE DelegateInterface {
public:
virtual ~DelegateInterface() = default;
@@ -153,6 +153,10 @@ class QUIC_EXPORT_PRIVATE QuicStreamIdManager {
largest_peer_created_stream_id_ = largest_peer_created_stream_id;
}
+ QuicStreamId largest_peer_created_stream_id() const {
+ return largest_peer_created_stream_id_;
+ }
+
// These are the limits for outgoing and incoming streams,
// respectively. For incoming there are two limits, what has
// been advertised to the peer and what is actually available.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager_test.cc
index 7b7fb1a9e72..2ff55be857c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager_test.cc
@@ -13,7 +13,6 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.h"
using testing::_;
-using testing::Invoke;
using testing::StrictMock;
namespace quic {
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 ead192dd6fe..158afd80f63 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.cc
@@ -9,6 +9,7 @@
#include "net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
@@ -95,6 +96,8 @@ void QuicStreamSendBuffer::OnStreamDataConsumed(size_t bytes_consumed) {
bool QuicStreamSendBuffer::WriteStreamData(QuicStreamOffset offset,
QuicByteCount data_length,
QuicDataWriter* writer) {
+ // TODO(renjietang): Remove this variable once quic_coalesce_stream_frames_2
+ // is deprecated.
bool write_index_hit = false;
QuicDeque<BufferedSlice>::iterator slice_it =
write_index_ == -1
@@ -134,15 +137,33 @@ bool QuicStreamSendBuffer::WriteStreamData(QuicStreamOffset offset,
offset += copy_length;
data_length -= copy_length;
- if (write_index_hit && copy_length == available_bytes_in_slice) {
+ if (GetQuicRestartFlag(quic_coalesce_stream_frames_2)) {
+ QUIC_RESTART_FLAG_COUNT_N(quic_coalesce_stream_frames_2, 2, 3);
+ if (write_index_ != -1) {
+ QuicDeque<BufferedSlice>::const_iterator index_slice =
+ buffered_slices_.begin() + write_index_;
+ if (index_slice->offset == slice_it->offset &&
+ copy_length == available_bytes_in_slice) {
+ // The slice pointed by write_index has been fully written, advance
+ // write index.
+ ++write_index_;
+ }
+ }
+ } else if (write_index_hit && copy_length == available_bytes_in_slice) {
// Finished writing all data in current slice, advance write index for
// next write.
++write_index_;
}
}
- if (write_index_hit &&
- static_cast<size_t>(write_index_) == buffered_slices_.size()) {
+ if (GetQuicRestartFlag(quic_coalesce_stream_frames_2)) {
+ QUIC_RESTART_FLAG_COUNT_N(quic_coalesce_stream_frames_2, 3, 3);
+ if (write_index_ != -1 &&
+ static_cast<size_t>(write_index_) == buffered_slices_.size()) {
+ write_index_ = -1;
+ }
+ } else if (write_index_hit &&
+ static_cast<size_t>(write_index_) == buffered_slices_.size()) {
// Already write to the end off buffer.
QUIC_DVLOG(2) << "Finish writing out all buffered data.";
write_index_ = -1;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h
index 74e9d0d5ee2..51a10e9f325 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h
@@ -26,7 +26,7 @@ class QuicDataWriter;
// contiguous memory space. Please note, BufferedSlice is constructed when
// stream data is saved in send buffer and is removed when stream data is fully
// acked. It is move-only.
-struct BufferedSlice {
+struct QUIC_EXPORT_PRIVATE BufferedSlice {
BufferedSlice(QuicMemSlice mem_slice, QuicStreamOffset offset);
BufferedSlice(BufferedSlice&& other);
BufferedSlice& operator=(BufferedSlice&& other);
@@ -41,8 +41,9 @@ struct BufferedSlice {
QuicStreamOffset offset;
};
-struct StreamPendingRetransmission {
- StreamPendingRetransmission(QuicStreamOffset offset, QuicByteCount length)
+struct QUIC_EXPORT_PRIVATE StreamPendingRetransmission {
+ constexpr StreamPendingRetransmission(QuicStreamOffset offset,
+ QuicByteCount length)
: offset(offset), length(length) {}
// Starting offset of this pending retransmission.
@@ -50,8 +51,7 @@ struct StreamPendingRetransmission {
// Length of this pending retransmission.
QuicByteCount length;
- QUIC_EXPORT_PRIVATE bool operator==(
- const StreamPendingRetransmission& other) const;
+ bool operator==(const StreamPendingRetransmission& other) const;
};
// QuicStreamSendBuffer contains a list of QuicStreamDataSlices. New data slices
@@ -62,7 +62,7 @@ class QUIC_EXPORT_PRIVATE QuicStreamSendBuffer {
public:
explicit QuicStreamSendBuffer(QuicBufferAllocator* allocator);
QuicStreamSendBuffer(const QuicStreamSendBuffer& other) = delete;
- QuicStreamSendBuffer(QuicStreamSendBuffer&& other) = default;
+ QuicStreamSendBuffer(QuicStreamSendBuffer&& other) = delete;
~QuicStreamSendBuffer();
// Save |data_length| of data starts at |iov_offset| in |iov| to send buffer.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer_test.cc
index 3a5efb50e7f..90fcd6eb104 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer_test.cc
@@ -64,7 +64,7 @@ class QuicStreamSendBufferTest : public QuicTest {
void WriteAllData() {
// Write all data.
char buf[4000];
- QuicDataWriter writer(4000, buf, HOST_BYTE_ORDER);
+ QuicDataWriter writer(4000, buf, quiche::HOST_BYTE_ORDER);
send_buffer_.WriteStreamData(0, 3840u, &writer);
send_buffer_.OnStreamDataConsumed(3840u);
@@ -78,7 +78,7 @@ class QuicStreamSendBufferTest : public QuicTest {
TEST_F(QuicStreamSendBufferTest, CopyDataToBuffer) {
char buf[4000];
- QuicDataWriter writer(4000, buf, HOST_BYTE_ORDER);
+ QuicDataWriter writer(4000, buf, quiche::HOST_BYTE_ORDER);
std::string copy1(1024, 'a');
std::string copy2 =
std::string(512, 'a') + std::string(256, 'b') + std::string(256, 'c');
@@ -95,7 +95,7 @@ TEST_F(QuicStreamSendBufferTest, CopyDataToBuffer) {
EXPECT_EQ(copy4, QuicStringPiece(buf + 3072, 768));
// Test data piece across boundries.
- QuicDataWriter writer2(4000, buf, HOST_BYTE_ORDER);
+ QuicDataWriter writer2(4000, buf, quiche::HOST_BYTE_ORDER);
std::string copy5 =
std::string(536, 'a') + std::string(256, 'b') + std::string(232, 'c');
ASSERT_TRUE(send_buffer_.WriteStreamData(1000, 1024, &writer2));
@@ -105,7 +105,7 @@ TEST_F(QuicStreamSendBufferTest, CopyDataToBuffer) {
EXPECT_EQ(copy6, QuicStringPiece(buf + 1024, 1024));
// Invalid data copy.
- QuicDataWriter writer3(4000, buf, HOST_BYTE_ORDER);
+ QuicDataWriter writer3(4000, buf, quiche::HOST_BYTE_ORDER);
EXPECT_FALSE(send_buffer_.WriteStreamData(3000, 1024, &writer3));
EXPECT_QUIC_BUG(send_buffer_.WriteStreamData(0, 4000, &writer3),
"Writer fails to write.");
@@ -115,6 +115,41 @@ TEST_F(QuicStreamSendBufferTest, CopyDataToBuffer) {
EXPECT_EQ(3840u, send_buffer_.stream_bytes_outstanding());
}
+// Regression test for b/143491027.
+TEST_F(QuicStreamSendBufferTest,
+ WriteStreamDataContainsBothRetransmissionAndNewData) {
+ std::string copy1(1024, 'a');
+ std::string copy2 =
+ std::string(512, 'a') + std::string(256, 'b') + std::string(256, 'c');
+ std::string copy3 = std::string(1024, 'c') + std::string(100, 'd');
+ char buf[6000];
+ QuicDataWriter writer(6000, buf, quiche::HOST_BYTE_ORDER);
+ // Write more than one slice.
+ EXPECT_EQ(0, QuicStreamSendBufferPeer::write_index(&send_buffer_));
+ ASSERT_TRUE(send_buffer_.WriteStreamData(0, 1024, &writer));
+ EXPECT_EQ(copy1, QuicStringPiece(buf, 1024));
+ EXPECT_EQ(1, QuicStreamSendBufferPeer::write_index(&send_buffer_));
+
+ // Retransmit the first frame and also send new data.
+ ASSERT_TRUE(send_buffer_.WriteStreamData(0, 2048, &writer));
+ EXPECT_EQ(copy1 + copy2, QuicStringPiece(buf + 1024, 2048));
+
+ // Write new data.
+ if (!GetQuicRestartFlag(quic_coalesce_stream_frames_2)) {
+ EXPECT_EQ(1, QuicStreamSendBufferPeer::write_index(&send_buffer_));
+ EXPECT_QUIC_DEBUG_DEATH(send_buffer_.WriteStreamData(2048, 50, &writer),
+ "Tried to write data out of sequence.");
+ } else {
+ EXPECT_EQ(2, QuicStreamSendBufferPeer::write_index(&send_buffer_));
+ ASSERT_TRUE(send_buffer_.WriteStreamData(2048, 50, &writer));
+ EXPECT_EQ(std::string(50, 'c'), QuicStringPiece(buf + 1024 + 2048, 50));
+ EXPECT_EQ(2, QuicStreamSendBufferPeer::write_index(&send_buffer_));
+ ASSERT_TRUE(send_buffer_.WriteStreamData(2048, 1124, &writer));
+ EXPECT_EQ(copy3, QuicStringPiece(buf + 1024 + 2048 + 50, 1124));
+ EXPECT_EQ(3, QuicStreamSendBufferPeer::write_index(&send_buffer_));
+ }
+}
+
TEST_F(QuicStreamSendBufferTest, RemoveStreamFrame) {
WriteAllData();
@@ -255,7 +290,7 @@ TEST_F(QuicStreamSendBufferTest, PendingRetransmission) {
TEST_F(QuicStreamSendBufferTest, CurrentWriteIndex) {
char buf[4000];
- QuicDataWriter writer(4000, buf, HOST_BYTE_ORDER);
+ QuicDataWriter writer(4000, buf, quiche::HOST_BYTE_ORDER);
// With data buffered, index points to the 1st slice of data.
EXPECT_EQ(0u,
QuicStreamSendBufferPeer::CurrentWriteSlice(&send_buffer_)->offset);
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 8f84fb9475b..d7976689331 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
@@ -9,6 +9,7 @@
#include <string>
#include <utility>
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h"
@@ -26,6 +27,7 @@ namespace quic {
QuicStreamSequencer::QuicStreamSequencer(StreamInterface* quic_stream)
: stream_(quic_stream),
buffered_frames_(kStreamReceiveWindowLimit),
+ highest_offset_(0),
close_offset_(std::numeric_limits<QuicStreamOffset>::max()),
blocked_(false),
num_frames_received_(0),
@@ -33,7 +35,13 @@ QuicStreamSequencer::QuicStreamSequencer(StreamInterface* quic_stream)
ignore_read_data_(false),
level_triggered_(false),
stop_reading_when_level_triggered_(
- GetQuicReloadableFlag(quic_stop_reading_when_level_triggered)) {}
+ GetQuicReloadableFlag(quic_stop_reading_when_level_triggered)),
+ close_connection_and_discard_data_on_wrong_offset_(GetQuicReloadableFlag(
+ quic_close_connection_and_discard_data_on_wrong_offset)) {
+ if (stop_reading_when_level_triggered_) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_stop_reading_when_level_triggered);
+ }
+}
QuicStreamSequencer::~QuicStreamSequencer() {}
@@ -48,8 +56,9 @@ void QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) {
if (data_len == 0) {
return;
}
- if (GetQuicReloadableFlag(quic_no_stream_data_after_reset)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_no_stream_data_after_reset);
+ if (close_connection_and_discard_data_on_wrong_offset_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_close_connection_and_discard_data_on_wrong_offset, 1, 3);
if (!should_process_data) {
return;
}
@@ -66,6 +75,7 @@ void QuicStreamSequencer::OnCryptoFrame(const QuicCryptoFrame& frame) {
void QuicStreamSequencer::OnFrameData(QuicStreamOffset byte_offset,
size_t data_len,
const char* data_buffer) {
+ highest_offset_ = std::max(highest_offset_, byte_offset + data_len);
const size_t previous_readable_bytes = buffered_frames_.ReadableBytes();
size_t bytes_written;
std::string error_details;
@@ -123,7 +133,31 @@ bool QuicStreamSequencer::CloseStreamAtOffset(QuicStreamOffset offset) {
// If there is a scheduled close, the new offset should match it.
if (close_offset_ != kMaxOffset && offset != close_offset_) {
- stream_->Reset(QUIC_MULTIPLE_TERMINATION_OFFSETS);
+ if (!close_connection_and_discard_data_on_wrong_offset_) {
+ stream_->Reset(QUIC_MULTIPLE_TERMINATION_OFFSETS);
+ return false;
+ }
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_close_connection_and_discard_data_on_wrong_offset, 2, 3);
+ stream_->CloseConnectionWithDetails(
+ QUIC_STREAM_SEQUENCER_INVALID_STATE,
+ QuicStrCat("Stream ", stream_->id(),
+ " received new final offset: ", offset,
+ ", which is different from close offset: ", close_offset_));
+ return false;
+ }
+
+ // The final offset should be no less than the highest offset that is
+ // received.
+ if (close_connection_and_discard_data_on_wrong_offset_ &&
+ offset < highest_offset_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_close_connection_and_discard_data_on_wrong_offset, 3, 3);
+ stream_->CloseConnectionWithDetails(
+ QUIC_STREAM_SEQUENCER_INVALID_STATE,
+ QuicStrCat(
+ "Stream ", stream_->id(), " received fin with offset: ", offset,
+ ", which reduces current highest offset: ", highest_offset_));
return false;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer.h b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer.h
index a735a1ebbf5..878acb04307 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer.h
@@ -11,6 +11,7 @@
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
namespace quic {
@@ -24,7 +25,7 @@ class QuicStreamSequencerPeer;
class QUIC_EXPORT_PRIVATE QuicStreamSequencer {
public:
// Interface that thie Sequencer uses to communicate with the Stream.
- class StreamInterface {
+ class QUIC_EXPORT_PRIVATE StreamInterface {
public:
virtual ~StreamInterface() = default;
@@ -182,6 +183,9 @@ class QUIC_EXPORT_PRIVATE QuicStreamSequencer {
// Stores received data in offset order.
QuicStreamSequencerBuffer buffered_frames_;
+ // The highest offset that is received so far.
+ QuicStreamOffset highest_offset_;
+
// The offset, if any, we got a stream termination for. When this many bytes
// have been processed, the sequencer will be closed.
QuicStreamOffset close_offset_;
@@ -207,6 +211,11 @@ class QUIC_EXPORT_PRIVATE QuicStreamSequencer {
// the sequencer will discard incoming data (but not FIN bits) after
// StopReading is called, even in level_triggered_ mode.
const bool stop_reading_when_level_triggered_;
+
+ // Latched value of quic_close_connection_and_discard_data_on_wrong_offset.
+ // When true, the sequencer will inform the stream to close connection when
+ // wrong offset is received. And the stream frame's data will be discarded.
+ const bool close_connection_and_discard_data_on_wrong_offset_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h
index 93b723f1781..406cd92edc3 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h
@@ -85,7 +85,7 @@ class QUIC_EXPORT_PRIVATE QuicStreamSequencerBuffer {
static const size_t kBlockSizeBytes = 8 * 1024; // 8KB
// The basic storage block used by this buffer.
- struct BufferBlock {
+ struct QUIC_EXPORT_PRIVATE BufferBlock {
char buffer[kBlockSizeBytes];
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer_test.cc
index 028c12b6077..b17dcc498fa 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer_test.cc
@@ -110,15 +110,15 @@ TEST_F(QuicStreamSequencerBufferTest, ClearOnEmpty) {
TEST_F(QuicStreamSequencerBufferTest, OnStreamData0length) {
QuicErrorCode error =
buffer_->OnStreamData(800, "", &written_, &error_details_);
- EXPECT_EQ(error, QUIC_EMPTY_STREAM_FRAME_NO_FIN);
+ EXPECT_THAT(error, IsError(QUIC_EMPTY_STREAM_FRAME_NO_FIN));
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithinBlock) {
EXPECT_FALSE(helper_->IsBufferAllocated());
std::string source(1024, 'a');
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->OnStreamData(800, source, &written_, &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(800, source, &written_, &error_details_),
+ IsQuicNoError());
BufferBlock* block_ptr = helper_->GetBlock(0);
for (size_t i = 0; i < source.size(); ++i) {
ASSERT_EQ('a', block_ptr->buffer[helper_->GetInBlockOffset(800) + i]);
@@ -135,8 +135,8 @@ TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithinBlock) {
TEST_F(QuicStreamSequencerBufferTest, Move) {
EXPECT_FALSE(helper_->IsBufferAllocated());
std::string source(1024, 'a');
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->OnStreamData(800, source, &written_, &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(800, source, &written_, &error_details_),
+ IsQuicNoError());
BufferBlock* block_ptr = helper_->GetBlock(0);
for (size_t i = 0; i < source.size(); ++i) {
ASSERT_EQ('a', block_ptr->buffer[helper_->GetInBlockOffset(800) + i]);
@@ -160,8 +160,8 @@ TEST_F(QuicStreamSequencerBufferTest, OnStreamDataInvalidSource) {
// Pass in an invalid source, expects to return error.
QuicStringPiece source;
source = QuicStringPiece(nullptr, 1024);
- EXPECT_EQ(QUIC_STREAM_SEQUENCER_INVALID_STATE,
- buffer_->OnStreamData(800, source, &written_, &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(800, source, &written_, &error_details_),
+ IsError(QUIC_STREAM_SEQUENCER_INVALID_STATE));
EXPECT_EQ(0u, error_details_.find(QuicStrCat(
"QuicStreamSequencerBuffer error: OnStreamData() "
"dest == nullptr: ",
@@ -171,13 +171,13 @@ TEST_F(QuicStreamSequencerBufferTest, OnStreamDataInvalidSource) {
TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithOverlap) {
std::string source(1024, 'a');
// Write something into [800, 1824)
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->OnStreamData(800, source, &written_, &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(800, source, &written_, &error_details_),
+ IsQuicNoError());
// Try to write to [0, 1024) and [1024, 2048).
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->OnStreamData(0, source, &written_, &error_details_));
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->OnStreamData(1024, source, &written_, &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(0, source, &written_, &error_details_),
+ IsQuicNoError());
+ EXPECT_THAT(buffer_->OnStreamData(1024, source, &written_, &error_details_),
+ IsQuicNoError());
}
TEST_F(QuicStreamSequencerBufferTest,
@@ -188,31 +188,31 @@ TEST_F(QuicStreamSequencerBufferTest,
source = std::string(800, 'b');
std::string one_byte = "c";
// Write [1, 801).
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->OnStreamData(1, source, &written_, &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(1, source, &written_, &error_details_),
+ IsQuicNoError());
// Write [0, 800).
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->OnStreamData(0, source, &written_, &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(0, source, &written_, &error_details_),
+ IsQuicNoError());
// Write [1823, 1824).
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->OnStreamData(1823, one_byte, &written_, &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(1823, one_byte, &written_, &error_details_),
+ IsQuicNoError());
EXPECT_EQ(0u, written_);
// write one byte to [1824, 1825)
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->OnStreamData(1824, one_byte, &written_, &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(1824, one_byte, &written_, &error_details_),
+ IsQuicNoError());
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithoutOverlap) {
std::string source(1024, 'a');
// Write something into [800, 1824).
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->OnStreamData(800, source, &written_, &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(800, source, &written_, &error_details_),
+ IsQuicNoError());
source = std::string(100, 'b');
// Write something into [kBlockSizeBytes * 2 - 20, kBlockSizeBytes * 2 + 80).
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->OnStreamData(kBlockSizeBytes * 2 - 20, source, &written_,
- &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(kBlockSizeBytes * 2 - 20, source, &written_,
+ &error_details_),
+ IsQuicNoError());
EXPECT_EQ(3, helper_->IntervalSize());
EXPECT_EQ(1024u + 100u, buffer_->BytesBuffered());
EXPECT_TRUE(helper_->CheckBufferInvariants());
@@ -229,20 +229,20 @@ TEST_F(QuicStreamSequencerBufferTest, OnStreamDataInLongStreamWithOverlap) {
std::string source(kBytesToWrite, 'a');
// Frame [2^32 + 500, 2^32 + 600).
QuicStreamOffset offset = pow(2, 32) + 500;
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->OnStreamData(offset, source, &written_, &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(offset, source, &written_, &error_details_),
+ IsQuicNoError());
EXPECT_EQ(2, helper_->IntervalSize());
// Frame [2^32 + 700, 2^32 + 800).
offset = pow(2, 32) + 700;
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->OnStreamData(offset, source, &written_, &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(offset, source, &written_, &error_details_),
+ IsQuicNoError());
EXPECT_EQ(3, helper_->IntervalSize());
// Another frame [2^32 + 300, 2^32 + 400).
offset = pow(2, 32) + 300;
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->OnStreamData(offset, source, &written_, &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(offset, source, &written_, &error_details_),
+ IsQuicNoError());
EXPECT_EQ(4, helper_->IntervalSize());
}
@@ -250,9 +250,9 @@ TEST_F(QuicStreamSequencerBufferTest, OnStreamDataTillEnd) {
// Write 50 bytes to the end.
const size_t kBytesToWrite = 50;
std::string source(kBytesToWrite, 'a');
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->OnStreamData(max_capacity_bytes_ - kBytesToWrite, source,
- &written_, &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(max_capacity_bytes_ - kBytesToWrite, source,
+ &written_, &error_details_),
+ IsQuicNoError());
EXPECT_EQ(50u, buffer_->BytesBuffered());
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
@@ -261,42 +261,42 @@ TEST_F(QuicStreamSequencerBufferTest, OnStreamDataTillEndCorner) {
// Write 1 byte to the end.
const size_t kBytesToWrite = 1;
std::string source(kBytesToWrite, 'a');
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->OnStreamData(max_capacity_bytes_ - kBytesToWrite, source,
- &written_, &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(max_capacity_bytes_ - kBytesToWrite, source,
+ &written_, &error_details_),
+ IsQuicNoError());
EXPECT_EQ(1u, buffer_->BytesBuffered());
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
TEST_F(QuicStreamSequencerBufferTest, OnStreamDataBeyondCapacity) {
std::string source(60, 'a');
- EXPECT_EQ(QUIC_INTERNAL_ERROR,
- buffer_->OnStreamData(max_capacity_bytes_ - 50, source, &written_,
- &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(max_capacity_bytes_ - 50, source, &written_,
+ &error_details_),
+ IsError(QUIC_INTERNAL_ERROR));
EXPECT_TRUE(helper_->CheckBufferInvariants());
source = "b";
- EXPECT_EQ(QUIC_INTERNAL_ERROR,
- buffer_->OnStreamData(max_capacity_bytes_, source, &written_,
- &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(max_capacity_bytes_, source, &written_,
+ &error_details_),
+ IsError(QUIC_INTERNAL_ERROR));
EXPECT_TRUE(helper_->CheckBufferInvariants());
- EXPECT_EQ(QUIC_INTERNAL_ERROR,
- buffer_->OnStreamData(max_capacity_bytes_ * 1000, source, &written_,
- &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(max_capacity_bytes_ * 1000, source,
+ &written_, &error_details_),
+ IsError(QUIC_INTERNAL_ERROR));
EXPECT_TRUE(helper_->CheckBufferInvariants());
// Disallow current_gap != gaps_.end()
- EXPECT_EQ(QUIC_INTERNAL_ERROR,
- buffer_->OnStreamData(static_cast<QuicStreamOffset>(-1), source,
- &written_, &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(static_cast<QuicStreamOffset>(-1), source,
+ &written_, &error_details_),
+ IsError(QUIC_INTERNAL_ERROR));
EXPECT_TRUE(helper_->CheckBufferInvariants());
// Disallow offset + size overflow
source = "bbb";
- EXPECT_EQ(QUIC_INTERNAL_ERROR,
- buffer_->OnStreamData(static_cast<QuicStreamOffset>(-2), source,
- &written_, &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(static_cast<QuicStreamOffset>(-2), source,
+ &written_, &error_details_),
+ IsError(QUIC_INTERNAL_ERROR));
EXPECT_TRUE(helper_->CheckBufferInvariants());
EXPECT_EQ(0u, buffer_->BytesBuffered());
}
@@ -314,7 +314,8 @@ TEST_F(QuicStreamSequencerBufferTest, Readv100Bytes) {
char dest[120];
iovec iovecs[3]{iovec{dest, 40}, iovec{dest + 40, 40}, iovec{dest + 80, 40}};
size_t read;
- EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(iovecs, 3, &read, &error_details_));
+ EXPECT_THAT(buffer_->Readv(iovecs, 3, &read, &error_details_),
+ IsQuicNoError());
QUIC_LOG(ERROR) << error_details_;
EXPECT_EQ(100u, read);
EXPECT_EQ(100u, buffer_->BytesConsumed());
@@ -335,7 +336,8 @@ TEST_F(QuicStreamSequencerBufferTest, ReadvAcrossBlocks) {
std::fill(dest, dest + 512, 0);
iovec iovecs[2]{iovec{dest, 256}, iovec{dest + 256, 256}};
size_t read;
- EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(iovecs, 2, &read, &error_details_));
+ EXPECT_THAT(buffer_->Readv(iovecs, 2, &read, &error_details_),
+ IsQuicNoError());
}
// The last read only reads the rest 50 bytes in 2nd block.
EXPECT_EQ(std::string(50, 'a'), std::string(dest, 50));
@@ -353,7 +355,7 @@ TEST_F(QuicStreamSequencerBufferTest, ClearAfterRead) {
char dest[512]{0};
const iovec iov{dest, 512};
size_t read;
- EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(&iov, 1, &read, &error_details_));
+ EXPECT_THAT(buffer_->Readv(&iov, 1, &read, &error_details_), IsQuicNoError());
// Clear() should make buffer empty while preserving BytesConsumed()
buffer_->Clear();
EXPECT_TRUE(buffer_->Empty());
@@ -369,14 +371,15 @@ TEST_F(QuicStreamSequencerBufferTest,
char dest[512]{0};
const iovec iov{dest, 512};
size_t read;
- EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(&iov, 1, &read, &error_details_));
+ EXPECT_THAT(buffer_->Readv(&iov, 1, &read, &error_details_), IsQuicNoError());
EXPECT_EQ(source.size(), written_);
// Write more than half block size of bytes in the last block with 'b', which
// will wrap to the beginning and reaches the full capacity.
source = std::string(0.5 * kBlockSizeBytes + 512, 'b');
- EXPECT_EQ(QUIC_NO_ERROR, buffer_->OnStreamData(2 * kBlockSizeBytes, source,
- &written_, &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(2 * kBlockSizeBytes, source, &written_,
+ &error_details_),
+ IsQuicNoError());
EXPECT_EQ(source.size(), written_);
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
@@ -390,14 +393,14 @@ TEST_F(QuicStreamSequencerBufferTest,
char dest[512]{0};
const iovec iov{dest, 512};
size_t read;
- EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(&iov, 1, &read, &error_details_));
+ EXPECT_THAT(buffer_->Readv(&iov, 1, &read, &error_details_), IsQuicNoError());
// Try to write from [max_capacity_bytes_ - 0.5 * kBlockSizeBytes,
// max_capacity_bytes_ + 512 + 1). But last bytes exceeds current capacity.
source = std::string(0.5 * kBlockSizeBytes + 512 + 1, 'b');
- EXPECT_EQ(QUIC_INTERNAL_ERROR,
- buffer_->OnStreamData(2 * kBlockSizeBytes, source, &written_,
- &error_details_));
+ EXPECT_THAT(buffer_->OnStreamData(2 * kBlockSizeBytes, source, &written_,
+ &error_details_),
+ IsError(QUIC_INTERNAL_ERROR));
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
@@ -409,7 +412,7 @@ TEST_F(QuicStreamSequencerBufferTest, ReadvAcrossLastBlock) {
char dest[512]{0};
const iovec iov{dest, 512};
size_t read;
- EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(&iov, 1, &read, &error_details_));
+ EXPECT_THAT(buffer_->Readv(&iov, 1, &read, &error_details_), IsQuicNoError());
source = std::string(256, 'b');
buffer_->OnStreamData(max_capacity_bytes_, source, &written_,
&error_details_);
@@ -419,7 +422,8 @@ TEST_F(QuicStreamSequencerBufferTest, ReadvAcrossLastBlock) {
std::unique_ptr<char[]> dest1{new char[max_capacity_bytes_]};
dest1[0] = 0;
const iovec iov1{dest1.get(), max_capacity_bytes_};
- EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(&iov1, 1, &read, &error_details_));
+ EXPECT_THAT(buffer_->Readv(&iov1, 1, &read, &error_details_),
+ IsQuicNoError());
EXPECT_EQ(max_capacity_bytes_ - 512 + 256, read);
EXPECT_EQ(max_capacity_bytes_ + 256, buffer_->BytesConsumed());
EXPECT_TRUE(buffer_->Empty());
@@ -430,7 +434,7 @@ TEST_F(QuicStreamSequencerBufferTest, ReadvEmpty) {
char dest[512]{0};
iovec iov{dest, 512};
size_t read;
- EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(&iov, 1, &read, &error_details_));
+ EXPECT_THAT(buffer_->Readv(&iov, 1, &read, &error_details_), IsQuicNoError());
EXPECT_EQ(0u, read);
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
@@ -452,7 +456,8 @@ TEST_F(QuicStreamSequencerBufferTest, ReleaseWholeBuffer) {
char dest[120];
iovec iovecs[3]{iovec{dest, 40}, iovec{dest + 40, 40}, iovec{dest + 80, 40}};
size_t read;
- EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(iovecs, 3, &read, &error_details_));
+ EXPECT_THAT(buffer_->Readv(iovecs, 3, &read, &error_details_),
+ IsQuicNoError());
EXPECT_EQ(100u, read);
EXPECT_EQ(100u, buffer_->BytesConsumed());
EXPECT_TRUE(helper_->CheckBufferInvariants());
@@ -847,7 +852,7 @@ TEST_F(QuicStreamSequencerBufferTest, TooManyGaps) {
QuicStreamOffset last_straw = 2 * kMaxNumGapsAllowed - 1;
if (begin == last_straw) {
- EXPECT_EQ(QUIC_TOO_MANY_STREAM_DATA_INTERVALS, rs);
+ EXPECT_THAT(rs, IsError(QUIC_TOO_MANY_STREAM_DATA_INTERVALS));
EXPECT_EQ("Too many data intervals received for this stream.",
error_details_);
break;
@@ -982,9 +987,9 @@ TEST_F(QuicStreamSequencerBufferRandomIOTest, RandomWriteAndReadv) {
num_to_read += dest_iov[i].iov_len;
}
size_t actually_read;
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->Readv(dest_iov, kNumReads, &actually_read,
- &error_details_));
+ EXPECT_THAT(buffer_->Readv(dest_iov, kNumReads, &actually_read,
+ &error_details_),
+ IsQuicNoError());
ASSERT_LE(actually_read, num_to_read);
QUIC_DVLOG(1) << " read from offset: " << total_bytes_read_
<< " size: " << num_to_read
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_test.cc
index 8ad845b80a7..cb6fb936cf6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_test.cc
@@ -15,6 +15,7 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
@@ -374,12 +375,16 @@ TEST_F(QuicStreamSequencerTest, MultipleOffsets) {
OnFinFrame(3, "");
EXPECT_EQ(3u, QuicStreamSequencerPeer::GetCloseOffset(sequencer_.get()));
- EXPECT_CALL(stream_, Reset(QUIC_MULTIPLE_TERMINATION_OFFSETS));
+ if (!GetQuicReloadableFlag(
+ quic_close_connection_and_discard_data_on_wrong_offset)) {
+ EXPECT_CALL(stream_, Reset(QUIC_MULTIPLE_TERMINATION_OFFSETS));
+ } else {
+ EXPECT_CALL(stream_, CloseConnectionWithDetails(
+ QUIC_STREAM_SEQUENCER_INVALID_STATE,
+ "Stream 1 received new final offset: 1, which is "
+ "different from close offset: 3"));
+ }
OnFinFrame(1, "");
- EXPECT_EQ(3u, QuicStreamSequencerPeer::GetCloseOffset(sequencer_.get()));
-
- OnFinFrame(3, "");
- EXPECT_EQ(3u, QuicStreamSequencerPeer::GetCloseOffset(sequencer_.get()));
}
class QuicSequencerRandomTest : public QuicStreamSequencerTest {
@@ -756,14 +761,35 @@ TEST_F(QuicStreamSequencerTest, StopReadingWithLevelTriggered) {
// Regression test for https://crbug.com/992486.
TEST_F(QuicStreamSequencerTest, CorruptFinFrames) {
- SetQuicReloadableFlag(quic_no_stream_data_after_reset, true);
- EXPECT_CALL(stream_, Reset(QUIC_MULTIPLE_TERMINATION_OFFSETS));
+ if (!GetQuicReloadableFlag(
+ quic_close_connection_and_discard_data_on_wrong_offset)) {
+ return;
+ }
+ EXPECT_CALL(stream_, CloseConnectionWithDetails(
+ QUIC_STREAM_SEQUENCER_INVALID_STATE,
+ "Stream 1 received new final offset: 1, which is "
+ "different from close offset: 2"));
OnFinFrame(2u, "");
OnFinFrame(0u, "a");
EXPECT_FALSE(sequencer_->HasBytesToRead());
}
+// Regression test for crbug.com/1015693
+TEST_F(QuicStreamSequencerTest, ReceiveFinLessThanHighestOffset) {
+ if (!GetQuicReloadableFlag(
+ quic_close_connection_and_discard_data_on_wrong_offset)) {
+ return;
+ }
+ EXPECT_CALL(stream_, OnDataAvailable()).Times(1);
+ EXPECT_CALL(stream_, CloseConnectionWithDetails(
+ QUIC_STREAM_SEQUENCER_INVALID_STATE,
+ "Stream 1 received fin with offset: 0, which "
+ "reduces current highest offset: 3"));
+ OnFrame(0u, "abc");
+ OnFinFrame(0u, "");
+}
+
} // namespace
} // namespace test
} // namespace quic
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 411d6d00858..673c7a7405c 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
@@ -8,8 +8,10 @@
#include <string>
#include <utility>
+#include "net/third_party/quiche/src/quic/core/frames/quic_rst_stream_frame.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
@@ -50,12 +52,14 @@ const size_t kDataLen = 9;
class TestStream : public QuicStream {
public:
TestStream(QuicStreamId id, QuicSession* session, StreamType type)
- : QuicStream(id, session, /*is_static=*/false, type) {}
+ : QuicStream(id, session, /*is_static=*/false, type) {
+ sequencer()->set_level_triggered(true);
+ }
TestStream(PendingStream* pending, StreamType type, bool is_static)
: QuicStream(pending, type, is_static) {}
- void OnDataAvailable() override {}
+ MOCK_METHOD0(OnDataAvailable, void());
MOCK_METHOD0(OnCanWriteNewData, void());
@@ -66,7 +70,6 @@ class TestStream : public QuicStream {
using QuicStream::OnClose;
using QuicStream::WriteMemSlices;
using QuicStream::WriteOrBufferData;
- using QuicStream::WritevData;
private:
std::string data_;
@@ -99,7 +102,8 @@ class QuicStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
session_->config(), 10);
session_->OnConfigNegotiated();
- stream_ = new TestStream(kTestStreamId, session_.get(), BIDIRECTIONAL);
+ stream_ = new StrictMock<TestStream>(kTestStreamId, session_.get(),
+ BIDIRECTIONAL);
EXPECT_NE(nullptr, stream_);
// session_ now owns stream_.
session_->ActivateStream(QuicWrapUnique(stream_));
@@ -144,7 +148,7 @@ class QuicStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
MockAlarmFactory alarm_factory_;
MockQuicConnection* connection_;
std::unique_ptr<MockQuicSession> session_;
- TestStream* stream_;
+ StrictMock<TestStream>* stream_;
QuicWriteBlockedList* write_blocked_list_;
QuicTime::Delta zero_;
ParsedQuicVersionVector supported_versions_;
@@ -177,8 +181,7 @@ TEST_P(QuicStreamTest, PendingStreamTooMuchData) {
// Receive a stream frame that violates flow control: the byte offset is
// higher than the receive window offset.
QuicStreamFrame frame(kTestStreamId + 2, false,
- kInitialSessionFlowControlWindowForTest + 1,
- QuicStringPiece("."));
+ kInitialSessionFlowControlWindowForTest + 1, ".");
// Stream should not accept the frame, and the connection should be closed.
EXPECT_CALL(*connection_,
@@ -221,10 +224,10 @@ TEST_P(QuicStreamTest, FromPendingStream) {
PendingStream pending(kTestStreamId + 2, session_.get());
- QuicStreamFrame frame(kTestStreamId + 2, false, 2, QuicStringPiece("."));
+ QuicStreamFrame frame(kTestStreamId + 2, false, 2, ".");
pending.OnStreamFrame(frame);
pending.OnStreamFrame(frame);
- QuicStreamFrame frame2(kTestStreamId + 2, true, 3, QuicStringPiece("."));
+ QuicStreamFrame frame2(kTestStreamId + 2, true, 3, ".");
pending.OnStreamFrame(frame2);
TestStream stream(&pending, StreamType::READ_UNIDIRECTIONAL, false);
@@ -243,14 +246,14 @@ TEST_P(QuicStreamTest, FromPendingStreamThenData) {
PendingStream pending(kTestStreamId + 2, session_.get());
- QuicStreamFrame frame(kTestStreamId + 2, false, 2, QuicStringPiece("."));
+ QuicStreamFrame frame(kTestStreamId + 2, false, 2, ".");
pending.OnStreamFrame(frame);
auto stream =
new TestStream(&pending, StreamType::READ_UNIDIRECTIONAL, false);
session_->ActivateStream(QuicWrapUnique(stream));
- QuicStreamFrame frame2(kTestStreamId + 2, true, 3, QuicStringPiece("."));
+ QuicStreamFrame frame2(kTestStreamId + 2, true, 3, ".");
stream->OnStreamFrame(frame2);
EXPECT_EQ(2, stream->num_frames_received());
@@ -301,11 +304,7 @@ TEST_P(QuicStreamTest, BlockIfOnlySomeDataConsumed) {
NO_FIN);
}));
stream_->WriteOrBufferData(QuicStringPiece(kData1, 2), false, nullptr);
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams());
EXPECT_EQ(1u, stream_->BufferedDataBytes());
}
@@ -323,11 +322,7 @@ TEST_P(QuicStreamTest, BlockIfFinNotConsumedWithData) {
NO_FIN);
}));
stream_->WriteOrBufferData(QuicStringPiece(kData1, 2), true, nullptr);
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams());
}
@@ -374,11 +369,7 @@ TEST_P(QuicStreamTest, WriteOrBufferData) {
}));
stream_->WriteOrBufferData(kData1, false, nullptr);
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_EQ(1u, stream_->BufferedDataBytes());
EXPECT_TRUE(HasWriteBlockedStreams());
@@ -392,12 +383,9 @@ TEST_P(QuicStreamTest, WriteOrBufferData) {
return MockQuicSession::ConsumeData(stream_, stream_->id(),
kDataLen - 1, kDataLen - 1, NO_FIN);
}));
+ EXPECT_CALL(*stream_, OnCanWriteNewData());
stream_->OnCanWrite();
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
// And finally the end of the bytes_consumed.
EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
@@ -405,12 +393,9 @@ TEST_P(QuicStreamTest, WriteOrBufferData) {
return MockQuicSession::ConsumeData(stream_, stream_->id(), 2u,
2 * kDataLen - 2, NO_FIN);
}));
+ EXPECT_CALL(*stream_, OnCanWriteNewData());
stream_->OnCanWrite();
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
}
TEST_P(QuicStreamTest, WriteOrBufferDataReachStreamLimit) {
@@ -421,11 +406,7 @@ TEST_P(QuicStreamTest, WriteOrBufferDataReachStreamLimit) {
EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillOnce(Invoke(&(MockQuicSession::ConsumeData)));
stream_->WriteOrBufferData(data, false, nullptr);
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_CALL(*connection_, CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _));
EXPECT_QUIC_BUG(stream_->WriteOrBufferData("a", false, nullptr),
"Write too many data via stream");
@@ -436,12 +417,12 @@ TEST_P(QuicStreamTest, ConnectionCloseAfterStreamClose) {
QuicStreamPeer::CloseReadSide(stream_);
stream_->CloseWriteSide();
- EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error());
- EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error());
+ EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
+ EXPECT_THAT(stream_->connection_error(), IsQuicNoError());
stream_->OnConnectionClosed(QUIC_INTERNAL_ERROR,
ConnectionCloseSource::FROM_SELF);
- EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error());
- EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error());
+ EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
+ EXPECT_THAT(stream_->connection_error(), IsQuicNoError());
}
TEST_P(QuicStreamTest, RstAlwaysSentIfNoFinSent) {
@@ -460,11 +441,7 @@ TEST_P(QuicStreamTest, RstAlwaysSentIfNoFinSent) {
NO_FIN);
}));
stream_->WriteOrBufferData(QuicStringPiece(kData1, 1), false, nullptr);
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_FALSE(fin_sent());
EXPECT_FALSE(rst_sent());
@@ -540,9 +517,8 @@ TEST_P(QuicStreamTest, StreamFlowControlMultipleWindowUpdates) {
QuicWindowUpdateFrame window_update_1(kInvalidControlFrameId, stream_->id(),
kMinimumFlowControlSendWindow + 5);
stream_->OnWindowUpdateFrame(window_update_1);
- EXPECT_EQ(
- window_update_1.byte_offset,
- QuicFlowControllerPeer::SendWindowOffset(stream_->flow_controller()));
+ EXPECT_EQ(window_update_1.max_data, QuicFlowControllerPeer::SendWindowOffset(
+ stream_->flow_controller()));
// Now send a few more WINDOW_UPDATES and make sure that only the largest is
// remembered.
@@ -555,9 +531,8 @@ TEST_P(QuicStreamTest, StreamFlowControlMultipleWindowUpdates) {
stream_->OnWindowUpdateFrame(window_update_2);
stream_->OnWindowUpdateFrame(window_update_3);
stream_->OnWindowUpdateFrame(window_update_4);
- EXPECT_EQ(
- window_update_3.byte_offset,
- QuicFlowControllerPeer::SendWindowOffset(stream_->flow_controller()));
+ EXPECT_EQ(window_update_3.max_data, QuicFlowControllerPeer::SendWindowOffset(
+ stream_->flow_controller()));
}
TEST_P(QuicStreamTest, FrameStats) {
@@ -565,13 +540,16 @@ TEST_P(QuicStreamTest, FrameStats) {
EXPECT_EQ(0, stream_->num_frames_received());
EXPECT_EQ(0, stream_->num_duplicate_frames_received());
- QuicStreamFrame frame(stream_->id(), false, 0, QuicStringPiece("."));
+ QuicStreamFrame frame(stream_->id(), false, 0, ".");
+ EXPECT_CALL(*stream_, OnDataAvailable()).Times(2);
stream_->OnStreamFrame(frame);
EXPECT_EQ(1, stream_->num_frames_received());
EXPECT_EQ(0, stream_->num_duplicate_frames_received());
stream_->OnStreamFrame(frame);
EXPECT_EQ(2, stream_->num_frames_received());
EXPECT_EQ(1, stream_->num_duplicate_frames_received());
+ QuicStreamFrame frame2(stream_->id(), false, 1, "abc");
+ stream_->OnStreamFrame(frame2);
}
// Verify that when we receive a packet which violates flow control (i.e. sends
@@ -583,8 +561,7 @@ TEST_P(QuicStreamTest, StreamSequencerNeverSeesPacketsViolatingFlowControl) {
// Receive a stream frame that violates flow control: the byte offset is
// higher than the receive window offset.
QuicStreamFrame frame(stream_->id(), false,
- kInitialSessionFlowControlWindowForTest + 1,
- QuicStringPiece("."));
+ kInitialSessionFlowControlWindowForTest + 1, ".");
EXPECT_GT(frame.offset, QuicFlowControllerPeer::ReceiveWindowOffset(
stream_->flow_controller()));
@@ -597,6 +574,7 @@ TEST_P(QuicStreamTest, StreamSequencerNeverSeesPacketsViolatingFlowControl) {
// Verify that after the consumer calls StopReading(), the stream still sends
// flow control updates.
TEST_P(QuicStreamTest, StopReadingSendsFlowControl) {
+ SetQuicReloadableFlag(quic_stop_reading_when_level_triggered, true);
Initialize();
stream_->StopReading();
@@ -624,40 +602,38 @@ TEST_P(QuicStreamTest, StopReadingSendsFlowControl) {
TEST_P(QuicStreamTest, FinalByteOffsetFromFin) {
Initialize();
- EXPECT_FALSE(stream_->HasFinalReceivedByteOffset());
+ EXPECT_FALSE(stream_->HasReceivedFinalOffset());
- QuicStreamFrame stream_frame_no_fin(stream_->id(), false, 1234,
- QuicStringPiece("."));
+ QuicStreamFrame stream_frame_no_fin(stream_->id(), false, 1234, ".");
stream_->OnStreamFrame(stream_frame_no_fin);
- EXPECT_FALSE(stream_->HasFinalReceivedByteOffset());
+ EXPECT_FALSE(stream_->HasReceivedFinalOffset());
- QuicStreamFrame stream_frame_with_fin(stream_->id(), true, 1234,
- QuicStringPiece("."));
+ QuicStreamFrame stream_frame_with_fin(stream_->id(), true, 1234, ".");
stream_->OnStreamFrame(stream_frame_with_fin);
- EXPECT_TRUE(stream_->HasFinalReceivedByteOffset());
+ EXPECT_TRUE(stream_->HasReceivedFinalOffset());
}
TEST_P(QuicStreamTest, FinalByteOffsetFromRst) {
Initialize();
- EXPECT_FALSE(stream_->HasFinalReceivedByteOffset());
+ EXPECT_FALSE(stream_->HasReceivedFinalOffset());
QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(),
QUIC_STREAM_CANCELLED, 1234);
stream_->OnStreamReset(rst_frame);
- EXPECT_TRUE(stream_->HasFinalReceivedByteOffset());
+ EXPECT_TRUE(stream_->HasReceivedFinalOffset());
}
TEST_P(QuicStreamTest, InvalidFinalByteOffsetFromRst) {
Initialize();
- EXPECT_FALSE(stream_->HasFinalReceivedByteOffset());
+ EXPECT_FALSE(stream_->HasReceivedFinalOffset());
QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(),
QUIC_STREAM_CANCELLED, 0xFFFFFFFFFFFF);
// Stream should not accept the frame, and the connection should be closed.
EXPECT_CALL(*connection_,
CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _));
stream_->OnStreamReset(rst_frame);
- EXPECT_TRUE(stream_->HasFinalReceivedByteOffset());
+ EXPECT_TRUE(stream_->HasReceivedFinalOffset());
stream_->OnClose();
}
@@ -670,7 +646,7 @@ TEST_P(QuicStreamTest, FinalByteOffsetFromZeroLengthStreamFrame) {
// ignores such a stream frame.
Initialize();
- EXPECT_FALSE(stream_->HasFinalReceivedByteOffset());
+ EXPECT_FALSE(stream_->HasReceivedFinalOffset());
const QuicStreamOffset kByteOffsetExceedingFlowControlWindow =
kInitialSessionFlowControlWindowForTest + 1;
const QuicStreamOffset current_stream_flow_control_offset =
@@ -688,7 +664,7 @@ TEST_P(QuicStreamTest, FinalByteOffsetFromZeroLengthStreamFrame) {
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
stream_->OnStreamFrame(zero_length_stream_frame_with_fin);
- EXPECT_TRUE(stream_->HasFinalReceivedByteOffset());
+ EXPECT_TRUE(stream_->HasReceivedFinalOffset());
// The flow control receive offset values should not have changed.
EXPECT_EQ(
@@ -721,11 +697,9 @@ TEST_P(QuicStreamTest, OnStreamFrameUpperLimit) {
EXPECT_CALL(*connection_, CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _))
.Times(0);
- QuicStreamFrame stream_frame(stream_->id(), false, kMaxStreamLength - 1,
- QuicStringPiece("."));
+ QuicStreamFrame stream_frame(stream_->id(), false, kMaxStreamLength - 1, ".");
stream_->OnStreamFrame(stream_frame);
- QuicStreamFrame stream_frame2(stream_->id(), true, kMaxStreamLength,
- QuicStringPiece(""));
+ QuicStreamFrame stream_frame2(stream_->id(), true, kMaxStreamLength, "");
stream_->OnStreamFrame(stream_frame2);
}
@@ -733,8 +707,7 @@ TEST_P(QuicStreamTest, StreamTooLong) {
Initialize();
EXPECT_CALL(*connection_, CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _))
.Times(1);
- QuicStreamFrame stream_frame(stream_->id(), false, kMaxStreamLength,
- QuicStringPiece("."));
+ QuicStreamFrame stream_frame(stream_->id(), false, kMaxStreamLength, ".");
EXPECT_QUIC_PEER_BUG(stream_->OnStreamFrame(stream_frame),
QuicStrCat("Receive stream frame on stream ",
stream_->id(), " reaches max stream length"));
@@ -745,11 +718,10 @@ TEST_P(QuicStreamTest, SetDrainingIncomingOutgoing) {
Initialize();
// Incoming data with FIN.
- QuicStreamFrame stream_frame_with_fin(stream_->id(), true, 1234,
- QuicStringPiece("."));
+ QuicStreamFrame stream_frame_with_fin(stream_->id(), true, 1234, ".");
stream_->OnStreamFrame(stream_frame_with_fin);
// The FIN has been received but not consumed.
- EXPECT_TRUE(stream_->HasFinalReceivedByteOffset());
+ EXPECT_TRUE(stream_->HasReceivedFinalOffset());
EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
EXPECT_FALSE(stream_->reading_stopped());
@@ -785,11 +757,10 @@ TEST_P(QuicStreamTest, SetDrainingOutgoingIncoming) {
EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
// Incoming data with FIN.
- QuicStreamFrame stream_frame_with_fin(stream_->id(), true, 1234,
- QuicStringPiece("."));
+ QuicStreamFrame stream_frame_with_fin(stream_->id(), true, 1234, ".");
stream_->OnStreamFrame(stream_frame_with_fin);
// The FIN has been received but not consumed.
- EXPECT_TRUE(stream_->HasFinalReceivedByteOffset());
+ EXPECT_TRUE(stream_->HasReceivedFinalOffset());
EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
EXPECT_FALSE(stream_->reading_stopped());
@@ -808,7 +779,8 @@ TEST_P(QuicStreamTest, EarlyResponseFinHandling) {
.WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
// Receive data for the request.
- QuicStreamFrame frame1(stream_->id(), false, 0, QuicStringPiece("Start"));
+ EXPECT_CALL(*stream_, OnDataAvailable()).Times(1);
+ QuicStreamFrame frame1(stream_->id(), false, 0, "Start");
stream_->OnStreamFrame(frame1);
// When QuicSimpleServerStream sends the response, it calls
// QuicStream::CloseReadSide() first.
@@ -817,10 +789,10 @@ TEST_P(QuicStreamTest, EarlyResponseFinHandling) {
stream_->WriteOrBufferData(kData1, false, nullptr);
EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream_));
// Receive remaining data and FIN for the request.
- QuicStreamFrame frame2(stream_->id(), true, 0, QuicStringPiece("End"));
+ QuicStreamFrame frame2(stream_->id(), true, 0, "End");
stream_->OnStreamFrame(frame2);
EXPECT_TRUE(stream_->fin_received());
- EXPECT_TRUE(stream_->HasFinalReceivedByteOffset());
+ EXPECT_TRUE(stream_->HasReceivedFinalOffset());
}
TEST_P(QuicStreamTest, StreamWaitsForAcks) {
@@ -834,11 +806,7 @@ TEST_P(QuicStreamTest, StreamWaitsForAcks) {
// Send kData1.
stream_->WriteOrBufferData(kData1, false, nullptr);
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_TRUE(stream_->IsWaitingForAcks());
QuicByteCount newly_acked_length = 0;
@@ -853,11 +821,7 @@ TEST_P(QuicStreamTest, StreamWaitsForAcks) {
// Send kData2.
stream_->WriteOrBufferData(kData2, false, nullptr);
EXPECT_TRUE(stream_->IsWaitingForAcks());
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
// Send FIN.
stream_->WriteOrBufferData("", true, nullptr);
@@ -873,11 +837,7 @@ TEST_P(QuicStreamTest, StreamWaitsForAcks) {
EXPECT_EQ(9u, newly_acked_length);
// Stream is waiting for acks as FIN is not acked.
EXPECT_TRUE(stream_->IsWaitingForAcks());
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
// FIN is acked.
@@ -900,46 +860,26 @@ TEST_P(QuicStreamTest, StreamDataGetAckedOutOfOrder) {
stream_->WriteOrBufferData("", true, nullptr);
EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_TRUE(stream_->IsWaitingForAcks());
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
QuicByteCount newly_acked_length = 0;
EXPECT_TRUE(stream_->OnStreamFrameAcked(9, 9, false, QuicTime::Delta::Zero(),
&newly_acked_length));
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_EQ(9u, newly_acked_length);
EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_TRUE(stream_->OnStreamFrameAcked(18, 9, false, QuicTime::Delta::Zero(),
&newly_acked_length));
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_EQ(9u, newly_acked_length);
EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_TRUE(stream_->OnStreamFrameAcked(0, 9, false, QuicTime::Delta::Zero(),
&newly_acked_length));
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_EQ(9u, newly_acked_length);
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
// FIN is not acked yet.
EXPECT_TRUE(stream_->IsWaitingForAcks());
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_TRUE(stream_->OnStreamFrameAcked(27, 0, true, QuicTime::Delta::Zero(),
&newly_acked_length));
EXPECT_EQ(0u, newly_acked_length);
@@ -957,31 +897,23 @@ TEST_P(QuicStreamTest, CancelStream) {
stream_->WriteOrBufferData(kData1, false, nullptr);
EXPECT_TRUE(stream_->IsWaitingForAcks());
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
// Cancel stream.
stream_->Reset(QUIC_STREAM_NO_ERROR);
// stream still waits for acks as the error code is QUIC_STREAM_NO_ERROR, and
// data is going to be retransmitted.
EXPECT_TRUE(stream_->IsWaitingForAcks());
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_CALL(*connection_,
OnStreamReset(stream_->id(), QUIC_STREAM_CANCELLED));
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(AtLeast(1))
+ .WillRepeatedly(Invoke(&ClearControlFrame));
EXPECT_CALL(*session_, SendRstStream(stream_->id(), QUIC_STREAM_CANCELLED, 9))
.WillOnce(InvokeWithoutArgs([this]() {
- return QuicSessionPeer::SendRstStreamInner(
- session_.get(), stream_->id(), QUIC_STREAM_CANCELLED,
- stream_->stream_bytes_written(),
- /*close_write_side_only=*/false);
+ session_->ReallySendRstStream(stream_->id(), QUIC_STREAM_CANCELLED,
+ stream_->stream_bytes_written());
}));
stream_->Reset(QUIC_STREAM_CANCELLED);
@@ -1007,11 +939,7 @@ TEST_P(QuicStreamTest, RstFrameReceivedStreamNotFinishSending) {
stream_->WriteOrBufferData(kData1, false, nullptr);
EXPECT_TRUE(stream_->IsWaitingForAcks());
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
// RST_STREAM received.
@@ -1037,11 +965,7 @@ TEST_P(QuicStreamTest, RstFrameReceivedStreamFinishSending) {
stream_->WriteOrBufferData(kData1, true, nullptr);
EXPECT_TRUE(stream_->IsWaitingForAcks());
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
// RST_STREAM received.
EXPECT_CALL(*session_, SendRstStream(_, _, _)).Times(0);
@@ -1050,11 +974,7 @@ TEST_P(QuicStreamTest, RstFrameReceivedStreamFinishSending) {
stream_->OnStreamReset(rst_frame);
// Stream still waits for acks as it finishes sending and has unacked data.
EXPECT_TRUE(stream_->IsWaitingForAcks());
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
}
@@ -1068,11 +988,7 @@ TEST_P(QuicStreamTest, ConnectionClosed) {
stream_->WriteOrBufferData(kData1, false, nullptr);
EXPECT_TRUE(stream_->IsWaitingForAcks());
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
EXPECT_CALL(*session_,
SendRstStream(stream_->id(), QUIC_RST_ACKNOWLEDGEMENT, 9));
stream_->OnConnectionClosed(QUIC_INTERNAL_ERROR,
@@ -1328,11 +1244,7 @@ TEST_P(QuicStreamTest, StreamDataGetAckedMultipleTimes) {
stream_->WriteOrBufferData(kData1, true, nullptr);
EXPECT_EQ(3u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_TRUE(stream_->IsWaitingForAcks());
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
// Ack [0, 9), [5, 22) and [18, 26)
// Verify [0, 9) 9 bytes are acked.
QuicByteCount newly_acked_length = 0;
@@ -1351,11 +1263,7 @@ TEST_P(QuicStreamTest, StreamDataGetAckedMultipleTimes) {
EXPECT_EQ(4u, newly_acked_length);
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_TRUE(stream_->IsWaitingForAcks());
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
// Ack [0, 27). Verify [26, 27) 1 byte is acked.
EXPECT_TRUE(stream_->OnStreamFrameAcked(26, 1, false, QuicTime::Delta::Zero(),
@@ -1363,11 +1271,7 @@ TEST_P(QuicStreamTest, StreamDataGetAckedMultipleTimes) {
EXPECT_EQ(1u, newly_acked_length);
EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
EXPECT_TRUE(stream_->IsWaitingForAcks());
- // Session decides what to write and puts stream into set of unacked streams
- // only after v39.
- if (GetParam().transport_version > QUIC_VERSION_39) {
- EXPECT_TRUE(session_->HasUnackedStreamData());
- }
+ EXPECT_TRUE(session_->HasUnackedStreamData());
// Ack Fin.
EXPECT_TRUE(stream_->OnStreamFrameAcked(27, 0, true, QuicTime::Delta::Zero(),
@@ -1410,6 +1314,7 @@ TEST_P(QuicStreamTest, OnStreamFrameLost) {
EXPECT_TRUE(stream_->HasPendingRetransmission());
EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillOnce(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
stream_->OnCanWrite();
EXPECT_FALSE(stream_->HasPendingRetransmission());
EXPECT_TRUE(stream_->HasBufferedData());
@@ -1581,10 +1486,6 @@ TEST_P(QuicStreamTest, RetransmitStreamData) {
}
TEST_P(QuicStreamTest, ResetStreamOnTtlExpiresRetransmitLostData) {
- // Version 39 and below doesn't support stream ttl.
- if (GetParam().transport_version <= QUIC_VERSION_39) {
- return;
- }
Initialize();
EXPECT_CALL(*session_, WritevData(_, stream_->id(), 200, 0, FIN))
@@ -1609,10 +1510,6 @@ TEST_P(QuicStreamTest, ResetStreamOnTtlExpiresRetransmitLostData) {
}
TEST_P(QuicStreamTest, ResetStreamOnTtlExpiresEarlyRetransmitData) {
- // Version 39 and below doesn't support stream ttl.
- if (GetParam().transport_version <= QUIC_VERSION_39) {
- return;
- }
Initialize();
EXPECT_CALL(*session_, WritevData(_, stream_->id(), 200, 0, FIN))
@@ -1675,50 +1572,6 @@ TEST_P(QuicStreamTest, OnStreamResetReadOrReadWrite) {
}
}
-// Test that receiving a STOP_SENDING just closes the write side of the stream.
-// If not V99, the test is a noop (no STOP_SENDING in Google QUIC).
-TEST_P(QuicStreamTest, OnStopSendingReadOrReadWrite) {
- Initialize();
- if (!VersionHasIetfQuicFrames(connection_->transport_version())) {
- return;
- }
-
- EXPECT_FALSE(stream_->write_side_closed());
- EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
-
- // Simulate receipt of a STOP_SENDING.
- stream_->OnStopSending(123);
-
- // Should close just the read side.
- EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
- // TODO(b/142425843): Currently no action is taken upon receiving stop
- // sending. Need to figure out what to do and turn on this expectation.
- // EXPECT_TRUE(stream_->write_side_closed());
-}
-
-// SendOnlyRstStream must only send a RESET_STREAM (no bundled STOP_SENDING).
-TEST_P(QuicStreamTest, SendOnlyRstStream) {
- Initialize();
- if (!VersionHasIetfQuicFrames(connection_->transport_version())) {
- return;
- }
-
- EXPECT_CALL(*connection_,
- OnStreamReset(stream_->id(), QUIC_BAD_APPLICATION_PAYLOAD));
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(1)
- .WillOnce(Invoke(this, &QuicStreamTest::ClearResetStreamFrame));
-
- QuicSessionPeer::SendRstStreamInner(session_.get(), stream_->id(),
- QUIC_BAD_APPLICATION_PAYLOAD,
- stream_->stream_bytes_written(),
- /*close_write_side_only=*/true);
-
- // ResetStreamOnly should just close the write side.
- EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
- EXPECT_TRUE(stream_->write_side_closed());
-}
-
TEST_P(QuicStreamTest, WindowUpdateForReadOnlyStream) {
Initialize();
@@ -1735,6 +1588,20 @@ TEST_P(QuicStreamTest, WindowUpdateForReadOnlyStream) {
stream.OnWindowUpdateFrame(window_update_frame);
}
+TEST_P(QuicStreamTest, RstStreamFrameChangesCloseOffset) {
+ SetQuicReloadableFlag(quic_close_connection_on_wrong_offset, true);
+ Initialize();
+
+ QuicStreamFrame stream_frame(stream_->id(), true, 0, "abc");
+ EXPECT_CALL(*stream_, OnDataAvailable());
+ stream_->OnStreamFrame(stream_frame);
+ QuicRstStreamFrame rst(kInvalidControlFrameId, stream_->id(),
+ QUIC_STREAM_CANCELLED, 0u);
+
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_STREAM_MULTIPLE_OFFSET, _, _));
+ stream_->OnStreamReset(rst);
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_time.h b/chromium/net/third_party/quiche/src/quic/core/quic_time.h
index 9a5ae7dd5b2..d4429e34ceb 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_time.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_time.h
@@ -210,6 +210,9 @@ inline bool operator<=(QuicTime::Delta lhs, QuicTime::Delta rhs) {
inline bool operator>=(QuicTime::Delta lhs, QuicTime::Delta rhs) {
return !(lhs < rhs);
}
+inline QuicTime::Delta operator<<(QuicTime::Delta lhs, size_t rhs) {
+ return QuicTime::Delta(lhs.time_offset_ << rhs);
+}
inline QuicTime::Delta operator>>(QuicTime::Delta lhs, size_t rhs) {
return QuicTime::Delta(lhs.time_offset_ >> rhs);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_time_accumulator.h b/chromium/net/third_party/quiche/src/quic/core/quic_time_accumulator.h
new file mode 100644
index 00000000000..6535d74c45b
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_time_accumulator.h
@@ -0,0 +1,69 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_QUIC_TIME_ACCUMULATOR_H_
+#define QUICHE_QUIC_CORE_QUIC_TIME_ACCUMULATOR_H_
+
+#include "net/third_party/quiche/src/quic/core/quic_time.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+
+namespace quic {
+
+// QuicTimeAccumulator accumulates elapsed times between Start(s) and Stop(s).
+class QUIC_EXPORT_PRIVATE QuicTimeAccumulator {
+ // TODO(wub): Switch to a data member called kNotRunningSentinel after c++17.
+ static constexpr QuicTime NotRunningSentinel() {
+ return QuicTime::Infinite();
+ }
+
+ public:
+ // True if Started and not Stopped.
+ bool IsRunning() const { return last_start_time_ != NotRunningSentinel(); }
+
+ void Start(QuicTime now) {
+ DCHECK(!IsRunning());
+ last_start_time_ = now;
+ DCHECK(IsRunning());
+ }
+
+ void Stop(QuicTime now) {
+ DCHECK(IsRunning());
+ if (now > last_start_time_) {
+ total_elapsed_ = total_elapsed_ + (now - last_start_time_);
+ }
+ last_start_time_ = NotRunningSentinel();
+ DCHECK(!IsRunning());
+ }
+
+ // Get total elapsed time between COMPLETED Start/Stop pairs.
+ QuicTime::Delta GetTotalElapsedTime() const { return total_elapsed_; }
+
+ // Get total elapsed time between COMPLETED Start/Stop pairs, plus, if it is
+ // running, the elapsed time between |last_start_time_| and |now|.
+ QuicTime::Delta GetTotalElapsedTime(QuicTime now) const {
+ if (!IsRunning()) {
+ return total_elapsed_;
+ }
+ if (now <= last_start_time_) {
+ return total_elapsed_;
+ }
+ return total_elapsed_ + (now - last_start_time_);
+ }
+
+ private:
+ //
+ // |last_start_time_|
+ // |
+ // V
+ // Start => Stop => Start => Stop => Start
+ // | | | |
+ // |___________| + |___________| = |total_elapsed_|
+ QuicTime::Delta total_elapsed_ = QuicTime::Delta::Zero();
+ QuicTime last_start_time_ = NotRunningSentinel();
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QUIC_TIME_ACCUMULATOR_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_time_accumulator_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_time_accumulator_test.cc
new file mode 100644
index 00000000000..e7bc43a0459
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_time_accumulator_test.cc
@@ -0,0 +1,82 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_time_accumulator.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
+
+namespace quic {
+namespace test {
+
+TEST(QuicTimeAccumulator, DefaultConstruct) {
+ MockClock clock;
+ clock.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
+
+ QuicTimeAccumulator acc;
+ EXPECT_FALSE(acc.IsRunning());
+
+ clock.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
+ EXPECT_EQ(QuicTime::Delta::Zero(), acc.GetTotalElapsedTime());
+ EXPECT_EQ(QuicTime::Delta::Zero(), acc.GetTotalElapsedTime(clock.Now()));
+}
+
+TEST(QuicTimeAccumulator, StartStop) {
+ MockClock clock;
+ clock.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
+
+ QuicTimeAccumulator acc;
+ acc.Start(clock.Now());
+ EXPECT_TRUE(acc.IsRunning());
+
+ clock.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ acc.Stop(clock.Now());
+ EXPECT_FALSE(acc.IsRunning());
+
+ clock.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), acc.GetTotalElapsedTime());
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10),
+ acc.GetTotalElapsedTime(clock.Now()));
+
+ acc.Start(clock.Now());
+ clock.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), acc.GetTotalElapsedTime());
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(15),
+ acc.GetTotalElapsedTime(clock.Now()));
+
+ clock.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), acc.GetTotalElapsedTime());
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(20),
+ acc.GetTotalElapsedTime(clock.Now()));
+
+ acc.Stop(clock.Now());
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(20), acc.GetTotalElapsedTime());
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(20),
+ acc.GetTotalElapsedTime(clock.Now()));
+}
+
+TEST(QuicTimeAccumulator, ClockStepBackwards) {
+ MockClock clock;
+ clock.AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
+
+ QuicTimeAccumulator acc;
+ acc.Start(clock.Now());
+
+ clock.AdvanceTime(QuicTime::Delta::FromMilliseconds(-10));
+ acc.Stop(clock.Now());
+ EXPECT_EQ(QuicTime::Delta::Zero(), acc.GetTotalElapsedTime());
+ EXPECT_EQ(QuicTime::Delta::Zero(), acc.GetTotalElapsedTime(clock.Now()));
+
+ acc.Start(clock.Now());
+ clock.AdvanceTime(QuicTime::Delta::FromMilliseconds(50));
+ acc.Stop(clock.Now());
+
+ acc.Start(clock.Now());
+ clock.AdvanceTime(QuicTime::Delta::FromMilliseconds(-80));
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(50), acc.GetTotalElapsedTime());
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(50),
+ acc.GetTotalElapsedTime(clock.Now()));
+}
+
+} // namespace test
+} // namespace quic
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 e2a45946b97..5c7553565b4 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
@@ -35,7 +35,8 @@ class QuicTimeWaitListManagerPeer;
// wait state. After the connection_id expires its time wait period, a new
// connection/session will be created if a packet is received for this
// connection_id.
-class QuicTimeWaitListManager : public QuicBlockedWriterInterface {
+class QUIC_NO_EXPORT QuicTimeWaitListManager
+ : public QuicBlockedWriterInterface {
public:
// Specifies what the time wait list manager should do when processing packets
// of a time wait connection.
@@ -49,7 +50,7 @@ class QuicTimeWaitListManager : public QuicBlockedWriterInterface {
DO_NOTHING,
};
- class Visitor : public QuicSession::Visitor {
+ class QUIC_NO_EXPORT Visitor : public QuicSession::Visitor {
public:
// Called after the given connection is added to the time-wait list.
virtual void OnConnectionAddedToTimeWaitList(
@@ -159,7 +160,7 @@ class QuicTimeWaitListManager : public QuicBlockedWriterInterface {
QuicConnectionId connection_id) const;
// Internal structure to store pending termination packets.
- class QueuedPacket {
+ class QUIC_NO_EXPORT QueuedPacket {
public:
QueuedPacket(const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
@@ -229,7 +230,7 @@ class QuicTimeWaitListManager : public QuicBlockedWriterInterface {
// A map from a recently closed connection_id to the number of packets
// received after the termination of the connection bound to the
// connection_id.
- struct ConnectionIdData {
+ struct QUIC_NO_EXPORT ConnectionIdData {
ConnectionIdData(int num_packets,
bool ietf_quic,
QuicTime time_added,
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 42ee003966d..50974853345 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.cc
@@ -6,7 +6,7 @@
#include <string>
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
@@ -44,7 +44,6 @@ QuicTraceVisitor::QuicTraceVisitor(const QuicConnection* connection)
}
void QuicTraceVisitor::OnPacketSent(const SerializedPacket& serialized_packet,
- QuicPacketNumber /*original_packet_number*/,
TransmissionType /*transmission_type*/,
QuicTime sent_time) {
quic_trace::Event* event = trace_.add_events();
@@ -172,7 +171,7 @@ void QuicTraceVisitor::PopulateFrameInfo(const QuicFrame& frame,
quic_trace::FlowControlInfo* info =
frame_record->mutable_flow_control_info();
- info->set_max_data(frame.window_update_frame->byte_offset);
+ info->set_max_data(frame.window_update_frame->max_data);
if (!is_connection) {
info->set_stream_id(frame.window_update_frame->stream_id);
}
@@ -266,7 +265,8 @@ void QuicTraceVisitor::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame,
void QuicTraceVisitor::OnSuccessfulVersionNegotiation(
const ParsedQuicVersion& version) {
- uint32_t tag = QuicEndian::HostToNet32(CreateQuicVersionLabel(version));
+ uint32_t tag =
+ quiche::QuicheEndian::HostToNet32(CreateQuicVersionLabel(version));
std::string binary_tag(reinterpret_cast<const char*>(&tag), sizeof(tag));
trace_.set_protocol_version(binary_tag);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.h b/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.h
index 0494d874331..86d7198ebe7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.h
@@ -14,12 +14,11 @@ namespace quic {
// Records a QUIC trace protocol buffer for a QuicConnection. It's the
// responsibility of the user of this visitor to process or store the resulting
// trace, which can be accessed via trace().
-class QuicTraceVisitor : public QuicConnectionDebugVisitor {
+class QUIC_NO_EXPORT QuicTraceVisitor : public QuicConnectionDebugVisitor {
public:
explicit QuicTraceVisitor(const QuicConnection* connection);
void OnPacketSent(const SerializedPacket& serialized_packet,
- QuicPacketNumber original_packet_number,
TransmissionType transmission_type,
QuicTime sent_time) override;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_transmission_info.cc b/chromium/net/third_party/quiche/src/quic/core/quic_transmission_info.cc
index fb5cf670063..163ba384f32 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_transmission_info.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_transmission_info.cc
@@ -8,7 +8,6 @@ namespace quic {
QuicTransmissionInfo::QuicTransmissionInfo()
: encryption_level(ENCRYPTION_INITIAL),
- packet_number_length(PACKET_1BYTE_PACKET_NUMBER),
bytes_sent(0),
sent_time(QuicTime::Zero()),
transmission_type(NOT_RETRANSMISSION),
@@ -19,14 +18,12 @@ QuicTransmissionInfo::QuicTransmissionInfo()
QuicTransmissionInfo::QuicTransmissionInfo(
EncryptionLevel level,
- QuicPacketNumberLength packet_number_length,
TransmissionType transmission_type,
QuicTime sent_time,
QuicPacketLength bytes_sent,
bool has_crypto_handshake,
int num_padding_bytes)
: encryption_level(level),
- packet_number_length(packet_number_length),
bytes_sent(bytes_sent),
sent_time(sent_time),
transmission_type(transmission_type),
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_transmission_info.h b/chromium/net/third_party/quiche/src/quic/core/quic_transmission_info.h
index 7c4881a290a..a4fa762d359 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_transmission_info.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_transmission_info.h
@@ -22,7 +22,6 @@ struct QUIC_EXPORT_PRIVATE QuicTransmissionInfo {
// Constructs a Transmission with a new all_transmissions set
// containing |packet_number|.
QuicTransmissionInfo(EncryptionLevel level,
- QuicPacketNumberLength packet_number_length,
TransmissionType transmission_type,
QuicTime sent_time,
QuicPacketLength bytes_sent,
@@ -35,8 +34,6 @@ struct QUIC_EXPORT_PRIVATE QuicTransmissionInfo {
QuicFrames retransmittable_frames;
EncryptionLevel encryption_level;
- // TODO(fayang): remove this when deprecating QUIC_VERSION_39.
- QuicPacketNumberLength packet_number_length;
QuicPacketLength bytes_sent;
QuicTime sent_time;
// Reason why this packet was transmitted.
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 db48c5c2391..ca12e76725b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_types.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_types.cc
@@ -6,13 +6,11 @@
#include <cstdint>
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
namespace quic {
-QuicConsumedData::QuicConsumedData(size_t bytes_consumed, bool fin_consumed)
- : bytes_consumed(bytes_consumed), fin_consumed(fin_consumed) {}
-
std::ostream& operator<<(std::ostream& os, const QuicConsumedData& s) {
os << "bytes_consumed: " << s.bytes_consumed
<< " fin_consumed: " << s.fin_consumed;
@@ -53,6 +51,8 @@ std::string HistogramEnumString(WriteStatus enum_value) {
return "ERROR";
case WRITE_STATUS_MSG_TOO_BIG:
return "MSG_TOO_BIG";
+ case WRITE_STATUS_FAILED_TO_COALESCE_PACKET:
+ return "WRITE_STATUS_FAILED_TO_COALESCE_PACKET";
case WRITE_STATUS_NUM_VALUES:
return "NUM_VALUES";
}
@@ -60,11 +60,6 @@ std::string HistogramEnumString(WriteStatus enum_value) {
return "<invalid>";
}
-WriteResult::WriteResult() : status(WRITE_STATUS_ERROR), bytes_written(0) {}
-
-WriteResult::WriteResult(WriteStatus status, int bytes_written_or_error_code)
- : status(status), bytes_written(bytes_written_or_error_code) {}
-
std::ostream& operator<<(std::ostream& os, const WriteResult& s) {
os << "{ status: " << s.status;
if (s.status == WRITE_STATUS_OK) {
@@ -413,6 +408,23 @@ QuicErrorCodeToIetfMapping QuicErrorCodeToTransportErrorCode(
{static_cast<uint64_t>(QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES)}};
case QUIC_TRANSPORT_INVALID_CLIENT_INDICATION:
return {false, {0u}};
+ case QUIC_QPACK_DECOMPRESSION_FAILED:
+ return {
+ false,
+ {static_cast<uint64_t>(IETF_QUIC_HTTP_QPACK_DECOMPRESSION_FAILED)}};
+ case QUIC_QPACK_ENCODER_STREAM_ERROR:
+ return {
+ false,
+ {static_cast<uint64_t>(IETF_QUIC_HTTP_QPACK_ENCODER_STREAM_ERROR)}};
+ case QUIC_QPACK_DECODER_STREAM_ERROR:
+ return {
+ false,
+ {static_cast<uint64_t>(IETF_QUIC_HTTP_QPACK_DECODER_STREAM_ERROR)}};
+ case QUIC_STREAM_DATA_BEYOND_CLOSE_OFFSET:
+ return {true,
+ {static_cast<uint64_t>(QUIC_STREAM_DATA_BEYOND_CLOSE_OFFSET)}};
+ case QUIC_STREAM_MULTIPLE_OFFSET:
+ return {true, {static_cast<uint64_t>(QUIC_STREAM_MULTIPLE_OFFSET)}};
case QUIC_LAST_ERROR:
return {false, {static_cast<uint64_t>(QUIC_LAST_ERROR)}};
}
@@ -450,6 +462,8 @@ std::string QuicIetfFrameTypeString(QuicIetfFrameType t) {
RETURN_STRING_LITERAL(IETF_APPLICATION_CLOSE);
RETURN_STRING_LITERAL(IETF_EXTENSION_MESSAGE_NO_LENGTH);
RETURN_STRING_LITERAL(IETF_EXTENSION_MESSAGE);
+ RETURN_STRING_LITERAL(IETF_EXTENSION_MESSAGE_NO_LENGTH_V99);
+ RETURN_STRING_LITERAL(IETF_EXTENSION_MESSAGE_V99);
default:
return QuicStrCat("Private value (", t, ")");
}
@@ -468,6 +482,7 @@ std::string TransmissionTypeToString(TransmissionType transmission_type) {
RETURN_STRING_LITERAL(LOSS_RETRANSMISSION);
RETURN_STRING_LITERAL(RTO_RETRANSMISSION);
RETURN_STRING_LITERAL(TLP_RETRANSMISSION);
+ RETURN_STRING_LITERAL(PTO_RETRANSMISSION);
RETURN_STRING_LITERAL(PROBING_RETRANSMISSION);
default:
// Some varz rely on this behavior for statistic collection.
@@ -502,6 +517,33 @@ std::string QuicLongHeaderTypeToString(QuicLongHeaderType type) {
}
}
+std::string MessageStatusToString(MessageStatus message_status) {
+ switch (message_status) {
+ RETURN_STRING_LITERAL(MESSAGE_STATUS_SUCCESS);
+ RETURN_STRING_LITERAL(MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED);
+ RETURN_STRING_LITERAL(MESSAGE_STATUS_UNSUPPORTED);
+ RETURN_STRING_LITERAL(MESSAGE_STATUS_BLOCKED);
+ RETURN_STRING_LITERAL(MESSAGE_STATUS_TOO_LARGE);
+ RETURN_STRING_LITERAL(MESSAGE_STATUS_INTERNAL_ERROR);
+ default:
+ return QuicStrCat("Unknown(", static_cast<int>(message_status), ")");
+ break;
+ }
+}
+
+std::string MessageResultToString(MessageResult message_result) {
+ if (message_result.status != MESSAGE_STATUS_SUCCESS) {
+ return QuicStrCat("{", MessageStatusToString(message_result.status), "}");
+ }
+ return QuicStrCat("{MESSAGE_STATUS_SUCCESS,id=", message_result.message_id,
+ "}");
+}
+
+std::ostream& operator<<(std::ostream& os, const MessageResult& mr) {
+ os << MessageResultToString(mr);
+ return os;
+}
+
std::string PacketNumberSpaceToString(PacketNumberSpace packet_number_space) {
switch (packet_number_space) {
RETURN_STRING_LITERAL(INITIAL_DATA);
@@ -513,6 +555,17 @@ std::string PacketNumberSpaceToString(PacketNumberSpace packet_number_space) {
}
}
+std::string SerializedPacketFateToString(SerializedPacketFate fate) {
+ switch (fate) {
+ RETURN_STRING_LITERAL(COALESCE);
+ RETURN_STRING_LITERAL(BUFFER);
+ RETURN_STRING_LITERAL(SEND_TO_WRITER);
+ RETURN_STRING_LITERAL(FAILED_TO_WRITE_COALESCED_PACKET);
+ default:
+ return QuicStrCat("Unknown(", static_cast<int>(fate), ")");
+ }
+}
+
std::string EncryptionLevelToString(EncryptionLevel level) {
switch (level) {
RETURN_STRING_LITERAL(ENCRYPTION_INITIAL);
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 afd42be3f46..23cbe7a4eb4 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
@@ -15,6 +15,7 @@
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_number.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
namespace quic {
@@ -23,6 +24,7 @@ typedef uint16_t QuicPacketLength;
typedef uint32_t QuicControlFrameId;
typedef uint32_t QuicHeaderId;
typedef uint32_t QuicMessageId;
+typedef uint64_t QuicDatagramFlowId;
// TODO(fkastenholz): Should update this to 64 bits for V99.
typedef uint32_t QuicStreamId;
@@ -55,7 +57,8 @@ typedef uint64_t QuicConnectionIdSequenceNumber;
// A struct for functions which consume data payloads and fins.
struct QUIC_EXPORT_PRIVATE QuicConsumedData {
- QuicConsumedData(size_t bytes_consumed, bool fin_consumed);
+ constexpr QuicConsumedData(size_t bytes_consumed, bool fin_consumed)
+ : bytes_consumed(bytes_consumed), fin_consumed(fin_consumed) {}
// By default, gtest prints the raw bytes of an object. The bool data
// member causes this object to have padding bytes, which causes the
@@ -94,6 +97,7 @@ enum WriteStatus {
// - Errors MUST be added after WRITE_STATUS_ERROR.
WRITE_STATUS_ERROR,
WRITE_STATUS_MSG_TOO_BIG,
+ WRITE_STATUS_FAILED_TO_COALESCE_PACKET,
WRITE_STATUS_NUM_VALUES,
};
@@ -115,8 +119,10 @@ inline bool IsWriteError(WriteStatus status) {
// A struct used to return the result of write calls including either the number
// of bytes written or the error code, depending upon the status.
struct QUIC_EXPORT_PRIVATE WriteResult {
- WriteResult(WriteStatus status, int bytes_written_or_error_code);
- WriteResult();
+ constexpr WriteResult(WriteStatus status, int bytes_written_or_error_code)
+ : status(status), bytes_written(bytes_written_or_error_code) {}
+
+ constexpr WriteResult() : WriteResult(WRITE_STATUS_ERROR, 0) {}
bool operator==(const WriteResult& other) const {
if (status != other.status) {
@@ -153,6 +159,7 @@ enum TransmissionType : int8_t {
LOSS_RETRANSMISSION, // Retransmits due to loss detection.
RTO_RETRANSMISSION, // Retransmits due to retransmit time out.
TLP_RETRANSMISSION, // Tail loss probes.
+ PTO_RETRANSMISSION, // Retransmission due to probe timeout.
PROBING_RETRANSMISSION, // Retransmission in order to probe bandwidth.
LAST_TRANSMISSION_TYPE = PROBING_RETRANSMISSION,
};
@@ -265,10 +272,13 @@ enum QuicIetfFrameType : uint8_t {
IETF_CONNECTION_CLOSE = 0x1c,
IETF_APPLICATION_CLOSE = 0x1d,
- // MESSAGE frame type is not yet determined, use 0x2x temporarily to give
- // stream frame some wiggle room.
+ // The MESSAGE frame type has not yet been fully standardized.
+ // QUIC versions starting with 46 and before 99 use 0x20-0x21.
+ // IETF QUIC (v99) uses 0x30-0x31, see draft-pauly-quic-datagram.
IETF_EXTENSION_MESSAGE_NO_LENGTH = 0x20,
IETF_EXTENSION_MESSAGE = 0x21,
+ IETF_EXTENSION_MESSAGE_NO_LENGTH_V99 = 0x30,
+ IETF_EXTENSION_MESSAGE_V99 = 0x31,
};
QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
const QuicIetfFrameType& c);
@@ -308,7 +318,8 @@ enum QuicPacketNumberLength : uint8_t {
PACKET_3BYTE_PACKET_NUMBER = 3, // Used in versions 45+.
PACKET_4BYTE_PACKET_NUMBER = 4,
IETF_MAX_PACKET_NUMBER_LENGTH = 4,
- // TODO(rch): Remove this when we remove QUIC_VERSION_39.
+ // TODO(rch): Remove these when we remove QUIC_VERSION_43 since these values
+ // are not representable with v46 and above.
PACKET_6BYTE_PACKET_NUMBER = 6,
PACKET_8BYTE_PACKET_NUMBER = 8
};
@@ -440,7 +451,7 @@ enum StreamSendingState {
};
enum SentPacketState : uint8_t {
- // The packet has been sent and waiting to be acked.
+ // The packet is in flight and waiting to be acked.
OUTSTANDING,
FIRST_PACKET_STATE = OUTSTANDING,
// The packet was never sent.
@@ -449,6 +460,8 @@ enum SentPacketState : uint8_t {
ACKED,
// This packet is not expected to be acked.
UNACKABLE,
+ // This packet has been delivered or unneeded.
+ NEUTERED,
// States below are corresponding to retransmission types in TransmissionType.
@@ -461,6 +474,8 @@ enum SentPacketState : uint8_t {
TLP_RETRANSMITTED,
// This packet has been retransmitted when RTO fires.
RTO_RETRANSMITTED,
+ // This packet has been retransmitted when PTO fires.
+ PTO_RETRANSMITTED,
// This packet has been retransmitted for probing purpose.
PROBE_RETRANSMITTED,
LAST_PACKET_STATE = PROBE_RETRANSMITTED,
@@ -476,10 +491,10 @@ QUIC_EXPORT_PRIVATE std::string PacketHeaderFormatToString(
PacketHeaderFormat format);
// Information about a newly acknowledged packet.
-struct AckedPacket {
- AckedPacket(QuicPacketNumber packet_number,
- QuicPacketLength bytes_acked,
- QuicTime receive_timestamp)
+struct QUIC_EXPORT_PRIVATE AckedPacket {
+ constexpr AckedPacket(QuicPacketNumber packet_number,
+ QuicPacketLength bytes_acked,
+ QuicTime receive_timestamp)
: packet_number(packet_number),
bytes_acked(bytes_acked),
receive_timestamp(receive_timestamp) {}
@@ -498,10 +513,10 @@ struct AckedPacket {
};
// A vector of acked packets.
-typedef std::vector<AckedPacket> AckedPacketVector;
+typedef QuicInlinedVector<AckedPacket, 2> AckedPacketVector;
// Information about a newly lost packet.
-struct LostPacket {
+struct QUIC_EXPORT_PRIVATE LostPacket {
LostPacket(QuicPacketNumber packet_number, QuicPacketLength bytes_lost)
: packet_number(packet_number), bytes_lost(bytes_lost) {}
@@ -515,7 +530,7 @@ struct LostPacket {
};
// A vector of lost packets.
-typedef std::vector<LostPacket> LostPacketVector;
+typedef QuicInlinedVector<LostPacket, 2> LostPacketVector;
enum QuicIetfTransportErrorCodes : uint64_t {
NO_IETF_QUIC_ERROR = 0x0,
@@ -542,7 +557,7 @@ QUIC_EXPORT_PRIVATE std::ostream& operator<<(
// first element of the pair is false, it means that an IETF Application Close
// should be done instead.
-struct QuicErrorCodeToIetfMapping {
+struct QUIC_EXPORT_PRIVATE QuicErrorCodeToIetfMapping {
bool is_transport_close_;
union {
uint64_t application_error_code_;
@@ -599,6 +614,9 @@ enum MessageStatus {
// reaches an invalid state.
};
+QUIC_EXPORT_PRIVATE std::string MessageStatusToString(
+ MessageStatus message_status);
+
// Used to return the result of SendMessage calls
struct QUIC_EXPORT_PRIVATE MessageResult {
MessageResult(MessageStatus status, QuicMessageId message_id);
@@ -607,11 +625,17 @@ struct QUIC_EXPORT_PRIVATE MessageResult {
return status == other.status && message_id == other.message_id;
}
+ QUIC_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
+ const MessageResult& mr);
+
MessageStatus status;
// Only valid when status is MESSAGE_STATUS_SUCCESS.
QuicMessageId message_id;
};
+QUIC_EXPORT_PRIVATE std::string MessageResultToString(
+ MessageResult message_result);
+
enum WriteStreamDataResult {
WRITE_SUCCESS,
STREAM_MISSING, // Trying to write data of a nonexistent stream (e.g.
@@ -660,6 +684,18 @@ enum AckResult {
PACKETS_ACKED_IN_WRONG_PACKET_NUMBER_SPACE,
};
+// Indicates the fate of a serialized packet in WritePacket().
+enum SerializedPacketFate : uint8_t {
+ COALESCE, // Try to coalesce packet.
+ BUFFER, // Buffer packet in buffered_packets_.
+ SEND_TO_WRITER, // Send packet to writer.
+ FAILED_TO_WRITE_COALESCED_PACKET, // Packet cannot be coalesced, error occurs
+ // when sending existing coalesced packet.
+};
+
+QUIC_EXPORT_PRIVATE std::string SerializedPacketFateToString(
+ SerializedPacketFate fate);
+
// There are three different forms of CONNECTION_CLOSE.
typedef enum QuicConnectionCloseType {
GOOGLE_QUIC_CONNECTION_CLOSE = 0,
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_types_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_types_test.cc
index 8b4df895224..c7e4316a218 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_types_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_types_test.cc
@@ -13,9 +13,9 @@ namespace quic {
namespace test {
namespace {
-class QuicUtilsTest : public QuicTest {};
+class QuicTypesTest : public QuicTest {};
-TEST_F(QuicUtilsTest, QuicIetfTransportErrorCodeString) {
+TEST_F(QuicTypesTest, QuicIetfTransportErrorCodeString) {
// QuicIetfTransportErrorCode out of bound.
for (quic::QuicErrorCode error = quic::QUIC_ENCRYPTION_FAILURE;
error < quic::QUIC_LAST_ERROR;
@@ -27,10 +27,6 @@ TEST_F(QuicUtilsTest, QuicIetfTransportErrorCodeString) {
QuicIetfTransportErrorCodeString(mapping.transport_error_code_),
QuicStrCat("Unknown Transport Error Code Value: ",
static_cast<uint16_t>(mapping.transport_error_code_)));
- } else {
- // Some QuicErrorCodes are no longer valid.
- EXPECT_EQ(QuicIetfTransportErrorCodeString(mapping.transport_error_code_),
- "NO_IETF_QUIC_ERROR");
}
}
}
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 cc9c13f7a4c..d8beb435967 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
@@ -28,17 +28,11 @@ QuicUnackedPacketMap::QuicUnackedPacketMap(Perspective perspective)
: perspective_(perspective),
least_unacked_(FirstSendingPacketNumber()),
bytes_in_flight_(0),
- pending_crypto_packet_count_(0),
+ packets_in_flight_(0),
last_inflight_packet_sent_time_(QuicTime::Zero()),
last_crypto_packet_sent_time_(QuicTime::Zero()),
session_notifier_(nullptr),
- session_decides_what_to_write_(false),
- supports_multiple_packet_number_spaces_(false),
- simple_inflight_time_(GetQuicReloadableFlag(quic_simple_inflight_time)) {
- if (simple_inflight_time_) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_simple_inflight_time);
- }
-}
+ supports_multiple_packet_number_spaces_(false) {}
QuicUnackedPacketMap::~QuicUnackedPacketMap() {
for (QuicTransmissionInfo& transmission_info : unacked_packets_) {
@@ -47,7 +41,6 @@ QuicUnackedPacketMap::~QuicUnackedPacketMap() {
}
void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* packet,
- QuicPacketNumber old_packet_number,
TransmissionType transmission_type,
QuicTime sent_time,
bool set_in_flight) {
@@ -65,15 +58,11 @@ void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* packet,
const bool has_crypto_handshake =
packet->has_crypto_handshake == IS_HANDSHAKE;
- QuicTransmissionInfo info(
- packet->encryption_level, packet->packet_number_length, transmission_type,
- sent_time, bytes_sent, has_crypto_handshake, packet->num_padding_bytes);
+ QuicTransmissionInfo info(packet->encryption_level, transmission_type,
+ sent_time, bytes_sent, has_crypto_handshake,
+ packet->num_padding_bytes);
info.largest_acked = packet->largest_acked;
largest_sent_largest_acked_.UpdateMax(packet->largest_acked);
- if (old_packet_number.IsInitialized()) {
- TransferRetransmissionInfo(old_packet_number, packet_number,
- transmission_type, &info);
- }
largest_sent_packet_ = packet_number;
if (supports_multiple_packet_number_spaces_) {
@@ -82,6 +71,7 @@ void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* packet,
}
if (set_in_flight) {
bytes_in_flight_ += bytes_sent;
+ ++packets_in_flight_;
info.in_flight = true;
largest_sent_retransmittable_packets_[GetPacketNumberSpace(
info.encryption_level)] = packet_number;
@@ -92,15 +82,12 @@ void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* packet,
unacked_packets_.push_back(info);
// Swap the retransmittable frames to avoid allocations.
// TODO(ianswett): Could use emplace_back when Chromium can.
- if (!old_packet_number.IsInitialized()) {
- if (has_crypto_handshake) {
- ++pending_crypto_packet_count_;
- last_crypto_packet_sent_time_ = sent_time;
- }
-
- packet->retransmittable_frames.swap(
- unacked_packets_.back().retransmittable_frames);
+ if (has_crypto_handshake) {
+ last_crypto_packet_sent_time_ = sent_time;
}
+
+ packet->retransmittable_frames.swap(
+ unacked_packets_.back().retransmittable_frames);
}
void QuicUnackedPacketMap::RemoveObsoletePackets() {
@@ -108,62 +95,12 @@ void QuicUnackedPacketMap::RemoveObsoletePackets() {
if (!IsPacketUseless(least_unacked_, unacked_packets_.front())) {
break;
}
- if (session_decides_what_to_write_) {
- DeleteFrames(&unacked_packets_.front().retransmittable_frames);
- }
+ DeleteFrames(&unacked_packets_.front().retransmittable_frames);
unacked_packets_.pop_front();
++least_unacked_;
}
}
-void QuicUnackedPacketMap::TransferRetransmissionInfo(
- QuicPacketNumber old_packet_number,
- QuicPacketNumber new_packet_number,
- TransmissionType transmission_type,
- QuicTransmissionInfo* info) {
- if (old_packet_number < least_unacked_) {
- // This can happen when a retransmission packet is queued because of write
- // blocked socket, and the original packet gets acked before the
- // retransmission gets sent.
- return;
- }
- if (old_packet_number > largest_sent_packet_) {
- QUIC_BUG << "Old QuicTransmissionInfo never existed for :"
- << old_packet_number << " largest_sent:" << largest_sent_packet_;
- return;
- }
- DCHECK_GE(new_packet_number, least_unacked_ + unacked_packets_.size());
- DCHECK_NE(NOT_RETRANSMISSION, transmission_type);
-
- QuicTransmissionInfo* transmission_info =
- &unacked_packets_.at(old_packet_number - least_unacked_);
- QuicFrames* frames = &transmission_info->retransmittable_frames;
- if (session_notifier_ != nullptr) {
- for (const QuicFrame& frame : *frames) {
- if (frame.type == STREAM_FRAME) {
- session_notifier_->OnStreamFrameRetransmitted(frame.stream_frame);
- }
- }
- }
-
- // Swap the frames and preserve num_padding_bytes and has_crypto_handshake.
- frames->swap(info->retransmittable_frames);
- info->has_crypto_handshake = transmission_info->has_crypto_handshake;
- transmission_info->has_crypto_handshake = false;
- info->num_padding_bytes = transmission_info->num_padding_bytes;
-
- // Don't link old transmissions to new ones when version or
- // encryption changes.
- if (transmission_type == ALL_INITIAL_RETRANSMISSION ||
- transmission_type == ALL_UNACKED_RETRANSMISSION) {
- transmission_info->state = UNACKABLE;
- } else {
- transmission_info->retransmission = new_packet_number;
- }
- // Proactively remove obsolete packets so the least unacked can be raised.
- RemoveObsoletePackets();
-}
-
bool QuicUnackedPacketMap::HasRetransmittableFrames(
QuicPacketNumber packet_number) const {
DCHECK_GE(packet_number, least_unacked_);
@@ -174,10 +111,6 @@ bool QuicUnackedPacketMap::HasRetransmittableFrames(
bool QuicUnackedPacketMap::HasRetransmittableFrames(
const QuicTransmissionInfo& info) const {
- if (!session_decides_what_to_write_) {
- return !info.retransmittable_frames.empty();
- }
-
if (!QuicUtils::IsAckable(info.state)) {
return false;
}
@@ -192,24 +125,8 @@ bool QuicUnackedPacketMap::HasRetransmittableFrames(
void QuicUnackedPacketMap::RemoveRetransmittability(
QuicTransmissionInfo* info) {
- if (session_decides_what_to_write_) {
- DeleteFrames(&info->retransmittable_frames);
- info->retransmission.Clear();
- return;
- }
- while (info->retransmission.IsInitialized()) {
- const QuicPacketNumber retransmission = info->retransmission;
- info->retransmission.Clear();
- info = &unacked_packets_[retransmission - least_unacked_];
- }
-
- if (info->has_crypto_handshake) {
- DCHECK(HasRetransmittableFrames(*info));
- DCHECK_LT(0u, pending_crypto_packet_count_);
- --pending_crypto_packet_count_;
- info->has_crypto_handshake = false;
- }
DeleteFrames(&info->retransmittable_frames);
+ info->retransmission.Clear();
}
void QuicUnackedPacketMap::RemoveRetransmittability(
@@ -250,16 +167,6 @@ bool QuicUnackedPacketMap::IsPacketUsefulForCongestionControl(
bool QuicUnackedPacketMap::IsPacketUsefulForRetransmittableData(
const QuicTransmissionInfo& info) const {
- if (!session_decides_what_to_write_) {
- // Packet may have retransmittable frames, or the data may have been
- // retransmitted with a new packet number.
- // Allow for an extra 1 RTT before stopping to track old packets.
- return (info.retransmission.IsInitialized() &&
- (!largest_acked_.IsInitialized() ||
- info.retransmission > largest_acked_)) ||
- HasRetransmittableFrames(info);
- }
-
// Wait for 1 RTT before giving up on the lost packet.
return info.retransmission.IsInitialized() &&
(!largest_acked_.IsInitialized() ||
@@ -286,7 +193,9 @@ 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);
bytes_in_flight_ -= info->bytes_sent;
+ --packets_in_flight_;
info->in_flight = false;
}
}
@@ -299,23 +208,6 @@ void QuicUnackedPacketMap::RemoveFromInFlight(QuicPacketNumber packet_number) {
RemoveFromInFlight(info);
}
-void QuicUnackedPacketMap::CancelRetransmissionsForStream(
- QuicStreamId stream_id) {
- DCHECK(!session_decides_what_to_write_);
- QuicPacketNumber packet_number = least_unacked_;
- for (auto it = unacked_packets_.begin(); it != unacked_packets_.end();
- ++it, ++packet_number) {
- QuicFrames* frames = &it->retransmittable_frames;
- if (frames->empty()) {
- continue;
- }
- RemoveFramesForStream(frames, stream_id);
- if (frames->empty()) {
- RemoveRetransmittability(packet_number);
- }
- }
-}
-
bool QuicUnackedPacketMap::HasInFlightPackets() const {
return bytes_in_flight_ > 0;
}
@@ -331,20 +223,7 @@ QuicTransmissionInfo* QuicUnackedPacketMap::GetMutableTransmissionInfo(
}
QuicTime QuicUnackedPacketMap::GetLastInFlightPacketSentTime() const {
- if (simple_inflight_time_) {
- return last_inflight_packet_sent_time_;
- }
- auto it = unacked_packets_.rbegin();
- while (it != unacked_packets_.rend()) {
- if (it->in_flight) {
- QUIC_BUG_IF(it->sent_time == QuicTime::Zero())
- << "Sent time can never be zero for a packet in flight.";
- return it->sent_time;
- }
- ++it;
- }
- QUIC_BUG << "GetLastPacketSentTime requires in flight packets.";
- return QuicTime::Zero();
+ return last_inflight_packet_sent_time_;
}
QuicTime QuicUnackedPacketMap::GetLastCryptoPacketSentTime() const {
@@ -381,9 +260,6 @@ bool QuicUnackedPacketMap::HasMultipleInFlightPackets() const {
}
bool QuicUnackedPacketMap::HasPendingCryptoPackets() const {
- if (!session_decides_what_to_write_) {
- return pending_crypto_packet_count_ > 0;
- }
return session_notifier_->HasUnackedCryptoData();
}
@@ -423,7 +299,6 @@ bool QuicUnackedPacketMap::NotifyFramesAcked(const QuicTransmissionInfo& info,
void QuicUnackedPacketMap::NotifyFramesLost(const QuicTransmissionInfo& info,
TransmissionType /*type*/) {
- DCHECK(session_decides_what_to_write_);
for (const QuicFrame& frame : info.retransmittable_frames) {
session_notifier_->OnFrameLost(frame);
}
@@ -431,7 +306,6 @@ void QuicUnackedPacketMap::NotifyFramesLost(const QuicTransmissionInfo& info,
void QuicUnackedPacketMap::RetransmitFrames(const QuicTransmissionInfo& info,
TransmissionType type) {
- DCHECK(session_decides_what_to_write_);
session_notifier_->RetransmitFrames(info.retransmittable_frames, type);
}
@@ -537,15 +411,6 @@ QuicUnackedPacketMap::GetLargestSentRetransmittableOfPacketNumberSpace(
return largest_sent_retransmittable_packets_[packet_number_space];
}
-void QuicUnackedPacketMap::SetSessionDecideWhatToWrite(
- bool session_decides_what_to_write) {
- if (largest_sent_packet_.IsInitialized()) {
- QUIC_BUG << "Cannot change session_decide_what_to_write with packets sent.";
- return;
- }
- session_decides_what_to_write_ = session_decides_what_to_write;
-}
-
void QuicUnackedPacketMap::EnableMultiplePacketNumberSpacesSupport() {
if (supports_multiple_packet_number_spaces_) {
QUIC_BUG << "Multiple packet number spaces has already been enabled";
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h b/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h
index 864e485fbf0..fd6510a6c77 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h
@@ -34,12 +34,9 @@ class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
// Marks the packet as in flight if |set_in_flight| is true.
// Packets marked as in flight are expected to be marked as missing when they
// don't arrive, indicating the need for retransmission.
- // |old_packet_number| is the packet number of the previous transmission,
- // or 0 if there was none.
// Any AckNotifierWrappers in |serialized_packet| are swapped from the
// serialized packet into the QuicTransmissionInfo.
void AddSentPacket(SerializedPacket* serialized_packet,
- QuicPacketNumber old_packet_number,
TransmissionType transmission_type,
QuicTime sent_time,
bool set_in_flight);
@@ -68,9 +65,6 @@ class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
// Marks |packet_number| as no longer in flight.
void RemoveFromInFlight(QuicPacketNumber packet_number);
- // No longer retransmit data for |stream_id|.
- void CancelRetransmissionsForStream(QuicStreamId stream_id);
-
// Returns true if |packet_number| has retransmittable frames. This will
// return false if all frames of this packet are either non-retransmittable or
// have been acked.
@@ -100,6 +94,7 @@ class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
// Returns the sum of bytes from all packets in flight.
QuicByteCount bytes_in_flight() const { return bytes_in_flight_; }
+ QuicPacketCount packets_in_flight() const { return packets_in_flight_; }
// Returns the smallest packet number of a serialized packet which has not
// been acked by the peer. If there are no unacked packets, returns 0.
@@ -140,16 +135,14 @@ class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
size_t GetNumUnackedPacketsDebugOnly() const;
// Returns true if there are multiple packets in flight.
+ // TODO(fayang): Remove this method and use packets_in_flight_ instead.
bool HasMultipleInFlightPackets() const;
// Returns true if there are any pending crypto packets.
- // TODO(fayang): Remove this method and call session_notifier_'s
- // HasUnackedCryptoData() when session_decides_what_to_write_ is default true.
bool HasPendingCryptoPackets() const;
// Returns true if there is any unacked non-crypto stream data.
bool HasUnackedStreamData() const {
- DCHECK(session_decides_what_to_write());
return session_notifier_->HasUnackedStreamData();
}
@@ -210,37 +203,19 @@ class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
QuicPacketNumber GetLargestSentPacketOfPacketNumberSpace(
EncryptionLevel encryption_level) const;
- // Called to start/stop letting session decide what to write.
- void SetSessionDecideWhatToWrite(bool session_decides_what_to_write);
-
void SetSessionNotifier(SessionNotifierInterface* session_notifier);
void EnableMultiplePacketNumberSpacesSupport();
- bool session_decides_what_to_write() const {
- return session_decides_what_to_write_;
- }
-
Perspective perspective() const { return perspective_; }
bool supports_multiple_packet_number_spaces() const {
return supports_multiple_packet_number_spaces_;
}
- bool simple_inflight_time() const { return simple_inflight_time_; }
-
private:
friend class test::QuicUnackedPacketMapPeer;
- // Called when a packet is retransmitted with a new packet number.
- // |old_packet_number| will remain unacked, but will have no
- // retransmittable data associated with it. Retransmittable frames will be
- // transferred to |info| and all_transmissions will be populated.
- void TransferRetransmissionInfo(QuicPacketNumber old_packet_number,
- QuicPacketNumber new_packet_number,
- TransmissionType transmission_type,
- QuicTransmissionInfo* info);
-
// Returns true if packet may be useful for an RTT measurement.
bool IsPacketUsefulForMeasuringRtt(QuicPacketNumber packet_number,
const QuicTransmissionInfo& info) const;
@@ -287,8 +262,7 @@ class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
QuicPacketNumber least_unacked_;
QuicByteCount bytes_in_flight_;
- // Number of retransmittable crypto handshake packets.
- size_t pending_crypto_packet_count_;
+ QuicPacketCount packets_in_flight_;
// Time that the last inflight packet was sent.
QuicTime last_inflight_packet_sent_time_;
@@ -303,9 +277,6 @@ class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
// Receives notifications of frames being retransmitted or acknowledged.
SessionNotifierInterface* session_notifier_;
- // If true, let session decides what to write.
- bool session_decides_what_to_write_;
-
// If true, supports multiple packet number spaces.
bool supports_multiple_packet_number_spaces_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map_test.cc
index ad096396468..92e61e3bb02 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map_test.cc
@@ -24,43 +24,12 @@ namespace {
// Default packet length.
const uint32_t kDefaultLength = 1000;
-struct TestParams {
- TestParams(Perspective perspective, bool session_decides_what_to_write)
- : perspective(perspective),
- session_decides_what_to_write(session_decides_what_to_write) {}
-
- Perspective perspective;
- bool session_decides_what_to_write;
-};
-
-// Used by ::testing::PrintToStringParamName().
-std::string PrintToString(const TestParams& p) {
- return QuicStrCat(
- (p.perspective == Perspective::IS_CLIENT ? "Client" : "Server"),
- "_Session",
- (p.session_decides_what_to_write ? "Decides" : "DoesNotDecide"),
- "WhatToWrite");
-}
-
-std::vector<TestParams> GetTestParams() {
- std::vector<TestParams> params;
- for (Perspective perspective :
- {Perspective::IS_CLIENT, Perspective::IS_SERVER}) {
- for (bool session_decides_what_to_write : {true, false}) {
- params.push_back(TestParams(perspective, session_decides_what_to_write));
- }
- }
- return params;
-}
-
-class QuicUnackedPacketMapTest : public QuicTestWithParam<TestParams> {
+class QuicUnackedPacketMapTest : public QuicTestWithParam<Perspective> {
protected:
QuicUnackedPacketMapTest()
- : unacked_packets_(GetParam().perspective),
+ : unacked_packets_(GetParam()),
now_(QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1000)) {
unacked_packets_.SetSessionNotifier(&notifier_);
- unacked_packets_.SetSessionDecideWhatToWrite(
- GetParam().session_decides_what_to_write);
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(true));
EXPECT_CALL(notifier_, OnStreamFrameRetransmitted(_))
.Times(testing::AnyNumber());
@@ -167,14 +136,6 @@ class QuicUnackedPacketMapTest : public QuicTestWithParam<TestParams> {
TransmissionType transmission_type) {
DCHECK(unacked_packets_.HasRetransmittableFrames(
QuicPacketNumber(old_packet_number)));
- if (!unacked_packets_.session_decides_what_to_write()) {
- SerializedPacket packet(
- CreateNonRetransmittablePacket(new_packet_number));
- unacked_packets_.AddSentPacket(&packet,
- QuicPacketNumber(old_packet_number),
- transmission_type, now_, true);
- return;
- }
QuicTransmissionInfo* info = unacked_packets_.GetMutableTransmissionInfo(
QuicPacketNumber(old_packet_number));
QuicStreamId stream_id = QuicUtils::GetFirstBidirectionalStreamId(
@@ -192,8 +153,7 @@ class QuicUnackedPacketMapTest : public QuicTestWithParam<TestParams> {
info->retransmission = QuicPacketNumber(new_packet_number);
SerializedPacket packet(
CreateRetransmittablePacketForStream(new_packet_number, stream_id));
- unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(),
- transmission_type, now_, true);
+ unacked_packets_.AddSentPacket(&packet, transmission_type, now_, true);
}
QuicUnackedPacketMap unacked_packets_;
QuicTime now_;
@@ -202,14 +162,14 @@ class QuicUnackedPacketMapTest : public QuicTestWithParam<TestParams> {
INSTANTIATE_TEST_SUITE_P(Tests,
QuicUnackedPacketMapTest,
- ::testing::ValuesIn(GetTestParams()),
+ ::testing::ValuesIn({Perspective::IS_CLIENT,
+ Perspective::IS_SERVER}),
::testing::PrintToStringParamName());
TEST_P(QuicUnackedPacketMapTest, RttOnly) {
// Acks are only tracked for RTT measurement purposes.
SerializedPacket packet(CreateNonRetransmittablePacket(1));
- unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, false);
+ unacked_packets_.AddSentPacket(&packet, NOT_RETRANSMISSION, now_, false);
uint64_t unacked[] = {1};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
@@ -225,8 +185,7 @@ TEST_P(QuicUnackedPacketMapTest, RttOnly) {
TEST_P(QuicUnackedPacketMapTest, RetransmittableInflightAndRtt) {
// Simulate a retransmittable packet being sent and acked.
SerializedPacket packet(CreateRetransmittablePacket(1));
- unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet, NOT_RETRANSMISSION, now_, true);
uint64_t unacked[] = {1};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
@@ -252,8 +211,7 @@ TEST_P(QuicUnackedPacketMapTest, RetransmittableInflightAndRtt) {
TEST_P(QuicUnackedPacketMapTest, StopRetransmission) {
const QuicStreamId stream_id = 2;
SerializedPacket packet(CreateRetransmittablePacketForStream(1, stream_id));
- unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet, NOT_RETRANSMISSION, now_, true);
uint64_t unacked[] = {1};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
@@ -262,11 +220,7 @@ TEST_P(QuicUnackedPacketMapTest, StopRetransmission) {
VerifyRetransmittablePackets(retransmittable,
QUIC_ARRAYSIZE(retransmittable));
- if (unacked_packets_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
- } else {
- unacked_packets_.CancelRetransmissionsForStream(stream_id);
- }
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(nullptr, 0);
@@ -275,8 +229,7 @@ TEST_P(QuicUnackedPacketMapTest, StopRetransmission) {
TEST_P(QuicUnackedPacketMapTest, StopRetransmissionOnOtherStream) {
const QuicStreamId stream_id = 2;
SerializedPacket packet(CreateRetransmittablePacketForStream(1, stream_id));
- unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet, NOT_RETRANSMISSION, now_, true);
uint64_t unacked[] = {1};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
@@ -285,10 +238,6 @@ TEST_P(QuicUnackedPacketMapTest, StopRetransmissionOnOtherStream) {
VerifyRetransmittablePackets(retransmittable,
QUIC_ARRAYSIZE(retransmittable));
- // Stop retransmissions on another stream and verify the packet is unchanged.
- if (!unacked_packets_.session_decides_what_to_write()) {
- unacked_packets_.CancelRetransmissionsForStream(stream_id + 2);
- }
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(retransmittable,
@@ -298,26 +247,16 @@ TEST_P(QuicUnackedPacketMapTest, StopRetransmissionOnOtherStream) {
TEST_P(QuicUnackedPacketMapTest, StopRetransmissionAfterRetransmission) {
const QuicStreamId stream_id = 2;
SerializedPacket packet1(CreateRetransmittablePacketForStream(1, stream_id));
- unacked_packets_.AddSentPacket(&packet1, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet1, NOT_RETRANSMISSION, now_, true);
RetransmitAndSendPacket(1, 2, LOSS_RETRANSMISSION);
uint64_t unacked[] = {1, 2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
- std::vector<uint64_t> retransmittable;
- if (unacked_packets_.session_decides_what_to_write()) {
- retransmittable = {1, 2};
- } else {
- retransmittable = {2};
- }
+ std::vector<uint64_t> retransmittable = {1, 2};
VerifyRetransmittablePackets(&retransmittable[0], retransmittable.size());
- if (unacked_packets_.session_decides_what_to_write()) {
- EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
- } else {
- unacked_packets_.CancelRetransmissionsForStream(stream_id);
- }
+ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(nullptr, 0);
@@ -327,19 +266,13 @@ TEST_P(QuicUnackedPacketMapTest, RetransmittedPacket) {
// Simulate a retransmittable packet being sent, retransmitted, and the first
// transmission being acked.
SerializedPacket packet1(CreateRetransmittablePacket(1));
- unacked_packets_.AddSentPacket(&packet1, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet1, NOT_RETRANSMISSION, now_, true);
RetransmitAndSendPacket(1, 2, LOSS_RETRANSMISSION);
uint64_t unacked[] = {1, 2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
- std::vector<uint64_t> retransmittable;
- if (unacked_packets_.session_decides_what_to_write()) {
- retransmittable = {1, 2};
- } else {
- retransmittable = {2};
- }
+ std::vector<uint64_t> retransmittable = {1, 2};
VerifyRetransmittablePackets(&retransmittable[0], retransmittable.size());
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
@@ -368,11 +301,9 @@ TEST_P(QuicUnackedPacketMapTest, RetransmittedPacket) {
TEST_P(QuicUnackedPacketMapTest, RetransmitThreeTimes) {
// Simulate a retransmittable packet being sent and retransmitted twice.
SerializedPacket packet1(CreateRetransmittablePacket(1));
- unacked_packets_.AddSentPacket(&packet1, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet1, NOT_RETRANSMISSION, now_, true);
SerializedPacket packet2(CreateRetransmittablePacket(2));
- unacked_packets_.AddSentPacket(&packet2, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet2, NOT_RETRANSMISSION, now_, true);
uint64_t unacked[] = {1, 2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
@@ -388,19 +319,13 @@ TEST_P(QuicUnackedPacketMapTest, RetransmitThreeTimes) {
unacked_packets_.RemoveFromInFlight(QuicPacketNumber(1));
RetransmitAndSendPacket(1, 3, LOSS_RETRANSMISSION);
SerializedPacket packet4(CreateRetransmittablePacket(4));
- unacked_packets_.AddSentPacket(&packet4, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet4, NOT_RETRANSMISSION, now_, true);
uint64_t unacked2[] = {1, 3, 4};
VerifyUnackedPackets(unacked2, QUIC_ARRAYSIZE(unacked2));
uint64_t pending2[] = {3, 4};
VerifyInFlightPackets(pending2, QUIC_ARRAYSIZE(pending2));
- std::vector<uint64_t> retransmittable2;
- if (unacked_packets_.session_decides_what_to_write()) {
- retransmittable2 = {1, 3, 4};
- } else {
- retransmittable2 = {3, 4};
- }
+ std::vector<uint64_t> retransmittable2 = {1, 3, 4};
VerifyRetransmittablePackets(&retransmittable2[0], retransmittable2.size());
// Early retransmit 3 (formerly 1) as 5, and remove 1 from unacked.
@@ -409,18 +334,10 @@ TEST_P(QuicUnackedPacketMapTest, RetransmitThreeTimes) {
unacked_packets_.RemoveRetransmittability(QuicPacketNumber(4));
RetransmitAndSendPacket(3, 5, LOSS_RETRANSMISSION);
SerializedPacket packet6(CreateRetransmittablePacket(6));
- unacked_packets_.AddSentPacket(&packet6, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, true);
-
- std::vector<uint64_t> unacked3;
- std::vector<uint64_t> retransmittable3;
- if (unacked_packets_.session_decides_what_to_write()) {
- unacked3 = {3, 5, 6};
- retransmittable3 = {3, 5, 6};
- } else {
- unacked3 = {3, 5, 6};
- retransmittable3 = {5, 6};
- }
+ unacked_packets_.AddSentPacket(&packet6, NOT_RETRANSMISSION, now_, true);
+
+ std::vector<uint64_t> unacked3 = {3, 5, 6};
+ std::vector<uint64_t> retransmittable3 = {3, 5, 6};
VerifyUnackedPackets(&unacked3[0], unacked3.size());
VerifyRetransmittablePackets(&retransmittable3[0], retransmittable3.size());
uint64_t pending3[] = {3, 5, 6};
@@ -432,15 +349,8 @@ TEST_P(QuicUnackedPacketMapTest, RetransmitThreeTimes) {
unacked_packets_.RemoveRetransmittability(QuicPacketNumber(6));
RetransmitAndSendPacket(5, 7, LOSS_RETRANSMISSION);
- std::vector<uint64_t> unacked4;
- std::vector<uint64_t> retransmittable4;
- if (unacked_packets_.session_decides_what_to_write()) {
- unacked4 = {3, 5, 7};
- retransmittable4 = {3, 5, 7};
- } else {
- unacked4 = {3, 5, 7};
- retransmittable4 = {7};
- }
+ std::vector<uint64_t> unacked4 = {3, 5, 7};
+ std::vector<uint64_t> retransmittable4 = {3, 5, 7};
VerifyUnackedPackets(&unacked4[0], unacked4.size());
VerifyRetransmittablePackets(&retransmittable4[0], retransmittable4.size());
uint64_t pending4[] = {3, 5, 7};
@@ -456,11 +366,9 @@ TEST_P(QuicUnackedPacketMapTest, RetransmitThreeTimes) {
TEST_P(QuicUnackedPacketMapTest, RetransmitFourTimes) {
// Simulate a retransmittable packet being sent and retransmitted twice.
SerializedPacket packet1(CreateRetransmittablePacket(1));
- unacked_packets_.AddSentPacket(&packet1, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet1, NOT_RETRANSMISSION, now_, true);
SerializedPacket packet2(CreateRetransmittablePacket(2));
- unacked_packets_.AddSentPacket(&packet2, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet2, NOT_RETRANSMISSION, now_, true);
uint64_t unacked[] = {1, 2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
@@ -480,30 +388,19 @@ TEST_P(QuicUnackedPacketMapTest, RetransmitFourTimes) {
VerifyUnackedPackets(unacked2, QUIC_ARRAYSIZE(unacked2));
uint64_t pending2[] = {3};
VerifyInFlightPackets(pending2, QUIC_ARRAYSIZE(pending2));
- std::vector<uint64_t> retransmittable2;
- if (unacked_packets_.session_decides_what_to_write()) {
- retransmittable2 = {1, 3};
- } else {
- retransmittable2 = {3};
- }
+ std::vector<uint64_t> retransmittable2 = {1, 3};
VerifyRetransmittablePackets(&retransmittable2[0], retransmittable2.size());
// TLP 3 (formerly 1) as 4, and don't remove 1 from unacked.
RetransmitAndSendPacket(3, 4, TLP_RETRANSMISSION);
SerializedPacket packet5(CreateRetransmittablePacket(5));
- unacked_packets_.AddSentPacket(&packet5, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet5, NOT_RETRANSMISSION, now_, true);
uint64_t unacked3[] = {1, 3, 4, 5};
VerifyUnackedPackets(unacked3, QUIC_ARRAYSIZE(unacked3));
uint64_t pending3[] = {3, 4, 5};
VerifyInFlightPackets(pending3, QUIC_ARRAYSIZE(pending3));
- std::vector<uint64_t> retransmittable3;
- if (unacked_packets_.session_decides_what_to_write()) {
- retransmittable3 = {1, 3, 4, 5};
- } else {
- retransmittable3 = {4, 5};
- }
+ std::vector<uint64_t> retransmittable3 = {1, 3, 4, 5};
VerifyRetransmittablePackets(&retransmittable3[0], retransmittable3.size());
// Early retransmit 4 as 6 and ensure in flight packet 3 is removed.
@@ -514,21 +411,11 @@ TEST_P(QuicUnackedPacketMapTest, RetransmitFourTimes) {
unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4));
RetransmitAndSendPacket(4, 6, LOSS_RETRANSMISSION);
- std::vector<uint64_t> unacked4;
- if (unacked_packets_.session_decides_what_to_write()) {
- unacked4 = {4, 6};
- } else {
- unacked4 = {4, 6};
- }
+ std::vector<uint64_t> unacked4 = {4, 6};
VerifyUnackedPackets(&unacked4[0], unacked4.size());
uint64_t pending4[] = {6};
VerifyInFlightPackets(pending4, QUIC_ARRAYSIZE(pending4));
- std::vector<uint64_t> retransmittable4;
- if (unacked_packets_.session_decides_what_to_write()) {
- retransmittable4 = {4, 6};
- } else {
- retransmittable4 = {6};
- }
+ std::vector<uint64_t> retransmittable4 = {4, 6};
VerifyRetransmittablePackets(&retransmittable4[0], retransmittable4.size());
}
@@ -536,11 +423,9 @@ TEST_P(QuicUnackedPacketMapTest, SendWithGap) {
// Simulate a retransmittable packet being sent, retransmitted, and the first
// transmission being acked.
SerializedPacket packet1(CreateRetransmittablePacket(1));
- unacked_packets_.AddSentPacket(&packet1, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet1, NOT_RETRANSMISSION, now_, true);
SerializedPacket packet3(CreateRetransmittablePacket(3));
- unacked_packets_.AddSentPacket(&packet3, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet3, NOT_RETRANSMISSION, now_, true);
RetransmitAndSendPacket(3, 5, LOSS_RETRANSMISSION);
EXPECT_EQ(QuicPacketNumber(1u), unacked_packets_.GetLeastUnacked());
@@ -685,8 +570,7 @@ TEST_P(QuicUnackedPacketMapTest, LargestSentPacketMultiplePacketNumberSpaces) {
// Send packet 1.
SerializedPacket packet1(CreateRetransmittablePacket(1));
packet1.encryption_level = ENCRYPTION_INITIAL;
- unacked_packets_.AddSentPacket(&packet1, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet1, NOT_RETRANSMISSION, now_, true);
EXPECT_EQ(QuicPacketNumber(1u), unacked_packets_.largest_sent_packet());
EXPECT_EQ(QuicPacketNumber(1),
unacked_packets_.GetLargestSentPacketOfPacketNumberSpace(
@@ -698,8 +582,7 @@ TEST_P(QuicUnackedPacketMapTest, LargestSentPacketMultiplePacketNumberSpaces) {
// Send packet 2.
SerializedPacket packet2(CreateRetransmittablePacket(2));
packet2.encryption_level = ENCRYPTION_HANDSHAKE;
- unacked_packets_.AddSentPacket(&packet2, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet2, NOT_RETRANSMISSION, now_, true);
EXPECT_EQ(QuicPacketNumber(2u), unacked_packets_.largest_sent_packet());
EXPECT_EQ(QuicPacketNumber(1),
unacked_packets_.GetLargestSentPacketOfPacketNumberSpace(
@@ -713,8 +596,7 @@ TEST_P(QuicUnackedPacketMapTest, LargestSentPacketMultiplePacketNumberSpaces) {
// Send packet 3.
SerializedPacket packet3(CreateRetransmittablePacket(3));
packet3.encryption_level = ENCRYPTION_ZERO_RTT;
- unacked_packets_.AddSentPacket(&packet3, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet3, NOT_RETRANSMISSION, now_, true);
EXPECT_EQ(QuicPacketNumber(3u), unacked_packets_.largest_sent_packet());
EXPECT_EQ(QuicPacketNumber(1),
unacked_packets_.GetLargestSentPacketOfPacketNumberSpace(
@@ -734,8 +616,7 @@ TEST_P(QuicUnackedPacketMapTest, LargestSentPacketMultiplePacketNumberSpaces) {
// Send packet 4.
SerializedPacket packet4(CreateRetransmittablePacket(4));
packet4.encryption_level = ENCRYPTION_FORWARD_SECURE;
- unacked_packets_.AddSentPacket(&packet4, QuicPacketNumber(),
- NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet4, NOT_RETRANSMISSION, now_, true);
EXPECT_EQ(QuicPacketNumber(4u), unacked_packets_.largest_sent_packet());
EXPECT_EQ(QuicPacketNumber(1),
unacked_packets_.GetLargestSentPacketOfPacketNumberSpace(
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 33f7de16c18..a69efcdf822 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
@@ -15,11 +15,11 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_aligned.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_prefetch.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
namespace {
@@ -161,10 +161,12 @@ const char* QuicUtils::SentPacketStateToString(SentPacketState state) {
RETURN_STRING_LITERAL(NEVER_SENT);
RETURN_STRING_LITERAL(ACKED);
RETURN_STRING_LITERAL(UNACKABLE);
+ RETURN_STRING_LITERAL(NEUTERED);
RETURN_STRING_LITERAL(HANDSHAKE_RETRANSMITTED);
RETURN_STRING_LITERAL(LOST);
RETURN_STRING_LITERAL(TLP_RETRANSMITTED);
RETURN_STRING_LITERAL(RTO_RETRANSMITTED);
+ RETURN_STRING_LITERAL(PTO_RETRANSMITTED);
RETURN_STRING_LITERAL(PROBE_RETRANSMITTED);
}
return "INVALID_SENT_PACKET_STATE";
@@ -329,6 +331,8 @@ SentPacketState QuicUtils::RetransmissionTypeToPacketState(
return TLP_RETRANSMITTED;
case RTO_RETRANSMISSION:
return RTO_RETRANSMITTED;
+ case PTO_RETRANSMISSION:
+ return PTO_RETRANSMITTED;
case PROBING_RETRANSMISSION:
return PROBE_RETRANSMITTED;
default:
@@ -514,7 +518,7 @@ bool QuicUtils::VariableLengthConnectionIdAllowedForVersion(
// We allow variable length connection IDs for unsupported versions to
// ensure that IETF version negotiation works when other implementations
// trigger version negotiation with custom connection ID lengths.
- return version >= QUIC_VERSION_47 || version == QUIC_VERSION_UNSUPPORTED;
+ return version > QUIC_VERSION_46 || version == QUIC_VERSION_UNSUPPORTED;
}
// static
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 62cfbd0cc99..362c766b7de 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
@@ -131,6 +131,8 @@ TEST_F(QuicUtilsTest, RetransmissionTypeToPacketState) {
EXPECT_EQ(TLP_RETRANSMITTED, state);
} else if (i == RTO_RETRANSMISSION) {
EXPECT_EQ(RTO_RETRANSMITTED, state);
+ } else if (i == PTO_RETRANSMISSION) {
+ EXPECT_EQ(PTO_RETRANSMITTED, state);
} else if (i == PROBING_RETRANSMISSION) {
EXPECT_EQ(PROBE_RETRANSMITTED, state);
} else {
@@ -244,17 +246,17 @@ TEST_F(QuicUtilsTest, RandomConnectionIdVariableLength) {
TEST_F(QuicUtilsTest, VariableLengthConnectionId) {
EXPECT_FALSE(
- QuicUtils::VariableLengthConnectionIdAllowedForVersion(QUIC_VERSION_39));
+ QuicUtils::VariableLengthConnectionIdAllowedForVersion(QUIC_VERSION_43));
EXPECT_TRUE(QuicUtils::IsConnectionIdValidForVersion(
- QuicUtils::CreateZeroConnectionId(QUIC_VERSION_39), QUIC_VERSION_39));
+ QuicUtils::CreateZeroConnectionId(QUIC_VERSION_43), QUIC_VERSION_43));
EXPECT_TRUE(QuicUtils::IsConnectionIdValidForVersion(
QuicUtils::CreateZeroConnectionId(QUIC_VERSION_99), QUIC_VERSION_99));
- EXPECT_NE(QuicUtils::CreateZeroConnectionId(QUIC_VERSION_39),
+ EXPECT_NE(QuicUtils::CreateZeroConnectionId(QUIC_VERSION_43),
EmptyQuicConnectionId());
EXPECT_EQ(QuicUtils::CreateZeroConnectionId(QUIC_VERSION_99),
EmptyQuicConnectionId());
EXPECT_FALSE(QuicUtils::IsConnectionIdValidForVersion(EmptyQuicConnectionId(),
- QUIC_VERSION_39));
+ QUIC_VERSION_43));
}
TEST_F(QuicUtilsTest, StatelessResetToken) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc
index 5f14ad4e80a..476bbc7fad3 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc
@@ -17,13 +17,9 @@ QuicVersionManager::QuicVersionManager(
ParsedQuicVersionVector supported_versions)
: enable_version_99_(GetQuicReloadableFlag(quic_enable_version_99)),
enable_version_50_(GetQuicReloadableFlag(quic_enable_version_50)),
- enable_version_49_(GetQuicReloadableFlag(quic_enable_version_49)),
- enable_version_48_(GetQuicReloadableFlag(quic_enable_version_48_2)),
- enable_version_47_(GetQuicReloadableFlag(quic_enable_version_47)),
- disable_version_39_(GetQuicReloadableFlag(quic_disable_version_39)),
enable_tls_(GetQuicReloadableFlag(quic_supports_tls_handshake)),
allowed_supported_versions_(std::move(supported_versions)) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
"Supported versions out of sync");
RefilterSupportedVersions();
}
@@ -42,21 +38,13 @@ const ParsedQuicVersionVector& QuicVersionManager::GetSupportedVersions() {
}
void QuicVersionManager::MaybeRefilterSupportedVersions() {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
"Supported versions out of sync");
if (enable_version_99_ != GetQuicReloadableFlag(quic_enable_version_99) ||
enable_version_50_ != GetQuicReloadableFlag(quic_enable_version_50) ||
- enable_version_49_ != GetQuicReloadableFlag(quic_enable_version_49) ||
- enable_version_48_ != GetQuicReloadableFlag(quic_enable_version_48_2) ||
- enable_version_47_ != GetQuicReloadableFlag(quic_enable_version_47) ||
- disable_version_39_ != GetQuicReloadableFlag(quic_disable_version_39) ||
enable_tls_ != GetQuicReloadableFlag(quic_supports_tls_handshake)) {
enable_version_99_ = GetQuicReloadableFlag(quic_enable_version_99);
enable_version_50_ = GetQuicReloadableFlag(quic_enable_version_50);
- enable_version_49_ = GetQuicReloadableFlag(quic_enable_version_49);
- enable_version_48_ = GetQuicReloadableFlag(quic_enable_version_48_2);
- enable_version_47_ = GetQuicReloadableFlag(quic_enable_version_47);
- disable_version_39_ = GetQuicReloadableFlag(quic_disable_version_39);
enable_tls_ = GetQuicReloadableFlag(quic_supports_tls_handshake);
RefilterSupportedVersions();
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h
index 3b2ec854230..0851464b857 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h
@@ -45,14 +45,6 @@ class QUIC_EXPORT_PRIVATE QuicVersionManager {
bool enable_version_99_;
// quic_enable_version_50 flag
bool enable_version_50_;
- // quic_enable_version_49 flag
- bool enable_version_49_;
- // quic_enable_version_48_2 flag
- bool enable_version_48_;
- // quic_enable_version_47 flag
- bool enable_version_47_;
- // quic_disable_version_39 flag
- bool disable_version_39_;
// quic_supports_tls_handshake flag
bool enable_tls_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager_test.cc
index 87494772887..48623a878f3 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager_test.cc
@@ -16,64 +16,36 @@ namespace {
class QuicVersionManagerTest : public QuicTest {};
TEST_F(QuicVersionManagerTest, QuicVersionManager) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
"Supported versions out of sync");
SetQuicReloadableFlag(quic_enable_version_99, false);
SetQuicReloadableFlag(quic_enable_version_50, false);
- SetQuicReloadableFlag(quic_enable_version_49, false);
- SetQuicReloadableFlag(quic_enable_version_48_2, false);
- SetQuicReloadableFlag(quic_enable_version_47, false);
- SetQuicReloadableFlag(quic_disable_version_39, true);
QuicVersionManager manager(AllSupportedVersions());
EXPECT_EQ(FilterSupportedTransportVersions(AllSupportedTransportVersions()),
manager.GetSupportedTransportVersions());
- EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_46, QUIC_VERSION_43}),
- manager.GetSupportedTransportVersions());
-
- SetQuicReloadableFlag(quic_disable_version_39, false);
- EXPECT_EQ(QuicTransportVersionVector(
- {QUIC_VERSION_46, QUIC_VERSION_43, QUIC_VERSION_39}),
- manager.GetSupportedTransportVersions());
-
- SetQuicReloadableFlag(quic_enable_version_47, true);
- EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_47, QUIC_VERSION_46,
- QUIC_VERSION_43, QUIC_VERSION_39}),
- manager.GetSupportedTransportVersions());
-
- SetQuicReloadableFlag(quic_enable_version_48_2, true);
- EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_48, QUIC_VERSION_47,
- QUIC_VERSION_46, QUIC_VERSION_43,
- QUIC_VERSION_39}),
- manager.GetSupportedTransportVersions());
-
- SetQuicReloadableFlag(quic_enable_version_49, true);
EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_49, QUIC_VERSION_48,
- QUIC_VERSION_47, QUIC_VERSION_46,
- QUIC_VERSION_43, QUIC_VERSION_39}),
+ QUIC_VERSION_46, QUIC_VERSION_43}),
manager.GetSupportedTransportVersions());
SetQuicReloadableFlag(quic_enable_version_50, true);
- EXPECT_EQ(
- QuicTransportVersionVector(
- {QUIC_VERSION_50, QUIC_VERSION_49, QUIC_VERSION_48, QUIC_VERSION_47,
- QUIC_VERSION_46, QUIC_VERSION_43, QUIC_VERSION_39}),
- manager.GetSupportedTransportVersions());
+ EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_50, QUIC_VERSION_49,
+ QUIC_VERSION_48, QUIC_VERSION_46,
+ QUIC_VERSION_43}),
+ manager.GetSupportedTransportVersions());
SetQuicReloadableFlag(quic_enable_version_99, true);
- EXPECT_EQ(
- QuicTransportVersionVector(
- {QUIC_VERSION_99, QUIC_VERSION_50, QUIC_VERSION_49, QUIC_VERSION_48,
- QUIC_VERSION_47, QUIC_VERSION_46, QUIC_VERSION_43, QUIC_VERSION_39}),
- manager.GetSupportedTransportVersions());
+ EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_99, QUIC_VERSION_50,
+ QUIC_VERSION_49, QUIC_VERSION_48,
+ QUIC_VERSION_46, QUIC_VERSION_43}),
+ manager.GetSupportedTransportVersions());
SetQuicReloadableFlag(quic_enable_version_99, true);
- EXPECT_EQ(
- QuicTransportVersionVector(
- {QUIC_VERSION_99, QUIC_VERSION_50, QUIC_VERSION_49, QUIC_VERSION_48,
- QUIC_VERSION_47, QUIC_VERSION_46, QUIC_VERSION_43, QUIC_VERSION_39}),
- manager.GetSupportedTransportVersions());
+ EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_99, QUIC_VERSION_50,
+ QUIC_VERSION_49, QUIC_VERSION_48,
+ QUIC_VERSION_46, QUIC_VERSION_43}),
+ manager.GetSupportedTransportVersions());
// Ensure that all versions are now supported.
EXPECT_EQ(FilterSupportedTransportVersions(AllSupportedTransportVersions()),
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 7aabc3d4b2f..abeb64e7f7f 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
@@ -11,11 +11,11 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
namespace {
@@ -27,10 +27,6 @@ QuicVersionLabel MakeVersionLabel(char a, char b, char c, char d) {
}
QuicVersionLabel CreateRandomVersionLabelForNegotiation() {
- if (!GetQuicReloadableFlag(quic_version_negotiation_grease)) {
- return MakeVersionLabel(0xda, 0x5a, 0x3a, 0x3a);
- }
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_version_negotiation_grease, 2, 2);
QuicVersionLabel result;
if (!GetQuicFlag(FLAGS_quic_disable_version_negotiation_grease_randomness)) {
QuicRandom::GetInstance()->RandBytes(&result, sizeof(result));
@@ -44,13 +40,8 @@ QuicVersionLabel CreateRandomVersionLabelForNegotiation() {
} // namespace
-ParsedQuicVersion::ParsedQuicVersion(HandshakeProtocol handshake_protocol,
- QuicTransportVersion transport_version)
- : handshake_protocol(handshake_protocol),
- transport_version(transport_version) {}
-
bool ParsedQuicVersion::KnowsWhichDecrypterToUse() const {
- return transport_version >= QUIC_VERSION_47 ||
+ return transport_version > QUIC_VERSION_46 ||
handshake_protocol == PROTOCOL_TLS1_3;
}
@@ -89,6 +80,11 @@ bool ParsedQuicVersion::SupportsAntiAmplificationLimit() const {
handshake_protocol == PROTOCOL_TLS1_3;
}
+bool ParsedQuicVersion::CanSendCoalescedPackets() const {
+ return QuicVersionHasLongHeaderLengths(transport_version) &&
+ handshake_protocol == PROTOCOL_TLS1_3;
+}
+
bool VersionHasLengthPrefixedConnectionIds(
QuicTransportVersion transport_version) {
return transport_version > QUIC_VERSION_48;
@@ -113,17 +109,13 @@ QuicVersionLabel CreateQuicVersionLabel(ParsedQuicVersion parsed_version) {
<< parsed_version.handshake_protocol;
return 0;
}
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
"Supported versions out of sync");
switch (parsed_version.transport_version) {
- case QUIC_VERSION_39:
- return MakeVersionLabel(proto, '0', '3', '9');
case QUIC_VERSION_43:
return MakeVersionLabel(proto, '0', '4', '3');
case QUIC_VERSION_46:
return MakeVersionLabel(proto, '0', '4', '6');
- case QUIC_VERSION_47:
- return MakeVersionLabel(proto, '0', '4', '7');
case QUIC_VERSION_48:
return MakeVersionLabel(proto, '0', '4', '8');
case QUIC_VERSION_49:
@@ -274,22 +266,6 @@ ParsedQuicVersionVector FilterSupportedVersions(
if (GetQuicReloadableFlag(quic_enable_version_50)) {
filtered_versions.push_back(version);
}
- } else if (version.transport_version == QUIC_VERSION_49) {
- if (GetQuicReloadableFlag(quic_enable_version_49)) {
- filtered_versions.push_back(version);
- }
- } else if (version.transport_version == QUIC_VERSION_48) {
- if (GetQuicReloadableFlag(quic_enable_version_48_2)) {
- filtered_versions.push_back(version);
- }
- } else if (version.transport_version == QUIC_VERSION_47) {
- if (GetQuicReloadableFlag(quic_enable_version_47)) {
- filtered_versions.push_back(version);
- }
- } else if (version.transport_version == QUIC_VERSION_39) {
- if (!GetQuicReloadableFlag(quic_disable_version_39)) {
- filtered_versions.push_back(version);
- }
} else {
filtered_versions.push_back(version);
}
@@ -340,7 +316,7 @@ QuicVersionLabel QuicVersionToQuicVersionLabel(
}
std::string QuicVersionLabelToString(QuicVersionLabel version_label) {
- return QuicTagToString(QuicEndian::HostToNet32(version_label));
+ return QuicTagToString(quiche::QuicheEndian::HostToNet32(version_label));
}
std::string QuicVersionLabelVectorToString(
@@ -377,13 +353,11 @@ HandshakeProtocol QuicVersionLabelToHandshakeProtocol(
return #x
std::string QuicVersionToString(QuicTransportVersion transport_version) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
"Supported versions out of sync");
switch (transport_version) {
- RETURN_STRING_LITERAL(QUIC_VERSION_39);
RETURN_STRING_LITERAL(QUIC_VERSION_43);
RETURN_STRING_LITERAL(QUIC_VERSION_46);
- RETURN_STRING_LITERAL(QUIC_VERSION_47);
RETURN_STRING_LITERAL(QUIC_VERSION_48);
RETURN_STRING_LITERAL(QUIC_VERSION_49);
RETURN_STRING_LITERAL(QUIC_VERSION_50);
@@ -430,6 +404,10 @@ std::string ParsedQuicVersionVectorToString(
return result;
}
+bool VersionSupportsGoogleAltSvcFormat(QuicTransportVersion transport_version) {
+ return transport_version <= QUIC_VERSION_46;
+}
+
bool QuicVersionLabelUses4BitConnectionIdLength(
QuicVersionLabel version_label) {
// As we deprecate old versions, we still need the ability to send valid
@@ -478,14 +456,13 @@ std::string AlpnForVersion(ParsedQuicVersion parsed_version) {
void QuicVersionInitializeSupportForIetfDraft() {
// Enable necessary flags.
SetQuicReloadableFlag(quic_supports_tls_handshake, true);
- SetQuicReloadableFlag(quic_simplify_stop_waiting, true);
}
void QuicEnableVersion(ParsedQuicVersion parsed_version) {
if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3) {
SetQuicReloadableFlag(quic_supports_tls_handshake, true);
}
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
"Supported versions out of sync");
if (parsed_version.transport_version == QUIC_VERSION_99) {
SetQuicReloadableFlag(quic_enable_version_99, true);
@@ -493,15 +470,6 @@ void QuicEnableVersion(ParsedQuicVersion parsed_version) {
if (parsed_version.transport_version == QUIC_VERSION_50) {
SetQuicReloadableFlag(quic_enable_version_50, true);
}
- if (parsed_version.transport_version == QUIC_VERSION_49) {
- SetQuicReloadableFlag(quic_enable_version_49, true);
- }
- if (parsed_version.transport_version == QUIC_VERSION_48) {
- SetQuicReloadableFlag(quic_enable_version_48_2, true);
- }
- if (parsed_version.transport_version == QUIC_VERSION_47) {
- SetQuicReloadableFlag(quic_enable_version_47, true);
- }
}
#undef RETURN_STRING_LITERAL // undef for jumbo builds
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_versions.h b/chromium/net/third_party/quiche/src/quic/core/quic_versions.h
index de5bbea167c..0a4022e2006 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_versions.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_versions.h
@@ -82,10 +82,9 @@ enum QuicTransportVersion {
// Version 38 switched to IETF padding frame format and support for NSTP (no
// stop waiting frame) connection option.
- QUIC_VERSION_39 = 39, // Integers and floating numbers are written in big
- // endian. Dot not ack acks. Send a connection level
- // WINDOW_UPDATE every 20 sent packets which do not
- // contain retransmittable frames.
+ // Version 39 writes integers and floating numbers in big endian, stops acking
+ // acks, sends a connection level WINDOW_UPDATE every 20 sent packets which do
+ // not contain retransmittable frames.
// Version 40 was an attempt to convert QUIC to IETF frame format; it was
// never shipped due to a bug.
@@ -103,7 +102,7 @@ enum QuicTransportVersion {
QUIC_VERSION_46 = 46, // Use IETF draft-17 header format with demultiplexing
// bit.
- QUIC_VERSION_47 = 47, // Allow variable-length QUIC connection IDs.
+ // Version 47 added variable-length QUIC server connection IDs.
QUIC_VERSION_48 = 48, // Use CRYPTO frames for the handshake.
QUIC_VERSION_49 = 49, // Client connection IDs, long header lengths, IETF
// header format from draft-ietf-quic-invariants-06.
@@ -120,7 +119,7 @@ enum QuicTransportVersion {
};
// IETF draft version most closely approximated by TLS + v99.
-static const int kQuicIetfDraftVersion = 23;
+static const int kQuicIetfDraftVersion = 24;
// The crypto handshake protocols that can be used with QUIC.
enum HandshakeProtocol {
@@ -135,10 +134,12 @@ struct QUIC_EXPORT_PRIVATE ParsedQuicVersion {
HandshakeProtocol handshake_protocol;
QuicTransportVersion transport_version;
- ParsedQuicVersion(HandshakeProtocol handshake_protocol,
- QuicTransportVersion transport_version);
+ constexpr ParsedQuicVersion(HandshakeProtocol handshake_protocol,
+ QuicTransportVersion transport_version)
+ : handshake_protocol(handshake_protocol),
+ transport_version(transport_version) {}
- ParsedQuicVersion(const ParsedQuicVersion& other)
+ constexpr ParsedQuicVersion(const ParsedQuicVersion& other)
: handshake_protocol(other.handshake_protocol),
transport_version(other.transport_version) {}
@@ -192,6 +193,9 @@ struct QUIC_EXPORT_PRIVATE ParsedQuicVersion {
// i.e., server will send no more than FLAGS_quic_anti_amplification_factor
// times received bytes until address can be validated.
bool SupportsAntiAmplificationLimit() const;
+
+ // Returns true if this version can send coalesced packets.
+ bool CanSendCoalescedPackets() const;
};
QUIC_EXPORT_PRIVATE ParsedQuicVersion UnsupportedQuicVersion();
@@ -215,8 +219,8 @@ using QuicVersionLabelVector = std::vector<QuicVersionLabel>;
//
// See go/new-quic-version for more details on how to roll out new versions.
static const QuicTransportVersion kSupportedTransportVersions[] = {
- QUIC_VERSION_99, QUIC_VERSION_50, QUIC_VERSION_49, QUIC_VERSION_48,
- QUIC_VERSION_47, QUIC_VERSION_46, QUIC_VERSION_43, QUIC_VERSION_39,
+ QUIC_VERSION_99, QUIC_VERSION_50, QUIC_VERSION_49,
+ QUIC_VERSION_48, QUIC_VERSION_46, QUIC_VERSION_43,
};
// This vector contains all crypto handshake protocols that are supported.
@@ -416,6 +420,11 @@ QUIC_EXPORT_PRIVATE inline bool VersionHasIetfQuicFrames(
QUIC_EXPORT_PRIVATE bool VersionHasLengthPrefixedConnectionIds(
QuicTransportVersion transport_version);
+// Returns true if this version supports the old Google-style Alt-Svc
+// advertisement format.
+QUIC_EXPORT_PRIVATE bool VersionSupportsGoogleAltSvcFormat(
+ QuicTransportVersion transport_version);
+
// Returns whether this version label supports long header 4-bit encoded
// connection ID lengths as described in draft-ietf-quic-invariants-05 and
// draft-ietf-quic-transport-21.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc
index a631187c561..283113fe37f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc
@@ -35,8 +35,8 @@ TEST_F(QuicVersionsTest, QuicVersionToQuicVersionLabel) {
log.StartCapturingLogs();
// Explicitly test a specific version.
- EXPECT_EQ(MakeQuicTag('9', '3', '0', 'Q'),
- QuicVersionToQuicVersionLabel(QUIC_VERSION_39));
+ EXPECT_EQ(MakeQuicTag('3', '4', '0', 'Q'),
+ QuicVersionToQuicVersionLabel(QUIC_VERSION_43));
// Loop over all supported versions and make sure that we never hit the
// default case (i.e. all supported versions should be successfully converted
@@ -63,8 +63,8 @@ TEST_F(QuicVersionsTest, QuicVersionLabelToQuicTransportVersion) {
log.StartCapturingLogs();
// Explicitly test specific versions.
- EXPECT_EQ(QUIC_VERSION_39,
- QuicVersionLabelToQuicVersion(MakeQuicTag('9', '3', '0', 'Q')));
+ EXPECT_EQ(QUIC_VERSION_43,
+ QuicVersionLabelToQuicVersion(MakeQuicTag('3', '4', '0', 'Q')));
for (size_t i = 0; i < QUIC_ARRAYSIZE(kSupportedTransportVersions); ++i) {
QuicTransportVersion version = kSupportedTransportVersions[i];
@@ -112,28 +112,20 @@ TEST_F(QuicVersionsTest, QuicVersionLabelToHandshakeProtocol) {
}
TEST_F(QuicVersionsTest, ParseQuicVersionLabel) {
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39),
- ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '3', '9')));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43),
ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '4', '3')));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46),
ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '4', '6')));
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47),
- ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '4', '7')));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48),
ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '4', '8')));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50),
ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '5', '0')));
// Test TLS versions:
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_39),
- ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '9')));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_43),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '3')));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_46),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '6')));
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47),
- ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '7')));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_48),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '8')));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_50),
@@ -141,33 +133,25 @@ TEST_F(QuicVersionsTest, ParseQuicVersionLabel) {
}
TEST_F(QuicVersionsTest, ParseQuicVersionString) {
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39),
- ParseQuicVersionString("Q039"));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43),
ParseQuicVersionString("Q043"));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46),
ParseQuicVersionString("Q046"));
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47),
- ParseQuicVersionString("Q047"));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48),
ParseQuicVersionString("Q048"));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50),
ParseQuicVersionString("Q050"));
EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString(""));
- EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("Q 47"));
- EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("Q047 "));
+ EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("Q 46"));
+ EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("Q046 "));
// Test a TLS version:
SetQuicReloadableFlag(quic_supports_tls_handshake, true);
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_39),
- ParseQuicVersionString("T039"));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_43),
ParseQuicVersionString("T043"));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_46),
ParseQuicVersionString("T046"));
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47),
- ParseQuicVersionString("T047"));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_48),
ParseQuicVersionString("T048"));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_50),
@@ -175,18 +159,12 @@ TEST_F(QuicVersionsTest, ParseQuicVersionString) {
}
TEST_F(QuicVersionsTest, CreateQuicVersionLabel) {
- EXPECT_EQ(MakeVersionLabel('Q', '0', '3', '9'),
- CreateQuicVersionLabel(
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39)));
EXPECT_EQ(MakeVersionLabel('Q', '0', '4', '3'),
CreateQuicVersionLabel(
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43)));
EXPECT_EQ(MakeVersionLabel('Q', '0', '4', '6'),
CreateQuicVersionLabel(
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46)));
- EXPECT_EQ(MakeVersionLabel('Q', '0', '4', '7'),
- CreateQuicVersionLabel(
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47)));
EXPECT_EQ(MakeVersionLabel('Q', '0', '4', '8'),
CreateQuicVersionLabel(
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48)));
@@ -195,18 +173,12 @@ TEST_F(QuicVersionsTest, CreateQuicVersionLabel) {
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50)));
// Test a TLS version:
- EXPECT_EQ(MakeVersionLabel('T', '0', '3', '9'),
- CreateQuicVersionLabel(
- ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_39)));
EXPECT_EQ(MakeVersionLabel('T', '0', '4', '3'),
CreateQuicVersionLabel(
ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_43)));
EXPECT_EQ(MakeVersionLabel('T', '0', '4', '6'),
CreateQuicVersionLabel(
ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_46)));
- EXPECT_EQ(MakeVersionLabel('T', '0', '4', '7'),
- CreateQuicVersionLabel(
- ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47)));
EXPECT_EQ(MakeVersionLabel('T', '0', '4', '8'),
CreateQuicVersionLabel(
ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_48)));
@@ -245,25 +217,24 @@ TEST_F(QuicVersionsTest, QuicVersionLabelToString) {
}
TEST_F(QuicVersionsTest, QuicVersionToString) {
- EXPECT_EQ("QUIC_VERSION_39", QuicVersionToString(QUIC_VERSION_39));
EXPECT_EQ("QUIC_VERSION_UNSUPPORTED",
QuicVersionToString(QUIC_VERSION_UNSUPPORTED));
- QuicTransportVersion single_version[] = {QUIC_VERSION_39};
+ QuicTransportVersion single_version[] = {QUIC_VERSION_43};
QuicTransportVersionVector versions_vector;
for (size_t i = 0; i < QUIC_ARRAYSIZE(single_version); ++i) {
versions_vector.push_back(single_version[i]);
}
- EXPECT_EQ("QUIC_VERSION_39",
+ EXPECT_EQ("QUIC_VERSION_43",
QuicTransportVersionVectorToString(versions_vector));
QuicTransportVersion multiple_versions[] = {QUIC_VERSION_UNSUPPORTED,
- QUIC_VERSION_39};
+ QUIC_VERSION_43};
versions_vector.clear();
for (size_t i = 0; i < QUIC_ARRAYSIZE(multiple_versions); ++i) {
versions_vector.push_back(multiple_versions[i]);
}
- EXPECT_EQ("QUIC_VERSION_UNSUPPORTED,QUIC_VERSION_39",
+ EXPECT_EQ("QUIC_VERSION_UNSUPPORTED,QUIC_VERSION_43",
QuicTransportVersionVectorToString(versions_vector));
// Make sure that all supported versions are present in QuicVersionToString.
@@ -275,16 +246,16 @@ TEST_F(QuicVersionsTest, QuicVersionToString) {
TEST_F(QuicVersionsTest, ParsedQuicVersionToString) {
ParsedQuicVersion unsupported = UnsupportedQuicVersion();
- ParsedQuicVersion version39(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39);
- EXPECT_EQ("Q039", ParsedQuicVersionToString(version39));
+ ParsedQuicVersion version43(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43);
+ EXPECT_EQ("Q043", ParsedQuicVersionToString(version43));
EXPECT_EQ("0", ParsedQuicVersionToString(unsupported));
- ParsedQuicVersionVector versions_vector = {version39};
- EXPECT_EQ("Q039", ParsedQuicVersionVectorToString(versions_vector));
+ ParsedQuicVersionVector versions_vector = {version43};
+ EXPECT_EQ("Q043", ParsedQuicVersionVectorToString(versions_vector));
- versions_vector = {unsupported, version39};
- EXPECT_EQ("0,Q039", ParsedQuicVersionVectorToString(versions_vector));
- EXPECT_EQ("0:Q039", ParsedQuicVersionVectorToString(versions_vector, ":",
+ versions_vector = {unsupported, version43};
+ EXPECT_EQ("0,Q043", ParsedQuicVersionVectorToString(versions_vector));
+ EXPECT_EQ("0:Q043", ParsedQuicVersionVectorToString(versions_vector, ":",
versions_vector.size()));
EXPECT_EQ("0|...", ParsedQuicVersionVectorToString(versions_vector, "|", 0));
@@ -307,12 +278,8 @@ TEST_F(QuicVersionsTest, AllSupportedTransportVersions) {
TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsAllVersions) {
QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
"Supported versions out of sync");
- SetQuicReloadableFlag(quic_disable_version_39, false);
- SetQuicReloadableFlag(quic_enable_version_47, true);
- SetQuicReloadableFlag(quic_enable_version_48_2, true);
- SetQuicReloadableFlag(quic_enable_version_49, true);
SetQuicReloadableFlag(quic_enable_version_50, true);
SetQuicReloadableFlag(quic_enable_version_99, true);
ParsedQuicVersionVector parsed_versions;
@@ -320,8 +287,8 @@ TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsAllVersions) {
parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
}
QuicTransportVersionVector expected_versions = {
- QUIC_VERSION_99, QUIC_VERSION_50, QUIC_VERSION_49, QUIC_VERSION_48,
- QUIC_VERSION_47, QUIC_VERSION_46, QUIC_VERSION_43, QUIC_VERSION_39};
+ QUIC_VERSION_99, QUIC_VERSION_50, QUIC_VERSION_49,
+ QUIC_VERSION_48, QUIC_VERSION_46, QUIC_VERSION_43};
ParsedQuicVersionVector expected_parsed_versions;
for (QuicTransportVersion version : expected_versions) {
expected_parsed_versions.push_back(
@@ -334,12 +301,8 @@ TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsAllVersions) {
TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo99) {
QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
"Supported versions out of sync");
- SetQuicReloadableFlag(quic_disable_version_39, false);
- SetQuicReloadableFlag(quic_enable_version_47, true);
- SetQuicReloadableFlag(quic_enable_version_48_2, true);
- SetQuicReloadableFlag(quic_enable_version_49, true);
SetQuicReloadableFlag(quic_enable_version_50, true);
SetQuicReloadableFlag(quic_enable_version_99, false);
ParsedQuicVersionVector parsed_versions;
@@ -347,8 +310,8 @@ TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo99) {
parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
}
QuicTransportVersionVector expected_versions = {
- QUIC_VERSION_50, QUIC_VERSION_49, QUIC_VERSION_48, QUIC_VERSION_47,
- QUIC_VERSION_46, QUIC_VERSION_43, QUIC_VERSION_39};
+ QUIC_VERSION_50, QUIC_VERSION_49, QUIC_VERSION_48, QUIC_VERSION_46,
+ QUIC_VERSION_43};
ParsedQuicVersionVector expected_parsed_versions;
for (QuicTransportVersion version : expected_versions) {
expected_parsed_versions.push_back(
@@ -361,64 +324,6 @@ TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo99) {
TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo50) {
QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
- SetQuicReloadableFlag(quic_disable_version_39, false);
- SetQuicReloadableFlag(quic_enable_version_47, true);
- SetQuicReloadableFlag(quic_enable_version_48_2, true);
- SetQuicReloadableFlag(quic_enable_version_49, true);
- SetQuicReloadableFlag(quic_enable_version_50, false);
- SetQuicReloadableFlag(quic_enable_version_99, false);
- ParsedQuicVersionVector parsed_versions;
- for (QuicTransportVersion version : all_versions) {
- parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
- }
- QuicTransportVersionVector expected_versions = {
- QUIC_VERSION_49, QUIC_VERSION_48, QUIC_VERSION_47,
- QUIC_VERSION_46, QUIC_VERSION_43, QUIC_VERSION_39};
- ParsedQuicVersionVector expected_parsed_versions;
- for (QuicTransportVersion version : expected_versions) {
- expected_parsed_versions.push_back(
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
- }
-
- ASSERT_EQ(expected_versions, FilterSupportedTransportVersions(all_versions));
- ASSERT_EQ(expected_parsed_versions, FilterSupportedVersions(parsed_versions));
-}
-
-TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo49) {
- QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
- "Supported versions out of sync");
- SetQuicReloadableFlag(quic_disable_version_39, false);
- SetQuicReloadableFlag(quic_enable_version_47, true);
- SetQuicReloadableFlag(quic_enable_version_48_2, true);
- SetQuicReloadableFlag(quic_enable_version_49, false);
- SetQuicReloadableFlag(quic_enable_version_50, false);
- SetQuicReloadableFlag(quic_enable_version_99, false);
- ParsedQuicVersionVector parsed_versions;
- for (QuicTransportVersion version : all_versions) {
- parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
- }
- QuicTransportVersionVector expected_versions = {
- QUIC_VERSION_48, QUIC_VERSION_47, QUIC_VERSION_46, QUIC_VERSION_43,
- QUIC_VERSION_39};
- ParsedQuicVersionVector expected_parsed_versions;
- for (QuicTransportVersion version : expected_versions) {
- expected_parsed_versions.push_back(
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
- }
-
- ASSERT_EQ(expected_versions, FilterSupportedTransportVersions(all_versions));
- ASSERT_EQ(expected_parsed_versions, FilterSupportedVersions(parsed_versions));
-}
-
-TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo48) {
- QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
- "Supported versions out of sync");
- SetQuicReloadableFlag(quic_disable_version_39, false);
- SetQuicReloadableFlag(quic_enable_version_47, true);
- SetQuicReloadableFlag(quic_enable_version_48_2, false);
- SetQuicReloadableFlag(quic_enable_version_49, false);
SetQuicReloadableFlag(quic_enable_version_50, false);
SetQuicReloadableFlag(quic_enable_version_99, false);
ParsedQuicVersionVector parsed_versions;
@@ -426,7 +331,7 @@ TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo48) {
parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
}
QuicTransportVersionVector expected_versions = {
- QUIC_VERSION_47, QUIC_VERSION_46, QUIC_VERSION_43, QUIC_VERSION_39};
+ QUIC_VERSION_49, QUIC_VERSION_48, QUIC_VERSION_46, QUIC_VERSION_43};
ParsedQuicVersionVector expected_parsed_versions;
for (QuicTransportVersion version : expected_versions) {
expected_parsed_versions.push_back(
@@ -437,14 +342,10 @@ TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo48) {
ASSERT_EQ(expected_parsed_versions, FilterSupportedVersions(parsed_versions));
}
-TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo47) {
+TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNoFlags) {
QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
"Supported versions out of sync");
- SetQuicReloadableFlag(quic_disable_version_39, false);
- SetQuicReloadableFlag(quic_enable_version_47, false);
- SetQuicReloadableFlag(quic_enable_version_48_2, false);
- SetQuicReloadableFlag(quic_enable_version_49, false);
SetQuicReloadableFlag(quic_enable_version_50, false);
SetQuicReloadableFlag(quic_enable_version_99, false);
ParsedQuicVersionVector parsed_versions;
@@ -452,33 +353,7 @@ TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo47) {
parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
}
QuicTransportVersionVector expected_versions = {
- QUIC_VERSION_46, QUIC_VERSION_43, QUIC_VERSION_39};
- ParsedQuicVersionVector expected_parsed_versions;
- for (QuicTransportVersion version : expected_versions) {
- expected_parsed_versions.push_back(
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
- }
-
- ASSERT_EQ(expected_versions, FilterSupportedTransportVersions(all_versions));
- ASSERT_EQ(expected_parsed_versions, FilterSupportedVersions(parsed_versions));
-}
-
-TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo39) {
- QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
- "Supported versions out of sync");
- SetQuicReloadableFlag(quic_disable_version_39, true);
- SetQuicReloadableFlag(quic_enable_version_47, false);
- SetQuicReloadableFlag(quic_enable_version_48_2, false);
- SetQuicReloadableFlag(quic_enable_version_49, false);
- SetQuicReloadableFlag(quic_enable_version_50, false);
- SetQuicReloadableFlag(quic_enable_version_99, false);
- ParsedQuicVersionVector parsed_versions;
- for (QuicTransportVersion version : all_versions) {
- parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
- }
- QuicTransportVersionVector expected_versions = {QUIC_VERSION_46,
- QUIC_VERSION_43};
+ QUIC_VERSION_49, QUIC_VERSION_48, QUIC_VERSION_46, QUIC_VERSION_43};
ParsedQuicVersionVector expected_parsed_versions;
for (QuicTransportVersion version : expected_versions) {
expected_parsed_versions.push_back(
@@ -490,7 +365,7 @@ TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo39) {
}
TEST_F(QuicVersionsTest, LookUpVersionByIndex) {
- QuicTransportVersionVector all_versions = {QUIC_VERSION_39};
+ QuicTransportVersionVector all_versions = {QUIC_VERSION_43};
int version_count = all_versions.size();
for (int i = -5; i <= version_count + 1; ++i) {
if (i >= 0 && i < version_count) {
@@ -528,12 +403,10 @@ TEST_F(QuicVersionsTest, ParsedVersionsToTransportVersions) {
// yet a typo was made in doing the #defines and it was caught
// only in some test far removed from here... Better safe than sorry.
TEST_F(QuicVersionsTest, CheckVersionNumbersForTypos) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
"Supported versions out of sync");
- EXPECT_EQ(QUIC_VERSION_39, 39);
EXPECT_EQ(QUIC_VERSION_43, 43);
EXPECT_EQ(QUIC_VERSION_46, 46);
- EXPECT_EQ(QUIC_VERSION_47, 47);
EXPECT_EQ(QUIC_VERSION_48, 48);
EXPECT_EQ(QUIC_VERSION_49, 49);
EXPECT_EQ(QUIC_VERSION_50, 50);
@@ -541,12 +414,8 @@ TEST_F(QuicVersionsTest, CheckVersionNumbersForTypos) {
}
TEST_F(QuicVersionsTest, AlpnForVersion) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
"Supported versions out of sync");
- ParsedQuicVersion parsed_version_q047 =
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47);
- ParsedQuicVersion parsed_version_t047 =
- ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47);
ParsedQuicVersion parsed_version_q048 =
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48);
ParsedQuicVersion parsed_version_t048 =
@@ -562,33 +431,21 @@ TEST_F(QuicVersionsTest, AlpnForVersion) {
ParsedQuicVersion parsed_version_t099 =
ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99);
- EXPECT_EQ("h3-Q047", AlpnForVersion(parsed_version_q047));
- EXPECT_EQ("h3-T047", AlpnForVersion(parsed_version_t047));
EXPECT_EQ("h3-Q048", AlpnForVersion(parsed_version_q048));
EXPECT_EQ("h3-T048", AlpnForVersion(parsed_version_t048));
EXPECT_EQ("h3-Q049", AlpnForVersion(parsed_version_q049));
EXPECT_EQ("h3-T049", AlpnForVersion(parsed_version_t049));
EXPECT_EQ("h3-Q050", AlpnForVersion(parsed_version_q050));
EXPECT_EQ("h3-T050", AlpnForVersion(parsed_version_t050));
- EXPECT_EQ("h3-23", AlpnForVersion(parsed_version_t099));
+ EXPECT_EQ("h3-24", AlpnForVersion(parsed_version_t099));
+ static_assert(kQuicIetfDraftVersion == 24,
+ "ALPN does not match draft version");
}
TEST_F(QuicVersionsTest, QuicEnableVersion) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
"Supported versions out of sync");
SetQuicReloadableFlag(quic_supports_tls_handshake, true);
- ParsedQuicVersion parsed_version_q047 =
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47);
- ParsedQuicVersion parsed_version_t047 =
- ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47);
- ParsedQuicVersion parsed_version_q048 =
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48);
- ParsedQuicVersion parsed_version_t048 =
- ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_48);
- ParsedQuicVersion parsed_version_q049 =
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_49);
- ParsedQuicVersion parsed_version_t049 =
- ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_49);
ParsedQuicVersion parsed_version_q050 =
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_50);
ParsedQuicVersion parsed_version_t050 =
@@ -596,59 +453,13 @@ TEST_F(QuicVersionsTest, QuicEnableVersion) {
ParsedQuicVersion parsed_version_t099 =
ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99);
SetQuicReloadableFlag(quic_supports_tls_handshake, false);
- SetQuicReloadableFlag(quic_disable_version_39, false);
- SetQuicReloadableFlag(quic_enable_version_47, false);
- SetQuicReloadableFlag(quic_enable_version_48_2, false);
- SetQuicReloadableFlag(quic_enable_version_49, false);
SetQuicReloadableFlag(quic_enable_version_50, false);
SetQuicReloadableFlag(quic_enable_version_99, false);
{
QuicFlagSaver flag_saver;
- QuicEnableVersion(parsed_version_q047);
- EXPECT_FALSE(GetQuicReloadableFlag(quic_supports_tls_handshake));
- EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_47));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_48_2));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_50));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
- }
-
- {
- QuicFlagSaver flag_saver;
- QuicEnableVersion(parsed_version_t047);
- EXPECT_TRUE(GetQuicReloadableFlag(quic_supports_tls_handshake));
- EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_47));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_48_2));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_50));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
- }
-
- {
- QuicFlagSaver flag_saver;
- QuicEnableVersion(parsed_version_q048);
- EXPECT_FALSE(GetQuicReloadableFlag(quic_supports_tls_handshake));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_47));
- EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_48_2));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_50));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
- }
-
- {
- QuicFlagSaver flag_saver;
- QuicEnableVersion(parsed_version_t048);
- EXPECT_TRUE(GetQuicReloadableFlag(quic_supports_tls_handshake));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_47));
- EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_48_2));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_50));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
- }
-
- {
- QuicFlagSaver flag_saver;
QuicEnableVersion(parsed_version_q050);
EXPECT_FALSE(GetQuicReloadableFlag(quic_supports_tls_handshake));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_47));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_48_2));
EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_50));
EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
}
@@ -657,38 +468,14 @@ TEST_F(QuicVersionsTest, QuicEnableVersion) {
QuicFlagSaver flag_saver;
QuicEnableVersion(parsed_version_t050);
EXPECT_TRUE(GetQuicReloadableFlag(quic_supports_tls_handshake));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_47));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_48_2));
EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_50));
EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
}
{
QuicFlagSaver flag_saver;
- QuicEnableVersion(parsed_version_q049);
- EXPECT_FALSE(GetQuicReloadableFlag(quic_supports_tls_handshake));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_47));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_48_2));
- EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_49));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
- }
-
- {
- QuicFlagSaver flag_saver;
- QuicEnableVersion(parsed_version_t049);
- EXPECT_TRUE(GetQuicReloadableFlag(quic_supports_tls_handshake));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_47));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_48_2));
- EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_49));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
- }
-
- {
- QuicFlagSaver flag_saver;
QuicEnableVersion(parsed_version_t099);
EXPECT_TRUE(GetQuicReloadableFlag(quic_supports_tls_handshake));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_47));
- EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_48_2));
EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_50));
EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_99));
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.h b/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.h
index 7cab768a56d..b80eca6e963 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.h
@@ -247,9 +247,9 @@ class QUIC_EXPORT_PRIVATE QuicWriteBlockedList {
// A StaticStreamCollection is a vector of <QuicStreamId, bool> pairs plus a
// eagerly-computed number of blocked static streams.
- class StaticStreamCollection {
+ class QUIC_EXPORT_PRIVATE StaticStreamCollection {
public:
- struct StreamIdBlockedPair {
+ struct QUIC_EXPORT_PRIVATE StreamIdBlockedPair {
QuicStreamId id;
bool is_blocked;
};
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 674cf2cdeb3..a65fefc308f 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
@@ -43,22 +43,21 @@ void TlsClientHandshaker::ProofVerifierCallbackImpl::Cancel() {
}
TlsClientHandshaker::TlsClientHandshaker(
+ const QuicServerId& server_id,
QuicCryptoStream* stream,
QuicSession* session,
- const QuicServerId& server_id,
- ProofVerifier* proof_verifier,
- SSL_CTX* ssl_ctx,
std::unique_ptr<ProofVerifyContext> verify_context,
- QuicCryptoClientStream::ProofHandler* proof_handler,
- const std::string& user_agent_id)
- : TlsHandshaker(stream, session, ssl_ctx),
+ QuicCryptoClientConfig* crypto_config,
+ QuicCryptoClientStream::ProofHandler* proof_handler)
+ : TlsHandshaker(stream, session, crypto_config->ssl_ctx()),
server_id_(server_id),
- proof_verifier_(proof_verifier),
+ proof_verifier_(crypto_config->proof_verifier()),
verify_context_(std::move(verify_context)),
proof_handler_(proof_handler),
- user_agent_id_(user_agent_id),
+ session_cache_(crypto_config->session_cache()),
+ user_agent_id_(crypto_config->user_agent_id()),
crypto_negotiated_params_(new QuicCryptoNegotiatedParameters),
- tls_connection_(ssl_ctx, this) {}
+ tls_connection_(crypto_config->ssl_ctx(), this) {}
TlsClientHandshaker::~TlsClientHandshaker() {
if (proof_verify_callback_) {
@@ -66,11 +65,6 @@ TlsClientHandshaker::~TlsClientHandshaker() {
}
}
-// static
-bssl::UniquePtr<SSL_CTX> TlsClientHandshaker::CreateSslCtx() {
- return TlsClientConnection::CreateSslCtx();
-}
-
bool TlsClientHandshaker::CryptoConnect() {
state_ = STATE_HANDSHAKE_RUNNING;
@@ -92,6 +86,15 @@ bool TlsClientHandshaker::CryptoConnect() {
return false;
}
+ // Set a session to resume, if there is one.
+ if (session_cache_) {
+ std::unique_ptr<QuicResumptionState> cached_state =
+ session_cache_->Lookup(server_id_, SSL_get_SSL_CTX(ssl()));
+ if (cached_state) {
+ SSL_set_session(ssl(), cached_state->tls_session.get());
+ }
+ }
+
// Start the handshake.
AdvanceHandshake();
return session()->connection()->connected();
@@ -202,6 +205,11 @@ int TlsClientHandshaker::num_sent_client_hellos() const {
return 0;
}
+bool TlsClientHandshaker::IsResumption() const {
+ QUIC_BUG_IF(!handshake_confirmed_);
+ return SSL_session_reused(ssl()) == 1;
+}
+
int TlsClientHandshaker::num_scup_messages_received() const {
// SCUP messages aren't sent or received when using the TLS handshake.
return 0;
@@ -245,7 +253,10 @@ void TlsClientHandshaker::AdvanceHandshake() {
return;
}
if (state_ == STATE_HANDSHAKE_COMPLETE) {
- // TODO(nharper): Handle post-handshake messages.
+ int rv = SSL_process_quic_post_handshake(ssl());
+ if (rv != 1) {
+ CloseConnection(QUIC_HANDSHAKE_FAILED, "Unexpected post-handshake data");
+ }
return;
}
@@ -322,12 +333,9 @@ void TlsClientHandshaker::FinishHandshake() {
QUIC_DLOG(INFO) << "Client: server selected ALPN: '" << received_alpn_string
<< "'";
- session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
- session()->NeuterUnencryptedData();
encryption_established_ = true;
handshake_confirmed_ = true;
- session()->OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_ESTABLISHED);
- session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
+ delegate()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
// Fill crypto_negotiated_params_:
const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
@@ -337,8 +345,9 @@ void TlsClientHandshaker::FinishHandshake() {
crypto_negotiated_params_->key_exchange_group = SSL_get_curve_id(ssl());
crypto_negotiated_params_->peer_signature_algorithm =
SSL_get_peer_signature_algorithm(ssl());
-
- session()->connection()->OnHandshakeComplete();
+ // TODO(fayang): Replace this with DiscardOldKeys(ENCRYPTION_HANDSHAKE) when
+ // handshake key discarding settles down.
+ delegate()->NeuterHandshakeData();
}
enum ssl_verify_result_t TlsClientHandshaker::VerifyCert(uint8_t* out_alert) {
@@ -394,4 +403,25 @@ enum ssl_verify_result_t TlsClientHandshaker::VerifyCert(uint8_t* out_alert) {
}
}
+void TlsClientHandshaker::InsertSession(bssl::UniquePtr<SSL_SESSION> session) {
+ if (session_cache_ == nullptr) {
+ QUIC_DVLOG(1) << "No session cache, not inserting a session";
+ return;
+ }
+ auto cache_state = std::make_unique<QuicResumptionState>();
+ cache_state->tls_session = std::move(session);
+ session_cache_->Insert(server_id_, std::move(cache_state));
+}
+
+void TlsClientHandshaker::WriteMessage(EncryptionLevel level,
+ QuicStringPiece data) {
+ if (level == ENCRYPTION_HANDSHAKE &&
+ state_ < STATE_ENCRYPTION_HANDSHAKE_DATA_SENT) {
+ state_ = STATE_ENCRYPTION_HANDSHAKE_DATA_SENT;
+ delegate()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
+ delegate()->DiscardOldDecryptionKey(ENCRYPTION_INITIAL);
+ }
+ TlsHandshaker::WriteMessage(level, data);
+}
+
} // namespace quic
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 4672821f72b..319cd1704bc 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
@@ -24,26 +24,21 @@ class QUIC_EXPORT_PRIVATE TlsClientHandshaker
public QuicCryptoClientStream::HandshakerDelegate,
public TlsClientConnection::Delegate {
public:
- TlsClientHandshaker(QuicCryptoStream* stream,
+ TlsClientHandshaker(const QuicServerId& server_id,
+ QuicCryptoStream* stream,
QuicSession* session,
- const QuicServerId& server_id,
- ProofVerifier* proof_verifier,
- SSL_CTX* ssl_ctx,
std::unique_ptr<ProofVerifyContext> verify_context,
- QuicCryptoClientStream::ProofHandler* proof_handler,
- const std::string& user_agent_id);
+ QuicCryptoClientConfig* crypto_config,
+ QuicCryptoClientStream::ProofHandler* proof_handler);
TlsClientHandshaker(const TlsClientHandshaker&) = delete;
TlsClientHandshaker& operator=(const TlsClientHandshaker&) = delete;
~TlsClientHandshaker() override;
- // Creates and configures an SSL_CTX to be used with a TlsClientHandshaker.
- // The caller is responsible for ownership of the newly created struct.
- static bssl::UniquePtr<SSL_CTX> CreateSslCtx();
-
// From QuicCryptoClientStream::HandshakerDelegate
bool CryptoConnect() override;
int num_sent_client_hellos() const override;
+ bool IsResumption() const override;
int num_scup_messages_received() const override;
std::string chlo_hash() const override;
@@ -55,6 +50,9 @@ class QUIC_EXPORT_PRIVATE TlsClientHandshaker
CryptoMessageParser* crypto_message_parser() override;
size_t BufferSizeLimitForLevel(EncryptionLevel level) const override;
+ // Override to drop initial keys if trying to write ENCRYPTION_HANDSHAKE data.
+ void WriteMessage(EncryptionLevel level, QuicStringPiece data) override;
+
void AllowEmptyAlpnForTests() { allow_empty_alpn_for_tests_ = true; }
protected:
@@ -73,7 +71,8 @@ class QUIC_EXPORT_PRIVATE TlsClientHandshaker
private:
// ProofVerifierCallbackImpl handles the result of an asynchronous certificate
// verification operation.
- class ProofVerifierCallbackImpl : public ProofVerifierCallback {
+ class QUIC_EXPORT_PRIVATE ProofVerifierCallbackImpl
+ : public ProofVerifierCallback {
public:
explicit ProofVerifierCallbackImpl(TlsClientHandshaker* parent);
~ProofVerifierCallbackImpl() override;
@@ -94,6 +93,7 @@ class QUIC_EXPORT_PRIVATE TlsClientHandshaker
STATE_IDLE,
STATE_HANDSHAKE_RUNNING,
STATE_CERT_VERIFY_PENDING,
+ STATE_ENCRYPTION_HANDSHAKE_DATA_SENT,
STATE_HANDSHAKE_COMPLETE,
STATE_CONNECTION_CLOSED,
} state_ = STATE_IDLE;
@@ -103,6 +103,8 @@ class QUIC_EXPORT_PRIVATE TlsClientHandshaker
bool ProcessTransportParameters(std::string* error_details);
void FinishHandshake();
+ void InsertSession(bssl::UniquePtr<SSL_SESSION> session) override;
+
QuicServerId server_id_;
// Objects used for verifying the server's certificate chain.
@@ -115,6 +117,10 @@ class QUIC_EXPORT_PRIVATE TlsClientHandshaker
// certificate verification.
QuicCryptoClientStream::ProofHandler* proof_handler_;
+ // Used for session resumption. |session_cache_| is owned by the
+ // QuicCryptoClientConfig passed into TlsClientHandshaker's constructor.
+ SessionCache* session_cache_;
+
std::string user_agent_id_;
// ProofVerifierCallback used for async certificate verification. This object
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 f2089cd102e..08b4eb9525c 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
@@ -16,7 +16,7 @@ namespace quic {
TlsHandshaker::TlsHandshaker(QuicCryptoStream* stream,
QuicSession* session,
SSL_CTX* /*ssl_ctx*/)
- : stream_(stream), session_(session) {
+ : stream_(stream), session_(session), delegate_(session) {
QUIC_BUG_IF(!GetQuicReloadableFlag(quic_supports_tls_handshake))
<< "Attempted to create TLS handshaker when TLS is disabled";
}
@@ -64,32 +64,22 @@ const EVP_MD* TlsHandshaker::Prf() {
SSL_CIPHER_get_prf_nid(SSL_get_pending_cipher(ssl())));
}
-std::unique_ptr<QuicEncrypter> TlsHandshaker::CreateEncrypter(
- const std::vector<uint8_t>& pp_secret) {
+void TlsHandshaker::SetEncryptionSecret(
+ EncryptionLevel level,
+ const std::vector<uint8_t>& read_secret,
+ const std::vector<uint8_t>& write_secret) {
std::unique_ptr<QuicEncrypter> encrypter =
QuicEncrypter::CreateFromCipherSuite(
SSL_CIPHER_get_id(SSL_get_pending_cipher(ssl())));
- CryptoUtils::SetKeyAndIV(Prf(), pp_secret, encrypter.get());
- return encrypter;
-}
-
-std::unique_ptr<QuicDecrypter> TlsHandshaker::CreateDecrypter(
- const std::vector<uint8_t>& pp_secret) {
+ CryptoUtils::SetKeyAndIV(Prf(), write_secret, encrypter.get());
std::unique_ptr<QuicDecrypter> decrypter =
QuicDecrypter::CreateFromCipherSuite(
SSL_CIPHER_get_id(SSL_get_pending_cipher(ssl())));
- CryptoUtils::SetKeyAndIV(Prf(), pp_secret, decrypter.get());
- return decrypter;
-}
-
-void TlsHandshaker::SetEncryptionSecret(
- EncryptionLevel level,
- const std::vector<uint8_t>& read_secret,
- const std::vector<uint8_t>& write_secret) {
- std::unique_ptr<QuicEncrypter> encrypter = CreateEncrypter(write_secret);
- session()->connection()->SetEncrypter(level, std::move(encrypter));
- std::unique_ptr<QuicDecrypter> decrypter = CreateDecrypter(read_secret);
- session()->connection()->InstallDecrypter(level, std::move(decrypter));
+ CryptoUtils::SetKeyAndIV(Prf(), read_secret, decrypter.get());
+ delegate_->OnNewKeysAvailable(level, std::move(decrypter),
+ /*set_alternative_decrypter=*/false,
+ /*latch_once_used=*/false,
+ std::move(encrypter));
}
void TlsHandshaker::WriteMessage(EncryptionLevel level, QuicStringPiece data) {
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 7d5b9bcb75f..14503cde549 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
@@ -61,17 +61,13 @@ class QUIC_EXPORT_PRIVATE TlsHandshaker : public TlsConnection::Delegate,
// Returns the PRF used by the cipher suite negotiated in the TLS handshake.
const EVP_MD* Prf();
- std::unique_ptr<QuicEncrypter> CreateEncrypter(
- const std::vector<uint8_t>& pp_secret);
- std::unique_ptr<QuicDecrypter> CreateDecrypter(
- const std::vector<uint8_t>& pp_secret);
-
virtual const TlsConnection* tls_connection() const = 0;
SSL* ssl() const { return tls_connection()->ssl(); }
QuicCryptoStream* stream() { return stream_; }
QuicSession* session() { return session_; }
+ HandshakerDelegateInterface* delegate() { return delegate_; }
// SetEncryptionSecret provides the encryption secret to use at a particular
// encryption level. The secrets provided here are the ones from the TLS 1.3
@@ -100,6 +96,7 @@ class QUIC_EXPORT_PRIVATE TlsHandshaker : public TlsConnection::Delegate,
private:
QuicCryptoStream* stream_;
QuicSession* session_;
+ HandshakerDelegateInterface* delegate_;
QuicErrorCode parser_error_ = QUIC_NO_ERROR;
std::string parser_error_detail_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_handshaker_test.cc b/chromium/net/third_party/quiche/src/quic/core/tls_handshaker_test.cc
index c23d56b44eb..a86b5217bfb 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_handshaker_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_handshaker_test.cc
@@ -177,6 +177,8 @@ class TestQuicCryptoStream : public QuicCryptoStream {
pending_writes_.push_back(std::make_pair(std::string(data), level));
}
+ void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
+
const std::vector<std::pair<std::string, EncryptionLevel>>& pending_writes() {
return pending_writes_;
}
@@ -223,17 +225,15 @@ class TestQuicCryptoClientStream : public TestQuicCryptoStream {
public:
explicit TestQuicCryptoClientStream(QuicSession* session)
: TestQuicCryptoStream(session),
- proof_verifier_(new FakeProofVerifier),
- ssl_ctx_(TlsClientConnection::CreateSslCtx()),
+ crypto_config_(std::make_unique<FakeProofVerifier>(),
+ /*session_cache*/ nullptr),
handshaker_(new TlsClientHandshaker(
+ QuicServerId("test.example.com", 443, false),
this,
session,
- QuicServerId("test.example.com", 443, false),
- proof_verifier_.get(),
- ssl_ctx_.get(),
crypto_test_utils::ProofVerifyContextForTesting(),
- &proof_handler_,
- "quic-tester")) {}
+ &crypto_config_,
+ &proof_handler_)) {}
~TestQuicCryptoClientStream() override = default;
@@ -244,13 +244,12 @@ class TestQuicCryptoClientStream : public TestQuicCryptoStream {
bool CryptoConnect() { return handshaker_->CryptoConnect(); }
FakeProofVerifier* GetFakeProofVerifier() const {
- return proof_verifier_.get();
+ return static_cast<FakeProofVerifier*>(crypto_config_.proof_verifier());
}
private:
- std::unique_ptr<FakeProofVerifier> proof_verifier_;
MockProofHandler proof_handler_;
- bssl::UniquePtr<SSL_CTX> ssl_ctx_;
+ QuicCryptoClientConfig crypto_config_;
std::unique_ptr<TlsClientHandshaker> handshaker_;
};
@@ -272,6 +271,10 @@ class TestQuicCryptoServerStream : public TestQuicCryptoStream {
handshaker_->CancelOutstandingCallbacks();
}
+ void OnPacketDecrypted(EncryptionLevel level) override {
+ handshaker_->OnPacketDecrypted(level);
+ }
+
TlsHandshaker* handshaker() const override { return handshaker_.get(); }
FakeProofSource* GetFakeProofSource() const { return proof_source_; }
@@ -334,8 +337,8 @@ class TlsHandshakerTest : public QuicTest {
EXPECT_TRUE(client_stream_->encryption_established());
EXPECT_TRUE(server_stream_->handshake_confirmed());
EXPECT_TRUE(server_stream_->encryption_established());
- EXPECT_TRUE(client_conn_->IsHandshakeConfirmed());
- EXPECT_TRUE(server_conn_->IsHandshakeConfirmed());
+ EXPECT_TRUE(client_conn_->IsHandshakeComplete());
+ EXPECT_TRUE(server_conn_->IsHandshakeComplete());
const auto& client_crypto_params =
client_stream_->crypto_negotiated_params();
@@ -370,17 +373,11 @@ class TlsHandshakerTest : public QuicTest {
};
TEST_F(TlsHandshakerTest, CryptoHandshake) {
- EXPECT_FALSE(client_conn_->IsHandshakeConfirmed());
- EXPECT_FALSE(server_conn_->IsHandshakeConfirmed());
+ EXPECT_FALSE(client_conn_->IsHandshakeComplete());
+ EXPECT_FALSE(server_conn_->IsHandshakeComplete());
EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
- EXPECT_CALL(client_session_,
- OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_ESTABLISHED));
- EXPECT_CALL(client_session_,
- OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED));
- EXPECT_CALL(server_session_,
- OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED));
EXPECT_CALL(client_stream_->proof_handler(), OnProofVerifyDetailsAvailable);
client_stream_->CryptoConnect();
ExchangeHandshakeMessages(client_stream_, server_stream_);
@@ -505,7 +502,7 @@ TEST_F(TlsHandshakerTest, ClientNotSendingALPN) {
}
TEST_F(TlsHandshakerTest, ClientSendingBadALPN) {
- static std::string kTestBadClientAlpn = "bad-client-alpn";
+ const std::string kTestBadClientAlpn = "bad-client-alpn";
EXPECT_CALL(client_session_, GetAlpnsToOffer())
.WillOnce(Return(std::vector<std::string>({kTestBadClientAlpn})));
EXPECT_CALL(*client_conn_, CloseConnection(QUIC_HANDSHAKE_FAILED,
@@ -539,9 +536,9 @@ TEST_F(TlsHandshakerTest, ClientSendingTooManyALPNs) {
}
TEST_F(TlsHandshakerTest, ServerRequiresCustomALPN) {
- static const std::string kTestAlpn = "An ALPN That Client Did Not Offer";
+ const std::string kTestAlpn = "An ALPN That Client Did Not Offer";
EXPECT_CALL(server_session_, SelectAlpn(_))
- .WillOnce([](const std::vector<QuicStringPiece>& alpns) {
+ .WillOnce([kTestAlpn](const std::vector<QuicStringPiece>& alpns) {
return std::find(alpns.cbegin(), alpns.cend(), kTestAlpn);
});
EXPECT_CALL(*client_conn_, CloseConnection(QUIC_HANDSHAKE_FAILED,
@@ -561,23 +558,18 @@ TEST_F(TlsHandshakerTest, ServerRequiresCustomALPN) {
TEST_F(TlsHandshakerTest, CustomALPNNegotiation) {
EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
- EXPECT_CALL(client_session_,
- OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_ESTABLISHED));
- EXPECT_CALL(client_session_,
- OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED));
- EXPECT_CALL(server_session_,
- OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED));
-
- static const std::string kTestAlpn = "A Custom ALPN Value";
- static const std::vector<std::string> kTestAlpns(
+
+ const std::string kTestAlpn = "A Custom ALPN Value";
+ const std::vector<std::string> kTestAlpns(
{"foo", "bar", kTestAlpn, "something else"});
EXPECT_CALL(client_session_, GetAlpnsToOffer())
.WillRepeatedly(Return(kTestAlpns));
EXPECT_CALL(server_session_, SelectAlpn(_))
- .WillOnce([](const std::vector<QuicStringPiece>& alpns) {
- EXPECT_THAT(alpns, ElementsAreArray(kTestAlpns));
- return std::find(alpns.cbegin(), alpns.cend(), kTestAlpn);
- });
+ .WillOnce(
+ [kTestAlpn, kTestAlpns](const std::vector<QuicStringPiece>& alpns) {
+ EXPECT_THAT(alpns, ElementsAreArray(kTestAlpns));
+ return std::find(alpns.cbegin(), alpns.cend(), kTestAlpn);
+ });
EXPECT_CALL(client_session_, OnAlpnSelected(QuicStringPiece(kTestAlpn)));
EXPECT_CALL(server_session_, OnAlpnSelected(QuicStringPiece(kTestAlpn)));
client_stream_->CryptoConnect();
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 f08f7817466..24af98daf00 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
@@ -39,11 +39,6 @@ void TlsServerHandshaker::SignatureCallback::Cancel() {
handshaker_ = nullptr;
}
-// static
-bssl::UniquePtr<SSL_CTX> TlsServerHandshaker::CreateSslCtx() {
- return TlsServerConnection::CreateSslCtx();
-}
-
TlsServerHandshaker::TlsServerHandshaker(QuicCryptoStream* stream,
QuicSession* session,
SSL_CTX* ssl_ctx,
@@ -114,6 +109,15 @@ bool TlsServerHandshaker::ZeroRttAttempted() const {
void TlsServerHandshaker::SetPreviousCachedNetworkParams(
CachedNetworkParameters /*cached_network_params*/) {}
+void TlsServerHandshaker::OnPacketDecrypted(EncryptionLevel level) {
+ if (level == ENCRYPTION_HANDSHAKE &&
+ state_ < STATE_ENCRYPTION_HANDSHAKE_DATA_PROCESSED) {
+ state_ = STATE_ENCRYPTION_HANDSHAKE_DATA_PROCESSED;
+ delegate()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
+ delegate()->DiscardOldDecryptionKey(ENCRYPTION_INITIAL);
+ }
+}
+
bool TlsServerHandshaker::ShouldSendExpectCTHeader() const {
return false;
}
@@ -257,11 +261,9 @@ void TlsServerHandshaker::FinishHandshake() {
QUIC_LOG(INFO) << "Server: handshake finished";
state_ = STATE_HANDSHAKE_COMPLETE;
- session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
- session()->NeuterUnencryptedData();
encryption_established_ = true;
handshake_confirmed_ = true;
- session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
+ delegate()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
// Fill crypto_negotiated_params_:
const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
@@ -269,8 +271,9 @@ void TlsServerHandshaker::FinishHandshake() {
crypto_negotiated_params_->cipher_suite = SSL_CIPHER_get_value(cipher);
}
crypto_negotiated_params_->key_exchange_group = SSL_get_curve_id(ssl());
-
- session()->connection()->OnHandshakeComplete();
+ // TODO(fayang): Replace this with DiscardOldKeys(ENCRYPTION_HANDSHAKE) when
+ // handshake key discarding settles down.
+ delegate()->NeuterHandshakeData();
}
ssl_private_key_result_t TlsServerHandshaker::PrivateKeySign(
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 829aeaf618b..507324b9ccd 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
@@ -34,10 +34,6 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
~TlsServerHandshaker() override;
- // Creates and configures an SSL_CTX to be used with a TlsServerHandshaker.
- // The caller is responsible for ownership of the newly created struct.
- static bssl::UniquePtr<SSL_CTX> CreateSslCtx();
-
// From QuicCryptoServerStream::HandshakerDelegate
void CancelOutstandingCallbacks() override;
bool GetBase64SHA256ClientChannelID(std::string* output) const override;
@@ -50,6 +46,7 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
bool ZeroRttAttempted() const override;
void SetPreviousCachedNetworkParams(
CachedNetworkParameters cached_network_params) override;
+ void OnPacketDecrypted(EncryptionLevel level) override;
bool ShouldSendExpectCTHeader() const override;
// From QuicCryptoServerStream::HandshakerDelegate and TlsHandshaker
@@ -88,7 +85,8 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
TlsConnection::Delegate* ConnectionDelegate() override { return this; }
private:
- class SignatureCallback : public ProofSource::SignatureCallback {
+ class QUIC_EXPORT_PRIVATE SignatureCallback
+ : public ProofSource::SignatureCallback {
public:
explicit SignatureCallback(TlsServerHandshaker* handshaker);
void Run(bool ok, std::string signature) override;
@@ -104,6 +102,7 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
STATE_LISTENING,
STATE_SIGNATURE_PENDING,
STATE_SIGNATURE_COMPLETE,
+ STATE_ENCRYPTION_HANDSHAKE_DATA_PROCESSED,
STATE_HANDSHAKE_COMPLETE,
STATE_CONNECTION_CLOSED,
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.cc b/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.cc
index f258384a46a..3fb5be8379b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.cc
@@ -135,6 +135,14 @@ void UberQuicStreamIdManager::SetLargestPeerCreatedStreamId(
largest_peer_created_stream_id);
}
+QuicStreamId UberQuicStreamIdManager::GetLargestPeerCreatedStreamId(
+ bool unidirectional) const {
+ if (unidirectional) {
+ return unidirectional_stream_id_manager_.largest_peer_created_stream_id();
+ }
+ return bidirectional_stream_id_manager_.largest_peer_created_stream_id();
+}
+
QuicStreamId UberQuicStreamIdManager::next_outgoing_bidirectional_stream_id()
const {
return bidirectional_stream_id_manager_.next_outgoing_stream_id();
diff --git a/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.h b/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.h
index a725fdd1285..75fcb9d7d3c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.h
@@ -73,6 +73,8 @@ class QUIC_EXPORT_PRIVATE UberQuicStreamIdManager {
void SetLargestPeerCreatedStreamId(
QuicStreamId largest_peer_created_stream_id);
+ QuicStreamId GetLargestPeerCreatedStreamId(bool unidirectional) const;
+
QuicStreamId next_outgoing_bidirectional_stream_id() const;
QuicStreamId next_outgoing_unidirectional_stream_id() const;
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_cert_utils.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_cert_utils.h
index 1c660b5a92c..8e21fcb65db 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_cert_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_cert_utils.h
@@ -5,12 +5,13 @@
#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_CERT_UTILS_H_
#define QUICHE_QUIC_PLATFORM_API_QUIC_CERT_UTILS_H_
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/quic/platform/impl/quic_cert_utils_impl.h"
namespace quic {
-class QuicCertUtils {
+class QUIC_EXPORT_PRIVATE QuicCertUtils {
public:
static bool ExtractSubjectNameFromDERCert(QuicStringPiece cert,
QuicStringPiece* subject_out) {
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_endian.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_endian.h
deleted file mode 100644
index 65edd51690f..00000000000
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_endian.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_QUIC_PLATFORM_API_QUIC_ENDIAN_H_
-#define QUICHE_QUIC_PLATFORM_API_QUIC_ENDIAN_H_
-
-#include "net/quic/platform/impl/quic_endian_impl.h"
-
-namespace quic {
-
-enum Endianness {
- NETWORK_BYTE_ORDER, // big endian
- HOST_BYTE_ORDER // little endian
-};
-
-// 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).
-class QuicEndian {
- public:
- // Convert |x| from host order (can be either little or big endian depending
- // on the platform) to network order (big endian).
- static uint16_t HostToNet16(uint16_t x) {
- return QuicEndianImpl::HostToNet16(x);
- }
- static uint32_t HostToNet32(uint32_t x) {
- return QuicEndianImpl::HostToNet32(x);
- }
- static uint64_t HostToNet64(uint64_t x) {
- return QuicEndianImpl::HostToNet64(x);
- }
-
- // Convert |x| from network order (big endian) to host order (can be either
- // little or big endian depending on the platform).
- static uint16_t NetToHost16(uint16_t x) {
- return QuicEndianImpl::NetToHost16(x);
- }
- static uint32_t NetToHost32(uint32_t x) {
- return QuicEndianImpl::NetToHost32(x);
- }
- static uint64_t NetToHost64(uint64_t x) {
- return QuicEndianImpl::NetToHost64(x);
- }
-
- // Returns true if current host order is little endian.
- static bool HostIsLittleEndian() {
- return QuicEndianImpl::HostIsLittleEndian();
- }
-};
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_PLATFORM_API_QUIC_ENDIAN_H_
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_endian_test.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_endian_test.cc
deleted file mode 100644
index d054d963021..00000000000
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_endian_test.cc
+++ /dev/null
@@ -1,51 +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 "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
-
-#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-
-namespace quic {
-namespace test {
-namespace {
-
-const uint16_t k16BitTestData = 0xaabb;
-const uint16_t k16BitSwappedTestData = 0xbbaa;
-const uint32_t k32BitTestData = 0xaabbccdd;
-const uint32_t k32BitSwappedTestData = 0xddccbbaa;
-const uint64_t k64BitTestData = 0xaabbccdd44332211;
-const uint64_t k64BitSwappedTestData = 0x11223344ddccbbaa;
-
-class QuicEndianTest : public QuicTest {};
-
-TEST_F(QuicEndianTest, HostToNet) {
- if (QuicEndian::HostIsLittleEndian()) {
- EXPECT_EQ(k16BitSwappedTestData, QuicEndian::HostToNet16(k16BitTestData));
- EXPECT_EQ(k32BitSwappedTestData, QuicEndian::HostToNet32(k32BitTestData));
- EXPECT_EQ(k64BitSwappedTestData, QuicEndian::HostToNet64(k64BitTestData));
- } else {
- EXPECT_EQ(k16BitTestData, QuicEndian::HostToNet16(k16BitTestData));
- EXPECT_EQ(k32BitTestData, QuicEndian::HostToNet32(k32BitTestData));
- EXPECT_EQ(k64BitTestData, QuicEndian::HostToNet64(k64BitTestData));
- }
-}
-
-TEST_F(QuicEndianTest, NetToHost) {
- if (QuicEndian::HostIsLittleEndian()) {
- EXPECT_EQ(k16BitTestData, QuicEndian::NetToHost16(k16BitSwappedTestData));
- EXPECT_EQ(k32BitTestData, QuicEndian::NetToHost32(k32BitSwappedTestData));
- EXPECT_EQ(k64BitTestData, QuicEndian::NetToHost64(k64BitSwappedTestData));
- } else {
- EXPECT_EQ(k16BitSwappedTestData,
- QuicEndian::NetToHost16(k16BitSwappedTestData));
- EXPECT_EQ(k32BitSwappedTestData,
- QuicEndian::NetToHost32(k32BitSwappedTestData));
- EXPECT_EQ(k64BitSwappedTestData,
- QuicEndian::NetToHost64(k64BitSwappedTestData));
- }
-}
-
-} // namespace
-} // namespace test
-} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_export.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_export.h
index 8ffd6765259..90696a6fba6 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_export.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_export.h
@@ -7,4 +7,11 @@
#include "net/quic/platform/impl/quic_export_impl.h"
+// quic_export_impl.h defines the following macros:
+// - QUIC_EXPORT is not meant to be used.
+// - QUIC_EXPORT_PRIVATE is meant for QUIC functionality that is built in
+// Chromium as part of //net, and not fully contained in headers.
+// - QUIC_NO_EXPORT is meant for QUIC functionality that is either fully defined
+// in a header, or is built in Chromium as part of tests or tools.
+
#endif // QUICHE_QUIC_PLATFORM_API_QUIC_EXPORT_H_
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
index d0ed4606cbb..71045e1c30e 100644
--- 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
@@ -12,11 +12,6 @@
namespace quic {
-template <typename T, typename... Args>
-std::unique_ptr<T> QuicMakeUnique(Args&&... args) {
- return QuicMakeUniqueImpl<T>(std::forward<Args>(args)...);
-}
-
template <typename T>
std::unique_ptr<T> QuicWrapUnique(T* ptr) {
return QuicWrapUniqueImpl<T>(ptr);
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h
index 6ffc237db36..18f6f37f5ab 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h
@@ -51,7 +51,7 @@ class QUIC_EXPORT_PRIVATE QuicReferenceCounted
// QuicReferenceCountedPointer<T> r_ptr_b = std::move(r_ptr_a);
template <class T>
-class QuicReferenceCountedPointer {
+class QUIC_NO_EXPORT QuicReferenceCountedPointer {
public:
QuicReferenceCountedPointer() = default;
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_test.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_test.h
index 2f3286541a9..f4ef99a3624 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_test.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_test.h
@@ -23,6 +23,11 @@ using ScopedEnvironmentForThreads = ScopedEnvironmentForThreadsImpl;
inline std::string QuicGetTestMemoryCachePath() {
return QuicGetTestMemoryCachePathImpl();
+
+#define EXPECT_QUIC_DEBUG_DEATH(condition, message) \
+ EXPECT_QUIC_DEBUG_DEATH_IMPL(condition, message)
}
+#define QUIC_SLOW_TEST(test) QUIC_SLOW_TEST_IMPL(test)
+
#endif // QUICHE_QUIC_PLATFORM_API_QUIC_TEST_H_
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_test_mem_slice_vector.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_test_mem_slice_vector.h
index 06be8f7a501..734db63684b 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_test_mem_slice_vector.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_test_mem_slice_vector.h
@@ -18,7 +18,7 @@ namespace test {
// Tests using QuicTestMemSliceVector need to make sure the actual data buffers
// outlive QuicTestMemSliceVector, and QuicTestMemSliceVector outlive the
// returned QuicMemSliceSpan.
-class QuicTestMemSliceVector {
+class QUIC_NO_EXPORT QuicTestMemSliceVector {
public:
explicit QuicTestMemSliceVector(std::vector<std::pair<char*, size_t>> buffers)
: impl_(std::move(buffers)) {}
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_text_utils.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_text_utils.h
index 1fa3c72ab16..186368f4f37 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_text_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_text_utils.h
@@ -7,13 +7,14 @@
#include <string>
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/quic/platform/impl/quic_text_utils_impl.h"
namespace quic {
// Various utilities for manipulating text.
-class QuicTextUtils {
+class QUIC_EXPORT_PRIVATE QuicTextUtils {
public:
// Returns true if |data| starts with |prefix|, case sensitively.
static bool StartsWith(QuicStringPiece data, QuicStringPiece prefix) {
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_thread.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_thread.h
index 7032dc425af..4b1e5642c58 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_thread.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_thread.h
@@ -7,12 +7,13 @@
#include <string>
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/quic/platform/impl/quic_thread_impl.h"
namespace quic {
// A class representing a thread of execution in QUIC.
-class QuicThread : public QuicThreadImpl {
+class QUIC_EXPORT_PRIVATE QuicThread : public QuicThreadImpl {
public:
QuicThread(const std::string& string) : QuicThreadImpl(string) {}
QuicThread(const QuicThread&) = delete;
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable.cc b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable.cc
index 7779a8b212f..a6913d10fd6 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable.cc
@@ -7,11 +7,11 @@
#include <netinet/ip6.h>
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mutex.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/qbone/platform/icmp_packet.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
namespace {
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable_test.cc
index 303f0e280b7..99de19ca9ad 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/icmp_reachable_test.cc
@@ -118,7 +118,7 @@ class IcmpReachableTest : public QuicTest {
};
TEST_F(IcmpReachableTest, SendsPings) {
- IcmpReachable reachable(source_, destination_, absl::Seconds(0), &kernel_,
+ IcmpReachable reachable(source_, destination_, absl::ZeroDuration(), &kernel_,
&epoll_server_, &stats_);
SetFdExpectations();
@@ -140,7 +140,7 @@ TEST_F(IcmpReachableTest, SendsPings) {
}
TEST_F(IcmpReachableTest, HandlesUnreachableEvents) {
- IcmpReachable reachable(source_, destination_, absl::Seconds(0), &kernel_,
+ IcmpReachable reachable(source_, destination_, absl::ZeroDuration(), &kernel_,
&epoll_server_, &stats_);
SetFdExpectations();
@@ -164,7 +164,7 @@ TEST_F(IcmpReachableTest, HandlesUnreachableEvents) {
}
TEST_F(IcmpReachableTest, HandlesReachableEvents) {
- IcmpReachable reachable(source_, destination_, absl::Seconds(0), &kernel_,
+ IcmpReachable reachable(source_, destination_, absl::ZeroDuration(), &kernel_,
&epoll_server_, &stats_);
SetFdExpectations();
@@ -212,7 +212,7 @@ TEST_F(IcmpReachableTest, HandlesReachableEvents) {
}
TEST_F(IcmpReachableTest, HandlesWriteErrors) {
- IcmpReachable reachable(source_, destination_, absl::Seconds(0), &kernel_,
+ IcmpReachable reachable(source_, destination_, absl::ZeroDuration(), &kernel_,
&epoll_server_, &stats_);
SetFdExpectations();
@@ -232,7 +232,7 @@ TEST_F(IcmpReachableTest, HandlesWriteErrors) {
}
TEST_F(IcmpReachableTest, HandlesReadErrors) {
- IcmpReachable reachable(source_, destination_, absl::Seconds(0), &kernel_,
+ IcmpReachable reachable(source_, destination_, absl::ZeroDuration(), &kernel_,
&epoll_server_, &stats_);
SetFdExpectations();
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/mock_packet_exchanger_stats_interface.h b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/mock_packet_exchanger_stats_interface.h
new file mode 100644
index 00000000000..f74e2a3bd30
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/mock_packet_exchanger_stats_interface.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_QBONE_BONNET_MOCK_PACKET_EXCHANGER_STATS_INTERFACE_H_
+#define QUICHE_QUIC_QBONE_BONNET_MOCK_PACKET_EXCHANGER_STATS_INTERFACE_H_
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.h"
+
+namespace quic {
+
+class MockPacketExchangerStatsInterface
+ : public TunDevicePacketExchanger::StatsInterface {
+ public:
+ MOCK_METHOD0(OnPacketRead, void());
+ MOCK_METHOD0(OnPacketWritten, void());
+ MOCK_METHOD1(OnReadError, void(string*));
+ MOCK_METHOD1(OnWriteError, void(string*));
+
+ MOCK_CONST_METHOD0(PacketsRead, int64_t());
+ MOCK_CONST_METHOD0(PacketsWritten, int64_t());
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_QBONE_BONNET_MOCK_PACKET_EXCHANGER_STATS_INTERFACE_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 6c0a8a55ed8..e266654892b 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
@@ -30,7 +30,9 @@ TunDevice::TunDevice(const string& interface_name,
kernel_(*kernel) {}
TunDevice::~TunDevice() {
- Down();
+ if (!persist_) {
+ Down();
+ }
CleanUpFileDescriptor();
}
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.cc b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.cc
index 799247c0dfa..37fd2c0163b 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.cc
@@ -81,4 +81,9 @@ int TunDevicePacketExchanger::file_descriptor() const {
return fd_;
}
+const TunDevicePacketExchanger::StatsInterface*
+TunDevicePacketExchanger::stats_interface() const {
+ return stats_;
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.h b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.h
index 12d9efa714a..42ed7fb5214 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.h
@@ -30,6 +30,9 @@ class TunDevicePacketExchanger : public QbonePacketExchanger {
virtual void OnPacketWritten() = 0;
virtual void OnReadError(string* error) = 0;
virtual void OnWriteError(string* error) = 0;
+
+ ABSL_MUST_USE_RESULT virtual int64_t PacketsRead() const = 0;
+ ABSL_MUST_USE_RESULT virtual int64_t PacketsWritten() const = 0;
};
// |fd| is a open file descriptor on a TUN device that's opened for both read
@@ -48,7 +51,9 @@ class TunDevicePacketExchanger : public QbonePacketExchanger {
size_t max_pending_packets,
StatsInterface* stats);
- int file_descriptor() const;
+ ABSL_MUST_USE_RESULT int file_descriptor() const;
+
+ ABSL_MUST_USE_RESULT const StatsInterface* stats_interface() const;
private:
// From QbonePacketExchanger.
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc
index 026ec26da5e..0f25e73eab4 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc
@@ -5,6 +5,7 @@
#include "net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/qbone/bonnet/mock_packet_exchanger_stats_interface.h"
#include "net/third_party/quiche/src/quic/qbone/mock_qbone_client.h"
#include "net/third_party/quiche/src/quic/qbone/platform/mock_kernel.h"
@@ -26,15 +27,6 @@ class MockVisitor : public QbonePacketExchanger::Visitor {
MOCK_METHOD1(OnWriteError, void(const string&));
};
-class MockStatsInterface : public TunDevicePacketExchanger::StatsInterface {
- public:
- MOCK_METHOD0(OnPacketRead, void());
- MOCK_METHOD0(OnPacketWritten, void());
-
- MOCK_METHOD1(OnReadError, void(string*));
- MOCK_METHOD1(OnWriteError, void(string*));
-};
-
class TunDevicePacketExchangerTest : public QuicTest {
protected:
TunDevicePacketExchangerTest()
@@ -50,7 +42,7 @@ class TunDevicePacketExchangerTest : public QuicTest {
MockKernel mock_kernel_;
StrictMock<MockVisitor> mock_visitor_;
StrictMock<MockQboneClient> mock_client_;
- StrictMock<MockStatsInterface> mock_stats_;
+ StrictMock<MockPacketExchangerStatsInterface> mock_stats_;
TunDevicePacketExchanger exchanger_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet.cc b/chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet.cc
index 8ba3916b951..9039944583c 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/icmp_packet.cc
@@ -5,8 +5,9 @@
#include "net/third_party/quiche/src/quic/qbone/platform/icmp_packet.h"
#include <netinet/ip6.h>
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
+
#include "net/third_party/quiche/src/quic/qbone/platform/internet_checksum.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
namespace {
@@ -46,7 +47,8 @@ void CreateIcmpPacket(in6_addr src,
// Set version to 6.
icmp_packet.ip_header.ip6_vfc = 0x6 << 4;
// Set the payload size, protocol and TTL.
- icmp_packet.ip_header.ip6_plen = QuicEndian::HostToNet16(payload_size);
+ icmp_packet.ip_header.ip6_plen =
+ quiche::QuicheEndian::HostToNet16(payload_size);
icmp_packet.ip_header.ip6_nxt = IPPROTO_ICMPV6;
icmp_packet.ip_header.ip6_hops = kIcmpTtl;
// Set the source address to the specified self IP.
@@ -58,7 +60,7 @@ void CreateIcmpPacket(in6_addr src,
icmp_packet.icmp_header.icmp6_cksum = 0;
IPv6PseudoHeader pseudo_header{};
- pseudo_header.payload_size = QuicEndian::HostToNet32(payload_size);
+ pseudo_header.payload_size = quiche::QuicheEndian::HostToNet32(payload_size);
InternetChecksum checksum;
// Pseudoheader.
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/internet_checksum.cc b/chromium/net/third_party/quiche/src/quic/qbone/platform/internet_checksum.cc
index 9cbe227abdc..b98c85767b4 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/internet_checksum.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/internet_checksum.cc
@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/qbone/platform/internet_checksum.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/ip_range.cc b/chromium/net/third_party/quiche/src/quic/qbone/platform/ip_range.cc
index 15ebb726b86..03ad6407996 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/ip_range.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/ip_range.cc
@@ -4,7 +4,7 @@
#include "net/third_party/quiche/src/quic/qbone/platform/ip_range.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
@@ -23,9 +23,9 @@ QuicIpAddress TruncateToLength(const QuicIpAddress& input,
}
uint32_t raw_address =
*reinterpret_cast<const uint32_t*>(input.ToPackedString().data());
- raw_address = QuicEndian::NetToHost32(raw_address);
+ raw_address = quiche::QuicheEndian::NetToHost32(raw_address);
raw_address &= ~0U << (kIPv4Size - *prefix_length);
- raw_address = QuicEndian::HostToNet32(raw_address);
+ raw_address = quiche::QuicheEndian::HostToNet32(raw_address);
output.FromPackedString(reinterpret_cast<const char*>(&raw_address),
sizeof(raw_address));
return output;
@@ -42,16 +42,16 @@ QuicIpAddress TruncateToLength(const QuicIpAddress& input,
// out.
// The endianess between raw_address[0] and raw_address[1] is handled
// explicitly by handling lower and higher bytes separately.
- raw_address[0] = QuicEndian::NetToHost64(raw_address[0]);
- raw_address[1] = QuicEndian::NetToHost64(raw_address[1]);
+ raw_address[0] = quiche::QuicheEndian::NetToHost64(raw_address[0]);
+ raw_address[1] = quiche::QuicheEndian::NetToHost64(raw_address[1]);
if (*prefix_length <= kIPv6Size / 2) {
raw_address[0] &= ~uint64_t{0} << (kIPv6Size / 2 - *prefix_length);
raw_address[1] = 0;
} else {
raw_address[1] &= ~uint64_t{0} << (kIPv6Size - *prefix_length);
}
- raw_address[0] = QuicEndian::HostToNet64(raw_address[0]);
- raw_address[1] = QuicEndian::HostToNet64(raw_address[1]);
+ raw_address[0] = quiche::QuicheEndian::HostToNet64(raw_address[0]);
+ raw_address[1] = quiche::QuicheEndian::HostToNet64(raw_address[1]);
output.FromPackedString(reinterpret_cast<const char*>(raw_address),
sizeof(raw_address));
return output;
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 7bd5f6b8563..04ce68cd9a9 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
@@ -45,7 +45,7 @@ class NetlinkTest : public QuicTest {
InSequence s;
EXPECT_CALL(mock_kernel_, sendmsg(kSocketFd, _, _))
- .WillOnce(Invoke([this, type, flags, send_callback](
+ .WillOnce(Invoke([type, flags, send_callback](
Unused, const struct msghdr* msg, int) {
EXPECT_EQ(sizeof(struct sockaddr_nl), msg->msg_namelen);
auto* nl_addr =
@@ -251,7 +251,7 @@ TEST_F(NetlinkTest, GetLinkInfoWorks) {
ExpectNetlinkPacket(
RTM_GETLINK, NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST,
- [this, &hwaddr, &bcaddr](void* buf, size_t len, int seq) {
+ [&hwaddr, &bcaddr](void* buf, size_t len, int seq) {
int ret = 0;
struct nlmsghdr* netlink_message =
@@ -291,7 +291,7 @@ TEST_F(NetlinkTest, GetAddressesWorks) {
ExpectNetlinkPacket(
RTM_GETADDR, NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST,
- [this, &addresses](void* buf, size_t len, int seq) {
+ [&addresses](void* buf, size_t len, int seq) {
int ret = 0;
struct nlmsghdr* nlm = nullptr;
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet.cc b/chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet.cc
index 56fa88ab2d3..2566d25eded 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/tcp_packet.cc
@@ -6,9 +6,9 @@
#include <netinet/ip6.h>
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/qbone/platform/internet_checksum.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
namespace {
@@ -45,8 +45,8 @@ void CreateTcpResetPacket(
if (QUIC_PREDICT_FALSE(ip6_header->ip6_nxt != IPPROTO_TCP)) {
return;
}
- if (QUIC_PREDICT_FALSE(QuicEndian::NetToHost16(ip6_header->ip6_plen) <
- sizeof(tcphdr))) {
+ if (QUIC_PREDICT_FALSE(quiche::QuicheEndian::NetToHost16(
+ ip6_header->ip6_plen) < sizeof(tcphdr))) {
return;
}
auto* tcp_header = reinterpret_cast<const tcphdr*>(ip6_header + 1);
@@ -60,7 +60,8 @@ void CreateTcpResetPacket(
// Set version to 6.
tcp_packet.ip_header.ip6_vfc = 0x6 << 4;
// Set the payload size, protocol and TTL.
- tcp_packet.ip_header.ip6_plen = QuicEndian::HostToNet16(payload_size);
+ tcp_packet.ip_header.ip6_plen =
+ quiche::QuicheEndian::HostToNet16(payload_size);
tcp_packet.ip_header.ip6_nxt = IPPROTO_TCP;
tcp_packet.ip_header.ip6_hops = kTcpTtl;
// Since the TCP RST is impersonating the endpoint, flip the source and
@@ -98,12 +99,12 @@ void CreateTcpResetPacket(
// the sum of the sequence number and segment length of the incoming segment
tcp_packet.tcp_header.ack = 1;
tcp_packet.tcp_header.seq = 0;
- tcp_packet.tcp_header.ack_seq =
- QuicEndian::HostToNet32(QuicEndian::NetToHost32(tcp_header->seq) + 1);
+ tcp_packet.tcp_header.ack_seq = quiche::QuicheEndian::HostToNet32(
+ quiche::QuicheEndian::NetToHost32(tcp_header->seq) + 1);
}
TCPv6PseudoHeader pseudo_header{};
- pseudo_header.payload_size = QuicEndian::HostToNet32(payload_size);
+ pseudo_header.payload_size = quiche::QuicheEndian::HostToNet32(payload_size);
InternetChecksum checksum;
// Pseudoheader.
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 e585d058386..95e3aeaf090 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
@@ -40,7 +40,8 @@ QboneClient::QboneClient(QuicSocketAddress server_address,
new QuicEpollConnectionHelper(epoll_server, QuicAllocator::SIMPLE),
new QuicEpollAlarmFactory(epoll_server),
CreateNetworkHelper(epoll_server, this),
- std::move(proof_verifier)),
+ std::move(proof_verifier),
+ nullptr),
qbone_writer_(qbone_writer),
qbone_handler_(qbone_handler),
session_owner_(session_owner) {
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 db7a1382a8f..39b622b4de5 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
@@ -7,11 +7,11 @@
#include <cstring>
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/qbone/platform/icmp_packet.h"
#include "net/third_party/quiche/src/quic/qbone/platform/internet_checksum.h"
#include "net/third_party/quiche/src/quic/qbone/platform/tcp_packet.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace {
@@ -171,7 +171,7 @@ QbonePacketProcessor::ProcessingResult QbonePacketProcessor::ProcessIPv6Header(
// Check payload size.
const size_t declared_payload_size =
- QuicEndian::NetToHost16(header->ip6_plen);
+ quiche::QuicheEndian::NetToHost16(header->ip6_plen);
const size_t actual_payload_size = packet->size() - kIPv6HeaderSize;
if (declared_payload_size != actual_payload_size) {
QUIC_DVLOG(1)
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 62bcaa4a511..c3e7731bcd0 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
@@ -4,11 +4,15 @@
#include "net/third_party/quiche/src/quic/qbone/qbone_session_base.h"
+#include <netinet/icmp6.h>
+#include <netinet/ip6.h>
+
#include <utility>
#include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_exported_stats.h"
+#include "net/third_party/quiche/src/quic/qbone/platform/icmp_packet.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_constants.h"
namespace quic {
@@ -137,12 +141,41 @@ void QboneSessionBase::SendPacketToPeer(QuicStringPiece packet) {
QuicMemSlice slice(connection()->helper()->GetStreamSendBufferAllocator(),
packet.size());
memcpy(const_cast<char*>(slice.data()), packet.data(), packet.size());
- if (SendMessage(QuicMemSliceSpan(&slice)).status ==
- MESSAGE_STATUS_SUCCESS) {
- return;
+ switch (SendMessage(QuicMemSliceSpan(&slice), /*flush=*/true).status) {
+ case MESSAGE_STATUS_SUCCESS:
+ break;
+ case MESSAGE_STATUS_TOO_LARGE: {
+ if (packet.size() < sizeof(ip6_hdr)) {
+ QUIC_BUG << "Dropped malformed packet: IPv6 header too short";
+ break;
+ }
+ auto* header = reinterpret_cast<const ip6_hdr*>(packet.begin());
+ icmp6_hdr icmp_header{};
+ icmp_header.icmp6_type = ICMP6_PACKET_TOO_BIG;
+ icmp_header.icmp6_mtu =
+ connection()->GetGuaranteedLargestMessagePayload();
+
+ CreateIcmpPacket(header->ip6_dst, header->ip6_src, icmp_header, packet,
+ [this](QuicStringPiece icmp_packet) {
+ writer_->WritePacketToNetwork(icmp_packet.data(),
+ icmp_packet.size());
+ });
+ break;
+ }
+ case MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED:
+ QUIC_BUG << "MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED";
+ break;
+ case MESSAGE_STATUS_UNSUPPORTED:
+ QUIC_BUG << "MESSAGE_STATUS_UNSUPPORTED";
+ break;
+ case MESSAGE_STATUS_BLOCKED:
+ QUIC_BUG << "MESSAGE_STATUS_BLOCKED";
+ break;
+ case MESSAGE_STATUS_INTERNAL_ERROR:
+ QUIC_BUG << "MESSAGE_STATUS_INTERNAL_ERROR";
+ break;
}
- // If SendMessage() fails for any reason, fall back to ephemeral streams.
- num_fallback_to_stream_++;
+ return;
}
// Qbone streams are ephemeral.
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_test.cc
index 83ee0877683..19ecd2c54fe 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_test.cc
@@ -12,6 +12,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test_loopback.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/quic/qbone/platform/icmp_packet.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_client_session.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_constants.h"
#include "net/third_party/quiche/src/quic/qbone/qbone_control_placeholder.pb.h"
@@ -170,7 +171,7 @@ class DataSavingQboneControlHandler : public QboneControlHandler<T> {
class FakeTaskRunner {
public:
explicit FakeTaskRunner(MockQuicConnectionHelper* helper)
- : tasks_([this](const TaskType& l, const TaskType& r) {
+ : tasks_([](const TaskType& l, const TaskType& r) {
// Items at a later time should run after items at an earlier time.
// Priority queue comparisons should return true if l appears after r.
return l->time() > r->time();
@@ -298,7 +299,7 @@ class QboneSessionTest : public QuicTest {
server_crypto_config_->GenerateConfig(QuicRandom::GetInstance(),
GetClock(), options);
std::unique_ptr<CryptoHandshakeMessage> message(
- server_crypto_config_->AddConfig(std::move(primary_config),
+ server_crypto_config_->AddConfig(primary_config,
GetClock()->WallNow()));
server_peer_ = std::make_unique<QboneServerSession>(
@@ -353,6 +354,23 @@ class QboneSessionTest : public QuicTest {
runner_.Run();
}
+ void ExpectICMPTooBigResponse(const std::vector<string>& written_packets,
+ const int mtu,
+ const string& packet) {
+ auto* header = reinterpret_cast<const ip6_hdr*>(packet.data());
+ icmp6_hdr icmp_header{};
+ icmp_header.icmp6_type = ICMP6_PACKET_TOO_BIG;
+ icmp_header.icmp6_mtu = mtu;
+
+ string expected;
+ CreateIcmpPacket(header->ip6_dst, header->ip6_src, icmp_header, packet,
+ [&expected](QuicStringPiece icmp_packet) {
+ expected = string(icmp_packet);
+ });
+
+ EXPECT_THAT(written_packets, Contains(expected));
+ }
+
// Test handshake establishment and sending/receiving of data for two
// directions.
void TestStreamConnection(bool use_messages) {
@@ -395,7 +413,14 @@ class QboneSessionTest : public QuicTest {
QUIC_LOG(INFO) << "Sending server -> client long data";
server_peer_->ProcessPacketFromNetwork(TestPacketIn(long_data));
runner_.Run();
- EXPECT_THAT(client_writer_->data(), Contains(TestPacketOut(long_data)));
+ if (use_messages) {
+ ExpectICMPTooBigResponse(
+ server_writer_->data(),
+ server_peer_->connection()->GetGuaranteedLargestMessagePayload(),
+ TestPacketOut(long_data));
+ } else {
+ EXPECT_THAT(client_writer_->data(), Contains(TestPacketOut(long_data)));
+ }
EXPECT_THAT(server_writer_->data(),
Not(Contains(TestPacketOut(long_data))));
EXPECT_EQ(0u, server_peer_->GetNumActiveStreams());
@@ -404,11 +429,22 @@ class QboneSessionTest : public QuicTest {
QUIC_LOG(INFO) << "Sending client -> server long data";
client_peer_->ProcessPacketFromNetwork(TestPacketIn(long_data));
runner_.Run();
- EXPECT_THAT(server_writer_->data(), Contains(TestPacketOut(long_data)));
+ if (use_messages) {
+ ExpectICMPTooBigResponse(
+ client_writer_->data(),
+ client_peer_->connection()->GetGuaranteedLargestMessagePayload(),
+ TestPacketIn(long_data));
+ } else {
+ EXPECT_THAT(server_writer_->data(), Contains(TestPacketOut(long_data)));
+ }
EXPECT_THAT(client_peer_->GetNumSentClientHellos(), Eq(2));
EXPECT_THAT(client_peer_->GetNumReceivedServerConfigUpdates(), Eq(0));
- EXPECT_THAT(client_peer_->GetNumStreamedPackets(), Eq(1));
- EXPECT_THAT(server_peer_->GetNumStreamedPackets(), Eq(1));
+
+ if (!use_messages) {
+ EXPECT_THAT(client_peer_->GetNumStreamedPackets(), Eq(1));
+ EXPECT_THAT(server_peer_->GetNumStreamedPackets(), Eq(1));
+ }
+
if (use_messages) {
EXPECT_THAT(client_peer_->GetNumEphemeralPackets(), Eq(0));
EXPECT_THAT(server_peer_->GetNumEphemeralPackets(), Eq(0));
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint_test.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint_test.cc
index 165139c46f1..8506067f13d 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint_test.cc
@@ -11,6 +11,7 @@
#include "net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_fakes.h"
#include "net/third_party/quiche/src/quic/quartc/simulated_packet_transport.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
@@ -195,7 +196,8 @@ TEST_F(QuartcEndpointTest,
return client_endpoint_delegate_.session() != nullptr &&
client_endpoint_delegate_.session()->error() != QUIC_NO_ERROR;
}));
- EXPECT_EQ(client_endpoint_delegate_.session()->error(), QUIC_INVALID_VERSION);
+ EXPECT_THAT(client_endpoint_delegate_.session()->error(),
+ test::IsError(QUIC_INVALID_VERSION));
}
// Tests that the client endpoint can create a new session in order to continue
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_factory.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_factory.cc
index 413c4f83f74..ad677fd8c94 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_factory.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_factory.cc
@@ -63,11 +63,8 @@ void ConfigureGlobalQuicSettings() {
// Fixes behavior of StopReading() with level-triggered stream sequencers.
SetQuicReloadableFlag(quic_stop_reading_when_level_triggered, true);
- // Enable version 47 to enable variable-length connection ids.
- SetQuicReloadableFlag(quic_enable_version_47, true);
-
- // Enable version 48 to be compatible with the latest version of Chrome.
- SetQuicReloadableFlag(quic_enable_version_48_2, true);
+ // Enable version 50 to be compatible with the latest version of Chrome.
+ SetQuicReloadableFlag(quic_enable_version_50, true);
// Ensure that we don't drop data because QUIC streams refuse to buffer it.
// TODO(b/120099046): Replace this with correct handling of WriteMemSlices().
@@ -98,7 +95,7 @@ QuicConfig CreateQuicConfig(const QuartcSessionConfig& quartc_session_config) {
// In exoblaze this may return false. DCHECK to avoid problems caused by
// incorrect flags configuration.
- DCHECK(GetQuicReloadableFlag(quic_enable_version_47))
+ DCHECK(GetQuicReloadableFlag(quic_enable_version_50))
<< "Your build does not support quic reloadable flags and shouldn't "
"place Quartc calls";
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer_test.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer_test.cc
index a8f53528e5e..3cc088b4da1 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_multiplexer_test.cc
@@ -23,6 +23,7 @@
#include "net/third_party/quiche/src/quic/quartc/quartc_session.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_stream.h"
#include "net/third_party/quiche/src/quic/quartc/simulated_packet_transport.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
@@ -468,8 +469,10 @@ TEST_F(QuartcMultiplexerTest, CloseEvent) {
Connect();
Disconnect();
- EXPECT_EQ(client_session_delegate_.error(), QUIC_CONNECTION_CANCELLED);
- EXPECT_EQ(server_session_delegate_.error(), QUIC_CONNECTION_CANCELLED);
+ EXPECT_THAT(client_session_delegate_.error(),
+ test::IsError(QUIC_CONNECTION_CANCELLED));
+ EXPECT_THAT(server_session_delegate_.error(),
+ test::IsError(QUIC_CONNECTION_CANCELLED));
}
TEST_F(QuartcMultiplexerTest, CongestionEvent) {
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_packet_writer.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_packet_writer.cc
index 5ffb892ef44..f67cc774ea8 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_packet_writer.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_packet_writer.cc
@@ -29,7 +29,7 @@ WriteResult QuartcPacketWriter::WritePacket(
static_cast<QuartcPerPacketOptions*>(options);
if (quartc_options && quartc_options->connection) {
info.packet_number =
- quartc_options->connection->packet_generator().packet_number();
+ quartc_options->connection->packet_creator().packet_number();
}
int bytes_written = packet_transport_->Write(buffer, buf_len, info);
if (bytes_written <= 0) {
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_session.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_session.cc
index 0868d72adbe..654e54081aa 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_session.cc
@@ -175,6 +175,36 @@ void QuartcSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
}
}
+void QuartcSession::SetDefaultEncryptionLevel(EncryptionLevel level) {
+ QuicSession::SetDefaultEncryptionLevel(level);
+ switch (level) {
+ case ENCRYPTION_INITIAL:
+ break;
+ case ENCRYPTION_ZERO_RTT:
+ if (connection()->perspective() == Perspective::IS_CLIENT) {
+ DCHECK(IsEncryptionEstablished());
+ DCHECK(session_delegate_);
+ session_delegate_->OnConnectionWritable();
+ }
+ break;
+ case ENCRYPTION_HANDSHAKE:
+ break;
+ case ENCRYPTION_FORWARD_SECURE:
+ // On the server, handshake confirmed is the first time when you can start
+ // writing packets.
+ DCHECK(IsEncryptionEstablished());
+ DCHECK(IsCryptoHandshakeConfirmed());
+
+ DCHECK(session_delegate_);
+ session_delegate_->OnConnectionWritable();
+ session_delegate_->OnCryptoHandshakeComplete();
+ break;
+ default:
+ QUIC_BUG << "Unknown encryption level: "
+ << EncryptionLevelToString(level);
+ }
+}
+
void QuartcSession::CancelStream(QuicStreamId stream_id) {
ResetStream(stream_id, QuicRstStreamErrorCode::QUIC_STREAM_CANCELLED);
}
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_session.h b/chromium/net/third_party/quiche/src/quic/quartc/quartc_session.h
index e9001d635d9..1c0fd317b4c 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_session.h
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_session.h
@@ -74,6 +74,7 @@ class QuartcSession : public QuicSession,
}
void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
+ void SetDefaultEncryptionLevel(EncryptionLevel level) override;
// QuicConnectionVisitorInterface overrides.
void OnCongestionWindowChange(QuicTime now) override;
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_session_test.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_session_test.cc
index 6ed8ec514e2..956073bade9 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_session_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_session_test.cc
@@ -20,6 +20,7 @@
#include "net/third_party/quiche/src/quic/quartc/quartc_packet_writer.h"
#include "net/third_party/quiche/src/quic/quartc/simulated_packet_transport.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/packet_filter.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
@@ -543,10 +544,10 @@ TEST_F(QuartcSessionTest, StreamRetransmissionDisabled) {
EXPECT_TRUE(client_peer_->IsClosedStream(stream_id));
EXPECT_TRUE(server_peer_->IsClosedStream(stream_id));
- EXPECT_EQ(client_stream_delegate_->stream_error(stream_id),
- QUIC_STREAM_CANCELLED);
- EXPECT_EQ(server_stream_delegate_->stream_error(stream_id),
- QUIC_STREAM_CANCELLED);
+ EXPECT_THAT(client_stream_delegate_->stream_error(stream_id),
+ test::IsStreamError(QUIC_STREAM_CANCELLED));
+ EXPECT_THAT(server_stream_delegate_->stream_error(stream_id),
+ test::IsStreamError(QUIC_STREAM_CANCELLED));
}
TEST_F(QuartcSessionTest, LostDatagramNotifications) {
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream_test.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream_test.cc
index c8a68fcefff..0e972e50aff 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream_test.cc
@@ -27,7 +27,6 @@
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
@@ -36,8 +35,12 @@
#include "net/third_party/quiche/src/quic/quartc/quartc_factory.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
+using ::quic::test::IsQuicStreamNoError;
+using ::quic::test::IsStreamError;
+
namespace quic {
namespace {
@@ -73,7 +76,7 @@ class MockQuicSession : public QuicSession {
// WritevData does not pass down a iovec, data is saved in stream before
// data is consumed. Retrieve data from stream.
char* buf = new char[write_length];
- QuicDataWriter writer(write_length, buf, NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(write_length, buf, quiche::NETWORK_BYTE_ORDER);
if (write_length > 0) {
stream->WriteStreamData(offset, write_length, &writer);
}
@@ -419,7 +422,7 @@ TEST_F(QuartcStreamTest, TestCancelOnLossDisabled) {
stream_->OnCanWrite();
EXPECT_EQ("Foo barFoo bar", write_buffer_);
- EXPECT_EQ(stream_->stream_error(), QUIC_STREAM_NO_ERROR);
+ EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
}
TEST_F(QuartcStreamTest, TestCancelOnLossEnabled) {
@@ -436,7 +439,7 @@ TEST_F(QuartcStreamTest, TestCancelOnLossEnabled) {
stream_->OnCanWrite();
EXPECT_EQ("Foo bar", write_buffer_);
- EXPECT_EQ(stream_->stream_error(), QUIC_STREAM_CANCELLED);
+ EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_STREAM_CANCELLED));
}
TEST_F(QuartcStreamTest, MaxRetransmissionsAbsent) {
@@ -456,7 +459,7 @@ TEST_F(QuartcStreamTest, MaxRetransmissionsAbsent) {
stream_->OnCanWrite();
EXPECT_EQ("Foo barFoo bar", write_buffer_);
- EXPECT_EQ(stream_->stream_error(), QUIC_STREAM_NO_ERROR);
+ EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
}
TEST_F(QuartcStreamTest, MaxRetransmissionsSet) {
@@ -483,7 +486,7 @@ TEST_F(QuartcStreamTest, MaxRetransmissionsSet) {
stream_->OnCanWrite();
EXPECT_EQ("Foo barFoo barFoo bar", write_buffer_);
- EXPECT_EQ(stream_->stream_error(), QUIC_STREAM_CANCELLED);
+ EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_STREAM_CANCELLED));
}
TEST_F(QuartcStreamTest, MaxRetransmissionsDisjointFrames) {
@@ -542,7 +545,7 @@ TEST_F(QuartcStreamTest, MaxRetransmissionsOverlappingFrames) {
stream_->OnCanWrite();
EXPECT_EQ("Foo barFoo bar", write_buffer_);
- EXPECT_EQ(stream_->stream_error(), QUIC_STREAM_CANCELLED);
+ EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_STREAM_CANCELLED));
}
TEST_F(QuartcStreamTest, MaxRetransmissionsWithAckedFrame) {
@@ -579,7 +582,7 @@ TEST_F(QuartcStreamTest, MaxRetransmissionsWithAckedFrame) {
// QuartcStream should be cancelled, but it stopped tracking the lost bytes
// after they were acked, so it's not.
- EXPECT_EQ(stream_->stream_error(), QUIC_STREAM_NO_ERROR);
+ EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
}
TEST_F(QuartcStreamTest, TestBytesPendingRetransmission) {
@@ -605,7 +608,7 @@ TEST_F(QuartcStreamTest, TestBytesPendingRetransmission) {
EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0u);
EXPECT_EQ("Foo barFoo bar", write_buffer_);
- EXPECT_EQ(stream_->stream_error(), QUIC_STREAM_NO_ERROR);
+ EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
}
TEST_F(QuartcStreamTest, TestBytesPendingRetransmissionWithCancelOnLoss) {
@@ -631,7 +634,7 @@ TEST_F(QuartcStreamTest, TestBytesPendingRetransmissionWithCancelOnLoss) {
EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0u);
EXPECT_EQ("Foo bar", write_buffer_);
- EXPECT_EQ(stream_->stream_error(), QUIC_STREAM_CANCELLED);
+ EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_STREAM_CANCELLED));
}
} // namespace
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 032f61d3bcb..e9487ec0458 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
@@ -16,9 +16,12 @@
#include "net/third_party/quiche/src/quic/core/quic_session.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h"
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
namespace quic {
@@ -40,15 +43,18 @@ QuicTransportClientSession::QuicTransportClientSession(
Visitor* owner,
const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
- const QuicServerId& server_id,
+ const GURL& url,
QuicCryptoClientConfig* crypto_config,
- url::Origin origin)
+ url::Origin origin,
+ ClientVisitor* visitor)
: QuicSession(connection,
owner,
config,
supported_versions,
/*num_expected_unidirectional_static_streams*/ 0),
- origin_(origin) {
+ url_(url),
+ origin_(origin),
+ visitor_(visitor) {
for (const ParsedQuicVersion& version : supported_versions) {
QUIC_BUG_IF(version.handshake_protocol != PROTOCOL_TLS1_3)
<< "QuicTransport requires TLS 1.3 handshake";
@@ -56,8 +62,22 @@ QuicTransportClientSession::QuicTransportClientSession(
// ProofHandler API is not used by TLS 1.3.
static DummyProofHandler* proof_handler = new DummyProofHandler();
crypto_stream_ = std::make_unique<QuicCryptoClientStream>(
- server_id, this, crypto_config->proof_verifier()->CreateDefaultContext(),
- crypto_config, proof_handler);
+ QuicServerId(url.host(), url.EffectiveIntPort()), this,
+ crypto_config->proof_verifier()->CreateDefaultContext(), crypto_config,
+ proof_handler);
+}
+
+QuicStream* QuicTransportClientSession::CreateIncomingStream(QuicStreamId id) {
+ QUIC_DVLOG(1) << "Creating incoming QuicTransport stream " << id;
+ QuicTransportStream* stream = CreateStream(id);
+ if (stream->type() == BIDIRECTIONAL) {
+ incoming_bidirectional_streams_.push_back(stream);
+ visitor_->OnIncomingBidirectionalStreamAvailable();
+ } else {
+ incoming_unidirectional_streams_.push_back(stream);
+ visitor_->OnIncomingUnidirectionalStreamAvailable();
+ }
+ return stream;
}
void QuicTransportClientSession::OnCryptoHandshakeEvent(
@@ -70,6 +90,59 @@ void QuicTransportClientSession::OnCryptoHandshakeEvent(
SendClientIndication();
}
+void QuicTransportClientSession::SetDefaultEncryptionLevel(
+ EncryptionLevel level) {
+ QuicSession::SetDefaultEncryptionLevel(level);
+ if (level == ENCRYPTION_FORWARD_SECURE) {
+ SendClientIndication();
+ }
+}
+
+QuicTransportStream*
+QuicTransportClientSession::AcceptIncomingBidirectionalStream() {
+ if (incoming_bidirectional_streams_.empty()) {
+ return nullptr;
+ }
+ QuicTransportStream* stream = incoming_bidirectional_streams_.front();
+ incoming_bidirectional_streams_.pop_front();
+ return stream;
+}
+
+QuicTransportStream*
+QuicTransportClientSession::AcceptIncomingUnidirectionalStream() {
+ if (incoming_unidirectional_streams_.empty()) {
+ return nullptr;
+ }
+ QuicTransportStream* stream = incoming_unidirectional_streams_.front();
+ incoming_unidirectional_streams_.pop_front();
+ return stream;
+}
+
+QuicTransportStream*
+QuicTransportClientSession::OpenOutgoingBidirectionalStream() {
+ if (!CanOpenNextOutgoingBidirectionalStream()) {
+ QUIC_BUG << "Attempted to open a stream in violation of flow control";
+ return nullptr;
+ }
+ return CreateStream(GetNextOutgoingBidirectionalStreamId());
+}
+
+QuicTransportStream*
+QuicTransportClientSession::OpenOutgoingUnidirectionalStream() {
+ if (!CanOpenNextOutgoingUnidirectionalStream()) {
+ QUIC_BUG << "Attempted to open a stream in violation of flow control";
+ return nullptr;
+ }
+ return CreateStream(GetNextOutgoingUnidirectionalStreamId());
+}
+
+QuicTransportStream* QuicTransportClientSession::CreateStream(QuicStreamId id) {
+ auto stream = std::make_unique<QuicTransportStream>(id, this, this);
+ QuicTransportStream* stream_ptr = stream.get();
+ ActivateStream(std::move(stream));
+ return stream_ptr;
+}
+
std::string QuicTransportClientSession::SerializeClientIndication() {
std::string serialized_origin = origin_.Serialize();
if (serialized_origin.size() > std::numeric_limits<uint16_t>::max()) {
@@ -82,16 +155,40 @@ std::string QuicTransportClientSession::SerializeClientIndication() {
QUIC_DLOG(INFO) << "Sending client indication with origin "
<< serialized_origin;
+ std::string path = url_.PathForRequest();
+ if (path.size() > std::numeric_limits<uint16_t>::max()) {
+ connection()->CloseConnection(
+ QUIC_TRANSPORT_INVALID_CLIENT_INDICATION, "Requested URL path too long",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return "";
+ }
+
+ constexpr size_t kPrefixSize =
+ sizeof(QuicTransportClientIndicationKeys) + sizeof(uint16_t);
+ const size_t buffer_size =
+ 2 * kPrefixSize + serialized_origin.size() + path.size();
+ if (buffer_size > std::numeric_limits<uint16_t>::max()) {
+ connection()->CloseConnection(
+ QUIC_TRANSPORT_INVALID_CLIENT_INDICATION,
+ "Client indication size limit exceeded",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return "";
+ }
+
std::string buffer;
- buffer.resize(/* key */ sizeof(QuicTransportClientIndicationKeys) +
- /* length */ sizeof(uint16_t) + serialized_origin.size());
+ buffer.resize(buffer_size);
QuicDataWriter writer(buffer.size(), &buffer[0]);
- writer.WriteUInt16(
- static_cast<uint16_t>(QuicTransportClientIndicationKeys::kOrigin));
- writer.WriteUInt16(serialized_origin.size());
- writer.WriteStringPiece(serialized_origin);
-
- buffer.resize(writer.length());
+ bool success =
+ writer.WriteUInt16(
+ static_cast<uint16_t>(QuicTransportClientIndicationKeys::kOrigin)) &&
+ writer.WriteUInt16(serialized_origin.size()) &&
+ writer.WriteStringPiece(serialized_origin) &&
+ 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())
+ << "Serialized client indication has length different from expected";
return buffer;
}
@@ -113,8 +210,11 @@ void QuicTransportClientSession::SendClientIndication() {
}
auto client_indication_owned = std::make_unique<ClientIndication>(
- /*stream_id=*/ClientIndicationStream(), this, /*is_static=*/false,
- WRITE_UNIDIRECTIONAL);
+ /*stream_id=*/GetNextOutgoingUnidirectionalStreamId(), this,
+ /*is_static=*/false, WRITE_UNIDIRECTIONAL);
+ QUIC_BUG_IF(client_indication_owned->id() != ClientIndicationStream())
+ << "Client indication stream is " << client_indication_owned->id()
+ << " instead of expected " << ClientIndicationStream();
ClientIndication* client_indication = client_indication_owned.get();
ActivateStream(std::move(client_indication_owned));
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 32149dfbb00..b3d8f17186b 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
@@ -8,6 +8,7 @@
#include <cstdint>
#include <memory>
+#include "url/gurl.h"
#include "url/origin.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h"
#include "net/third_party/quiche/src/quic/core/quic_config.h"
@@ -19,24 +20,38 @@
#include "net/third_party/quiche/src/quic/core/quic_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_session_interface.h"
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
namespace quic {
// A client session for the QuicTransport protocol.
-class QUIC_EXPORT QuicTransportClientSession
+class QUIC_EXPORT_PRIVATE QuicTransportClientSession
: public QuicSession,
public QuicTransportSessionInterface {
public:
+ class QUIC_EXPORT_PRIVATE ClientVisitor {
+ public:
+ virtual ~ClientVisitor() {}
+
+ // 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;
+ };
+
QuicTransportClientSession(QuicConnection* connection,
Visitor* owner,
const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
- const QuicServerId& server_id,
+ const GURL& url,
QuicCryptoClientConfig* crypto_config,
- url::Origin origin);
+ url::Origin origin,
+ ClientVisitor* visitor);
std::vector<std::string> GetAlpnsToOffer() const override {
return std::vector<std::string>({QuicTransportAlpn()});
@@ -53,12 +68,35 @@ class QUIC_EXPORT QuicTransportClientSession
return crypto_stream_.get();
}
+ // Returns true once the encryption has been established and the client
+ // indication has been sent. No application data will be read or written
+ // before the connection is ready. Once the connection becomes ready, this
+ // method will never return false.
bool IsSessionReady() const override { return ready_; }
+ QuicStream* CreateIncomingStream(QuicStreamId id) override;
+ QuicStream* CreateIncomingStream(PendingStream* /*pending*/) override {
+ QUIC_BUG << "QuicTransportClientSession::CreateIncomingStream("
+ "PendingStream) not implemented";
+ return nullptr;
+ }
+
void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
+ void SetDefaultEncryptionLevel(EncryptionLevel level) override;
+
+ // Return the earliest incoming stream that has been received by the session
+ // but has not been accepted. Returns nullptr if there are no incoming
+ // streams.
+ QuicTransportStream* AcceptIncomingBidirectionalStream();
+ QuicTransportStream* AcceptIncomingUnidirectionalStream();
+
+ using QuicSession::CanOpenNextOutgoingBidirectionalStream;
+ using QuicSession::CanOpenNextOutgoingUnidirectionalStream;
+ QuicTransportStream* OpenOutgoingBidirectionalStream();
+ QuicTransportStream* OpenOutgoingUnidirectionalStream();
protected:
- class ClientIndication : public QuicStream {
+ class QUIC_EXPORT_PRIVATE ClientIndication : public QuicStream {
public:
using QuicStream::QuicStream;
@@ -69,6 +107,9 @@ class QUIC_EXPORT QuicTransportClientSession
}
};
+ // Creates and activates a QuicTransportStream for the given ID.
+ QuicTransportStream* CreateStream(QuicStreamId id);
+
// Serializes the client indication as described in
// https://vasilvv.github.io/webtransport/draft-vvv-webtransport-quic.html#rfc.section.3.2
std::string SerializeClientIndication();
@@ -76,9 +117,22 @@ class QUIC_EXPORT QuicTransportClientSession
void SendClientIndication();
std::unique_ptr<QuicCryptoClientStream> crypto_stream_;
+ GURL url_;
url::Origin origin_;
+ ClientVisitor* visitor_; // not owned
bool client_indication_sent_ = false;
bool ready_ = false;
+
+ // Contains all of the streams that has been received by the session but have
+ // not been processed by the application.
+ // TODO(vasilvv): currently, we always send MAX_STREAMS as long as the overall
+ // maximum number of streams for the connection has not been exceeded. We
+ // should also limit the maximum number of streams that the consuming code
+ // has not accepted to a smaller number, by checking the size of
+ // |incoming_bidirectional_streams_| and |incoming_unidirectional_streams_|
+ // before sending MAX_STREAMS.
+ QuicDeque<QuicTransportStream*> incoming_bidirectional_streams_;
+ QuicDeque<QuicTransportStream*> incoming_unidirectional_streams_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session_test.cc b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session_test.cc
index 24e1071d3e9..17a475751d6 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session_test.cc
@@ -20,6 +20,7 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h"
namespace quic {
namespace test {
@@ -29,8 +30,6 @@ using testing::_;
using testing::ElementsAre;
const char* kTestOrigin = "https://test-origin.test";
-constexpr char kTestOriginClientIndication[] =
- "\0\0\0\x18https://test-origin.test";
url::Origin GetTestOrigin() {
GURL origin_url(kTestOrigin);
return url::Origin::Create(origin_url);
@@ -50,32 +49,6 @@ std::string DataInStream(QuicStream* stream) {
return result;
}
-class TestClientSession : public QuicTransportClientSession {
- public:
- using QuicTransportClientSession::QuicTransportClientSession;
-
- class Stream : public QuicStream {
- public:
- using QuicStream::QuicStream;
- void OnDataAvailable() override {}
- };
-
- QuicStream* CreateIncomingStream(QuicStreamId id) override {
- auto stream = std::make_unique<Stream>(
- id, this, /*is_static=*/false,
- QuicUtils::GetStreamType(id, connection()->perspective(),
- /*peer_initiated=*/true));
- QuicStream* result = stream.get();
- ActivateStream(std::move(stream));
- return result;
- }
-
- QuicStream* CreateIncomingStream(PendingStream* /*pending*/) override {
- QUIC_NOTREACHED();
- return nullptr;
- }
-};
-
class QuicTransportClientSessionTest : public QuicTest {
protected:
QuicTransportClientSessionTest()
@@ -83,16 +56,16 @@ class QuicTransportClientSessionTest : public QuicTest {
&alarm_factory_,
Perspective::IS_CLIENT,
GetVersions()),
- server_id_("test.example.com", 443),
crypto_config_(crypto_test_utils::ProofVerifierForTesting()) {
SetQuicReloadableFlag(quic_supports_tls_handshake, true);
- CreateSession(GetTestOrigin());
+ CreateSession(GetTestOrigin(), "");
}
- void CreateSession(url::Origin origin) {
- session_ = std::make_unique<TestClientSession>(
- &connection_, nullptr, DefaultQuicConfig(), GetVersions(), server_id_,
- &crypto_config_, origin);
+ void CreateSession(url::Origin origin, std::string url_suffix) {
+ session_ = std::make_unique<QuicTransportClientSession>(
+ &connection_, nullptr, DefaultQuicConfig(), GetVersions(),
+ GURL("quic-transport://test.example.com:50000" + url_suffix),
+ &crypto_config_, origin, &visitor_);
session_->Initialize();
crypto_stream_ = static_cast<QuicCryptoClientStream*>(
session_->GetMutableCryptoStream());
@@ -101,18 +74,20 @@ class QuicTransportClientSessionTest : public QuicTest {
void Connect() {
session_->CryptoConnect();
QuicConfig server_config = DefaultQuicConfig();
+ std::unique_ptr<QuicCryptoServerConfig> crypto_config(
+ crypto_test_utils::CryptoServerConfigForTesting());
crypto_test_utils::HandshakeWithFakeServer(
- &server_config, &helper_, &alarm_factory_, &connection_, crypto_stream_,
- QuicTransportAlpn());
+ &server_config, crypto_config.get(), &helper_, &alarm_factory_,
+ &connection_, crypto_stream_, QuicTransportAlpn());
}
MockAlarmFactory alarm_factory_;
MockQuicConnectionHelper helper_;
PacketSavingConnection connection_;
- QuicServerId server_id_;
QuicCryptoClientConfig crypto_config_;
- std::unique_ptr<TestClientSession> session_;
+ MockClientVisitor visitor_;
+ std::unique_ptr<QuicTransportClientSession> session_;
QuicCryptoClientStream* crypto_stream_;
};
@@ -121,6 +96,39 @@ TEST_F(QuicTransportClientSessionTest, HasValidAlpn) {
}
TEST_F(QuicTransportClientSessionTest, SuccessfulConnection) {
+ constexpr char kTestOriginClientIndication[] =
+ "\0\0" // key (0x0000, origin)
+ "\0\x18" // length
+ "https://test-origin.test" // value
+ "\0\x01" // key (0x0001, path)
+ "\0\x01" // length
+ "/"; // value
+
+ Connect();
+ EXPECT_TRUE(session_->IsSessionReady());
+
+ QuicStream* client_indication_stream =
+ QuicSessionPeer::zombie_streams(session_.get())[ClientIndicationStream()]
+ .get();
+ ASSERT_TRUE(client_indication_stream != nullptr);
+ const std::string client_indication = DataInStream(client_indication_stream);
+ const std::string expected_client_indication{
+ kTestOriginClientIndication,
+ QUIC_ARRAYSIZE(kTestOriginClientIndication) - 1};
+ EXPECT_EQ(client_indication, expected_client_indication);
+}
+
+TEST_F(QuicTransportClientSessionTest, SuccessfulConnectionWithPath) {
+ constexpr char kSuffix[] = "/foo/bar?hello=world#not-sent";
+ constexpr char kTestOriginClientIndication[] =
+ "\0\0" // key (0x0000, origin)
+ "\0\x18" // length
+ "https://test-origin.test" // value
+ "\0\x01" // key (0x0001, path)
+ "\0\x14" // length
+ "/foo/bar?hello=world"; // value
+
+ CreateSession(GetTestOrigin(), kSuffix);
Connect();
EXPECT_TRUE(session_->IsSessionReady());
@@ -139,11 +147,28 @@ TEST_F(QuicTransportClientSessionTest, OriginTooLong) {
std::string long_string(68000, 'a');
GURL bad_origin_url{"https://" + long_string + ".example/"};
EXPECT_TRUE(bad_origin_url.is_valid());
- CreateSession(url::Origin::Create(bad_origin_url));
+ CreateSession(url::Origin::Create(bad_origin_url), "");
EXPECT_QUIC_BUG(Connect(), "Client origin too long");
}
+TEST_F(QuicTransportClientSessionTest, ReceiveNewStreams) {
+ Connect();
+ ASSERT_TRUE(session_->IsSessionReady());
+ ASSERT_TRUE(session_->AcceptIncomingUnidirectionalStream() == nullptr);
+
+ const QuicStreamId id = GetNthServerInitiatedUnidirectionalStreamId(
+ session_->transport_version(), 0);
+ QuicStreamFrame frame(id, /*fin=*/false, /*offset=*/0, "test");
+ EXPECT_CALL(visitor_, OnIncomingUnidirectionalStreamAvailable()).Times(1);
+ session_->OnStreamFrame(frame);
+
+ QuicTransportStream* stream = session_->AcceptIncomingUnidirectionalStream();
+ ASSERT_TRUE(stream != nullptr);
+ EXPECT_EQ(stream->ReadableBytes(), 4u);
+ EXPECT_EQ(stream->id(), id);
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_integration_test.cc b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_integration_test.cc
new file mode 100644
index 00000000000..57f53804c3a
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_integration_test.cc
@@ -0,0 +1,331 @@
+// 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.
+
+// An integration test that covers interactions between QuicTransport client and
+// server sessions.
+
+#include <memory>
+#include <vector>
+
+#include "url/gurl.h"
+#include "url/origin.h"
+#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h"
+#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
+#include "net/third_party/quiche/src/quic/core/quic_connection.h"
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.h"
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h"
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
+#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h"
+#include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"
+#include "net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_base.h"
+#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
+#include "net/third_party/quiche/src/quic/test_tools/simulator/switch.h"
+#include "net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.h"
+
+namespace quic {
+namespace test {
+namespace {
+
+using simulator::QuicEndpointBase;
+using simulator::Simulator;
+using testing::Assign;
+
+url::Origin GetTestOrigin() {
+ constexpr char kTestOrigin[] = "https://test-origin.test";
+ GURL origin_url(kTestOrigin);
+ return url::Origin::Create(origin_url);
+}
+
+ParsedQuicVersionVector GetVersions() {
+ return {ParsedQuicVersion{PROTOCOL_TLS1_3, QUIC_VERSION_99}};
+}
+
+class QuicTransportEndpointBase : public QuicEndpointBase {
+ public:
+ QuicTransportEndpointBase(Simulator* simulator,
+ const std::string& name,
+ const std::string& peer_name,
+ Perspective perspective)
+ : QuicEndpointBase(simulator, name, peer_name) {
+ connection_ = std::make_unique<QuicConnection>(
+ TestConnectionId(0x10), simulator::GetAddressFromName(peer_name),
+ simulator, simulator->GetAlarmFactory(), &writer_,
+ /*owns_writer=*/false, perspective, GetVersions());
+ connection_->SetSelfAddress(simulator::GetAddressFromName(name));
+
+ SetQuicReloadableFlag(quic_supports_tls_handshake, true);
+ }
+};
+
+class QuicTransportClientEndpoint : public QuicTransportEndpointBase {
+ public:
+ QuicTransportClientEndpoint(Simulator* simulator,
+ const std::string& name,
+ const std::string& peer_name,
+ url::Origin origin)
+ : QuicTransportEndpointBase(simulator,
+ name,
+ peer_name,
+ Perspective::IS_CLIENT),
+ crypto_config_(crypto_test_utils::ProofVerifierForTesting()),
+ session_(connection_.get(),
+ nullptr,
+ DefaultQuicConfig(),
+ GetVersions(),
+ GURL("quic-transport://test.example.com:50000"),
+ &crypto_config_,
+ origin,
+ &visitor_) {
+ session_.Initialize();
+ }
+
+ QuicTransportClientSession* session() { return &session_; }
+ MockClientVisitor* visitor() { return &visitor_; }
+
+ private:
+ QuicCryptoClientConfig crypto_config_;
+ MockClientVisitor visitor_;
+ QuicTransportClientSession session_;
+};
+
+class QuicTransportServerEndpoint : public QuicTransportEndpointBase {
+ public:
+ QuicTransportServerEndpoint(Simulator* simulator,
+ const std::string& name,
+ const std::string& peer_name,
+ QuicTransportSimpleServerSession::Mode mode,
+ std::vector<url::Origin> accepted_origins)
+ : QuicTransportEndpointBase(simulator,
+ name,
+ peer_name,
+ Perspective::IS_SERVER),
+ crypto_config_(QuicCryptoServerConfig::TESTING,
+ QuicRandom::GetInstance(),
+ crypto_test_utils::ProofSourceForTesting(),
+ KeyExchangeSource::Default()),
+ compressed_certs_cache_(
+ QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
+ session_(connection_.get(),
+ /*owns_connection=*/false,
+ nullptr,
+ DefaultQuicConfig(),
+ GetVersions(),
+ &crypto_config_,
+ &compressed_certs_cache_,
+ mode,
+ accepted_origins) {
+ session_.Initialize();
+ }
+
+ QuicTransportServerSession* session() { return &session_; }
+
+ private:
+ QuicCryptoServerConfig crypto_config_;
+ QuicCompressedCertsCache compressed_certs_cache_;
+ 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 =
+ QuicTime::Delta::FromMilliseconds(2);
+constexpr QuicBandwidth kServerBandwidth =
+ QuicBandwidth::FromKBitsPerSecond(4000);
+constexpr QuicTime::Delta kServerPropagationDelay =
+ QuicTime::Delta::FromMilliseconds(50);
+const QuicTime::Delta kTransferTime =
+ kClientBandwidth.TransferTime(kMaxOutgoingPacketSize) +
+ kServerBandwidth.TransferTime(kMaxOutgoingPacketSize);
+const QuicTime::Delta kRtt =
+ (kClientPropagationDelay + kServerPropagationDelay + kTransferTime) * 2;
+const QuicByteCount kBdp = kRtt * kServerBandwidth;
+
+constexpr QuicTime::Delta kDefaultTimeout = QuicTime::Delta::FromSeconds(3);
+
+class QuicTransportIntegrationTest : public QuicTest {
+ public:
+ QuicTransportIntegrationTest()
+ : switch_(&simulator_, "Switch", 8, 2 * kBdp) {}
+
+ void CreateDefaultEndpoints(QuicTransportSimpleServerSession::Mode mode) {
+ client_ = std::make_unique<QuicTransportClientEndpoint>(
+ &simulator_, "Client", "Server", GetTestOrigin());
+ server_ = std::make_unique<QuicTransportServerEndpoint>(
+ &simulator_, "Server", "Client", mode, accepted_origins_);
+ }
+
+ void WireUpEndpoints() {
+ client_link_ = std::make_unique<simulator::SymmetricLink>(
+ client_.get(), switch_.port(1), kClientBandwidth,
+ kClientPropagationDelay);
+ server_link_ = std::make_unique<simulator::SymmetricLink>(
+ server_.get(), switch_.port(2), kServerBandwidth,
+ kServerPropagationDelay);
+ }
+
+ void RunHandshake() {
+ client_->session()->CryptoConnect();
+ bool result = simulator_.RunUntilOrTimeout(
+ [this]() {
+ return IsHandshakeDone(client_->session()) &&
+ IsHandshakeDone(server_->session());
+ },
+ kDefaultTimeout);
+ EXPECT_TRUE(result);
+ }
+
+ protected:
+ template <class Session>
+ static bool IsHandshakeDone(const Session* session) {
+ return session->IsSessionReady() || session->error() != QUIC_NO_ERROR;
+ }
+
+ Simulator simulator_;
+ simulator::Switch switch_;
+ std::unique_ptr<simulator::SymmetricLink> client_link_;
+ std::unique_ptr<simulator::SymmetricLink> server_link_;
+
+ std::unique_ptr<QuicTransportClientEndpoint> client_;
+ std::unique_ptr<QuicTransportServerEndpoint> server_;
+
+ std::vector<url::Origin> accepted_origins_ = {GetTestOrigin()};
+};
+
+TEST_F(QuicTransportIntegrationTest, SuccessfulHandshake) {
+ CreateDefaultEndpoints(QuicTransportSimpleServerSession::DISCARD);
+ WireUpEndpoints();
+ RunHandshake();
+ EXPECT_TRUE(client_->session()->IsSessionReady());
+ EXPECT_TRUE(server_->session()->IsSessionReady());
+}
+
+TEST_F(QuicTransportIntegrationTest, OriginMismatch) {
+ accepted_origins_ = {url::Origin::Create(GURL{"https://wrong-origin.test"})};
+ CreateDefaultEndpoints(QuicTransportSimpleServerSession::DISCARD);
+ WireUpEndpoints();
+ RunHandshake();
+ // Wait until the client receives CONNECTION_CLOSE.
+ simulator_.RunUntilOrTimeout(
+ [this]() { return !client_->session()->connection()->connected(); },
+ kDefaultTimeout);
+ EXPECT_TRUE(client_->session()->IsSessionReady());
+ EXPECT_FALSE(server_->session()->IsSessionReady());
+ EXPECT_FALSE(client_->session()->connection()->connected());
+ EXPECT_FALSE(server_->session()->connection()->connected());
+ EXPECT_THAT(client_->session()->error(),
+ IsError(QUIC_TRANSPORT_INVALID_CLIENT_INDICATION));
+ EXPECT_THAT(server_->session()->error(),
+ IsError(QUIC_TRANSPORT_INVALID_CLIENT_INDICATION));
+}
+
+TEST_F(QuicTransportIntegrationTest, SendOutgoingStreams) {
+ CreateDefaultEndpoints(QuicTransportSimpleServerSession::DISCARD);
+ WireUpEndpoints();
+ RunHandshake();
+
+ std::vector<QuicTransportStream*> streams;
+ for (int i = 0; i < 10; i++) {
+ QuicTransportStream* stream =
+ client_->session()->OpenOutgoingUnidirectionalStream();
+ ASSERT_TRUE(stream->Write("test"));
+ streams.push_back(stream);
+ }
+ ASSERT_TRUE(simulator_.RunUntilOrTimeout(
+ [this]() {
+ return server_->session()->GetNumOpenIncomingStreams() == 10;
+ },
+ kDefaultTimeout));
+
+ for (QuicTransportStream* stream : streams) {
+ ASSERT_TRUE(stream->SendFin());
+ }
+ ASSERT_TRUE(simulator_.RunUntilOrTimeout(
+ [this]() { return server_->session()->GetNumOpenIncomingStreams() == 0; },
+ kDefaultTimeout));
+}
+
+TEST_F(QuicTransportIntegrationTest, EchoBidirectionalStreams) {
+ CreateDefaultEndpoints(QuicTransportSimpleServerSession::ECHO);
+ WireUpEndpoints();
+ RunHandshake();
+
+ QuicTransportStream* stream =
+ client_->session()->OpenOutgoingBidirectionalStream();
+ EXPECT_TRUE(stream->Write("Hello!"));
+
+ ASSERT_TRUE(simulator_.RunUntilOrTimeout(
+ [stream]() { return stream->ReadableBytes() == strlen("Hello!"); },
+ kDefaultTimeout));
+ std::string received;
+ EXPECT_EQ(stream->Read(&received), strlen("Hello!"));
+ EXPECT_EQ(received, "Hello!");
+
+ EXPECT_TRUE(stream->SendFin());
+ ASSERT_TRUE(simulator_.RunUntilOrTimeout(
+ [this]() { return server_->session()->GetNumOpenIncomingStreams() == 0; },
+ kDefaultTimeout));
+}
+
+TEST_F(QuicTransportIntegrationTest, EchoUnidirectionalStreams) {
+ CreateDefaultEndpoints(QuicTransportSimpleServerSession::ECHO);
+ WireUpEndpoints();
+ RunHandshake();
+
+ // Send two streams, but only send FIN on the second one.
+ QuicTransportStream* stream1 =
+ client_->session()->OpenOutgoingUnidirectionalStream();
+ EXPECT_TRUE(stream1->Write("Stream One"));
+ QuicTransportStream* stream2 =
+ client_->session()->OpenOutgoingUnidirectionalStream();
+ EXPECT_TRUE(stream2->Write("Stream Two"));
+ EXPECT_TRUE(stream2->SendFin());
+
+ // Wait until a stream is received.
+ bool stream_received = false;
+ EXPECT_CALL(*client_->visitor(), OnIncomingUnidirectionalStreamAvailable())
+ .Times(2)
+ .WillRepeatedly(Assign(&stream_received, true));
+ ASSERT_TRUE(simulator_.RunUntilOrTimeout(
+ [&stream_received]() { return stream_received; }, kDefaultTimeout));
+
+ // Receive a reply stream and expect it to be the second one.
+ QuicTransportStream* reply =
+ client_->session()->AcceptIncomingUnidirectionalStream();
+ ASSERT_TRUE(reply != nullptr);
+ std::string buffer;
+ reply->set_visitor(VisitorExpectingFin());
+ EXPECT_GT(reply->Read(&buffer), 0u);
+ EXPECT_EQ(buffer, "Stream Two");
+
+ // Reset reply-related variables.
+ stream_received = false;
+ buffer = "";
+
+ // Send FIN on the first stream, and expect to receive it back.
+ EXPECT_TRUE(stream1->SendFin());
+ ASSERT_TRUE(simulator_.RunUntilOrTimeout(
+ [&stream_received]() { return stream_received; }, kDefaultTimeout));
+ reply = client_->session()->AcceptIncomingUnidirectionalStream();
+ ASSERT_TRUE(reply != nullptr);
+ reply->set_visitor(VisitorExpectingFin());
+ EXPECT_GT(reply->Read(&buffer), 0u);
+ EXPECT_EQ(buffer, "Stream One");
+}
+
+} // namespace
+} // namespace test
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h
index 307354f32ad..f97b8e777de 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h
@@ -12,23 +12,24 @@
namespace quic {
// The ALPN used by QuicTransport.
-QUIC_EXPORT inline const char* QuicTransportAlpn() {
+QUIC_EXPORT_PRIVATE inline const char* QuicTransportAlpn() {
return "wq-vvv-01";
}
// The stream ID on which the client indication is sent.
-QUIC_EXPORT constexpr QuicStreamId ClientIndicationStream() {
+QUIC_EXPORT_PRIVATE constexpr QuicStreamId ClientIndicationStream() {
return 2;
}
// The maximum allowed size of the client indication.
-QUIC_EXPORT constexpr QuicByteCount ClientIndicationMaxSize() {
+QUIC_EXPORT_PRIVATE constexpr QuicByteCount ClientIndicationMaxSize() {
return 65536;
}
// The keys of the fields in the client indication.
enum class QuicTransportClientIndicationKeys : uint16_t {
kOrigin = 0x0000,
+ kPath = 0x0001,
};
} // namespace quic
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 92cffcd9156..7f00acd470f 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
@@ -12,8 +12,8 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h"
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
namespace quic {
@@ -63,9 +63,11 @@ QuicStream* QuicTransportServerSession::CreateIncomingStream(QuicStreamId id) {
return indication_ptr;
}
- // TODO(vasilvv): implement incoming data streams.
- QUIC_BUG << "Not implemented";
- return nullptr;
+ auto stream = std::make_unique<QuicTransportStream>(id, this, this);
+ QuicTransportStream* stream_ptr = stream.get();
+ ActivateStream(std::move(stream));
+ OnIncomingDataStream(stream_ptr);
+ return stream_ptr;
}
QuicTransportServerSession::ClientIndication::ClientIndication(
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 7183eada1c8..b3fcfa07588 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
@@ -12,15 +12,16 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h"
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_session_interface.h"
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
namespace quic {
// A server session for the QuicTransport protocol.
-class QUIC_EXPORT QuicTransportServerSession
+class QUIC_EXPORT_PRIVATE QuicTransportServerSession
: public QuicSession,
public QuicTransportSessionInterface {
public:
- class ServerVisitor {
+ class QUIC_EXPORT_PRIVATE ServerVisitor {
public:
virtual ~ServerVisitor() {}
@@ -49,6 +50,10 @@ class QUIC_EXPORT QuicTransportServerSession
return crypto_stream_.get();
}
+ // Returns true once the encryption has been established, the client
+ // indication has been received and the origin has been verified. No
+ // application data will be read or written before the connection is ready.
+ // Once the connection becomes ready, this method will never return false.
bool IsSessionReady() const override { return ready_; }
QuicStream* CreateIncomingStream(QuicStreamId id) override;
@@ -59,7 +64,7 @@ class QUIC_EXPORT QuicTransportServerSession
}
protected:
- class ClientIndication : public QuicStream {
+ class QUIC_EXPORT_PRIVATE ClientIndication : public QuicStream {
public:
explicit ClientIndication(QuicTransportServerSession* session);
void OnDataAvailable() override;
@@ -70,7 +75,7 @@ class QUIC_EXPORT QuicTransportServerSession
};
// Utility class for parsing the client indication.
- class ClientIndicationParser {
+ class QUIC_EXPORT_PRIVATE ClientIndicationParser {
public:
ClientIndicationParser(QuicTransportServerSession* session,
QuicStringPiece indication)
@@ -93,6 +98,8 @@ class QUIC_EXPORT QuicTransportServerSession
// https://vasilvv.github.io/webtransport/draft-vvv-webtransport-quic.html#rfc.section.3.2
void ProcessClientIndication(QuicStringPiece indication);
+ virtual void OnIncomingDataStream(QuicTransportStream* /*stream*/) {}
+
std::unique_ptr<QuicCryptoServerStream> crypto_stream_;
bool ready_ = false;
ServerVisitor* visitor_;
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session_test.cc b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session_test.cc
index 818c08db9e4..5e6774810f0 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session_test.cc
@@ -21,6 +21,7 @@
#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h"
namespace quic {
namespace test {
@@ -48,11 +49,6 @@ ParsedQuicVersionVector GetVersions() {
return {ParsedQuicVersion{PROTOCOL_TLS1_3, QUIC_VERSION_99}};
}
-class MockVisitor : public QuicTransportServerSession::ServerVisitor {
- public:
- MOCK_METHOD1(CheckOrigin, bool(url::Origin));
-};
-
class QuicTransportServerSessionTest : public QuicTest {
public:
QuicTransportServerSessionTest()
@@ -76,7 +72,9 @@ class QuicTransportServerSessionTest : public QuicTest {
session_->Initialize();
crypto_stream_ = static_cast<QuicCryptoServerStream*>(
session_->GetMutableCryptoStream());
- crypto_stream_->OnSuccessfulVersionNegotiation(GetVersions()[0]);
+ if (!GetQuicReloadableFlag(quic_version_negotiated_by_default_at_server)) {
+ crypto_stream_->OnSuccessfulVersionNegotiation(GetVersions()[0]);
+ }
}
void Connect() {
@@ -111,7 +109,7 @@ class QuicTransportServerSessionTest : public QuicTest {
QuicCryptoServerConfig crypto_config_;
std::unique_ptr<QuicTransportServerSession> session_;
QuicCompressedCertsCache compressed_certs_cache_;
- testing::StrictMock<MockVisitor> visitor_;
+ testing::StrictMock<MockServerVisitor> visitor_;
QuicCryptoServerStream* crypto_stream_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_session_interface.h b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_session_interface.h
index 971fa5b3c73..cdb3e999790 100644
--- a/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_session_interface.h
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_session_interface.h
@@ -5,11 +5,13 @@
#ifndef QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_SESSION_INTERFACE_H_
#define QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_SESSION_INTERFACE_H_
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+
namespace quic {
// Shared interface between QuicTransportClientSession and
// QuicTransportServerSession.
-class QuicTransportSessionInterface {
+class QUIC_EXPORT_PRIVATE QuicTransportSessionInterface {
public:
virtual ~QuicTransportSessionInterface() {}
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
new file mode 100644
index 00000000000..61f4345d61b
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.cc
@@ -0,0 +1,112 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
+
+#include <sys/types.h>
+
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+
+namespace quic {
+
+QuicTransportStream::QuicTransportStream(
+ QuicStreamId id,
+ QuicSession* session,
+ QuicTransportSessionInterface* session_interface)
+ : QuicStream(id,
+ session,
+ /*is_static=*/false,
+ QuicUtils::GetStreamType(id,
+ session->connection()->perspective(),
+ session->IsIncomingStream(id))),
+ session_interface_(session_interface) {}
+
+size_t QuicTransportStream::Read(char* buffer, size_t buffer_size) {
+ if (!session_interface_->IsSessionReady()) {
+ return 0;
+ }
+
+ iovec iov;
+ iov.iov_base = buffer;
+ iov.iov_len = buffer_size;
+ const size_t result = sequencer()->Readv(&iov, 1);
+ if (sequencer()->IsClosed() && visitor_ != nullptr) {
+ visitor_->OnFinRead();
+ }
+ return result;
+}
+
+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);
+ DCHECK_EQ(bytes_to_read, bytes_read);
+ output->resize(old_size + bytes_read);
+ return bytes_read;
+}
+
+bool QuicTransportStream::Write(QuicStringPiece data) {
+ if (!CanWrite()) {
+ return false;
+ }
+
+ // TODO(vasilvv): use WriteMemSlices()
+ WriteOrBufferData(data, /*fin=*/false, nullptr);
+ return true;
+}
+
+bool QuicTransportStream::SendFin() {
+ if (!CanWrite()) {
+ return false;
+ }
+
+ WriteOrBufferData(QuicStringPiece(), /*fin=*/true, nullptr);
+ return true;
+}
+
+bool QuicTransportStream::CanWrite() const {
+ return session_interface_->IsSessionReady() && CanWriteNewData();
+}
+
+size_t QuicTransportStream::ReadableBytes() const {
+ if (!session_interface_->IsSessionReady()) {
+ return 0;
+ }
+
+ return sequencer()->ReadableBytes();
+}
+
+void QuicTransportStream::OnDataAvailable() {
+ if (sequencer()->IsClosed()) {
+ if (visitor_ != nullptr) {
+ visitor_->OnFinRead();
+ }
+ OnFinRead();
+ return;
+ }
+
+ if (visitor_ == nullptr) {
+ return;
+ }
+ if (ReadableBytes() == 0) {
+ return;
+ }
+ visitor_->OnCanRead();
+}
+
+void QuicTransportStream::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/quic_transport/quic_transport_stream.h b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h
new file mode 100644
index 00000000000..1651a1cb082
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h
@@ -0,0 +1,72 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_STREAM_H_
+#define QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_STREAM_H_
+
+#include <cstddef>
+#include <memory>
+
+#include "net/third_party/quiche/src/quic/core/quic_session.h"
+#include "net/third_party/quiche/src/quic/core/quic_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_macros.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_session_interface.h"
+
+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 {
+ 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);
+ // Reads all available data and appends it to the end of |output|.
+ size_t Read(std::string* output);
+ // Writes |data| into the stream. Returns true on success.
+ QUIC_MUST_USE_RESULT bool Write(QuicStringPiece data);
+ // Sends the FIN on the stream. Returns true on success.
+ QUIC_MUST_USE_RESULT bool SendFin();
+
+ // Indicates whether it is possible to write into stream right now.
+ bool CanWrite() const;
+ // Indicates the number of bytes that can be read from the stream.
+ size_t ReadableBytes() const;
+
+ // 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);
+ }
+
+ protected:
+ // Hide the methods that allow writing data without checking IsSessionReady().
+ using QuicStream::WriteMemSlices;
+ using QuicStream::WriteOrBufferData;
+
+ QuicTransportSessionInterface* session_interface_;
+ std::unique_ptr<Visitor> visitor_ = nullptr;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_STREAM_H_
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
new file mode 100644
index 00000000000..c291b54cf2b
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/quic_transport/quic_transport_stream_test.cc
@@ -0,0 +1,123 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
+
+#include <memory>
+
+#include "net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_session_interface.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h"
+
+namespace quic {
+namespace test {
+namespace {
+
+using testing::Return;
+
+ParsedQuicVersionVector GetVersions() {
+ return {ParsedQuicVersion{PROTOCOL_TLS1_3, QUIC_VERSION_99}};
+}
+
+class MockQuicTransportSessionInterface : public QuicTransportSessionInterface {
+ public:
+ MOCK_CONST_METHOD0(IsSessionReady, bool());
+};
+
+class QuicTransportStreamTest : public QuicTest {
+ public:
+ QuicTransportStreamTest()
+ : connection_(new MockQuicConnection(&helper_,
+ &alarm_factory_,
+ Perspective::IS_CLIENT,
+ GetVersions())),
+ session_(connection_) {
+ session_.Initialize();
+
+ stream_ = new QuicTransportStream(0, &session_, &interface_);
+ session_.ActivateStream(QuicWrapUnique(stream_));
+
+ auto visitor = std::make_unique<MockStreamVisitor>();
+ visitor_ = visitor.get();
+ stream_->set_visitor(std::move(visitor));
+ }
+
+ void ReceiveStreamData(QuicStringPiece data, QuicStreamOffset offset) {
+ QuicStreamFrame frame(0, false, offset, data);
+ stream_->OnStreamFrame(frame);
+ }
+
+ protected:
+ MockAlarmFactory alarm_factory_;
+ MockQuicConnectionHelper helper_;
+
+ MockQuicConnection* connection_; // Owned by |session_|.
+ MockQuicSession session_;
+ MockQuicTransportSessionInterface interface_;
+ QuicTransportStream* stream_; // Owned by |session_|.
+ MockStreamVisitor* visitor_; // Owned by |stream_|.
+};
+
+TEST_F(QuicTransportStreamTest, NotReady) {
+ EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(false));
+ ReceiveStreamData("test", 0);
+ EXPECT_EQ(stream_->ReadableBytes(), 0u);
+ EXPECT_FALSE(stream_->CanWrite());
+}
+
+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);
+}
+
+TEST_F(QuicTransportStreamTest, WriteWhenNotReady) {
+ EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(false));
+ EXPECT_FALSE(stream_->Write("test"));
+}
+
+TEST_F(QuicTransportStreamTest, Ready) {
+ EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(true));
+ ReceiveStreamData("test", 0);
+ EXPECT_EQ(stream_->ReadableBytes(), 4u);
+ EXPECT_TRUE(stream_->CanWrite());
+ EXPECT_TRUE(stream_->Write("test"));
+}
+
+TEST_F(QuicTransportStreamTest, ReceiveData) {
+ EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*visitor_, OnCanRead());
+ ReceiveStreamData("test", 0);
+}
+
+TEST_F(QuicTransportStreamTest, FinReadWithNoDataPending) {
+ EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*visitor_, OnFinRead());
+ QuicStreamFrame frame(0, true, 0, "");
+ stream_->OnStreamFrame(frame);
+}
+
+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);
+}
+
+} // namespace
+} // namespace test
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc b/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc
index 98d65e8d0fe..6716dec2605 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
@@ -209,7 +209,14 @@ class FullChloGenerator {
} // namespace
+std::unique_ptr<QuicCryptoServerConfig> CryptoServerConfigForTesting() {
+ return std::make_unique<QuicCryptoServerConfig>(
+ QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(),
+ ProofSourceForTesting(), KeyExchangeSource::Default());
+}
+
int HandshakeWithFakeServer(QuicConfig* server_quic_config,
+ QuicCryptoServerConfig* crypto_config,
MockQuicConnectionHelper* helper,
MockAlarmFactory* alarm_factory,
PacketSavingConnection* client_conn,
@@ -219,19 +226,19 @@ int HandshakeWithFakeServer(QuicConfig* server_quic_config,
helper, alarm_factory, Perspective::IS_SERVER,
ParsedVersionOfIndex(client_conn->supported_versions(), 0));
- QuicCryptoServerConfig crypto_config(
- QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(),
- ProofSourceForTesting(), KeyExchangeSource::Default());
QuicCompressedCertsCache compressed_certs_cache(
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize);
SetupCryptoServerConfigForTest(
- server_conn->clock(), server_conn->random_generator(), &crypto_config);
+ server_conn->clock(), server_conn->random_generator(), crypto_config);
TestQuicSpdyServerSession server_session(
server_conn, *server_quic_config, client_conn->supported_versions(),
- &crypto_config, &compressed_certs_cache);
- server_session.OnSuccessfulVersionNegotiation(
- client_conn->supported_versions().front());
+ crypto_config, &compressed_certs_cache);
+ server_session.Initialize();
+ if (!GetQuicReloadableFlag(quic_version_negotiated_by_default_at_server)) {
+ server_session.OnSuccessfulVersionNegotiation(
+ client_conn->supported_versions().front());
+ }
EXPECT_CALL(*server_session.helper(),
CanAcceptClientHello(testing::_, testing::_, testing::_,
testing::_, testing::_))
@@ -346,7 +353,8 @@ void CommunicateHandshakeMessages(PacketSavingConnection* client_conn,
MovePackets(client_conn, &client_i, server, server_conn,
Perspective::IS_SERVER);
- if (client->handshake_confirmed() && server->handshake_confirmed()) {
+ if (client->handshake_confirmed() && server->handshake_confirmed() &&
+ server_conn->encrypted_packets_.size() == server_i) {
break;
}
ASSERT_GT(server_conn->encrypted_packets_.size(), server_i);
@@ -782,7 +790,7 @@ std::string GenerateClientNonceHex(const QuicClock* clock,
QuicRandom::GetInstance(), clock, new_config_options);
primary_config.set_primary_time(clock->WallNow().ToUNIXSeconds());
std::unique_ptr<CryptoHandshakeMessage> msg =
- crypto_config->AddConfig(std::move(primary_config), clock->WallNow());
+ crypto_config->AddConfig(primary_config, clock->WallNow());
QuicStringPiece orbit;
CHECK(msg->GetStringPiece(kORBT, &orbit));
std::string nonce;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h b/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h
index 6f87e90494c..327eb673523 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h
@@ -64,8 +64,13 @@ struct FakeClientOptions {
bool only_tls_versions = false;
};
+// Returns a QuicCryptoServerConfig that is in a reasonable configuration to
+// pass into HandshakeWithFakeServer.
+std::unique_ptr<QuicCryptoServerConfig> CryptoServerConfigForTesting();
+
// returns: the number of client hellos that the client sent.
int HandshakeWithFakeServer(QuicConfig* server_quic_config,
+ QuicCryptoServerConfig* crypto_config,
MockQuicConnectionHelper* helper,
MockAlarmFactory* alarm_factory,
PacketSavingConnection* client_conn,
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils_test.cc b/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils_test.cc
index 59a3947393e..656549772fa 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils_test.cc
@@ -128,7 +128,7 @@ TEST_F(CryptoTestUtilsTest, TestGenerateFullCHLO) {
QuicRandom::GetInstance(), &clock, new_config_options);
primary_config.set_primary_time(clock.WallNow().ToUNIXSeconds());
std::unique_ptr<CryptoHandshakeMessage> msg =
- crypto_config.AddConfig(std::move(primary_config), clock.WallNow());
+ crypto_config.AddConfig(primary_config, clock.WallNow());
QuicStringPiece orbit;
ASSERT_TRUE(msg->GetStringPiece(kORBT, &orbit));
std::string nonce;
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.cc b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.cc
index eaf66648cb0..2b835ae2e46 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.h"
#include <algorithm>
#include <cstddef>
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.h b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.h
index 6505b60a1fe..213aded1ba5 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.h
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef QUICHE_QUIC_CORE_QPACK_QPACK_DECODER_TEST_UTILS_H_
-#define QUICHE_QUIC_CORE_QPACK_QPACK_DECODER_TEST_UTILS_H_
+#ifndef QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_DECODER_TEST_UTILS_H_
+#define QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_DECODER_TEST_UTILS_H_
#include <string>
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
namespace quic {
@@ -100,4 +100,4 @@ void QpackDecode(
} // namespace test
} // namespace quic
-#endif // QUICHE_QUIC_CORE_QPACK_QPACK_DECODER_TEST_UTILS_H_
+#endif // QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_DECODER_TEST_UTILS_H_
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/qpack_encoder_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.cc
index 9719bdb9b7a..709686a85e8 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/qpack_encoder_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/third_party/quiche/src/quic/test_tools/qpack_encoder_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h"
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/qpack_encoder_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.h
index 2edf4274611..a824276bc4c 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/qpack_encoder_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_peer.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef QUICHE_QUIC_TEST_TOOLS_QPACK_ENCODER_PEER_H_
-#define QUICHE_QUIC_TEST_TOOLS_QPACK_ENCODER_PEER_H_
+#ifndef QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_ENCODER_PEER_H_
+#define QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_ENCODER_PEER_H_
#include <cstdint>
@@ -27,4 +27,4 @@ class QpackEncoderPeer {
} // namespace quic
-#endif // QUICHE_QUIC_TEST_TOOLS_QPACK_ENCODER_PEER_H_
+#endif // QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_ENCODER_PEER_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test_utils.cc b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.cc
index d91d3d13d5e..dbdd3690d55 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h"
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test_utils.h b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.h
index b1103dae6c3..5fa229256b4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_encoder_test_utils.h
@@ -2,15 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef QUICHE_QUIC_CORE_QPACK_QPACK_ENCODER_TEST_UTILS_H_
-#define QUICHE_QUIC_CORE_QPACK_QPACK_ENCODER_TEST_UTILS_H_
+#ifndef QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_ENCODER_TEST_UTILS_H_
+#define QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_ENCODER_TEST_UTILS_H_
#include <string>
#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
namespace quic {
@@ -37,4 +37,4 @@ class MockDecoderStreamErrorDelegate
} // namespace test
} // namespace quic
-#endif // QUICHE_QUIC_CORE_QPACK_QPACK_ENCODER_TEST_UTILS_H_
+#endif // QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_ENCODER_TEST_UTILS_H_
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/qpack_header_table_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.cc
index bb18731dae7..c554a97d1ce 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/qpack_header_table_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/third_party/quiche/src/quic/test_tools/qpack_header_table_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h"
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/qpack_header_table_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.h
index cbf3f448a28..19e8d0d64e3 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/qpack_header_table_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_header_table_peer.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef QUICHE_QUIC_TEST_TOOLS_QPACK_HEADER_TABLE_PEER_H_
-#define QUICHE_QUIC_TEST_TOOLS_QPACK_HEADER_TABLE_PEER_H_
+#ifndef QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_HEADER_TABLE_PEER_H_
+#define QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_HEADER_TABLE_PEER_H_
#include <cstdint>
@@ -26,4 +26,4 @@ class QpackHeaderTablePeer {
} // namespace quic
-#endif // QUICHE_QUIC_TEST_TOOLS_QPACK_HEADER_TABLE_PEER_H_
+#endif // QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_HEADER_TABLE_PEER_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/offline/qpack_offline_decoder.cc b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.cc
index 379cb6ad835..a5a74aa4cb0 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/offline/qpack_offline_decoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.cc
@@ -2,18 +2,40 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/third_party/quiche/src/quic/core/qpack/offline/qpack_offline_decoder.h"
+// Decoder to test QPACK Offline Interop corpus
+//
+// See https://github.com/quicwg/base-drafts/wiki/QPACK-Offline-Interop for
+// description of test data format.
+//
+// Example usage
+//
+// cd $TEST_DATA
+// git clone https://github.com/qpackers/qifs.git
+// TEST_ENCODED_DATA=$TEST_DATA/qifs/encoded/qpack-06
+// TEST_QIF_DATA=$TEST_DATA/qifs/qifs
+// $BIN/qpack_offline_decoder \
+// $TEST_ENCODED_DATA/f5/fb-req.qifencoded.4096.100.0 \
+// $TEST_QIF_DATA/fb-req.qif
+// $TEST_ENCODED_DATA/h2o/fb-req-hq.out.512.0.1 \
+// $TEST_QIF_DATA/fb-req-hq.qif
+// $TEST_ENCODED_DATA/ls-qpack/fb-resp-hq.out.0.0.0 \
+// $TEST_QIF_DATA/fb-resp-hq.qif
+// $TEST_ENCODED_DATA/proxygen/netbsd.qif.proxygen.out.4096.0.0 \
+// $TEST_QIF_DATA/netbsd.qif
+//
+
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.h"
#include <cstdint>
#include <string>
#include <utility>
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_file_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
namespace quic {
@@ -120,11 +142,11 @@ bool QpackOfflineDecoder::DecodeHeaderBlocksFromFile(
return false;
}
- uint64_t stream_id = QuicEndian::NetToHost64(
+ uint64_t stream_id = quiche::QuicheEndian::NetToHost64(
*reinterpret_cast<const uint64_t*>(input_data.data()));
input_data = input_data.substr(sizeof(uint64_t));
- uint32_t length = QuicEndian::NetToHost32(
+ uint32_t length = quiche::QuicheEndian::NetToHost32(
*reinterpret_cast<const uint32_t*>(input_data.data()));
input_data = input_data.substr(sizeof(uint32_t));
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/offline/qpack_offline_decoder.h b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.h
index c12c49181fa..cb7dedd3aaf 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/offline/qpack_offline_decoder.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.h
@@ -2,15 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef QUICHE_QUIC_CORE_QPACK_OFFLINE_QPACK_OFFLINE_DECODER_H_
-#define QUICHE_QUIC_CORE_QPACK_OFFLINE_QPACK_OFFLINE_DECODER_H_
+#ifndef QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_OFFLINE_DECODER_H_
+#define QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_OFFLINE_DECODER_H_
#include <list>
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_decoder_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
namespace quic {
@@ -71,7 +71,7 @@ class QpackOfflineDecoder : public QpackDecoder::EncoderStreamErrorDelegate {
spdy::SpdyHeaderBlock expected_header_list);
bool encoder_stream_error_detected_;
- NoopQpackStreamSenderDelegate decoder_stream_sender_delegate_;
+ test::NoopQpackStreamSenderDelegate decoder_stream_sender_delegate_;
std::unique_ptr<QpackDecoder> qpack_decoder_;
// Objects necessary for decoding, one list element for each header block.
@@ -83,4 +83,4 @@ class QpackOfflineDecoder : public QpackDecoder::EncoderStreamErrorDelegate {
} // namespace quic
-#endif // QUICHE_QUIC_CORE_QPACK_OFFLINE_QPACK_OFFLINE_DECODER_H_
+#endif // QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_OFFLINE_DECODER_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.cc b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.cc
index 2d4a72e71b0..faaddcb2187 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h"
#include <limits>
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h
index 42fa383a3ea..08cab4e0b2c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_test_utils.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef QUICHE_QUIC_CORE_QPACK_QPACK_TEST_UTILS_H_
-#define QUICHE_QUIC_CORE_QPACK_QPACK_TEST_UTILS_H_
+#ifndef QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_TEST_UTILS_H_
+#define QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_TEST_UTILS_H_
#include <cstddef>
#include <functional>
@@ -34,7 +34,14 @@ class MockQpackStreamSenderDelegate : public QpackStreamSenderDelegate {
MOCK_METHOD1(WriteStreamData, void(QuicStringPiece data));
};
+class NoopQpackStreamSenderDelegate : public QpackStreamSenderDelegate {
+ public:
+ ~NoopQpackStreamSenderDelegate() override = default;
+
+ void WriteStreamData(QuicStringPiece /*data*/) override {}
+};
+
} // namespace test
} // namespace quic
-#endif // QUICHE_QUIC_CORE_QPACK_QPACK_TEST_UTILS_H_
+#endif // QUICHE_QUIC_TEST_TOOLS_QPACK_QPACK_TEST_UTILS_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 02775caf901..7b9264c31b8 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
@@ -9,7 +9,6 @@
#include "net/third_party/quiche/src/quic/core/quic_received_packet_manager.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h"
-#include "net/third_party/quiche/src/quic/test_tools/quic_packet_generator_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h"
namespace quic {
@@ -37,22 +36,9 @@ void QuicConnectionPeer::PopulateStopWaitingFrame(
}
// static
-QuicConnectionVisitorInterface* QuicConnectionPeer::GetVisitor(
- QuicConnection* connection) {
- return connection->visitor_;
-}
-
-// static
QuicPacketCreator* QuicConnectionPeer::GetPacketCreator(
QuicConnection* connection) {
- return QuicPacketGeneratorPeer::GetPacketCreator(
- &connection->packet_generator_);
-}
-
-// static
-QuicPacketGenerator* QuicConnectionPeer::GetPacketGenerator(
- QuicConnection* connection) {
- return &connection->packet_generator_;
+ return &connection->packet_creator_;
}
// static
@@ -226,22 +212,7 @@ QuicConnectionStats* QuicConnectionPeer::GetStats(QuicConnection* connection) {
// static
QuicPacketCount QuicConnectionPeer::GetPacketsBetweenMtuProbes(
QuicConnection* connection) {
- if (connection->mtu_discovery_v2_) {
- return connection->mtu_discoverer_.packets_between_probes();
- }
- return connection->packets_between_mtu_probes_;
-}
-
-// static
-void QuicConnectionPeer::SetPacketsBetweenMtuProbes(QuicConnection* connection,
- QuicPacketCount packets) {
- connection->packets_between_mtu_probes_ = packets;
-}
-
-// static
-void QuicConnectionPeer::SetNextMtuProbeAt(QuicConnection* connection,
- QuicPacketNumber number) {
- connection->next_mtu_probe_at_ = number;
+ return connection->mtu_discoverer_.packets_between_probes();
}
// static
@@ -308,15 +279,13 @@ void QuicConnectionPeer::SetMaxTrackedPackets(
}
// static
-void QuicConnectionPeer::SetSessionDecidesWhatToWrite(
- QuicConnection* connection) {
- connection->sent_packet_manager_.SetSessionDecideWhatToWrite(true);
- connection->packet_generator_.SetCanSetTransmissionType(true);
-}
-
-// static
void QuicConnectionPeer::SetNegotiatedVersion(QuicConnection* connection) {
connection->version_negotiated_ = true;
+ if (connection->perspective() == Perspective::IS_SERVER &&
+ !QuicFramerPeer::infer_packet_header_type_from_version(
+ &connection->framer_)) {
+ connection->framer_.InferPacketHeaderTypeFromVersion();
+ }
}
// static
@@ -364,5 +333,18 @@ void QuicConnectionPeer::SendConnectionClosePacket(QuicConnection* connection,
connection->SendConnectionClosePacket(error, details);
}
+// static
+size_t QuicConnectionPeer::GetNumEncryptionLevels(QuicConnection* connection) {
+ size_t count = 0;
+ for (EncryptionLevel level :
+ {ENCRYPTION_INITIAL, ENCRYPTION_HANDSHAKE, ENCRYPTION_ZERO_RTT,
+ ENCRYPTION_FORWARD_SECURE}) {
+ if (connection->framer_.HasEncrypterOfEncryptionLevel(level)) {
+ ++count;
+ }
+ }
+ return count;
+}
+
} // 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 c5c972f9cc0..b7140ded5ed 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
@@ -20,7 +20,6 @@ class QuicConnectionVisitorInterface;
class QuicEncryptedPacket;
class QuicFramer;
class QuicPacketCreator;
-class QuicPacketGenerator;
class QuicPacketWriter;
class QuicSentPacketManager;
class SendAlgorithmInterface;
@@ -41,12 +40,8 @@ class QuicConnectionPeer {
static void PopulateStopWaitingFrame(QuicConnection* connection,
QuicStopWaitingFrame* stop_waiting);
- static QuicConnectionVisitorInterface* GetVisitor(QuicConnection* connection);
-
static QuicPacketCreator* GetPacketCreator(QuicConnection* connection);
- static QuicPacketGenerator* GetPacketGenerator(QuicConnection* connection);
-
static QuicSentPacketManager* GetSentPacketManager(
QuicConnection* connection);
@@ -107,10 +102,6 @@ class QuicConnectionPeer {
static QuicPacketCount GetPacketsBetweenMtuProbes(QuicConnection* connection);
- static void SetPacketsBetweenMtuProbes(QuicConnection* connection,
- QuicPacketCount packets);
- static void SetNextMtuProbeAt(QuicConnection* connection,
- QuicPacketNumber number);
static void ReInitializeMtuDiscoverer(
QuicConnection* connection,
QuicPacketCount packets_between_probes_base,
@@ -127,7 +118,6 @@ class QuicConnectionPeer {
bool no_stop_waiting_frames);
static void SetMaxTrackedPackets(QuicConnection* connection,
QuicPacketCount max_tracked_packets);
- static void SetSessionDecidesWhatToWrite(QuicConnection* connection);
static void SetNegotiatedVersion(QuicConnection* connection);
static void SetMaxConsecutiveNumPacketsWithNoRetransmittableFrames(
QuicConnection* connection,
@@ -143,6 +133,8 @@ class QuicConnectionPeer {
static void SendConnectionClosePacket(QuicConnection* connection,
QuicErrorCode error,
const std::string& details);
+
+ static size_t GetNumEncryptionLevels(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 2590834891c..b460165d906 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
@@ -11,6 +11,12 @@ namespace quic {
namespace test {
// static
+QuicTimeWaitListManager* QuicDispatcherPeer::GetTimeWaitListManager(
+ QuicDispatcher* dispatcher) {
+ return dispatcher->time_wait_list_manager_.get();
+}
+
+// static
void QuicDispatcherPeer::SetTimeWaitListManager(
QuicDispatcher* dispatcher,
QuicTimeWaitListManager* time_wait_list_manager) {
@@ -77,8 +83,7 @@ const QuicDispatcher::SessionMap& QuicDispatcherPeer::session_map(
void QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(
QuicDispatcher* dispatcher,
size_t num_session_allowed) {
- return dispatcher->set_new_sessions_allowed_per_event_loop(
- num_session_allowed);
+ dispatcher->new_sessions_allowed_per_event_loop_ = num_session_allowed;
}
// 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 a888b4e0967..7cb4c92c5a9 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
@@ -17,6 +17,9 @@ class QuicDispatcherPeer {
public:
QuicDispatcherPeer() = delete;
+ static QuicTimeWaitListManager* GetTimeWaitListManager(
+ QuicDispatcher* dispatcher);
+
static void SetTimeWaitListManager(
QuicDispatcher* dispatcher,
QuicTimeWaitListManager* time_wait_list_manager);
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h
index 661def5493a..d462555a104 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h
@@ -187,6 +187,10 @@ class QuicFramerPeer {
uint64_t current_received_frame_type) {
framer->current_received_frame_type_ = current_received_frame_type;
}
+
+ static bool infer_packet_header_type_from_version(QuicFramer* framer) {
+ return framer->infer_packet_header_type_from_version_;
+ }
};
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.cc
index d4e5598ffa0..7c8db91da7f 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.cc
@@ -4,6 +4,7 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_frame.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_creator.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
@@ -63,6 +64,11 @@ void QuicPacketCreatorPeer::SetPacketNumber(QuicPacketCreator* creator,
creator->packet_.packet_number = QuicPacketNumber(s);
}
+void QuicPacketCreatorPeer::SetPacketNumber(QuicPacketCreator* creator,
+ QuicPacketNumber num) {
+ creator->packet_.packet_number = num;
+}
+
// static
void QuicPacketCreatorPeer::ClearPacketNumber(QuicPacketCreator* creator) {
creator->packet_.packet_number.Clear();
@@ -102,14 +108,13 @@ SerializedPacket QuicPacketCreatorPeer::SerializeAllFrames(
DCHECK(creator->queued_frames_.empty());
DCHECK(!frames.empty());
for (const QuicFrame& frame : frames) {
- bool success = creator->AddFrame(frame, false, NOT_RETRANSMISSION);
+ bool success = creator->AddFrame(frame, NOT_RETRANSMISSION);
DCHECK(success);
}
creator->SerializePacket(buffer, buffer_len);
- SerializedPacket packet = creator->packet_;
+ SerializedPacket packet = std::move(creator->packet_);
// The caller takes ownership of the QuicEncryptedPacket.
creator->packet_.encrypted_buffer = nullptr;
- DCHECK(packet.retransmittable_frames.empty());
return packet;
}
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h
index e040090f6dd..88587a212b5 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h
@@ -31,6 +31,7 @@ class QuicPacketCreatorPeer {
static QuicVariableLengthIntegerLength GetLengthLength(
QuicPacketCreator* creator);
static void SetPacketNumber(QuicPacketCreator* creator, uint64_t s);
+ static void SetPacketNumber(QuicPacketCreator* creator, QuicPacketNumber num);
static void ClearPacketNumber(QuicPacketCreator* creator);
static void FillPacketHeader(QuicPacketCreator* creator,
QuicPacketHeader* header);
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_generator_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_generator_peer.cc
deleted file mode 100644
index 91a875282c2..00000000000
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_generator_peer.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/third_party/quiche/src/quic/test_tools/quic_packet_generator_peer.h"
-
-#include "net/third_party/quiche/src/quic/core/quic_packet_creator.h"
-#include "net/third_party/quiche/src/quic/core/quic_packet_generator.h"
-
-namespace quic {
-namespace test {
-
-// static
-QuicPacketCreator* QuicPacketGeneratorPeer::GetPacketCreator(
- QuicPacketGenerator* generator) {
- return &generator->packet_creator_;
-}
-
-} // namespace test
-} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_generator_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_generator_peer.h
deleted file mode 100644
index 6941b089d23..00000000000
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_packet_generator_peer.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2014 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_PACKET_GENERATOR_PEER_H_
-#define QUICHE_QUIC_TEST_TOOLS_QUIC_PACKET_GENERATOR_PEER_H_
-
-#include "net/third_party/quiche/src/quic/core/quic_packets.h"
-
-namespace quic {
-
-class QuicPacketCreator;
-class QuicPacketGenerator;
-
-namespace test {
-
-class QuicPacketGeneratorPeer {
- public:
- QuicPacketGeneratorPeer() = delete;
-
- static QuicPacketCreator* GetPacketCreator(QuicPacketGenerator* generator);
-};
-
-} // namespace test
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_TEST_TOOLS_QUIC_PACKET_GENERATOR_PEER_H_
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.cc
index b680f66d815..cd8297a961e 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.cc
@@ -86,18 +86,9 @@ bool QuicSentPacketManagerPeer::IsRetransmission(
if (!HasRetransmittableFrames(sent_packet_manager, packet_number)) {
return false;
}
- if (sent_packet_manager->session_decides_what_to_write()) {
- return sent_packet_manager->unacked_packets_
- .GetTransmissionInfo(QuicPacketNumber(packet_number))
- .transmission_type != NOT_RETRANSMISSION;
- }
- for (auto transmission_info : sent_packet_manager->unacked_packets_) {
- if (transmission_info.retransmission.IsInitialized() &&
- transmission_info.retransmission == QuicPacketNumber(packet_number)) {
- return true;
- }
- }
- return false;
+ return sent_packet_manager->unacked_packets_
+ .GetTransmissionInfo(QuicPacketNumber(packet_number))
+ .transmission_type != NOT_RETRANSMISSION;
}
// static
@@ -223,5 +214,12 @@ bool QuicSentPacketManagerPeer::AdaptiveReorderingThresholdEnabled(
.use_adaptive_reordering_threshold();
}
+// static
+bool QuicSentPacketManagerPeer::AdaptiveTimeThresholdEnabled(
+ QuicSentPacketManager* sent_packet_manager) {
+ return sent_packet_manager->uber_loss_algorithm_.general_loss_algorithms_[0]
+ .use_adaptive_time_threshold();
+}
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h
index 6be8b46308f..3927189ee3f 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h
@@ -98,6 +98,9 @@ class QuicSentPacketManagerPeer {
static bool AdaptiveReorderingThresholdEnabled(
QuicSentPacketManager* sent_packet_manager);
+
+ static bool AdaptiveTimeThresholdEnabled(
+ QuicSentPacketManager* sent_packet_manager);
};
} // namespace test
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 001f1ca2b87..f9e785d2c98 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
@@ -226,15 +226,6 @@ QuicStreamIdManager* QuicSessionPeer::v99_unidirectional_stream_id_manager(
}
// static
-void QuicSessionPeer::SendRstStreamInner(QuicSession* session,
- QuicStreamId id,
- QuicRstStreamErrorCode error,
- QuicStreamOffset bytes_written,
- bool close_write_side_only) {
- session->SendRstStreamInner(id, error, bytes_written, close_write_side_only);
-}
-
-// static
PendingStream* QuicSessionPeer::GetPendingStream(QuicSession* session,
QuicStreamId stream_id) {
auto it = session->pending_stream_map_.find(stream_id);
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.h
index eed3bddcf88..446cd67b176 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.h
@@ -79,11 +79,6 @@ class QuicSessionPeer {
QuicSession* session);
static QuicStreamIdManager* v99_unidirectional_stream_id_manager(
QuicSession* session);
- static void SendRstStreamInner(QuicSession* session,
- QuicStreamId id,
- QuicRstStreamErrorCode error,
- QuicStreamOffset bytes_written,
- bool close_write_side_only);
static PendingStream* GetPendingStream(QuicSession* session,
QuicStreamId stream_id);
static void set_is_configured(QuicSession* session, bool value);
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_peer.cc
index d501debb7e3..42961984527 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_peer.cc
@@ -29,7 +29,7 @@ void QuicStreamPeer::SetStreamBytesWritten(
// static
bool QuicStreamPeer::read_side_closed(QuicStream* stream) {
- return stream->read_side_closed();
+ return stream->read_side_closed_;
}
// static
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h
index f61cb0049a5..3adb173b91d 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h
@@ -20,6 +20,10 @@ class QuicStreamSendBufferPeer {
QuicStreamSendBuffer* send_buffer);
static QuicByteCount TotalLength(QuicStreamSendBuffer* send_buffer);
+
+ static int32_t write_index(QuicStreamSendBuffer* send_buffer) {
+ return send_buffer->write_index_;
+ }
};
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_sequencer_buffer_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_sequencer_buffer_peer.cc
index 36d2b04ee60..b3bf224df4e 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_sequencer_buffer_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_sequencer_buffer_peer.cc
@@ -7,6 +7,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
typedef quic::QuicStreamSequencerBuffer::BufferBlock BufferBlock;
@@ -28,8 +29,8 @@ size_t QuicStreamSequencerBufferPeer::Read(char* dest_buffer, size_t size) {
dest.iov_base = dest_buffer, dest.iov_len = size;
size_t bytes_read;
std::string error_details;
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->Readv(&dest, 1, &bytes_read, &error_details));
+ EXPECT_THAT(buffer_->Readv(&dest, 1, &bytes_read, &error_details),
+ IsQuicNoError());
return bytes_read;
}
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 237d9f66d8f..ca5e95ab0f6 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
@@ -382,7 +382,9 @@ ssize_t QuicTestClient::SendRequestAndRstTogether(const std::string& uri) {
QuicStreamId stream_id = GetNthClientInitiatedBidirectionalStreamId(
session->transport_version(), 0);
- session->SendRstStream(stream_id, QUIC_STREAM_CANCELLED, 0);
+ QuicStream* stream = session->GetOrCreateStream(stream_id);
+ session->SendRstStream(stream_id, QUIC_STREAM_CANCELLED,
+ stream->stream_bytes_written());
return ret;
}
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 a893830102e..81b54d47260 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
@@ -230,12 +230,20 @@ ImmediateGoAwaySession::ImmediateGoAwaySession(
quic_simple_server_backend) {}
void ImmediateGoAwaySession::OnStreamFrame(const QuicStreamFrame& frame) {
- SendGoAway(QUIC_PEER_GOING_AWAY, "");
+ if (VersionUsesHttp3(transport_version())) {
+ SendHttp3GoAway();
+ } else {
+ SendGoAway(QUIC_PEER_GOING_AWAY, "");
+ }
QuicSimpleServerSession::OnStreamFrame(frame);
}
void ImmediateGoAwaySession::OnCryptoFrame(const QuicCryptoFrame& frame) {
- SendGoAway(QUIC_PEER_GOING_AWAY, "");
+ // In IETF QUIC, GOAWAY lives up in HTTP/3 layer. Even if it's a immediate
+ // goaway session, goaway shouldn't be sent when crypto frame is received.
+ if (!VersionUsesHttp3(transport_version())) {
+ SendGoAway(QUIC_PEER_GOING_AWAY, "");
+ }
QuicSimpleServerSession::OnCryptoFrame(frame);
}
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 ff0239213a2..4b10826660b 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
@@ -22,12 +22,12 @@
#include "net/third_party/quiche/src/quic/core/quic_packet_creator.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
#include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h"
using testing::_;
@@ -44,14 +44,14 @@ QuicConnectionId TestConnectionId() {
QuicConnectionId TestConnectionId(uint64_t connection_number) {
const uint64_t connection_id64_net =
- QuicEndian::HostToNet64(connection_number);
+ quiche::QuicheEndian::HostToNet64(connection_number);
return QuicConnectionId(reinterpret_cast<const char*>(&connection_id64_net),
sizeof(connection_id64_net));
}
QuicConnectionId TestConnectionIdNineBytesLong(uint64_t connection_number) {
const uint64_t connection_number_net =
- QuicEndian::HostToNet64(connection_number);
+ quiche::QuicheEndian::HostToNet64(connection_number);
char connection_id_bytes[9] = {};
static_assert(
sizeof(connection_id_bytes) == 1 + sizeof(connection_number_net),
@@ -67,7 +67,7 @@ uint64_t TestConnectionIdToUInt64(QuicConnectionId connection_id) {
memcpy(&connection_id64_net, connection_id.data(),
std::min<size_t>(static_cast<size_t>(connection_id.length()),
sizeof(connection_id64_net)));
- return QuicEndian::NetToHost64(connection_id64_net);
+ return quiche::QuicheEndian::NetToHost64(connection_id64_net);
}
QuicAckFrame InitAckFrame(const std::vector<QuicAckBlock>& ack_blocks) {
@@ -531,7 +531,7 @@ void PacketSavingConnection::SendOrQueuePacket(SerializedPacket* packet) {
// Transfer ownership of the packet to the SentPacketManager and the
// ack notifier to the AckNotifierManager.
QuicConnectionPeer::GetSentPacketManager(this)->OnPacketSent(
- packet, QuicPacketNumber(), clock_.ApproximateNow(), NOT_RETRANSMISSION,
+ packet, clock_.ApproximateNow(), NOT_RETRANSMISSION,
HAS_RETRANSMITTABLE_DATA);
}
@@ -576,7 +576,7 @@ QuicConsumedData MockQuicSession::ConsumeData(QuicStream* stream,
StreamSendingState state) {
if (write_length > 0) {
auto buf = std::make_unique<char[]>(write_length);
- QuicDataWriter writer(write_length, buf.get(), HOST_BYTE_ORDER);
+ QuicDataWriter writer(write_length, buf.get(), quiche::HOST_BYTE_ORDER);
stream->WriteStreamData(offset, write_length, &writer);
} else {
DCHECK(state != NO_FIN);
@@ -652,7 +652,6 @@ TestQuicSpdyServerSession::TestQuicSpdyServerSession(
&helper_,
crypto_config,
compressed_certs_cache) {
- Initialize();
ON_CALL(helper_, CanAcceptClientHello(_, _, _, _, _))
.WillByDefault(testing::Return(true));
}
@@ -992,7 +991,7 @@ QuicEncryptedPacket* ConstructMisFramedEncryptedPacket(
QuicConnectionIdIncluded destination_connection_id_included,
QuicConnectionIdIncluded source_connection_id_included,
QuicPacketNumberLength packet_number_length,
- ParsedQuicVersionVector* versions,
+ ParsedQuicVersion version,
Perspective perspective) {
QuicPacketHeader header;
header.destination_connection_id = destination_connection_id;
@@ -1004,7 +1003,7 @@ QuicEncryptedPacket* ConstructMisFramedEncryptedPacket(
header.reset_flag = reset_flag;
header.packet_number_length = packet_number_length;
header.packet_number = QuicPacketNumber(packet_number);
- if (QuicVersionHasLongHeaderLengths((*versions)[0].transport_version) &&
+ if (QuicVersionHasLongHeaderLengths(version.transport_version) &&
version_flag) {
header.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1;
header.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2;
@@ -1012,10 +1011,7 @@ QuicEncryptedPacket* ConstructMisFramedEncryptedPacket(
QuicFrame frame(QuicStreamFrame(1, false, 0, QuicStringPiece(data)));
QuicFrames frames;
frames.push_back(frame);
- ParsedQuicVersion version =
- (versions != nullptr ? *versions : AllSupportedVersions())[0];
- QuicFramer framer(versions != nullptr ? *versions : AllSupportedVersions(),
- QuicTime::Zero(), perspective,
+ QuicFramer framer({version}, QuicTime::Zero(), perspective,
kQuicDefaultConnectionIdLength);
framer.SetInitialObfuscators(destination_connection_id);
EncryptionLevel level =
@@ -1184,6 +1180,7 @@ void CreateServerSessionForTest(
*server_session = new TestQuicSpdyServerSession(
*server_connection, DefaultQuicConfig(), supported_versions,
server_crypto_config, compressed_certs_cache);
+ (*server_session)->Initialize();
// We advance the clock initially because the default time is zero and the
// strike register worries that we've just overflowed a uint32_t time.
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 be6e84d7746..7919ef30299 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
@@ -23,6 +23,7 @@
#include "net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h"
#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_storage.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
@@ -161,7 +162,7 @@ QuicEncryptedPacket* ConstructMisFramedEncryptedPacket(
QuicConnectionIdIncluded destination_connection_id_included,
QuicConnectionIdIncluded source_connection_id_included,
QuicPacketNumberLength packet_number_length,
- ParsedQuicVersionVector* versions,
+ ParsedQuicVersion version,
Perspective perspective);
void CompareCharArraysWithHexError(const std::string& description,
@@ -412,7 +413,8 @@ class MockQuicConnectionVisitor : public QuicConnectionVisitorInterface {
MOCK_METHOD1(OnMaxStreamsFrame, bool(const QuicMaxStreamsFrame& frame));
MOCK_METHOD1(OnStreamsBlockedFrame,
bool(const QuicStreamsBlockedFrame& frame));
- MOCK_METHOD1(OnStopSendingFrame, bool(const QuicStopSendingFrame& frame));
+ MOCK_METHOD1(OnStopSendingFrame, void(const QuicStopSendingFrame& frame));
+ MOCK_METHOD1(OnPacketDecrypted, void(EncryptionLevel));
};
class MockQuicConnectionHelper : public QuicConnectionHelperInterface {
@@ -533,7 +535,8 @@ class MockQuicConnection : public QuicConnection {
MOCK_METHOD2(OnStreamReset, void(QuicStreamId, QuicRstStreamErrorCode));
MOCK_METHOD1(SendControlFrame, bool(const QuicFrame& frame));
- MOCK_METHOD2(SendMessage, MessageStatus(QuicMessageId, QuicMemSliceSpan));
+ MOCK_METHOD3(SendMessage,
+ MessageStatus(QuicMessageId, QuicMemSliceSpan, bool));
MOCK_METHOD3(OnConnectionClosed,
void(QuicErrorCode error,
const std::string& error_details,
@@ -666,6 +669,12 @@ class MockQuicSession : public QuicSession {
QuicStreamOffset offset,
StreamSendingState state);
+ void ReallySendRstStream(QuicStreamId id,
+ QuicRstStreamErrorCode error,
+ QuicStreamOffset bytes_written) {
+ QuicSession::SendRstStream(id, error, bytes_written);
+ }
+
private:
std::unique_ptr<QuicCryptoStream> crypto_stream_;
};
@@ -681,6 +690,7 @@ class MockQuicCryptoStream : public QuicCryptoStream {
const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
const override;
CryptoMessageParser* crypto_message_parser() override;
+ void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
private:
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
@@ -947,7 +957,9 @@ class MockSendAlgorithm : public SendAlgorithmInterface {
MOCK_CONST_METHOD0(GetCongestionControlType, CongestionControlType());
MOCK_METHOD3(AdjustNetworkParameters,
void(QuicBandwidth, QuicTime::Delta, bool));
+ MOCK_METHOD1(AdjustNetworkParameters, void(const NetworkParams&));
MOCK_METHOD1(OnApplicationLimited, void(QuicByteCount));
+ MOCK_CONST_METHOD1(PopulateConnectionStats, void(QuicConnectionStats*));
};
class MockLossAlgorithm : public LossDetectionInterface {
@@ -966,11 +978,6 @@ class MockLossAlgorithm : public LossDetectionInterface {
const AckedPacketVector& packets_acked,
LostPacketVector* packets_lost));
MOCK_CONST_METHOD0(GetLossTimeout, QuicTime());
- MOCK_METHOD4(SpuriousRetransmitDetected,
- void(const QuicUnackedPacketMap&,
- QuicTime,
- const RttStats&,
- QuicPacketNumber));
MOCK_METHOD5(SpuriousLossDetected,
void(const QuicUnackedPacketMap&,
const RttStats&,
@@ -1014,11 +1021,8 @@ class MockQuicConnectionDebugVisitor : public QuicConnectionDebugVisitor {
MOCK_METHOD1(OnFrameAddedToPacket, void(const QuicFrame&));
- MOCK_METHOD4(OnPacketSent,
- void(const SerializedPacket&,
- QuicPacketNumber,
- TransmissionType,
- QuicTime));
+ MOCK_METHOD3(OnPacketSent,
+ void(const SerializedPacket&, TransmissionType, QuicTime));
MOCK_METHOD0(OnPingSent, void());
@@ -1195,8 +1199,6 @@ void ExpectApproxEq(T expected, T actual, float relative_margin) {
template <typename T>
QuicHeaderList AsHeaderList(const T& container) {
QuicHeaderList l;
- // No need to enforce header list size limits again in this handler.
- l.set_max_header_list_size(UINT_MAX);
l.OnHeaderBlockStart();
size_t total_size = 0;
for (auto p : container) {
@@ -1254,6 +1256,46 @@ MATCHER_P2(InRange, min, max, "") {
return arg >= min && arg <= max;
}
+// A GMock matcher that prints expected and actual QuicErrorCode strings
+// upon failure. Example usage:
+// EXPECT_THAT(stream_->connection_error()), IsError(QUIC_INTERNAL_ERROR));
+MATCHER_P(IsError,
+ expected,
+ QuicStrCat(negation ? "isn't equal to " : "is equal to ",
+ QuicErrorCodeToString(expected))) {
+ *result_listener << QuicErrorCodeToString(arg);
+ return arg == expected;
+}
+
+// Shorthand for IsError(QUIC_NO_ERROR).
+// Example usage: EXPECT_THAT(stream_->connection_error(), IsQuicNoError());
+MATCHER(IsQuicNoError,
+ QuicStrCat(negation ? "isn't equal to " : "is equal to ",
+ QuicErrorCodeToString(QUIC_NO_ERROR))) {
+ *result_listener << QuicErrorCodeToString(arg);
+ return arg == QUIC_NO_ERROR;
+}
+
+// A GMock matcher that prints expected and actual QuicRstStreamErrorCode
+// strings upon failure. Example usage:
+// EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_INTERNAL_ERROR));
+MATCHER_P(IsStreamError,
+ expected,
+ QuicStrCat(negation ? "isn't equal to " : "is equal to ",
+ QuicRstStreamErrorCodeToString(expected))) {
+ *result_listener << QuicRstStreamErrorCodeToString(arg);
+ return arg == expected;
+}
+
+// Shorthand for IsStreamError(QUIC_STREAM_NO_ERROR). Example usage:
+// EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
+MATCHER(IsQuicStreamNoError,
+ QuicStrCat(negation ? "isn't equal to " : "is equal to ",
+ QuicRstStreamErrorCodeToString(QUIC_STREAM_NO_ERROR))) {
+ *result_listener << QuicRstStreamErrorCodeToString(arg);
+ return arg == QUIC_STREAM_NO_ERROR;
+}
+
} // 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
new file mode 100644
index 00000000000..c6a8b46496e
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_TEST_TOOLS_QUIC_TRANSPORT_TEST_TOOLS_H_
+#define QUICHE_QUIC_TEST_TOOLS_QUIC_TRANSPORT_TEST_TOOLS_H_
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_client_session.h"
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h"
+
+namespace quic {
+namespace test {
+
+class MockClientVisitor : public QuicTransportClientSession::ClientVisitor {
+ public:
+ MOCK_METHOD0(OnIncomingBidirectionalStreamAvailable, void());
+ MOCK_METHOD0(OnIncomingUnidirectionalStreamAvailable, void());
+};
+
+class MockServerVisitor : public QuicTransportServerSession::ServerVisitor {
+ public:
+ MOCK_METHOD1(CheckOrigin, bool(url::Origin));
+};
+
+class MockStreamVisitor : public QuicTransportStream::Visitor {
+ public:
+ MOCK_METHOD0(OnCanRead, void());
+ MOCK_METHOD0(OnFinRead, void());
+ MOCK_METHOD0(OnCanWrite, void());
+};
+
+} // namespace test
+} // namespace quic
+
+#endif // QUICHE_QUIC_TEST_TOOLS_QUIC_TRANSPORT_TEST_TOOLS_H_
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 be03aa1c869..588f3b66d43 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
@@ -59,7 +59,9 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
return true;
}
- void OnCoalescedPacket(const QuicEncryptedPacket& /*packet*/) override {}
+ void OnCoalescedPacket(const QuicEncryptedPacket& packet) override {
+ coalesced_packet_ = packet.Clone();
+ }
void OnUndecryptablePacket(const QuicEncryptedPacket& /*packet*/,
EncryptionLevel /*decryption_level*/,
@@ -253,6 +255,9 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
return version_negotiation_packet_.get();
}
EncryptionLevel last_decrypted_level() const { return last_decrypted_level_; }
+ const QuicEncryptedPacket* coalesced_packet() const {
+ return coalesced_packet_.get();
+ }
private:
QuicErrorCode error_;
@@ -284,6 +289,7 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
std::vector<std::unique_ptr<std::string>> stream_data_;
std::vector<std::unique_ptr<std::string>> crypto_data_;
EncryptionLevel last_decrypted_level_;
+ std::unique_ptr<QuicEncryptedPacket> coalesced_packet_;
};
SimpleQuicFramer::SimpleQuicFramer()
@@ -404,5 +410,9 @@ const std::vector<QuicPaddingFrame>& SimpleQuicFramer::padding_frames() const {
return visitor_->padding_frames();
}
+const QuicEncryptedPacket* SimpleQuicFramer::coalesced_packet() const {
+ return visitor_->coalesced_packet();
+}
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simple_quic_framer.h b/chromium/net/third_party/quiche/src/quic/test_tools/simple_quic_framer.h
index a254ce523e9..3e063d07334 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simple_quic_framer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simple_quic_framer.h
@@ -50,6 +50,7 @@ class SimpleQuicFramer {
const std::vector<QuicPaddingFrame>& padding_frames() const;
const QuicVersionNegotiationPacket* version_negotiation_packet() const;
EncryptionLevel last_decrypted_level() const;
+ const QuicEncryptedPacket* coalesced_packet() const;
QuicFramer* framer();
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_cache.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_cache.cc
new file mode 100644
index 00000000000..7787fbeb059
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_cache.cc
@@ -0,0 +1,28 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/test_tools/simple_session_cache.h"
+
+namespace quic {
+namespace test {
+
+void SimpleSessionCache::Insert(const QuicServerId& server_id,
+ std::unique_ptr<QuicResumptionState> state) {
+ cache_entries_.insert(std::make_pair(server_id, std::move(state)));
+}
+
+std::unique_ptr<QuicResumptionState> SimpleSessionCache::Lookup(
+ const QuicServerId& server_id,
+ const SSL_CTX* /*ctx*/) {
+ auto it = cache_entries_.find(server_id);
+ if (it == cache_entries_.end()) {
+ return nullptr;
+ }
+ std::unique_ptr<QuicResumptionState> state = std::move(it->second);
+ cache_entries_.erase(it);
+ return state;
+}
+
+} // namespace test
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_cache.h b/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_cache.h
new file mode 100644
index 00000000000..40a6946dfde
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_cache.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_TEST_TOOLS_SIMPLE_SESSION_CACHE_H_
+#define QUICHE_QUIC_TEST_TOOLS_SIMPLE_SESSION_CACHE_H_
+
+#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h"
+
+namespace quic {
+namespace test {
+
+// SimpleSessionCache provides a simple implementation of SessionCache that
+// stores only one QuicResumptionState per QuicServerId. No limit is placed on
+// the total number of entries in the cache. When Lookup is called, if a cache
+// entry exists for the provided QuicServerId, the entry will be removed from
+// the cached when it is returned.
+class SimpleSessionCache : public SessionCache {
+ public:
+ SimpleSessionCache() = default;
+ ~SimpleSessionCache() override = default;
+
+ void Insert(const QuicServerId& server_id,
+ std::unique_ptr<QuicResumptionState> state) override;
+ std::unique_ptr<QuicResumptionState> Lookup(const QuicServerId& server_id,
+ const SSL_CTX* ctx) override;
+
+ private:
+ std::map<QuicServerId, std::unique_ptr<QuicResumptionState>> cache_entries_;
+};
+
+} // namespace test
+} // namespace quic
+
+#endif // QUICHE_QUIC_TEST_TOOLS_SIMPLE_SESSION_CACHE_H_
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 72a23d73178..9e67c899f51 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
@@ -46,7 +46,6 @@ QuicConsumedData SimpleSessionNotifier::WriteOrBufferData(
StreamState& stream_state = stream_map_.find(id)->second;
const bool had_buffered_data =
HasBufferedStreamData() || HasBufferedControlFrames();
- QuicConsumedData total_consumed(0, false);
QuicStreamOffset offset = stream_state.bytes_sent;
QUIC_DVLOG(1) << "WriteOrBuffer stream_id: " << id << " [" << offset << ", "
<< offset + data_length << "), fin: " << (state != NO_FIN);
@@ -127,8 +126,13 @@ void SimpleSessionNotifier::WriteOrBufferPing() {
}
void SimpleSessionNotifier::NeuterUnencryptedData() {
- // TODO(nharper): Handle CRYPTO frame case.
if (QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ for (const auto& interval : crypto_bytes_transferred_[ENCRYPTION_INITIAL]) {
+ QuicCryptoFrame crypto_frame(ENCRYPTION_INITIAL, interval.min(),
+ interval.max() - interval.min());
+ OnFrameAcked(QuicFrame(&crypto_frame), QuicTime::Delta::Zero(),
+ QuicTime::Zero());
+ }
return;
}
for (const auto& interval : crypto_bytes_transferred_[ENCRYPTION_INITIAL]) {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier_test.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier_test.cc
index 93f11aa387d..4dc48a7c1d5 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier_test.cc
@@ -42,7 +42,7 @@ class SimpleSessionNotifierTest : public QuicTest {
: connection_(&helper_, &alarm_factory_, Perspective::IS_CLIENT),
notifier_(&connection_) {
connection_.set_visitor(&visitor_);
- QuicConnectionPeer::SetSessionDecidesWhatToWrite(&connection_);
+ connection_.SetSessionNotifier(&notifier_);
EXPECT_FALSE(notifier_.WillingToWrite());
EXPECT_EQ(0u, notifier_.StreamBytesSent());
EXPECT_FALSE(notifier_.HasBufferedStreamData());
@@ -135,6 +135,8 @@ TEST_F(SimpleSessionNotifierTest, WriteOrBufferPing) {
TEST_F(SimpleSessionNotifierTest, NeuterUnencryptedData) {
if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ // This test writes crypto data through crypto streams. It won't work when
+ // crypto frames are used instead.
return;
}
InSequence s;
@@ -175,6 +177,8 @@ TEST_F(SimpleSessionNotifierTest, NeuterUnencryptedData) {
TEST_F(SimpleSessionNotifierTest, OnCanWrite) {
if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ // This test writes crypto data through crypto streams. It won't work when
+ // crypto frames are used instead.
return;
}
InSequence s;
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 bd01c43d252..9f504359dbf 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
@@ -4,6 +4,7 @@
#include "net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h"
+#include <memory>
#include <utility>
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
@@ -23,89 +24,41 @@ const QuicStreamId kDataStream = 3;
const QuicByteCount kWriteChunkSize = 128 * 1024;
const char kStreamDataContents = 'Q';
-// Takes a SHA-1 hash of the name and converts it into five 32-bit integers.
-static std::vector<uint32_t> HashNameIntoFive32BitIntegers(std::string name) {
- const std::string hash = test::Sha1Hash(name);
-
- std::vector<uint32_t> output;
- uint32_t current_number = 0;
- for (size_t i = 0; i < hash.size(); i++) {
- current_number = (current_number << 8) + hash[i];
- if (i % 4 == 3) {
- output.push_back(i);
- current_number = 0;
- }
- }
-
- return output;
-}
-
-QuicSocketAddress GetAddressFromName(std::string name) {
- const std::vector<uint32_t> hash = HashNameIntoFive32BitIntegers(name);
-
- // Generate a random port between 1025 and 65535.
- const uint16_t port = 1025 + hash[0] % (65535 - 1025 + 1);
-
- // Generate a random 10.x.x.x address, where x is between 1 and 254.
- std::string ip_address{"\xa\0\0\0", 4};
- for (size_t i = 1; i < 4; i++) {
- ip_address[i] = 1 + hash[i] % 254;
- }
- QuicIpAddress host;
- host.FromPackedString(ip_address.c_str(), ip_address.length());
- return QuicSocketAddress(host, port);
-}
-
QuicEndpoint::QuicEndpoint(Simulator* simulator,
std::string name,
std::string peer_name,
Perspective perspective,
QuicConnectionId connection_id)
- : Endpoint(simulator, name),
- peer_name_(peer_name),
- writer_(this),
- nic_tx_queue_(simulator,
- QuicStringPrintf("%s (TX Queue)", name.c_str()),
- kMaxOutgoingPacketSize * kTxQueueSize),
- connection_(connection_id,
- GetAddressFromName(peer_name),
- simulator,
- simulator->GetAlarmFactory(),
- &writer_,
- false,
- perspective,
- ParsedVersionOfIndex(CurrentSupportedVersions(), 0)),
+ : QuicEndpointBase(simulator, name, peer_name),
bytes_to_transfer_(0),
bytes_transferred_(0),
- write_blocked_count_(0),
wrong_data_received_(false),
- drop_next_packet_(false),
notifier_(nullptr) {
- nic_tx_queue_.set_listener_interface(this);
-
- connection_.SetSelfAddress(GetAddressFromName(name));
- connection_.set_visitor(this);
- connection_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
- std::make_unique<NullEncrypter>(perspective));
- connection_.SetEncrypter(ENCRYPTION_INITIAL, nullptr);
- if (connection_.version().KnowsWhichDecrypterToUse()) {
- connection_.InstallDecrypter(ENCRYPTION_FORWARD_SECURE,
- std::make_unique<NullDecrypter>(perspective));
- connection_.RemoveDecrypter(ENCRYPTION_INITIAL);
+ connection_ = std::make_unique<QuicConnection>(
+ connection_id, GetAddressFromName(peer_name), simulator,
+ simulator->GetAlarmFactory(), &writer_, false, perspective,
+ ParsedVersionOfIndex(CurrentSupportedVersions(), 0));
+ connection_->SetSelfAddress(GetAddressFromName(name));
+ connection_->set_visitor(this);
+ connection_->SetEncrypter(ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<NullEncrypter>(perspective));
+ connection_->SetEncrypter(ENCRYPTION_INITIAL, nullptr);
+ if (connection_->version().KnowsWhichDecrypterToUse()) {
+ connection_->InstallDecrypter(ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<NullDecrypter>(perspective));
+ connection_->RemoveDecrypter(ENCRYPTION_INITIAL);
} else {
- connection_.SetDecrypter(ENCRYPTION_FORWARD_SECURE,
- std::make_unique<NullDecrypter>(perspective));
+ connection_->SetDecrypter(ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<NullDecrypter>(perspective));
}
- connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
if (perspective == Perspective::IS_SERVER) {
// Skip version negotiation.
- test::QuicConnectionPeer::SetNegotiatedVersion(&connection_);
- }
- connection_.SetDataProducer(&producer_);
- connection_.SetSessionNotifier(this);
- if (connection_.session_decides_what_to_write()) {
- notifier_ = std::make_unique<test::SimpleSessionNotifier>(&connection_);
+ test::QuicConnectionPeer::SetNegotiatedVersion(connection_.get());
}
+ connection_->SetDataProducer(&producer_);
+ connection_->SetSessionNotifier(this);
+ notifier_ = std::make_unique<test::SimpleSessionNotifier>(connection_.get());
// Configure the connection as if it received a handshake. This is important
// primarily because
@@ -122,19 +75,7 @@ QuicEndpoint::QuicEndpoint(Simulator* simulator,
peer_hello, perspective == Perspective::IS_CLIENT ? SERVER : CLIENT,
&error);
DCHECK_EQ(error_code, QUIC_NO_ERROR) << "Configuration failed: " << error;
- connection_.SetFromConfig(config);
-}
-
-QuicEndpoint::~QuicEndpoint() {
- if (trace_visitor_ != nullptr) {
- const char* perspective_prefix =
- connection_.perspective() == Perspective::IS_CLIENT ? "C" : "S";
-
- std::string identifier =
- QuicStrCat(perspective_prefix, connection_.connection_id().ToString());
- QuicRecordTestOutput(identifier,
- trace_visitor_->trace()->SerializeAsString());
- }
+ connection_->SetFromConfig(config);
}
QuicByteCount QuicEndpoint::bytes_received() const {
@@ -176,48 +117,6 @@ void QuicEndpoint::AddBytesToTransfer(QuicByteCount bytes) {
WriteStreamData();
}
-void QuicEndpoint::DropNextIncomingPacket() {
- drop_next_packet_ = true;
-}
-
-void QuicEndpoint::RecordTrace() {
- trace_visitor_ = std::make_unique<QuicTraceVisitor>(&connection_);
- connection_.set_debug_visitor(trace_visitor_.get());
-}
-
-void QuicEndpoint::AcceptPacket(std::unique_ptr<Packet> packet) {
- if (packet->destination != name_) {
- return;
- }
- if (drop_next_packet_) {
- drop_next_packet_ = false;
- return;
- }
-
- QuicReceivedPacket received_packet(packet->contents.data(),
- packet->contents.size(), clock_->Now());
- connection_.ProcessUdpPacket(connection_.self_address(),
- connection_.peer_address(), received_packet);
-}
-
-UnconstrainedPortInterface* QuicEndpoint::GetRxPort() {
- return this;
-}
-
-void QuicEndpoint::SetTxPort(ConstrainedPortInterface* port) {
- // Any egress done by the endpoint is actually handled by a queue on an NIC.
- nic_tx_queue_.set_tx_port(port);
-}
-
-void QuicEndpoint::OnPacketDequeued() {
- if (writer_.IsWriteBlocked() &&
- (nic_tx_queue_.capacity() - nic_tx_queue_.bytes_queued()) >=
- kMaxOutgoingPacketSize) {
- writer_.SetWritable();
- connection_.OnCanWrite();
- }
-}
-
void QuicEndpoint::OnStreamFrame(const QuicStreamFrame& frame) {
// Verify that the data received always matches the expected.
DCHECK(frame.stream_id == kDataStream);
@@ -302,73 +201,6 @@ bool QuicEndpoint::HasUnackedStreamData() const {
return false;
}
-QuicEndpoint::Writer::Writer(QuicEndpoint* endpoint)
- : endpoint_(endpoint), is_blocked_(false) {}
-
-QuicEndpoint::Writer::~Writer() {}
-
-WriteResult QuicEndpoint::Writer::WritePacket(
- const char* buffer,
- size_t buf_len,
- const QuicIpAddress& /*self_address*/,
- const QuicSocketAddress& /*peer_address*/,
- PerPacketOptions* options) {
- DCHECK(!IsWriteBlocked());
- DCHECK(options == nullptr);
- DCHECK(buf_len <= kMaxOutgoingPacketSize);
-
- // Instead of losing a packet, become write-blocked when the egress queue is
- // full.
- if (endpoint_->nic_tx_queue_.packets_queued() > kTxQueueSize) {
- is_blocked_ = true;
- endpoint_->write_blocked_count_++;
- return WriteResult(WRITE_STATUS_BLOCKED, 0);
- }
-
- auto packet = std::make_unique<Packet>();
- packet->source = endpoint_->name();
- packet->destination = endpoint_->peer_name_;
- packet->tx_timestamp = endpoint_->clock_->Now();
-
- packet->contents = std::string(buffer, buf_len);
- packet->size = buf_len;
-
- endpoint_->nic_tx_queue_.AcceptPacket(std::move(packet));
-
- return WriteResult(WRITE_STATUS_OK, buf_len);
-}
-
-bool QuicEndpoint::Writer::IsWriteBlocked() const {
- return is_blocked_;
-}
-
-void QuicEndpoint::Writer::SetWritable() {
- is_blocked_ = false;
-}
-
-QuicByteCount QuicEndpoint::Writer::GetMaxPacketSize(
- const QuicSocketAddress& /*peer_address*/) const {
- return kMaxOutgoingPacketSize;
-}
-
-bool QuicEndpoint::Writer::SupportsReleaseTime() const {
- return false;
-}
-
-bool QuicEndpoint::Writer::IsBatchMode() const {
- return false;
-}
-
-char* QuicEndpoint::Writer::GetNextWriteLocation(
- const QuicIpAddress& /*self_address*/,
- const QuicSocketAddress& /*peer_address*/) {
- return nullptr;
-}
-
-WriteResult QuicEndpoint::Writer::Flush() {
- return WriteResult(WRITE_STATUS_OK, 0);
-}
-
WriteStreamDataResult QuicEndpoint::DataProducer::WriteStreamData(
QuicStreamId /*id*/,
QuicStreamOffset /*offset*/,
@@ -388,14 +220,14 @@ bool QuicEndpoint::DataProducer::WriteCryptoData(EncryptionLevel /*level*/,
void QuicEndpoint::WriteStreamData() {
// Instantiate a flusher which would normally be here due to QuicSession.
- QuicConnection::ScopedPacketFlusher flusher(&connection_);
+ QuicConnection::ScopedPacketFlusher flusher(connection_.get());
while (bytes_to_transfer_ > 0) {
// Transfer data in chunks of size at most |kWriteChunkSize|.
const size_t transmission_size =
std::min(kWriteChunkSize, bytes_to_transfer_);
- QuicConsumedData consumed_data = connection_.SendStreamData(
+ QuicConsumedData consumed_data = connection_->SendStreamData(
kDataStream, transmission_size, bytes_transferred_, NO_FIN);
DCHECK(consumed_data.bytes_consumed <= transmission_size);
@@ -407,33 +239,5 @@ void QuicEndpoint::WriteStreamData() {
}
}
-QuicEndpointMultiplexer::QuicEndpointMultiplexer(
- std::string name,
- const std::vector<QuicEndpoint*>& endpoints)
- : Endpoint((*endpoints.begin())->simulator(), name) {
- for (QuicEndpoint* endpoint : endpoints) {
- mapping_.insert(std::make_pair(endpoint->name(), endpoint));
- }
-}
-
-QuicEndpointMultiplexer::~QuicEndpointMultiplexer() {}
-
-void QuicEndpointMultiplexer::AcceptPacket(std::unique_ptr<Packet> packet) {
- auto key_value_pair_it = mapping_.find(packet->destination);
- if (key_value_pair_it == mapping_.end()) {
- return;
- }
-
- key_value_pair_it->second->GetRxPort()->AcceptPacket(std::move(packet));
-}
-UnconstrainedPortInterface* QuicEndpointMultiplexer::GetRxPort() {
- return this;
-}
-void QuicEndpointMultiplexer::SetTxPort(ConstrainedPortInterface* port) {
- for (auto& key_value_pair : mapping_) {
- key_value_pair.second->SetTxPort(port);
- }
-}
-
} // namespace simulator
} // namespace quic
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 43fce53bb4c..c2d24ac5404 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
@@ -16,26 +16,17 @@
#include "net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/queue.h"
+#include "net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_base.h"
namespace quic {
namespace simulator {
-// Size of the TX queue used by the kernel/NIC. 1000 is the Linux
-// kernel default.
-const QuicByteCount kTxQueueSize = 1000;
-
-// Generate a random local network host-port tuple based on the name of the
-// endpoint.
-QuicSocketAddress GetAddressFromName(std::string name);
-
// A QUIC connection endpoint. Wraps around QuicConnection. In order to
// initiate a transfer, the caller has to call AddBytesToTransfer(). The data
// transferred is always the same and is always transferred on a single stream.
// The endpoint receives all packets addressed to it, and verifies that the data
// received is what it's supposed to be.
-class QuicEndpoint : public Endpoint,
- public UnconstrainedPortInterface,
- public Queue::ListenerInterface,
+class QuicEndpoint : public QuicEndpointBase,
public QuicConnectionVisitorInterface,
public SessionNotifierInterface {
public:
@@ -44,40 +35,16 @@ class QuicEndpoint : public Endpoint,
std::string peer_name,
Perspective perspective,
QuicConnectionId connection_id);
- ~QuicEndpoint() override;
- inline QuicConnection* connection() { return &connection_; }
QuicByteCount bytes_to_transfer() const;
QuicByteCount bytes_transferred() const;
QuicByteCount bytes_received() const;
- inline size_t write_blocked_count() { return write_blocked_count_; }
inline bool wrong_data_received() const { return wrong_data_received_; }
// Send |bytes| bytes. Initiates the transfer if one is not already in
// progress.
void AddBytesToTransfer(QuicByteCount bytes);
- // Drop the next packet upon receipt.
- void DropNextIncomingPacket();
-
- // UnconstrainedPortInterface method. Called whenever the endpoint receives a
- // packet.
- void AcceptPacket(std::unique_ptr<Packet> packet) override;
-
- // Enables logging of the connection trace at the end of the unit test.
- void RecordTrace();
-
- // Begin Endpoint implementation.
- UnconstrainedPortInterface* GetRxPort() override;
- void SetTxPort(ConstrainedPortInterface* port) override;
- // End Endpoint implementation.
-
- // Actor method.
- void Act() override {}
-
- // Queue::ListenerInterface method.
- void OnPacketDequeued() override;
-
// Begin QuicConnectionVisitorInterface implementation.
void OnStreamFrame(const QuicStreamFrame& frame) override;
void OnCryptoFrame(const QuicCryptoFrame& frame) override;
@@ -114,9 +81,8 @@ class QuicEndpoint : public Endpoint,
const QuicStreamsBlockedFrame& /*frame*/) override {
return true;
}
- bool OnStopSendingFrame(const QuicStopSendingFrame& /*frame*/) override {
- return true;
- }
+ void OnStopSendingFrame(const QuicStopSendingFrame& /*frame*/) override {}
+ void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
// End QuicConnectionVisitorInterface implementation.
@@ -134,33 +100,6 @@ class QuicEndpoint : public Endpoint,
// End SessionNotifierInterface implementation.
private:
- // A Writer object that writes into the |nic_tx_queue_|.
- class Writer : public QuicPacketWriter {
- public:
- explicit Writer(QuicEndpoint* endpoint);
- ~Writer() override;
-
- WriteResult WritePacket(const char* buffer,
- size_t buf_len,
- const QuicIpAddress& self_address,
- const QuicSocketAddress& peer_address,
- PerPacketOptions* options) override;
- bool IsWriteBlocked() const override;
- void SetWritable() override;
- QuicByteCount GetMaxPacketSize(
- const QuicSocketAddress& peer_address) const override;
- bool SupportsReleaseTime() const override;
- bool IsBatchMode() const override;
- char* GetNextWriteLocation(const QuicIpAddress& self_address,
- const QuicSocketAddress& peer_address) override;
- WriteResult Flush() override;
-
- private:
- QuicEndpoint* endpoint_;
-
- bool is_blocked_;
- };
-
// The producer outputs the repetition of the same byte. That sequence is
// verified by the receiver.
class DataProducer : public QuicStreamFrameDataProducer {
@@ -175,60 +114,30 @@ class QuicEndpoint : public Endpoint,
QuicDataWriter* writer) override;
};
+ std::unique_ptr<QuicConnection> CreateConnection(
+ Simulator* simulator,
+ std::string name,
+ std::string peer_name,
+ Perspective perspective,
+ QuicConnectionId connection_id);
+
// Write stream data until |bytes_to_transfer_| is zero or the connection is
// write-blocked.
void WriteStreamData();
- std::string peer_name_;
-
- Writer writer_;
DataProducer producer_;
- // The queue for the outgoing packets. In reality, this might be either on
- // the network card, or in the kernel, but for concreteness we assume it's on
- // the network card.
- Queue nic_tx_queue_;
- QuicConnection connection_;
QuicByteCount bytes_to_transfer_;
QuicByteCount bytes_transferred_;
- // Counts the number of times the writer became write-blocked.
- size_t write_blocked_count_;
-
// Set to true if the endpoint receives stream data different from what it
// expects.
bool wrong_data_received_;
- // If true, drop the next packet when receiving it.
- bool drop_next_packet_;
-
// Record of received offsets in the data stream.
QuicIntervalSet<QuicStreamOffset> offsets_received_;
std::unique_ptr<test::SimpleSessionNotifier> notifier_;
- std::unique_ptr<QuicTraceVisitor> trace_visitor_;
-};
-
-// Multiplexes multiple connections at the same host on the network.
-class QuicEndpointMultiplexer : public Endpoint,
- public UnconstrainedPortInterface {
- public:
- QuicEndpointMultiplexer(std::string name,
- const std::vector<QuicEndpoint*>& endpoints);
- ~QuicEndpointMultiplexer() override;
-
- // Receives a packet and passes it to the specified endpoint if that endpoint
- // is one of the endpoints being multiplexed, otherwise ignores the packet.
- void AcceptPacket(std::unique_ptr<Packet> packet) override;
- UnconstrainedPortInterface* GetRxPort() override;
-
- // Sets the egress port for all the endpoints being multiplexed.
- void SetTxPort(ConstrainedPortInterface* port) override;
-
- void Act() override {}
-
- private:
- QuicUnorderedMap<std::string, QuicEndpoint*> mapping_;
};
} // namespace simulator
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_base.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_base.cc
new file mode 100644
index 00000000000..537a94737b4
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_base.cc
@@ -0,0 +1,222 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_base.h"
+
+#include <memory>
+#include <utility>
+
+#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
+#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
+#include "net/third_party/quiche/src/quic/core/quic_connection.h"
+#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test_output.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
+
+namespace quic {
+namespace simulator {
+
+// Takes a SHA-1 hash of the name and converts it into five 32-bit integers.
+static std::vector<uint32_t> HashNameIntoFive32BitIntegers(std::string name) {
+ const std::string hash = test::Sha1Hash(name);
+
+ std::vector<uint32_t> output;
+ uint32_t current_number = 0;
+ for (size_t i = 0; i < hash.size(); i++) {
+ current_number = (current_number << 8) + hash[i];
+ if (i % 4 == 3) {
+ output.push_back(i);
+ current_number = 0;
+ }
+ }
+
+ return output;
+}
+
+QuicSocketAddress GetAddressFromName(std::string name) {
+ const std::vector<uint32_t> hash = HashNameIntoFive32BitIntegers(name);
+
+ // Generate a random port between 1025 and 65535.
+ const uint16_t port = 1025 + hash[0] % (65535 - 1025 + 1);
+
+ // Generate a random 10.x.x.x address, where x is between 1 and 254.
+ std::string ip_address{"\xa\0\0\0", 4};
+ for (size_t i = 1; i < 4; i++) {
+ ip_address[i] = 1 + hash[i] % 254;
+ }
+ QuicIpAddress host;
+ host.FromPackedString(ip_address.c_str(), ip_address.length());
+ return QuicSocketAddress(host, port);
+}
+
+QuicEndpointBase::QuicEndpointBase(Simulator* simulator,
+ std::string name,
+ std::string peer_name)
+ : Endpoint(simulator, name),
+ peer_name_(peer_name),
+ writer_(this),
+ nic_tx_queue_(simulator,
+ QuicStringPrintf("%s (TX Queue)", name.c_str()),
+ kMaxOutgoingPacketSize * kTxQueueSize),
+ connection_(nullptr),
+ write_blocked_count_(0),
+ drop_next_packet_(false) {
+ nic_tx_queue_.set_listener_interface(this);
+}
+
+QuicEndpointBase::~QuicEndpointBase() {
+ if (trace_visitor_ != nullptr) {
+ const char* perspective_prefix =
+ connection_->perspective() == Perspective::IS_CLIENT ? "C" : "S";
+
+ std::string identifier =
+ QuicStrCat(perspective_prefix, connection_->connection_id().ToString());
+ QuicRecordTestOutput(identifier,
+ trace_visitor_->trace()->SerializeAsString());
+ }
+}
+
+void QuicEndpointBase::DropNextIncomingPacket() {
+ drop_next_packet_ = true;
+}
+
+void QuicEndpointBase::RecordTrace() {
+ trace_visitor_ = std::make_unique<QuicTraceVisitor>(connection_.get());
+ connection_->set_debug_visitor(trace_visitor_.get());
+}
+
+void QuicEndpointBase::AcceptPacket(std::unique_ptr<Packet> packet) {
+ if (packet->destination != name_) {
+ return;
+ }
+ if (drop_next_packet_) {
+ drop_next_packet_ = false;
+ return;
+ }
+
+ QuicReceivedPacket received_packet(packet->contents.data(),
+ packet->contents.size(), clock_->Now());
+ connection_->ProcessUdpPacket(connection_->self_address(),
+ connection_->peer_address(), received_packet);
+}
+
+UnconstrainedPortInterface* QuicEndpointBase::GetRxPort() {
+ return this;
+}
+
+void QuicEndpointBase::SetTxPort(ConstrainedPortInterface* port) {
+ // Any egress done by the endpoint is actually handled by a queue on an NIC.
+ nic_tx_queue_.set_tx_port(port);
+}
+
+void QuicEndpointBase::OnPacketDequeued() {
+ if (writer_.IsWriteBlocked() &&
+ (nic_tx_queue_.capacity() - nic_tx_queue_.bytes_queued()) >=
+ kMaxOutgoingPacketSize) {
+ writer_.SetWritable();
+ connection_->OnCanWrite();
+ }
+}
+
+QuicEndpointBase::Writer::Writer(QuicEndpointBase* endpoint)
+ : endpoint_(endpoint), is_blocked_(false) {}
+
+QuicEndpointBase::Writer::~Writer() {}
+
+WriteResult QuicEndpointBase::Writer::WritePacket(
+ const char* buffer,
+ size_t buf_len,
+ const QuicIpAddress& /*self_address*/,
+ const QuicSocketAddress& /*peer_address*/,
+ PerPacketOptions* options) {
+ DCHECK(!IsWriteBlocked());
+ DCHECK(options == nullptr);
+ DCHECK(buf_len <= kMaxOutgoingPacketSize);
+
+ // Instead of losing a packet, become write-blocked when the egress queue is
+ // full.
+ if (endpoint_->nic_tx_queue_.packets_queued() > kTxQueueSize) {
+ is_blocked_ = true;
+ endpoint_->write_blocked_count_++;
+ return WriteResult(WRITE_STATUS_BLOCKED, 0);
+ }
+
+ auto packet = std::make_unique<Packet>();
+ packet->source = endpoint_->name();
+ packet->destination = endpoint_->peer_name_;
+ packet->tx_timestamp = endpoint_->clock_->Now();
+
+ packet->contents = std::string(buffer, buf_len);
+ packet->size = buf_len;
+
+ endpoint_->nic_tx_queue_.AcceptPacket(std::move(packet));
+
+ return WriteResult(WRITE_STATUS_OK, buf_len);
+}
+
+bool QuicEndpointBase::Writer::IsWriteBlocked() const {
+ return is_blocked_;
+}
+
+void QuicEndpointBase::Writer::SetWritable() {
+ is_blocked_ = false;
+}
+
+QuicByteCount QuicEndpointBase::Writer::GetMaxPacketSize(
+ const QuicSocketAddress& /*peer_address*/) const {
+ return kMaxOutgoingPacketSize;
+}
+
+bool QuicEndpointBase::Writer::SupportsReleaseTime() const {
+ return false;
+}
+
+bool QuicEndpointBase::Writer::IsBatchMode() const {
+ return false;
+}
+
+char* QuicEndpointBase::Writer::GetNextWriteLocation(
+ const QuicIpAddress& /*self_address*/,
+ const QuicSocketAddress& /*peer_address*/) {
+ return nullptr;
+}
+
+WriteResult QuicEndpointBase::Writer::Flush() {
+ return WriteResult(WRITE_STATUS_OK, 0);
+}
+
+QuicEndpointMultiplexer::QuicEndpointMultiplexer(
+ std::string name,
+ const std::vector<QuicEndpointBase*>& endpoints)
+ : Endpoint((*endpoints.begin())->simulator(), name) {
+ for (QuicEndpointBase* endpoint : endpoints) {
+ mapping_.insert(std::make_pair(endpoint->name(), endpoint));
+ }
+}
+
+QuicEndpointMultiplexer::~QuicEndpointMultiplexer() {}
+
+void QuicEndpointMultiplexer::AcceptPacket(std::unique_ptr<Packet> packet) {
+ auto key_value_pair_it = mapping_.find(packet->destination);
+ if (key_value_pair_it == mapping_.end()) {
+ return;
+ }
+
+ key_value_pair_it->second->GetRxPort()->AcceptPacket(std::move(packet));
+}
+UnconstrainedPortInterface* QuicEndpointMultiplexer::GetRxPort() {
+ return this;
+}
+void QuicEndpointMultiplexer::SetTxPort(ConstrainedPortInterface* port) {
+ for (auto& key_value_pair : mapping_) {
+ key_value_pair.second->SetTxPort(port);
+ }
+}
+
+} // namespace simulator
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_base.h b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_base.h
new file mode 100644
index 00000000000..ae9f69b95fc
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_base.h
@@ -0,0 +1,158 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_TEST_TOOLS_SIMULATOR_QUIC_ENDPOINT_BASE_H_
+#define QUICHE_QUIC_TEST_TOOLS_SIMULATOR_QUIC_ENDPOINT_BASE_H_
+
+#include <memory>
+
+#include "net/third_party/quiche/src/quic/core/crypto/null_decrypter.h"
+#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
+#include "net/third_party/quiche/src/quic/core/quic_connection.h"
+#include "net/third_party/quiche/src/quic/core/quic_default_packet_writer.h"
+#include "net/third_party/quiche/src/quic/core/quic_packets.h"
+#include "net/third_party/quiche/src/quic/core/quic_stream_frame_data_producer.h"
+#include "net/third_party/quiche/src/quic/core/quic_trace_visitor.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
+#include "net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h"
+#include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"
+#include "net/third_party/quiche/src/quic/test_tools/simulator/queue.h"
+
+namespace quic {
+namespace simulator {
+
+// Size of the TX queue used by the kernel/NIC. 1000 is the Linux
+// kernel default.
+const QuicByteCount kTxQueueSize = 1000;
+
+// Generate a random local network host-port tuple based on the name of the
+// endpoint.
+QuicSocketAddress GetAddressFromName(std::string name);
+
+// A QUIC connection endpoint. If the specific data transmitted does not matter
+// (e.g. for congestion control purposes), QuicEndpoint is the subclass that
+// transmits dummy data. If the actual semantics of the connection matter,
+// subclassing QuicEndpointBase is required.
+class QuicEndpointBase : public Endpoint,
+ public UnconstrainedPortInterface,
+ public Queue::ListenerInterface {
+ public:
+ // Does not create the connection; the subclass has to create connection by
+ // itself.
+ QuicEndpointBase(Simulator* simulator,
+ std::string name,
+ std::string peer_name);
+ ~QuicEndpointBase() override;
+
+ inline QuicConnection* connection() { return connection_.get(); }
+ inline size_t write_blocked_count() { return write_blocked_count_; }
+
+ // Drop the next packet upon receipt.
+ void DropNextIncomingPacket();
+
+ // UnconstrainedPortInterface method. Called whenever the endpoint receives a
+ // packet.
+ void AcceptPacket(std::unique_ptr<Packet> packet) override;
+
+ // Enables logging of the connection trace at the end of the unit test.
+ void RecordTrace();
+
+ // Begin Endpoint implementation.
+ UnconstrainedPortInterface* GetRxPort() override;
+ void SetTxPort(ConstrainedPortInterface* port) override;
+ // End Endpoint implementation.
+
+ // Actor method.
+ void Act() override {}
+
+ // Queue::ListenerInterface method.
+ void OnPacketDequeued() override;
+
+ protected:
+ // A Writer object that writes into the |nic_tx_queue_|.
+ class Writer : public QuicPacketWriter {
+ public:
+ explicit Writer(QuicEndpointBase* endpoint);
+ ~Writer() override;
+
+ WriteResult WritePacket(const char* buffer,
+ size_t buf_len,
+ const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address,
+ PerPacketOptions* options) override;
+ bool IsWriteBlocked() const override;
+ void SetWritable() override;
+ QuicByteCount GetMaxPacketSize(
+ const QuicSocketAddress& peer_address) const override;
+ bool SupportsReleaseTime() const override;
+ bool IsBatchMode() const override;
+ char* GetNextWriteLocation(const QuicIpAddress& self_address,
+ const QuicSocketAddress& peer_address) override;
+ WriteResult Flush() override;
+
+ private:
+ QuicEndpointBase* endpoint_;
+
+ bool is_blocked_;
+ };
+
+ // The producer outputs the repetition of the same byte. That sequence is
+ // verified by the receiver.
+ class DataProducer : public QuicStreamFrameDataProducer {
+ public:
+ WriteStreamDataResult WriteStreamData(QuicStreamId id,
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ QuicDataWriter* writer) override;
+ bool WriteCryptoData(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ QuicDataWriter* writer) override;
+ };
+
+ std::string peer_name_;
+
+ Writer writer_;
+ // The queue for the outgoing packets. In reality, this might be either on
+ // the network card, or in the kernel, but for concreteness we assume it's on
+ // the network card.
+ Queue nic_tx_queue_;
+ // Created by the subclass.
+ std::unique_ptr<QuicConnection> connection_;
+
+ // Counts the number of times the writer became write-blocked.
+ size_t write_blocked_count_;
+
+ // If true, drop the next packet when receiving it.
+ bool drop_next_packet_;
+
+ std::unique_ptr<QuicTraceVisitor> trace_visitor_;
+};
+
+// Multiplexes multiple connections at the same host on the network.
+class QuicEndpointMultiplexer : public Endpoint,
+ public UnconstrainedPortInterface {
+ public:
+ QuicEndpointMultiplexer(std::string name,
+ const std::vector<QuicEndpointBase*>& endpoints);
+ ~QuicEndpointMultiplexer() override;
+
+ // Receives a packet and passes it to the specified endpoint if that endpoint
+ // is one of the endpoints being multiplexed, otherwise ignores the packet.
+ void AcceptPacket(std::unique_ptr<Packet> packet) override;
+ UnconstrainedPortInterface* GetRxPort() override;
+
+ // Sets the egress port for all the endpoints being multiplexed.
+ void SetTxPort(ConstrainedPortInterface* port) override;
+
+ void Act() override {}
+
+ private:
+ QuicUnorderedMap<std::string, QuicEndpointBase*> mapping_;
+};
+
+} // namespace simulator
+} // namespace quic
+
+#endif // QUICHE_QUIC_TEST_TOOLS_SIMULATOR_QUIC_ENDPOINT_BASE_H_
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_test.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_test.cc
index 772cd2e4ffd..0989a3bc0f7 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint_test.cc
@@ -104,8 +104,8 @@ TEST_F(QuicEndpointTest, WriteBlocked) {
EXPECT_CALL(*sender, BandwidthEstimate())
.WillRepeatedly(Return(10 * kDefaultBandwidth));
EXPECT_CALL(*sender, GetCongestionWindow())
- .WillRepeatedly(
- Return(kMaxOutgoingPacketSize * kDefaultMaxCongestionWindowPackets));
+ .WillRepeatedly(Return(kMaxOutgoingPacketSize *
+ GetQuicFlag(FLAGS_quic_max_congestion_window)));
test::QuicConnectionPeer::SetSendAlgorithm(endpoint_a.connection(), sender);
// First transmit a small, packet-size chunk of data.
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 cccb7ba3e6f..379cfac3c13 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
@@ -70,7 +70,24 @@ QuicClient::QuicClient(QuicSocketAddress server_address,
QuicConfig(),
epoll_server,
QuicWrapUnique(new QuicClientEpollNetworkHelper(epoll_server, this)),
- std::move(proof_verifier)) {}
+ std::move(proof_verifier),
+ nullptr) {}
+
+QuicClient::QuicClient(QuicSocketAddress server_address,
+ const QuicServerId& server_id,
+ const ParsedQuicVersionVector& supported_versions,
+ QuicEpollServer* epoll_server,
+ std::unique_ptr<ProofVerifier> proof_verifier,
+ std::unique_ptr<SessionCache> session_cache)
+ : QuicClient(
+ server_address,
+ server_id,
+ supported_versions,
+ QuicConfig(),
+ epoll_server,
+ QuicWrapUnique(new QuicClientEpollNetworkHelper(epoll_server, this)),
+ std::move(proof_verifier),
+ std::move(session_cache)) {}
QuicClient::QuicClient(
QuicSocketAddress server_address,
@@ -85,7 +102,8 @@ QuicClient::QuicClient(
QuicConfig(),
epoll_server,
std::move(network_helper),
- std::move(proof_verifier)) {}
+ std::move(proof_verifier),
+ nullptr) {}
QuicClient::QuicClient(
QuicSocketAddress server_address,
@@ -95,6 +113,24 @@ QuicClient::QuicClient(
QuicEpollServer* epoll_server,
std::unique_ptr<QuicClientEpollNetworkHelper> network_helper,
std::unique_ptr<ProofVerifier> proof_verifier)
+ : QuicClient(server_address,
+ server_id,
+ supported_versions,
+ config,
+ epoll_server,
+ std::move(network_helper),
+ std::move(proof_verifier),
+ nullptr) {}
+
+QuicClient::QuicClient(
+ QuicSocketAddress server_address,
+ const QuicServerId& server_id,
+ const ParsedQuicVersionVector& supported_versions,
+ const QuicConfig& config,
+ QuicEpollServer* epoll_server,
+ std::unique_ptr<QuicClientEpollNetworkHelper> network_helper,
+ std::unique_ptr<ProofVerifier> proof_verifier,
+ std::unique_ptr<SessionCache> session_cache)
: QuicSpdyClientBase(
server_id,
supported_versions,
@@ -102,7 +138,8 @@ QuicClient::QuicClient(
new QuicEpollConnectionHelper(epoll_server, QuicAllocator::SIMPLE),
new QuicEpollAlarmFactory(epoll_server),
std::move(network_helper),
- std::move(proof_verifier)) {
+ std::move(proof_verifier),
+ std::move(session_cache)) {
set_server_address(server_address);
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_client.h b/chromium/net/third_party/quiche/src/quic/tools/quic_client.h
index 8e43be8498b..10c61f378d0 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_client.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_client.h
@@ -37,12 +37,18 @@ QuicSocketAddress LookupAddress(std::string host, std::string port);
class QuicClient : public QuicSpdyClientBase {
public:
- // This will create its own QuicClientEpollNetworkHelper.
+ // These will create their own QuicClientEpollNetworkHelper.
QuicClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
const ParsedQuicVersionVector& supported_versions,
QuicEpollServer* epoll_server,
std::unique_ptr<ProofVerifier> proof_verifier);
+ QuicClient(QuicSocketAddress server_address,
+ const QuicServerId& server_id,
+ const ParsedQuicVersionVector& supported_versions,
+ QuicEpollServer* epoll_server,
+ std::unique_ptr<ProofVerifier> proof_verifier,
+ std::unique_ptr<SessionCache> session_cache);
// This will take ownership of a passed in network primitive.
QuicClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
@@ -57,6 +63,14 @@ class QuicClient : public QuicSpdyClientBase {
QuicEpollServer* epoll_server,
std::unique_ptr<QuicClientEpollNetworkHelper> network_helper,
std::unique_ptr<ProofVerifier> proof_verifier);
+ QuicClient(QuicSocketAddress server_address,
+ const QuicServerId& server_id,
+ const ParsedQuicVersionVector& supported_versions,
+ const QuicConfig& config,
+ QuicEpollServer* epoll_server,
+ std::unique_ptr<QuicClientEpollNetworkHelper> network_helper,
+ std::unique_ptr<ProofVerifier> proof_verifier,
+ std::unique_ptr<SessionCache> session_cache);
QuicClient(const QuicClient&) = delete;
QuicClient& operator=(const QuicClient&) = delete;
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 b03f7cc342d..b6c33759b47 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
@@ -23,12 +23,13 @@ QuicClientBase::QuicClientBase(
QuicConnectionHelperInterface* helper,
QuicAlarmFactory* alarm_factory,
std::unique_ptr<NetworkHelper> network_helper,
- std::unique_ptr<ProofVerifier> proof_verifier)
+ std::unique_ptr<ProofVerifier> proof_verifier,
+ std::unique_ptr<SessionCache> session_cache)
: server_id_(server_id),
initialized_(false),
local_port_(0),
config_(config),
- crypto_config_(std::move(proof_verifier)),
+ crypto_config_(std::move(proof_verifier), std::move(session_cache)),
helper_(helper),
alarm_factory_(alarm_factory),
supported_versions_(supported_versions),
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.h b/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.h
index fb15b862b08..8cb639bd58f 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.h
@@ -23,6 +23,7 @@ namespace quic {
class ProofVerifier;
class QuicServerId;
+class SessionCache;
// QuicClientBase handles establishing a connection to the passed in
// server id, including ensuring that it supports the passed in versions
@@ -64,7 +65,8 @@ class QuicClientBase {
QuicConnectionHelperInterface* helper,
QuicAlarmFactory* alarm_factory,
std::unique_ptr<NetworkHelper> network_helper,
- std::unique_ptr<ProofVerifier> proof_verifier);
+ std::unique_ptr<ProofVerifier> proof_verifier,
+ std::unique_ptr<SessionCache> session_cache);
QuicClientBase(const QuicClientBase&) = delete;
QuicClientBase& operator=(const QuicClientBase&) = delete;
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 278a22e29ba..8c9f6d16930 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
@@ -13,6 +13,8 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_system_event_loop.h"
#include "net/quic/platform/impl/quic_epoll_clock.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/simple_session_cache.h"
#include "net/third_party/quiche/src/quic/tools/fake_proof_verifier.h"
#include "net/third_party/quiche/src/quic/tools/quic_client.h"
#include "net/third_party/quiche/src/quic/tools/quic_url.h"
@@ -36,6 +38,8 @@ enum class Feature {
kStreamData,
// The connection close procedcure completes with a zero error code.
kConnectionClose,
+ // The connection was established using TLS resumption.
+ kResumption,
// A RETRY packet was successfully processed.
kRetry,
@@ -46,6 +50,9 @@ enum class Feature {
// Third row of features (H3 tests)
// An H3 transaction succeeded.
kHttp3,
+ // One or both endpoints insert entries into dynamic table and subsequenly
+ // reference them from header blocks.
+ kDynamicEntryReferenced,
};
char MatrixLetter(Feature f) {
@@ -58,39 +65,80 @@ char MatrixLetter(Feature f) {
return 'D';
case Feature::kConnectionClose:
return 'C';
- case Feature::kHttp3:
- return '3';
+ case Feature::kResumption:
+ return 'R';
case Feature::kRetry:
return 'S';
case Feature::kRebinding:
return 'B';
+ case Feature::kHttp3:
+ return '3';
+ case Feature::kDynamicEntryReferenced:
+ return 'd';
+ }
+}
+
+// Attempts a resumption using |client| by disconnecting and reconnecting. If
+// resumption is successful, |features| is modified to add Feature::kResumption
+// to it, otherwise it is left unmodified.
+void AttemptResumption(QuicClient* client, std::set<Feature>* features) {
+ client->Disconnect();
+ if (!client->Initialize()) {
+ QUIC_LOG(ERROR) << "Failed to reinitialize client";
+ return;
+ }
+ if (!client->Connect() || !client->session()->IsCryptoHandshakeConfirmed()) {
+ return;
+ }
+ if (static_cast<QuicCryptoClientStream*>(
+ test::QuicSessionPeer::GetMutableCryptoStream(client->session()))
+ ->IsResumption()) {
+ features->insert(Feature::kResumption);
}
}
std::set<Feature> AttemptRequest(QuicSocketAddress addr,
std::string authority,
QuicServerId server_id,
- ParsedQuicVersionVector versions,
+ bool test_version_negotiation,
bool attempt_rebind) {
+ ParsedQuicVersion version(PROTOCOL_TLS1_3, QUIC_VERSION_99);
+ ParsedQuicVersionVector versions = {version};
+ if (test_version_negotiation) {
+ versions.insert(versions.begin(), QuicVersionReservedForNegotiation());
+ }
+
std::set<Feature> features;
auto proof_verifier = std::make_unique<FakeProofVerifier>();
+ auto session_cache = std::make_unique<test::SimpleSessionCache>();
QuicEpollServer epoll_server;
QuicEpollClock epoll_clock(&epoll_server);
auto client = std::make_unique<QuicClient>(
- addr, server_id, versions, &epoll_server, std::move(proof_verifier));
+ addr, server_id, versions, &epoll_server, std::move(proof_verifier),
+ std::move(session_cache));
if (!client->Initialize()) {
+ QUIC_LOG(ERROR) << "Failed to initialize client";
return features;
}
- if (!client->Connect()) {
- QuicErrorCode error = client->session()->error();
- if (error == QUIC_INVALID_VERSION) {
- // QuicFramer::ProcessPacket returns RaiseError(QUIC_INVALID_VERSION) if
- // it receives a packet containing a version in the header that is not our
- // version. It might be possible that we didn't actually process a VN
- // packet here.
+ const bool connect_result = client->Connect();
+ QuicConnection* connection = client->session()->connection();
+ if (connection != nullptr) {
+ QuicConnectionStats client_stats = connection->GetStats();
+ if (client_stats.retry_packet_processed) {
+ features.insert(Feature::kRetry);
+ }
+ if (test_version_negotiation && connection->version() == version) {
features.insert(Feature::kVersionNegotiation);
- return features;
}
+ }
+ if (test_version_negotiation && !connect_result) {
+ // Failed to negotiate version, retry without version negotiation.
+ std::set<Feature> features_without_version_negotiation =
+ AttemptRequest(addr, authority, server_id,
+ /*test_version_negotiation=*/false, attempt_rebind);
+
+ features.insert(features_without_version_negotiation.begin(),
+ features_without_version_negotiation.end());
return features;
}
if (!client->session()->IsCryptoHandshakeConfirmed()) {
@@ -109,19 +157,17 @@ std::set<Feature> AttemptRequest(QuicSocketAddress addr,
const QuicTime request_start_time = epoll_clock.Now();
static const auto request_timeout = QuicTime::Delta::FromSeconds(20);
+ bool request_timed_out = false;
while (client->WaitForEvents()) {
if (epoll_clock.Now() - request_start_time >= request_timeout) {
QUIC_LOG(ERROR) << "Timed out waiting for HTTP response";
- return features;
+ request_timed_out = true;
+ break;
}
}
- QuicConnection* connection = client->session()->connection();
if (connection != nullptr) {
QuicConnectionStats client_stats = connection->GetStats();
- if (client_stats.retry_packet_processed) {
- features.insert(Feature::kRetry);
- }
QuicSentPacketManager* sent_packet_manager =
test::QuicConnectionPeer::GetSentPacketManager(connection);
const bool received_forward_secure_ack =
@@ -133,13 +179,17 @@ std::set<Feature> AttemptRequest(QuicSocketAddress addr,
}
}
- if (!client->connected()) {
+ if (request_timed_out || !client->connected()) {
return features;
}
if (client->latest_response_code() != -1) {
features.insert(Feature::kHttp3);
+ if (client->client_session()->dynamic_table_entry_referenced()) {
+ features.insert(Feature::kDynamicEntryReferenced);
+ }
+
if (attempt_rebind) {
// Now make a second request after switching to a different client port.
if (client->ChangeEphemeralPort()) {
@@ -150,11 +200,19 @@ std::set<Feature> AttemptRequest(QuicSocketAddress addr,
if (epoll_clock.Now() - second_request_start_time >=
request_timeout) {
// Rebinding does not work, retry without attempting it.
- return AttemptRequest(addr, authority, server_id, versions,
- /*attempt_rebind=*/false);
+ std::set<Feature> features_without_rebind = AttemptRequest(
+ addr, authority, server_id, test_version_negotiation,
+ /*attempt_rebind=*/false);
+ features.insert(features_without_rebind.begin(),
+ features_without_rebind.end());
+ return features;
}
}
features.insert(Feature::kRebinding);
+
+ if (client->client_session()->dynamic_table_entry_referenced()) {
+ features.insert(Feature::kDynamicEntryReferenced);
+ }
} else {
QUIC_LOG(ERROR) << "Failed to change ephemeral port";
}
@@ -170,6 +228,7 @@ std::set<Feature> AttemptRequest(QuicSocketAddress addr,
client->epoll_network_helper()->RunEventLoop();
if (epoll_clock.Now() - close_start_time >= close_timeout) {
QUIC_LOG(ERROR) << "Timed out waiting for connection close";
+ AttemptResumption(client.get(), &features);
return features;
}
}
@@ -183,35 +242,27 @@ std::set<Feature> AttemptRequest(QuicSocketAddress addr,
}
}
+ AttemptResumption(client.get(), &features);
return features;
}
std::set<Feature> ServerSupport(std::string host, int port) {
- // Configure version list.
+ // Enable IETF version support.
QuicVersionInitializeSupportForIetfDraft();
- ParsedQuicVersion version =
- ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99);
- ParsedQuicVersionVector versions = {version};
- QuicEnableVersion(version);
+ QuicEnableVersion(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99));
// Build the client, and try to connect.
QuicSocketAddress addr = tools::LookupAddress(host, QuicStrCat(port));
+ if (!addr.IsInitialized()) {
+ QUIC_LOG(ERROR) << "Failed to resolve " << host;
+ return std::set<Feature>();
+ }
QuicServerId server_id(host, port, false);
std::string authority = QuicStrCat(host, ":", port);
- ParsedQuicVersionVector versions_with_negotiation = versions;
- versions_with_negotiation.insert(versions_with_negotiation.begin(),
- QuicVersionReservedForNegotiation());
- auto supported_features =
- AttemptRequest(addr, authority, server_id, versions_with_negotiation,
- /*attempt_rebind=*/true);
- if (!supported_features.empty()) {
- supported_features.insert(Feature::kVersionNegotiation);
- } else {
- supported_features = AttemptRequest(addr, authority, server_id, versions,
- /*attempt_rebind=*/true);
- }
- return supported_features;
+ return AttemptRequest(addr, authority, server_id,
+ /*test_version_negotiation=*/true,
+ /*attempt_rebind=*/true);
}
} // namespace quic
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 6452d22c5ed..38d25e53734 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
@@ -289,7 +289,6 @@ void QuicMemoryCacheBackend::GenerateDynamicResponses() {
QuicWriterMutexLock lock(&response_mutex_);
// Add a generate bytes response.
spdy::SpdyHeaderBlock response_headers;
- response_headers[":version"] = "HTTP/1.1";
response_headers[":status"] = "200";
generate_bytes_response_ = std::make_unique<QuicBackendResponse>();
generate_bytes_response_->set_headers(std::move(response_headers));
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 e0ff400f410..f88d458e965 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
@@ -134,9 +134,6 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend {
// 'response'.
void AddDefaultResponse(QuicBackendResponse* response);
- // |cache_cirectory| can be generated using `wget -p --save-headers <url>`.
- void InitializeFromDirectory(const std::string& cache_directory);
-
// Once called, URLs which have a numeric path will send a dynamically
// generated response of that many bytes.
void GenerateDynamicResponses();
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 80b1b293206..01ac334d1dd 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
@@ -59,7 +59,6 @@ TEST_F(QuicMemoryCacheBackendTest, AddResponse) {
const std::string kResponseBody("hello response");
spdy::SpdyHeaderBlock response_headers;
- response_headers[":version"] = "HTTP/1.1";
response_headers[":status"] = "200";
response_headers["content-length"] =
QuicTextUtils::Uint64ToString(kResponseBody.size());
@@ -123,7 +122,6 @@ TEST_F(QuicMemoryCacheBackendTest, DefaultResponse) {
// Add a default response.
spdy::SpdyHeaderBlock response_headers;
- response_headers[":version"] = "HTTP/1.1";
response_headers[":status"] = "200";
response_headers["content-length"] = "0";
Response* default_response = new Response;
@@ -164,7 +162,6 @@ TEST_F(QuicMemoryCacheBackendTest, AddSimpleResponseWithServerPushResources) {
std::string body =
QuicStrCat("This is server push response body for ", path);
spdy::SpdyHeaderBlock response_headers;
- response_headers[":version"] = "HTTP/1.1";
response_headers[":status"] = "200";
response_headers["content-length"] =
QuicTextUtils::Uint64ToString(body.size());
@@ -203,7 +200,6 @@ TEST_F(QuicMemoryCacheBackendTest, GetServerPushResourcesAndPushResponses) {
QuicUrl resource_url(url);
std::string body = "This is server push response body for " + path;
spdy::SpdyHeaderBlock response_headers;
- response_headers[":version"] = "HTTP/1.1";
response_headers[":status"] = push_response_status[i];
response_headers["content-length"] =
QuicTextUtils::Uint64ToString(body.size());
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_server.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_server.cc
index 294dbc50ee7..04cc9508aad 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_server.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_server.cc
@@ -218,8 +218,6 @@ void QuicServer::OnEvent(int fd, QuicEpollEvent* event) {
event->out_ready_mask |= EPOLLOUT;
}
}
- if (event->in_events & EPOLLERR) {
- }
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_stream.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_stream.cc
index a627007972c..b851a1d7eb0 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_stream.cc
@@ -26,8 +26,4 @@ void QuicSimpleClientStream::OnBodyAvailable() {
}
}
-void QuicSimpleClientStream::OnStopSending(uint16_t code) {
- last_stop_sending_code_ = code;
-}
-
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_stream.h b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_stream.h
index f1eb653bea4..aa6d2f6fe44 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_stream.h
@@ -16,17 +16,11 @@ class QuicSimpleClientStream : public QuicSpdyClientStream {
StreamType type,
bool drop_response_body)
: QuicSpdyClientStream(id, session, type),
- drop_response_body_(drop_response_body),
- last_stop_sending_code_(0) {}
+ drop_response_body_(drop_response_body) {}
void OnBodyAvailable() override;
- void OnStopSending(uint16_t code) override;
- uint16_t last_stop_sending_code() { return last_stop_sending_code_; }
private:
const bool drop_response_body_;
- // Application code value that was in the most recently received
- // STOP_SENDING frame for this stream.
- uint16_t last_stop_sending_code_;
};
} // namespace quic
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 a4bab0f5380..a548c6c906a 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
@@ -10,10 +10,12 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
+#include "net/third_party/quiche/src/quic/core/http/http_encoder.h"
#include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters_proto.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
@@ -228,9 +230,10 @@ class QuicSimpleServerSessionTest
QuicRandom::GetInstance(), &clock,
QuicCryptoServerConfig::ConfigOptions());
session_->Initialize();
- QuicSessionPeer::GetMutableCryptoStream(session_.get())
- ->OnSuccessfulVersionNegotiation(supported_versions.front());
- visitor_ = QuicConnectionPeer::GetVisitor(connection_);
+ if (!GetQuicReloadableFlag(quic_version_negotiated_by_default_at_server)) {
+ QuicSessionPeer::GetMutableCryptoStream(session_.get())
+ ->OnSuccessfulVersionNegotiation(supported_versions.front());
+ }
if (VersionHasIetfQuicFrames(transport_version())) {
EXPECT_CALL(*connection_, SendControlFrame(_))
@@ -284,12 +287,12 @@ class QuicSimpleServerSessionTest
QuicMemoryCacheBackend memory_cache_backend_;
std::unique_ptr<MockQuicSimpleServerSession> session_;
std::unique_ptr<CryptoHandshakeMessage> handshake_message_;
- QuicConnectionVisitorInterface* visitor_;
};
INSTANTIATE_TEST_SUITE_P(Tests,
QuicSimpleServerSessionTest,
- ::testing::ValuesIn(AllSupportedVersions()));
+ ::testing::ValuesIn(AllSupportedVersions()),
+ ::testing::PrintToStringParamName());
TEST_P(QuicSimpleServerSessionTest, CloseStreamDueToReset) {
// Open a stream, then reset it.
@@ -311,7 +314,7 @@ TEST_P(QuicSimpleServerSessionTest, CloseStreamDueToReset) {
OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
QUIC_RST_ACKNOWLEDGEMENT));
}
- visitor_->OnRstStream(rst1);
+ session_->OnRstStream(rst1);
// Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
// RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
// a one-way close.
@@ -320,7 +323,7 @@ TEST_P(QuicSimpleServerSessionTest, CloseStreamDueToReset) {
EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
// Send the same two bytes of payload in a new packet.
- visitor_->OnStreamFrame(data1);
+ session_->OnStreamFrame(data1);
// The stream should not be re-opened.
EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
@@ -340,7 +343,7 @@ TEST_P(QuicSimpleServerSessionTest, NeverOpenStreamDueToReset) {
OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
QUIC_RST_ACKNOWLEDGEMENT));
}
- visitor_->OnRstStream(rst1);
+ session_->OnRstStream(rst1);
// Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
// RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
// a one-way close.
@@ -352,7 +355,7 @@ TEST_P(QuicSimpleServerSessionTest, NeverOpenStreamDueToReset) {
// Send two bytes of payload.
QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
QuicStringPiece("HT"));
- visitor_->OnStreamFrame(data1);
+ session_->OnStreamFrame(data1);
// The stream should never be opened, now that the reset is received.
EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
@@ -365,8 +368,8 @@ TEST_P(QuicSimpleServerSessionTest, AcceptClosedStream) {
QuicStringPiece("\1\0\0\0\0\0\0\0HT"));
QuicStreamFrame frame2(GetNthClientInitiatedBidirectionalId(1), false, 0,
QuicStringPiece("\2\0\0\0\0\0\0\0HT"));
- visitor_->OnStreamFrame(frame1);
- visitor_->OnStreamFrame(frame2);
+ session_->OnStreamFrame(frame1);
+ session_->OnStreamFrame(frame2);
EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams());
// Send a reset (and expect the peer to send a RST in response).
@@ -381,7 +384,7 @@ TEST_P(QuicSimpleServerSessionTest, AcceptClosedStream) {
OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
QUIC_RST_ACKNOWLEDGEMENT));
}
- visitor_->OnRstStream(rst);
+ session_->OnRstStream(rst);
// Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
// RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
// a one-way close.
@@ -395,8 +398,8 @@ TEST_P(QuicSimpleServerSessionTest, AcceptClosedStream) {
QuicStringPiece("TP"));
QuicStreamFrame frame4(GetNthClientInitiatedBidirectionalId(1), false, 2,
QuicStringPiece("TP"));
- visitor_->OnStreamFrame(frame3);
- visitor_->OnStreamFrame(frame4);
+ session_->OnStreamFrame(frame3);
+ session_->OnStreamFrame(frame4);
// The stream should never be opened, now that the reset is received.
EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
EXPECT_TRUE(connection_->connected());
@@ -589,8 +592,10 @@ class QuicSimpleServerSessionServerPushTest
config_, connection_, &owner_, &stream_helper_, &crypto_config_,
&compressed_certs_cache_, &memory_cache_backend_);
session_->Initialize();
- QuicSessionPeer::GetMutableCryptoStream(session_.get())
- ->OnSuccessfulVersionNegotiation(supported_versions.front());
+ if (!GetQuicReloadableFlag(quic_version_negotiated_by_default_at_server)) {
+ QuicSessionPeer::GetMutableCryptoStream(session_.get())
+ ->OnSuccessfulVersionNegotiation(supported_versions.front());
+ }
// Needed to make new session flow control window and server push work.
if (VersionHasIetfQuicFrames(transport_version())) {
@@ -600,8 +605,6 @@ class QuicSimpleServerSessionServerPushTest
}
session_->OnConfigNegotiated();
- visitor_ = QuicConnectionPeer::GetVisitor(connection_);
-
if (!VersionUsesHttp3(connection_->transport_version())) {
session_->UnregisterStreamPriority(
QuicUtils::GetHeadersStreamId(connection_->transport_version()),
@@ -657,10 +660,9 @@ class QuicSimpleServerSessionServerPushTest
std::string data;
data_frame_header_length = 0;
if (VersionUsesHttp3(connection_->transport_version())) {
- HttpEncoder encoder;
std::unique_ptr<char[]> buffer;
data_frame_header_length =
- encoder.SerializeDataFrameHeader(body.length(), &buffer);
+ HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
std::string header(buffer.get(), data_frame_header_length);
data = header + body;
} else {
@@ -813,6 +815,12 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
// prevent a promised resource to be send out.
TEST_P(QuicSimpleServerSessionServerPushTest,
ResetPromisedStreamToCancelServerPush) {
+ if (VersionHasIetfQuicFrames(transport_version())) {
+ // This test is resetting a stream that is not opened yet. IETF QUIC has no
+ // way to handle this. Some similar tests can be added once CANCEL_PUSH is
+ // supported.
+ return;
+ }
MaybeConsumeHeadersStreamData();
session_->SetMaxAllowedPushId(kMaxQuicStreamId);
@@ -844,7 +852,7 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
.WillOnce(Invoke(&ClearControlFrame));
EXPECT_CALL(*connection_,
OnStreamReset(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT));
- visitor_->OnRstStream(rst);
+ session_->OnRstStream(rst);
// When the first 2 streams becomes draining, the two queued up stream could
// be created. But since one of them was marked cancelled due to RST frame,
@@ -863,8 +871,6 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
EXPECT_CALL(*connection_,
SendStreamData(stream_not_reset, 1, offset, NO_FIN));
offset++;
- }
- if (VersionUsesHttp3(connection_->transport_version())) {
EXPECT_CALL(*connection_,
SendStreamData(stream_not_reset, kHeadersFrameHeaderLength,
offset, NO_FIN));
@@ -873,8 +879,6 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
SendStreamData(stream_not_reset, kHeadersFramePayloadLength,
offset, NO_FIN));
offset += kHeadersFramePayloadLength;
- }
- if (VersionUsesHttp3(connection_->transport_version())) {
EXPECT_CALL(*connection_,
SendStreamData(stream_not_reset, data_frame_header_length,
offset, NO_FIN));
@@ -924,9 +928,9 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
// Resetting an open stream will close the stream and give space for extra
// stream to be opened.
QuicStreamId stream_got_reset = GetNthServerInitiatedUnidirectionalId(3);
- EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
EXPECT_CALL(*connection_, SendControlFrame(_));
if (!VersionHasIetfQuicFrames(transport_version())) {
+ EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
// For version 99, this is covered in InjectStopSending()
EXPECT_CALL(*connection_,
OnStreamReset(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT));
@@ -936,8 +940,6 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
EXPECT_CALL(*connection_,
SendStreamData(stream_to_open, 1, offset, NO_FIN));
offset++;
- }
- if (VersionUsesHttp3(connection_->transport_version())) {
EXPECT_CALL(*connection_,
SendStreamData(stream_to_open, kHeadersFrameHeaderLength,
offset, NO_FIN));
@@ -946,8 +948,6 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
SendStreamData(stream_to_open, kHeadersFramePayloadLength,
offset, NO_FIN));
offset += kHeadersFramePayloadLength;
- }
- if (VersionUsesHttp3(connection_->transport_version())) {
EXPECT_CALL(*connection_,
SendStreamData(stream_to_open, data_frame_header_length, offset,
NO_FIN));
@@ -968,8 +968,9 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
// available as it closes/etc them.
session_->OnMaxStreamsFrame(
QuicMaxStreamsFrame(0, num_resources + 3, /*unidirectional=*/true));
+ } else {
+ session_->OnRstStream(rst);
}
- visitor_->OnRstStream(rst);
// Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
// RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
// a one-way close.
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 783dba0c55c..50ca84fd188 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
@@ -8,6 +8,7 @@
#include <memory>
#include <utility>
+#include "net/third_party/quiche/src/quic/core/http/http_encoder.h"
#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
@@ -192,7 +193,6 @@ class QuicSimpleServerStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
header_list_.OnHeader(":authority", "www.google.com");
header_list_.OnHeader(":path", "/");
header_list_.OnHeader(":method", "POST");
- header_list_.OnHeader(":version", "HTTP/1.1");
header_list_.OnHeader("content-length", "11");
header_list_.OnHeaderBlockEnd(128, 128);
@@ -248,7 +248,6 @@ class QuicSimpleServerStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
std::unique_ptr<QuicBackendResponse> quic_response_;
std::string body_;
QuicHeaderList header_list_;
- HttpEncoder encoder_;
};
INSTANTIATE_TEST_SUITE_P(Tests,
@@ -262,7 +261,7 @@ TEST_P(QuicSimpleServerStreamTest, TestFraming) {
stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
- encoder_.SerializeDataFrameHeader(body_.length(), &buffer);
+ HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
std::string header = std::string(buffer.get(), header_length);
std::string data = UsesHttp3() ? header + body_ : body_;
stream_->OnStreamFrame(
@@ -280,7 +279,7 @@ TEST_P(QuicSimpleServerStreamTest, TestFramingOnePacket) {
stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
- encoder_.SerializeDataFrameHeader(body_.length(), &buffer);
+ HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
std::string header = std::string(buffer.get(), header_length);
std::string data = UsesHttp3() ? header + body_ : body_;
stream_->OnStreamFrame(
@@ -321,7 +320,7 @@ TEST_P(QuicSimpleServerStreamTest, TestFramingExtraData) {
stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
- encoder_.SerializeDataFrameHeader(body_.length(), &buffer);
+ HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
std::string header = std::string(buffer.get(), header_length);
std::string data = UsesHttp3() ? header + body_ : body_;
@@ -330,7 +329,7 @@ TEST_P(QuicSimpleServerStreamTest, TestFramingExtraData) {
// Content length is still 11. This will register as an error and we won't
// accept the bytes.
header_length =
- encoder_.SerializeDataFrameHeader(large_body.length(), &buffer);
+ HttpEncoder::SerializeDataFrameHeader(large_body.length(), &buffer);
header = std::string(buffer.get(), header_length);
std::string data2 = UsesHttp3() ? header + large_body : large_body;
stream_->OnStreamFrame(
@@ -345,17 +344,15 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus) {
spdy::SpdyHeaderBlock* request_headers = stream_->mutable_headers();
(*request_headers)[":path"] = "/bar";
(*request_headers)[":authority"] = "www.google.com";
- (*request_headers)[":version"] = "HTTP/1.1";
(*request_headers)[":method"] = "GET";
- response_headers_[":version"] = "HTTP/1.1";
// HTTP/2 only supports integer responsecode, so "200 OK" is illegal.
response_headers_[":status"] = "200 OK";
response_headers_["content-length"] = "5";
std::string body = "Yummm";
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
- encoder_.SerializeDataFrameHeader(body.length(), &buffer);
+ HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
memory_cache_backend_.AddResponse("www.google.com", "/bar",
std::move(response_headers_), body);
@@ -379,10 +376,8 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus2) {
spdy::SpdyHeaderBlock* request_headers = stream_->mutable_headers();
(*request_headers)[":path"] = "/bar";
(*request_headers)[":authority"] = "www.google.com";
- (*request_headers)[":version"] = "HTTP/1.1";
(*request_headers)[":method"] = "GET";
- response_headers_[":version"] = "HTTP/1.1";
// HTTP/2 only supports 3-digit-integer, so "+200" is illegal.
response_headers_[":status"] = "+200";
response_headers_["content-length"] = "5";
@@ -390,7 +385,7 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus2) {
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
- encoder_.SerializeDataFrameHeader(body.length(), &buffer);
+ HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
memory_cache_backend_.AddResponse("www.google.com", "/bar",
std::move(response_headers_), body);
@@ -422,10 +417,8 @@ TEST_P(QuicSimpleServerStreamTest, SendPushResponseWith404Response) {
spdy::SpdyHeaderBlock* request_headers = promised_stream->mutable_headers();
(*request_headers)[":path"] = "/bar";
(*request_headers)[":authority"] = "www.google.com";
- (*request_headers)[":version"] = "HTTP/1.1";
(*request_headers)[":method"] = "GET";
- response_headers_[":version"] = "HTTP/1.1";
response_headers_[":status"] = "404";
response_headers_["content-length"] = "8";
std::string body = "NotFound";
@@ -445,17 +438,15 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithValidHeaders) {
spdy::SpdyHeaderBlock* request_headers = stream_->mutable_headers();
(*request_headers)[":path"] = "/bar";
(*request_headers)[":authority"] = "www.google.com";
- (*request_headers)[":version"] = "HTTP/1.1";
(*request_headers)[":method"] = "GET";
- response_headers_[":version"] = "HTTP/1.1";
response_headers_[":status"] = "200";
response_headers_["content-length"] = "5";
std::string body = "Yummm";
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
- encoder_.SerializeDataFrameHeader(body.length(), &buffer);
+ HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
memory_cache_backend_.AddResponse("www.google.com", "/bar",
std::move(response_headers_), body);
@@ -483,7 +474,7 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithPushResources) {
std::string body = "Yummm";
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
- encoder_.SerializeDataFrameHeader(body.length(), &buffer);
+ HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
QuicBackendResponse::ServerPushInfo push_info(
QuicUrl(host, "/bar"), spdy::SpdyHeaderBlock(),
QuicStream::kDefaultPriority, "Push body");
@@ -495,7 +486,6 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithPushResources) {
spdy::SpdyHeaderBlock* request_headers = stream_->mutable_headers();
(*request_headers)[":path"] = request_path;
(*request_headers)[":authority"] = host;
- (*request_headers)[":version"] = "HTTP/1.1";
(*request_headers)[":method"] = "GET";
stream_->set_fin_received(true);
@@ -546,16 +536,14 @@ TEST_P(QuicSimpleServerStreamTest, PushResponseOnServerInitiatedStream) {
spdy::SpdyHeaderBlock headers;
headers[":path"] = kPath;
headers[":authority"] = kHost;
- headers[":version"] = "HTTP/1.1";
headers[":method"] = "GET";
- response_headers_[":version"] = "HTTP/1.1";
response_headers_[":status"] = "200";
response_headers_["content-length"] = "5";
const std::string kBody = "Hello";
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
- encoder_.SerializeDataFrameHeader(kBody.length(), &buffer);
+ HttpEncoder::SerializeDataFrameHeader(kBody.length(), &buffer);
memory_cache_backend_.AddResponse(kHost, kPath, std::move(response_headers_),
kBody);
@@ -645,6 +633,16 @@ TEST_P(QuicSimpleServerStreamTest,
EXPECT_FALSE(stream_->reading_stopped());
EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0);
+ if (VersionUsesHttp3(connection_->transport_version())) {
+ // Unidirectional stream type and then a Stream Cancellation instruction is
+ // sent on the QPACK decoder stream. Ignore these writes without any
+ // assumption on their number or size.
+ auto* qpack_decoder_stream =
+ QuicSpdySessionPeer::GetQpackDecoderSendStream(&session_);
+ EXPECT_CALL(session_, WritevData(qpack_decoder_stream,
+ qpack_decoder_stream->id(), _, _, _))
+ .Times(AnyNumber());
+ }
EXPECT_CALL(session_, SendRstStream(_, QUIC_RST_ACKNOWLEDGEMENT, _)).Times(1);
QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(),
QUIC_STREAM_CANCELLED, 1234);
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 3cd4cbdf4cf..6b4cc8d042f 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
@@ -37,14 +37,16 @@ QuicSpdyClientBase::QuicSpdyClientBase(
QuicConnectionHelperInterface* helper,
QuicAlarmFactory* alarm_factory,
std::unique_ptr<NetworkHelper> network_helper,
- std::unique_ptr<ProofVerifier> proof_verifier)
+ std::unique_ptr<ProofVerifier> proof_verifier,
+ std::unique_ptr<SessionCache> session_cache)
: QuicClientBase(server_id,
supported_versions,
config,
helper,
alarm_factory,
std::move(network_helper),
- std::move(proof_verifier)),
+ std::move(proof_verifier),
+ std::move(session_cache)),
store_response_(false),
latest_response_code_(-1),
max_allowed_push_id_(0),
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 2a1267fa8be..d95303855c4 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
@@ -23,6 +23,7 @@ namespace quic {
class ProofVerifier;
class QuicServerId;
+class SessionCache;
class QuicSpdyClientBase : public QuicClientBase,
public QuicClientPushPromiseIndex::Delegate,
@@ -69,7 +70,8 @@ class QuicSpdyClientBase : public QuicClientBase,
QuicConnectionHelperInterface* helper,
QuicAlarmFactory* alarm_factory,
std::unique_ptr<NetworkHelper> network_helper,
- std::unique_ptr<ProofVerifier> proof_verifier);
+ std::unique_ptr<ProofVerifier> proof_verifier,
+ std::unique_ptr<SessionCache> session_cache);
QuicSpdyClientBase(const QuicSpdyClientBase&) = delete;
QuicSpdyClientBase& operator=(const QuicSpdyClientBase&) = delete;
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc
index eee4e6132d7..41597359280 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc
@@ -63,7 +63,6 @@
namespace {
-using quic::QuicSocketAddress;
using quic::QuicStringPiece;
using quic::QuicTextUtils;
using quic::QuicUrl;
@@ -237,10 +236,6 @@ int QuicToyClient::SendRequestsAndPrintResponses(
std::cerr << "Failed to initialize client." << std::endl;
return 1;
}
- client->client_session()->set_qpack_maximum_dynamic_table_capacity(
- kDefaultQpackMaxDynamicTableCapacity);
- client->client_session()->set_qpack_maximum_blocked_streams(
- kDefaultMaximumBlockedStreams);
if (!client->Connect()) {
quic::QuicErrorCode error = client->session()->error();
if (error == quic::QUIC_INVALID_VERSION) {
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.cc
index fdb1bb6ce78..390dcf6aa0c 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.cc
@@ -62,12 +62,13 @@ int QuicToyServer::Start() {
ParsedQuicVersionVector supported_versions;
if (GetQuicFlag(FLAGS_quic_ietf_draft)) {
QuicVersionInitializeSupportForIetfDraft();
- ParsedQuicVersion version(PROTOCOL_TLS1_3, QUIC_VERSION_99);
- QuicEnableVersion(version);
- supported_versions = {version};
+ supported_versions = {ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99)};
} else {
supported_versions = AllSupportedVersions();
}
+ for (const auto& version : supported_versions) {
+ QuicEnableVersion(version);
+ }
auto proof_source = quic::CreateDefaultProofSource();
auto backend = backend_factory_->CreateBackend();
auto server = server_factory_->CreateServer(
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
new file mode 100644
index 00000000000..9b1ea04cfe6
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.cc
@@ -0,0 +1,55 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.h"
+
+#include <memory>
+
+#include "net/third_party/quiche/src/quic/core/quic_connection.h"
+#include "net/third_party/quiche/src/quic/core/quic_dispatcher.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
+#include "net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.h"
+
+namespace quic {
+
+QuicTransportSimpleServerDispatcher::QuicTransportSimpleServerDispatcher(
+ const QuicConfig* config,
+ const QuicCryptoServerConfig* crypto_config,
+ QuicVersionManager* version_manager,
+ std::unique_ptr<QuicConnectionHelperInterface> helper,
+ std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
+ std::unique_ptr<QuicAlarmFactory> alarm_factory,
+ uint8_t expected_server_connection_id_length,
+ QuicTransportSimpleServerSession::Mode mode,
+ std::vector<url::Origin> accepted_origins)
+ : QuicDispatcher(config,
+ crypto_config,
+ version_manager,
+ std::move(helper),
+ std::move(session_helper),
+ std::move(alarm_factory),
+ expected_server_connection_id_length),
+ mode_(mode),
+ accepted_origins_(accepted_origins) {}
+
+QuicSession* QuicTransportSimpleServerDispatcher::CreateQuicSession(
+ QuicConnectionId server_connection_id,
+ const QuicSocketAddress& peer_address,
+ QuicStringPiece /*alpn*/,
+ const ParsedQuicVersion& version) {
+ auto connection = std::make_unique<QuicConnection>(
+ server_connection_id, peer_address, helper(), alarm_factory(), writer(),
+ /*owns_writer=*/false, Perspective::IS_SERVER,
+ ParsedQuicVersionVector{version});
+ QuicTransportSimpleServerSession* session =
+ new QuicTransportSimpleServerSession(
+ connection.release(), /*owns_connection=*/true, this, config(),
+ GetSupportedVersions(), crypto_config(), compressed_certs_cache(),
+ mode_, accepted_origins_);
+ session->Initialize();
+ return session;
+}
+
+} // namespace quic
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
new file mode 100644
index 00000000000..ea4eb8bf8ef
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_dispatcher.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_TOOLS_QUIC_TRANSPORT_SIMPLE_SERVER_DISPATCHER_H_
+#define QUICHE_QUIC_TOOLS_QUIC_TRANSPORT_SIMPLE_SERVER_DISPATCHER_H_
+
+#include "url/origin.h"
+#include "net/third_party/quiche/src/quic/core/quic_dispatcher.h"
+#include "net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.h"
+
+namespace quic {
+
+// Dispatcher that creates a QuicTransportSimpleServerSession for every incoming
+// connection.
+class QuicTransportSimpleServerDispatcher : public QuicDispatcher {
+ public:
+ QuicTransportSimpleServerDispatcher(
+ const QuicConfig* config,
+ const QuicCryptoServerConfig* crypto_config,
+ QuicVersionManager* version_manager,
+ std::unique_ptr<QuicConnectionHelperInterface> helper,
+ std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
+ std::unique_ptr<QuicAlarmFactory> alarm_factory,
+ uint8_t expected_server_connection_id_length,
+ QuicTransportSimpleServerSession::Mode mode,
+ std::vector<url::Origin> accepted_origins);
+
+ protected:
+ QuicSession* CreateQuicSession(QuicConnectionId server_connection_id,
+ const QuicSocketAddress& peer_address,
+ QuicStringPiece alpn,
+ const ParsedQuicVersion& version) override;
+
+ QuicTransportSimpleServerSession::Mode mode_;
+ std::vector<url::Origin> accepted_origins_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_TOOLS_QUIC_TRANSPORT_SIMPLE_SERVER_DISPATCHER_H_
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
new file mode 100644
index 00000000000..6e86ccab78d
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.cc
@@ -0,0 +1,226 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.h"
+
+#include <memory>
+
+#include "url/gurl.h"
+#include "url/origin.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h"
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
+
+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();
+ 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_);
+ 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();
+ DCHECK(fin_sent);
+ }
+
+ private:
+ QuicTransportStream* stream_;
+ std::string data_;
+};
+
+} // namespace
+
+QuicTransportSimpleServerSession::QuicTransportSimpleServerSession(
+ QuicConnection* connection,
+ bool owns_connection,
+ Visitor* owner,
+ const QuicConfig& config,
+ const ParsedQuicVersionVector& supported_versions,
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ Mode mode,
+ std::vector<url::Origin> accepted_origins)
+ : QuicTransportServerSession(connection,
+ owner,
+ config,
+ supported_versions,
+ crypto_config,
+ compressed_certs_cache,
+ this),
+ connection_(connection),
+ owns_connection_(owns_connection),
+ mode_(mode),
+ accepted_origins_(accepted_origins) {}
+
+QuicTransportSimpleServerSession::~QuicTransportSimpleServerSession() {
+ if (owns_connection_) {
+ delete connection_;
+ }
+}
+
+void QuicTransportSimpleServerSession::OnIncomingDataStream(
+ QuicTransportStream* stream) {
+ switch (mode_) {
+ case DISCARD:
+ stream->set_visitor(std::make_unique<DiscardVisitor>(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));
+ 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));
+ break;
+ default:
+ QUIC_NOTREACHED();
+ break;
+ }
+ break;
+ }
+}
+
+void QuicTransportSimpleServerSession::OnCanCreateNewOutgoingStream(
+ bool unidirectional) {
+ if (mode_ == ECHO && unidirectional) {
+ MaybeEchoStreamsBack();
+ }
+}
+
+bool QuicTransportSimpleServerSession::CheckOrigin(url::Origin origin) {
+ if (accepted_origins_.empty()) {
+ return true;
+ }
+
+ for (const url::Origin& accepted_origin : accepted_origins_) {
+ if (origin.IsSameOriginWith(accepted_origin)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void QuicTransportSimpleServerSession::MaybeEchoStreamsBack() {
+ while (!streams_to_echo_back_.empty() &&
+ CanOpenNextOutgoingUnidirectionalStream()) {
+ // Remove the stream from the queue first, in order to avoid accidentally
+ // entering an infinite loop in case any of the following code calls
+ // OnCanCreateNewOutgoingStream().
+ std::string data = std::move(streams_to_echo_back_.front());
+ streams_to_echo_back_.pop_front();
+
+ auto stream_owned = std::make_unique<QuicTransportStream>(
+ GetNextOutgoingUnidirectionalStreamId(), this, this);
+ QuicTransportStream* stream = stream_owned.get();
+ ActivateStream(std::move(stream_owned));
+ QUIC_DVLOG(1) << "Opened echo response stream " << stream->id();
+
+ stream->set_visitor(
+ std::make_unique<UnidirectionalEchoWriteVisitor>(stream, data));
+ stream->visitor()->OnCanWrite();
+ }
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.h b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.h
new file mode 100644
index 00000000000..11f82f2d272
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_transport_simple_server_session.h
@@ -0,0 +1,72 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_TOOLS_QUIC_TRANSPORT_SIMPLE_SERVER_SESSION_H_
+#define QUICHE_QUIC_TOOLS_QUIC_TRANSPORT_SIMPLE_SERVER_SESSION_H_
+
+#include <memory>
+#include <vector>
+
+#include "url/origin.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h"
+#include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
+
+namespace quic {
+
+// QuicTransport simple server is a non-production server that can be used for
+// testing QuicTransport. It has two modes that can be changed using the
+// command line flags, "echo" and "discard".
+class QuicTransportSimpleServerSession
+ : public QuicTransportServerSession,
+ QuicTransportServerSession::ServerVisitor {
+ public:
+ enum Mode {
+ // In DISCARD mode, any data on incoming streams is discarded and no
+ // outgoing streams are initiated.
+ DISCARD,
+ // In ECHO mode, any data sent on a bidirectional stream is echoed back.
+ // Any data sent on a unidirectional stream is buffered, and echoed back on
+ // a server-initiated unidirectional stream that is sent as soon as a FIN is
+ // received on the incoming stream.
+ ECHO,
+ };
+
+ QuicTransportSimpleServerSession(
+ QuicConnection* connection,
+ bool owns_connection,
+ Visitor* owner,
+ const QuicConfig& config,
+ const ParsedQuicVersionVector& supported_versions,
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ Mode mode,
+ std::vector<url::Origin> accepted_origins);
+ ~QuicTransportSimpleServerSession();
+
+ void OnIncomingDataStream(QuicTransportStream* stream) override;
+ void OnCanCreateNewOutgoingStream(bool unidirectional) override;
+ bool CheckOrigin(url::Origin origin) override;
+
+ void EchoStreamBack(const std::string& data) {
+ streams_to_echo_back_.push_back(data);
+ MaybeEchoStreamsBack();
+ }
+
+ private:
+ void MaybeEchoStreamsBack();
+
+ QuicConnection* connection_;
+ const bool owns_connection_;
+ Mode mode_;
+ std::vector<url::Origin> accepted_origins_;
+ QuicDeque<std::string> streams_to_echo_back_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_TOOLS_QUIC_TRANSPORT_SIMPLE_SERVER_SESSION_H_