summaryrefslogtreecommitdiff
path: root/chromium/net/third_party
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-07-31 15:50:41 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-08-30 12:35:23 +0000
commit7b2ffa587235a47d4094787d72f38102089f402a (patch)
tree30e82af9cbab08a7fa028bb18f4f2987a3f74dfa /chromium/net/third_party
parentd94af01c90575348c4e81a418257f254b6f8d225 (diff)
downloadqtwebengine-chromium-7b2ffa587235a47d4094787d72f38102089f402a.tar.gz
BASELINE: Update Chromium to 76.0.3809.94
Change-Id: I321c3f5f929c105aec0f98c5091ef6108822e647 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/net/third_party')
-rw-r--r--chromium/net/third_party/nist-pkits/generate_tests.py8
-rw-r--r--chromium/net/third_party/nist-pkits/pkits_testcases-inl.h9
-rw-r--r--chromium/net/third_party/quiche/OWNERS3
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/api/quiche_logging.h6
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/api/quiche_ptr_util.h21
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/api/quiche_test.h10
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/api/quiche_unordered_containers.h24
-rw-r--r--chromium/net/third_party/quiche/src/common/simple_linked_hash_map.h246
-rw-r--r--chromium/net/third_party/quiche/src/common/simple_linked_hash_map_test.cc396
-rw-r--r--chromium/net/third_party/quiche/src/epoll_server/fake_simple_epoll_server.h5
-rw-r--r--chromium/net/third_party/quiche/src/epoll_server/platform/api/epoll_time.h2
-rw-r--r--chromium/net/third_party/quiche/src/epoll_server/simple_epoll_server_test.cc25
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/chlo_extractor.cc36
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/chlo_extractor_test.cc20
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.cc39
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr_sender_test.cc114
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender_test.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm_test.cc17
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/windowed_filter_test.cc44
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/channel_id.h48
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/channel_id_test.cc35
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.h1
-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.cc32
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_printer_bin.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_server_test.cc76
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.cc28
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/proof_source.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/proof_verifier.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.cc98
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc55
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.cc30
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.cc17
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.cc786
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h172
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters_test.cc710
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.cc50
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.h12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_frames_test.cc36
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_max_stream_id_frame.cc25
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_max_stream_id_frame.h40
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_max_streams_frame.cc30
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_max_streams_frame.h43
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_id_blocked_frame.cc27
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_id_blocked_frame.h40
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_streams_blocked_frame.cc33
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_streams_blocked_frame.h44
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc591
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_decoder.cc165
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_decoder.h26
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_decoder_test.cc199
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_encoder.cc76
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_encoder.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_encoder_test.cc85
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_frames.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream_test.cc20
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream_test.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc31
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_test.cc131
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream_test.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc109
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.h34
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc340
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc305
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h21
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_buffer_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc204
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc16
-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_decoder_stream_receiver_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender_test.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver_test.cc2
-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.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_encoder.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_encoder.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_round_trip_test.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.cc88
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.h61
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list_test.cc121
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_bandwidth_test.cc27
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_config.cc197
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_config.h39
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_config_test.cc49
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection.cc346
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection.h67
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_close_delegate_interface.h29
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_id_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_stats.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc1301
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_constants.h15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc22
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.cc154
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.h58
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker_test.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_stream_test.cc128
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_handshaker.cc36
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc35
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h24
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream_test.cc187
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.cc18
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_data_reader.cc16
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_data_reader.h14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_data_writer.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_data_writer.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_data_writer_test.cc70
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.cc809
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h158
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_dispatcher_test.cc1060
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h20
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_framer.cc1286
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_framer.h181
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_framer_test.cc1443
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_ietf_framer_test.cc88
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.cc222
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.h55
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_creator_test.cc119
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_generator.cc77
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_generator.h31
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_generator_test.cc238
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_number.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packets.cc48
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packets.h27
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packets_test.cc91
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_received_packet_manager.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc84
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc177
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_session.cc465
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_session.h97
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc303
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream.cc99
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream.h16
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc503
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.h309
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager_test.cc872
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.cc40
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer_test.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_test.cc37
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time_test.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.cc62
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager_test.cc58
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_types.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_types.h23
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_utils.cc63
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_utils.h11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_version_manager_test.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_versions.cc79
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_versions.h46
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc81
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list_test.cc282
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/stateless_rejector.cc162
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/stateless_rejector.h123
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/stateless_rejector_test.cc292
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc31
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_handshaker.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_handshaker_test.cc20
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.cc155
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.h62
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager_test.cc335
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/README.md12
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/README.md67
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_clock.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_flags.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address_test.cc63
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h9
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_optional.h17
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_string_utils_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_test.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_connection_helper.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.cc68
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.h52
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint_test.cc97
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_factory.cc15
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_fakes.h57
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_interval_counter_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_session.cc52
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_session.h40
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_session_test.cc116
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_stream.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/quartc_stream_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/quartc/simulated_packet_transport_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc251
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h79
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_client_promised_info.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_dispatcher.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_spdy_client_stream.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_time_wait_list_manager.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/packet_reordering_writer.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.cc22
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h17
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.cc26
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h12
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_server_session_base_peer.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.cc74
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.h19
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc16
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.cc27
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.h16
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.cc40
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.h20
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.cc129
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.h88
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils_test.cc50
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_quic_framer.cc25
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.cc56
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier_test.cc74
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/README.md99
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.h13
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator_test.cc22
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/fake_proof_verifier.h49
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_base.cc26
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_base.h9
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_bin.cc357
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.cc55
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.h28
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_epoll_server_factory.cc18
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_epoll_server_factory.h26
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc13
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_server.cc18
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_server.h16
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_server_bin.cc54
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session_test.cc140
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.cc33
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h14
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_spdy_server_base.h30
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_tcp_like_trace_converter.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_tcp_like_trace_converter_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc357
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.h45
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.cc73
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.h62
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler.h17
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.h2
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test_utils.h1
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_simple_arena.cc2
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_test_utils.h2
320 files changed, 13747 insertions, 10003 deletions
diff --git a/chromium/net/third_party/nist-pkits/generate_tests.py b/chromium/net/third_party/nist-pkits/generate_tests.py
index b2c42c2a059..2da0c120d7f 100644
--- a/chromium/net/third_party/nist-pkits/generate_tests.py
+++ b/chromium/net/third_party/nist-pkits/generate_tests.py
@@ -200,6 +200,8 @@ def parse_cert_path_lines(lines):
if "is composed of the following objects:" in line:
continue
+ if "See the introduction to Section 4.4 for more information." in line:
+ continue
if not line or PAGE_NUMBER_MATCHER.match(line):
continue
@@ -1182,6 +1184,12 @@ def main():
output = open(output_path, 'w')
output.write('// Autogenerated by %s, do not edit\n\n' % sys.argv[0])
+ output.write("""
+// This file intentionally does not have header guards, it's intended to
+// be inlined in another header file. The following line silences a
+// presubmit warning that would otherwise be triggered by this:
+// no-include-guard-because-multiply-included
+// NOLINT(build/header_guard)\n\n""")
output.write('// Hack to allow disabling type parameterized test cases.\n'
'// See https://github.com/google/googletest/issues/389\n')
output.write('#define WRAPPED_TYPED_TEST_P(CaseName, TestName) '
diff --git a/chromium/net/third_party/nist-pkits/pkits_testcases-inl.h b/chromium/net/third_party/nist-pkits/pkits_testcases-inl.h
index f83c0a244ed..6fee9585417 100644
--- a/chromium/net/third_party/nist-pkits/pkits_testcases-inl.h
+++ b/chromium/net/third_party/nist-pkits/pkits_testcases-inl.h
@@ -1,5 +1,11 @@
// Autogenerated by generate_tests.py, do not edit
+// This file intentionally does not have header guards, it's intended to
+// be inlined in another header file. The following line silences a
+// presubmit warning that would otherwise be triggered by this:
+// no-include-guard-because-multiply-included
+// NOLINT(build/header_guard)
+
// Hack to allow disabling type parameterized test cases.
// See https://github.com/google/googletest/issues/389
#define WRAPPED_TYPED_TEST_P(CaseName, TestName) \
@@ -556,8 +562,7 @@ WRAPPED_TYPED_TEST_P(PkitsTest04BasicCertificateRevocationTests,
Section4Invalidpre2000CRLnextUpdateTest12) {
const char* const certs[] = {"TrustAnchorRootCertificate",
"pre2000CRLnextUpdateCACert",
- "Invalidpre2000CRLnextUpdateTest12EESeetheintrod"
- "uctiontoSection4.4formoreinformation."};
+ "Invalidpre2000CRLnextUpdateTest12EE"};
const char* const crls[] = {"TrustAnchorRootCRL",
"pre2000CRLnextUpdateCACRL"};
PkitsTestInfo info;
diff --git a/chromium/net/third_party/quiche/OWNERS b/chromium/net/third_party/quiche/OWNERS
new file mode 100644
index 00000000000..e2c377d23b0
--- /dev/null
+++ b/chromium/net/third_party/quiche/OWNERS
@@ -0,0 +1,3 @@
+file://net/quic/OWNERS
+
+# COMPONENT: Internals>Network>QUIC
diff --git a/chromium/net/third_party/quiche/src/common/platform/api/quiche_logging.h b/chromium/net/third_party/quiche/src/common/platform/api/quiche_logging.h
new file mode 100644
index 00000000000..15f5bf3fbc5
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/platform/api/quiche_logging.h
@@ -0,0 +1,6 @@
+#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_LOGGING_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_LOGGING_H_
+
+#include "net/quiche/common/platform/impl/quiche_logging_impl.h"
+
+#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_LOGGING_H_
diff --git a/chromium/net/third_party/quiche/src/common/platform/api/quiche_ptr_util.h b/chromium/net/third_party/quiche/src/common/platform/api/quiche_ptr_util.h
new file mode 100644
index 00000000000..26b152bd47f
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/platform/api/quiche_ptr_util.h
@@ -0,0 +1,21 @@
+// 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_COMMON_PLATFORM_API_QUICHE_PTR_UTIL_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_PTR_UTIL_H_
+
+#include <memory>
+
+#include "net/quiche/common/platform/impl/quiche_ptr_util_impl.h"
+
+namespace quiche {
+
+template <typename T, typename... Args>
+std::unique_ptr<T> QuicheMakeUnique(Args&&... args) {
+ return QuicheMakeUniqueImpl<T>(std::forward<Args>(args)...);
+}
+
+} // namespace quiche
+
+#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_PTR_UTIL_H_
diff --git a/chromium/net/third_party/quiche/src/common/platform/api/quiche_test.h b/chromium/net/third_party/quiche/src/common/platform/api/quiche_test.h
new file mode 100644
index 00000000000..f51c85e63a0
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/platform/api/quiche_test.h
@@ -0,0 +1,10 @@
+// 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_COMMON_PLATFORM_API_QUICHE_TEST_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_H_
+
+#include "net/quiche/common/platform/impl/quiche_test_impl.h"
+
+#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_H_
diff --git a/chromium/net/third_party/quiche/src/common/platform/api/quiche_unordered_containers.h b/chromium/net/third_party/quiche/src/common/platform/api/quiche_unordered_containers.h
new file mode 100644
index 00000000000..583f97eba65
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/platform/api/quiche_unordered_containers.h
@@ -0,0 +1,24 @@
+// 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_COMMON_PLATFORM_API_QUICHE_UNORDERED_CONTAINERS_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_UNORDERED_CONTAINERS_H_
+
+#include "net/quiche/common/platform/impl/quiche_unordered_containers_impl.h"
+
+namespace quiche {
+
+// The default hasher used by hash tables.
+template <typename Key>
+using QuicheDefaultHasher = QuicheDefaultHasherImpl<Key>;
+
+// A general-purpose unordered map.
+template <typename Key,
+ typename Value,
+ typename Hash = QuicheDefaultHasher<Key>>
+using QuicheUnorderedMap = QuicheUnorderedMapImpl<Key, Value, Hash>;
+
+} // namespace quiche
+
+#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_UNORDERED_CONTAINERS_H_
diff --git a/chromium/net/third_party/quiche/src/common/simple_linked_hash_map.h b/chromium/net/third_party/quiche/src/common/simple_linked_hash_map.h
new file mode 100644
index 00000000000..c99585e2092
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/simple_linked_hash_map.h
@@ -0,0 +1,246 @@
+// 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.
+
+// This is a simplistic insertion-ordered map. It behaves similarly to an STL
+// map, but only implements a small subset of the map's methods. Internally, we
+// just keep a map and a list going in parallel.
+//
+// This class provides no thread safety guarantees, beyond what you would
+// normally see with std::list.
+//
+// Iterators point into the list and should be stable in the face of
+// mutations, except for an iterator pointing to an element that was just
+// deleted.
+
+#ifndef QUICHE_COMMON_SIMPLE_LINKED_HASH_MAP_H_
+#define QUICHE_COMMON_SIMPLE_LINKED_HASH_MAP_H_
+
+#include <list>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_logging.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_unordered_containers.h"
+
+namespace quiche {
+
+// This holds a list of pair<Key, Value> items. This list is what gets
+// traversed, and it's iterators from this list that we return from
+// begin/end/find.
+//
+// We also keep a set<list::iterator> for find. Since std::list is a
+// doubly-linked list, the iterators should remain stable.
+
+template <class Key, class Value, class Hash = std::hash<Key>>
+class SimpleLinkedHashMap {
+ private:
+ typedef std::list<std::pair<Key, Value>> ListType;
+ typedef QuicheUnorderedMap<Key, typename ListType::iterator, Hash> MapType;
+
+ public:
+ typedef typename ListType::iterator iterator;
+ typedef typename ListType::reverse_iterator reverse_iterator;
+ typedef typename ListType::const_iterator const_iterator;
+ typedef typename ListType::const_reverse_iterator const_reverse_iterator;
+ typedef typename MapType::key_type key_type;
+ typedef typename ListType::value_type value_type;
+ typedef typename ListType::size_type size_type;
+
+ SimpleLinkedHashMap() = default;
+ explicit SimpleLinkedHashMap(size_type bucket_count) : map_(bucket_count) {}
+
+ SimpleLinkedHashMap(const SimpleLinkedHashMap& other) = delete;
+ SimpleLinkedHashMap& operator=(const SimpleLinkedHashMap& other) = delete;
+ SimpleLinkedHashMap(SimpleLinkedHashMap&& other) = default;
+ SimpleLinkedHashMap& operator=(SimpleLinkedHashMap&& other) = default;
+
+ // Returns an iterator to the first (insertion-ordered) element. Like a map,
+ // this can be dereferenced to a pair<Key, Value>.
+ iterator begin() { return list_.begin(); }
+ const_iterator begin() const { return list_.begin(); }
+
+ // Returns an iterator beyond the last element.
+ iterator end() { return list_.end(); }
+ const_iterator end() const { return list_.end(); }
+
+ // Returns an iterator to the last (insertion-ordered) element. Like a map,
+ // this can be dereferenced to a pair<Key, Value>.
+ reverse_iterator rbegin() { return list_.rbegin(); }
+ const_reverse_iterator rbegin() const { return list_.rbegin(); }
+
+ // Returns an iterator beyond the first element.
+ reverse_iterator rend() { return list_.rend(); }
+ const_reverse_iterator rend() const { return list_.rend(); }
+
+ // Front and back accessors common to many stl containers.
+
+ // Returns the earliest-inserted element
+ const value_type& front() const { return list_.front(); }
+
+ // Returns the earliest-inserted element.
+ value_type& front() { return list_.front(); }
+
+ // Returns the most-recently-inserted element.
+ const value_type& back() const { return list_.back(); }
+
+ // Returns the most-recently-inserted element.
+ value_type& back() { return list_.back(); }
+
+ // Clears the map of all values.
+ void clear() {
+ map_.clear();
+ list_.clear();
+ }
+
+ // Returns true iff the map is empty.
+ bool empty() const { return list_.empty(); }
+
+ // Removes the first element from the list.
+ void pop_front() { erase(begin()); }
+
+ // Erases values with the provided key. Returns the number of elements
+ // erased. In this implementation, this will be 0 or 1.
+ size_type erase(const Key& key) {
+ typename MapType::iterator found = map_.find(key);
+ if (found == map_.end()) {
+ return 0;
+ }
+
+ list_.erase(found->second);
+ map_.erase(found);
+
+ return 1;
+ }
+
+ // Erases the item that 'position' points to. Returns an iterator that points
+ // to the item that comes immediately after the deleted item in the list, or
+ // end().
+ // If the provided iterator is invalid or there is inconsistency between the
+ // map and list, a CHECK() error will occur.
+ iterator erase(iterator position) {
+ typename MapType::iterator found = map_.find(position->first);
+ CHECK(found->second == position)
+ << "Inconsisent iterator for map and list, or the iterator is invalid.";
+
+ map_.erase(found);
+ return list_.erase(position);
+ }
+
+ // Erases all the items in the range [first, last). Returns an iterator that
+ // points to the item that comes immediately after the last deleted item in
+ // the list, or end().
+ iterator erase(iterator first, iterator last) {
+ while (first != last && first != end()) {
+ first = erase(first);
+ }
+ return first;
+ }
+
+ // Finds the element with the given key. Returns an iterator to the
+ // value found, or to end() if the value was not found. Like a map, this
+ // iterator points to a pair<Key, Value>.
+ iterator find(const Key& key) {
+ typename MapType::iterator found = map_.find(key);
+ if (found == map_.end()) {
+ return end();
+ }
+ return found->second;
+ }
+
+ const_iterator find(const Key& key) const {
+ typename MapType::const_iterator found = map_.find(key);
+ if (found == map_.end()) {
+ return end();
+ }
+ return found->second;
+ }
+
+ bool contains(const Key& key) const { return find(key) != end(); }
+
+ // Returns the value mapped to key, or an inserted iterator to that position
+ // in the map.
+ Value& operator[](const key_type& key) {
+ return (*((this->insert(std::make_pair(key, Value()))).first)).second;
+ }
+
+ // Inserts an element into the map
+ std::pair<iterator, bool> insert(const std::pair<Key, Value>& pair) {
+ // First make sure the map doesn't have a key with this value. If it does,
+ // return a pair with an iterator to it, and false indicating that we
+ // didn't insert anything.
+ typename MapType::iterator found = map_.find(pair.first);
+ if (found != map_.end()) {
+ return std::make_pair(found->second, false);
+ }
+
+ // Otherwise, insert into the list first.
+ list_.push_back(pair);
+
+ // Obtain an iterator to the newly added element. We do -- instead of -
+ // since list::iterator doesn't implement operator-().
+ typename ListType::iterator last = list_.end();
+ --last;
+
+ CHECK(map_.insert(std::make_pair(pair.first, last)).second)
+ << "Map and list are inconsistent";
+
+ return std::make_pair(last, true);
+ }
+
+ // Inserts an element into the map
+ std::pair<iterator, bool> insert(std::pair<Key, Value>&& pair) {
+ // First make sure the map doesn't have a key with this value. If it does,
+ // return a pair with an iterator to it, and false indicating that we
+ // didn't insert anything.
+ typename MapType::iterator found = map_.find(pair.first);
+ if (found != map_.end()) {
+ return std::make_pair(found->second, false);
+ }
+
+ // Otherwise, insert into the list first.
+ list_.push_back(std::move(pair));
+
+ // Obtain an iterator to the newly added element. We do -- instead of -
+ // since list::iterator doesn't implement operator-().
+ typename ListType::iterator last = list_.end();
+ --last;
+
+ CHECK(map_.insert(std::make_pair(pair.first, last)).second)
+ << "Map and list are inconsistent";
+ return std::make_pair(last, true);
+ }
+
+ size_type size() const { return list_.size(); }
+
+ template <typename... Args>
+ std::pair<iterator, bool> emplace(Args&&... args) {
+ ListType node_donor;
+ auto node_pos =
+ node_donor.emplace(node_donor.end(), std::forward<Args>(args)...);
+ const auto& k = node_pos->first;
+ auto ins = map_.insert({k, node_pos});
+ if (!ins.second) {
+ return {ins.first->second, false};
+ }
+ list_.splice(list_.end(), node_donor, node_pos);
+ return {ins.first->second, true};
+ }
+
+ void swap(SimpleLinkedHashMap& other) {
+ map_.swap(other.map_);
+ list_.swap(other.list_);
+ }
+
+ private:
+ // The map component, used for speedy lookups
+ MapType map_;
+
+ // The list component, used for maintaining insertion order
+ ListType list_;
+};
+
+} // namespace quiche
+
+#endif // QUICHE_COMMON_SIMPLE_LINKED_HASH_MAP_H_
diff --git a/chromium/net/third_party/quiche/src/common/simple_linked_hash_map_test.cc b/chromium/net/third_party/quiche/src/common/simple_linked_hash_map_test.cc
new file mode 100644
index 00000000000..0ea7d8a015d
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/simple_linked_hash_map_test.cc
@@ -0,0 +1,396 @@
+// 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.
+
+// Tests SimpleLinkedHashMap.
+
+#include "net/third_party/quiche/src/common/simple_linked_hash_map.h"
+
+#include <memory>
+#include <utility>
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_ptr_util.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_test.h"
+
+using testing::Pair;
+using testing::Pointee;
+using testing::UnorderedElementsAre;
+
+namespace quiche {
+namespace test {
+
+// Tests that move constructor works.
+TEST(LinkedHashMapTest, Move) {
+ // Use unique_ptr as an example of a non-copyable type.
+ SimpleLinkedHashMap<int, std::unique_ptr<int>> m;
+ m[2] = QuicheMakeUnique<int>(12);
+ m[3] = QuicheMakeUnique<int>(13);
+ SimpleLinkedHashMap<int, std::unique_ptr<int>> n = std::move(m);
+ EXPECT_THAT(n,
+ UnorderedElementsAre(Pair(2, Pointee(12)), Pair(3, Pointee(13))));
+}
+
+TEST(LinkedHashMapTest, CanEmplaceMoveOnly) {
+ SimpleLinkedHashMap<int, std::unique_ptr<int>> m;
+ struct Data {
+ int k, v;
+ };
+ const Data data[] = {{1, 123}, {3, 345}, {2, 234}, {4, 456}};
+ for (const auto& kv : data) {
+ m.emplace(std::piecewise_construct, std::make_tuple(kv.k),
+ std::make_tuple(new int{kv.v}));
+ }
+ EXPECT_TRUE(m.contains(2));
+ auto found = m.find(2);
+ ASSERT_TRUE(found != m.end());
+ EXPECT_EQ(234, *found->second);
+}
+
+struct NoCopy {
+ explicit NoCopy(int x) : x(x) {}
+ NoCopy(const NoCopy&) = delete;
+ NoCopy& operator=(const NoCopy&) = delete;
+ NoCopy(NoCopy&&) = delete;
+ NoCopy& operator=(NoCopy&&) = delete;
+ int x;
+};
+
+TEST(LinkedHashMapTest, CanEmplaceNoMoveNoCopy) {
+ SimpleLinkedHashMap<int, NoCopy> m;
+ struct Data {
+ int k, v;
+ };
+ const Data data[] = {{1, 123}, {3, 345}, {2, 234}, {4, 456}};
+ for (const auto& kv : data) {
+ m.emplace(std::piecewise_construct, std::make_tuple(kv.k),
+ std::make_tuple(kv.v));
+ }
+ EXPECT_TRUE(m.contains(2));
+ auto found = m.find(2);
+ ASSERT_TRUE(found != m.end());
+ EXPECT_EQ(234, found->second.x);
+}
+
+TEST(LinkedHashMapTest, ConstKeys) {
+ SimpleLinkedHashMap<int, int> m;
+ m.insert(std::make_pair(1, 2));
+ // Test that keys are const in iteration.
+ std::pair<int, int>& p = *m.begin();
+ EXPECT_EQ(1, p.first);
+}
+
+// Tests that iteration from begin() to end() works
+TEST(LinkedHashMapTest, Iteration) {
+ SimpleLinkedHashMap<int, int> m;
+ EXPECT_TRUE(m.begin() == m.end());
+
+ m.insert(std::make_pair(2, 12));
+ m.insert(std::make_pair(1, 11));
+ m.insert(std::make_pair(3, 13));
+
+ SimpleLinkedHashMap<int, int>::iterator i = m.begin();
+ ASSERT_TRUE(m.begin() == i);
+ ASSERT_TRUE(m.end() != i);
+ EXPECT_EQ(2, i->first);
+ EXPECT_EQ(12, i->second);
+
+ ++i;
+ ASSERT_TRUE(m.end() != i);
+ EXPECT_EQ(1, i->first);
+ EXPECT_EQ(11, i->second);
+
+ ++i;
+ ASSERT_TRUE(m.end() != i);
+ EXPECT_EQ(3, i->first);
+ EXPECT_EQ(13, i->second);
+
+ ++i; // Should be the end of the line.
+ ASSERT_TRUE(m.end() == i);
+}
+
+// Tests that reverse iteration from rbegin() to rend() works
+TEST(LinkedHashMapTest, ReverseIteration) {
+ SimpleLinkedHashMap<int, int> m;
+ EXPECT_TRUE(m.rbegin() == m.rend());
+
+ m.insert(std::make_pair(2, 12));
+ m.insert(std::make_pair(1, 11));
+ m.insert(std::make_pair(3, 13));
+
+ SimpleLinkedHashMap<int, int>::reverse_iterator i = m.rbegin();
+ ASSERT_TRUE(m.rbegin() == i);
+ ASSERT_TRUE(m.rend() != i);
+ EXPECT_EQ(3, i->first);
+ EXPECT_EQ(13, i->second);
+
+ ++i;
+ ASSERT_TRUE(m.rend() != i);
+ EXPECT_EQ(1, i->first);
+ EXPECT_EQ(11, i->second);
+
+ ++i;
+ ASSERT_TRUE(m.rend() != i);
+ EXPECT_EQ(2, i->first);
+ EXPECT_EQ(12, i->second);
+
+ ++i; // Should be the end of the line.
+ ASSERT_TRUE(m.rend() == i);
+}
+
+// Tests that clear() works
+TEST(LinkedHashMapTest, Clear) {
+ SimpleLinkedHashMap<int, int> m;
+ m.insert(std::make_pair(2, 12));
+ m.insert(std::make_pair(1, 11));
+ m.insert(std::make_pair(3, 13));
+
+ ASSERT_EQ(3u, m.size());
+
+ m.clear();
+
+ EXPECT_EQ(0u, m.size());
+
+ m.clear(); // Make sure we can call it on an empty map.
+
+ EXPECT_EQ(0u, m.size());
+}
+
+// Tests that size() works.
+TEST(LinkedHashMapTest, Size) {
+ SimpleLinkedHashMap<int, int> m;
+ EXPECT_EQ(0u, m.size());
+ m.insert(std::make_pair(2, 12));
+ EXPECT_EQ(1u, m.size());
+ m.insert(std::make_pair(1, 11));
+ EXPECT_EQ(2u, m.size());
+ m.insert(std::make_pair(3, 13));
+ EXPECT_EQ(3u, m.size());
+ m.clear();
+ EXPECT_EQ(0u, m.size());
+}
+
+// Tests empty()
+TEST(LinkedHashMapTest, Empty) {
+ SimpleLinkedHashMap<int, int> m;
+ ASSERT_TRUE(m.empty());
+ m.insert(std::make_pair(2, 12));
+ ASSERT_FALSE(m.empty());
+ m.clear();
+ ASSERT_TRUE(m.empty());
+}
+
+TEST(LinkedHashMapTest, Erase) {
+ SimpleLinkedHashMap<int, int> m;
+ ASSERT_EQ(0u, m.size());
+ EXPECT_EQ(0u, m.erase(2)); // Nothing to erase yet
+
+ m.insert(std::make_pair(2, 12));
+ ASSERT_EQ(1u, m.size());
+ EXPECT_EQ(1u, m.erase(2));
+ EXPECT_EQ(0u, m.size());
+
+ EXPECT_EQ(0u, m.erase(2)); // Make sure nothing bad happens if we repeat.
+ EXPECT_EQ(0u, m.size());
+}
+
+TEST(LinkedHashMapTest, Erase2) {
+ SimpleLinkedHashMap<int, int> m;
+ ASSERT_EQ(0u, m.size());
+ EXPECT_EQ(0u, m.erase(2)); // Nothing to erase yet
+
+ m.insert(std::make_pair(2, 12));
+ m.insert(std::make_pair(1, 11));
+ m.insert(std::make_pair(3, 13));
+ m.insert(std::make_pair(4, 14));
+ ASSERT_EQ(4u, m.size());
+
+ // Erase middle two
+ EXPECT_EQ(1u, m.erase(1));
+ EXPECT_EQ(1u, m.erase(3));
+
+ EXPECT_EQ(2u, m.size());
+
+ // Make sure we can still iterate over everything that's left.
+ SimpleLinkedHashMap<int, int>::iterator it = m.begin();
+ ASSERT_TRUE(it != m.end());
+ EXPECT_EQ(12, it->second);
+ ++it;
+ ASSERT_TRUE(it != m.end());
+ EXPECT_EQ(14, it->second);
+ ++it;
+ ASSERT_TRUE(it == m.end());
+
+ EXPECT_EQ(0u, m.erase(1)); // Make sure nothing bad happens if we repeat.
+ ASSERT_EQ(2u, m.size());
+
+ EXPECT_EQ(1u, m.erase(2));
+ EXPECT_EQ(1u, m.erase(4));
+ ASSERT_EQ(0u, m.size());
+
+ EXPECT_EQ(0u, m.erase(1)); // Make sure nothing bad happens if we repeat.
+ ASSERT_EQ(0u, m.size());
+}
+
+// Test that erase(iter,iter) and erase(iter) compile and work.
+TEST(LinkedHashMapTest, Erase3) {
+ SimpleLinkedHashMap<int, int> m;
+
+ m.insert(std::make_pair(1, 11));
+ m.insert(std::make_pair(2, 12));
+ m.insert(std::make_pair(3, 13));
+ m.insert(std::make_pair(4, 14));
+
+ // Erase middle two
+ SimpleLinkedHashMap<int, int>::iterator it2 = m.find(2);
+ SimpleLinkedHashMap<int, int>::iterator it4 = m.find(4);
+ EXPECT_EQ(m.erase(it2, it4), m.find(4));
+ EXPECT_EQ(2u, m.size());
+
+ // Make sure we can still iterate over everything that's left.
+ SimpleLinkedHashMap<int, int>::iterator it = m.begin();
+ ASSERT_TRUE(it != m.end());
+ EXPECT_EQ(11, it->second);
+ ++it;
+ ASSERT_TRUE(it != m.end());
+ EXPECT_EQ(14, it->second);
+ ++it;
+ ASSERT_TRUE(it == m.end());
+
+ // Erase first one using an iterator.
+ EXPECT_EQ(m.erase(m.begin()), m.find(4));
+
+ // Only the last element should be left.
+ it = m.begin();
+ ASSERT_TRUE(it != m.end());
+ EXPECT_EQ(14, it->second);
+ ++it;
+ ASSERT_TRUE(it == m.end());
+}
+
+TEST(LinkedHashMapTest, Insertion) {
+ SimpleLinkedHashMap<int, int> m;
+ ASSERT_EQ(0u, m.size());
+ std::pair<SimpleLinkedHashMap<int, int>::iterator, bool> result;
+
+ result = m.insert(std::make_pair(2, 12));
+ ASSERT_EQ(1u, m.size());
+ EXPECT_TRUE(result.second);
+ EXPECT_EQ(2, result.first->first);
+ EXPECT_EQ(12, result.first->second);
+
+ result = m.insert(std::make_pair(1, 11));
+ ASSERT_EQ(2u, m.size());
+ EXPECT_TRUE(result.second);
+ EXPECT_EQ(1, result.first->first);
+ EXPECT_EQ(11, result.first->second);
+
+ result = m.insert(std::make_pair(3, 13));
+ SimpleLinkedHashMap<int, int>::iterator result_iterator = result.first;
+ ASSERT_EQ(3u, m.size());
+ EXPECT_TRUE(result.second);
+ EXPECT_EQ(3, result.first->first);
+ EXPECT_EQ(13, result.first->second);
+
+ result = m.insert(std::make_pair(3, 13));
+ EXPECT_EQ(3u, m.size());
+ EXPECT_FALSE(result.second) << "No insertion should have occurred.";
+ EXPECT_TRUE(result_iterator == result.first)
+ << "Duplicate insertion should have given us the original iterator.";
+}
+
+static std::pair<int, int> Pair(int i, int j) {
+ return {i, j};
+}
+
+// Test front accessors.
+TEST(LinkedHashMapTest, Front) {
+ SimpleLinkedHashMap<int, int> m;
+
+ m.insert(std::make_pair(2, 12));
+ m.insert(std::make_pair(1, 11));
+ m.insert(std::make_pair(3, 13));
+
+ EXPECT_EQ(3u, m.size());
+ EXPECT_EQ(Pair(2, 12), m.front());
+ m.pop_front();
+ EXPECT_EQ(2u, m.size());
+ EXPECT_EQ(Pair(1, 11), m.front());
+ m.pop_front();
+ EXPECT_EQ(1u, m.size());
+ EXPECT_EQ(Pair(3, 13), m.front());
+ m.pop_front();
+ EXPECT_TRUE(m.empty());
+}
+
+TEST(LinkedHashMapTest, Find) {
+ SimpleLinkedHashMap<int, int> m;
+
+ EXPECT_TRUE(m.end() == m.find(1))
+ << "We shouldn't find anything in an empty map.";
+
+ m.insert(std::make_pair(2, 12));
+ EXPECT_TRUE(m.end() == m.find(1))
+ << "We shouldn't find an element that doesn't exist in the map.";
+
+ std::pair<SimpleLinkedHashMap<int, int>::iterator, bool> result =
+ m.insert(std::make_pair(1, 11));
+ ASSERT_TRUE(result.second);
+ ASSERT_TRUE(m.end() != result.first);
+ EXPECT_TRUE(result.first == m.find(1))
+ << "We should have found an element we know exists in the map.";
+ EXPECT_EQ(11, result.first->second);
+
+ // Check that a follow-up insertion doesn't affect our original
+ m.insert(std::make_pair(3, 13));
+ SimpleLinkedHashMap<int, int>::iterator it = m.find(1);
+ ASSERT_TRUE(m.end() != it);
+ EXPECT_EQ(11, it->second);
+
+ m.clear();
+ EXPECT_TRUE(m.end() == m.find(1))
+ << "We shouldn't find anything in a map that we've cleared.";
+}
+
+TEST(LinkedHashMapTest, Contains) {
+ SimpleLinkedHashMap<int, int> m;
+
+ EXPECT_FALSE(m.contains(1)) << "An empty map shouldn't contain anything.";
+
+ m.insert(std::make_pair(2, 12));
+ EXPECT_FALSE(m.contains(1))
+ << "The map shouldn't contain an element that doesn't exist.";
+
+ m.insert(std::make_pair(1, 11));
+ EXPECT_TRUE(m.contains(1))
+ << "The map should contain an element that we know exists.";
+
+ m.clear();
+ EXPECT_FALSE(m.contains(1))
+ << "A map that we've cleared shouldn't contain anything.";
+}
+
+TEST(LinkedHashMapTest, Swap) {
+ SimpleLinkedHashMap<int, int> m1;
+ SimpleLinkedHashMap<int, int> m2;
+ m1.insert(std::make_pair(1, 1));
+ m1.insert(std::make_pair(2, 2));
+ m2.insert(std::make_pair(3, 3));
+ ASSERT_EQ(2u, m1.size());
+ ASSERT_EQ(1u, m2.size());
+ m1.swap(m2);
+ ASSERT_EQ(1u, m1.size());
+ ASSERT_EQ(2u, m2.size());
+}
+
+TEST(LinkedHashMapTest, CustomHashAndEquality) {
+ struct CustomIntHash {
+ size_t operator()(int x) const { return x; }
+ };
+ SimpleLinkedHashMap<int, int, CustomIntHash> m;
+ m.insert(std::make_pair(1, 1));
+ EXPECT_TRUE(m.contains(1));
+ EXPECT_EQ(1, m[1]);
+}
+
+} // namespace test
+} // namespace quiche
diff --git a/chromium/net/third_party/quiche/src/epoll_server/fake_simple_epoll_server.h b/chromium/net/third_party/quiche/src/epoll_server/fake_simple_epoll_server.h
index 470311a4088..cd5bd3a8808 100644
--- a/chromium/net/third_party/quiche/src/epoll_server/fake_simple_epoll_server.h
+++ b/chromium/net/third_party/quiche/src/epoll_server/fake_simple_epoll_server.h
@@ -8,8 +8,7 @@
#include <stddef.h>
#include <stdint.h>
-#include <unordered_map>
-#include <unordered_set>
+#include <map>
#include "net/third_party/quiche/src/epoll_server/platform/api/epoll_export.h"
#include "net/third_party/quiche/src/epoll_server/simple_epoll_server.h"
@@ -57,7 +56,7 @@ class EPOLL_EXPORT_PRIVATE FakeTimeSimpleEpollServer
class EPOLL_EXPORT_PRIVATE FakeSimpleEpollServer
: public FakeTimeSimpleEpollServer {
public: // type definitions
- using EventQueue = std::unordered_multimap<int64_t, struct epoll_event>;
+ using EventQueue = std::multimap<int64_t, struct epoll_event>;
FakeSimpleEpollServer();
FakeSimpleEpollServer(const FakeSimpleEpollServer&) = delete;
diff --git a/chromium/net/third_party/quiche/src/epoll_server/platform/api/epoll_time.h b/chromium/net/third_party/quiche/src/epoll_server/platform/api/epoll_time.h
index 95f04079a97..3d263848b5c 100644
--- a/chromium/net/third_party/quiche/src/epoll_server/platform/api/epoll_time.h
+++ b/chromium/net/third_party/quiche/src/epoll_server/platform/api/epoll_time.h
@@ -9,7 +9,7 @@
namespace epoll_server {
-int64_t WallTimeNowInUsec() { return WallTimeNowInUsecImpl(); }
+inline int64_t WallTimeNowInUsec() { return WallTimeNowInUsecImpl(); }
} // namespace epoll_server
diff --git a/chromium/net/third_party/quiche/src/epoll_server/simple_epoll_server_test.cc b/chromium/net/third_party/quiche/src/epoll_server/simple_epoll_server_test.cc
index 7c024f1d562..dbc3292f96d 100644
--- a/chromium/net/third_party/quiche/src/epoll_server/simple_epoll_server_test.cc
+++ b/chromium/net/third_party/quiche/src/epoll_server/simple_epoll_server_test.cc
@@ -164,7 +164,10 @@ class RecordingCB : public EpollCallbackInterface {
if (event->in_events & EPOLLIN) {
const int kLength = 1024;
char buf[kLength];
- read(fd, &buf, kLength);
+ int data_read;
+ do {
+ data_read = read(fd, &buf, kLength);
+ } while (data_read > 0);
}
}
@@ -258,7 +261,7 @@ class EpollFunctionTest : public EpollTest {
int pipe_fds[2];
if (pipe(pipe_fds) < 0) {
- PLOG(FATAL) << "pipe() failed";
+ EPOLL_PLOG(FATAL) << "pipe() failed";
}
fd_ = pipe_fds[0];
fd2_ = pipe_fds[1];
@@ -1004,7 +1007,7 @@ TEST(SimpleEpollServerTest, TestRepeatAlarms) {
alarm.Reset();
// Make sure the alarm is called one final time.
- EXPECT_EQ(1, ep.GetNumPendingAlarmsForTest());
+ EXPECT_EQ(1u, ep.GetNumPendingAlarmsForTest());
ep.set_timeout_in_us(alarm_time * 1000 * 2);
WaitForAlarm(&ep, alarm);
@@ -1481,18 +1484,18 @@ TEST(SimpleEpollServerTest, TestMultipleFDs) {
EXPECT_EQ(2u, records_one->size());
EXPECT_EQ(2u, records_two->size());
- write(pipe_one[1], &data, 1);
+ EXPECT_EQ(1, write(pipe_one[1], &data, 1));
ep.WaitForEventsAndExecuteCallbacks();
EXPECT_EQ(3u, records_one->size());
EXPECT_EQ(2u, records_two->size());
- write(pipe_two[1], &data, 1);
+ EXPECT_EQ(1, write(pipe_two[1], &data, 1));
ep.WaitForEventsAndExecuteCallbacks();
EXPECT_EQ(3u, records_one->size());
EXPECT_EQ(3u, records_two->size());
- write(pipe_one[1], &data, 1);
- write(pipe_two[1], &data, 1);
+ EXPECT_EQ(1, write(pipe_one[1], &data, 1));
+ EXPECT_EQ(1, write(pipe_two[1], &data, 1));
ep.WaitForEventsAndExecuteCallbacks();
EXPECT_EQ(4u, records_one->size());
EXPECT_EQ(4u, records_two->size());
@@ -1724,7 +1727,7 @@ class EpollReader: public EpollCallbackInterface {
void TestPipe(char *test_message, int len) {
int pipe_fds[2];
if (pipe(pipe_fds) < 0) {
- PLOG(FATAL) << "pipe failed()";
+ EPOLL_PLOG(FATAL) << "pipe failed()";
}
int reader_pipe = pipe_fds[0];
int writer_pipe = pipe_fds[1];
@@ -1744,14 +1747,14 @@ void TestPipe(char *test_message, int len) {
}
}
if (len > 0) {
- PLOG(FATAL) << "write() failed";
+ EPOLL_PLOG(FATAL) << "write() failed";
}
close(writer_pipe);
_exit(0);
}
case -1:
- PLOG(FATAL) << "fork() failed";
+ EPOLL_PLOG(FATAL) << "fork() failed";
break;
default: { // Parent will receive message.
close(writer_pipe);
@@ -1925,7 +1928,7 @@ class EdgeTriggerCB : public EpollCallbackInterface {
// Since we can only get on the ready list once, wait till we confirm both
// read and write side continuation state and set the correct event mask
// for the ready list.
- event->out_ready_mask = can_read_ ? EPOLLIN : 0;
+ event->out_ready_mask = can_read_ ? static_cast<int>(EPOLLIN) : 0;
if (can_write_) {
event->out_ready_mask |= EPOLLOUT;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/chlo_extractor.cc b/chromium/net/third_party/quiche/src/quic/core/chlo_extractor.cc
index 4ce5d8caccb..ec3a899b8bd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/chlo_extractor.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/chlo_extractor.cc
@@ -5,8 +5,10 @@
#include "net/third_party/quiche/src/quic/core/chlo_extractor.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
+#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
+#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.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_framer.h"
@@ -35,6 +37,9 @@ class ChloFramerVisitor : public QuicFramerVisitorInterface,
void OnPublicResetPacket(const QuicPublicResetPacket& packet) override {}
void OnVersionNegotiationPacket(
const QuicVersionNegotiationPacket& packet) override {}
+ void OnRetryPacket(QuicConnectionId original_connection_id,
+ QuicConnectionId new_connection_id,
+ QuicStringPiece retry_token) override {}
bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override;
bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
void OnDecryptedPacket(EncryptionLevel level) override {}
@@ -60,8 +65,8 @@ class ChloFramerVisitor : public QuicFramerVisitorInterface,
bool OnPathChallengeFrame(const QuicPathChallengeFrame& frame) override;
bool OnPathResponseFrame(const QuicPathResponseFrame& frame) override;
bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override;
- bool OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) override;
- bool OnStreamIdBlockedFrame(const QuicStreamIdBlockedFrame& frame) override;
+ bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override;
+ bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
bool OnBlockedFrame(const QuicBlockedFrame& frame) override;
bool OnPaddingFrame(const QuicPaddingFrame& frame) override;
@@ -113,6 +118,23 @@ bool ChloFramerVisitor::OnProtocolVersionMismatch(ParsedQuicVersion version,
bool ChloFramerVisitor::OnUnauthenticatedPublicHeader(
const QuicPacketHeader& header) {
connection_id_ = header.destination_connection_id;
+ // QuicFramer creates a NullEncrypter and NullDecrypter at level
+ // ENCRYPTION_INITIAL, which are the correct ones to use with the QUIC Crypto
+ // handshake. When the TLS handshake is used, the IETF-style initial crypters
+ // are used instead, so those need to be created and installed.
+ if (header.version.handshake_protocol == PROTOCOL_TLS1_3) {
+ CrypterPair crypters;
+ CryptoUtils::CreateTlsInitialCrypters(
+ Perspective::IS_SERVER, header.version.transport_version,
+ header.destination_connection_id, &crypters);
+ framer_->SetEncrypter(ENCRYPTION_INITIAL, std::move(crypters.encrypter));
+ if (framer_->version().KnowsWhichDecrypterToUse()) {
+ framer_->InstallDecrypter(ENCRYPTION_INITIAL,
+ std::move(crypters.decrypter));
+ } else {
+ framer_->SetDecrypter(ENCRYPTION_INITIAL, std::move(crypters.decrypter));
+ }
+ }
return true;
}
bool ChloFramerVisitor::OnUnauthenticatedHeader(
@@ -129,8 +151,8 @@ bool ChloFramerVisitor::OnStreamFrame(const QuicStreamFrame& frame) {
return false;
}
QuicStringPiece data(frame.data_buffer, frame.data_length);
- if (frame.stream_id ==
- QuicUtils::GetCryptoStreamId(framer_->transport_version()) &&
+ if (QuicUtils::IsCryptoStreamId(framer_->transport_version(),
+ frame.stream_id) &&
frame.offset == 0 && QuicTextUtils::StartsWith(data, "CHLO")) {
return OnHandshakeData(data);
}
@@ -263,12 +285,12 @@ bool ChloFramerVisitor::IsValidStatelessResetToken(QuicUint128 token) const {
return false;
}
-bool ChloFramerVisitor::OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) {
+bool ChloFramerVisitor::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
return true;
}
-bool ChloFramerVisitor::OnStreamIdBlockedFrame(
- const QuicStreamIdBlockedFrame& frame) {
+bool ChloFramerVisitor::OnStreamsBlockedFrame(
+ const QuicStreamsBlockedFrame& frame) {
return true;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/chlo_extractor_test.cc b/chromium/net/third_party/quiche/src/quic/core/chlo_extractor_test.cc
index cea445dabaa..258e141fe34 100644
--- a/chromium/net/third_party/quiche/src/quic/core/chlo_extractor_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/chlo_extractor_test.cc
@@ -70,6 +70,14 @@ class ChloExtractorTest : public QuicTest {
}
QuicFramer framer(SupportedVersions(header_.version), QuicTime::Zero(),
Perspective::IS_CLIENT, kQuicDefaultConnectionIdLength);
+ if (version.handshake_protocol == PROTOCOL_TLS1_3) {
+ CrypterPair crypters;
+ CryptoUtils::CreateTlsInitialCrypters(Perspective::IS_CLIENT,
+ version.transport_version,
+ TestConnectionId(), &crypters);
+ framer.SetEncrypter(ENCRYPTION_INITIAL, std::move(crypters.encrypter));
+ framer.SetDecrypter(ENCRYPTION_INITIAL, std::move(crypters.decrypter));
+ }
if (!QuicVersionUsesCryptoFrames(version.transport_version) ||
munge_stream_id) {
QuicStreamId stream_id =
@@ -133,11 +141,15 @@ TEST_F(ChloExtractorTest, FindsValidChlo) {
}
TEST_F(ChloExtractorTest, DoesNotFindValidChloOnWrongStream) {
+ ParsedQuicVersion version = AllSupportedVersions()[0];
+ if (QuicVersionUsesCryptoFrames(version.transport_version)) {
+ return;
+ }
CryptoHandshakeMessage client_hello;
client_hello.set_tag(kCHLO);
std::string client_hello_str(client_hello.GetSerialized().AsStringPiece());
- MakePacket(AllSupportedVersions()[0], client_hello_str,
+ MakePacket(version, client_hello_str,
/*munge_offset*/ false, /*munge_stream_id*/ true);
EXPECT_FALSE(ChloExtractor::Extract(*packet_, AllSupportedVersions(), {},
&delegate_,
@@ -157,7 +169,11 @@ TEST_F(ChloExtractorTest, DoesNotFindValidChloOnWrongOffset) {
}
TEST_F(ChloExtractorTest, DoesNotFindInvalidChlo) {
- MakePacket(AllSupportedVersions()[0], "foo", /*munge_offset*/ false,
+ ParsedQuicVersion version = AllSupportedVersions()[0];
+ if (QuicVersionUsesCryptoFrames(version.transport_version)) {
+ return;
+ }
+ MakePacket(version, "foo", /*munge_offset*/ false,
/*munge_stream_id*/ true);
EXPECT_FALSE(ChloExtractor::Extract(*packet_, AllSupportedVersions(), {},
&delegate_,
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 1c0d274fe1d..5844987b3cb 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
@@ -30,7 +30,7 @@ const float kDefaultHighGain = 2.885f;
// The newly derived gain for STARTUP, equal to 4 * ln(2)
const float kDerivedHighGain = 2.773f;
// The newly derived CWND gain for STARTUP, 2.
-const float kDerivedHighCWNDGain = 2.773f;
+const float kDerivedHighCWNDGain = 2.0f;
// The gain used in STARTUP after loss has been detected.
// 1.5 is enough to allow for 25% exogenous loss and still observe a 25% growth
// in measured bandwidth.
@@ -329,11 +329,6 @@ void BbrSender::SetFromConfig(const QuicConfig& config,
QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr_slower_startup3, 3, 4);
enable_ack_aggregation_during_startup_ = true;
}
- if (GetQuicReloadableFlag(quic_bbr_slower_startup3) &&
- config.HasClientRequestedIndependentOption(kBBQ4, perspective)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr_slower_startup3, 4, 4);
- set_drain_gain(kModerateProbeRttMultiplier);
- }
if (GetQuicReloadableFlag(quic_bbr_slower_startup4) &&
config.HasClientRequestedIndependentOption(kBBQ5, perspective)) {
QUIC_RELOADABLE_FLAG_COUNT(quic_bbr_slower_startup4);
@@ -345,13 +340,43 @@ void BbrSender::SetFromConfig(const QuicConfig& config,
}
void BbrSender::AdjustNetworkParameters(QuicBandwidth bandwidth,
- QuicTime::Delta rtt) {
+ QuicTime::Delta rtt,
+ bool allow_cwnd_to_decrease) {
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 (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()));
+ 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) {
+ // Only decrease cwnd if allow_cwnd_to_decrease is true.
+ return;
+ }
+ // Decreases cwnd gain and pacing gain. Please note, if pacing_rate_ has
+ // been calculated, it cannot decrease in STARTUP phase.
+ set_high_gain(kDerivedHighCWNDGain);
+ set_high_cwnd_gain(kDerivedHighCWNDGain);
+ congestion_window_ = new_cwnd;
+ }
}
void BbrSender::OnCongestionEvent(bool /*rtt_updated*/,
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 d01dbfe4dc2..a49a5efd579 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
@@ -108,7 +108,8 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
Perspective perspective) override;
void AdjustNetworkParameters(QuicBandwidth bandwidth,
- QuicTime::Delta rtt) override;
+ QuicTime::Delta rtt,
+ bool allow_cwnd_to_decrease) override;
void SetNumEmulatedConnections(int num_connections) override {}
void SetInitialCongestionWindowInPackets(
QuicPacketCount congestion_window) override;
@@ -164,6 +165,10 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
drain_gain_ = drain_gain;
}
+ // Returns the current estimate of the RTT of the connection. Outside of the
+ // edge cases, this is minimum RTT.
+ QuicTime::Delta GetMinRtt() const;
+
DebugState ExportDebugState() const;
private:
@@ -179,9 +184,6 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
QuicRoundTripCount>
MaxAckHeightFilter;
- // Returns the current estimate of the RTT of the connection. Outside of the
- // edge cases, this is minimum RTT.
- QuicTime::Delta GetMinRtt() const;
// Returns whether the connection has achieved full bandwidth required to exit
// the slow start.
bool IsAtFullBandwidth() const;
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 3d40e0a2217..be4f291406b 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
@@ -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/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#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"
@@ -161,7 +162,7 @@ class BbrSenderTest : public QuicTest {
0.5 * kTestBdp);
bbr_sender_link_ = QuicMakeUnique<simulator::SymmetricLink>(
&bbr_sender_, switch_->port(1), kLocalLinkBandwidth,
- kTestPropagationDelay);
+ kLocalPropagationDelay);
receiver_link_ = QuicMakeUnique<simulator::SymmetricLink>(
&receiver_, switch_->port(2), kTestLinkBandwidth,
kTestPropagationDelay);
@@ -217,8 +218,8 @@ class BbrSenderTest : public QuicTest {
ASSERT_FALSE(sender_->ExportDebugState().is_at_full_bandwidth);
DoSimpleTransfer(1024 * 1024, QuicTime::Delta::FromSeconds(15));
EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
- ExpectApproxEq(kTestLinkBandwidth,
- sender_->ExportDebugState().max_bandwidth, 0.02f);
+ EXPECT_APPROX_EQ(kTestLinkBandwidth,
+ sender_->ExportDebugState().max_bandwidth, 0.02f);
}
// Send |bytes|-sized bursts of data |number_of_bursts| times, waiting for
@@ -276,8 +277,8 @@ TEST_F(BbrSenderTest, SimpleTransfer) {
// Verify that pacing rate is based on the initial RTT.
QuicBandwidth expected_pacing_rate = QuicBandwidth::FromBytesAndTimeDelta(
2.885 * kDefaultWindowTCP, rtt_stats_->initial_rtt());
- ExpectApproxEq(expected_pacing_rate.ToBitsPerSecond(),
- sender_->PacingRate(0).ToBitsPerSecond(), 0.01f);
+ EXPECT_APPROX_EQ(expected_pacing_rate.ToBitsPerSecond(),
+ sender_->PacingRate(0).ToBitsPerSecond(), 0.01f);
ASSERT_GE(kTestBdp, kDefaultWindowTCP + kDefaultTCPMSS);
@@ -288,7 +289,7 @@ TEST_F(BbrSenderTest, SimpleTransfer) {
// The margin here is quite high, since there exists a possibility that the
// connection just exited high gain cycle.
- ExpectApproxEq(kTestRtt, rtt_stats_->smoothed_rtt(), 0.2f);
+ EXPECT_APPROX_EQ(kTestRtt, rtt_stats_->smoothed_rtt(), 0.2f);
}
// Test a simple transfer in a situation when the buffer is less than BDP.
@@ -297,10 +298,14 @@ TEST_F(BbrSenderTest, SimpleTransferSmallBuffer) {
DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(30));
EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
- ExpectApproxEq(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth,
- 0.01f);
+ EXPECT_APPROX_EQ(kTestLinkBandwidth,
+ sender_->ExportDebugState().max_bandwidth, 0.01f);
EXPECT_GE(bbr_sender_.connection()->GetStats().packets_lost, 0u);
EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
+
+ // The margin here is quite high, since there exists a possibility that the
+ // connection just exited high gain cycle.
+ EXPECT_APPROX_EQ(kTestRtt, sender_->GetMinRtt(), 0.2f);
}
TEST_F(BbrSenderTest, SimpleTransferEarlyPacketLoss) {
@@ -363,7 +368,7 @@ TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes) {
// The margin here is high, because the aggregation greatly increases
// smoothed rtt.
EXPECT_GE(kTestRtt * 4, rtt_stats_->smoothed_rtt());
- ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.2f);
+ EXPECT_APPROX_EQ(kTestRtt, rtt_stats_->min_rtt(), 0.2f);
}
// Test a simple long data transfer with 2 rtts of aggregation.
@@ -398,7 +403,7 @@ TEST_F(BbrSenderTest, SimpleTransferAckDecimation) {
// The margin here is high, because the aggregation greatly increases
// smoothed rtt.
EXPECT_GE(kTestRtt * 2, rtt_stats_->smoothed_rtt());
- ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.1f);
+ EXPECT_APPROX_EQ(kTestRtt, rtt_stats_->min_rtt(), 0.1f);
}
// Test a simple long data transfer with 2 rtts of aggregation.
@@ -425,7 +430,7 @@ TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes20RTTWindow) {
// The margin here is high, because the aggregation greatly increases
// smoothed rtt.
EXPECT_GE(kTestRtt * 4, rtt_stats_->smoothed_rtt());
- ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.12f);
+ EXPECT_APPROX_EQ(kTestRtt, rtt_stats_->min_rtt(), 0.12f);
}
// Test a simple long data transfer with 2 rtts of aggregation.
@@ -452,7 +457,7 @@ TEST_F(BbrSenderTest, SimpleTransfer2RTTAggregationBytes40RTTWindow) {
// The margin here is high, because the aggregation greatly increases
// smoothed rtt.
EXPECT_GE(kTestRtt * 4, rtt_stats_->smoothed_rtt());
- ExpectApproxEq(kTestRtt, rtt_stats_->min_rtt(), 0.12f);
+ EXPECT_APPROX_EQ(kTestRtt, rtt_stats_->min_rtt(), 0.12f);
}
// Test the number of losses incurred by the startup phase in a situation when
@@ -467,15 +472,23 @@ TEST_F(BbrSenderTest, PacketLossOnSmallBufferStartup) {
EXPECT_LE(loss_rate, 0.31);
}
+// Test the number of losses incurred by the startup phase in a situation when
+// the buffer is less than BDP, with a STARTUP CWND gain of 2.
+TEST_F(BbrSenderTest, PacketLossOnSmallBufferStartupDerivedCWNDGain) {
+ SetQuicReloadableFlag(quic_bbr_slower_startup3, true);
+ CreateSmallBufferSetup();
+
+ SetConnectionOption(kBBQ2);
+ DriveOutOfStartup();
+ float loss_rate =
+ static_cast<float>(bbr_sender_.connection()->GetStats().packets_lost) /
+ bbr_sender_.connection()->GetStats().packets_sent;
+ EXPECT_LE(loss_rate, 0.1);
+}
+
// Ensures the code transitions loss recovery states correctly (NOT_IN_RECOVERY
// -> CONSERVATION -> GROWTH -> NOT_IN_RECOVERY).
TEST_F(BbrSenderTest, RecoveryStates) {
- // Set seed to the position where the gain cycling causes the sender go
- // into conservation upon entering PROBE_BW.
- //
- // TODO(vasilvv): there should be a better way to test this.
- random_.set_seed(UINT64_C(14719894707049085006));
-
const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(10);
bool simulator_result;
CreateSmallBufferSetup();
@@ -509,7 +522,6 @@ TEST_F(BbrSenderTest, RecoveryStates) {
},
timeout);
- ASSERT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
ASSERT_EQ(BbrSender::NOT_IN_RECOVERY,
sender_->ExportDebugState().recovery_state);
ASSERT_TRUE(simulator_result);
@@ -525,8 +537,8 @@ TEST_F(BbrSenderTest, ApplicationLimitedBursts) {
SendBursts(20, 512, QuicTime::Delta::FromSeconds(3));
EXPECT_TRUE(sender_->ExportDebugState().last_sample_is_app_limited);
- ExpectApproxEq(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth,
- 0.01f);
+ EXPECT_APPROX_EQ(kTestLinkBandwidth,
+ sender_->ExportDebugState().max_bandwidth, 0.01f);
}
// Verify the behavior of the algorithm in the case when the connection sends
@@ -538,8 +550,8 @@ TEST_F(BbrSenderTest, ApplicationLimitedBurstsWithoutPrior) {
EXPECT_TRUE(sender_->ExportDebugState().last_sample_is_app_limited);
DriveOutOfStartup();
- ExpectApproxEq(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth,
- 0.01f);
+ EXPECT_APPROX_EQ(kTestLinkBandwidth,
+ sender_->ExportDebugState().max_bandwidth, 0.01f);
EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
}
@@ -566,8 +578,8 @@ TEST_F(BbrSenderTest, Drain) {
timeout);
ASSERT_TRUE(simulator_result);
ASSERT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
- ExpectApproxEq(sender_->BandwidthEstimate() * (1 / 2.885f),
- sender_->PacingRate(0), 0.01f);
+ EXPECT_APPROX_EQ(sender_->BandwidthEstimate() * (1 / 2.885f),
+ sender_->PacingRate(0), 0.01f);
// BBR uses CWND gain of 2.88 during STARTUP, hence it will fill the buffer
// with approximately 1.88 BDPs. Here, we use 1.5 to give some margin for
// error.
@@ -576,7 +588,7 @@ TEST_F(BbrSenderTest, Drain) {
// Observe increased RTT due to bufferbloat.
const QuicTime::Delta queueing_delay =
kTestLinkBandwidth.TransferTime(queue->bytes_queued());
- ExpectApproxEq(kTestRtt + queueing_delay, rtt_stats_->latest_rtt(), 0.1f);
+ EXPECT_APPROX_EQ(kTestRtt + queueing_delay, rtt_stats_->latest_rtt(), 0.1f);
// Transition to the drain phase and verify that it makes the queue
// have at most a BDP worth of packets.
@@ -602,18 +614,17 @@ TEST_F(BbrSenderTest, Drain) {
ASSERT_TRUE(simulator_result);
// Observe the bufferbloat go away.
- ExpectApproxEq(kTestRtt, rtt_stats_->smoothed_rtt(), 0.1f);
+ EXPECT_APPROX_EQ(kTestRtt, rtt_stats_->smoothed_rtt(), 0.1f);
}
+// TODO(wub): Re-enable this test once default drain_gain changed to 0.75.
// Verify that the DRAIN phase works correctly.
-TEST_F(BbrSenderTest, ShallowDrain) {
+TEST_F(BbrSenderTest, DISABLED_ShallowDrain) {
SetQuicReloadableFlag(quic_bbr_slower_startup3, true);
// Disable Ack Decimation on the receiver, because it can increase srtt.
QuicConnectionPeer::SetAckMode(receiver_.connection(), AckMode::TCP_ACKING);
CreateDefaultSetup();
- // BBQ4 increases the pacing gain in DRAIN to 0.75
- SetConnectionOption(kBBQ4);
const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(10);
// Get the queue at the bottleneck, which is the outgoing queue at the port to
// which the receiver is connected.
@@ -641,7 +652,7 @@ TEST_F(BbrSenderTest, ShallowDrain) {
// Observe increased RTT due to bufferbloat.
const QuicTime::Delta queueing_delay =
kTestLinkBandwidth.TransferTime(queue->bytes_queued());
- ExpectApproxEq(kTestRtt + queueing_delay, rtt_stats_->latest_rtt(), 0.1f);
+ EXPECT_APPROX_EQ(kTestRtt + queueing_delay, rtt_stats_->latest_rtt(), 0.1f);
// Transition to the drain phase and verify that it makes the queue
// have at most a BDP worth of packets.
@@ -667,7 +678,7 @@ TEST_F(BbrSenderTest, ShallowDrain) {
ASSERT_TRUE(simulator_result);
// Observe the bufferbloat go away.
- ExpectApproxEq(kTestRtt, rtt_stats_->smoothed_rtt(), 0.1f);
+ EXPECT_APPROX_EQ(kTestRtt, rtt_stats_->smoothed_rtt(), 0.1f);
}
// Verify that the connection enters and exits PROBE_RTT correctly.
@@ -834,8 +845,8 @@ TEST_F(BbrSenderTest, InFlightAwareGainCycling) {
SendBursts(5, target_bandwidth * burst_interval, burst_interval);
EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
EXPECT_EQ(0, sender_->ExportDebugState().gain_cycle_index);
- ExpectApproxEq(kTestLinkBandwidth,
- sender_->ExportDebugState().max_bandwidth, 0.01f);
+ EXPECT_APPROX_EQ(kTestLinkBandwidth,
+ sender_->ExportDebugState().max_bandwidth, 0.01f);
}
// Now that in-flight is almost zero and the pacing gain is still above 1,
@@ -1170,8 +1181,8 @@ TEST_F(BbrSenderTest, DerivedPacingGainStartup) {
// Verify that pacing rate is based on the initial RTT.
QuicBandwidth expected_pacing_rate = QuicBandwidth::FromBytesAndTimeDelta(
2.773 * kDefaultWindowTCP, rtt_stats_->initial_rtt());
- ExpectApproxEq(expected_pacing_rate.ToBitsPerSecond(),
- sender_->PacingRate(0).ToBitsPerSecond(), 0.01f);
+ EXPECT_APPROX_EQ(expected_pacing_rate.ToBitsPerSecond(),
+ sender_->PacingRate(0).ToBitsPerSecond(), 0.01f);
// Run until the full bandwidth is reached and check how many rounds it was.
bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
@@ -1181,15 +1192,15 @@ TEST_F(BbrSenderTest, DerivedPacingGainStartup) {
ASSERT_TRUE(simulator_result);
EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
EXPECT_EQ(3u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
- ExpectApproxEq(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth,
- 0.01f);
+ EXPECT_APPROX_EQ(kTestLinkBandwidth,
+ sender_->ExportDebugState().max_bandwidth, 0.01f);
EXPECT_EQ(0u, bbr_sender_.connection()->GetStats().packets_lost);
EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
}
TEST_F(BbrSenderTest, DerivedCWNDGainStartup) {
SetQuicReloadableFlag(quic_bbr_slower_startup3, true);
- CreateDefaultSetup();
+ CreateSmallBufferSetup();
SetConnectionOption(kBBQ2);
EXPECT_EQ(3u, sender_->num_startup_rtts());
@@ -1198,8 +1209,8 @@ TEST_F(BbrSenderTest, DerivedCWNDGainStartup) {
// Verify that pacing rate is based on the initial RTT.
QuicBandwidth expected_pacing_rate = QuicBandwidth::FromBytesAndTimeDelta(
2.885 * kDefaultWindowTCP, rtt_stats_->initial_rtt());
- ExpectApproxEq(expected_pacing_rate.ToBitsPerSecond(),
- sender_->PacingRate(0).ToBitsPerSecond(), 0.01f);
+ EXPECT_APPROX_EQ(expected_pacing_rate.ToBitsPerSecond(),
+ sender_->PacingRate(0).ToBitsPerSecond(), 0.01f);
// Run until the full bandwidth is reached and check how many rounds it was.
bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
@@ -1209,9 +1220,12 @@ TEST_F(BbrSenderTest, DerivedCWNDGainStartup) {
ASSERT_TRUE(simulator_result);
EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
EXPECT_EQ(3u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
- ExpectApproxEq(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth,
- 0.01f);
- EXPECT_EQ(0u, bbr_sender_.connection()->GetStats().packets_lost);
+ EXPECT_APPROX_EQ(kTestLinkBandwidth,
+ sender_->ExportDebugState().max_bandwidth, 0.01f);
+ float loss_rate =
+ static_cast<float>(bbr_sender_.connection()->GetStats().packets_lost) /
+ bbr_sender_.connection()->GetStats().packets_sent;
+ EXPECT_LT(loss_rate, 0.15f);
EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
// Expect an SRTT less than 2.7 * Min RTT on exit from STARTUP.
EXPECT_GT(kTestRtt * 2.7, rtt_stats_->smoothed_rtt());
@@ -1231,8 +1245,8 @@ TEST_F(BbrSenderTest, AckAggregationInStartup) {
// Verify that pacing rate is based on the initial RTT.
QuicBandwidth expected_pacing_rate = QuicBandwidth::FromBytesAndTimeDelta(
2.885 * kDefaultWindowTCP, rtt_stats_->initial_rtt());
- ExpectApproxEq(expected_pacing_rate.ToBitsPerSecond(),
- sender_->PacingRate(0).ToBitsPerSecond(), 0.01f);
+ EXPECT_APPROX_EQ(expected_pacing_rate.ToBitsPerSecond(),
+ sender_->PacingRate(0).ToBitsPerSecond(), 0.01f);
// Run until the full bandwidth is reached and check how many rounds it was.
bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
@@ -1242,8 +1256,8 @@ TEST_F(BbrSenderTest, AckAggregationInStartup) {
ASSERT_TRUE(simulator_result);
EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
EXPECT_EQ(3u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
- ExpectApproxEq(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth,
- 0.01f);
+ EXPECT_APPROX_EQ(kTestLinkBandwidth,
+ sender_->ExportDebugState().max_bandwidth, 0.01f);
EXPECT_EQ(0u, bbr_sender_.connection()->GetStats().packets_lost);
EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
}
@@ -1278,10 +1292,10 @@ TEST_F(BbrSenderTest, ResumeConnectionState) {
CreateDefaultSetup();
bbr_sender_.connection()->AdjustNetworkParameters(kTestLinkBandwidth,
- kTestRtt);
+ kTestRtt, false);
EXPECT_EQ(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth);
EXPECT_EQ(kTestLinkBandwidth, sender_->BandwidthEstimate());
- ExpectApproxEq(kTestRtt, sender_->ExportDebugState().min_rtt, 0.01f);
+ EXPECT_APPROX_EQ(kTestRtt, sender_->ExportDebugState().min_rtt, 0.01f);
DriveOutOfStartup();
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.cc
index 45e8bae6fdc..0968935492d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.cc
@@ -99,6 +99,7 @@ void PacingSender::OnPacketSent(
if (GetQuicReloadableFlag(quic_no_lumpy_pacing_at_low_bw) &&
sender_->BandwidthEstimate() <
QuicBandwidth::FromKBitsPerSecond(1200)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_no_lumpy_pacing_at_low_bw);
// Below 1.2Mbps, send 1 packet at once, because one full-sized packet
// is about 10ms of queueing.
lumpy_tokens_ = 1u;
@@ -121,6 +122,13 @@ void PacingSender::OnApplicationLimited() {
pacing_limited_ = false;
}
+void PacingSender::SetBurstTokens(uint32_t burst_tokens) {
+ initial_burst_size_ = burst_tokens;
+ burst_tokens_ = std::min(
+ initial_burst_size_,
+ static_cast<uint32_t>(sender_->GetCongestionWindow() / kDefaultTCPMSS));
+}
+
QuicTime::Delta PacingSender::TimeUntilSend(
QuicTime now,
QuicByteCount bytes_in_flight) const {
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.h
index 8420c7f1650..781a9211951 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.h
@@ -66,6 +66,9 @@ class QUIC_EXPORT_PRIVATE PacingSender {
// making up for lost time.
void OnApplicationLimited();
+ // Set burst_tokens_ and initial_burst_size_.
+ void SetBurstTokens(uint32_t burst_tokens);
+
QuicTime::Delta TimeUntilSend(QuicTime now,
QuicByteCount bytes_in_flight) const;
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender_test.cc
index ea9debf302d..4e4c401229d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender_test.cc
@@ -388,8 +388,8 @@ TEST_F(PacingSenderTest, CwndLimited) {
TEST_F(PacingSenderTest, LumpyPacingWithInitialBurstToken) {
// Set lumpy size to be 3, and cwnd faction to 0.5
- SetQuicFlag(&FLAGS_quic_lumpy_pacing_size, 3);
- SetQuicFlag(&FLAGS_quic_lumpy_pacing_cwnd_fraction, 0.5f);
+ SetQuicFlag(FLAGS_quic_lumpy_pacing_size, 3);
+ SetQuicFlag(FLAGS_quic_lumpy_pacing_cwnd_fraction, 0.5f);
// Configure pacing rate of 1 packet per 1 ms.
InitPacingRate(
10, QuicBandwidth::FromBytesAndTimeDelta(
@@ -442,8 +442,8 @@ TEST_F(PacingSenderTest, LumpyPacingWithInitialBurstToken) {
TEST_F(PacingSenderTest, NoLumpyPacingForLowBandwidthFlows) {
// Set lumpy size to be 3, and cwnd faction to 0.5
- SetQuicFlag(&FLAGS_quic_lumpy_pacing_size, 3);
- SetQuicFlag(&FLAGS_quic_lumpy_pacing_cwnd_fraction, 0.5f);
+ SetQuicFlag(FLAGS_quic_lumpy_pacing_size, 3);
+ SetQuicFlag(FLAGS_quic_lumpy_pacing_cwnd_fraction, 0.5f);
SetQuicReloadableFlag(quic_no_lumpy_pacing_at_low_bw, true);
// Configure pacing rate of 1 packet per 100 ms.
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 620b23f879d..9db67b5abd1 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
@@ -120,7 +120,8 @@ class QUIC_EXPORT_PRIVATE SendAlgorithmInterface {
// measurement or prediction. Either |bandwidth| or |rtt| may be zero if no
// sample is available.
virtual void AdjustNetworkParameters(QuicBandwidth bandwidth,
- QuicTime::Delta rtt) = 0;
+ QuicTime::Delta rtt,
+ bool allow_cwnd_to_decrease) = 0;
// Retrieves debugging information about the current state of the
// send algorithm.
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 fde8d750101..7cbf332ffcd 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,8 +105,10 @@ void TcpCubicSenderBytes::SetFromConfig(const QuicConfig& config,
}
}
-void TcpCubicSenderBytes::AdjustNetworkParameters(QuicBandwidth bandwidth,
- QuicTime::Delta rtt) {
+void TcpCubicSenderBytes::AdjustNetworkParameters(
+ QuicBandwidth bandwidth,
+ QuicTime::Delta rtt,
+ bool /*allow_cwnd_to_decrease*/) {
if (bandwidth.IsZero() || rtt.IsZero()) {
return;
}
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 a437426ae5e..dd8be128be3 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
@@ -47,7 +47,8 @@ class QUIC_EXPORT_PRIVATE TcpCubicSenderBytes : public SendAlgorithmInterface {
void SetFromConfig(const QuicConfig& config,
Perspective perspective) override;
void AdjustNetworkParameters(QuicBandwidth bandwidth,
- QuicTime::Delta rtt) override;
+ QuicTime::Delta rtt,
+ bool allow_cwnd_to_decrease) override;
void SetNumEmulatedConnections(int num_connections) override;
void SetInitialCongestionWindowInPackets(
QuicPacketCount congestion_window) override;
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
index 5eb6226b33e..32451a51020 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,11 +677,11 @@ TEST_F(TcpCubicSenderBytesTest, BandwidthResumption) {
const QuicBandwidth kBandwidthEstimate =
QuicBandwidth::FromBytesPerSecond(kNumberOfPackets * kDefaultTCPMSS);
const QuicTime::Delta kRttEstimate = QuicTime::Delta::FromSeconds(1);
- sender_->AdjustNetworkParameters(kBandwidthEstimate, kRttEstimate);
+ sender_->AdjustNetworkParameters(kBandwidthEstimate, kRttEstimate, false);
EXPECT_EQ(kNumberOfPackets * kDefaultTCPMSS, sender_->GetCongestionWindow());
// Resume with an illegal value of 0 and verify the server ignores it.
- sender_->AdjustNetworkParameters(QuicBandwidth::Zero(), kRttEstimate);
+ sender_->AdjustNetworkParameters(QuicBandwidth::Zero(), kRttEstimate, false);
EXPECT_EQ(kNumberOfPackets * kDefaultTCPMSS, sender_->GetCongestionWindow());
// Resumed CWND is limited to be in a sensible range.
@@ -689,7 +689,7 @@ TEST_F(TcpCubicSenderBytesTest, BandwidthResumption) {
QuicBandwidth::FromBytesPerSecond((kMaxCongestionWindowPackets + 1) *
kDefaultTCPMSS);
sender_->AdjustNetworkParameters(kUnreasonableBandwidth,
- QuicTime::Delta::FromSeconds(1));
+ QuicTime::Delta::FromSeconds(1), false);
EXPECT_EQ(kMaxCongestionWindowPackets * kDefaultTCPMSS,
sender_->GetCongestionWindow());
}
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 33b93930db2..1fe346534e3 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
@@ -31,12 +31,17 @@ class UberLossAlgorithmTest : public QuicTest {
void SendPacket(uint64_t packet_number, EncryptionLevel encryption_level) {
QuicStreamFrame frame;
- frame.stream_id =
- encryption_level == ENCRYPTION_INITIAL
- ? QuicUtils::GetCryptoStreamId(
- CurrentSupportedVersions()[0].transport_version)
- : QuicUtils::GetHeadersStreamId(
- CurrentSupportedVersions()[0].transport_version);
+ QuicTransportVersion version =
+ CurrentSupportedVersions()[0].transport_version;
+ frame.stream_id = QuicUtils::GetHeadersStreamId(version);
+ if (encryption_level == ENCRYPTION_INITIAL) {
+ if (QuicVersionUsesCryptoFrames(version)) {
+ frame.stream_id = QuicUtils::GetFirstBidirectionalStreamId(
+ version, Perspective::IS_CLIENT);
+ } else {
+ frame.stream_id = QuicUtils::GetCryptoStreamId(version);
+ }
+ }
SerializedPacket packet(QuicPacketNumber(packet_number),
PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
false, false);
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/windowed_filter_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/windowed_filter_test.cc
index d9f3655d203..30387e062db 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/windowed_filter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/windowed_filter_test.cc
@@ -32,11 +32,11 @@ class WindowedFilterTest : public QuicTest {
QuicTime::Delta rtt_sample = QuicTime::Delta::FromMilliseconds(10);
for (int i = 0; i < 5; ++i) {
windowed_min_rtt_.Update(rtt_sample, now);
- VLOG(1) << "i: " << i << " sample: " << rtt_sample.ToMilliseconds()
- << " mins: "
- << " " << windowed_min_rtt_.GetBest().ToMilliseconds() << " "
- << windowed_min_rtt_.GetSecondBest().ToMilliseconds() << " "
- << windowed_min_rtt_.GetThirdBest().ToMilliseconds();
+ QUIC_VLOG(1) << "i: " << i << " sample: " << rtt_sample.ToMilliseconds()
+ << " mins: "
+ << " " << windowed_min_rtt_.GetBest().ToMilliseconds() << " "
+ << windowed_min_rtt_.GetSecondBest().ToMilliseconds() << " "
+ << windowed_min_rtt_.GetThirdBest().ToMilliseconds();
now = now + QuicTime::Delta::FromMilliseconds(25);
rtt_sample = rtt_sample + QuicTime::Delta::FromMilliseconds(10);
}
@@ -57,11 +57,11 @@ class WindowedFilterTest : public QuicTest {
QuicBandwidth bw_sample = QuicBandwidth::FromBitsPerSecond(1000);
for (int i = 0; i < 5; ++i) {
windowed_max_bw_.Update(bw_sample, now);
- VLOG(1) << "i: " << i << " sample: " << bw_sample.ToBitsPerSecond()
- << " maxs: "
- << " " << windowed_max_bw_.GetBest().ToBitsPerSecond() << " "
- << windowed_max_bw_.GetSecondBest().ToBitsPerSecond() << " "
- << windowed_max_bw_.GetThirdBest().ToBitsPerSecond();
+ QUIC_VLOG(1) << "i: " << i << " sample: " << bw_sample.ToBitsPerSecond()
+ << " maxs: "
+ << " " << windowed_max_bw_.GetBest().ToBitsPerSecond() << " "
+ << windowed_max_bw_.GetSecondBest().ToBitsPerSecond() << " "
+ << windowed_max_bw_.GetThirdBest().ToBitsPerSecond();
now = now + QuicTime::Delta::FromMilliseconds(25);
bw_sample = bw_sample - QuicBandwidth::FromBitsPerSecond(100);
}
@@ -120,11 +120,11 @@ TEST_F(WindowedFilterTest, MonotonicallyIncreasingMin) {
now = now + QuicTime::Delta::FromMilliseconds(25);
rtt_sample = rtt_sample + QuicTime::Delta::FromMilliseconds(10);
windowed_min_rtt_.Update(rtt_sample, now);
- VLOG(1) << "i: " << i << " sample: " << rtt_sample.ToMilliseconds()
- << " mins: "
- << " " << windowed_min_rtt_.GetBest().ToMilliseconds() << " "
- << windowed_min_rtt_.GetSecondBest().ToMilliseconds() << " "
- << windowed_min_rtt_.GetThirdBest().ToMilliseconds();
+ QUIC_VLOG(1) << "i: " << i << " sample: " << rtt_sample.ToMilliseconds()
+ << " mins: "
+ << " " << windowed_min_rtt_.GetBest().ToMilliseconds() << " "
+ << windowed_min_rtt_.GetSecondBest().ToMilliseconds() << " "
+ << windowed_min_rtt_.GetThirdBest().ToMilliseconds();
if (i < 3) {
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10),
windowed_min_rtt_.GetBest());
@@ -150,11 +150,11 @@ TEST_F(WindowedFilterTest, MonotonicallyDecreasingMax) {
now = now + QuicTime::Delta::FromMilliseconds(25);
bw_sample = bw_sample - QuicBandwidth::FromBitsPerSecond(100);
windowed_max_bw_.Update(bw_sample, now);
- VLOG(1) << "i: " << i << " sample: " << bw_sample.ToBitsPerSecond()
- << " maxs: "
- << " " << windowed_max_bw_.GetBest().ToBitsPerSecond() << " "
- << windowed_max_bw_.GetSecondBest().ToBitsPerSecond() << " "
- << windowed_max_bw_.GetThirdBest().ToBitsPerSecond();
+ QUIC_VLOG(1) << "i: " << i << " sample: " << bw_sample.ToBitsPerSecond()
+ << " maxs: "
+ << " " << windowed_max_bw_.GetBest().ToBitsPerSecond() << " "
+ << windowed_max_bw_.GetSecondBest().ToBitsPerSecond() << " "
+ << windowed_max_bw_.GetThirdBest().ToBitsPerSecond();
if (i < 3) {
EXPECT_EQ(QuicBandwidth::FromBitsPerSecond(1000),
windowed_max_bw_.GetBest());
@@ -371,8 +371,8 @@ TEST_F(WindowedFilterTest, ExpireCounterBasedMax) {
EXPECT_EQ(kBest, max_filter.GetBest());
UpdateWithIrrelevantSamples(&max_filter, 20, 3);
EXPECT_EQ(kBest, max_filter.GetBest());
- VLOG(0) << max_filter.GetSecondBest();
- VLOG(0) << max_filter.GetThirdBest();
+ QUIC_VLOG(0) << max_filter.GetSecondBest();
+ QUIC_VLOG(0) << max_filter.GetThirdBest();
// Insert 20000 at t = 4. 50000 at t = 1 expires, so 40000 becomes the new
// maximum.
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.cc
index 49fc71d4602..cdb21b85a43 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/aes_base_encrypter.cc
@@ -11,7 +11,7 @@ namespace quic {
bool AesBaseEncrypter::SetHeaderProtectionKey(QuicStringPiece key) {
if (key.size() != GetKeySize()) {
- QUIC_BUG << "Invalid key size for header protection";
+ QUIC_BUG << "Invalid key size for header protection: " << key.size();
return false;
}
if (AES_set_encrypt_key(reinterpret_cast<const uint8_t*>(key.data()),
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id.h b/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id.h
index 309aaf207d8..8719394ce47 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id.h
@@ -14,54 +14,6 @@
namespace quic {
-// ChannelIDKey is an interface that supports signing with and serializing a
-// ChannelID key.
-class QUIC_EXPORT_PRIVATE ChannelIDKey {
- public:
- virtual ~ChannelIDKey() {}
-
- // Sign signs |signed_data| using the ChannelID private key and puts the
- // signature into |out_signature|. It returns true on success.
- virtual bool Sign(QuicStringPiece signed_data,
- std::string* out_signature) const = 0;
-
- // SerializeKey returns the serialized ChannelID public key.
- virtual std::string SerializeKey() const = 0;
-};
-
-// ChannelIDSourceCallback provides a generic mechanism for a ChannelIDSource
-// to call back after an asynchronous GetChannelIDKey operation.
-class ChannelIDSourceCallback {
- public:
- virtual ~ChannelIDSourceCallback() {}
-
- // Run is called on the original thread to mark the completion of an
- // asynchonous GetChannelIDKey operation. If |*channel_id_key| is not nullptr
- // then the channel ID lookup is successful. |Run| may take ownership of
- // |*channel_id_key| by calling |release| on it.
- virtual void Run(std::unique_ptr<ChannelIDKey>* channel_id_key) = 0;
-};
-
-// ChannelIDSource is an abstract interface by which a QUIC client can obtain
-// a ChannelIDKey for a given hostname.
-class QUIC_EXPORT_PRIVATE ChannelIDSource {
- public:
- virtual ~ChannelIDSource() {}
-
- // GetChannelIDKey looks up the ChannelIDKey for |hostname|. On success it
- // returns QUIC_SUCCESS and stores the ChannelIDKey in |*channel_id_key|,
- // which the caller takes ownership of. On failure, it returns QUIC_FAILURE.
- //
- // This function may also return QUIC_PENDING, in which case the
- // ChannelIDSource will call back, on the original thread, via |callback|
- // when complete. In this case, the ChannelIDSource will take ownership of
- // |callback|.
- virtual QuicAsyncStatus GetChannelIDKey(
- const std::string& hostname,
- std::unique_ptr<ChannelIDKey>* channel_id_key,
- ChannelIDSourceCallback* callback) = 0;
-};
-
// ChannelIDVerifier verifies ChannelID signatures.
class QUIC_EXPORT_PRIVATE ChannelIDVerifier {
public:
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id_test.cc
index 99a84dd5909..d3673826d27 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/channel_id_test.cc
@@ -282,40 +282,5 @@ TEST_F(ChannelIDTest, VerifyKnownAnswerTest) {
}
}
-TEST_F(ChannelIDTest, SignAndVerify) {
- std::unique_ptr<ChannelIDSource> source(
- crypto_test_utils::ChannelIDSourceForTesting());
-
- const std::string signed_data = "signed data";
- const std::string hostname = "foo.example.com";
- std::unique_ptr<ChannelIDKey> channel_id_key;
- QuicAsyncStatus status =
- source->GetChannelIDKey(hostname, &channel_id_key, nullptr);
- ASSERT_EQ(QUIC_SUCCESS, status);
-
- std::string signature;
- ASSERT_TRUE(channel_id_key->Sign(signed_data, &signature));
-
- std::string key = channel_id_key->SerializeKey();
- EXPECT_TRUE(ChannelIDVerifier::Verify(key, signed_data, signature));
-
- EXPECT_FALSE(ChannelIDVerifier::Verify("a" + key, signed_data, signature));
- EXPECT_FALSE(ChannelIDVerifier::Verify(key, "a" + signed_data, signature));
-
- std::unique_ptr<char[]> bad_key(new char[key.size()]);
- memcpy(bad_key.get(), key.data(), key.size());
- bad_key[1] ^= 0x80;
- EXPECT_FALSE(ChannelIDVerifier::Verify(std::string(bad_key.get(), key.size()),
- signed_data, signature));
-
- std::unique_ptr<char[]> bad_signature(new char[signature.size()]);
- memcpy(bad_signature.get(), signature.data(), signature.size());
- bad_signature[1] ^= 0x80;
- EXPECT_FALSE(ChannelIDVerifier::Verify(
- key, signed_data, std::string(bad_signature.get(), signature.size())));
-
- EXPECT_FALSE(ChannelIDVerifier::Verify(key, "wrong signed data", signature));
-}
-
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.h b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.h
index f20f0407bd9..5dcc81a87fe 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_framer.h
@@ -14,7 +14,6 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_message_parser.h"
-#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
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 1bbed745bd0..457d0fb054e 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
@@ -274,7 +274,8 @@ std::string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
case kCFCW:
case kSFCW:
case kIRTT:
- case kMIDS:
+ case kMIUS:
+ case kMIBS:
case kSCLS:
case kTCID:
// uint32_t value
@@ -285,16 +286,6 @@ std::string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
done = true;
}
break;
- case kRCID:
- // uint64_t value
- if (it->second.size() == 8) {
- uint64_t value;
- memcpy(&value, it->second.data(), sizeof(value));
- value = QuicEndian::NetToHost64(value);
- ret += QuicTextUtils::Uint64ToString(value);
- done = true;
- }
- break;
case kTBKP:
case kKEXS:
case kAEAD:
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 fc5298036a9..f595581601f 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
@@ -93,37 +93,11 @@ TEST(CryptoHandshakeMessageTest, DebugStringWithTagVector) {
EXPECT_EQ(str, message5.DebugString());
}
-TEST(CryptoHandshakeMessageTest, ServerDesignatedConnectionId) {
- const char* str = "SREJ<\n RCID: 18364758544493064720\n>";
-
- CryptoHandshakeMessage message;
- message.set_tag(kSREJ);
- message.SetValue(kRCID,
- QuicEndian::NetToHost64(UINT64_C(18364758544493064720)));
- EXPECT_EQ(str, message.DebugString());
-
- // Test copy
- CryptoHandshakeMessage message2(message);
- EXPECT_EQ(str, message2.DebugString());
-
- // Test move
- CryptoHandshakeMessage message3(std::move(message));
- EXPECT_EQ(str, message3.DebugString());
-
- // Test assign
- CryptoHandshakeMessage message4 = message3;
- EXPECT_EQ(str, message4.DebugString());
-
- // Test move-assign
- CryptoHandshakeMessage message5 = std::move(message3);
- EXPECT_EQ(str, message5.DebugString());
-}
-
TEST(CryptoHandshakeMessageTest, HasStringPiece) {
CryptoHandshakeMessage message;
- EXPECT_FALSE(message.HasStringPiece(kRCID));
- message.SetStringPiece(kRCID, "foo");
- EXPECT_TRUE(message.HasStringPiece(kRCID));
+ EXPECT_FALSE(message.HasStringPiece(kALPN));
+ message.SetStringPiece(kALPN, "foo");
+ EXPECT_TRUE(message.HasStringPiece(kALPN));
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_printer_bin.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_message_printer_bin.cc
index c680290bcb4..ecbcab82e53 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
@@ -10,7 +10,6 @@
#include <iostream>
#include <string>
-#include "base/init_google.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
@@ -37,13 +36,19 @@ class CryptoMessagePrinter : public ::quic::CryptoFramerVisitorInterface {
} // namespace quic
int main(int argc, char* argv[]) {
- InitGoogle(argv[0], &argc, &argv, true);
+ const char* usage = "Usage: crypto_message_printer <hex>";
+ std::vector<std::string> messages =
+ quic::QuicParseCommandLineFlags(usage, argc, argv);
+ if (messages.size() != 1) {
+ quic::QuicPrintCommandLineFlagHelp(usage);
+ exit(0);
+ }
quic::CryptoMessagePrinter printer;
quic::CryptoFramer framer;
framer.set_visitor(&printer);
framer.set_process_truncated_messages(true);
- std::string input = quic::QuicTextUtils::HexDecode(argv[1]);
+ std::string input = quic::QuicTextUtils::HexDecode(messages[0]);
if (!framer.ProcessInput(input)) {
return 1;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h
index d9a1ebce3b5..e63224a38ed 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
@@ -26,12 +26,14 @@ namespace quic {
typedef std::string ServerConfigID;
+// The following tags have been deprecated and should not be reused:
+// "BBQ4", "RCID", "SREJ"
+
// clang-format off
const QuicTag kCHLO = TAG('C', 'H', 'L', 'O'); // Client hello
const QuicTag kSHLO = TAG('S', 'H', 'L', 'O'); // Server hello
const QuicTag kSCFG = TAG('S', 'C', 'F', 'G'); // Server config
const QuicTag kREJ = TAG('R', 'E', 'J', '\0'); // Reject
-const QuicTag kSREJ = TAG('S', 'R', 'E', 'J'); // Stateless reject
const QuicTag kCETV = TAG('C', 'E', 'T', 'V'); // Client encrypted tag-value
// pairs
const QuicTag kPRST = TAG('P', 'R', 'S', 'T'); // Public reset
@@ -112,7 +114,6 @@ const QuicTag kBBQ2 = TAG('B', 'B', 'Q', '2'); // BBR with lower 2.0 STARTUP
// CWND gain.
const QuicTag kBBQ3 = TAG('B', 'B', 'Q', '3'); // BBR with ack aggregation
// compensation in STARTUP.
-const QuicTag kBBQ4 = TAG('B', 'B', 'Q', '4'); // Drain gain of 0.75.
const QuicTag kBBQ5 = TAG('B', 'B', 'Q', '5'); // Expire ack aggregation upon
// bandwidth increase in
// STARTUP.
@@ -188,6 +189,9 @@ const QuicTag kBWRE = TAG('B', 'W', 'R', 'E'); // Bandwidth resumption.
const QuicTag kBWMX = TAG('B', 'W', 'M', 'X'); // Max bandwidth resumption.
const QuicTag kBWRS = TAG('B', 'W', 'R', 'S'); // Server bandwidth resumption.
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
// Enable path MTU discovery experiment.
const QuicTag kMTUH = TAG('M', 'T', 'U', 'H'); // High-target MTU discovery.
@@ -213,7 +217,8 @@ const QuicTag kCOPT = TAG('C', 'O', 'P', 'T'); // Connection options
const QuicTag kCLOP = TAG('C', 'L', 'O', 'P'); // Client connection options
const QuicTag kICSL = TAG('I', 'C', 'S', 'L'); // Idle network timeout
const QuicTag kSCLS = TAG('S', 'C', 'L', 'S'); // Silently close on timeout
-const QuicTag kMIDS = TAG('M', 'I', 'D', 'S'); // Max incoming dynamic streams
+const QuicTag kMIBS = TAG('M', 'I', 'D', 'S'); // Max incoming bidi streams
+const QuicTag kMIUS = TAG('M', 'I', 'U', 'S'); // Max incoming unidi streams
const QuicTag kIRTT = TAG('I', 'R', 'T', 'T'); // Estimated initial RTT in us.
const QuicTag kSNI = TAG('S', 'N', 'I', '\0'); // Server name
// indication
@@ -239,9 +244,7 @@ const QuicTag kTB10 = TAG('T', 'B', '1', '0'); // TB draft 10 with P256.
// Rejection tags
const QuicTag kRREJ = TAG('R', 'R', 'E', 'J'); // Reasons for server sending
-// Stateless Reject tags
-const QuicTag kRCID = TAG('R', 'C', 'I', 'D'); // Server-designated
- // connection ID
+
// Server hello tags
const QuicTag kCADR = TAG('C', 'A', 'D', 'R'); // Client IP address and port
const QuicTag kASAD = TAG('A', 'S', 'A', 'D'); // Alternate Server IP address
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.cc
index 40f69df0013..c44cbb9d7ed 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.cc
@@ -55,7 +55,7 @@ void CryptoSecretBoxer::SetKeys(const std::vector<std::string>& keys) {
key.size(), EVP_AEAD_DEFAULT_TAG_LENGTH));
if (!ctx) {
ERR_clear_error();
- LOG(DFATAL) << "EVP_AEAD_CTX_init failed";
+ QUIC_LOG(DFATAL) << "EVP_AEAD_CTX_init failed";
return;
}
@@ -94,7 +94,7 @@ std::string CryptoSecretBoxer::Box(QuicRandom* rand,
reinterpret_cast<const uint8_t*>(plaintext.data()),
plaintext.size(), nullptr, 0)) {
ERR_clear_error();
- LOG(DFATAL) << "EVP_AEAD_CTX_seal failed";
+ QUIC_LOG(DFATAL) << "EVP_AEAD_CTX_seal failed";
return "";
}
}
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 4d080c700d2..306a28b8ebf 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
@@ -57,29 +57,15 @@ const char kOldConfigId[] = "old-config-id";
} // namespace
struct TestParams {
- TestParams(bool enable_stateless_rejects,
- bool use_stateless_rejects,
- ParsedQuicVersionVector supported_versions)
- : enable_stateless_rejects(enable_stateless_rejects),
- use_stateless_rejects(use_stateless_rejects),
- supported_versions(std::move(supported_versions)) {}
+ TestParams(ParsedQuicVersionVector supported_versions)
+ : supported_versions(std::move(supported_versions)) {}
friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
- os << " enable_stateless_rejects: " << p.enable_stateless_rejects
- << std::endl;
- os << " use_stateless_rejects: " << p.use_stateless_rejects << std::endl;
os << " versions: "
<< ParsedQuicVersionVectorToString(p.supported_versions) << " }";
return os;
}
- // This only enables the stateless reject feature via the feature-flag.
- // It does not force the crypto server to emit stateless rejects.
- bool enable_stateless_rejects;
- // If true, this forces the server to send a stateless reject when
- // rejecting messages. This should be a no-op if
- // enable_stateless_rejects is false.
- bool use_stateless_rejects;
// Versions supported by client and server.
ParsedQuicVersionVector supported_versions;
};
@@ -87,18 +73,14 @@ struct TestParams {
// Constructs various test permutations.
std::vector<TestParams> GetTestParams() {
std::vector<TestParams> params;
- static const bool kTrueFalse[] = {true, false};
- for (bool enable_stateless_rejects : kTrueFalse) {
- for (bool use_stateless_rejects : kTrueFalse) {
- // Start with all versions, remove highest on each iteration.
- ParsedQuicVersionVector supported_versions = AllSupportedVersions();
- while (!supported_versions.empty()) {
- params.push_back(TestParams(enable_stateless_rejects,
- use_stateless_rejects, supported_versions));
- supported_versions.erase(supported_versions.begin());
- }
- }
+
+ // Start with all versions, remove highest on each iteration.
+ ParsedQuicVersionVector supported_versions = AllSupportedVersions();
+ while (!supported_versions.empty()) {
+ params.push_back(TestParams(supported_versions));
+ supported_versions.erase(supported_versions.begin());
}
+
return params;
}
@@ -124,10 +106,6 @@ class CryptoServerTest : public QuicTestWithParam<TestParams> {
client_version_ = supported_versions_.front();
client_version_string_ = ParsedQuicVersionToString(client_version_);
-
- SetQuicReloadableFlag(enable_quic_stateless_reject_support,
- GetParam().enable_stateless_rejects);
- use_stateless_rejects_ = GetParam().use_stateless_rejects;
}
void SetUp() override {
@@ -169,7 +147,6 @@ class CryptoServerTest : public QuicTestWithParam<TestParams> {
const HandshakeFailureReason kRejectReasons[] = {
SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
- CheckForServerDesignatedConnectionId();
QuicStringPiece srct;
ASSERT_TRUE(out_.GetStringPiece(kSourceAddressTokenTag, &srct));
@@ -320,8 +297,8 @@ class CryptoServerTest : public QuicTestWithParam<TestParams> {
result, /*reject_only=*/false,
/*connection_id=*/TestConnectionId(1), server_address, client_address_,
supported_versions_.front(), supported_versions_,
- use_stateless_rejects_, server_designated_connection_id, &clock_, rand_,
- &compressed_certs_cache_, params_, signed_config_,
+ /*use_stateless_rejects=*/false, server_designated_connection_id,
+ &clock_, rand_, &compressed_certs_cache_, params_, signed_config_,
/*total_framing_overhead=*/50, chlo_packet_size_,
QuicMakeUnique<ProcessCallback>(result, should_succeed, error_substr,
&called, &out_));
@@ -352,36 +329,8 @@ class CryptoServerTest : public QuicTestWithParam<TestParams> {
}
}
- // If the server is rejecting statelessly, make sure it contains a
- // server-designated connection id. Once the check is complete,
- // allow the random id-generator to move to the next value.
- void CheckForServerDesignatedConnectionId() {
- uint64_t server_designated_connection_id;
- if (!RejectsAreStateless()) {
- EXPECT_EQ(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND,
- out_.GetUint64(kRCID, &server_designated_connection_id));
- } else {
- ASSERT_EQ(QUIC_NO_ERROR,
- out_.GetUint64(kRCID, &server_designated_connection_id));
- server_designated_connection_id =
- QuicEndian::NetToHost64(server_designated_connection_id);
- EXPECT_EQ(rand_for_id_generation_.RandUint64(),
- server_designated_connection_id);
- }
- rand_for_id_generation_.ChangeValue();
- }
-
void CheckRejectTag() {
- if (RejectsAreStateless()) {
- ASSERT_EQ(kSREJ, out_.tag()) << QuicTagToString(out_.tag());
- } else {
- ASSERT_EQ(kREJ, out_.tag()) << QuicTagToString(out_.tag());
- }
- }
-
- bool RejectsAreStateless() {
- return GetParam().enable_stateless_rejects &&
- GetParam().use_stateless_rejects;
+ ASSERT_EQ(kREJ, out_.tag()) << QuicTagToString(out_.tag());
}
std::string XlctHexString() {
@@ -406,7 +355,6 @@ class CryptoServerTest : public QuicTestWithParam<TestParams> {
QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
CryptoHandshakeMessage out_;
uint8_t orbit_[kOrbitSize];
- bool use_stateless_rejects_;
size_t chlo_packet_size_;
// These strings contain hex escaped values from the server suitable for using
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 724f245fb7c..be12ad42034 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
@@ -76,10 +76,14 @@ void CryptoUtils::SetKeyAndIV(const EVP_MD* prf,
prf, pp_secret, "quic key", crypter->GetKeySize());
std::vector<uint8_t> iv = CryptoUtils::HkdfExpandLabel(
prf, pp_secret, "quic iv", crypter->GetIVSize());
+ std::vector<uint8_t> pn = CryptoUtils::HkdfExpandLabel(
+ prf, pp_secret, "quic hp", crypter->GetKeySize());
crypter->SetKey(
QuicStringPiece(reinterpret_cast<char*>(key.data()), key.size()));
crypter->SetIV(
QuicStringPiece(reinterpret_cast<char*>(iv.data()), iv.size()));
+ crypter->SetHeaderProtectionKey(
+ QuicStringPiece(reinterpret_cast<char*>(pn.data()), pn.size()));
}
namespace {
@@ -97,6 +101,10 @@ void CryptoUtils::CreateTlsInitialCrypters(Perspective perspective,
QuicTransportVersion version,
QuicConnectionId connection_id,
CrypterPair* crypters) {
+ QUIC_DLOG(INFO) << "Creating "
+ << (perspective == Perspective::IS_CLIENT ? "client"
+ : "server")
+ << " TLS crypters for " << connection_id;
QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(connection_id, version))
<< "CreateTlsInitialCrypters: attempted to use connection ID "
<< connection_id << " which is invalid with version "
@@ -224,15 +232,23 @@ bool CryptoUtils::DeriveKeys(QuicStringPiece premaster_secret,
if (perspective == Perspective::IS_SERVER) {
if (!crypters->encrypter->SetKey(hkdf.server_write_key()) ||
!crypters->encrypter->SetNoncePrefix(hkdf.server_write_iv()) ||
+ !crypters->encrypter->SetHeaderProtectionKey(
+ hkdf.server_hp_key()) ||
!crypters->decrypter->SetKey(hkdf.client_write_key()) ||
- !crypters->decrypter->SetNoncePrefix(hkdf.client_write_iv())) {
+ !crypters->decrypter->SetNoncePrefix(hkdf.client_write_iv()) ||
+ !crypters->decrypter->SetHeaderProtectionKey(
+ hkdf.client_hp_key())) {
return false;
}
} else {
if (!crypters->encrypter->SetKey(hkdf.client_write_key()) ||
!crypters->encrypter->SetNoncePrefix(hkdf.client_write_iv()) ||
+ !crypters->encrypter->SetHeaderProtectionKey(
+ hkdf.client_hp_key()) ||
!crypters->decrypter->SetKey(hkdf.server_write_key()) ||
- !crypters->decrypter->SetNoncePrefix(hkdf.server_write_iv())) {
+ !crypters->decrypter->SetNoncePrefix(hkdf.server_write_iv()) ||
+ !crypters->decrypter->SetHeaderProtectionKey(
+ hkdf.server_hp_key())) {
return false;
}
}
@@ -246,8 +262,10 @@ bool CryptoUtils::DeriveKeys(QuicStringPiece premaster_secret,
if (!crypters->encrypter->SetKey(hkdf.client_write_key()) ||
!crypters->encrypter->SetNoncePrefix(hkdf.client_write_iv()) ||
+ !crypters->encrypter->SetHeaderProtectionKey(hkdf.client_hp_key()) ||
!crypters->decrypter->SetPreliminaryKey(hkdf.server_write_key()) ||
- !crypters->decrypter->SetNoncePrefix(hkdf.server_write_iv())) {
+ !crypters->decrypter->SetNoncePrefix(hkdf.server_write_iv()) ||
+ !crypters->decrypter->SetHeaderProtectionKey(hkdf.server_hp_key())) {
return false;
}
break;
@@ -265,8 +283,10 @@ bool CryptoUtils::DeriveKeys(QuicStringPiece premaster_secret,
&nonce_prefix);
if (!crypters->decrypter->SetKey(hkdf.client_write_key()) ||
!crypters->decrypter->SetNoncePrefix(hkdf.client_write_iv()) ||
+ !crypters->decrypter->SetHeaderProtectionKey(hkdf.client_hp_key()) ||
!crypters->encrypter->SetKey(key) ||
- !crypters->encrypter->SetNoncePrefix(nonce_prefix)) {
+ !crypters->encrypter->SetNoncePrefix(nonce_prefix) ||
+ !crypters->encrypter->SetHeaderProtectionKey(hkdf.server_hp_key())) {
return false;
}
break;
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 cc777c7b3cd..fd890987d5d 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
@@ -10,7 +10,7 @@
#include <vector>
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_proof.h"
-#include "net/third_party/quiche/src/quic/core/quic_packets.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/proof_verifier.h b/chromium/net/third_party/quiche/src/quic/core/crypto/proof_verifier.h
index e6605bb0961..38e978a2d6f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/proof_verifier.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/proof_verifier.h
@@ -9,8 +9,8 @@
#include <string>
#include <vector>
-#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
@@ -103,6 +103,8 @@ class QUIC_EXPORT_PRIVATE ProofVerifier {
virtual QuicAsyncStatus VerifyCertChain(
const std::string& hostname,
const std::vector<std::string>& certs,
+ const std::string& ocsp_response,
+ const std::string& cert_sct,
const ProofVerifyContext* context,
std::string* error_details,
std::unique_ptr<ProofVerifyDetails>* details,
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 39838369e93..4fca4bb00a3 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
@@ -11,7 +11,6 @@
#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "net/third_party/quiche/src/quic/core/crypto/cert_compressor.h"
#include "net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_encrypter.h"
-#include "net/third_party/quiche/src/quic/core/crypto/channel_id.h"
#include "net/third_party/quiche/src/quic/core/crypto/common_cert_set.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
@@ -517,7 +516,6 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
const CachedState* cached,
QuicWallTime now,
QuicRandom* rand,
- const ChannelIDKey* channel_id_key,
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
CryptoHandshakeMessage* out,
std::string* error_details) const {
@@ -643,65 +641,6 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
}
out->SetValue(kXLCT, CryptoUtils::ComputeLeafCertHash(certs[0]));
- if (channel_id_key) {
- // In order to calculate the encryption key for the CETV block we need to
- // serialise the client hello as it currently is (i.e. without the CETV
- // block). For this, the client hello is serialized without padding.
- const size_t orig_min_size = out->minimum_size();
- out->set_minimum_size(0);
-
- CryptoHandshakeMessage cetv;
- cetv.set_tag(kCETV);
-
- std::string hkdf_input;
- const QuicData& client_hello_serialized = out->GetSerialized();
- hkdf_input.append(QuicCryptoConfig::kCETVLabel,
- strlen(QuicCryptoConfig::kCETVLabel) + 1);
- hkdf_input.append(connection_id.data(), connection_id.length());
- hkdf_input.append(client_hello_serialized.data(),
- client_hello_serialized.length());
- hkdf_input.append(cached->server_config());
-
- std::string key = channel_id_key->SerializeKey();
- std::string signature;
- if (!channel_id_key->Sign(hkdf_input, &signature)) {
- *error_details = "Channel ID signature failed";
- return QUIC_INVALID_CHANNEL_ID_SIGNATURE;
- }
-
- cetv.SetStringPiece(kCIDK, key);
- cetv.SetStringPiece(kCIDS, signature);
-
- CrypterPair crypters;
- if (!CryptoUtils::DeriveKeys(out_params->initial_premaster_secret,
- out_params->aead, out_params->client_nonce,
- out_params->server_nonce, pre_shared_key_,
- hkdf_input, Perspective::IS_CLIENT,
- CryptoUtils::Diversification::Never(),
- &crypters, nullptr /* subkey secret */)) {
- *error_details = "Symmetric key setup failed";
- return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
- }
-
- const QuicData& cetv_plaintext = cetv.GetSerialized();
- const size_t encrypted_len =
- crypters.encrypter->GetCiphertextSize(cetv_plaintext.length());
- std::unique_ptr<char[]> output(new char[encrypted_len]);
- size_t output_size = 0;
- if (!crypters.encrypter->EncryptPacket(
- 0 /* packet number */, QuicStringPiece() /* associated data */,
- cetv_plaintext.AsStringPiece(), output.get(), &output_size,
- encrypted_len)) {
- *error_details = "Packet encryption failed";
- return QUIC_ENCRYPTION_FAILURE;
- }
-
- out->SetStringPiece(kCETV, QuicStringPiece(output.get(), output_size));
- out->MarkDirty();
-
- out->set_minimum_size(orig_min_size);
- }
-
// Derive the symmetric keys and set up the encrypters and decrypters.
// Set the following members of out_params:
// out_params->hkdf_input_suffix
@@ -822,8 +761,8 @@ QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
std::string* error_details) {
DCHECK(error_details != nullptr);
- if ((rej.tag() != kREJ) && (rej.tag() != kSREJ)) {
- *error_details = "Message is not REJ or SREJ";
+ if (rej.tag() != kREJ) {
+ *error_details = "Message is not REJ";
return QUIC_CRYPTO_INTERNAL_ERROR;
}
@@ -839,30 +778,6 @@ QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
out_params->server_nonce = std::string(nonce);
}
- if (rej.tag() == kSREJ) {
- QuicConnectionId connection_id;
-
- QuicStringPiece connection_id_bytes;
- if (!rej.GetStringPiece(kRCID, &connection_id_bytes)) {
- *error_details = "Missing kRCID";
- return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
- }
- connection_id = QuicConnectionId(connection_id_bytes.data(),
- connection_id_bytes.length());
- if (!QuicUtils::IsConnectionIdValidForVersion(connection_id, version)) {
- QUIC_PEER_BUG << "Received server-designated connection ID "
- << connection_id << " which is invalid with version "
- << QuicVersionToString(version);
- *error_details = "Bad kRCID length";
- return QUIC_CRYPTO_INTERNAL_ERROR;
- }
- cached->add_server_designated_connection_id(connection_id);
- if (!nonce.empty()) {
- cached->add_server_nonce(std::string(nonce));
- }
- return QUIC_NO_ERROR;
- }
-
return QUIC_NO_ERROR;
}
@@ -951,19 +866,10 @@ ProofVerifier* QuicCryptoClientConfig::proof_verifier() const {
return proof_verifier_.get();
}
-ChannelIDSource* QuicCryptoClientConfig::channel_id_source() const {
- return channel_id_source_.get();
-}
-
SSL_CTX* QuicCryptoClientConfig::ssl_ctx() const {
return ssl_ctx_.get();
}
-void QuicCryptoClientConfig::SetChannelIDSource(
- std::unique_ptr<ChannelIDSource> source) {
- channel_id_source_ = std::move(source);
-}
-
void QuicCryptoClientConfig::InitializeFrom(
const QuicServerId& server_id,
const QuicServerId& canonical_server_id,
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 f4293c0c85e..2918a23bb13 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
@@ -22,8 +22,6 @@
namespace quic {
-class ChannelIDKey;
-class ChannelIDSource;
class CryptoHandshakeMessage;
class ProofVerifier;
class ProofVerifyDetails;
@@ -258,7 +256,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
const CachedState* cached,
QuicWallTime now,
QuicRandom* rand,
- const ChannelIDKey* channel_id_key,
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
CryptoHandshakeMessage* out,
std::string* error_details) const;
@@ -312,15 +309,8 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
ProofVerifier* proof_verifier() const;
- ChannelIDSource* channel_id_source() const;
-
SSL_CTX* ssl_ctx() const;
- // SetChannelIDSource sets a ChannelIDSource that will be called, when the
- // server supports channel IDs, to obtain a channel ID for signing a message
- // proving possession of the channel ID.
- void SetChannelIDSource(std::unique_ptr<ChannelIDSource> source);
-
// Initialize the CachedState from |canonical_crypto_config| for the
// |canonical_server_id| as the initial CachedState for |server_id|. We will
// copy config data only if |canonical_crypto_config| has valid proof.
@@ -397,7 +387,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
std::vector<std::string> canonical_suffixes_;
std::unique_ptr<ProofVerifier> proof_verifier_;
- std::unique_ptr<ChannelIDSource> channel_id_source_;
bssl::UniquePtr<SSL_CTX> ssl_ctx_;
// The |user_agent_id_| passed in QUIC's CHLO message.
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc
index 2158cd3859e..563c7f1cc80 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
@@ -323,7 +323,6 @@ TEST_F(QuicCryptoClientConfigTest, FillClientHello) {
QuicServerId server_id("www.google.com", 443, false);
config.FillClientHello(server_id, kConnectionId, QuicVersionMax(), &state,
QuicWallTime::Zero(), &rand,
- nullptr, // channel_id_key
params, &chlo, &error_details);
// Verify that the version label has been set correctly in the CHLO.
@@ -346,7 +345,6 @@ TEST_F(QuicCryptoClientConfigTest, FillClientHelloNoPadding) {
QuicServerId server_id("www.google.com", 443, false);
config.FillClientHello(server_id, kConnectionId, QuicVersionMax(), &state,
QuicWallTime::Zero(), &rand,
- nullptr, // channel_id_key
params, &chlo, &error_details);
// Verify that the version label has been set correctly in the CHLO.
@@ -537,7 +535,7 @@ TEST_F(QuicCryptoClientConfigTest, ClearCachedStates) {
TEST_F(QuicCryptoClientConfigTest, ProcessReject) {
CryptoHandshakeMessage rej;
- crypto_test_utils::FillInDummyReject(&rej, /* stateless */ false);
+ crypto_test_utils::FillInDummyReject(&rej);
// Now process the rejection.
QuicCryptoClientConfig::CachedState cached;
@@ -556,7 +554,7 @@ TEST_F(QuicCryptoClientConfigTest, ProcessReject) {
TEST_F(QuicCryptoClientConfigTest, ProcessRejectWithLongTTL) {
CryptoHandshakeMessage rej;
- crypto_test_utils::FillInDummyReject(&rej, /* stateless */ false);
+ crypto_test_utils::FillInDummyReject(&rej);
QuicTime::Delta one_week = QuicTime::Delta::FromSeconds(kNumSecondsPerWeek);
int64_t long_ttl = 3 * one_week.ToSeconds();
rej.SetValue(kSTTL, long_ttl);
@@ -580,55 +578,6 @@ TEST_F(QuicCryptoClientConfigTest, ProcessRejectWithLongTTL) {
QuicWallTime::FromUNIXSeconds(one_week.ToSeconds() - 1)));
}
-TEST_F(QuicCryptoClientConfigTest, ProcessStatelessReject) {
- // Create a dummy reject message and mark it as stateless.
- CryptoHandshakeMessage rej;
- crypto_test_utils::FillInDummyReject(&rej, /* stateless */ true);
- const QuicConnectionId kConnectionId = TestConnectionId(0xdeadbeef);
- const std::string server_nonce = "SERVER_NONCE";
- const uint64_t kConnectionId64 = TestConnectionIdToUInt64(kConnectionId);
- rej.SetValue(kRCID, kConnectionId64);
- rej.SetStringPiece(kServerNonceTag, server_nonce);
-
- // Now process the rejection.
- QuicCryptoClientConfig::CachedState cached;
- QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params(
- new QuicCryptoNegotiatedParameters);
- std::string error;
- QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(),
- TlsClientHandshaker::CreateSslCtx());
- EXPECT_EQ(QUIC_NO_ERROR,
- config.ProcessRejection(rej, QuicWallTime::FromUNIXSeconds(0),
- AllSupportedTransportVersions().front(), "",
- &cached, out_params, &error));
- EXPECT_TRUE(cached.has_server_designated_connection_id());
- EXPECT_EQ(TestConnectionId(QuicEndian::NetToHost64(
- TestConnectionIdToUInt64(kConnectionId))),
- cached.GetNextServerDesignatedConnectionId());
- EXPECT_EQ(server_nonce, cached.GetNextServerNonce());
-}
-
-TEST_F(QuicCryptoClientConfigTest, BadlyFormattedStatelessReject) {
- // Create a dummy reject message and mark it as stateless. Do not
- // add an server-designated connection-id.
- CryptoHandshakeMessage rej;
- crypto_test_utils::FillInDummyReject(&rej, /* stateless */ true);
-
- // Now process the rejection.
- QuicCryptoClientConfig::CachedState cached;
- QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params(
- new QuicCryptoNegotiatedParameters);
- std::string error;
- QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(),
- TlsClientHandshaker::CreateSslCtx());
- EXPECT_EQ(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND,
- config.ProcessRejection(rej, QuicWallTime::FromUNIXSeconds(0),
- AllSupportedTransportVersions().front(), "",
- &cached, out_params, &error));
- EXPECT_FALSE(cached.has_server_designated_connection_id());
- EXPECT_EQ("Missing kRCID", error);
-}
-
TEST_F(QuicCryptoClientConfigTest, ServerNonceinSHLO) {
// Test that the server must include a nonce in the SHLO.
CryptoHandshakeMessage msg;
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 88875beb5a2..54d4bf48fec 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
@@ -205,7 +205,7 @@ QuicCryptoServerConfig::ConfigOptions::~ConfigOptions() {}
QuicCryptoServerConfig::ProcessClientHelloContext::
~ProcessClientHelloContext() {
if (done_cb_ != nullptr) {
- LOG(WARNING)
+ QUIC_LOG(WARNING)
<< "Deleting ProcessClientHelloContext with a pending callback.";
}
}
@@ -341,10 +341,6 @@ QuicServerConfigProtobuf QuicCryptoServerConfig::GenerateConfig(
msg.SetVector(kPDMD, QuicTagVector{kCHID});
}
- if (!options.token_binding_params.empty()) {
- msg.SetVector(kTBKP, options.token_binding_params);
- }
-
if (options.id.empty()) {
// We need to ensure that the SCID changes whenever the server config does
// thus we make it a hash of the rest of the server config.
@@ -1441,28 +1437,8 @@ void QuicCryptoServerConfig::BuildRejection(
const std::vector<uint32_t>& reject_reasons,
CryptoHandshakeMessage* out) const {
const QuicWallTime now = context.clock()->WallNow();
- if (GetQuicReloadableFlag(enable_quic_stateless_reject_support) &&
- context.use_stateless_rejects()) {
- QUIC_DVLOG(1) << "QUIC Crypto server config returning stateless reject "
- << "with server-designated connection ID "
- << context.server_designated_connection_id();
- out->set_tag(kSREJ);
- if (!QuicUtils::IsConnectionIdValidForVersion(
- context.server_designated_connection_id(),
- context.transport_version())) {
- QUIC_BUG << "Tried to send server designated connection ID "
- << context.server_designated_connection_id()
- << " which is invalid with version "
- << QuicVersionToString(context.transport_version());
- return;
- }
- out->SetStringPiece(
- kRCID,
- QuicStringPiece(context.server_designated_connection_id().data(),
- context.server_designated_connection_id().length()));
- } else {
- out->set_tag(kREJ);
- }
+
+ out->set_tag(kREJ);
out->SetStringPiece(kSCFG, config.serialized);
out->SetStringPiece(
kSourceAddressTokenTag,
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 7f3f947a313..039da84bf6c 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
@@ -191,9 +191,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig {
// channel_id_enabled controls whether the server config will indicate
// support for ChannelIDs.
bool channel_id_enabled;
- // token_binding_params contains the list of Token Binding params (e.g.
- // P256, TB10) that the server config will include.
- QuicTagVector token_binding_params;
// id contains the server config id for the resulting config. If empty, a
// random id is generated.
std::string id;
@@ -341,6 +338,8 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig {
const QuicSocketAddress& client_address,
ParsedQuicVersion version,
const ParsedQuicVersionVector& supported_versions,
+ // TODO(wub): Deprecate use_stateless_rejects and
+ // server_designated_connection_id.
bool use_stateless_rejects,
QuicConnectionId server_designated_connection_id,
const QuicClock* clock,
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.cc
index 3754cab89c2..1bd9ad54c2b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.cc
@@ -39,8 +39,8 @@ QuicHKDF::QuicHKDF(QuicStringPiece secret,
size_t server_iv_bytes_to_generate,
size_t subkey_secret_bytes_to_generate) {
const size_t material_length =
- client_key_bytes_to_generate + client_iv_bytes_to_generate +
- server_key_bytes_to_generate + server_iv_bytes_to_generate +
+ 2 * client_key_bytes_to_generate + client_iv_bytes_to_generate +
+ 2 * server_key_bytes_to_generate + server_iv_bytes_to_generate +
subkey_secret_bytes_to_generate;
DCHECK_LT(material_length, kMaxKeyMaterialSize);
@@ -85,6 +85,19 @@ QuicHKDF::QuicHKDF(QuicStringPiece secret,
if (subkey_secret_bytes_to_generate) {
subkey_secret_ = QuicStringPiece(reinterpret_cast<char*>(&output_[j]),
subkey_secret_bytes_to_generate);
+ j += subkey_secret_bytes_to_generate;
+ }
+ // Repeat client and server key bytes for header protection keys.
+ if (client_key_bytes_to_generate) {
+ client_hp_key_ = QuicStringPiece(reinterpret_cast<char*>(&output_[j]),
+ client_key_bytes_to_generate);
+ j += client_key_bytes_to_generate;
+ }
+
+ if (server_key_bytes_to_generate) {
+ server_hp_key_ = QuicStringPiece(reinterpret_cast<char*>(&output_[j]),
+ server_key_bytes_to_generate);
+ j += server_key_bytes_to_generate;
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h
index fb80f7bd1ad..c57b894b52c 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
@@ -54,6 +54,8 @@ class QUIC_EXPORT QuicHKDF {
QuicStringPiece server_write_key() const { return server_write_key_; }
QuicStringPiece server_write_iv() const { return server_write_iv_; }
QuicStringPiece subkey_secret() const { return subkey_secret_; }
+ QuicStringPiece client_hp_key() const { return client_hp_key_; }
+ QuicStringPiece server_hp_key() const { return server_hp_key_; }
private:
std::vector<uint8_t> output_;
@@ -63,6 +65,8 @@ class QUIC_EXPORT QuicHKDF {
QuicStringPiece client_write_iv_;
QuicStringPiece server_write_iv_;
QuicStringPiece subkey_secret_;
+ QuicStringPiece client_hp_key_;
+ QuicStringPiece server_hp_key_;
};
} // namespace quic
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 60fb22c09f7..ee0ebf094a4 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
@@ -4,184 +4,535 @@
#include "net/third_party/quiche/src/quic/core/crypto/transport_parameters.h"
+#include <cstdint>
+#include <cstring>
+
#include "third_party/boringssl/src/include/openssl/bytestring.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
+#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
+#include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
+#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.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"
namespace quic {
-namespace {
+// Values of the TransportParameterId enum as defined in the
+// "Transport Parameter Encoding" section of draft-ietf-quic-transport.
+// When parameters are encoded, one of these enum values is used to indicate
+// which parameter is encoded. The supported draft version is noted in
+// transport_parameters.h.
+enum TransportParameters::TransportParameterId : uint16_t {
+ kOriginalConnectionId = 0,
+ kIdleTimeout = 1,
+ kStatelessResetToken = 2,
+ kMaxPacketSize = 3,
+ kInitialMaxData = 4,
+ kInitialMaxStreamDataBidiLocal = 5,
+ kInitialMaxStreamDataBidiRemote = 6,
+ kInitialMaxStreamDataUni = 7,
+ kInitialMaxStreamsBidi = 8,
+ kInitialMaxStreamsUni = 9,
+ kAckDelayExponent = 0xa,
+ kMaxAckDelay = 0xb,
+ kDisableMigration = 0xc,
+ kPreferredAddress = 0xd,
-// Values of the TransportParameterId enum as defined in
-// draft-ietf-quic-transport-08 section 7.4. When parameters are encoded, one of
-// these enum values is used to indicate which parameter is encoded.
-enum TransportParameterId : uint16_t {
- kInitialMaxStreamDataId = 0,
- kInitialMaxDataId = 1,
- kInitialMaxBidiStreamsId = 2,
- kIdleTimeoutId = 3,
- kMaxOutgoingPacketSizeId = 5,
- kStatelessResetTokenId = 6,
- kAckDelayExponentId = 7,
- kInitialMaxUniStreamsId = 8,
-
- kMaxKnownParameterId = 9,
+ kGoogleQuicParam = 18257, // Used for non-standard Google-specific params.
+ kGoogleQuicVersion =
+ 18258, // Used to transmit version and supported_versions.
};
-// Value for the TransportParameterId to use for non-standard Google QUIC params
-// in Transport Parameters.
-const uint16_t kGoogleQuicParamId = 18257;
+namespace {
// The following constants define minimum and maximum allowed values for some of
-// the parameters. These come from draft-ietf-quic-transport-08 section 7.4.1.
-const uint16_t kMaxAllowedIdleTimeout = 600;
-const uint16_t kMinAllowedMaxPacketSize = 1200;
-const uint16_t kMaxAllowedMaxPacketSize = 65527;
-const uint8_t kMaxAllowedAckDelayExponent = 20;
-
-static_assert(kMaxKnownParameterId <= 32, "too many parameters to bit pack");
-
-// The initial_max_stream_data, initial_max_data, and idle_timeout parameters
-// are always required to be present. When parsing the extension, a bitmask is
-// used to keep track of which parameter have been seen so far, and that bitmask
-// will be compared to this mask to check that all of the required parameters
-// were present.
-static constexpr uint16_t kRequiredParamsMask = (1 << kInitialMaxStreamDataId) |
- (1 << kInitialMaxDataId) |
- (1 << kIdleTimeoutId);
+// the parameters. These come from the "Transport Parameter Definitions"
+// section of draft-ietf-quic-transport.
+const uint64_t kMinMaxPacketSizeTransportParam = 1200;
+const uint64_t kDefaultMaxPacketSizeTransportParam = 65527;
+const uint64_t kMaxAckDelayExponentTransportParam = 20;
+const uint64_t kDefaultAckDelayExponentTransportParam = 3;
+const uint64_t kMaxMaxAckDelayTransportParam = 16383;
+const uint64_t kDefaultMaxAckDelayTransportParam = 25;
+const size_t kStatelessResetTokenLength = 16;
+
+std::string TransportParameterIdToString(
+ TransportParameters::TransportParameterId param_id) {
+ switch (param_id) {
+ case kOriginalConnectionId:
+ return "original_connection_id";
+ case kIdleTimeout:
+ return "idle_timeout";
+ case kStatelessResetToken:
+ return "stateless_reset_token";
+ case kMaxPacketSize:
+ return "max_packet_size";
+ case kInitialMaxData:
+ return "initial_max_data";
+ case kInitialMaxStreamDataBidiLocal:
+ return "initial_max_stream_data_bidi_local";
+ case kInitialMaxStreamDataBidiRemote:
+ return "initial_max_stream_data_bidi_remote";
+ case kInitialMaxStreamDataUni:
+ return "initial_max_stream_data_uni";
+ case kInitialMaxStreamsBidi:
+ return "initial_max_streams_bidi";
+ case kInitialMaxStreamsUni:
+ return "initial_max_streams_uni";
+ case kAckDelayExponent:
+ return "ack_delay_exponent";
+ case kMaxAckDelay:
+ return "max_ack_delay";
+ case kDisableMigration:
+ return "disable_migration";
+ case kPreferredAddress:
+ return "preferred_address";
+ case kGoogleQuicParam:
+ return "google";
+ case kGoogleQuicVersion:
+ return "google-version";
+ }
+ return "Unknown(" + QuicTextUtils::Uint64ToString(param_id) + ")";
+}
} // namespace
-TransportParameters::TransportParameters() = default;
+TransportParameters::IntegerParameter::IntegerParameter(
+ TransportParameters::TransportParameterId param_id,
+ uint64_t default_value,
+ uint64_t min_value,
+ uint64_t max_value)
+ : param_id_(param_id),
+ value_(default_value),
+ default_value_(default_value),
+ min_value_(min_value),
+ max_value_(max_value),
+ has_been_read_from_cbs_(false) {
+ DCHECK_LE(min_value, default_value);
+ DCHECK_LE(default_value, max_value);
+ DCHECK_LE(max_value, kVarInt62MaxValue);
+}
-TransportParameters::~TransportParameters() = default;
+TransportParameters::IntegerParameter::IntegerParameter(
+ TransportParameters::TransportParameterId param_id)
+ : TransportParameters::IntegerParameter::IntegerParameter(
+ param_id,
+ 0,
+ 0,
+ kVarInt62MaxValue) {}
-bool TransportParameters::is_valid() const {
- if (perspective == Perspective::IS_CLIENT && !stateless_reset_token.empty()) {
+void TransportParameters::IntegerParameter::set_value(uint64_t value) {
+ value_ = value;
+}
+
+uint64_t TransportParameters::IntegerParameter::value() const {
+ return value_;
+}
+
+bool TransportParameters::IntegerParameter::IsValid() const {
+ return min_value_ <= value_ && value_ <= max_value_;
+}
+
+bool TransportParameters::IntegerParameter::WriteToCbb(CBB* parent_cbb) const {
+ DCHECK(IsValid());
+ if (value_ == default_value_) {
+ // Do not write if the value is default.
+ return true;
+ }
+ uint8_t encoded_data[sizeof(uint64_t)] = {};
+ QuicDataWriter writer(sizeof(encoded_data),
+ reinterpret_cast<char*>(encoded_data));
+ writer.WriteVarInt62(value_);
+ const uint16_t value_length = writer.length();
+ DCHECK_LE(value_length, sizeof(encoded_data));
+ const bool ok = CBB_add_u16(parent_cbb, param_id_) &&
+ CBB_add_u16(parent_cbb, value_length) &&
+ CBB_add_bytes(parent_cbb, encoded_data, value_length);
+ QUIC_BUG_IF(!ok) << "Failed to write " << this;
+ return ok;
+}
+
+bool TransportParameters::IntegerParameter::ReadFromCbs(CBS* const value_cbs) {
+ if (has_been_read_from_cbs_) {
+ QUIC_DLOG(ERROR) << "Received a second "
+ << TransportParameterIdToString(param_id_);
+ return false;
+ }
+ has_been_read_from_cbs_ = true;
+ QuicDataReader reader(reinterpret_cast<const char*>(CBS_data(value_cbs)),
+ CBS_len(value_cbs));
+ QuicVariableLengthIntegerLength value_length = reader.PeekVarInt62Length();
+ if (value_length == 0 || !reader.ReadVarInt62(&value_)) {
+ QUIC_DLOG(ERROR) << "Failed to parse value for "
+ << TransportParameterIdToString(param_id_);
return false;
}
- if (perspective == Perspective::IS_SERVER &&
- stateless_reset_token.size() != 16) {
+ if (!reader.IsDoneReading()) {
+ QUIC_DLOG(ERROR) << "Received unexpected " << reader.BytesRemaining()
+ << " bytes after parsing " << this;
return false;
}
- if (idle_timeout > kMaxAllowedIdleTimeout ||
- (max_packet_size.present &&
- (max_packet_size.value > kMaxAllowedMaxPacketSize ||
- max_packet_size.value < kMinAllowedMaxPacketSize)) ||
- (ack_delay_exponent.present &&
- ack_delay_exponent.value > kMaxAllowedAckDelayExponent)) {
+ if (!CBS_skip(value_cbs, value_length)) {
+ QUIC_BUG << "Failed to advance CBS past value for " << this;
return false;
}
return true;
}
+std::string TransportParameters::IntegerParameter::ToString(
+ bool for_use_in_list) const {
+ if (for_use_in_list && value_ == default_value_) {
+ return "";
+ }
+ std::string rv = for_use_in_list ? " " : "";
+ rv += TransportParameterIdToString(param_id_) + " ";
+ rv += QuicTextUtils::Uint64ToString(value_);
+ if (!IsValid()) {
+ rv += " (Invalid)";
+ }
+ return rv;
+}
+
+std::ostream& operator<<(std::ostream& os,
+ const TransportParameters::IntegerParameter& param) {
+ os << param.ToString(/*for_use_in_list=*/false);
+ return os;
+}
+
+TransportParameters::PreferredAddress::PreferredAddress()
+ : ipv4_socket_address(QuicIpAddress::Any4(), 0),
+ ipv6_socket_address(QuicIpAddress::Any6(), 0),
+ connection_id(EmptyQuicConnectionId()),
+ stateless_reset_token(kStatelessResetTokenLength, 0) {}
+
+TransportParameters::PreferredAddress::~PreferredAddress() {}
+
+std::ostream& operator<<(
+ std::ostream& os,
+ const TransportParameters::PreferredAddress& preferred_address) {
+ os << preferred_address.ToString();
+ return os;
+}
+
+std::string TransportParameters::PreferredAddress::ToString() const {
+ return "[" + ipv4_socket_address.ToString() + " " +
+ ipv6_socket_address.ToString() + " connection_id " +
+ connection_id.ToString() + " stateless_reset_token " +
+ QuicTextUtils::HexEncode(
+ reinterpret_cast<const char*>(stateless_reset_token.data()),
+ stateless_reset_token.size()) +
+ "]";
+}
+
+std::ostream& operator<<(std::ostream& os, const TransportParameters& params) {
+ os << params.ToString();
+ return os;
+}
+
+std::string TransportParameters::ToString() const {
+ std::string rv = "[";
+ if (perspective == Perspective::IS_SERVER) {
+ rv += "Server";
+ } else {
+ rv += "Client";
+ }
+ if (version != 0) {
+ rv += " version " + QuicVersionLabelToString(version);
+ }
+ if (!supported_versions.empty()) {
+ rv += " supported_versions " +
+ QuicVersionLabelVectorToString(supported_versions);
+ }
+ if (!original_connection_id.IsEmpty()) {
+ rv += " " + TransportParameterIdToString(kOriginalConnectionId) + " " +
+ original_connection_id.ToString();
+ }
+ rv += idle_timeout_milliseconds.ToString(/*for_use_in_list=*/true);
+ if (!stateless_reset_token.empty()) {
+ rv += " " + TransportParameterIdToString(kStatelessResetToken) + " " +
+ QuicTextUtils::HexEncode(
+ reinterpret_cast<const char*>(stateless_reset_token.data()),
+ stateless_reset_token.size());
+ }
+ rv += max_packet_size.ToString(/*for_use_in_list=*/true);
+ rv += initial_max_data.ToString(/*for_use_in_list=*/true);
+ rv += initial_max_stream_data_bidi_local.ToString(/*for_use_in_list=*/true);
+ rv += initial_max_stream_data_bidi_remote.ToString(/*for_use_in_list=*/true);
+ rv += initial_max_stream_data_uni.ToString(/*for_use_in_list=*/true);
+ rv += initial_max_streams_bidi.ToString(/*for_use_in_list=*/true);
+ rv += initial_max_streams_uni.ToString(/*for_use_in_list=*/true);
+ rv += ack_delay_exponent.ToString(/*for_use_in_list=*/true);
+ rv += max_ack_delay.ToString(/*for_use_in_list=*/true);
+ if (disable_migration) {
+ rv += " " + TransportParameterIdToString(kDisableMigration);
+ }
+ if (preferred_address) {
+ rv += " " + TransportParameterIdToString(kPreferredAddress) + " " +
+ preferred_address->ToString();
+ }
+ if (google_quic_params) {
+ rv += " " + TransportParameterIdToString(kGoogleQuicParam);
+ }
+ rv += "]";
+ return rv;
+}
+
+TransportParameters::TransportParameters()
+ : version(0),
+ original_connection_id(EmptyQuicConnectionId()),
+ idle_timeout_milliseconds(kIdleTimeout),
+ max_packet_size(kMaxPacketSize,
+ kDefaultMaxPacketSizeTransportParam,
+ kMinMaxPacketSizeTransportParam,
+ kVarInt62MaxValue),
+ initial_max_data(kInitialMaxData),
+ initial_max_stream_data_bidi_local(kInitialMaxStreamDataBidiLocal),
+ initial_max_stream_data_bidi_remote(kInitialMaxStreamDataBidiRemote),
+ initial_max_stream_data_uni(kInitialMaxStreamDataUni),
+ initial_max_streams_bidi(kInitialMaxStreamsBidi),
+ initial_max_streams_uni(kInitialMaxStreamsUni),
+ ack_delay_exponent(kAckDelayExponent,
+ kDefaultAckDelayExponentTransportParam,
+ 0,
+ kMaxAckDelayExponentTransportParam),
+ max_ack_delay(kMaxAckDelay,
+ kDefaultMaxAckDelayTransportParam,
+ 0,
+ kMaxMaxAckDelayTransportParam),
+ disable_migration(false)
+// Important note: any new transport parameters must be added
+// to TransportParameters::AreValid, SerializeTransportParameters and
+// ParseTransportParameters.
+{}
+
+bool TransportParameters::AreValid() const {
+ DCHECK(perspective == Perspective::IS_CLIENT ||
+ perspective == Perspective::IS_SERVER);
+ if (perspective == Perspective::IS_CLIENT && !stateless_reset_token.empty()) {
+ QUIC_DLOG(ERROR) << "Client cannot send stateless reset token";
+ return false;
+ }
+ if (perspective == Perspective::IS_CLIENT &&
+ !original_connection_id.IsEmpty()) {
+ QUIC_DLOG(ERROR) << "Client cannot send original connection ID";
+ return false;
+ }
+ if (!stateless_reset_token.empty() &&
+ stateless_reset_token.size() != kStatelessResetTokenLength) {
+ QUIC_DLOG(ERROR) << "Stateless reset token has bad length "
+ << stateless_reset_token.size();
+ return false;
+ }
+ if (perspective == Perspective::IS_CLIENT && preferred_address) {
+ QUIC_DLOG(ERROR) << "Client cannot send preferred address";
+ return false;
+ }
+ if (preferred_address && preferred_address->stateless_reset_token.size() !=
+ kStatelessResetTokenLength) {
+ QUIC_DLOG(ERROR)
+ << "Preferred address stateless reset token has bad length "
+ << preferred_address->stateless_reset_token.size();
+ return false;
+ }
+ if (preferred_address &&
+ (!preferred_address->ipv4_socket_address.host().IsIPv4() ||
+ !preferred_address->ipv6_socket_address.host().IsIPv6())) {
+ QUIC_BUG << "Preferred address family failure";
+ 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();
+ if (!ok) {
+ QUIC_DLOG(ERROR) << "Invalid transport parameters " << *this;
+ }
+ return ok;
+}
+
+TransportParameters::~TransportParameters() = default;
+
bool SerializeTransportParameters(const TransportParameters& in,
std::vector<uint8_t>* out) {
- if (!in.is_valid()) {
+ if (!in.AreValid()) {
+ QUIC_DLOG(ERROR) << "Not serializing invalid transport parameters " << in;
+ return false;
+ }
+ if (in.version == 0 || (in.perspective == Perspective::IS_SERVER &&
+ in.supported_versions.empty())) {
+ QUIC_DLOG(ERROR) << "Refusing to serialize without versions";
return false;
}
+
bssl::ScopedCBB cbb;
- // 28 is the minimum size that the serialized TransportParameters can be,
- // which is when it is for a client and only the required parameters are
- // present. The CBB will grow to fit larger serializations.
- if (!CBB_init(cbb.get(), 28) || !CBB_add_u32(cbb.get(), in.version)) {
+ // Empirically transport parameters generally fit within 128 bytes.
+ // The CBB will grow to fit larger serializations if required.
+ if (!CBB_init(cbb.get(), 128)) {
+ QUIC_BUG << "Failed to initialize CBB for " << in;
return false;
}
- CBB versions;
- if (in.perspective == Perspective::IS_SERVER) {
- if (!CBB_add_u8_length_prefixed(cbb.get(), &versions)) {
+
+ CBB params;
+ // Add length of the transport parameters list.
+ if (!CBB_add_u16_length_prefixed(cbb.get(), &params)) {
+ QUIC_BUG << "Failed to write parameter length for " << in;
+ return false;
+ }
+
+ // original_connection_id
+ CBB original_connection_id_param;
+ if (!in.original_connection_id.IsEmpty()) {
+ DCHECK_EQ(Perspective::IS_SERVER, in.perspective);
+ if (!CBB_add_u16(&params, kOriginalConnectionId) ||
+ !CBB_add_u16_length_prefixed(&params, &original_connection_id_param) ||
+ !CBB_add_bytes(
+ &original_connection_id_param,
+ reinterpret_cast<const uint8_t*>(in.original_connection_id.data()),
+ in.original_connection_id.length())) {
+ QUIC_BUG << "Failed to write original_connection_id "
+ << in.original_connection_id << " for " << in;
return false;
}
- for (QuicVersionLabel version : in.supported_versions) {
- if (!CBB_add_u32(&versions, version)) {
- return false;
- }
- }
}
- CBB params, initial_max_stream_data_param, initial_max_data_param,
- idle_timeout_param;
- // required parameters
- if (!CBB_add_u16_length_prefixed(cbb.get(), &params) ||
- // initial_max_stream_data
- !CBB_add_u16(&params, kInitialMaxStreamDataId) ||
- !CBB_add_u16_length_prefixed(&params, &initial_max_stream_data_param) ||
- !CBB_add_u32(&initial_max_stream_data_param,
- in.initial_max_stream_data) ||
- // initial_max_data
- !CBB_add_u16(&params, kInitialMaxDataId) ||
- !CBB_add_u16_length_prefixed(&params, &initial_max_data_param) ||
- !CBB_add_u32(&initial_max_data_param, in.initial_max_data) ||
- // idle_timeout
- !CBB_add_u16(&params, kIdleTimeoutId) ||
- !CBB_add_u16_length_prefixed(&params, &idle_timeout_param) ||
- !CBB_add_u16(&idle_timeout_param, in.idle_timeout)) {
+ if (!in.idle_timeout_milliseconds.WriteToCbb(&params)) {
+ QUIC_BUG << "Failed to write idle_timeout for " << in;
return false;
}
+ // stateless_reset_token
CBB stateless_reset_token_param;
if (!in.stateless_reset_token.empty()) {
- if (!CBB_add_u16(&params, kStatelessResetTokenId) ||
+ DCHECK_EQ(kStatelessResetTokenLength, in.stateless_reset_token.size());
+ DCHECK_EQ(Perspective::IS_SERVER, in.perspective);
+ if (!CBB_add_u16(&params, kStatelessResetToken) ||
!CBB_add_u16_length_prefixed(&params, &stateless_reset_token_param) ||
!CBB_add_bytes(&stateless_reset_token_param,
in.stateless_reset_token.data(),
in.stateless_reset_token.size())) {
+ QUIC_BUG << "Failed to write stateless_reset_token of length "
+ << in.stateless_reset_token.size() << " for " << in;
return false;
}
}
- CBB initial_max_bidi_streams_param;
- if (in.initial_max_bidi_streams.present) {
- if (!CBB_add_u16(&params, kInitialMaxBidiStreamsId) ||
- !CBB_add_u16_length_prefixed(&params,
- &initial_max_bidi_streams_param) ||
- !CBB_add_u16(&initial_max_bidi_streams_param,
- in.initial_max_bidi_streams.value)) {
- return false;
- }
+ if (!in.max_packet_size.WriteToCbb(&params) ||
+ !in.initial_max_data.WriteToCbb(&params) ||
+ !in.initial_max_stream_data_bidi_local.WriteToCbb(&params) ||
+ !in.initial_max_stream_data_bidi_remote.WriteToCbb(&params) ||
+ !in.initial_max_stream_data_uni.WriteToCbb(&params) ||
+ !in.initial_max_streams_bidi.WriteToCbb(&params) ||
+ !in.initial_max_streams_uni.WriteToCbb(&params) ||
+ !in.ack_delay_exponent.WriteToCbb(&params) ||
+ !in.max_ack_delay.WriteToCbb(&params)) {
+ QUIC_BUG << "Failed to write integers for " << in;
+ return false;
}
- CBB initial_max_uni_streams_param;
- if (in.initial_max_uni_streams.present) {
- if (!CBB_add_u16(&params, kInitialMaxUniStreamsId) ||
- !CBB_add_u16_length_prefixed(&params, &initial_max_uni_streams_param) ||
- !CBB_add_u16(&initial_max_uni_streams_param,
- in.initial_max_uni_streams.value)) {
+
+ // disable_migration
+ if (in.disable_migration) {
+ if (!CBB_add_u16(&params, kDisableMigration) ||
+ !CBB_add_u16(&params, 0u)) { // 0 is the length of this parameter.
+ QUIC_BUG << "Failed to write disable_migration for " << in;
return false;
}
}
- CBB max_packet_size_param;
- if (in.max_packet_size.present) {
- if (!CBB_add_u16(&params, kMaxOutgoingPacketSizeId) ||
- !CBB_add_u16_length_prefixed(&params, &max_packet_size_param) ||
- !CBB_add_u16(&max_packet_size_param, in.max_packet_size.value)) {
+
+ // preferred_address
+ CBB preferred_address_params, preferred_address_connection_id_param;
+ if (in.preferred_address) {
+ std::string v4_address_bytes =
+ in.preferred_address->ipv4_socket_address.host().ToPackedString();
+ std::string v6_address_bytes =
+ in.preferred_address->ipv6_socket_address.host().ToPackedString();
+ if (v4_address_bytes.length() != 4 || v6_address_bytes.length() != 16 ||
+ in.preferred_address->stateless_reset_token.size() !=
+ kStatelessResetTokenLength) {
+ QUIC_BUG << "Bad lengths " << *in.preferred_address;
return false;
}
- }
- CBB ack_delay_exponent_param;
- if (in.ack_delay_exponent.present) {
- if (!CBB_add_u16(&params, kAckDelayExponentId) ||
- !CBB_add_u16_length_prefixed(&params, &ack_delay_exponent_param) ||
- !CBB_add_u8(&ack_delay_exponent_param, in.ack_delay_exponent.value)) {
+ if (!CBB_add_u16(&params, kPreferredAddress) ||
+ !CBB_add_u16_length_prefixed(&params, &preferred_address_params) ||
+ !CBB_add_bytes(
+ &preferred_address_params,
+ reinterpret_cast<const uint8_t*>(v4_address_bytes.data()),
+ v4_address_bytes.length()) ||
+ !CBB_add_u16(&preferred_address_params,
+ in.preferred_address->ipv4_socket_address.port()) ||
+ !CBB_add_bytes(
+ &preferred_address_params,
+ reinterpret_cast<const uint8_t*>(v6_address_bytes.data()),
+ v6_address_bytes.length()) ||
+ !CBB_add_u16(&preferred_address_params,
+ in.preferred_address->ipv6_socket_address.port()) ||
+ !CBB_add_u8_length_prefixed(&preferred_address_params,
+ &preferred_address_connection_id_param) ||
+ !CBB_add_bytes(&preferred_address_connection_id_param,
+ reinterpret_cast<const uint8_t*>(
+ in.preferred_address->connection_id.data()),
+ in.preferred_address->connection_id.length()) ||
+ !CBB_add_bytes(&preferred_address_params,
+ in.preferred_address->stateless_reset_token.data(),
+ in.preferred_address->stateless_reset_token.size())) {
+ QUIC_BUG << "Failed to write preferred_address for " << in;
return false;
}
}
+
+ // Google-specific non-standard parameter.
CBB google_quic_params;
if (in.google_quic_params) {
const QuicData& serialized_google_quic_params =
in.google_quic_params->GetSerialized();
- if (!CBB_add_u16(&params, kGoogleQuicParamId) ||
+ if (!CBB_add_u16(&params, kGoogleQuicParam) ||
!CBB_add_u16_length_prefixed(&params, &google_quic_params) ||
!CBB_add_bytes(&google_quic_params,
reinterpret_cast<const uint8_t*>(
serialized_google_quic_params.data()),
serialized_google_quic_params.length())) {
+ QUIC_BUG << "Failed to write Google params of length "
+ << serialized_google_quic_params.length() << " for " << in;
+ return false;
+ }
+ }
+
+ // Google-specific version extension.
+ CBB google_version_params;
+ if (!CBB_add_u16(&params, kGoogleQuicVersion) ||
+ !CBB_add_u16_length_prefixed(&params, &google_version_params) ||
+ !CBB_add_u32(&google_version_params, in.version)) {
+ QUIC_BUG << "Failed to write Google version extension for " << in;
+ return false;
+ }
+ CBB versions;
+ if (in.perspective == Perspective::IS_SERVER) {
+ if (!CBB_add_u8_length_prefixed(&google_version_params, &versions)) {
+ QUIC_BUG << "Failed to write versions length for " << in;
return false;
}
+ for (QuicVersionLabel version : in.supported_versions) {
+ if (!CBB_add_u32(&versions, version)) {
+ QUIC_BUG << "Failed to write supported version for " << in;
+ return false;
+ }
+ }
}
+
if (!CBB_flush(cbb.get())) {
+ QUIC_BUG << "Failed to flush CBB for " << in;
return false;
}
out->resize(CBB_len(cbb.get()));
memcpy(out->data(), CBB_data(cbb.get()), CBB_len(cbb.get()));
+ QUIC_DLOG(INFO) << "Serialized " << in << " as " << CBB_len(cbb.get())
+ << " bytes";
return true;
}
@@ -189,114 +540,205 @@ bool ParseTransportParameters(const uint8_t* in,
size_t in_len,
Perspective perspective,
TransportParameters* out) {
+ out->perspective = perspective;
CBS cbs;
CBS_init(&cbs, in, in_len);
- if (!CBS_get_u32(&cbs, &out->version)) {
- return false;
- }
- if (perspective == Perspective::IS_SERVER) {
- CBS versions;
- if (!CBS_get_u8_length_prefixed(&cbs, &versions) ||
- CBS_len(&versions) % 4 != 0) {
- return false;
- }
- while (CBS_len(&versions) > 0) {
- QuicVersionLabel version;
- if (!CBS_get_u32(&versions, &version)) {
- return false;
- }
- out->supported_versions.push_back(version);
- }
- }
- out->perspective = perspective;
- uint32_t present_params = 0;
- bool has_google_quic_params = false;
CBS params;
if (!CBS_get_u16_length_prefixed(&cbs, &params)) {
+ QUIC_DLOG(ERROR) << "Failed to parse the number of transport parameters";
return false;
}
+
while (CBS_len(&params) > 0) {
- uint16_t param_id;
+ TransportParameters::TransportParameterId param_id;
CBS value;
- if (!CBS_get_u16(&params, &param_id) ||
- !CBS_get_u16_length_prefixed(&params, &value)) {
+ static_assert(sizeof(param_id) == sizeof(uint16_t), "bad size");
+ if (!CBS_get_u16(&params, reinterpret_cast<uint16_t*>(&param_id))) {
+ QUIC_DLOG(ERROR) << "Failed to parse transport parameter ID";
return false;
}
- if (param_id < kMaxKnownParameterId) {
- uint16_t mask = 1 << param_id;
- if (present_params & mask) {
- return false;
- }
- present_params |= mask;
+ if (!CBS_get_u16_length_prefixed(&params, &value)) {
+ QUIC_DLOG(ERROR) << "Failed to parse length of transport parameter "
+ << TransportParameterIdToString(param_id);
+ return false;
}
+ bool parse_success = true;
switch (param_id) {
- case kInitialMaxStreamDataId:
- if (!CBS_get_u32(&value, &out->initial_max_stream_data) ||
- CBS_len(&value) != 0) {
+ case kOriginalConnectionId:
+ if (!out->original_connection_id.IsEmpty()) {
+ QUIC_DLOG(ERROR) << "Received a second original connection ID";
return false;
}
- break;
- case kInitialMaxDataId:
- if (!CBS_get_u32(&value, &out->initial_max_data) ||
- CBS_len(&value) != 0) {
+ if (CBS_len(&value) > static_cast<size_t>(kQuicMaxConnectionIdLength)) {
+ QUIC_DLOG(ERROR) << "Received original connection ID of "
+ << "invalid length " << CBS_len(&value);
return false;
}
- break;
- case kInitialMaxBidiStreamsId:
- if (!CBS_get_u16(&value, &out->initial_max_bidi_streams.value) ||
- CBS_len(&value) != 0) {
- return false;
+ if (CBS_len(&value) != 0) {
+ out->original_connection_id.set_length(CBS_len(&value));
+ memcpy(out->original_connection_id.mutable_data(), CBS_data(&value),
+ CBS_len(&value));
}
- out->initial_max_bidi_streams.present = true;
break;
- case kIdleTimeoutId:
- if (!CBS_get_u16(&value, &out->idle_timeout) || CBS_len(&value) != 0) {
- return false;
- }
+ case kIdleTimeout:
+ parse_success = out->idle_timeout_milliseconds.ReadFromCbs(&value);
break;
- case kMaxOutgoingPacketSizeId:
- if (!CBS_get_u16(&value, &out->max_packet_size.value) ||
- CBS_len(&value) != 0) {
+ case kStatelessResetToken:
+ if (!out->stateless_reset_token.empty()) {
+ QUIC_DLOG(ERROR) << "Received a second stateless reset token";
return false;
}
- out->max_packet_size.present = true;
- break;
- case kStatelessResetTokenId:
- if (CBS_len(&value) == 0) {
+ if (CBS_len(&value) != kStatelessResetTokenLength) {
+ QUIC_DLOG(ERROR) << "Received stateless reset token of "
+ << "invalid length " << CBS_len(&value);
return false;
}
out->stateless_reset_token.assign(CBS_data(&value),
CBS_data(&value) + CBS_len(&value));
break;
- case kAckDelayExponentId:
- if (!CBS_get_u8(&value, &out->ack_delay_exponent.value) ||
- CBS_len(&value) != 0) {
+ case kMaxPacketSize:
+ parse_success = out->max_packet_size.ReadFromCbs(&value);
+ break;
+ case kInitialMaxData:
+ parse_success = out->initial_max_data.ReadFromCbs(&value);
+ break;
+ case kInitialMaxStreamDataBidiLocal:
+ parse_success =
+ out->initial_max_stream_data_bidi_local.ReadFromCbs(&value);
+ break;
+ case kInitialMaxStreamDataBidiRemote:
+ parse_success =
+ out->initial_max_stream_data_bidi_remote.ReadFromCbs(&value);
+ break;
+ case kInitialMaxStreamDataUni:
+ parse_success = out->initial_max_stream_data_uni.ReadFromCbs(&value);
+ break;
+ case kInitialMaxStreamsBidi:
+ parse_success = out->initial_max_streams_bidi.ReadFromCbs(&value);
+ break;
+ case kInitialMaxStreamsUni:
+ parse_success = out->initial_max_streams_uni.ReadFromCbs(&value);
+ break;
+ case kAckDelayExponent:
+ parse_success = out->ack_delay_exponent.ReadFromCbs(&value);
+ break;
+ case kMaxAckDelay:
+ parse_success = out->max_ack_delay.ReadFromCbs(&value);
+ break;
+ case kDisableMigration:
+ if (out->disable_migration) {
+ QUIC_DLOG(ERROR) << "Received a second disable migration";
return false;
}
- out->ack_delay_exponent.present = true;
- break;
- case kInitialMaxUniStreamsId:
- if (!CBS_get_u16(&value, &out->initial_max_uni_streams.value) ||
- CBS_len(&value) != 0) {
+ if (CBS_len(&value) != 0) {
+ QUIC_DLOG(ERROR) << "Received disable migration of invalid length "
+ << CBS_len(&value);
return false;
}
- out->initial_max_uni_streams.present = true;
+ out->disable_migration = true;
break;
- case kGoogleQuicParamId:
- if (has_google_quic_params) {
+ case kPreferredAddress: {
+ uint16_t ipv4_port, ipv6_port;
+ in_addr ipv4_address;
+ in6_addr ipv6_address;
+ if (!CBS_copy_bytes(&value, reinterpret_cast<uint8_t*>(&ipv4_address),
+ sizeof(ipv4_address)) ||
+ !CBS_get_u16(&value, &ipv4_port) ||
+ !CBS_copy_bytes(&value, reinterpret_cast<uint8_t*>(&ipv6_address),
+ sizeof(ipv6_address)) ||
+ !CBS_get_u16(&value, &ipv6_port)) {
+ QUIC_DLOG(ERROR) << "Failed to parse preferred address IPs and ports";
+ return false;
+ }
+ TransportParameters::PreferredAddress preferred_address;
+ preferred_address.ipv4_socket_address =
+ QuicSocketAddress(QuicIpAddress(ipv4_address), ipv4_port);
+ preferred_address.ipv6_socket_address =
+ QuicSocketAddress(QuicIpAddress(ipv6_address), ipv6_port);
+ if (!preferred_address.ipv4_socket_address.host().IsIPv4() ||
+ !preferred_address.ipv6_socket_address.host().IsIPv6()) {
+ QUIC_DLOG(ERROR) << "Received preferred addresses of bad families "
+ << preferred_address;
+ return false;
+ }
+ CBS connection_id_cbs;
+ if (!CBS_get_u8_length_prefixed(&value, &connection_id_cbs)) {
+ QUIC_DLOG(ERROR)
+ << "Failed to parse length of preferred address connection ID";
+ return false;
+ }
+ if (CBS_len(&connection_id_cbs) > kQuicMaxConnectionIdLength) {
+ QUIC_DLOG(ERROR) << "Bad preferred address connection ID length";
+ return false;
+ }
+ preferred_address.connection_id.set_length(CBS_len(&connection_id_cbs));
+ if (preferred_address.connection_id.length() > 0 &&
+ !CBS_copy_bytes(&connection_id_cbs,
+ reinterpret_cast<uint8_t*>(
+ preferred_address.connection_id.mutable_data()),
+ preferred_address.connection_id.length())) {
+ QUIC_DLOG(ERROR) << "Failed to read preferred address connection ID";
+ return false;
+ }
+ if (CBS_len(&value) != kStatelessResetTokenLength) {
+ QUIC_DLOG(ERROR) << "Received preferred address with "
+ << "invalid remaining length " << CBS_len(&value);
+ return false;
+ }
+ preferred_address.stateless_reset_token.assign(
+ CBS_data(&value), CBS_data(&value) + CBS_len(&value));
+ out->preferred_address =
+ QuicMakeUnique<TransportParameters::PreferredAddress>(
+ preferred_address);
+ } break;
+ case kGoogleQuicParam: {
+ if (out->google_quic_params) {
+ QUIC_DLOG(ERROR) << "Received a second Google parameter";
return false;
}
- has_google_quic_params = true;
QuicStringPiece serialized_params(
reinterpret_cast<const char*>(CBS_data(&value)), CBS_len(&value));
out->google_quic_params = CryptoFramer::ParseMessage(serialized_params);
+ } break;
+ case kGoogleQuicVersion: {
+ if (!CBS_get_u32(&value, &out->version)) {
+ QUIC_DLOG(ERROR) << "Failed to parse Google version extension";
+ return false;
+ }
+ if (perspective == Perspective::IS_SERVER) {
+ CBS versions;
+ if (!CBS_get_u8_length_prefixed(&value, &versions) ||
+ CBS_len(&versions) % 4 != 0) {
+ QUIC_DLOG(ERROR)
+ << "Failed to parse Google supported versions length";
+ return false;
+ }
+ while (CBS_len(&versions) > 0) {
+ QuicVersionLabel version;
+ if (!CBS_get_u32(&versions, &version)) {
+ QUIC_DLOG(ERROR) << "Failed to parse Google supported version";
+ return false;
+ }
+ out->supported_versions.push_back(version);
+ }
+ }
+ } break;
+ }
+ if (!parse_success) {
+ return false;
}
}
- if ((present_params & kRequiredParamsMask) != kRequiredParamsMask) {
- return false;
+
+ const bool ok = out->AreValid();
+ if (ok) {
+ QUIC_DLOG(INFO) << "Parsed transport parameters " << *out << " from "
+ << in_len << " bytes";
+ } else {
+ QUIC_DLOG(ERROR) << "Transport parameter validity check failed " << *out
+ << " from " << in_len << " bytes";
}
- return out->is_valid();
+ return ok;
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h
index b8abc0ba7f6..27b5fe77e38 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/transport_parameters.h
@@ -8,71 +8,178 @@
#include <memory>
#include <vector>
+#include "third_party/boringssl/src/include/openssl/bytestring.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
+#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
+#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
namespace quic {
// TransportParameters contains parameters for QUIC's transport layer that are
-// indicated during the TLS handshake. This struct is a mirror of the struct in
-// section 6.4 of draft-ietf-quic-transport-11.
+// exchanged during the TLS handshake. This struct is a mirror of the struct in
+// the "Transport Parameter Encoding" section of draft-ietf-quic-transport.
+// This struct currently uses the values from draft 20.
struct QUIC_EXPORT_PRIVATE TransportParameters {
+ // The identifier used to differentiate transport parameters.
+ enum TransportParameterId : uint16_t;
+ // Represents an individual QUIC transport parameter that only encodes a
+ // variable length integer. Can only be created inside the constructor for
+ // TransportParameters.
+ class QUIC_EXPORT_PRIVATE IntegerParameter {
+ public:
+ // Forbid constructing and copying apart from TransportParameters.
+ IntegerParameter() = delete;
+ IntegerParameter(const IntegerParameter&) = delete;
+ IntegerParameter& operator=(const IntegerParameter&) = delete;
+ // Sets the value of this transport parameter.
+ void set_value(uint64_t value);
+ // Gets the value of this transport parameter.
+ uint64_t value() const;
+ // Validates whether the current value is valid.
+ bool IsValid() const;
+ // Writes to a crypto byte buffer, used during serialization. Does not write
+ // anything if the value is equal to the parameter's default value.
+ // Returns whether the write was successful.
+ bool WriteToCbb(CBB* parent_cbb) const;
+ // Reads from a crypto byte string, used during parsing.
+ // Returns whether the read was successful.
+ bool ReadFromCbs(CBS* const value_cbs);
+ // operator<< allows easily logging integer transport parameters.
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const IntegerParameter& param);
+
+ private:
+ friend struct TransportParameters;
+ // Constructors for initial setup used by TransportParameters only.
+ // This constructor sets |default_value| and |min_value| to 0, and
+ // |max_value| to kVarInt62MaxValue.
+ explicit IntegerParameter(TransportParameterId param_id);
+ IntegerParameter(TransportParameterId param_id,
+ uint64_t default_value,
+ uint64_t min_value,
+ uint64_t max_value);
+ // Human-readable string representation.
+ std::string ToString(bool for_use_in_list) const;
+
+ // Number used to indicate this transport parameter.
+ TransportParameterId param_id_;
+ // Current value of the transport parameter.
+ uint64_t value_;
+ // Default value of this transport parameter, as per IETF specification.
+ const uint64_t default_value_;
+ // Minimum value of this transport parameter, as per IETF specification.
+ const uint64_t min_value_;
+ // Maximum value of this transport parameter, as per IETF specification.
+ const uint64_t max_value_;
+ // Ensures this parameter is not parsed twice in the same message.
+ bool has_been_read_from_cbs_;
+ };
+
+ // Represents the preferred_address transport parameter that a server can
+ // send to clients.
+ struct QUIC_EXPORT_PRIVATE PreferredAddress {
+ PreferredAddress();
+ ~PreferredAddress();
+
+ QuicSocketAddress ipv4_socket_address;
+ QuicSocketAddress ipv6_socket_address;
+ QuicConnectionId connection_id;
+ std::vector<uint8_t> stateless_reset_token;
+
+ // Allows easily logging.
+ std::string ToString() const;
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const TransportParameters& params);
+ };
+
TransportParameters();
~TransportParameters();
- // When |perspective| is Perspective::IS_CLIENT, this struct is being used in
- // the client_hello handshake message; when it is Perspective::IS_SERVER, it
- // is being used in the encrypted_extensions handshake message.
+ // Represents the sender of the transport parameters. When |perspective| is
+ // Perspective::IS_CLIENT, this struct is being used in the client_hello
+ // handshake message; when it is Perspective::IS_SERVER, it is being used in
+ // the encrypted_extensions handshake message.
Perspective perspective;
// When Perspective::IS_CLIENT, |version| is the initial version offered by
// the client (before any version negotiation packets) for this connection.
// When Perspective::IS_SERVER, |version| is the version that is in use.
- QuicVersionLabel version = 0;
-
- // Server-only parameters:
+ QuicVersionLabel version;
// |supported_versions| contains a list of all versions that the server would
// send in a version negotiation packet. It is not used if |perspective ==
// Perspective::IS_CLIENT|.
QuicVersionLabelVector supported_versions;
- // See section 6.4.1 of draft-ietf-quic-transport-11 for definition.
+ // The value of the Destination Connection ID field from the first
+ // Initial packet sent by the client.
+ QuicConnectionId original_connection_id;
+
+ // Idle timeout expressed in milliseconds.
+ IntegerParameter idle_timeout_milliseconds;
+
+ // Stateless reset token used in verifying stateless resets.
std::vector<uint8_t> stateless_reset_token;
- // Required parameters. See section 6.4.1 of draft-ietf-quic-transport-11 for
- // definitions.
- uint32_t initial_max_stream_data = 0;
- uint32_t initial_max_data = 0;
- uint16_t idle_timeout = 0;
+ // Limits the size of packets that the endpoint is willing to receive.
+ // This indicates that packets larger than this limit will be dropped.
+ IntegerParameter max_packet_size;
- template <typename T>
- struct OptionalParam {
- bool present = false;
- T value;
- };
+ // Contains the initial value for the maximum amount of data that can
+ // be sent on the connection.
+ IntegerParameter initial_max_data;
+
+ // Initial flow control limit for locally-initiated bidirectional streams.
+ IntegerParameter initial_max_stream_data_bidi_local;
- // Optional parameters. See section 6.4.1 of draft-ietf-quic-transport-11 for
- // definitions.
- OptionalParam<uint16_t> initial_max_bidi_streams;
- OptionalParam<uint16_t> initial_max_uni_streams;
- OptionalParam<uint16_t> max_packet_size;
- OptionalParam<uint8_t> ack_delay_exponent;
+ // Initial flow control limit for peer-initiated bidirectional streams.
+ IntegerParameter initial_max_stream_data_bidi_remote;
+
+ // Initial flow control limit for unidirectional streams.
+ IntegerParameter initial_max_stream_data_uni;
+
+ // Initial maximum number of bidirectional streams the peer may initiate.
+ IntegerParameter initial_max_streams_bidi;
+
+ // Initial maximum number of unidirectional streams the peer may initiate.
+ IntegerParameter initial_max_streams_uni;
+
+ // Exponent used to decode the ACK Delay field in ACK frames.
+ IntegerParameter ack_delay_exponent;
+
+ // Maximum amount of time in milliseconds by which the endpoint will
+ // delay sending acknowledgments.
+ IntegerParameter max_ack_delay;
+
+ // Indicates lack of support for connection migration.
+ bool disable_migration;
+
+ // Used to effect a change in server address at the end of the handshake.
+ std::unique_ptr<PreferredAddress> preferred_address;
// Transport parameters used by Google QUIC but not IETF QUIC. This is
// serialized into a TransportParameter struct with a TransportParameterId of
- // 18257.
+ // kGoogleQuicParamId.
std::unique_ptr<CryptoHandshakeMessage> google_quic_params;
- // Returns true if the contents of this struct are valid.
- bool is_valid() const;
+ // Validates whether transport parameters are valid according to
+ // the specification.
+ bool AreValid() const;
+
+ // Allows easily logging transport parameters.
+ std::string ToString() const;
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const TransportParameters& params);
};
// Serializes a TransportParameters struct into the format for sending it in a
-// TLS extension. The serialized bytes are put in |*out|, and this function
-// returns true on success or false if |TransportParameters::is_valid| returns
-// false.
+// TLS extension. The serialized bytes are written to |*out|. Returns if the
+// parameters are valid and serialization succeeded.
QUIC_EXPORT_PRIVATE bool SerializeTransportParameters(
const TransportParameters& in,
std::vector<uint8_t>* out);
@@ -80,8 +187,7 @@ QUIC_EXPORT_PRIVATE bool SerializeTransportParameters(
// Parses bytes from the quic_transport_parameters TLS extension and writes the
// parsed parameters into |*out|. Input is read from |in| for |in_len| bytes.
// |perspective| indicates whether the input came from a client or a server.
-// This method returns true if the input was successfully parsed, and false if
-// it could not be parsed.
+// This method returns true if the input was successfully parsed.
// TODO(nharper): Write fuzz tests for this method.
QUIC_EXPORT_PRIVATE bool ParseTransportParameters(const uint8_t* in,
size_t in_len,
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 23b18e54bbc..7776af14b13 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
@@ -4,31 +4,98 @@
#include "net/third_party/quiche/src/quic/core/crypto/transport_parameters.h"
+#include <cstring>
+
#include "third_party/boringssl/src/include/openssl/mem.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.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"
namespace quic {
namespace test {
+namespace {
+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;
+const uint64_t kFakeInitialMaxStreamDataBidiRemote = 2002;
+const uint64_t kFakeInitialMaxStreamDataUni = 3000;
+const uint64_t kFakeInitialMaxStreamsBidi = 21;
+const uint64_t kFakeInitialMaxStreamsUni = 22;
+const uint64_t kFakeAckDelayExponent = 10;
+const uint64_t kFakeMaxAckDelay = 51;
+const bool kFakeDisableMigration = true;
+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));
+
+QuicSocketAddress CreateFakeV4SocketAddress() {
+ QuicIpAddress ipv4_address;
+ if (!ipv4_address.FromString("65.66.67.68")) { // 0x41, 0x42, 0x43, 0x44
+ QUIC_LOG(FATAL) << "Failed to create IPv4 address";
+ return QuicSocketAddress();
+ }
+ return QuicSocketAddress(ipv4_address, 0x4884);
+}
+
+QuicSocketAddress CreateFakeV6SocketAddress() {
+ QuicIpAddress ipv6_address;
+ if (!ipv6_address.FromString("6061:6263:6465:6667:6869:6A6B:6C6D:6E6F")) {
+ QUIC_LOG(FATAL) << "Failed to create IPv6 address";
+ return QuicSocketAddress();
+ }
+ return QuicSocketAddress(ipv6_address, 0x6336);
+}
+
+std::unique_ptr<TransportParameters::PreferredAddress>
+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;
+ return QuicMakeUnique<TransportParameters::PreferredAddress>(
+ preferred_address);
+}
+
+} // namespace
class TransportParametersTest : public QuicTest {};
TEST_F(TransportParametersTest, RoundTripClient) {
TransportParameters orig_params;
orig_params.perspective = Perspective::IS_CLIENT;
- orig_params.initial_max_stream_data = 12;
- orig_params.initial_max_data = 34;
- orig_params.idle_timeout = 56;
- orig_params.initial_max_bidi_streams.present = true;
- orig_params.initial_max_bidi_streams.value = 2000;
- orig_params.initial_max_uni_streams.present = true;
- orig_params.initial_max_uni_streams.value = 3000;
- orig_params.max_packet_size.present = true;
- orig_params.max_packet_size.value = 9001;
- orig_params.ack_delay_exponent.present = true;
- orig_params.ack_delay_exponent.value = 10;
- orig_params.version = 0xff000005;
+ orig_params.version = kFakeVersionLabel;
+ orig_params.idle_timeout_milliseconds.set_value(kFakeIdleTimeoutMilliseconds);
+ 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(
+ kFakeInitialMaxStreamDataBidiLocal);
+ orig_params.initial_max_stream_data_bidi_remote.set_value(
+ kFakeInitialMaxStreamDataBidiRemote);
+ orig_params.initial_max_stream_data_uni.set_value(
+ kFakeInitialMaxStreamDataUni);
+ orig_params.initial_max_streams_bidi.set_value(kFakeInitialMaxStreamsBidi);
+ orig_params.initial_max_streams_uni.set_value(kFakeInitialMaxStreamsUni);
+ orig_params.ack_delay_exponent.set_value(kFakeAckDelayExponent);
+ orig_params.max_ack_delay.set_value(kFakeMaxAckDelay);
+ orig_params.disable_migration = kFakeDisableMigration;
std::vector<uint8_t> serialized;
ASSERT_TRUE(SerializeTransportParameters(orig_params, &serialized));
@@ -37,35 +104,53 @@ TEST_F(TransportParametersTest, RoundTripClient) {
ASSERT_TRUE(ParseTransportParameters(serialized.data(), serialized.size(),
Perspective::IS_CLIENT, &new_params));
- EXPECT_EQ(new_params.initial_max_stream_data,
- orig_params.initial_max_stream_data);
- EXPECT_EQ(new_params.initial_max_data, orig_params.initial_max_data);
- EXPECT_EQ(new_params.idle_timeout, orig_params.idle_timeout);
- EXPECT_EQ(new_params.version, orig_params.version);
- EXPECT_TRUE(new_params.initial_max_bidi_streams.present);
- EXPECT_EQ(new_params.initial_max_bidi_streams.value,
- orig_params.initial_max_bidi_streams.value);
- EXPECT_TRUE(new_params.initial_max_uni_streams.present);
- EXPECT_EQ(new_params.initial_max_uni_streams.value,
- orig_params.initial_max_uni_streams.value);
- EXPECT_TRUE(new_params.max_packet_size.present);
- EXPECT_EQ(new_params.max_packet_size.value,
- orig_params.max_packet_size.value);
- EXPECT_TRUE(new_params.ack_delay_exponent.present);
- EXPECT_EQ(new_params.ack_delay_exponent.value,
- orig_params.ack_delay_exponent.value);
+ EXPECT_EQ(Perspective::IS_CLIENT, new_params.perspective);
+ EXPECT_EQ(kFakeVersionLabel, new_params.version);
+ EXPECT_TRUE(new_params.supported_versions.empty());
+ EXPECT_EQ(EmptyQuicConnectionId(), new_params.original_connection_id);
+ EXPECT_EQ(kFakeIdleTimeoutMilliseconds,
+ new_params.idle_timeout_milliseconds.value());
+ EXPECT_TRUE(new_params.stateless_reset_token.empty());
+ EXPECT_EQ(kFakeMaxPacketSize, new_params.max_packet_size.value());
+ EXPECT_EQ(kFakeInitialMaxData, new_params.initial_max_data.value());
+ EXPECT_EQ(kFakeInitialMaxStreamDataBidiLocal,
+ new_params.initial_max_stream_data_bidi_local.value());
+ EXPECT_EQ(kFakeInitialMaxStreamDataBidiRemote,
+ new_params.initial_max_stream_data_bidi_remote.value());
+ EXPECT_EQ(kFakeInitialMaxStreamDataUni,
+ new_params.initial_max_stream_data_uni.value());
+ EXPECT_EQ(kFakeInitialMaxStreamsBidi,
+ new_params.initial_max_streams_bidi.value());
+ EXPECT_EQ(kFakeInitialMaxStreamsUni,
+ new_params.initial_max_streams_uni.value());
+ EXPECT_EQ(kFakeAckDelayExponent, new_params.ack_delay_exponent.value());
+ EXPECT_EQ(kFakeMaxAckDelay, new_params.max_ack_delay.value());
+ EXPECT_EQ(kFakeDisableMigration, new_params.disable_migration);
}
TEST_F(TransportParametersTest, RoundTripServer) {
TransportParameters orig_params;
orig_params.perspective = Perspective::IS_SERVER;
- orig_params.initial_max_stream_data = 12;
- orig_params.initial_max_data = 34;
- orig_params.idle_timeout = 56;
- orig_params.stateless_reset_token.resize(16);
- orig_params.version = 0xff000005;
- orig_params.supported_versions.push_back(0xff000005);
- orig_params.supported_versions.push_back(0xff000004);
+ 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.idle_timeout_milliseconds.set_value(kFakeIdleTimeoutMilliseconds);
+ orig_params.stateless_reset_token = kFakeStatelessResetToken;
+ 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(
+ kFakeInitialMaxStreamDataBidiLocal);
+ orig_params.initial_max_stream_data_bidi_remote.set_value(
+ kFakeInitialMaxStreamDataBidiRemote);
+ orig_params.initial_max_stream_data_uni.set_value(
+ kFakeInitialMaxStreamDataUni);
+ orig_params.initial_max_streams_bidi.set_value(kFakeInitialMaxStreamsBidi);
+ orig_params.initial_max_streams_uni.set_value(kFakeInitialMaxStreamsUni);
+ orig_params.ack_delay_exponent.set_value(kFakeAckDelayExponent);
+ orig_params.max_ack_delay.set_value(kFakeMaxAckDelay);
+ orig_params.disable_migration = kFakeDisableMigration;
+ orig_params.preferred_address = CreateFakePreferredAddress();
std::vector<uint8_t> serialized;
ASSERT_TRUE(SerializeTransportParameters(orig_params, &serialized));
@@ -74,107 +159,177 @@ TEST_F(TransportParametersTest, RoundTripServer) {
ASSERT_TRUE(ParseTransportParameters(serialized.data(), serialized.size(),
Perspective::IS_SERVER, &new_params));
- EXPECT_EQ(new_params.initial_max_stream_data,
- orig_params.initial_max_stream_data);
- EXPECT_EQ(new_params.initial_max_data, orig_params.initial_max_data);
- EXPECT_EQ(new_params.idle_timeout, orig_params.idle_timeout);
- EXPECT_EQ(new_params.stateless_reset_token,
- orig_params.stateless_reset_token);
- EXPECT_EQ(new_params.version, orig_params.version);
- ASSERT_EQ(new_params.supported_versions, orig_params.supported_versions);
+ EXPECT_EQ(Perspective::IS_SERVER, new_params.perspective);
+ EXPECT_EQ(kFakeVersionLabel, new_params.version);
+ 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(kFakeIdleTimeoutMilliseconds,
+ new_params.idle_timeout_milliseconds.value());
+ EXPECT_EQ(kFakeStatelessResetToken, 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,
+ new_params.initial_max_stream_data_bidi_local.value());
+ EXPECT_EQ(kFakeInitialMaxStreamDataBidiRemote,
+ new_params.initial_max_stream_data_bidi_remote.value());
+ EXPECT_EQ(kFakeInitialMaxStreamDataUni,
+ new_params.initial_max_stream_data_uni.value());
+ EXPECT_EQ(kFakeInitialMaxStreamsBidi,
+ new_params.initial_max_streams_bidi.value());
+ EXPECT_EQ(kFakeInitialMaxStreamsUni,
+ new_params.initial_max_streams_uni.value());
+ EXPECT_EQ(kFakeAckDelayExponent, new_params.ack_delay_exponent.value());
+ EXPECT_EQ(kFakeMaxAckDelay, new_params.max_ack_delay.value());
+ EXPECT_EQ(kFakeDisableMigration, new_params.disable_migration);
+ ASSERT_NE(nullptr, new_params.preferred_address.get());
+ EXPECT_EQ(CreateFakeV4SocketAddress(),
+ new_params.preferred_address->ipv4_socket_address);
+ EXPECT_EQ(CreateFakeV6SocketAddress(),
+ new_params.preferred_address->ipv6_socket_address);
+ EXPECT_EQ(kFakePreferredConnectionId,
+ new_params.preferred_address->connection_id);
+ EXPECT_EQ(kFakePreferredStatelessResetToken,
+ new_params.preferred_address->stateless_reset_token);
}
TEST_F(TransportParametersTest, IsValid) {
- TransportParameters empty_params;
- empty_params.perspective = Perspective::IS_CLIENT;
- EXPECT_TRUE(empty_params.is_valid());
-
{
TransportParameters params;
params.perspective = Perspective::IS_CLIENT;
- EXPECT_TRUE(params.is_valid());
- params.idle_timeout = 600;
- EXPECT_TRUE(params.is_valid());
- params.idle_timeout = 601;
- EXPECT_FALSE(params.is_valid());
+ EXPECT_TRUE(params.AreValid());
}
{
TransportParameters params;
params.perspective = Perspective::IS_CLIENT;
- EXPECT_TRUE(params.is_valid());
- params.max_packet_size.present = true;
- params.max_packet_size.value = 0;
- EXPECT_FALSE(params.is_valid());
- params.max_packet_size.value = 1200;
- EXPECT_TRUE(params.is_valid());
- params.max_packet_size.value = 65527;
- EXPECT_TRUE(params.is_valid());
- params.max_packet_size.value = 65535;
- EXPECT_FALSE(params.is_valid());
+ EXPECT_TRUE(params.AreValid());
+ params.idle_timeout_milliseconds.set_value(kFakeIdleTimeoutMilliseconds);
+ EXPECT_TRUE(params.AreValid());
+ params.idle_timeout_milliseconds.set_value(601000);
+ EXPECT_TRUE(params.AreValid());
}
{
TransportParameters params;
params.perspective = Perspective::IS_CLIENT;
- EXPECT_TRUE(params.is_valid());
- params.ack_delay_exponent.present = true;
- params.ack_delay_exponent.value = 0;
- EXPECT_TRUE(params.is_valid());
- params.ack_delay_exponent.value = 20;
- EXPECT_TRUE(params.is_valid());
- params.ack_delay_exponent.value = 21;
- EXPECT_FALSE(params.is_valid());
+ EXPECT_TRUE(params.AreValid());
+ params.max_packet_size.set_value(0);
+ EXPECT_FALSE(params.AreValid());
+ params.max_packet_size.set_value(1199);
+ EXPECT_FALSE(params.AreValid());
+ params.max_packet_size.set_value(1200);
+ EXPECT_TRUE(params.AreValid());
+ params.max_packet_size.set_value(65535);
+ EXPECT_TRUE(params.AreValid());
+ params.max_packet_size.set_value(9999999);
+ EXPECT_TRUE(params.AreValid());
+ }
+ {
+ TransportParameters params;
+ params.perspective = Perspective::IS_CLIENT;
+ EXPECT_TRUE(params.AreValid());
+ params.ack_delay_exponent.set_value(0);
+ EXPECT_TRUE(params.AreValid());
+ params.ack_delay_exponent.set_value(20);
+ EXPECT_TRUE(params.AreValid());
+ params.ack_delay_exponent.set_value(21);
+ EXPECT_FALSE(params.AreValid());
}
-}
-
-TEST_F(TransportParametersTest, NoServerParamsWithoutStatelessResetToken) {
- TransportParameters orig_params;
- orig_params.perspective = Perspective::IS_SERVER;
- orig_params.initial_max_stream_data = 12;
- orig_params.initial_max_data = 34;
- orig_params.idle_timeout = 56;
- orig_params.version = 0xff000005;
- orig_params.supported_versions.push_back(0xff000005);
- orig_params.supported_versions.push_back(0xff000004);
-
- std::vector<uint8_t> out;
- ASSERT_FALSE(SerializeTransportParameters(orig_params, &out));
}
TEST_F(TransportParametersTest, NoClientParamsWithStatelessResetToken) {
TransportParameters orig_params;
orig_params.perspective = Perspective::IS_CLIENT;
- orig_params.initial_max_stream_data = 12;
- orig_params.initial_max_data = 34;
- orig_params.idle_timeout = 56;
- orig_params.stateless_reset_token.resize(16);
- orig_params.version = 0xff000005;
+ orig_params.version = kFakeVersionLabel;
+ orig_params.idle_timeout_milliseconds.set_value(kFakeIdleTimeoutMilliseconds);
+ orig_params.stateless_reset_token = kFakeStatelessResetToken;
+ orig_params.max_packet_size.set_value(kFakeMaxPacketSize);
std::vector<uint8_t> out;
- ASSERT_FALSE(SerializeTransportParameters(orig_params, &out));
+ EXPECT_FALSE(SerializeTransportParameters(orig_params, &out));
}
TEST_F(TransportParametersTest, ParseClientParams) {
+ // clang-format off
const uint8_t kClientParams[] = {
- 0xff, 0x00, 0x00, 0x05, // initial version
- 0x00, 0x16, // length parameters array that follows
- // initial_max_stream_data
- 0x00, 0x00, // parameter id
- 0x00, 0x04, // length
- 0x00, 0x00, 0x00, 0x0c, // value
- // initial_max_data
- 0x00, 0x01, // parameter id
- 0x00, 0x04, // length
- 0x00, 0x00, 0x00, 0x22, // value
+ 0x00, 0x44, // length of the parameters array that follows
// idle_timeout
+ 0x00, 0x01, // parameter id
+ 0x00, 0x02, // length
+ 0x6e, 0xec, // value
+ // max_packet_size
0x00, 0x03, // parameter id
0x00, 0x02, // length
- 0x00, 0x38, // value
+ 0x63, 0x29, // value
+ // initial_max_data
+ 0x00, 0x04, // parameter id
+ 0x00, 0x02, // length
+ 0x40, 0x65, // value
+ // initial_max_stream_data_bidi_local
+ 0x00, 0x05, // parameter id
+ 0x00, 0x02, // length
+ 0x47, 0xD1, // value
+ // initial_max_stream_data_bidi_remote
+ 0x00, 0x06, // parameter id
+ 0x00, 0x02, // length
+ 0x47, 0xD2, // value
+ // initial_max_stream_data_uni
+ 0x00, 0x07, // parameter id
+ 0x00, 0x02, // length
+ 0x4B, 0xB8, // value
+ // initial_max_streams_bidi
+ 0x00, 0x08, // parameter id
+ 0x00, 0x01, // length
+ 0x15, // value
+ // initial_max_streams_uni
+ 0x00, 0x09, // parameter id
+ 0x00, 0x01, // length
+ 0x16, // value
+ // ack_delay_exponent
+ 0x00, 0x0a, // parameter id
+ 0x00, 0x01, // length
+ 0x0a, // value
+ // max_ack_delay
+ 0x00, 0x0b, // parameter id
+ 0x00, 0x01, // length
+ 0x33, // value
+ // disable_migration
+ 0x00, 0x0c, // parameter id
+ 0x00, 0x00, // length
+ // Google version extension
+ 0x47, 0x52, // parameter id
+ 0x00, 0x04, // length
+ 0x01, 0x23, 0x45, 0x67, // initial version
};
+ // clang-format on
- TransportParameters out_params;
+ TransportParameters new_params;
ASSERT_TRUE(ParseTransportParameters(kClientParams,
QUIC_ARRAYSIZE(kClientParams),
- Perspective::IS_CLIENT, &out_params));
+ Perspective::IS_CLIENT, &new_params));
+
+ EXPECT_EQ(Perspective::IS_CLIENT, new_params.perspective);
+ EXPECT_EQ(kFakeVersionLabel, new_params.version);
+ EXPECT_TRUE(new_params.supported_versions.empty());
+ EXPECT_EQ(EmptyQuicConnectionId(), new_params.original_connection_id);
+ EXPECT_EQ(kFakeIdleTimeoutMilliseconds,
+ new_params.idle_timeout_milliseconds.value());
+ EXPECT_TRUE(new_params.stateless_reset_token.empty());
+ EXPECT_EQ(kFakeMaxPacketSize, new_params.max_packet_size.value());
+ EXPECT_EQ(kFakeInitialMaxData, new_params.initial_max_data.value());
+ EXPECT_EQ(kFakeInitialMaxStreamDataBidiLocal,
+ new_params.initial_max_stream_data_bidi_local.value());
+ EXPECT_EQ(kFakeInitialMaxStreamDataBidiRemote,
+ new_params.initial_max_stream_data_bidi_remote.value());
+ EXPECT_EQ(kFakeInitialMaxStreamDataUni,
+ new_params.initial_max_stream_data_uni.value());
+ EXPECT_EQ(kFakeInitialMaxStreamsBidi,
+ new_params.initial_max_streams_bidi.value());
+ EXPECT_EQ(kFakeInitialMaxStreamsUni,
+ new_params.initial_max_streams_uni.value());
+ EXPECT_EQ(kFakeAckDelayExponent, new_params.ack_delay_exponent.value());
+ EXPECT_EQ(kFakeMaxAckDelay, new_params.max_ack_delay.value());
+ EXPECT_EQ(kFakeDisableMigration, new_params.disable_migration);
}
TEST_F(TransportParametersTest, ParseClientParamsFailsWithStatelessResetToken) {
@@ -182,234 +337,237 @@ TEST_F(TransportParametersTest, ParseClientParamsFailsWithStatelessResetToken) {
// clang-format off
const uint8_t kClientParamsWithFullToken[] = {
- 0xff, 0x00, 0x00, 0x05, // initial version
- 0x00, 0x2a, // length parameters array that follows
- // initial_max_stream_data
- 0x00, 0x00, // parameter id
- 0x00, 0x04, // length
- 0x00, 0x00, 0x00, 0x0c, // value
- // initial_max_data
- 0x00, 0x01, // parameter id
- 0x00, 0x04, // length
- 0x00, 0x00, 0x00, 0x22, // value
+ 0x00, 0x26, // length parameters array that follows
// idle_timeout
- 0x00, 0x03, // parameter id
+ 0x00, 0x01, // parameter id
0x00, 0x02, // length
- 0x00, 0x38, // value
+ 0x6e, 0xec, // value
// stateless_reset_token
- 0x00, 0x06, // parameter id
- 0x00, 0x10, // length
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x00, 0x02,
+ 0x00, 0x10,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
+ // max_packet_size
+ 0x00, 0x03, // parameter id
+ 0x00, 0x02, // length
+ 0x63, 0x29, // value
+ // initial_max_data
+ 0x00, 0x04, // parameter id
+ 0x00, 0x02, // length
+ 0x40, 0x65, // value
};
// clang-format on
- ASSERT_FALSE(ParseTransportParameters(
+ EXPECT_FALSE(ParseTransportParameters(
kClientParamsWithFullToken, QUIC_ARRAYSIZE(kClientParamsWithFullToken),
Perspective::IS_CLIENT, &out_params));
+ // clang-format off
const uint8_t kClientParamsWithEmptyToken[] = {
- 0xff, 0x00, 0x00, 0x05, // initial version
- 0x00, 0x1a, // length parameters array that follows
- // initial_max_stream_data
- 0x00, 0x00, // parameter id
- 0x00, 0x04, // length
- 0x00, 0x00, 0x00, 0x0c, // value
- // initial_max_data
- 0x00, 0x01, // parameter id
- 0x00, 0x04, // length
- 0x00, 0x00, 0x00, 0x22, // value
+ 0x00, 0x16, // length parameters array that follows
// idle_timeout
- 0x00, 0x03, // parameter id
+ 0x00, 0x01, // parameter id
0x00, 0x02, // length
- 0x00, 0x38, // value
+ 0x6e, 0xec, // value
// stateless_reset_token
- 0x00, 0x06, // parameter id
- 0x00, 0x00, // length
+ 0x00, 0x02,
+ 0x00, 0x00,
+ // max_packet_size
+ 0x00, 0x03, // parameter id
+ 0x00, 0x02, // length
+ 0x63, 0x29, // value
+ // initial_max_data
+ 0x00, 0x04, // parameter id
+ 0x00, 0x02, // length
+ 0x40, 0x65, // value
};
+ // clang-format on
- ASSERT_FALSE(ParseTransportParameters(
+ EXPECT_FALSE(ParseTransportParameters(
kClientParamsWithEmptyToken, QUIC_ARRAYSIZE(kClientParamsWithEmptyToken),
Perspective::IS_CLIENT, &out_params));
}
-TEST_F(TransportParametersTest, ParseClientParametersWithInvalidParams) {
- TransportParameters out_params;
-
+TEST_F(TransportParametersTest, ParseClientParametersRepeated) {
+ // clang-format off
const uint8_t kClientParamsRepeated[] = {
- 0xff, 0x00, 0x00, 0x05, // initial version
- 0x00, 0x1c, // length parameters array that follows
- // initial_max_stream_data
- 0x00, 0x00, // parameter id
- 0x00, 0x04, // length
- 0x00, 0x00, 0x00, 0x0c, // value
- // initial_max_data
- 0x00, 0x01, // parameter id
- 0x00, 0x04, // length
- 0x00, 0x00, 0x00, 0x22, // value
+ 0x00, 0x16, // length parameters array that follows
// idle_timeout
- 0x00, 0x03, // parameter id
+ 0x00, 0x01, // parameter id
0x00, 0x02, // length
- 0x00, 0x38, // value
- // idle_timeout (repeat)
+ 0x6e, 0xec, // value
+ // stateless_reset_token
+ 0x00, 0x02,
+ 0x00, 0x00,
+ // max_packet_size
0x00, 0x03, // parameter id
0x00, 0x02, // length
- 0x00, 0x38, // value
+ 0x63, 0x29, // value
+ // idle_timeout (repeated)
+ 0x00, 0x01, // parameter id
+ 0x00, 0x02, // length
+ 0x6e, 0xec, // value
};
- ASSERT_FALSE(ParseTransportParameters(kClientParamsRepeated,
+ // clang-format on
+ TransportParameters out_params;
+ EXPECT_FALSE(ParseTransportParameters(kClientParamsRepeated,
QUIC_ARRAYSIZE(kClientParamsRepeated),
Perspective::IS_CLIENT, &out_params));
-
- const uint8_t kClientParamsMissing[] = {
- 0xff, 0x00, 0x00, 0x05, // initial version
- 0x00, 0x10, // length parameters array that follows
- // initial_max_stream_data
- 0x00, 0x00, // parameter id
- 0x00, 0x04, // length
- 0x00, 0x00, 0x00, 0x0c, // value
- // initial_max_data
- 0x00, 0x01, // parameter id
- 0x00, 0x04, // length
- 0x00, 0x00, 0x00, 0x22, // value
- };
- ASSERT_FALSE(ParseTransportParameters(kClientParamsMissing,
- QUIC_ARRAYSIZE(kClientParamsMissing),
- Perspective::IS_CLIENT, &out_params));
}
TEST_F(TransportParametersTest, ParseServerParams) {
// clang-format off
const uint8_t kServerParams[] = {
- 0xff, 0x00, 0x00, 0x05, // negotiated_version
- 0x08, // length of supported versions array
- 0xff, 0x00, 0x00, 0x05,
- 0xff, 0x00, 0x00, 0x04,
- 0x00, 0x2a, // length of parameters array that follows
- // initial_max_stream_data
- 0x00, 0x00,
- 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x0c,
- // initial_max_data
- 0x00, 0x01,
- 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x22,
+ 0x00, 0xa2, // length of parameters array that follows
+ // original_connection_id
+ 0x00, 0x00, // parameter id
+ 0x00, 0x08, // length
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x37,
// idle_timeout
- 0x00, 0x03,
- 0x00, 0x02,
- 0x00, 0x38,
+ 0x00, 0x01, // parameter id
+ 0x00, 0x02, // length
+ 0x6e, 0xec, // value
// stateless_reset_token
- 0x00, 0x06,
+ 0x00, 0x02,
0x00, 0x10,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
+ // max_packet_size
+ 0x00, 0x03, // parameter id
+ 0x00, 0x02, // length
+ 0x63, 0x29, // value
+ // initial_max_data
+ 0x00, 0x04, // parameter id
+ 0x00, 0x02, // length
+ 0x40, 0x65, // value
+ // initial_max_stream_data_bidi_local
+ 0x00, 0x05, // parameter id
+ 0x00, 0x02, // length
+ 0x47, 0xD1, // value
+ // initial_max_stream_data_bidi_remote
+ 0x00, 0x06, // parameter id
+ 0x00, 0x02, // length
+ 0x47, 0xD2, // value
+ // initial_max_stream_data_uni
+ 0x00, 0x07, // parameter id
+ 0x00, 0x02, // length
+ 0x4B, 0xB8, // value
+ // initial_max_streams_bidi
+ 0x00, 0x08, // parameter id
+ 0x00, 0x01, // length
+ 0x15, // value
+ // initial_max_streams_uni
+ 0x00, 0x09, // parameter id
+ 0x00, 0x01, // length
+ 0x16, // value
+ // ack_delay_exponent
+ 0x00, 0x0a, // parameter id
+ 0x00, 0x01, // length
+ 0x0a, // value
+ // max_ack_delay
+ 0x00, 0x0b, // parameter id
+ 0x00, 0x01, // length
+ 0x33, // value
+ // disable_migration
+ 0x00, 0x0c, // parameter id
+ 0x00, 0x00, // length
+ // preferred_address
+ 0x00, 0x0d, // parameter id
+ 0x00, 0x31, // length
+ 0x41, 0x42, 0x43, 0x44, // IPv4 address
+ 0x48, 0x84, // IPv4 port
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, // IPv6 address
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x63, 0x36, // IPv6 port
+ 0x08, // connection ID length
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF, // connection ID
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, // stateless reset token
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
+ // Google version extension
+ 0x47, 0x52, // parameter id
+ 0x00, 0x0d, // length
+ 0x01, 0x23, 0x45, 0x67, // negotiated_version
+ 0x08, // length of supported versions array
+ 0x01, 0x23, 0x45, 0x67,
+ 0x89, 0xab, 0xcd, 0xef,
};
// clang-format on
- TransportParameters out_params;
+ TransportParameters new_params;
ASSERT_TRUE(ParseTransportParameters(kServerParams,
QUIC_ARRAYSIZE(kServerParams),
- Perspective::IS_SERVER, &out_params));
-}
-
-TEST_F(TransportParametersTest, ParseServerParamsWithoutToken) {
- // clang-format off
- const uint8_t kServerParams[] = {
- 0xff, 0x00, 0x00, 0x05, // negotiated_version
- 0x08, // length of supported versions array
- 0xff, 0x00, 0x00, 0x05,
- 0xff, 0x00, 0x00, 0x04,
- 0x00, 0x16, // length of parameters array that follows
- // initial_max_stream_data
- 0x00, 0x00,
- 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x0c,
- // initial_max_data
- 0x00, 0x01,
- 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x22,
- // idle_timeout
- 0x00, 0x03,
- 0x00, 0x02,
- 0x00, 0x38,
- };
- // clang-format on
+ Perspective::IS_SERVER, &new_params));
- TransportParameters out_params;
- ASSERT_FALSE(ParseTransportParameters(kServerParams,
- QUIC_ARRAYSIZE(kServerParams),
- Perspective::IS_SERVER, &out_params));
+ EXPECT_EQ(Perspective::IS_SERVER, new_params.perspective);
+ EXPECT_EQ(kFakeVersionLabel, new_params.version);
+ 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(kFakeIdleTimeoutMilliseconds,
+ new_params.idle_timeout_milliseconds.value());
+ EXPECT_EQ(kFakeStatelessResetToken, 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,
+ new_params.initial_max_stream_data_bidi_local.value());
+ EXPECT_EQ(kFakeInitialMaxStreamDataBidiRemote,
+ new_params.initial_max_stream_data_bidi_remote.value());
+ EXPECT_EQ(kFakeInitialMaxStreamDataUni,
+ new_params.initial_max_stream_data_uni.value());
+ EXPECT_EQ(kFakeInitialMaxStreamsBidi,
+ new_params.initial_max_streams_bidi.value());
+ EXPECT_EQ(kFakeInitialMaxStreamsUni,
+ new_params.initial_max_streams_uni.value());
+ EXPECT_EQ(kFakeAckDelayExponent, new_params.ack_delay_exponent.value());
+ EXPECT_EQ(kFakeMaxAckDelay, new_params.max_ack_delay.value());
+ EXPECT_EQ(kFakeDisableMigration, new_params.disable_migration);
+ ASSERT_NE(nullptr, new_params.preferred_address.get());
+ EXPECT_EQ(CreateFakeV4SocketAddress(),
+ new_params.preferred_address->ipv4_socket_address);
+ EXPECT_EQ(CreateFakeV6SocketAddress(),
+ new_params.preferred_address->ipv6_socket_address);
+ EXPECT_EQ(kFakePreferredConnectionId,
+ new_params.preferred_address->connection_id);
+ EXPECT_EQ(kFakePreferredStatelessResetToken,
+ new_params.preferred_address->stateless_reset_token);
}
-TEST_F(TransportParametersTest, ParseServerParametersWithInvalidParams) {
- TransportParameters out_params;
-
+TEST_F(TransportParametersTest, ParseServerParametersRepeated) {
// clang-format off
const uint8_t kServerParamsRepeated[] = {
- 0xff, 0x00, 0x00, 0x05, // negotiated_version
- 0x08, // length of supported versions array
- 0xff, 0x00, 0x00, 0x05,
- 0xff, 0x00, 0x00, 0x04,
- 0x00, 0x30, // length of parameters array that follows
- // initial_max_stream_data
- 0x00, 0x00,
- 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x0c,
- // initial_max_data
- 0x00, 0x01,
- 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x22,
+ 0x00, 0x2c, // length of parameters array that follows
+ // original_connection_id
+ 0x00, 0x00, // parameter id
+ 0x00, 0x08, // length
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x37,
// idle_timeout
- 0x00, 0x03,
- 0x00, 0x02,
- 0x00, 0x38,
- // idle_timeout (repeat)
- 0x00, 0x03,
- 0x00, 0x02,
- 0x00, 0x38,
+ 0x00, 0x01, // parameter id
+ 0x00, 0x02, // length
+ 0x6e, 0xec, // value
// stateless_reset_token
- 0x00, 0x06,
+ 0x00, 0x02,
0x00, 0x10,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+ // idle_timeout (repeated)
+ 0x00, 0x01, // parameter id
+ 0x00, 0x02, // length
+ 0x6e, 0xec, // value
};
// clang-format on
- ASSERT_FALSE(ParseTransportParameters(kServerParamsRepeated,
- QUIC_ARRAYSIZE(kServerParamsRepeated),
- Perspective::IS_SERVER, &out_params));
- // clang-format off
- const uint8_t kServerParamsMissing[] = {
- 0xff, 0x00, 0x00, 0x05, // negotiated_version
- 0x08, // length of supported versions array
- 0xff, 0x00, 0x00, 0x05,
- 0xff, 0x00, 0x00, 0x04,
- 0x00, 0x24, // length of parameters array that follows
- // initial_max_stream_data
- 0x00, 0x00,
- 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x0c,
- // initial_max_data
- 0x00, 0x01,
- 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x22,
- // stateless_reset_token
- 0x00, 0x06,
- 0x00, 0x10,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- };
- // clang-format on
- ASSERT_FALSE(ParseTransportParameters(kServerParamsMissing,
- QUIC_ARRAYSIZE(kServerParamsMissing),
+ TransportParameters out_params;
+ EXPECT_FALSE(ParseTransportParameters(kServerParamsRepeated,
+ QUIC_ARRAYSIZE(kServerParamsRepeated),
Perspective::IS_SERVER, &out_params));
}
TEST_F(TransportParametersTest, CryptoHandshakeMessageRoundtrip) {
TransportParameters orig_params;
orig_params.perspective = Perspective::IS_CLIENT;
- orig_params.initial_max_stream_data = 12;
- orig_params.initial_max_data = 34;
- orig_params.idle_timeout = 56;
+ orig_params.version = kFakeVersionLabel;
+ orig_params.max_packet_size.set_value(kFakeMaxPacketSize);
orig_params.google_quic_params = QuicMakeUnique<CryptoHandshakeMessage>();
const std::string kTestString = "test string";
@@ -434,6 +592,8 @@ TEST_F(TransportParametersTest, CryptoHandshakeMessageRoundtrip) {
EXPECT_EQ(new_params.google_quic_params->GetUint32(1337, &test_value),
QUIC_NO_ERROR);
EXPECT_EQ(test_value, kTestValue);
+ EXPECT_EQ(kFakeVersionLabel, new_params.version);
+ EXPECT_EQ(kFakeMaxPacketSize, new_params.max_packet_size.value());
}
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.cc
index baffa9d941b..3587ebd063f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.cc
@@ -4,6 +4,8 @@
#include "net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.h"
+#include <memory>
+
namespace quic {
QuicConnectionCloseFrame::QuicConnectionCloseFrame()
@@ -48,11 +50,13 @@ std::ostream& operator<<(
<< ", error_code: "
<< ((connection_close_frame.close_type ==
IETF_QUIC_TRANSPORT_CONNECTION_CLOSE)
- ? connection_close_frame.transport_error_code
+ ? static_cast<uint16_t>(
+ connection_close_frame.transport_error_code)
: ((connection_close_frame.close_type ==
IETF_QUIC_APPLICATION_CONNECTION_CLOSE)
? connection_close_frame.application_error_code
- : connection_close_frame.quic_error_code))
+ : static_cast<uint16_t>(
+ connection_close_frame.quic_error_code)))
<< ", extracted_error_code: "
<< connection_close_frame.extracted_error_code << ", error_details: '"
<< connection_close_frame.error_details
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 95fee41f6bf..0f3e7344cc2 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
@@ -51,10 +51,10 @@ QuicFrame::QuicFrame(QuicNewConnectionIdFrame* frame)
QuicFrame::QuicFrame(QuicRetireConnectionIdFrame* frame)
: type(RETIRE_CONNECTION_ID_FRAME), retire_connection_id_frame(frame) {}
-QuicFrame::QuicFrame(QuicMaxStreamIdFrame frame) : max_stream_id_frame(frame) {}
+QuicFrame::QuicFrame(QuicMaxStreamsFrame frame) : max_streams_frame(frame) {}
-QuicFrame::QuicFrame(QuicStreamIdBlockedFrame frame)
- : stream_id_blocked_frame(frame) {}
+QuicFrame::QuicFrame(QuicStreamsBlockedFrame frame)
+ : streams_blocked_frame(frame) {}
QuicFrame::QuicFrame(QuicPathResponseFrame* frame)
: type(PATH_RESPONSE_FRAME), path_response_frame(frame) {}
@@ -84,9 +84,9 @@ void DeleteFrame(QuicFrame* frame) {
case PADDING_FRAME:
case MTU_DISCOVERY_FRAME:
case PING_FRAME:
- case MAX_STREAM_ID_FRAME:
+ case MAX_STREAMS_FRAME:
case STOP_WAITING_FRAME:
- case STREAM_ID_BLOCKED_FRAME:
+ case STREAMS_BLOCKED_FRAME:
case STREAM_FRAME:
break;
case ACK_FRAME:
@@ -154,8 +154,8 @@ bool IsControlFrame(QuicFrameType type) {
case GOAWAY_FRAME:
case WINDOW_UPDATE_FRAME:
case BLOCKED_FRAME:
- case STREAM_ID_BLOCKED_FRAME:
- case MAX_STREAM_ID_FRAME:
+ case STREAMS_BLOCKED_FRAME:
+ case MAX_STREAMS_FRAME:
case PING_FRAME:
case STOP_SENDING_FRAME:
return true;
@@ -174,10 +174,10 @@ QuicControlFrameId GetControlFrameId(const QuicFrame& frame) {
return frame.window_update_frame->control_frame_id;
case BLOCKED_FRAME:
return frame.blocked_frame->control_frame_id;
- case STREAM_ID_BLOCKED_FRAME:
- return frame.stream_id_blocked_frame.control_frame_id;
- case MAX_STREAM_ID_FRAME:
- return frame.max_stream_id_frame.control_frame_id;
+ case STREAMS_BLOCKED_FRAME:
+ return frame.streams_blocked_frame.control_frame_id;
+ case MAX_STREAMS_FRAME:
+ return frame.max_streams_frame.control_frame_id;
case PING_FRAME:
return frame.ping_frame.control_frame_id;
case STOP_SENDING_FRAME:
@@ -204,11 +204,11 @@ void SetControlFrameId(QuicControlFrameId control_frame_id, QuicFrame* frame) {
case PING_FRAME:
frame->ping_frame.control_frame_id = control_frame_id;
return;
- case STREAM_ID_BLOCKED_FRAME:
- frame->stream_id_blocked_frame.control_frame_id = control_frame_id;
+ case STREAMS_BLOCKED_FRAME:
+ frame->streams_blocked_frame.control_frame_id = control_frame_id;
return;
- case MAX_STREAM_ID_FRAME:
- frame->max_stream_id_frame.control_frame_id = control_frame_id;
+ case MAX_STREAMS_FRAME:
+ frame->max_streams_frame.control_frame_id = control_frame_id;
return;
case STOP_SENDING_FRAME:
frame->stop_sending_frame->control_frame_id = control_frame_id;
@@ -240,11 +240,11 @@ QuicFrame CopyRetransmittableControlFrame(const QuicFrame& frame) {
case STOP_SENDING_FRAME:
copy = QuicFrame(new QuicStopSendingFrame(*frame.stop_sending_frame));
break;
- case STREAM_ID_BLOCKED_FRAME:
- copy = QuicFrame(QuicStreamIdBlockedFrame(frame.stream_id_blocked_frame));
+ case STREAMS_BLOCKED_FRAME:
+ copy = QuicFrame(QuicStreamsBlockedFrame(frame.streams_blocked_frame));
break;
- case MAX_STREAM_ID_FRAME:
- copy = QuicFrame(QuicMaxStreamIdFrame(frame.max_stream_id_frame));
+ case MAX_STREAMS_FRAME:
+ copy = QuicFrame(QuicMaxStreamsFrame(frame.max_streams_frame));
break;
default:
QUIC_BUG << "Try to copy a non-retransmittable control frame: " << frame;
@@ -297,6 +297,10 @@ std::ostream& operator<<(std::ostream& os, const QuicFrame& frame) {
os << "type { PING_FRAME } " << frame.ping_frame;
break;
}
+ case CRYPTO_FRAME: {
+ os << "type { CRYPTO_FRAME } " << frame.crypto_frame;
+ break;
+ }
case MTU_DISCOVERY_FRAME: {
os << "type { MTU_DISCOVERY_FRAME } ";
break;
@@ -308,11 +312,11 @@ std::ostream& operator<<(std::ostream& os, const QuicFrame& frame) {
os << "type { RETIRE_CONNECTION_ID } "
<< *(frame.retire_connection_id_frame);
break;
- case MAX_STREAM_ID_FRAME:
- os << "type { MAX_STREAM_ID } " << frame.max_stream_id_frame;
+ case MAX_STREAMS_FRAME:
+ os << "type { MAX_STREAMS } " << frame.max_streams_frame;
break;
- case STREAM_ID_BLOCKED_FRAME:
- os << "type { STREAM_ID_BLOCKED } " << frame.stream_id_blocked_frame;
+ case STREAMS_BLOCKED_FRAME:
+ os << "type { STREAMS_BLOCKED } " << frame.streams_blocked_frame;
break;
case PATH_RESPONSE_FRAME:
os << "type { PATH_RESPONSE } " << *(frame.path_response_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 c452bf41303..caa5fcecf36 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.h
@@ -13,7 +13,7 @@
#include "net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_crypto_frame.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_goaway_frame.h"
-#include "net/third_party/quiche/src/quic/core/frames/quic_max_stream_id_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_max_streams_frame.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_message_frame.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_mtu_discovery_frame.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_new_connection_id_frame.h"
@@ -27,7 +27,7 @@
#include "net/third_party/quiche/src/quic/core/frames/quic_stop_sending_frame.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_stop_waiting_frame.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h"
-#include "net/third_party/quiche/src/quic/core/frames/quic_stream_id_blocked_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_streams_blocked_frame.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
@@ -41,9 +41,9 @@ struct QUIC_EXPORT_PRIVATE QuicFrame {
explicit QuicFrame(QuicPaddingFrame padding_frame);
explicit QuicFrame(QuicMtuDiscoveryFrame frame);
explicit QuicFrame(QuicPingFrame frame);
- explicit QuicFrame(QuicMaxStreamIdFrame frame);
+ explicit QuicFrame(QuicMaxStreamsFrame frame);
explicit QuicFrame(QuicStopWaitingFrame frame);
- explicit QuicFrame(QuicStreamIdBlockedFrame frame);
+ explicit QuicFrame(QuicStreamsBlockedFrame frame);
explicit QuicFrame(QuicStreamFrame stream_frame);
explicit QuicFrame(QuicAckFrame* frame);
@@ -72,9 +72,9 @@ struct QUIC_EXPORT_PRIVATE QuicFrame {
QuicPaddingFrame padding_frame;
QuicMtuDiscoveryFrame mtu_discovery_frame;
QuicPingFrame ping_frame;
- QuicMaxStreamIdFrame max_stream_id_frame;
+ QuicMaxStreamsFrame max_streams_frame;
QuicStopWaitingFrame stop_waiting_frame;
- QuicStreamIdBlockedFrame stream_id_blocked_frame;
+ QuicStreamsBlockedFrame streams_blocked_frame;
QuicStreamFrame stream_frame;
// Out of line 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 c432657a442..bf60b7b8917 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
@@ -101,33 +101,37 @@ TEST_F(QuicFramesTest, StopSendingFrameToString) {
EXPECT_TRUE(IsControlFrame(frame.type));
}
-TEST_F(QuicFramesTest, StreamIdBlockedFrameToString) {
- QuicStreamIdBlockedFrame stream_id_blocked;
- QuicFrame frame(stream_id_blocked);
+TEST_F(QuicFramesTest, StreamsBlockedFrameToString) {
+ QuicStreamsBlockedFrame streams_blocked;
+ QuicFrame frame(streams_blocked);
SetControlFrameId(1, &frame);
EXPECT_EQ(1u, GetControlFrameId(frame));
- // QuicStreamIdBlocked is copied into a QuicFrame (as opposed to putting a
+ // QuicStreamsBlocked is copied into a QuicFrame (as opposed to putting a
// pointer to it into QuicFrame) so need to work with the copy in |frame| and
- // not the original one, stream_id_blocked.
- frame.stream_id_blocked_frame.stream_id = 321;
+ // not the original one, streams_blocked.
+ frame.streams_blocked_frame.stream_count = 321;
+ frame.streams_blocked_frame.unidirectional = false;
std::ostringstream stream;
- stream << frame.stream_id_blocked_frame;
- EXPECT_EQ("{ control_frame_id: 1, stream id: 321 }\n", stream.str());
+ stream << frame.streams_blocked_frame;
+ EXPECT_EQ("{ control_frame_id: 1, stream count: 321, bidirectional }\n",
+ stream.str());
EXPECT_TRUE(IsControlFrame(frame.type));
}
-TEST_F(QuicFramesTest, MaxStreamIdFrameToString) {
- QuicMaxStreamIdFrame max_stream_id;
- QuicFrame frame(max_stream_id);
+TEST_F(QuicFramesTest, MaxStreamsFrameToString) {
+ QuicMaxStreamsFrame max_streams;
+ QuicFrame frame(max_streams);
SetControlFrameId(1, &frame);
EXPECT_EQ(1u, GetControlFrameId(frame));
- // QuicMaxStreamId is copied into a QuicFrame (as opposed to putting a
+ // QuicMaxStreams is copied into a QuicFrame (as opposed to putting a
// pointer to it into QuicFrame) so need to work with the copy in |frame| and
- // not the original one, max_stream_id.
- frame.max_stream_id_frame.max_stream_id = 321;
+ // not the original one, max_streams.
+ frame.max_streams_frame.stream_count = 321;
+ frame.max_streams_frame.unidirectional = true;
std::ostringstream stream;
- stream << frame.max_stream_id_frame;
- EXPECT_EQ("{ control_frame_id: 1, stream_id: 321 }\n", stream.str());
+ stream << frame.max_streams_frame;
+ EXPECT_EQ("{ control_frame_id: 1, stream_count: 321, unidirectional }\n",
+ stream.str());
EXPECT_TRUE(IsControlFrame(frame.type));
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_max_stream_id_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_max_stream_id_frame.cc
deleted file mode 100644
index 19270e8e23e..00000000000
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_max_stream_id_frame.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/third_party/quiche/src/quic/core/frames/quic_max_stream_id_frame.h"
-
-namespace quic {
-
-QuicMaxStreamIdFrame::QuicMaxStreamIdFrame()
- : QuicInlinedFrame(MAX_STREAM_ID_FRAME),
- control_frame_id(kInvalidControlFrameId) {}
-
-QuicMaxStreamIdFrame::QuicMaxStreamIdFrame(QuicControlFrameId control_frame_id,
- QuicStreamId max_stream_id)
- : QuicInlinedFrame(MAX_STREAM_ID_FRAME),
- control_frame_id(control_frame_id),
- max_stream_id(max_stream_id) {}
-
-std::ostream& operator<<(std::ostream& os, const QuicMaxStreamIdFrame& frame) {
- os << "{ control_frame_id: " << frame.control_frame_id
- << ", stream_id: " << frame.max_stream_id << " }\n";
- return os;
-}
-
-} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_max_stream_id_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_max_stream_id_frame.h
deleted file mode 100644
index 6177687d44e..00000000000
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_max_stream_id_frame.h
+++ /dev/null
@@ -1,40 +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_FRAMES_QUIC_MAX_STREAM_ID_FRAME_H_
-#define QUICHE_QUIC_CORE_FRAMES_QUIC_MAX_STREAM_ID_FRAME_H_
-
-#include <ostream>
-
-#include "net/third_party/quiche/src/quic/core/frames/quic_inlined_frame.h"
-#include "net/third_party/quiche/src/quic/core/quic_constants.h"
-#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-
-namespace quic {
-
-// IETF format MAX_STREAM_ID frame.
-// This frame is used by the sender to inform the peer of the largest
-// stream id that the peer may open and that the sender will accept.
-struct QUIC_EXPORT_PRIVATE QuicMaxStreamIdFrame
- : public QuicInlinedFrame<QuicMaxStreamIdFrame> {
- QuicMaxStreamIdFrame();
- QuicMaxStreamIdFrame(QuicControlFrameId control_frame_id,
- QuicStreamId max_stream_id);
-
- friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
- std::ostream& os,
- const QuicMaxStreamIdFrame& frame);
-
- // A unique identifier of this control frame. 0 when this frame is received,
- // and non-zero when sent.
- QuicControlFrameId control_frame_id;
-
- // The maximum stream id to support.
- QuicStreamId max_stream_id;
-};
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_MAX_STREAM_ID_FRAME_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_max_streams_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_max_streams_frame.cc
new file mode 100644
index 00000000000..21dce5bf706
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_max_streams_frame.cc
@@ -0,0 +1,30 @@
+// 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/frames/quic_max_streams_frame.h"
+
+namespace quic {
+
+QuicMaxStreamsFrame::QuicMaxStreamsFrame()
+ : QuicInlinedFrame(MAX_STREAMS_FRAME),
+ control_frame_id(kInvalidControlFrameId),
+ unidirectional(false) {}
+
+QuicMaxStreamsFrame::QuicMaxStreamsFrame(QuicControlFrameId control_frame_id,
+ QuicStreamCount stream_count,
+ bool unidirectional)
+ : QuicInlinedFrame(MAX_STREAMS_FRAME),
+ control_frame_id(control_frame_id),
+ stream_count(stream_count),
+ unidirectional(unidirectional) {}
+
+std::ostream& operator<<(std::ostream& os, const QuicMaxStreamsFrame& frame) {
+ os << "{ control_frame_id: " << frame.control_frame_id
+ << ", stream_count: " << frame.stream_count
+ << ((frame.unidirectional) ? ", unidirectional }\n"
+ : ", bidirectional }\n");
+ return os;
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_max_streams_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_max_streams_frame.h
new file mode 100644
index 00000000000..f8c78f9afd4
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_max_streams_frame.h
@@ -0,0 +1,43 @@
+// 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_FRAMES_QUIC_MAX_STREAMS_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_MAX_STREAMS_FRAME_H_
+
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/frames/quic_inlined_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+
+namespace quic {
+
+// IETF format MAX_STREAMS frame.
+// This frame is used by the sender to inform the peer of the number of
+// streams that the peer may open and that the sender will accept.
+struct QUIC_EXPORT_PRIVATE QuicMaxStreamsFrame
+ : public QuicInlinedFrame<QuicMaxStreamsFrame> {
+ QuicMaxStreamsFrame();
+ QuicMaxStreamsFrame(QuicControlFrameId control_frame_id,
+ QuicStreamCount stream_count,
+ bool unidirectional);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicMaxStreamsFrame& frame);
+
+ // A unique identifier of this control frame. 0 when this frame is received,
+ // and non-zero when sent.
+ QuicControlFrameId control_frame_id;
+
+ // The number of streams that may be opened.
+ QuicStreamCount stream_count;
+ // Whether uni- or bi-directional streams
+ bool unidirectional;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_MAX_STREAMS_FRAME_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_id_blocked_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_id_blocked_frame.cc
deleted file mode 100644
index 627ad2a93ce..00000000000
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_id_blocked_frame.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/third_party/quiche/src/quic/core/frames/quic_stream_id_blocked_frame.h"
-
-namespace quic {
-
-QuicStreamIdBlockedFrame::QuicStreamIdBlockedFrame()
- : QuicInlinedFrame(STREAM_ID_BLOCKED_FRAME),
- control_frame_id(kInvalidControlFrameId) {}
-
-QuicStreamIdBlockedFrame::QuicStreamIdBlockedFrame(
- QuicControlFrameId control_frame_id,
- QuicStreamId stream_id)
- : QuicInlinedFrame(STREAM_ID_BLOCKED_FRAME),
- control_frame_id(control_frame_id),
- stream_id(stream_id) {}
-
-std::ostream& operator<<(std::ostream& os,
- const QuicStreamIdBlockedFrame& frame) {
- os << "{ control_frame_id: " << frame.control_frame_id
- << ", stream id: " << frame.stream_id << " }\n";
- return os;
-}
-
-} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_id_blocked_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_id_blocked_frame.h
deleted file mode 100644
index f9ccca2d8b1..00000000000
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_stream_id_blocked_frame.h
+++ /dev/null
@@ -1,40 +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_FRAMES_QUIC_STREAM_ID_BLOCKED_FRAME_H_
-#define QUICHE_QUIC_CORE_FRAMES_QUIC_STREAM_ID_BLOCKED_FRAME_H_
-
-#include <ostream>
-
-#include "net/third_party/quiche/src/quic/core/frames/quic_inlined_frame.h"
-#include "net/third_party/quiche/src/quic/core/quic_constants.h"
-#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-
-namespace quic {
-
-// IETF format STREAM_ID_BLOCKED frame.
-// The sender uses this to inform the peer that the sender wished to
-// open a new stream but was blocked from doing so due due to the
-// maximum stream ID limit set by the peer (via a MAX_STREAM_ID frame)
-struct QUIC_EXPORT_PRIVATE QuicStreamIdBlockedFrame
- : public QuicInlinedFrame<QuicStreamIdBlockedFrame> {
- QuicStreamIdBlockedFrame();
- QuicStreamIdBlockedFrame(QuicControlFrameId control_frame_id,
- QuicStreamId stream_id);
-
- friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
- std::ostream& os,
- const QuicStreamIdBlockedFrame& frame);
-
- // A unique identifier of this control frame. 0 when this frame is received,
- // and non-zero when sent.
- QuicControlFrameId control_frame_id;
-
- QuicStreamId stream_id;
-};
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_STREAM_ID_BLOCKED_FRAME_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_streams_blocked_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_streams_blocked_frame.cc
new file mode 100644
index 00000000000..f0579c55b68
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_streams_blocked_frame.cc
@@ -0,0 +1,33 @@
+// 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/frames/quic_streams_blocked_frame.h"
+
+namespace quic {
+
+QuicStreamsBlockedFrame::QuicStreamsBlockedFrame()
+ : QuicInlinedFrame(STREAMS_BLOCKED_FRAME),
+ control_frame_id(kInvalidControlFrameId),
+ unidirectional(false) {}
+
+QuicStreamsBlockedFrame::QuicStreamsBlockedFrame(
+ QuicControlFrameId control_frame_id,
+ QuicStreamCount stream_count,
+ bool unidirectional)
+ : QuicInlinedFrame(STREAMS_BLOCKED_FRAME),
+ control_frame_id(control_frame_id),
+ stream_count(stream_count),
+ unidirectional(unidirectional) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicStreamsBlockedFrame& frame) {
+ os << "{ control_frame_id: " << frame.control_frame_id
+ << ", stream count: " << frame.stream_count
+ << ((frame.unidirectional) ? ", unidirectional }\n"
+ : ", bidirectional }\n");
+
+ return os;
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_streams_blocked_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_streams_blocked_frame.h
new file mode 100644
index 00000000000..ff7c7f44621
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_streams_blocked_frame.h
@@ -0,0 +1,44 @@
+// 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_FRAMES_QUIC_STREAMS_BLOCKED_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_STREAMS_BLOCKED_FRAME_H_
+
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/frames/quic_inlined_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+
+namespace quic {
+
+// IETF format STREAMS_BLOCKED frame.
+// The sender uses this to inform the peer that the sender wished to
+// open a new stream, exceeding the limit on the number of streams.
+struct QUIC_EXPORT_PRIVATE QuicStreamsBlockedFrame
+ : public QuicInlinedFrame<QuicStreamsBlockedFrame> {
+ QuicStreamsBlockedFrame();
+ QuicStreamsBlockedFrame(QuicControlFrameId control_frame_id,
+ QuicStreamCount stream_count,
+ bool unidirectional);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicStreamsBlockedFrame& frame);
+
+ // A unique identifier of this control frame. 0 when this frame is received,
+ // and non-zero when sent.
+ QuicControlFrameId control_frame_id;
+
+ // The number of streams that the sender wishes to exceed
+ QuicStreamCount stream_count;
+
+ // Whether uni- or bi-directional streams
+ bool unidirectional;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_STREAMS_BLOCKED_FRAME_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 e537c735377..0a0326ce437 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
@@ -13,6 +13,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.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_epoll_connection_helper.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_framer.h"
@@ -83,18 +84,11 @@ struct TestParams {
TestParams(const ParsedQuicVersionVector& client_supported_versions,
const ParsedQuicVersionVector& server_supported_versions,
ParsedQuicVersion negotiated_version,
- bool client_supports_stateless_rejects,
- bool server_uses_stateless_rejects_if_peer_supported,
- QuicTag congestion_control_tag,
- bool use_cheap_stateless_reject)
+ QuicTag congestion_control_tag)
: client_supported_versions(client_supported_versions),
server_supported_versions(server_supported_versions),
negotiated_version(negotiated_version),
- client_supports_stateless_rejects(client_supports_stateless_rejects),
- server_uses_stateless_rejects_if_peer_supported(
- server_uses_stateless_rejects_if_peer_supported),
- congestion_control_tag(congestion_control_tag),
- use_cheap_stateless_reject(use_cheap_stateless_reject) {}
+ congestion_control_tag(congestion_control_tag) {}
friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
os << "{ server_supported_versions: "
@@ -103,29 +97,19 @@ struct TestParams {
<< ParsedQuicVersionVectorToString(p.client_supported_versions);
os << " negotiated_version: "
<< ParsedQuicVersionToString(p.negotiated_version);
- os << " client_supports_stateless_rejects: "
- << p.client_supports_stateless_rejects;
- os << " server_uses_stateless_rejects_if_peer_supported: "
- << p.server_uses_stateless_rejects_if_peer_supported;
os << " congestion_control_tag: "
- << QuicTagToString(p.congestion_control_tag);
- os << " use_cheap_stateless_reject: " << p.use_cheap_stateless_reject
- << " }";
+ << QuicTagToString(p.congestion_control_tag) << " }";
return os;
}
ParsedQuicVersionVector client_supported_versions;
ParsedQuicVersionVector server_supported_versions;
ParsedQuicVersion negotiated_version;
- bool client_supports_stateless_rejects;
- bool server_uses_stateless_rejects_if_peer_supported;
QuicTag congestion_control_tag;
- bool use_cheap_stateless_reject;
};
// Constructs various test permutations.
-std::vector<TestParams> GetTestParams(bool use_tls_handshake,
- bool test_stateless_rejects) {
+std::vector<TestParams> GetTestParams(bool use_tls_handshake) {
QuicFlagSaver flags;
// Divide the versions into buckets in which the intra-frame format
// is compatible. When clients encounter QUIC version negotiation
@@ -135,7 +119,7 @@ std::vector<TestParams> GetTestParams(bool use_tls_handshake,
// handshake protocol). So these tests need to ensure that clients are never
// attempting to do 0-RTT across incompatible versions. Chromium only
// supports a single version at a time anyway. :)
- FLAGS_quic_supports_tls_handshake = use_tls_handshake;
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, use_tls_handshake);
ParsedQuicVersionVector all_supported_versions =
FilterSupportedVersions(AllSupportedVersions());
@@ -157,92 +141,35 @@ std::vector<TestParams> GetTestParams(bool use_tls_handshake,
}
}
- // This must be kept in sync with the number of nested for-loops below as it
- // is used to prune the number of tests that are run.
- const int kMaxEnabledOptions = 4;
- int max_enabled_options = 0;
std::vector<TestParams> params;
for (const QuicTag congestion_control_tag : {kRENO, kTBBR, kQBIC, kTPCC}) {
- for (bool server_uses_stateless_rejects_if_peer_supported : {true, false}) {
- for (bool client_supports_stateless_rejects : {true, false}) {
- for (bool use_cheap_stateless_reject : {true, false}) {
- int enabled_options = 0;
- if (congestion_control_tag != kQBIC) {
- ++enabled_options;
- }
- if (client_supports_stateless_rejects) {
- ++enabled_options;
- }
- if (server_uses_stateless_rejects_if_peer_supported) {
- ++enabled_options;
- }
- if (use_cheap_stateless_reject) {
- ++enabled_options;
- }
- CHECK_GE(kMaxEnabledOptions, enabled_options);
- if (enabled_options > max_enabled_options) {
- max_enabled_options = enabled_options;
- }
-
- // Run tests with no options, a single option, or all the
- // options enabled to avoid a combinatorial explosion.
- if (enabled_options > 1 && enabled_options < kMaxEnabledOptions) {
- continue;
- }
-
- // There are many stateless reject combinations, so don't test them
- // unless requested.
- if ((server_uses_stateless_rejects_if_peer_supported ||
- client_supports_stateless_rejects ||
- use_cheap_stateless_reject) &&
- !test_stateless_rejects) {
- continue;
- }
-
- for (const ParsedQuicVersionVector& client_versions :
- version_buckets) {
- if (FilterSupportedVersions(client_versions).empty()) {
- continue;
- }
- // Add an entry for server and client supporting all
- // versions.
- params.push_back(TestParams(
- client_versions, all_supported_versions,
- client_versions.front(), client_supports_stateless_rejects,
- server_uses_stateless_rejects_if_peer_supported,
- congestion_control_tag, use_cheap_stateless_reject));
-
- // Run version negotiation tests tests with no options, or
- // all the options enabled to avoid a combinatorial
- // explosion.
- if (enabled_options > 1 && enabled_options < kMaxEnabledOptions) {
- continue;
- }
-
- // Test client supporting all versions and server supporting
- // 1 version. Simulate an old server and exercise version
- // downgrade in the client. Protocol negotiation should
- // occur. Skip the i = 0 case because it is essentially the
- // same as the default case.
- for (size_t i = 1; i < client_versions.size(); ++i) {
- ParsedQuicVersionVector server_supported_versions;
- server_supported_versions.push_back(client_versions[i]);
- if (FilterSupportedVersions(server_supported_versions).empty()) {
- continue;
- }
- params.push_back(TestParams(
- client_versions, server_supported_versions,
- server_supported_versions.front(),
- client_supports_stateless_rejects,
- server_uses_stateless_rejects_if_peer_supported,
- congestion_control_tag, use_cheap_stateless_reject));
- } // End of inner version loop.
- } // End of outer version loop.
- } // End of use_cheap_stateless_reject loop.
- } // End of client_supports_stateless_rejects loop.
- } // End of server_uses_stateless_rejects_if_peer_supported loop.
- } // End of congestion_control_tag loop.
- CHECK_EQ(kMaxEnabledOptions, max_enabled_options);
+ for (const ParsedQuicVersionVector& client_versions : version_buckets) {
+ if (FilterSupportedVersions(client_versions).empty()) {
+ continue;
+ }
+ // Add an entry for server and client supporting all versions.
+ params.push_back(TestParams(client_versions, all_supported_versions,
+ client_versions.front(),
+ congestion_control_tag));
+
+ // Test client supporting all versions and server supporting
+ // 1 version. Simulate an old server and exercise version
+ // downgrade in the client. Protocol negotiation should
+ // occur. Skip the i = 0 case because it is essentially the
+ // same as the default case.
+ for (size_t i = 1; i < client_versions.size(); ++i) {
+ ParsedQuicVersionVector server_supported_versions;
+ server_supported_versions.push_back(client_versions[i]);
+ if (FilterSupportedVersions(server_supported_versions).empty()) {
+ continue;
+ }
+ params.push_back(TestParams(client_versions, server_supported_versions,
+ server_supported_versions.front(),
+ congestion_control_tag));
+ } // End of inner version loop.
+ } // End of outer version loop.
+ } // End of congestion_control_tag loop.
+
return params;
}
@@ -284,9 +211,9 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
chlo_multiplier_(0),
stream_factory_(nullptr),
support_server_push_(false),
- override_connection_id_(nullptr),
- expected_connection_id_length_(kQuicDefaultConnectionIdLength) {
- FLAGS_quic_supports_tls_handshake = true;
+ override_server_connection_id_(nullptr),
+ expected_server_connection_id_length_(kQuicDefaultConnectionIdLength) {
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
SetQuicRestartFlag(quic_no_server_conn_ver_negotiation2, true);
SetQuicReloadableFlag(quic_no_client_conn_ver_negotiation, true);
client_supported_versions_ = GetParam().client_supported_versions;
@@ -332,8 +259,8 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
if (!pre_shared_key_client_.empty()) {
client->client()->SetPreSharedKey(pre_shared_key_client_);
}
- if (override_connection_id_ != nullptr) {
- client->UseConnectionId(*override_connection_id_);
+ if (override_server_connection_id_ != nullptr) {
+ client->UseConnectionId(*override_server_connection_id_);
}
client->Connect();
return client;
@@ -406,9 +333,6 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
copt.push_back(kTPCC);
}
- if (GetParam().client_supports_stateless_rejects) {
- copt.push_back(kSREJ);
- }
client_config_.SetConnectionOptionsToSend(copt);
// Start the server first, because CreateQuicClient() attempts
@@ -448,13 +372,10 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
}
void StartServer() {
- SetQuicReloadableFlag(quic_use_cheap_stateless_rejects,
- GetParam().use_cheap_stateless_reject);
-
auto* test_server = new QuicTestServer(
crypto_test_utils::ProofSourceForTesting(), server_config_,
server_supported_versions_, &memory_cache_backend_,
- expected_connection_id_length_);
+ expected_server_connection_id_length_);
server_thread_ = QuicMakeUnique<ServerThread>(test_server, server_address_);
if (chlo_multiplier_ != 0) {
server_thread_->server()->SetChloMultiplier(chlo_multiplier_);
@@ -467,10 +388,6 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
QuicServerPeer::GetDispatcher(server_thread_->server());
QuicDispatcherPeer::UseWriter(dispatcher, server_writer_);
- SetQuicReloadableFlag(
- enable_quic_stateless_reject_support,
- GetParam().server_uses_stateless_rejects_if_peer_supported);
-
server_writer_->Initialize(QuicDispatcherPeer::GetHelper(dispatcher),
QuicDispatcherPeer::GetAlarmFactory(dispatcher),
QuicMakeUnique<ServerDelegate>(dispatcher));
@@ -524,13 +441,10 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
EXPECT_EQ(0u, client_stats.packets_lost);
}
EXPECT_EQ(0u, client_stats.packets_discarded);
- // When doing 0-RTT with stateless rejects, the encrypted requests cause
- // a retranmission of the SREJ packets which are dropped by the client.
// When client starts with an unsupported version, the version negotiation
// packet sent by server for the old connection (respond for the connection
// close packet) will be dropped by the client.
- if (!BothSidesSupportStatelessRejects() &&
- !ServerSendsVersionNegotiation()) {
+ if (!ServerSendsVersionNegotiation()) {
EXPECT_EQ(0u, client_stats.packets_dropped);
}
if (!ClientSupportsIetfQuicNotSupportedByServer()) {
@@ -542,13 +456,7 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
EXPECT_EQ(client_stats.packets_received, client_stats.packets_processed);
}
- const int num_expected_stateless_rejects =
- (BothSidesSupportStatelessRejects() &&
- client_->client()->client_session()->GetNumSentClientHellos() > 0)
- ? 1
- : 0;
- EXPECT_EQ(num_expected_stateless_rejects,
- client_->client()->num_stateless_rejects_received());
+ EXPECT_EQ(0, client_->client()->num_stateless_rejects_received());
server_thread_->Pause();
QuicConnectionStats server_stats = GetServerConnection()->GetStats();
@@ -562,15 +470,9 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
server_thread_->Resume();
}
- bool BothSidesSupportStatelessRejects() {
- return (GetParam().server_uses_stateless_rejects_if_peer_supported &&
- GetParam().client_supports_stateless_rejects);
- }
-
// Client supports IETF QUIC, while it is not supported by server.
bool ClientSupportsIetfQuicNotSupportedByServer() {
- return GetParam().client_supported_versions[0].transport_version >
- QUIC_VERSION_43 &&
+ return client_supported_versions_[0].transport_version > QUIC_VERSION_43 &&
FilterSupportedVersions(GetParam().server_supported_versions)[0]
.transport_version <= QUIC_VERSION_43;
}
@@ -579,8 +481,7 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
// closes connection when version negotiation is received.
bool ServerSendsVersionNegotiation() {
return GetQuicReloadableFlag(quic_no_client_conn_ver_negotiation) &&
- GetParam().client_supported_versions[0] !=
- GetParam().negotiated_version;
+ client_supported_versions_[0] != GetParam().negotiated_version;
}
bool SupportsIetfQuicWithTls(ParsedQuicVersion version) {
@@ -637,26 +538,20 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
bool support_server_push_;
std::string pre_shared_key_client_;
std::string pre_shared_key_server_;
- QuicConnectionId* override_connection_id_;
- uint8_t expected_connection_id_length_;
+ QuicConnectionId* override_server_connection_id_;
+ uint8_t expected_server_connection_id_length_;
};
// Run all end to end tests with all supported versions.
INSTANTIATE_TEST_SUITE_P(EndToEndTests,
EndToEndTest,
- ::testing::ValuesIn(GetTestParams(false, false)));
+ ::testing::ValuesIn(GetTestParams(false)));
class EndToEndTestWithTls : public EndToEndTest {};
INSTANTIATE_TEST_SUITE_P(EndToEndTestsWithTls,
EndToEndTestWithTls,
- ::testing::ValuesIn(GetTestParams(true, false)));
-
-class EndToEndTestWithStatelessReject : public EndToEndTest {};
-
-INSTANTIATE_TEST_SUITE_P(WithStatelessReject,
- EndToEndTestWithStatelessReject,
- ::testing::ValuesIn(GetTestParams(false, true)));
+ ::testing::ValuesIn(GetTestParams(true)));
TEST_P(EndToEndTestWithTls, HandshakeSuccessful) {
ASSERT_TRUE(Initialize());
@@ -680,7 +575,7 @@ TEST_P(EndToEndTestWithTls, HandshakeSuccessful) {
EXPECT_FALSE(QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer));
}
-TEST_P(EndToEndTestWithStatelessReject, SimpleRequestResponseStatless) {
+TEST_P(EndToEndTest, SimpleRequestResponse) {
ASSERT_TRUE(Initialize());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
@@ -688,35 +583,28 @@ TEST_P(EndToEndTestWithStatelessReject, SimpleRequestResponseStatless) {
int expected_num_client_hellos = 2;
if (ServerSendsVersionNegotiation()) {
++expected_num_client_hellos;
- if (BothSidesSupportStatelessRejects()) {
- ++expected_num_client_hellos;
- }
}
EXPECT_EQ(expected_num_client_hellos,
client_->client()->GetNumSentClientHellos());
}
-TEST_P(EndToEndTest, SimpleRequestResponse) {
+TEST_P(EndToEndTest, SimpleRequestResponseForcedVersionNegotiation) {
+ client_supported_versions_.insert(client_supported_versions_.begin(),
+ QuicVersionReservedForNegotiation());
ASSERT_TRUE(Initialize());
+ ASSERT_TRUE(ServerSendsVersionNegotiation());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
- int expected_num_client_hellos = 2;
- if (ServerSendsVersionNegotiation()) {
- ++expected_num_client_hellos;
- if (BothSidesSupportStatelessRejects()) {
- ++expected_num_client_hellos;
- }
- }
- EXPECT_EQ(expected_num_client_hellos,
- client_->client()->GetNumSentClientHellos());
+
+ EXPECT_EQ(3, client_->client()->GetNumSentClientHellos());
}
TEST_P(EndToEndTest, SimpleRequestResponseZeroConnectionID) {
QuicConnectionId connection_id = QuicUtils::CreateZeroConnectionId(
GetParam().negotiated_version.transport_version);
- override_connection_id_ = &connection_id;
- expected_connection_id_length_ = connection_id.length();
+ override_server_connection_id_ = &connection_id;
+ expected_server_connection_id_length_ = connection_id.length();
ASSERT_TRUE(Initialize());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
@@ -724,9 +612,6 @@ TEST_P(EndToEndTest, SimpleRequestResponseZeroConnectionID) {
int expected_num_client_hellos = 2;
if (ServerSendsVersionNegotiation()) {
++expected_num_client_hellos;
- if (BothSidesSupportStatelessRejects()) {
- ++expected_num_client_hellos;
- }
}
EXPECT_EQ(expected_num_client_hellos,
client_->client()->GetNumSentClientHellos());
@@ -743,8 +628,35 @@ TEST_P(EndToEndTest, BadConnectionIdLength) {
}
QuicConnectionId connection_id =
TestConnectionIdNineBytesLong(UINT64_C(0xBADbadBADbad));
- override_connection_id_ = &connection_id;
+ override_server_connection_id_ = &connection_id;
+ ASSERT_TRUE(Initialize());
+ EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
+ EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+ EXPECT_EQ(kQuicDefaultConnectionIdLength, client_->client()
+ ->client_session()
+ ->connection()
+ ->connection_id()
+ .length());
+}
+
+TEST_P(EndToEndTest, ForcedVersionNegotiationAndBadConnectionIdLength) {
+ if (!GetQuicRestartFlag(
+ quic_allow_variable_length_connection_id_for_negotiation)) {
+ ASSERT_TRUE(Initialize());
+ return;
+ }
+ if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
+ GetParam().negotiated_version.transport_version)) {
+ ASSERT_TRUE(Initialize());
+ return;
+ }
+ client_supported_versions_.insert(client_supported_versions_.begin(),
+ QuicVersionReservedForNegotiation());
+ QuicConnectionId connection_id =
+ TestConnectionIdNineBytesLong(UINT64_C(0xBADbadBADbad));
+ override_server_connection_id_ = &connection_id;
ASSERT_TRUE(Initialize());
+ ASSERT_TRUE(ServerSendsVersionNegotiation());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
EXPECT_EQ(kQuicDefaultConnectionIdLength, client_->client()
@@ -764,9 +676,9 @@ TEST_P(EndToEndTest, MixGoodAndBadConnectionIdLengths) {
// Start client_ which will use a bad connection ID length.
QuicConnectionId connection_id =
TestConnectionIdNineBytesLong(UINT64_C(0xBADbadBADbad));
- override_connection_id_ = &connection_id;
+ override_server_connection_id_ = &connection_id;
ASSERT_TRUE(Initialize());
- override_connection_id_ = nullptr;
+ override_server_connection_id_ = nullptr;
// Start client2 which will use a good connection ID length.
std::unique_ptr<QuicTestClient> client2(CreateQuicClient(nullptr));
@@ -819,6 +731,22 @@ TEST_P(EndToEndTestWithTls, SimpleRequestResponsev6) {
EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
}
+TEST_P(EndToEndTestWithTls, NoUndecryptablePackets) {
+ ASSERT_TRUE(Initialize());
+
+ EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
+ EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+
+ QuicConnectionStats client_stats =
+ client_->client()->client_session()->connection()->GetStats();
+ EXPECT_EQ(0u, client_stats.undecryptable_packets_received);
+
+ server_thread_->Pause();
+ QuicConnectionStats server_stats = GetServerConnection()->GetStats();
+ EXPECT_EQ(0u, server_stats.undecryptable_packets_received);
+ server_thread_->Resume();
+}
+
TEST_P(EndToEndTestWithTls, SeparateFinPacket) {
ASSERT_TRUE(Initialize());
@@ -855,8 +783,8 @@ TEST_P(EndToEndTestWithTls, MultipleRequestResponse) {
TEST_P(EndToEndTest, MultipleRequestResponseZeroConnectionID) {
QuicConnectionId connection_id = QuicUtils::CreateZeroConnectionId(
GetParam().negotiated_version.transport_version);
- override_connection_id_ = &connection_id;
- expected_connection_id_length_ = connection_id.length();
+ override_server_connection_id_ = &connection_id;
+ expected_server_connection_id_length_ = connection_id.length();
ASSERT_TRUE(Initialize());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
@@ -1000,14 +928,10 @@ TEST_P(EndToEndTest, LargePostNoPacketLoss1sRTT) {
}
TEST_P(EndToEndTest, LargePostWithPacketLoss) {
- if (!BothSidesSupportStatelessRejects()) {
- // Connect with lower fake packet loss than we'd like to test.
- // Until b/10126687 is fixed, losing handshake packets is pretty
- // brutal.
- // TODO(jokulik): Until we support redundant SREJ packets, don't
- // drop handshake packets for stateless rejects.
- SetPacketLossPercentage(5);
- }
+ // Connect with lower fake packet loss than we'd like to test.
+ // Until b/10126687 is fixed, losing handshake packets is pretty
+ // brutal.
+ SetPacketLossPercentage(5);
ASSERT_TRUE(Initialize());
// Wait for the server SHLO before upping the packet loss.
@@ -1059,13 +983,9 @@ TEST_P(EndToEndTest, LargePostWithPacketLossAndAlwaysBundleWindowUpdates) {
}
TEST_P(EndToEndTest, LargePostWithPacketLossAndBlockedSocket) {
- if (!BothSidesSupportStatelessRejects()) {
- // Connect with lower fake packet loss than we'd like to test. Until
- // b/10126687 is fixed, losing handshake packets is pretty brutal.
- // TODO(jokulik): Until we support redundant SREJ packets, don't
- // drop handshake packets for stateless rejects.
- SetPacketLossPercentage(5);
- }
+ // Connect with lower fake packet loss than we'd like to test. Until
+ // b/10126687 is fixed, losing handshake packets is pretty brutal.
+ SetPacketLossPercentage(5);
ASSERT_TRUE(Initialize());
// Wait for the server SHLO before upping the packet loss.
@@ -1119,17 +1039,9 @@ TEST_P(EndToEndTest, LargePostZeroRTTFailure) {
EXPECT_EQ(kFooResponseBody,
client_->SendCustomSynchronousRequest(headers, body));
- // In the non-stateless case, the same session is used for both
- // hellos, so the number of hellos sent on that session is 2. In
- // the stateless case, the first client session will be completely
- // torn down after the reject. The number of hellos on the latest
- // session is 1.
- const int expected_num_hellos_latest_session =
- (BothSidesSupportStatelessRejects() && !ServerSendsVersionNegotiation())
- ? 1
- : 2;
- EXPECT_EQ(expected_num_hellos_latest_session,
- client_->client()->client_session()->GetNumSentClientHellos());
+ // The same session is used for both hellos, so the number of hellos sent on
+ // that session is 2.
+ EXPECT_EQ(2, client_->client()->client_session()->GetNumSentClientHellos());
if (ServerSendsVersionNegotiation()) {
EXPECT_EQ(3, client_->client()->GetNumSentClientHellos());
} else {
@@ -1164,13 +1076,9 @@ TEST_P(EndToEndTest, LargePostZeroRTTFailure) {
ASSERT_TRUE(client_->client()->connected());
EXPECT_EQ(kFooResponseBody,
client_->SendCustomSynchronousRequest(headers, body));
- // In the non-stateless case, the same session is used for both
- // hellos, so the number of hellos sent on that session is 2. In
- // the stateless case, the first client session will be completely
- // torn down after the reject. The number of hellos sent on the
- // latest session is 1.
- EXPECT_EQ(expected_num_hellos_latest_session,
- client_->client()->client_session()->GetNumSentClientHellos());
+ // The same session is used for both hellos, so the number of hellos sent on
+ // that session is 2.
+ EXPECT_EQ(2, client_->client()->client_session()->GetNumSentClientHellos());
if (ServerSendsVersionNegotiation()) {
EXPECT_EQ(3, client_->client()->GetNumSentClientHellos());
} else {
@@ -1186,17 +1094,9 @@ TEST_P(EndToEndTest, SynchronousRequestZeroRTTFailure) {
ASSERT_TRUE(Initialize());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
- // In the non-stateless case, the same session is used for both
- // hellos, so the number of hellos sent on that session is 2. In
- // the stateless case, the first client session will be completely
- // torn down after the reject. The number of hellos on that second
- // latest session is 1.
- const int expected_num_hellos_latest_session =
- (BothSidesSupportStatelessRejects() && !ServerSendsVersionNegotiation())
- ? 1
- : 2;
- EXPECT_EQ(expected_num_hellos_latest_session,
- client_->client()->client_session()->GetNumSentClientHellos());
+ // The same session is used for both hellos, so the number of hellos sent on
+ // that session is 2.
+ EXPECT_EQ(2, client_->client()->client_session()->GetNumSentClientHellos());
if (ServerSendsVersionNegotiation()) {
EXPECT_EQ(3, client_->client()->GetNumSentClientHellos());
} else {
@@ -1229,13 +1129,8 @@ TEST_P(EndToEndTest, SynchronousRequestZeroRTTFailure) {
EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
ASSERT_TRUE(client_->client()->connected());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
- // In the non-stateless case, the same session is used for both
- // hellos, so the number of hellos sent on that session is 2. In
- // the stateless case, the first client session will be completely
- // torn down after the reject. The number of hellos sent on the
- // latest session is 1.
- EXPECT_EQ(expected_num_hellos_latest_session,
- client_->client()->client_session()->GetNumSentClientHellos());
+
+ EXPECT_EQ(2, client_->client()->client_session()->GetNumSentClientHellos());
if (ServerSendsVersionNegotiation()) {
EXPECT_EQ(3, client_->client()->GetNumSentClientHellos());
} else {
@@ -1259,17 +1154,9 @@ TEST_P(EndToEndTest, LargePostSynchronousRequest) {
EXPECT_EQ(kFooResponseBody,
client_->SendCustomSynchronousRequest(headers, body));
- // In the non-stateless case, the same session is used for both
- // hellos, so the number of hellos sent on that session is 2. In
- // the stateless case, the first client session will be completely
- // torn down after the reject. The number of hellos on the latest
- // session is 1.
- const int expected_num_hellos_latest_session =
- (BothSidesSupportStatelessRejects() && !ServerSendsVersionNegotiation())
- ? 1
- : 2;
- EXPECT_EQ(expected_num_hellos_latest_session,
- client_->client()->client_session()->GetNumSentClientHellos());
+ // The same session is used for both hellos, so the number of hellos sent on
+ // that session is 2.
+ EXPECT_EQ(2, client_->client()->client_session()->GetNumSentClientHellos());
if (ServerSendsVersionNegotiation()) {
EXPECT_EQ(3, client_->client()->GetNumSentClientHellos());
} else {
@@ -1304,13 +1191,8 @@ TEST_P(EndToEndTest, LargePostSynchronousRequest) {
ASSERT_TRUE(client_->client()->connected());
EXPECT_EQ(kFooResponseBody,
client_->SendCustomSynchronousRequest(headers, body));
- // In the non-stateless case, the same session is used for both
- // hellos, so the number of hellos sent on that session is 2. In
- // the stateless case, the first client session will be completely
- // torn down after the reject. The number of hellos sent on the
- // latest session is 1.
- EXPECT_EQ(expected_num_hellos_latest_session,
- client_->client()->client_session()->GetNumSentClientHellos());
+
+ EXPECT_EQ(2, client_->client()->client_session()->GetNumSentClientHellos());
if (ServerSendsVersionNegotiation()) {
EXPECT_EQ(3, client_->client()->GetNumSentClientHellos());
} else {
@@ -1320,9 +1202,9 @@ TEST_P(EndToEndTest, LargePostSynchronousRequest) {
VerifyCleanConnection(false);
}
-TEST_P(EndToEndTest, StatelessRejectWithPacketLoss) {
+TEST_P(EndToEndTest, RejectWithPacketLoss) {
// In this test, we intentionally drop the first packet from the
- // server, which corresponds with the initial REJ/SREJ response from
+ // server, which corresponds with the initial REJ response from
// the server.
server_writer_->set_fake_drop_first_n_packets(1);
ASSERT_TRUE(Initialize());
@@ -1461,8 +1343,17 @@ TEST_P(EndToEndTest, LargeHeaders) {
headers["key3"] = std::string(15 * 1024, 'a');
client_->SendCustomSynchronousRequest(headers, body);
- EXPECT_EQ(QUIC_HEADERS_TOO_LARGE, client_->stream_error());
- EXPECT_EQ(QUIC_NO_ERROR, client_->connection_error());
+
+ if (VersionUsesQpack(client_->client()
+ ->client_session()
+ ->connection()
+ ->transport_version())) {
+ EXPECT_EQ(QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE,
+ client_->connection_error());
+ } else {
+ EXPECT_EQ(QUIC_HEADERS_TOO_LARGE, client_->stream_error());
+ EXPECT_EQ(QUIC_NO_ERROR, client_->connection_error());
+ }
}
TEST_P(EndToEndTest, EarlyResponseWithQuicStreamNoError) {
@@ -1524,12 +1415,18 @@ TEST_P(EndToEndTestWithTls, MaxIncomingDynamicStreamsLimitRespected) {
// Set a limit on maximum number of incoming dynamic streams.
// Make sure the limit is respected.
const uint32_t kServerMaxIncomingDynamicStreams = 1;
- server_config_.SetMaxIncomingDynamicStreamsToSend(
+ server_config_.SetMaxIncomingBidirectionalStreamsToSend(
kServerMaxIncomingDynamicStreams);
ASSERT_TRUE(Initialize());
+ if (GetParam().negotiated_version.transport_version == QUIC_VERSION_99) {
+ // Do not run this test for version 99/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());
- QuicConnection* client_connection =
- client_->client()->client_session()->connection();
// Make the client misbehave after negotiation.
const int kServerMaxStreams = kMaxStreamsMinimumIncrement + 1;
@@ -1549,35 +1446,43 @@ TEST_P(EndToEndTestWithTls, MaxIncomingDynamicStreamsLimitRespected) {
client_->SendMessage(headers, "", /*fin=*/false);
}
client_->WaitForResponse();
- if (client_connection->transport_version() != QUIC_VERSION_99) {
- EXPECT_TRUE(client_->connected());
- EXPECT_EQ(QUIC_REFUSED_STREAM, client_->stream_error());
- EXPECT_EQ(QUIC_NO_ERROR, client_->connection_error());
- } else {
- // Version 99 disconnects the connection if we exceed the stream limit.
- EXPECT_FALSE(client_->connected());
- EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error());
- EXPECT_EQ(QUIC_INVALID_STREAM_ID, client_->connection_error());
- }
+
+ EXPECT_TRUE(client_->connected());
+ EXPECT_EQ(QUIC_REFUSED_STREAM, client_->stream_error());
+ EXPECT_EQ(QUIC_NO_ERROR, client_->connection_error());
}
TEST_P(EndToEndTest, SetIndependentMaxIncomingDynamicStreamsLimits) {
// Each endpoint can set max incoming dynamic streams independently.
const uint32_t kClientMaxIncomingDynamicStreams = 2;
const uint32_t kServerMaxIncomingDynamicStreams = 1;
- client_config_.SetMaxIncomingDynamicStreamsToSend(
+ client_config_.SetMaxIncomingBidirectionalStreamsToSend(
+ kClientMaxIncomingDynamicStreams);
+ server_config_.SetMaxIncomingBidirectionalStreamsToSend(
+ kServerMaxIncomingDynamicStreams);
+ client_config_.SetMaxIncomingUnidirectionalStreamsToSend(
kClientMaxIncomingDynamicStreams);
- server_config_.SetMaxIncomingDynamicStreamsToSend(
+ server_config_.SetMaxIncomingUnidirectionalStreamsToSend(
kServerMaxIncomingDynamicStreams);
+
ASSERT_TRUE(Initialize());
EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
// The client has received the server's limit and vice versa.
QuicSpdyClientSession* client_session = client_->client()->client_session();
+ // The value returned by max_allowed... includes the Crypto and Header
+ // stream (created as a part of initialization). The config. values,
+ // above, are treated as "number of requests/responses" - that is, they do
+ // not include the static Crypto and Header streams. Reduce the value
+ // returned by max_allowed... by 2 to remove the static streams from the
+ // count.
size_t client_max_open_outgoing_bidirectional_streams =
client_session->connection()->transport_version() == QUIC_VERSION_99
? QuicSessionPeer::v99_streamid_manager(client_session)
- ->max_allowed_outgoing_bidirectional_streams()
+ ->max_allowed_outgoing_bidirectional_streams() -
+ QuicSessionPeer::v99_bidirectional_stream_id_manager(
+ client_session)
+ ->outgoing_static_stream_count()
: QuicSessionPeer::GetStreamIdManager(client_session)
->max_open_outgoing_streams();
size_t client_max_open_outgoing_unidirectional_streams =
@@ -1757,6 +1662,11 @@ TEST_P(EndToEndTest, MinInitialRTT) {
}
TEST_P(EndToEndTest, 0ByteConnectionId) {
+ if (GetParam().negotiated_version.transport_version > QUIC_VERSION_43) {
+ // SetBytesForConnectionIdToSend only applies to Google QUIC encoding.
+ ASSERT_TRUE(Initialize());
+ return;
+ }
client_config_.SetBytesForConnectionIdToSend(0);
ASSERT_TRUE(Initialize());
@@ -1766,10 +1676,19 @@ TEST_P(EndToEndTest, 0ByteConnectionId) {
client_->client()->client_session()->connection();
QuicPacketHeader* header =
QuicConnectionPeer::GetLastHeader(client_connection);
- EXPECT_EQ(CONNECTION_ID_ABSENT, header->destination_connection_id_included);
+ if (!GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ EXPECT_EQ(CONNECTION_ID_ABSENT, header->destination_connection_id_included);
+ } else {
+ EXPECT_EQ(CONNECTION_ID_ABSENT, header->source_connection_id_included);
+ }
}
TEST_P(EndToEndTestWithTls, 8ByteConnectionId) {
+ if (GetParam().negotiated_version.transport_version > QUIC_VERSION_43) {
+ // SetBytesForConnectionIdToSend only applies to Google QUIC encoding.
+ ASSERT_TRUE(Initialize());
+ return;
+ }
client_config_.SetBytesForConnectionIdToSend(8);
ASSERT_TRUE(Initialize());
@@ -1779,15 +1698,15 @@ TEST_P(EndToEndTestWithTls, 8ByteConnectionId) {
client_->client()->client_session()->connection();
QuicPacketHeader* header =
QuicConnectionPeer::GetLastHeader(client_connection);
- if (client_connection->transport_version() > QUIC_VERSION_43) {
- EXPECT_EQ(CONNECTION_ID_ABSENT, header->destination_connection_id_included);
- } else {
- EXPECT_EQ(CONNECTION_ID_PRESENT,
- header->destination_connection_id_included);
- }
+ EXPECT_EQ(CONNECTION_ID_PRESENT, header->destination_connection_id_included);
}
TEST_P(EndToEndTestWithTls, 15ByteConnectionId) {
+ if (GetParam().negotiated_version.transport_version > QUIC_VERSION_43) {
+ // SetBytesForConnectionIdToSend only applies to Google QUIC encoding.
+ ASSERT_TRUE(Initialize());
+ return;
+ }
client_config_.SetBytesForConnectionIdToSend(15);
ASSERT_TRUE(Initialize());
@@ -1798,12 +1717,7 @@ TEST_P(EndToEndTestWithTls, 15ByteConnectionId) {
client_->client()->client_session()->connection();
QuicPacketHeader* header =
QuicConnectionPeer::GetLastHeader(client_connection);
- if (client_connection->transport_version() > QUIC_VERSION_43) {
- EXPECT_EQ(CONNECTION_ID_ABSENT, header->destination_connection_id_included);
- } else {
- EXPECT_EQ(CONNECTION_ID_PRESENT,
- header->destination_connection_id_included);
- }
+ EXPECT_EQ(CONNECTION_ID_PRESENT, header->destination_connection_id_included);
}
TEST_P(EndToEndTestWithTls, ResetConnection) {
@@ -1820,13 +1734,9 @@ TEST_P(EndToEndTestWithTls, ResetConnection) {
// TODO(nharper): Needs to get turned back to EndToEndTestWithTls
// when we figure out why the test doesn't work on chrome.
TEST_P(EndToEndTest, MaxStreamsUberTest) {
- if (!BothSidesSupportStatelessRejects()) {
- // Connect with lower fake packet loss than we'd like to test. Until
- // b/10126687 is fixed, losing handshake packets is pretty brutal.
- // TODO(jokulik): Until we support redundant SREJ packets, don't
- // drop handshake packets for stateless rejects.
- SetPacketLossPercentage(1);
- }
+ // Connect with lower fake packet loss than we'd like to test. Until
+ // b/10126687 is fixed, losing handshake packets is pretty brutal.
+ SetPacketLossPercentage(1);
ASSERT_TRUE(Initialize());
std::string large_body(10240, 'a');
int max_streams = 100;
@@ -2086,10 +1996,9 @@ TEST_P(EndToEndTest, HeadersAndCryptoStreamsNoConnectionFlowControl) {
client_->client()->client_session());
// In v47 and later, the crypto handshake (sent in CRYPTO frames) is not
// subject to flow control.
- if (!QuicVersionUsesCryptoFrames(client_->client()
- ->client_session()
- ->connection()
- ->transport_version())) {
+ const QuicTransportVersion transport_version =
+ client_->client()->client_session()->connection()->transport_version();
+ if (!QuicVersionUsesCryptoFrames(transport_version)) {
EXPECT_LT(QuicFlowControllerPeer::SendWindowSize(
crypto_stream->flow_controller()),
kStreamIFCW);
@@ -2102,6 +2011,11 @@ TEST_P(EndToEndTest, HeadersAndCryptoStreamsNoConnectionFlowControl) {
// has not been affected.
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
+ // No headers stream in IETF QUIC.
+ if (VersionUsesQpack(transport_version)) {
+ return;
+ }
+
QuicHeadersStream* headers_stream = QuicSpdySessionPeer::GetHeadersStream(
client_->client()->client_session());
EXPECT_LT(
@@ -2135,11 +2049,16 @@ TEST_P(EndToEndTest, FlowControlsSynced) {
auto* server_session = static_cast<QuicSpdySession*>(GetServerSession());
ExpectFlowControlsSynced(client_session->flow_controller(),
server_session->flow_controller());
- ExpectFlowControlsSynced(
- QuicSessionPeer::GetMutableCryptoStream(client_session)
- ->flow_controller(),
- QuicSessionPeer::GetMutableCryptoStream(server_session)
- ->flow_controller());
+ if (!QuicVersionUsesCryptoFrames(client_->client()
+ ->client_session()
+ ->connection()
+ ->transport_version())) {
+ ExpectFlowControlsSynced(
+ QuicSessionPeer::GetMutableCryptoStream(client_session)
+ ->flow_controller(),
+ QuicSessionPeer::GetMutableCryptoStream(server_session)
+ ->flow_controller());
+ }
SpdyFramer spdy_framer(SpdyFramer::ENABLE_COMPRESSION);
SpdySettingsIR settings_frame;
settings_frame.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE,
@@ -2243,11 +2162,8 @@ TEST_P(EndToEndTest, AckNotifierWithPacketLossAndBlockedSocket) {
// socket, an AckNotifierDelegate will get informed that the data it is
// interested in has been ACKed. This tests end-to-end ACK notification, and
// demonstrates that retransmissions do not break this functionality.
- if (!BothSidesSupportStatelessRejects()) {
- // TODO(jokulik): Until we support redundant SREJ packets, don't
- // drop handshake packets for stateless rejects.
- SetPacketLossPercentage(5);
- }
+
+ SetPacketLossPercentage(5);
ASSERT_TRUE(Initialize());
// Wait for the server SHLO before upping the packet loss.
@@ -2264,6 +2180,29 @@ TEST_P(EndToEndTest, AckNotifierWithPacketLossAndBlockedSocket) {
client_->SendMessage(headers, "", /*fin=*/false);
+ // Size of headers on the request stream. Zero if headers are sent on the
+ // header stream.
+ size_t header_size = 0;
+ if (VersionUsesQpack(client_->client()
+ ->client_session()
+ ->connection()
+ ->transport_version())) {
+ // Determine size of compressed headers.
+ NoopDecoderStreamErrorDelegate decoder_stream_error_delegate;
+ NoopEncoderStreamSenderDelegate encoder_stream_sender_delegate;
+ QpackEncoder qpack_encoder(&decoder_stream_error_delegate,
+ &encoder_stream_sender_delegate);
+ auto progressive_encoder =
+ qpack_encoder.EncodeHeaderList(/* stream_id = */ 0, &headers);
+ std::string encoded_headers;
+ while (progressive_encoder->HasNext()) {
+ progressive_encoder->Next(
+ /* max_encoded_bytes = */ std::numeric_limits<size_t>::max(),
+ &encoded_headers);
+ }
+ header_size = encoded_headers.size();
+ }
+
// Test the AckNotifier's ability to track multiple packets by making the
// request body exceed the size of a single packet.
std::string request_string = "a request body bigger than one packet" +
@@ -2271,7 +2210,7 @@ TEST_P(EndToEndTest, AckNotifierWithPacketLossAndBlockedSocket) {
// The TestAckListener will cause a failure if not notified.
QuicReferenceCountedPointer<TestAckListener> ack_listener(
- new TestAckListener(request_string.length()));
+ new TestAckListener(header_size + request_string.length()));
// Send the request, and register the delegate for ACKs.
client_->SendData(request_string, true, ack_listener);
@@ -2437,7 +2376,7 @@ TEST_P(EndToEndTestWithTls,
TestConnectionIdToUInt64(client_connection->connection_id()) + 1);
std::unique_ptr<QuicEncryptedPacket> packet(
QuicFramer::BuildVersionNegotiationPacket(
- incorrect_connection_id,
+ incorrect_connection_id, EmptyQuicConnectionId(),
client_connection->transport_version() > QUIC_VERSION_43,
server_supported_versions_));
testing::NiceMock<MockQuicConnectionDebugVisitor> visitor;
@@ -2863,8 +2802,10 @@ class EndToEndTestServerPush : public EndToEndTest {
const size_t kNumMaxStreams = 10;
EndToEndTestServerPush() : EndToEndTest() {
- client_config_.SetMaxIncomingDynamicStreamsToSend(kNumMaxStreams);
- server_config_.SetMaxIncomingDynamicStreamsToSend(kNumMaxStreams);
+ client_config_.SetMaxIncomingBidirectionalStreamsToSend(kNumMaxStreams);
+ server_config_.SetMaxIncomingBidirectionalStreamsToSend(kNumMaxStreams);
+ client_config_.SetMaxIncomingUnidirectionalStreamsToSend(kNumMaxStreams);
+ server_config_.SetMaxIncomingUnidirectionalStreamsToSend(kNumMaxStreams);
support_server_push_ = true;
}
@@ -2911,7 +2852,7 @@ class EndToEndTestServerPush : public EndToEndTest {
// Run all server push end to end tests with all supported versions.
INSTANTIATE_TEST_SUITE_P(EndToEndTestsServerPush,
EndToEndTestServerPush,
- ::testing::ValuesIn(GetTestParams(false, false)));
+ ::testing::ValuesIn(GetTestParams(false)));
TEST_P(EndToEndTestServerPush, ServerPush) {
ASSERT_TRUE(Initialize());
@@ -3206,10 +3147,7 @@ TEST_P(EndToEndTest, DISABLED_TestHugeResponseWithPacketLoss) {
SetPacketLossPercentage(1);
client_->SendRequest("/huge_response");
client_->WaitForResponse();
- // TODO(fayang): Fix this test to work with stateless rejects.
- if (!BothSidesSupportStatelessRejects()) {
- VerifyCleanConnection(true);
- }
+ VerifyCleanConnection(true);
}
// Regression test for b/111515567
@@ -3348,7 +3286,8 @@ TEST_P(EndToEndTest,
EXPECT_EQ("", client_->SendSynchronousRequest("/foo"));
if (client_->client()->client_session()->connection()->transport_version() >
- QUIC_VERSION_43) {
+ QUIC_VERSION_43 ||
+ GetQuicReloadableFlag(quic_terminate_gquic_connection_as_ietf)) {
EXPECT_EQ(QUIC_HANDSHAKE_FAILED, client_->connection_error());
} else {
EXPECT_EQ(QUIC_PUBLIC_RESET, client_->connection_error());
@@ -3629,7 +3568,7 @@ class EndToEndPacketReorderingTest : public EndToEndTest {
INSTANTIATE_TEST_SUITE_P(EndToEndPacketReorderingTests,
EndToEndPacketReorderingTest,
- testing::ValuesIn(GetTestParams(false, false)));
+ testing::ValuesIn(GetTestParams(false)));
TEST_P(EndToEndPacketReorderingTest, ReorderedConnectivityProbing) {
ASSERT_TRUE(Initialize());
@@ -3883,7 +3822,6 @@ class BadShloPacketWriter2 : public QuicPacketWriterWrapper {
TEST_P(EndToEndTest, ForwardSecureConnectionClose) {
// This test ensures ZERO_RTT_PROTECTED connection close is sent to a client
// which has ZERO_RTT_PROTECTED encryption level.
- SetQuicReloadableFlag(quic_fix_termination_packets, true);
connect_to_server_on_initialize_ =
negotiated_version_.transport_version <= QUIC_VERSION_43;
ASSERT_TRUE(Initialize());
@@ -3910,6 +3848,37 @@ TEST_P(EndToEndTest, ForwardSecureConnectionClose) {
EXPECT_EQ(QUIC_PACKET_WRITE_ERROR, client_->connection_error());
}
+// Test that the stream id manager closes the connection if a stream
+// in excess of the allowed maximum.
+TEST_P(EndToEndTest, TooBigStreamIdClosesConnection) {
+ // Has to be before version test, see EndToEndTest::TearDown()
+ ASSERT_TRUE(Initialize());
+ if (negotiated_version_.transport_version != QUIC_VERSION_99) {
+ // Only runs for IETF QUIC.
+ return;
+ }
+ EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
+
+ std::string body(kMaxOutgoingPacketSize, 'a');
+ SpdyHeaderBlock headers;
+ headers[":method"] = "POST";
+ headers[":path"] = "/foo";
+ headers[":scheme"] = "https";
+ headers[":authority"] = server_hostname_;
+
+ // Force the client to write with a stream ID that exceeds the limit.
+ QuicSpdySession* session = client_->client()->client_session();
+ QuicStreamIdManager* stream_id_manager =
+ QuicSessionPeer::v99_bidirectional_stream_id_manager(session);
+ QuicStreamCount max_number_of_streams =
+ stream_id_manager->outgoing_max_streams();
+ 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, client_->connection_error());
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.cc b/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.cc
index ec0062a0dd0..c59e8b0699b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.cc
@@ -24,8 +24,6 @@ uint8_t ExtractBits(uint8_t flags, uint8_t num_bits, uint8_t offset) {
return (flags >> offset) & GetMaskFromNumBits(num_bits);
}
-// Length of the type field of HTTP/3 frames.
-static const QuicByteCount kFrameTypeLength = 1;
// Length of the weight field of a priority frame.
static const size_t kPriorityWeightLength = 1;
// Length of a priority frame's first byte.
@@ -35,12 +33,14 @@ static const size_t kPriorityFirstByteLength = 1;
HttpDecoder::HttpDecoder()
: visitor_(nullptr),
- state_(STATE_READING_FRAME_LENGTH),
+ state_(STATE_READING_FRAME_TYPE),
current_frame_type_(0),
- current_length_field_size_(0),
+ current_length_field_length_(0),
remaining_length_field_length_(0),
current_frame_length_(0),
remaining_frame_length_(0),
+ current_type_field_length_(0),
+ remaining_type_field_length_(0),
error_(QUIC_NO_ERROR),
error_detail_("") {}
@@ -51,12 +51,12 @@ QuicByteCount HttpDecoder::ProcessInput(const char* data, QuicByteCount len) {
while (error_ == QUIC_NO_ERROR &&
(reader.BytesRemaining() != 0 || state_ == STATE_FINISH_PARSING)) {
switch (state_) {
- case STATE_READING_FRAME_LENGTH:
- ReadFrameLength(&reader);
- break;
case STATE_READING_FRAME_TYPE:
ReadFrameType(&reader);
break;
+ case STATE_READING_FRAME_LENGTH:
+ ReadFrameLength(&reader);
+ break;
case STATE_READING_FRAME_PAYLOAD:
ReadFramePayload(&reader);
break;
@@ -77,29 +77,83 @@ QuicByteCount HttpDecoder::ProcessInput(const char* data, QuicByteCount len) {
return len - reader.BytesRemaining();
}
-void HttpDecoder::ReadFrameLength(QuicDataReader* reader) {
+void HttpDecoder::ReadFrameType(QuicDataReader* reader) {
DCHECK_NE(0u, reader->BytesRemaining());
- BufferFrameLength(reader);
- if (remaining_length_field_length_ != 0) {
- return;
- }
- QuicDataReader length_reader(length_buffer_.data(),
- current_length_field_size_);
- if (!length_reader.ReadVarInt62(&current_frame_length_)) {
- RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame length");
- visitor_->OnError(this);
- return;
+ if (current_type_field_length_ == 0) {
+ // A new frame is coming.
+ current_type_field_length_ = reader->PeekVarInt62Length();
+ if (current_type_field_length_ == 0) {
+ RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame type length");
+ visitor_->OnError(this);
+ return;
+ }
+ if (current_type_field_length_ <= reader->BytesRemaining()) {
+ // The reader has all type data needed, so no need to buffer.
+ if (!reader->ReadVarInt62(&current_frame_type_)) {
+ RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame type");
+ return;
+ }
+ } else {
+ // Buffer a new type field.
+ remaining_type_field_length_ = current_type_field_length_;
+ BufferFrameType(reader);
+ return;
+ }
+ } else {
+ // Buffer the existing type field.
+ BufferFrameType(reader);
+ // The frame is still not buffered completely.
+ if (remaining_type_field_length_ != 0) {
+ return;
+ }
+ QuicDataReader type_reader(type_buffer_.data(), current_type_field_length_);
+ if (!type_reader.ReadVarInt62(&current_frame_type_)) {
+ RaiseError(QUIC_INTERNAL_ERROR, "Unable to read buffered frame type");
+ visitor_->OnError(this);
+ return;
+ }
}
- state_ = STATE_READING_FRAME_TYPE;
- remaining_frame_length_ = current_frame_length_;
+ state_ = STATE_READING_FRAME_LENGTH;
}
-void HttpDecoder::ReadFrameType(QuicDataReader* reader) {
+void HttpDecoder::ReadFrameLength(QuicDataReader* reader) {
DCHECK_NE(0u, reader->BytesRemaining());
- if (!reader->ReadUInt8(&current_frame_type_)) {
- RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame type");
- return;
+ if (current_length_field_length_ == 0) {
+ // A new frame is coming.
+ current_length_field_length_ = reader->PeekVarInt62Length();
+ if (current_length_field_length_ == 0) {
+ RaiseError(QUIC_INTERNAL_ERROR,
+ "Unable to read the length of frame length");
+ visitor_->OnError(this);
+ return;
+ }
+ if (current_length_field_length_ <= reader->BytesRemaining()) {
+ // The reader has all length data needed, so no need to buffer.
+ if (!reader->ReadVarInt62(&current_frame_length_)) {
+ RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame length");
+ return;
+ }
+ } else {
+ // Buffer a new length field.
+ remaining_length_field_length_ = current_length_field_length_;
+ BufferFrameLength(reader);
+ return;
+ }
+ } else {
+ // Buffer the existing length field.
+ BufferFrameLength(reader);
+ // The frame is still not buffered completely.
+ if (remaining_length_field_length_ != 0) {
+ return;
+ }
+ QuicDataReader length_reader(length_buffer_.data(),
+ current_length_field_length_);
+ if (!length_reader.ReadVarInt62(&current_frame_length_)) {
+ RaiseError(QUIC_INTERNAL_ERROR, "Unable to read buffered frame length");
+ visitor_->OnError(this);
+ return;
+ }
}
if (current_frame_length_ > MaxFrameLength(current_frame_type_)) {
@@ -112,15 +166,19 @@ void HttpDecoder::ReadFrameType(QuicDataReader* reader) {
// frame payload.
if (current_frame_type_ == 0x0) {
visitor_->OnDataFrameStart(Http3FrameLengths(
- current_length_field_size_ + kFrameTypeLength, current_frame_length_));
+ current_length_field_length_ + current_type_field_length_,
+ current_frame_length_));
} else if (current_frame_type_ == 0x1) {
visitor_->OnHeadersFrameStart(Http3FrameLengths(
- current_length_field_size_ + kFrameTypeLength, current_frame_length_));
+ current_length_field_length_ + current_type_field_length_,
+ current_frame_length_));
} else if (current_frame_type_ == 0x4) {
visitor_->OnSettingsFrameStart(Http3FrameLengths(
- current_length_field_size_ + kFrameTypeLength, current_frame_length_));
+ current_length_field_length_ + current_type_field_length_,
+ current_frame_length_));
}
+ remaining_frame_length_ = current_frame_length_;
state_ = (remaining_frame_length_ == 0) ? STATE_FINISH_PARSING
: STATE_READING_FRAME_PAYLOAD;
}
@@ -233,6 +291,7 @@ void HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
QUIC_FALLTHROUGH_INTENDED;
default:
DiscardFramePayload(reader);
+ return;
}
if (remaining_frame_length_ == 0) {
@@ -274,10 +333,6 @@ void HttpDecoder::FinishParsing() {
break;
}
case 0x4: { // SETTINGS
- // TODO(rch): Handle overly large SETTINGS frames. Either:
- // 1. Impose a limit on SETTINGS frame size, and close the connection if
- // exceeded
- // 2. Implement a streaming parsing mode.
SettingsFrame frame;
QuicDataReader reader(buffer_.data(), current_frame_length_);
if (!ParseSettingsFrame(&reader, &frame)) {
@@ -330,8 +385,9 @@ void HttpDecoder::FinishParsing() {
}
}
- current_length_field_size_ = 0;
- state_ = STATE_READING_FRAME_LENGTH;
+ current_length_field_length_ = 0;
+ current_type_field_length_ = 0;
+ state_ = STATE_READING_FRAME_TYPE;
}
void HttpDecoder::DiscardFramePayload(QuicDataReader* reader) {
@@ -344,8 +400,9 @@ void HttpDecoder::DiscardFramePayload(QuicDataReader* reader) {
}
remaining_frame_length_ -= payload.length();
if (remaining_frame_length_ == 0) {
- state_ = STATE_READING_FRAME_LENGTH;
- current_length_field_size_ = 0;
+ state_ = STATE_READING_FRAME_TYPE;
+ current_length_field_length_ = 0;
+ current_type_field_length_ = 0;
}
}
@@ -366,31 +423,37 @@ void HttpDecoder::BufferFramePayload(QuicDataReader* reader) {
}
void HttpDecoder::BufferFrameLength(QuicDataReader* reader) {
- if (current_length_field_size_ == 0) {
- current_length_field_size_ = reader->PeekVarInt62Length();
- if (current_length_field_size_ == 0) {
- RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame length");
- visitor_->OnError(this);
- return;
- }
- remaining_length_field_length_ = current_length_field_size_;
- }
- if (current_length_field_size_ == remaining_length_field_length_) {
- length_buffer_.erase(length_buffer_.size());
- length_buffer_.reserve(current_length_field_size_);
+ if (current_length_field_length_ == remaining_length_field_length_) {
+ length_buffer_.fill(0);
}
QuicByteCount bytes_to_read = std::min<QuicByteCount>(
remaining_length_field_length_, reader->BytesRemaining());
- if (!reader->ReadBytes(&(length_buffer_[0]) + current_length_field_size_ -
+ if (!reader->ReadBytes(length_buffer_.data() + current_length_field_length_ -
remaining_length_field_length_,
bytes_to_read)) {
- RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame length");
+ RaiseError(QUIC_INTERNAL_ERROR, "Unable to buffer frame length bytes.");
visitor_->OnError(this);
return;
}
remaining_length_field_length_ -= bytes_to_read;
}
+void HttpDecoder::BufferFrameType(QuicDataReader* reader) {
+ if (current_type_field_length_ == remaining_type_field_length_) {
+ type_buffer_.fill(0);
+ }
+ QuicByteCount bytes_to_read = std::min<QuicByteCount>(
+ remaining_type_field_length_, reader->BytesRemaining());
+ if (!reader->ReadBytes(type_buffer_.data() + current_type_field_length_ -
+ remaining_type_field_length_,
+ bytes_to_read)) {
+ RaiseError(QUIC_INTERNAL_ERROR, "Unable to buffer frame type bytes.");
+ visitor_->OnError(this);
+ return;
+ }
+ remaining_type_field_length_ -= bytes_to_read;
+}
+
void HttpDecoder::RaiseError(QuicErrorCode error, std::string error_detail) {
state_ = STATE_ERROR;
error_ = error;
@@ -428,8 +491,8 @@ bool HttpDecoder::ParsePriorityFrame(QuicDataReader* reader,
bool HttpDecoder::ParseSettingsFrame(QuicDataReader* reader,
SettingsFrame* frame) {
while (!reader->IsDoneReading()) {
- uint16_t id;
- if (!reader->ReadUInt16(&id)) {
+ uint64_t id;
+ if (!reader->ReadVarInt62(&id)) {
RaiseError(QUIC_INTERNAL_ERROR,
"Unable to read settings frame identifier");
return false;
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.h b/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.h
index 55de8adf3ac..a392962149e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.h
@@ -117,6 +117,7 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
QuicErrorCode error() const { return error_; }
const std::string& error_detail() const { return error_detail_; }
+ uint64_t current_frame_type() const { return current_frame_type_; }
private:
// Represents the current state of the parsing state machine.
@@ -128,15 +129,15 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
STATE_ERROR
};
- // Reads the length of a frame from |reader|. Sets error_ and error_detail_
- // if there are any errors.
- void ReadFrameLength(QuicDataReader* reader);
-
// Reads the type of a frame from |reader|. Sets error_ and error_detail_
// if there are any errors. Also calls OnDataFrameStart() or
// OnHeadersFrameStart() for appropriate frame types.
void ReadFrameType(QuicDataReader* reader);
+ // Reads the length of a frame from |reader|. Sets error_ and error_detail_
+ // if there are any errors.
+ void ReadFrameLength(QuicDataReader* reader);
+
// Reads the payload of the current frame from |reader| and processes it,
// possibly buffering the data or invoking the visitor.
void ReadFramePayload(QuicDataReader* reader);
@@ -152,9 +153,12 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
void BufferFramePayload(QuicDataReader* reader);
// Buffers any remaining frame length field from |reader| into
- // |length_buffer_|
+ // |length_buffer_|.
void BufferFrameLength(QuicDataReader* reader);
+ // Buffers any remaining frame type field from |reader| into |type_buffer_|.
+ void BufferFrameType(QuicDataReader* reader);
+
// Sets |error_| and |error_detail_| accordingly.
void RaiseError(QuicErrorCode error, std::string error_detail);
@@ -172,15 +176,19 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// Current state of the parsing.
HttpDecoderState state_;
// Type of the frame currently being parsed.
- uint8_t current_frame_type_;
+ uint64_t current_frame_type_;
// Size of the frame's length field.
- QuicByteCount current_length_field_size_;
+ QuicByteCount current_length_field_length_;
// Remaining length that's needed for the frame's length field.
QuicByteCount remaining_length_field_length_;
// Length of the payload of the frame currently being parsed.
QuicByteCount current_frame_length_;
// Remaining payload bytes to be parsed.
QuicByteCount remaining_frame_length_;
+ // Length of the frame's type field.
+ QuicByteCount current_type_field_length_;
+ // Remaining length that's needed for the frame's type field.
+ QuicByteCount remaining_type_field_length_;
// Last error.
QuicErrorCode error_;
// The issue which caused |error_|
@@ -188,7 +196,9 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// Remaining unparsed data.
std::string buffer_;
// Remaining unparsed length field data.
- std::string length_buffer_;
+ std::array<char, sizeof(uint64_t)> length_buffer_;
+ // Remaining unparsed type field data.
+ std::array<char, sizeof(uint64_t)> type_buffer_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_decoder_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/http_decoder_test.cc
index 7f0dcd44048..a4903b5db18 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
@@ -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_data_writer.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.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"
using testing::InSequence;
@@ -54,58 +55,106 @@ TEST_F(HttpDecoderTest, InitialState) {
}
TEST_F(HttpDecoderTest, ReservedFramesNoPayload) {
+ std::unique_ptr<char[]> input;
for (int n = 0; n < 8; ++n) {
const uint8_t type = 0xB + 0x1F * n;
- char input[] = {// length
- 0x00,
- // type
- type};
-
- EXPECT_EQ(2u, decoder_.ProcessInput(input, QUIC_ARRAYSIZE(input))) << n;
+ QuicByteCount total_length = QuicDataWriter::GetVarInt62Len(0x00) +
+ QuicDataWriter::GetVarInt62Len(type);
+ input = QuicMakeUnique<char[]>(total_length);
+ QuicDataWriter writer(total_length, input.get());
+ writer.WriteVarInt62(type);
+ writer.WriteVarInt62(0x00);
+
+ EXPECT_EQ(total_length, decoder_.ProcessInput(input.get(), total_length))
+ << n;
EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
ASSERT_EQ("", decoder_.error_detail());
+ EXPECT_EQ(type, decoder_.current_frame_type());
}
+ // Test on a arbitrary reserved frame with 2-byte type field by hard coding
+ // variable length integer.
+ char in[] = {// type 0xB + 0x1F*3
+ 0x40, 0x68,
+ // length
+ 0x00};
+ EXPECT_EQ(3u, decoder_.ProcessInput(in, QUIC_ARRAYSIZE(in)));
+ EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ ASSERT_EQ("", decoder_.error_detail());
+ EXPECT_EQ(0xB + 0x1F * 3u, decoder_.current_frame_type());
}
TEST_F(HttpDecoderTest, ReservedFramesSmallPayload) {
+ std::unique_ptr<char[]> input;
+ const uint8_t payload_size = 50;
+ std::string data(payload_size, 'a');
for (int n = 0; n < 8; ++n) {
const uint8_t type = 0xB + 0x1F * n;
- const uint8_t payload_size = 50;
- char input[payload_size + 2] = {// length
- payload_size,
- // type
- type};
-
- EXPECT_EQ(QUIC_ARRAYSIZE(input),
- decoder_.ProcessInput(input, QUIC_ARRAYSIZE(input)))
+ QuicByteCount total_length = QuicDataWriter::GetVarInt62Len(payload_size) +
+ QuicDataWriter::GetVarInt62Len(type) +
+ payload_size;
+ input = QuicMakeUnique<char[]>(total_length);
+ QuicDataWriter writer(total_length, input.get());
+ writer.WriteVarInt62(type);
+ writer.WriteVarInt62(payload_size);
+ writer.WriteStringPiece(data);
+ EXPECT_EQ(total_length, decoder_.ProcessInput(input.get(), total_length))
<< n;
EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
ASSERT_EQ("", decoder_.error_detail());
+ EXPECT_EQ(type, decoder_.current_frame_type());
}
+
+ // Test on a arbitrary reserved frame with 2-byte type field by hard coding
+ // variable length integer.
+ char in[payload_size + 3] = {// type 0xB + 0x1F*3
+ 0x40, 0x68,
+ // length
+ payload_size};
+ EXPECT_EQ(QUIC_ARRAYSIZE(in), decoder_.ProcessInput(in, QUIC_ARRAYSIZE(in)));
+ EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ ASSERT_EQ("", decoder_.error_detail());
+ EXPECT_EQ(0xB + 0x1F * 3u, decoder_.current_frame_type());
}
TEST_F(HttpDecoderTest, ReservedFramesLargePayload) {
+ std::unique_ptr<char[]> input;
+ const QuicByteCount payload_size = 256;
+ std::string data(payload_size, 'a');
for (int n = 0; n < 8; ++n) {
const uint8_t type = 0xB + 0x1F * n;
- const QuicByteCount payload_size = 256;
- char input[payload_size + 3] = {// length
- 0x40 + 0x01, 0x00,
- // type
- type};
-
- EXPECT_EQ(QUIC_ARRAYSIZE(input),
- decoder_.ProcessInput(input, QUIC_ARRAYSIZE(input)))
+ QuicByteCount total_length = QuicDataWriter::GetVarInt62Len(payload_size) +
+ QuicDataWriter::GetVarInt62Len(type) +
+ payload_size;
+ input = QuicMakeUnique<char[]>(total_length);
+ QuicDataWriter writer(total_length, input.get());
+ writer.WriteVarInt62(type);
+ writer.WriteVarInt62(payload_size);
+ writer.WriteStringPiece(data);
+
+ EXPECT_EQ(total_length, decoder_.ProcessInput(input.get(), total_length))
<< n;
EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
ASSERT_EQ("", decoder_.error_detail());
+ EXPECT_EQ(type, decoder_.current_frame_type());
}
+
+ // Test on a arbitrary reserved frame with 2-byte type field by hard coding
+ // variable length integer.
+ char in[payload_size + 4] = {// type 0xB + 0x1F*3
+ 0x40, 0x68,
+ // length
+ 0x40 + 0x01, 0x00};
+ EXPECT_EQ(QUIC_ARRAYSIZE(in), decoder_.ProcessInput(in, QUIC_ARRAYSIZE(in)));
+ EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ ASSERT_EQ("", decoder_.error_detail());
+ EXPECT_EQ(0xB + 0x1F * 3u, decoder_.current_frame_type());
}
TEST_F(HttpDecoderTest, CancelPush) {
- char input[] = {// length
- 0x1,
- // type (CANCEL_PUSH)
+ char input[] = {// type (CANCEL_PUSH)
0x03,
+ // length
+ 0x1,
// Push Id
0x01};
@@ -126,10 +175,10 @@ TEST_F(HttpDecoderTest, CancelPush) {
}
TEST_F(HttpDecoderTest, PushPromiseFrame) {
- char input[] = {// length
- 0x8,
- // type (PUSH_PROMISE)
+ char input[] = {// type (PUSH_PROMISE)
0x05,
+ // length
+ 0x8,
// Push Id
0x01,
// Header Block
@@ -163,10 +212,10 @@ TEST_F(HttpDecoderTest, PushPromiseFrame) {
}
TEST_F(HttpDecoderTest, MaxPushId) {
- char input[] = {// length
- 0x1,
- // type (MAX_PUSH_ID)
+ char input[] = {// type (MAX_PUSH_ID)
0x0D,
+ // length
+ 0x1,
// Push Id
0x01};
@@ -187,10 +236,10 @@ TEST_F(HttpDecoderTest, MaxPushId) {
}
TEST_F(HttpDecoderTest, DuplicatePush) {
- char input[] = {// length
- 0x1,
- // type (DUPLICATE_PUSH)
+ char input[] = {// type (DUPLICATE_PUSH)
0x0E,
+ // length
+ 0x1,
// Push Id
0x01};
// Process the full frame.
@@ -210,10 +259,10 @@ TEST_F(HttpDecoderTest, DuplicatePush) {
}
TEST_F(HttpDecoderTest, PriorityFrame) {
- char input[] = {// length
- 0x4,
- // type (PRIORITY)
+ char input[] = {// type (PRIORITY)
0x2,
+ // length
+ 0x4,
// request stream, request stream, exclusive
0x01,
// prioritized_element_id
@@ -252,29 +301,32 @@ TEST_F(HttpDecoderTest, PriorityFrame) {
TEST_F(HttpDecoderTest, SettingsFrame) {
// clang-format off
char input[] = {
- // length
- 0x06,
// type (SETTINGS)
0x04,
+ // length
+ 0x07,
// identifier (SETTINGS_NUM_PLACEHOLDERS)
- 0x00,
0x03,
// content
0x02,
// identifier (SETTINGS_MAX_HEADER_LIST_SIZE)
- 0x00,
0x06,
// content
0x05,
- };
+ // identifier (256 in variable length integer)
+ 0x40 + 0x01,
+ 0x00,
+ // content
+ 0x04};
// clang-format on
SettingsFrame frame;
frame.values[3] = 2;
frame.values[6] = 5;
+ frame.values[256] = 4;
// Process the full frame.
- EXPECT_CALL(visitor_, OnSettingsFrameStart(Http3FrameLengths(2, 6)));
+ EXPECT_CALL(visitor_, OnSettingsFrameStart(Http3FrameLengths(2, 7)));
EXPECT_CALL(visitor_, OnSettingsFrame(frame));
EXPECT_EQ(QUIC_ARRAYSIZE(input),
decoder_.ProcessInput(input, QUIC_ARRAYSIZE(input)));
@@ -282,7 +334,7 @@ TEST_F(HttpDecoderTest, SettingsFrame) {
EXPECT_EQ("", decoder_.error_detail());
// Process the frame incremently.
- EXPECT_CALL(visitor_, OnSettingsFrameStart(Http3FrameLengths(2, 6)));
+ EXPECT_CALL(visitor_, OnSettingsFrameStart(Http3FrameLengths(2, 7)));
EXPECT_CALL(visitor_, OnSettingsFrame(frame));
for (char c : input) {
EXPECT_EQ(1u, decoder_.ProcessInput(&c, 1));
@@ -292,10 +344,10 @@ TEST_F(HttpDecoderTest, SettingsFrame) {
}
TEST_F(HttpDecoderTest, DataFrame) {
- char input[] = {// length
- 0x05,
- // type (DATA)
+ char input[] = {// type (DATA)
0x00,
+ // length
+ 0x05,
// data
'D', 'a', 't', 'a', '!'};
@@ -352,11 +404,32 @@ TEST_F(HttpDecoderTest, FrameHeaderPartialDelivery) {
EXPECT_EQ("", decoder_.error_detail());
}
+TEST_F(HttpDecoderTest, PartialDeliveryOfLargeFrameType) {
+ // Use a reserved type that's more than 1 byte in VarInt62.
+ const uint8_t type = 0xB + 0x1F * 3;
+ std::unique_ptr<char[]> input;
+ QuicByteCount total_length = QuicDataWriter::GetVarInt62Len(0x00) +
+ QuicDataWriter::GetVarInt62Len(type);
+ input.reset(new char[total_length]);
+ QuicDataWriter writer(total_length, input.get());
+ writer.WriteVarInt62(type);
+ writer.WriteVarInt62(0x00);
+
+ auto raw_input = input.get();
+ for (uint64_t i = 0; i < total_length; ++i) {
+ char c = raw_input[i];
+ EXPECT_EQ(1u, decoder_.ProcessInput(&c, 1));
+ }
+ EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_EQ("", decoder_.error_detail());
+ EXPECT_EQ(type, decoder_.current_frame_type());
+}
+
TEST_F(HttpDecoderTest, GoAway) {
- char input[] = {// length
- 0x1,
- // type (GOAWAY)
+ char input[] = {// type (GOAWAY)
0x07,
+ // length
+ 0x1,
// StreamId
0x01};
@@ -377,10 +450,10 @@ TEST_F(HttpDecoderTest, GoAway) {
}
TEST_F(HttpDecoderTest, HeadersFrame) {
- char input[] = {// length
- 0x07,
- // type (HEADERS)
+ char input[] = {// type (HEADERS)
0x01,
+ // length
+ 0x07,
// headers
'H', 'e', 'a', 'd', 'e', 'r', 's'};
@@ -412,8 +485,8 @@ TEST_F(HttpDecoderTest, HeadersFrame) {
}
TEST_F(HttpDecoderTest, EmptyDataFrame) {
- char input[] = {0x00, // length
- 0x00}; // type (DATA)
+ char input[] = {0x00, // type (DATA)
+ 0x00}; // length
// Process the full frame.
InSequence s;
@@ -435,8 +508,8 @@ TEST_F(HttpDecoderTest, EmptyDataFrame) {
}
TEST_F(HttpDecoderTest, EmptyHeadersFrame) {
- char input[] = {0x00, // length
- 0x01}; // type (HEADERS)
+ char input[] = {0x01, // type (HEADERS)
+ 0x00}; // length
// Process the full frame.
InSequence s;
@@ -458,8 +531,8 @@ TEST_F(HttpDecoderTest, EmptyHeadersFrame) {
}
TEST_F(HttpDecoderTest, PushPromiseFrameNoHeaders) {
- char input[] = {0x01, // length
- 0x05, // type (PUSH_PROMISE)
+ char input[] = {0x05, // type (PUSH_PROMISE)
+ 0x01, // length
0x01}; // Push Id
// Process the full frame.
@@ -482,8 +555,8 @@ TEST_F(HttpDecoderTest, PushPromiseFrameNoHeaders) {
}
TEST_F(HttpDecoderTest, MalformedFrameWithOverlyLargePayload) {
- char input[] = {0x10, // length
- 0x03, // type (CANCEL_PUSH)
+ char input[] = {0x03, // type (CANCEL_PUSH)
+ 0x10, // length
0x15}; // malformed payload
// Process the full frame.
EXPECT_CALL(visitor_, OnError(&decoder_));
@@ -495,10 +568,10 @@ TEST_F(HttpDecoderTest, MalformedFrameWithOverlyLargePayload) {
TEST_F(HttpDecoderTest, MalformedSettingsFrame) {
char input[30];
QuicDataWriter writer(30, input);
- // Write length.
- writer.WriteVarInt62(2048 * 1024);
// Write type SETTINGS.
writer.WriteUInt8(0x04);
+ // Write length.
+ writer.WriteVarInt62(2048 * 1024);
writer.WriteStringPiece("Malformed payload");
EXPECT_CALL(visitor_, OnError(&decoder_));
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 beeef9b6abb..01f9c10bea0 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
@@ -44,14 +44,10 @@ uint8_t SetPriorityFields(uint8_t num,
}
}
-// Length of the type field of a frame.
-static const size_t kFrameTypeLength = 1;
// Length of the weight field of a priority frame.
static const size_t kPriorityWeightLength = 1;
// Length of a priority frame's first byte.
static const size_t kPriorityFirstByteLength = 1;
-// Length of a key in the map of a settings frame.
-static const size_t kSettingsMapKeyLength = 2;
} // namespace
@@ -63,8 +59,9 @@ QuicByteCount HttpEncoder::SerializeDataFrameHeader(
QuicByteCount payload_length,
std::unique_ptr<char[]>* output) {
DCHECK_NE(0u, payload_length);
- QuicByteCount header_length =
- QuicDataWriter::GetVarInt62Len(payload_length) + kFrameTypeLength;
+ QuicByteCount header_length = QuicDataWriter::GetVarInt62Len(payload_length) +
+ QuicDataWriter::GetVarInt62Len(
+ static_cast<uint64_t>(HttpFrameType::DATA));
output->reset(new char[header_length]);
QuicDataWriter writer(header_length, output->get());
@@ -72,6 +69,8 @@ QuicByteCount HttpEncoder::SerializeDataFrameHeader(
if (WriteFrameHeader(payload_length, HttpFrameType::DATA, &writer)) {
return header_length;
}
+ QUIC_DLOG(ERROR)
+ << "Http encoder failed when attempting to serialize data frame header.";
return 0;
}
@@ -80,7 +79,9 @@ QuicByteCount HttpEncoder::SerializeHeadersFrameHeader(
std::unique_ptr<char[]>* output) {
DCHECK_NE(0u, payload_length);
QuicByteCount header_length =
- QuicDataWriter::GetVarInt62Len(payload_length) + kFrameTypeLength;
+ QuicDataWriter::GetVarInt62Len(payload_length) +
+ QuicDataWriter::GetVarInt62Len(
+ static_cast<uint64_t>(HttpFrameType::HEADERS));
output->reset(new char[header_length]);
QuicDataWriter writer(header_length, output->get());
@@ -88,6 +89,9 @@ QuicByteCount HttpEncoder::SerializeHeadersFrameHeader(
if (WriteFrameHeader(payload_length, HttpFrameType::HEADERS, &writer)) {
return header_length;
}
+ QUIC_DLOG(ERROR)
+ << "Http encoder failed when attempting to serialize headers "
+ "frame header.";
return 0;
}
@@ -99,12 +103,15 @@ QuicByteCount HttpEncoder::SerializePriorityFrame(
QuicDataWriter::GetVarInt62Len(priority.prioritized_element_id) +
QuicDataWriter::GetVarInt62Len(priority.element_dependency_id) +
kPriorityWeightLength;
- QuicByteCount total_length = GetTotalLength(payload_length);
+ QuicByteCount total_length =
+ GetTotalLength(payload_length, HttpFrameType::PRIORITY);
output->reset(new char[total_length]);
QuicDataWriter writer(total_length, output->get());
if (!WriteFrameHeader(payload_length, HttpFrameType::PRIORITY, &writer)) {
+ QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
+ "priority frame header.";
return 0;
}
@@ -122,6 +129,8 @@ QuicByteCount HttpEncoder::SerializePriorityFrame(
writer.WriteUInt8(priority.weight)) {
return total_length;
}
+ QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
+ "priority frame payload.";
return 0;
}
@@ -130,7 +139,8 @@ QuicByteCount HttpEncoder::SerializeCancelPushFrame(
std::unique_ptr<char[]>* output) {
QuicByteCount payload_length =
QuicDataWriter::GetVarInt62Len(cancel_push.push_id);
- QuicByteCount total_length = GetTotalLength(payload_length);
+ QuicByteCount total_length =
+ GetTotalLength(payload_length, HttpFrameType::CANCEL_PUSH);
output->reset(new char[total_length]);
QuicDataWriter writer(total_length, output->get());
@@ -139,30 +149,37 @@ QuicByteCount HttpEncoder::SerializeCancelPushFrame(
writer.WriteVarInt62(cancel_push.push_id)) {
return total_length;
}
+ QUIC_DLOG(ERROR)
+ << "Http encoder failed when attempting to serialize cancel push frame.";
return 0;
}
QuicByteCount HttpEncoder::SerializeSettingsFrame(
const SettingsFrame& settings,
std::unique_ptr<char[]>* output) {
- // Calculate the key sizes.
- QuicByteCount payload_length = settings.values.size() * kSettingsMapKeyLength;
- // Calculate the value sizes.
+ QuicByteCount payload_length = 0;
+ // Calculate the payload length.
for (auto it = settings.values.begin(); it != settings.values.end(); ++it) {
+ payload_length += QuicDataWriter::GetVarInt62Len(it->first);
payload_length += QuicDataWriter::GetVarInt62Len(it->second);
}
- QuicByteCount total_length = GetTotalLength(payload_length);
+ QuicByteCount total_length =
+ GetTotalLength(payload_length, HttpFrameType::SETTINGS);
output->reset(new char[total_length]);
QuicDataWriter writer(total_length, output->get());
if (!WriteFrameHeader(payload_length, HttpFrameType::SETTINGS, &writer)) {
+ QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
+ "settings frame header.";
return 0;
}
for (auto it = settings.values.begin(); it != settings.values.end(); ++it) {
- if (!writer.WriteUInt16(it->first) || !writer.WriteVarInt62(it->second)) {
+ if (!writer.WriteVarInt62(it->first) || !writer.WriteVarInt62(it->second)) {
+ QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
+ "settings frame payload.";
return 0;
}
}
@@ -178,7 +195,9 @@ QuicByteCount HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
push_promise.headers.length();
// GetTotalLength() is not used because headers will not be serialized.
QuicByteCount total_length =
- QuicDataWriter::GetVarInt62Len(payload_length) + kFrameTypeLength +
+ QuicDataWriter::GetVarInt62Len(payload_length) +
+ QuicDataWriter::GetVarInt62Len(
+ static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE)) +
QuicDataWriter::GetVarInt62Len(push_promise.push_id);
output->reset(new char[total_length]);
@@ -188,6 +207,8 @@ QuicByteCount HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
writer.WriteVarInt62(push_promise.push_id)) {
return total_length;
}
+ QUIC_DLOG(ERROR)
+ << "Http encoder failed when attempting to serialize push promise frame.";
return 0;
}
@@ -196,7 +217,8 @@ QuicByteCount HttpEncoder::SerializeGoAwayFrame(
std::unique_ptr<char[]>* output) {
QuicByteCount payload_length =
QuicDataWriter::GetVarInt62Len(goaway.stream_id);
- QuicByteCount total_length = GetTotalLength(payload_length);
+ QuicByteCount total_length =
+ GetTotalLength(payload_length, HttpFrameType::GOAWAY);
output->reset(new char[total_length]);
QuicDataWriter writer(total_length, output->get());
@@ -205,6 +227,8 @@ QuicByteCount HttpEncoder::SerializeGoAwayFrame(
writer.WriteVarInt62(goaway.stream_id)) {
return total_length;
}
+ QUIC_DLOG(ERROR)
+ << "Http encoder failed when attempting to serialize goaway frame.";
return 0;
}
@@ -213,7 +237,8 @@ QuicByteCount HttpEncoder::SerializeMaxPushIdFrame(
std::unique_ptr<char[]>* output) {
QuicByteCount payload_length =
QuicDataWriter::GetVarInt62Len(max_push_id.push_id);
- QuicByteCount total_length = GetTotalLength(payload_length);
+ QuicByteCount total_length =
+ GetTotalLength(payload_length, HttpFrameType::MAX_PUSH_ID);
output->reset(new char[total_length]);
QuicDataWriter writer(total_length, output->get());
@@ -222,6 +247,8 @@ QuicByteCount HttpEncoder::SerializeMaxPushIdFrame(
writer.WriteVarInt62(max_push_id.push_id)) {
return total_length;
}
+ QUIC_DLOG(ERROR)
+ << "Http encoder failed when attempting to serialize max push id frame.";
return 0;
}
@@ -230,7 +257,8 @@ QuicByteCount HttpEncoder::SerializeDuplicatePushFrame(
std::unique_ptr<char[]>* output) {
QuicByteCount payload_length =
QuicDataWriter::GetVarInt62Len(duplicate_push.push_id);
- QuicByteCount total_length = GetTotalLength(payload_length);
+ QuicByteCount total_length =
+ GetTotalLength(payload_length, HttpFrameType::DUPLICATE_PUSH);
output->reset(new char[total_length]);
QuicDataWriter writer(total_length, output->get());
@@ -240,18 +268,22 @@ QuicByteCount HttpEncoder::SerializeDuplicatePushFrame(
writer.WriteVarInt62(duplicate_push.push_id)) {
return total_length;
}
+ QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
+ "duplicate push frame.";
return 0;
}
bool HttpEncoder::WriteFrameHeader(QuicByteCount length,
HttpFrameType type,
QuicDataWriter* writer) {
- return writer->WriteVarInt62(length) &&
- writer->WriteUInt8(static_cast<uint8_t>(type));
+ return writer->WriteVarInt62(static_cast<uint64_t>(type)) &&
+ writer->WriteVarInt62(length);
}
-QuicByteCount HttpEncoder::GetTotalLength(QuicByteCount payload_length) {
- return QuicDataWriter::GetVarInt62Len(payload_length) + kFrameTypeLength +
+QuicByteCount HttpEncoder::GetTotalLength(QuicByteCount payload_length,
+ HttpFrameType type) {
+ return QuicDataWriter::GetVarInt62Len(payload_length) +
+ QuicDataWriter::GetVarInt62Len(static_cast<uint64_t>(type)) +
payload_length;
}
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 f04e6e40700..6691e315700 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
@@ -77,7 +77,8 @@ class QUIC_EXPORT_PRIVATE HttpEncoder {
HttpFrameType type,
QuicDataWriter* writer);
- QuicByteCount GetTotalLength(QuicByteCount payload_length);
+ QuicByteCount GetTotalLength(QuicByteCount payload_length,
+ HttpFrameType type);
};
} // 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 154d7688e8d..1ff5d8984c0 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
@@ -22,10 +22,10 @@ TEST_F(HttpEncoderTest, SerializeDataFrameHeader) {
std::unique_ptr<char[]> buffer;
uint64_t length =
encoder_.SerializeDataFrameHeader(/* payload_length = */ 5, &buffer);
- char output[] = {// length
- 0x05,
- // type (DATA)
- 0x00};
+ char output[] = {// type (DATA)
+ 0x00,
+ // length
+ 0x05};
EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
CompareCharArraysWithHexError("DATA", buffer.get(), length, output,
QUIC_ARRAYSIZE(output));
@@ -35,10 +35,10 @@ TEST_F(HttpEncoderTest, SerializeHeadersFrameHeader) {
std::unique_ptr<char[]> buffer;
uint64_t length =
encoder_.SerializeHeadersFrameHeader(/* payload_length = */ 7, &buffer);
- char output[] = {// length
- 0x07,
- // type (HEADERS)
- 0x01};
+ char output[] = {// type (HEADERS)
+ 0x01,
+ // length
+ 0x07};
EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
CompareCharArraysWithHexError("HEADERS", buffer.get(), length, output,
QUIC_ARRAYSIZE(output));
@@ -52,10 +52,10 @@ TEST_F(HttpEncoderTest, SerializePriorityFrame) {
priority.prioritized_element_id = 0x03;
priority.element_dependency_id = 0x04;
priority.weight = 0xFF;
- char output[] = {// length
- 0x4,
- // type (PRIORITY)
+ char output[] = {// type (PRIORITY)
0x2,
+ // length
+ 0x4,
// request stream, request stream, exclusive
0x01,
// prioritized_element_id
@@ -75,10 +75,10 @@ TEST_F(HttpEncoderTest, SerializePriorityFrame) {
TEST_F(HttpEncoderTest, SerializeCancelPushFrame) {
CancelPushFrame cancel_push;
cancel_push.push_id = 0x01;
- char output[] = {// length
- 0x1,
- // type (CANCEL_PUSH)
+ char output[] = {// type (CANCEL_PUSH)
0x03,
+ // length
+ 0x1,
// Push Id
0x01};
std::unique_ptr<char[]> buffer;
@@ -92,22 +92,23 @@ TEST_F(HttpEncoderTest, SerializeSettingsFrame) {
SettingsFrame settings;
settings.values[3] = 2;
settings.values[6] = 5;
- char output[] = {
- // length
- 0x06,
- // type (SETTINGS)
- 0x04,
- // identifier (SETTINGS_NUM_PLACEHOLDERS)
- 0x00,
- 0x03,
- // content
- 0x02,
- // identifier (SETTINGS_MAX_HEADER_LIST_SIZE)
- 0x00,
- 0x06,
- // content
- 0x05,
- };
+ settings.values[256] = 4;
+ char output[] = {// type (SETTINGS)
+ 0x04,
+ // length
+ 0x07,
+ // identifier (SETTINGS_NUM_PLACEHOLDERS)
+ 0x03,
+ // content
+ 0x02,
+ // identifier (SETTINGS_MAX_HEADER_LIST_SIZE)
+ 0x06,
+ // content
+ 0x05,
+ // identifier (256 in variable length integer)
+ 0x40 + 0x01, 0x00,
+ // content
+ 0x04};
std::unique_ptr<char[]> buffer;
uint64_t length = encoder_.SerializeSettingsFrame(settings, &buffer);
EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
@@ -119,10 +120,10 @@ TEST_F(HttpEncoderTest, SerializePushPromiseFrameWithOnlyPushId) {
PushPromiseFrame push_promise;
push_promise.push_id = 0x01;
push_promise.headers = "Headers";
- char output[] = {// length
- 0x8,
- // type (PUSH_PROMISE)
+ char output[] = {// type (PUSH_PROMISE)
0x05,
+ // length
+ 0x8,
// Push Id
0x01};
std::unique_ptr<char[]> buffer;
@@ -136,10 +137,10 @@ TEST_F(HttpEncoderTest, SerializePushPromiseFrameWithOnlyPushId) {
TEST_F(HttpEncoderTest, SerializeGoAwayFrame) {
GoAwayFrame goaway;
goaway.stream_id = 0x1;
- char output[] = {// length
- 0x1,
- // type (GOAWAY)
+ char output[] = {// type (GOAWAY)
0x07,
+ // length
+ 0x1,
// StreamId
0x01};
std::unique_ptr<char[]> buffer;
@@ -152,10 +153,10 @@ TEST_F(HttpEncoderTest, SerializeGoAwayFrame) {
TEST_F(HttpEncoderTest, SerializeMaxPushIdFrame) {
MaxPushIdFrame max_push_id;
max_push_id.push_id = 0x1;
- char output[] = {// length
- 0x1,
- // type (MAX_PUSH_ID)
+ char output[] = {// type (MAX_PUSH_ID)
0x0D,
+ // length
+ 0x1,
// Push Id
0x01};
std::unique_ptr<char[]> buffer;
@@ -168,10 +169,10 @@ TEST_F(HttpEncoderTest, SerializeMaxPushIdFrame) {
TEST_F(HttpEncoderTest, SerializeDuplicatePushFrame) {
DuplicatePushFrame duplicate_push;
duplicate_push.push_id = 0x1;
- char output[] = {// length
- 0x1,
- // type (DUPLICATE_PUSH)
+ char output[] = {// type (DUPLICATE_PUSH)
0x0E,
+ // length
+ 0x1,
// Push Id
0x01};
std::unique_ptr<char[]> buffer;
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 ea115571fc2..f1aa7ff81f2 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
@@ -90,8 +90,7 @@ struct CancelPushFrame {
// affect how endpoints communicate, such as preferences and constraints
// on peer behavior
-using SettingsId = uint16_t;
-using SettingsMap = std::map<SettingsId, uint64_t>;
+using SettingsMap = std::map<uint64_t, uint64_t>;
struct SettingsFrame {
SettingsMap values;
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 2f669df22c3..a41235fbc31 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
@@ -370,6 +370,10 @@ TEST_P(QuicHeadersStreamTest, StreamId) {
}
TEST_P(QuicHeadersStreamTest, WriteHeaders) {
+ if (VersionUsesQpack(transport_version())) {
+ return;
+ }
+
for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
stream_id += next_stream_id_) {
for (bool fin : {false, true}) {
@@ -421,6 +425,10 @@ TEST_P(QuicHeadersStreamTest, WritePushPromises) {
}
TEST_P(QuicHeadersStreamTest, ProcessRawData) {
+ if (VersionUsesQpack(transport_version())) {
+ return;
+ }
+
for (QuicStreamId stream_id = client_id_1_; stream_id < client_id_3_;
stream_id += next_stream_id_) {
for (bool fin : {false, true}) {
@@ -536,6 +544,10 @@ TEST_P(QuicHeadersStreamTest, ProcessPushPromiseDisabledSetting) {
}
TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) {
+ if (VersionUsesQpack(transport_version())) {
+ return;
+ }
+
QuicSpdySessionPeer::SetMaxUncompressedHeaderBytes(&session_, 256 * 1024);
// We want to create a frame that is more than the SPDY Framer's max control
// frame size, which is 16K, but less than the HPACK decoders max decode
@@ -710,6 +722,10 @@ TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) {
}
TEST_P(QuicHeadersStreamTest, HpackDecoderDebugVisitor) {
+ if (VersionUsesQpack(transport_version())) {
+ return;
+ }
+
auto hpack_decoder_visitor =
QuicMakeUnique<StrictMock<MockQuicHpackDebugVisitor>>();
{
@@ -762,6 +778,10 @@ TEST_P(QuicHeadersStreamTest, HpackDecoderDebugVisitor) {
}
TEST_P(QuicHeadersStreamTest, HpackEncoderDebugVisitor) {
+ if (VersionUsesQpack(transport_version())) {
+ return;
+ }
+
auto hpack_encoder_visitor =
QuicMakeUnique<StrictMock<MockQuicHpackDebugVisitor>>();
if (perspective() == Perspective::IS_SERVER) {
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 4c625c0df04..b53d4e9e1a2 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
@@ -111,6 +111,14 @@ QuicReceiveControlStream::QuicReceiveControlStream(QuicStreamId id,
sequencer()->set_level_triggered(true);
}
+QuicReceiveControlStream::QuicReceiveControlStream(PendingStream pending)
+ : QuicStream(std::move(pending), READ_UNIDIRECTIONAL, /*is_static=*/true),
+ received_settings_length_(0),
+ http_decoder_visitor_(new HttpDecoderVisitor(this)) {
+ decoder_.set_visitor(http_decoder_visitor_.get());
+ sequencer()->set_level_triggered(true);
+}
+
QuicReceiveControlStream::~QuicReceiveControlStream() {}
void QuicReceiveControlStream::OnStreamReset(const QuicRstStreamFrame& frame) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h
index 1805d6ccc08..61e4299e118 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h
@@ -20,6 +20,9 @@ class QUIC_EXPORT_PRIVATE QuicReceiveControlStream : public QuicStream {
// |session| can't be nullptr, and the ownership is not passed. The stream can
// only be accessed through the session.
explicit QuicReceiveControlStream(QuicStreamId id, QuicSpdySession* session);
+ // Construct control stream from pending stream, the |pending| object will no
+ // longer exist after the construction.
+ explicit QuicReceiveControlStream(PendingStream pending);
QuicReceiveControlStream(const QuicReceiveControlStream&) = delete;
QuicReceiveControlStream& operator=(const QuicReceiveControlStream&) = delete;
~QuicReceiveControlStream() 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 1861d17495c..73e8fedabd2 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
@@ -50,7 +50,7 @@ std::vector<TestParams> GetTestParams() {
std::vector<TestParams> params;
ParsedQuicVersionVector all_supported_versions = AllSupportedVersions();
for (const auto& version : AllSupportedVersions()) {
- if (!VersionHasControlStreams(version.transport_version)) {
+ if (!VersionHasStreamType(version.transport_version)) {
continue;
}
for (Perspective p : {Perspective::IS_SERVER, Perspective::IS_CLIENT}) {
@@ -100,6 +100,7 @@ INSTANTIATE_TEST_SUITE_P(Tests,
::testing::ValuesIn(GetTestParams()));
TEST_P(QuicReceiveControlStreamTest, ResetControlStream) {
+ EXPECT_TRUE(receive_control_stream_->is_static());
QuicRstStreamFrame rst_frame(kInvalidControlFrameId,
receive_control_stream_->id(),
QUIC_STREAM_CANCELLED, 1234);
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 980cdf54133..a015c5fae30 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
@@ -50,7 +50,7 @@ std::vector<TestParams> GetTestParams() {
std::vector<TestParams> params;
ParsedQuicVersionVector all_supported_versions = AllSupportedVersions();
for (const auto& version : AllSupportedVersions()) {
- if (!VersionHasControlStreams(version.transport_version)) {
+ if (!VersionHasStreamType(version.transport_version)) {
continue;
}
for (Perspective p : {Perspective::IS_SERVER, Perspective::IS_CLIENT}) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.cc
index 5cdb2c46451..683793dc838 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.cc
@@ -227,8 +227,8 @@ bool QuicServerSessionBase::ShouldCreateOutgoingBidirectionalStream() {
connection()->transport_version() != QUIC_VERSION_99) {
if (GetNumOpenOutgoingStreams() >=
stream_id_manager().max_open_outgoing_streams()) {
- VLOG(1) << "No more streams should be created. "
- << "Already " << GetNumOpenOutgoingStreams() << " open.";
+ QUIC_VLOG(1) << "No more streams should be created. "
+ << "Already " << GetNumOpenOutgoingStreams() << " open.";
return false;
}
}
@@ -251,8 +251,8 @@ bool QuicServerSessionBase::ShouldCreateOutgoingUnidirectionalStream() {
connection()->transport_version() != QUIC_VERSION_99) {
if (GetNumOpenOutgoingStreams() >=
stream_id_manager().max_open_outgoing_streams()) {
- VLOG(1) << "No more streams should be created. "
- << "Already " << GetNumOpenOutgoingStreams() << " open.";
+ QUIC_VLOG(1) << "No more streams should be created. "
+ << "Already " << GetNumOpenOutgoingStreams() << " open.";
return false;
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc
index e5945e1c9d6..94ebb67a0bf 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
@@ -105,10 +105,8 @@ class TestServerSession : public QuicServerSessionBase {
QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache) override {
- return new QuicCryptoServerStream(
- crypto_config, compressed_certs_cache,
- GetQuicReloadableFlag(enable_quic_stateless_reject_support), this,
- stream_helper());
+ return new QuicCryptoServerStream(crypto_config, compressed_certs_cache,
+ this, stream_helper());
}
private:
@@ -131,9 +129,12 @@ class QuicServerSessionBaseTest : public QuicTestWithParam<ParsedQuicVersion> {
TlsServerHandshaker::CreateSslCtx()),
compressed_certs_cache_(
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {
- config_.SetMaxIncomingDynamicStreamsToSend(kMaxStreamsForTest);
- QuicConfigPeer::SetReceivedMaxIncomingDynamicStreams(&config_,
- kMaxStreamsForTest);
+ config_.SetMaxIncomingBidirectionalStreamsToSend(kMaxStreamsForTest);
+ config_.SetMaxIncomingUnidirectionalStreamsToSend(kMaxStreamsForTest);
+ QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams(
+ &config_, kMaxStreamsForTest);
+ QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
+ &config_, kMaxStreamsForTest);
config_.SetInitialStreamFlowControlWindowToSend(
kInitialStreamFlowControlWindowForTest);
config_.SetInitialSessionFlowControlWindowToSend(
@@ -460,12 +461,10 @@ class MockQuicCryptoServerStream : public QuicCryptoServerStream {
QuicCompressedCertsCache* compressed_certs_cache,
QuicServerSessionBase* session,
QuicCryptoServerStream::Helper* helper)
- : QuicCryptoServerStream(
- crypto_config,
- compressed_certs_cache,
- GetQuicReloadableFlag(enable_quic_stateless_reject_support),
- session,
- helper) {}
+ : QuicCryptoServerStream(crypto_config,
+ compressed_certs_cache,
+ session,
+ helper) {}
MockQuicCryptoServerStream(const MockQuicCryptoServerStream&) = delete;
MockQuicCryptoServerStream& operator=(const MockQuicCryptoServerStream&) =
delete;
@@ -693,13 +692,11 @@ TEST_P(StreamMemberLifetimeTest, Basic) {
// TODO(nharper): Fix this test so it doesn't rely on QUIC crypto.
return;
}
- SetQuicReloadableFlag(enable_quic_stateless_reject_support, true);
- SetQuicReloadableFlag(quic_use_cheap_stateless_rejects, true);
const QuicClock* clock = helper_.GetClock();
CryptoHandshakeMessage chlo = crypto_test_utils::GenerateDefaultInchoateCHLO(
clock, GetParam().transport_version, &crypto_config_);
- chlo.SetVector(kCOPT, QuicTagVector{kSREJ});
+ chlo.SetVector(kCOPT, QuicTagVector{kREJ});
std::vector<ParsedQuicVersion> packet_version_list = {GetParam()};
std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
TestConnectionId(1), EmptyQuicConnectionId(), true, false, 1,
@@ -708,8 +705,6 @@ TEST_P(StreamMemberLifetimeTest, Basic) {
EXPECT_CALL(stream_helper_, CanAcceptClientHello(_, _, _, _, _))
.WillOnce(testing::Return(true));
- EXPECT_CALL(stream_helper_, GenerateConnectionIdForReject(_, _))
- .WillOnce(testing::Return(TestConnectionId(12345)));
// Set the current packet
QuicConnectionPeer::SetCurrentPacket(session_->connection(),
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 d388d2e1931..93f68808d42 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
@@ -64,7 +64,7 @@ void QuicSpdyClientSessionBase::OnPromiseHeaderList(
QuicStreamId promised_stream_id,
size_t frame_len,
const QuicHeaderList& header_list) {
- if (QuicContainsKey(static_streams(), stream_id)) {
+ if (IsStaticStream(stream_id)) {
connection()->CloseConnection(
QUIC_INVALID_HEADERS_STREAM_DATA, "stream is static",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
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 9a99ca7bfc8..ea9e0585967 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
@@ -8,7 +8,8 @@
#include <string>
#include <vector>
-#include "net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter.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/http/quic_spdy_client_stream.h"
#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
@@ -114,13 +115,13 @@ class QuicSpdyClientSessionTest : public QuicTestWithParam<ParsedQuicVersion> {
connection_->transport_version(), 0);
}
- // The function ensures that A) the max stream id frames get properly deleted
+ // The function ensures that A) the MAX_STREAMS frames get properly deleted
// (since the test uses a 'did we leak memory' check ... if we just lose the
// frame, the test fails) and B) returns true (instead of the default, false)
// which ensures that the rest of the system thinks that the frame actually
// was transmitted.
- bool ClearMaxStreamIdControlFrame(const QuicFrame& frame) {
- if (frame.type == MAX_STREAM_ID_FRAME) {
+ bool ClearMaxStreamsControlFrame(const QuicFrame& frame) {
+ if (frame.type == MAX_STREAMS_FRAME) {
DeleteFrame(&const_cast<QuicFrame&>(frame));
return true;
}
@@ -128,8 +129,8 @@ class QuicSpdyClientSessionTest : public QuicTestWithParam<ParsedQuicVersion> {
}
public:
- bool ClearStreamIdBlockedControlFrame(const QuicFrame& frame) {
- if (frame.type == STREAM_ID_BLOCKED_FRAME) {
+ bool ClearStreamsBlockedControlFrame(const QuicFrame& frame) {
+ if (frame.type == STREAMS_BLOCKED_FRAME) {
DeleteFrame(&const_cast<QuicFrame&>(frame));
return true;
}
@@ -146,16 +147,23 @@ class QuicSpdyClientSessionTest : public QuicTestWithParam<ParsedQuicVersion> {
EXPECT_CALL(*connection_, SendControlFrame(_))
.Times(testing::AnyNumber())
.WillRepeatedly(Invoke(
- this, &QuicSpdyClientSessionTest::ClearMaxStreamIdControlFrame));
+ this, &QuicSpdyClientSessionTest::ClearMaxStreamsControlFrame));
}
session_->CryptoConnect();
QuicCryptoClientStream* stream = static_cast<QuicCryptoClientStream*>(
session_->GetMutableCryptoStream());
- crypto_test_utils::FakeServerOptions options;
QuicConfig config = DefaultQuicConfig();
- config.SetMaxIncomingDynamicStreamsToSend(server_max_incoming_streams);
+ if (connection_->transport_version() == QUIC_VERSION_99) {
+ config.SetMaxIncomingUnidirectionalStreamsToSend(
+ server_max_incoming_streams);
+ config.SetMaxIncomingBidirectionalStreamsToSend(
+ server_max_incoming_streams);
+ } else {
+ config.SetMaxIncomingBidirectionalStreamsToSend(
+ server_max_incoming_streams);
+ }
crypto_test_utils::HandshakeWithFakeServer(
- &config, &helper_, &alarm_factory_, connection_, stream, options);
+ &config, &helper_, &alarm_factory_, connection_, stream);
}
QuicCryptoClientConfig crypto_config_;
@@ -199,16 +207,14 @@ TEST_P(QuicSpdyClientSessionTest, NoEncryptionAfterInitialEncryption) {
EXPECT_TRUE(session_->IsEncryptionEstablished());
QuicSpdyClientStream* stream = session_->CreateOutgoingBidirectionalStream();
ASSERT_TRUE(stream != nullptr);
- if (!QuicVersionUsesCryptoFrames(GetParam().transport_version)) {
- EXPECT_NE(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- stream->id());
- }
+ EXPECT_FALSE(QuicUtils::IsCryptoStreamId(connection_->transport_version(),
+ stream->id()));
// Process an "inchoate" REJ from the server which will cause
// an inchoate CHLO to be sent and will leave the encryption level
// at NONE.
CryptoHandshakeMessage rej;
- crypto_test_utils::FillInDummyReject(&rej, /* stateless */ false);
+ crypto_test_utils::FillInDummyReject(&rej);
EXPECT_TRUE(session_->IsEncryptionEstablished());
crypto_test_utils::SendHandshakeMessageToStream(
session_->GetMutableCryptoStream(), rej, Perspective::IS_CLIENT);
@@ -244,12 +250,24 @@ TEST_P(QuicSpdyClientSessionTest, MaxNumStreamsWithNoFinOrRst) {
EXPECT_FALSE(session_->CreateOutgoingBidirectionalStream());
// Close the stream, but without having received a FIN or a RST_STREAM
- // or MAX_STREAM_ID (V99) and check that a new one can not be created.
+ // or MAX_STREAMS (V99) and check that a new one can not be created.
session_->CloseStream(stream->id());
EXPECT_EQ(1u, session_->GetNumOpenOutgoingStreams());
stream = session_->CreateOutgoingBidirectionalStream();
EXPECT_FALSE(stream);
+
+ if (GetParam().transport_version == QUIC_VERSION_99) {
+ // Ensure that we have/have had 3 open streams, crypto, header, and the
+ // 1 test stream. Primary purpose of this is to fail when crypto
+ // no longer uses a normal stream. Some above constants will then need
+ // to be changed.
+ EXPECT_EQ(QuicSessionPeer::v99_bidirectional_stream_id_manager(&*session_)
+ ->outgoing_static_stream_count() +
+ 1,
+ QuicSessionPeer::v99_bidirectional_stream_id_manager(&*session_)
+ ->outgoing_stream_count());
+ }
}
TEST_P(QuicSpdyClientSessionTest, MaxNumStreamsWithRst) {
@@ -276,17 +294,29 @@ TEST_P(QuicSpdyClientSessionTest, MaxNumStreamsWithRst) {
// Check that a new one can be created.
EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams());
if (GetParam().transport_version == QUIC_VERSION_99) {
- // In V99 the stream limit increases only if we get a MAX_STREAM_ID
+ // In V99 the stream limit increases only if we get a MAX_STREAMS
// frame; pretend we got one.
- // Note that this is to be the second stream created, but GetNth... starts
- // numbering at 0 (the first stream is 0, second is 1...)
- QuicMaxStreamIdFrame frame(0, GetNthClientInitiatedBidirectionalStreamId(
- connection_->transport_version(), 1));
- session_->OnMaxStreamIdFrame(frame);
+ // Note that this is to be the second stream created, hence
+ // the stream count is 3 (the two streams created as a part of
+ // the test plus the header stream, internally created).
+ QuicMaxStreamsFrame frame(
+ 0,
+ QuicSessionPeer::v99_bidirectional_stream_id_manager(&*session_)
+ ->outgoing_static_stream_count() +
+ 2,
+ /*unidirectional=*/false);
+ session_->OnMaxStreamsFrame(frame);
}
stream = session_->CreateOutgoingBidirectionalStream();
EXPECT_NE(nullptr, stream);
+ if (GetParam().transport_version == QUIC_VERSION_99) {
+ // Ensure that we have/have had three open streams: two test streams and the
+ // header stream.
+ EXPECT_EQ(3u,
+ QuicSessionPeer::v99_bidirectional_stream_id_manager(&*session_)
+ ->outgoing_stream_count());
+ }
}
TEST_P(QuicSpdyClientSessionTest, ResetAndTrailers) {
@@ -308,7 +338,7 @@ TEST_P(QuicSpdyClientSessionTest, ResetAndTrailers) {
if (GetParam().transport_version == QUIC_VERSION_99) {
// For v99, trying to open a stream and failing due to lack
- // of stream ids will result in a STREAM_ID_BLOCKED. Make
+ // of stream ids will result in a STREAMS_BLOCKED. Make
// sure we get one. Also clear out the frame because if it's
// left sitting, the later SendRstStream will not actually
// transmit the RST_STREAM because the connection will be in write-blocked
@@ -316,8 +346,7 @@ TEST_P(QuicSpdyClientSessionTest, ResetAndTrailers) {
// RST_STREAM, below, will not be satisfied.
EXPECT_CALL(*connection_, SendControlFrame(_))
.WillOnce(Invoke(
- this,
- &QuicSpdyClientSessionTest::ClearStreamIdBlockedControlFrame));
+ this, &QuicSpdyClientSessionTest::ClearStreamsBlockedControlFrame));
}
EXPECT_EQ(nullptr, session_->CreateOutgoingBidirectionalStream());
@@ -347,14 +376,27 @@ TEST_P(QuicSpdyClientSessionTest, ResetAndTrailers) {
// be able to create a new outgoing stream.
EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams());
if (GetParam().transport_version == QUIC_VERSION_99) {
- // Note that this is to be the second stream created, but GetNth... starts
- // numbering at 0 (the first stream is 0, second is 1...)
- QuicMaxStreamIdFrame frame(0, GetNthClientInitiatedBidirectionalStreamId(
- connection_->transport_version(), 1));
- session_->OnMaxStreamIdFrame(frame);
+ // Note that this is to be the second stream created, hence
+ // the stream count is 3 (the two streams created as a part of
+ // the test plus the header stream, internally created).
+ QuicMaxStreamsFrame frame(
+ 0,
+ QuicSessionPeer::v99_bidirectional_stream_id_manager(&*session_)
+ ->outgoing_static_stream_count() +
+ 2,
+ /*unidirectional=*/false);
+
+ session_->OnMaxStreamsFrame(frame);
}
stream = session_->CreateOutgoingBidirectionalStream();
EXPECT_NE(nullptr, stream);
+ if (GetParam().transport_version == QUIC_VERSION_99) {
+ // Ensure that we have/have had three open streams: two test streams and the
+ // header stream.
+ EXPECT_EQ(3u,
+ QuicSessionPeer::v99_bidirectional_stream_id_manager(&*session_)
+ ->outgoing_stream_count());
+ }
}
TEST_P(QuicSpdyClientSessionTest, ReceivedMalformedTrailersAfterSendingRst) {
@@ -394,7 +436,7 @@ TEST_P(QuicSpdyClientSessionTest, OnStreamHeaderListWithStaticStream) {
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(1);
session_->OnStreamHeaderList(
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ QuicUtils::GetHeadersStreamId(connection_->transport_version()),
/*fin=*/false, 0, trailers);
}
@@ -410,7 +452,7 @@ TEST_P(QuicSpdyClientSessionTest, OnPromiseHeaderListWithStaticStream) {
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(1);
session_->OnPromiseHeaderList(
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ QuicUtils::GetHeadersStreamId(connection_->transport_version()),
promised_stream_id_, 0, trailers);
}
@@ -462,13 +504,19 @@ TEST_P(QuicSpdyClientSessionTest, InvalidPacketReceived) {
session_->ProcessUdpPacket(client_address, server_address, valid_packet);
// Verify that a non-decryptable packet doesn't close the connection.
- QuicFramerPeer::SetLastSerializedConnectionId(
+ QuicFramerPeer::SetLastSerializedServerConnectionId(
QuicConnectionPeer::GetFramer(connection_), connection_id);
ParsedQuicVersionVector versions = SupportedVersions(GetParam());
+ QuicConnectionId destination_connection_id = EmptyQuicConnectionId();
+ QuicConnectionId source_connection_id = connection_id;
+ if (!GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ destination_connection_id = connection_id;
+ source_connection_id = EmptyQuicConnectionId();
+ }
std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
- connection_id, EmptyQuicConnectionId(), false, false, 100, "data",
- CONNECTION_ID_ABSENT, CONNECTION_ID_ABSENT, PACKET_4BYTE_PACKET_NUMBER,
- &versions, Perspective::IS_SERVER));
+ destination_connection_id, source_connection_id, false, false, 100,
+ "data", CONNECTION_ID_ABSENT, CONNECTION_ID_ABSENT,
+ PACKET_4BYTE_PACKET_NUMBER, &versions, Perspective::IS_SERVER));
std::unique_ptr<QuicReceivedPacket> received(
ConstructReceivedPacket(*packet, QuicTime::Zero()));
// Change the last byte of the encrypted data.
@@ -482,6 +530,15 @@ TEST_P(QuicSpdyClientSessionTest, InvalidPacketReceived) {
TEST_P(QuicSpdyClientSessionTest, InvalidFramedPacketReceived) {
QuicSocketAddress server_address(TestPeerIPAddress(), kTestPort);
QuicSocketAddress client_address(TestPeerIPAddress(), kTestPort);
+ if (GetParam().KnowsWhichDecrypterToUse()) {
+ connection_->InstallDecrypter(
+ ENCRYPTION_FORWARD_SECURE,
+ QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT));
+ } else {
+ connection_->SetDecrypter(
+ ENCRYPTION_FORWARD_SECURE,
+ QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT));
+ }
EXPECT_CALL(*connection_, ProcessUdpPacket(server_address, client_address, _))
.WillRepeatedly(Invoke(static_cast<MockQuicConnection*>(connection_),
@@ -492,7 +549,7 @@ TEST_P(QuicSpdyClientSessionTest, InvalidFramedPacketReceived) {
QuicConnectionId destination_connection_id =
session_->connection()->connection_id();
QuicConnectionId source_connection_id = EmptyQuicConnectionId();
- QuicFramerPeer::SetLastSerializedConnectionId(
+ QuicFramerPeer::SetLastSerializedServerConnectionId(
QuicConnectionPeer::GetFramer(connection_), destination_connection_id);
ParsedQuicVersionVector versions = {GetParam()};
bool version_flag = false;
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 007bba08e48..5f5d5c13466 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
@@ -193,9 +193,14 @@ TEST_P(QuicSpdyClientStreamTest,
EXPECT_NE(QUIC_STREAM_NO_ERROR, stream_->stream_error());
}
+// Test that receiving trailing headers (on the headers stream), containing a
+// final offset, results in the stream being closed at that byte offset.
TEST_P(QuicSpdyClientStreamTest, ReceivingTrailers) {
- // Test that receiving trailing headers, containing a final offset, results in
- // the stream being closed at that byte offset.
+ // There is no kFinalOffsetHeaderKey if trailers are sent on the
+ // request/response stream.
+ if (VersionUsesQpack(connection_->transport_version())) {
+ return;
+ }
// Send headers as usual.
auto headers = AsHeaderList(headers_);
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 bda2e172d01..35b2d5ef305 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
@@ -51,6 +51,9 @@ namespace quic {
namespace {
+// TODO(renjietang): remove this once HTTP/3 error codes are adopted.
+const uint16_t kHttpUnknownStreamType = 0x0D;
+
class HeaderTableDebugVisitor : public HpackHeaderTable::DebugVisitorInterface {
public:
HeaderTableDebugVisitor(const QuicClock* clock,
@@ -204,6 +207,12 @@ class QuicSpdySession::SpdyFramerVisitor
return;
}
+ if (VersionUsesQpack(session_->connection()->transport_version())) {
+ CloseConnection("HEADERS frame not allowed on headers stream.",
+ QUIC_INVALID_HEADERS_STREAM_DATA);
+ return;
+ }
+
// TODO(mpw): avoid down-conversion and plumb SpdyStreamPrecedence through
// QuicHeadersStream.
SpdyPriority priority =
@@ -331,6 +340,9 @@ QuicSpdySession::~QuicSpdySession() {
static_cast<QuicSpdyStream*>(kv.second.get())->ClearSession();
}
for (auto const& kv : dynamic_streams()) {
+ if (eliminate_static_stream_map() && kv.second->is_static()) {
+ continue;
+ }
static_cast<QuicSpdyStream*>(kv.second.get())->ClearSession();
}
}
@@ -355,9 +367,15 @@ void QuicSpdySession::Initialize() {
headers_stream_ = QuicMakeUnique<QuicHeadersStream>((this));
DCHECK_EQ(QuicUtils::GetHeadersStreamId(connection()->transport_version()),
headers_stream_->id());
- RegisterStaticStream(
- QuicUtils::GetHeadersStreamId(connection()->transport_version()),
- headers_stream_.get());
+ if (!eliminate_static_stream_map()) {
+ RegisterStaticStream(
+ QuicUtils::GetHeadersStreamId(connection()->transport_version()),
+ headers_stream_.get());
+ } else {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map_3, 7, 17);
+ unowned_headers_stream_ = headers_stream_.get();
+ RegisterStaticStreamNew(std::move(headers_stream_));
+ }
set_max_uncompressed_header_bytes(max_inbound_header_list_size_);
@@ -390,7 +408,6 @@ void QuicSpdySession::WriteDecoderStreamData(QuicStringPiece data) {
DCHECK(VersionUsesQpack(connection()->transport_version()));
// TODO(112770235): Send decoder stream data on decoder stream.
- QUIC_NOTREACHED();
}
void QuicSpdySession::OnStreamHeadersPriority(QuicStreamId stream_id,
@@ -407,7 +424,7 @@ void QuicSpdySession::OnStreamHeaderList(QuicStreamId stream_id,
bool fin,
size_t frame_len,
const QuicHeaderList& header_list) {
- if (QuicContainsKey(static_streams(), stream_id)) {
+ if (IsStaticStream(stream_id)) {
connection()->CloseConnection(
QUIC_INVALID_HEADERS_STREAM_DATA, "stream is static",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -429,8 +446,8 @@ void QuicSpdySession::OnStreamHeaderList(QuicStreamId stream_id,
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
- DVLOG(1) << "Received final byte offset in trailers for stream "
- << stream_id << ", which no longer exists.";
+ QUIC_DVLOG(1) << "Received final byte offset in trailers for stream "
+ << stream_id << ", which no longer exists.";
OnFinalByteOffsetReceived(stream_id, final_byte_offset);
}
}
@@ -463,6 +480,8 @@ size_t QuicSpdySession::WriteHeadersOnHeadersStream(
bool fin,
SpdyPriority priority,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
+ DCHECK(!VersionUsesQpack(connection()->transport_version()));
+
return WriteHeadersOnHeadersStreamImpl(
id, std::move(headers), fin,
/* parent_stream_id = */ 0, Spdy3PriorityToHttp2Weight(priority),
@@ -478,7 +497,7 @@ size_t QuicSpdySession::WritePriority(QuicStreamId id,
}
SpdyPriorityIR priority_frame(id, parent_stream_id, weight, exclusive);
SpdySerializedFrame frame(spdy_framer_.SerializeFrame(priority_frame));
- headers_stream_->WriteOrBufferData(
+ headers_stream()->WriteOrBufferData(
QuicStringPiece(frame.data(), frame.size()), false, nullptr);
return frame.size();
}
@@ -498,19 +517,18 @@ size_t QuicSpdySession::WritePushPromise(QuicStreamId original_stream_id,
push_promise.set_fin(false);
SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise));
- headers_stream_->WriteOrBufferData(
+ headers_stream()->WriteOrBufferData(
QuicStringPiece(frame.data(), frame.size()), false, nullptr);
return frame.size();
}
-size_t QuicSpdySession::SendMaxHeaderListSize(size_t value) {
+void QuicSpdySession::SendMaxHeaderListSize(size_t value) {
SpdySettingsIR settings_frame;
settings_frame.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE, value);
SpdySerializedFrame frame(spdy_framer_.SerializeFrame(settings_frame));
- headers_stream_->WriteOrBufferData(
+ headers_stream()->WriteOrBufferData(
QuicStringPiece(frame.data(), frame.size()), false, nullptr);
- return frame.size();
}
QpackEncoder* QuicSpdySession::qpack_encoder() {
@@ -527,7 +545,9 @@ QpackDecoder* QuicSpdySession::qpack_decoder() {
QuicSpdyStream* QuicSpdySession::GetSpdyDataStream(
const QuicStreamId stream_id) {
- return static_cast<QuicSpdyStream*>(GetOrCreateDynamicStream(stream_id));
+ QuicStream* stream = GetOrCreateDynamicStream(stream_id);
+ DCHECK(!stream || !stream->is_static());
+ return static_cast<QuicSpdyStream*>(stream);
}
void QuicSpdySession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
@@ -545,9 +565,9 @@ bool QuicSpdySession::ShouldKeepConnectionAlive() const {
return GetNumOpenDynamicStreams() > 0;
}
-bool QuicSpdySession::ShouldBufferIncomingStream(QuicStreamId id) const {
- DCHECK_EQ(QUIC_VERSION_99, connection()->transport_version());
- return !QuicUtils::IsBidirectionalStreamId(id);
+bool QuicSpdySession::UsesPendingStreams() const {
+ DCHECK(VersionHasStreamType(connection()->transport_version()));
+ return true;
}
size_t QuicSpdySession::WriteHeadersOnHeadersStreamImpl(
@@ -558,6 +578,8 @@ size_t QuicSpdySession::WriteHeadersOnHeadersStreamImpl(
int weight,
bool exclusive,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
+ DCHECK(!VersionUsesQpack(connection()->transport_version()));
+
SpdyHeadersIR headers_frame(id, std::move(headers));
headers_frame.set_fin(fin);
if (perspective() == Perspective::IS_CLIENT) {
@@ -567,7 +589,7 @@ size_t QuicSpdySession::WriteHeadersOnHeadersStreamImpl(
headers_frame.set_exclusive(exclusive);
}
SpdySerializedFrame frame(spdy_framer_.SerializeFrame(headers_frame));
- headers_stream_->WriteOrBufferData(
+ headers_stream()->WriteOrBufferData(
QuicStringPiece(frame.data(), frame.size()), false,
std::move(ack_listener));
return frame.size();
@@ -695,8 +717,57 @@ void QuicSpdySession::CloseConnectionWithDetails(QuicErrorCode error,
}
bool QuicSpdySession::HasActiveRequestStreams() const {
- // TODO(renjietang): Exclude static streams.
- return !dynamic_streams().empty();
+ if (!eliminate_static_stream_map()) {
+ return !dynamic_streams().empty();
+ }
+ // In the case where session is destructed by calling
+ // dynamic_streams().clear(), we will have incorrect accounting here.
+ // TODO(renjietang): Modify destructors and make this a DCHECK.
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map_3, 9, 17);
+ if (static_cast<size_t>(dynamic_streams().size()) >
+ num_incoming_static_streams() + num_outgoing_static_streams()) {
+ return dynamic_streams().size() - num_incoming_static_streams() -
+ num_outgoing_static_streams() >
+ 0;
+ }
+ return false;
+}
+
+bool QuicSpdySession::ProcessPendingStream(PendingStream* pending) {
+ DCHECK(VersionHasStreamType(connection()->transport_version()));
+ struct iovec iov;
+ if (!pending->sequencer()->GetReadableRegion(&iov)) {
+ // The first byte hasn't been received yet.
+ return false;
+ }
+
+ QuicDataReader reader(static_cast<char*>(iov.iov_base), iov.iov_len);
+ uint8_t stream_type_length = reader.PeekVarInt62Length();
+ uint64_t stream_type = 0;
+ if (!reader.ReadVarInt62(&stream_type)) {
+ return false;
+ }
+ pending->MarkConsumed(stream_type_length);
+
+ switch (stream_type) {
+ case kControlStream: // HTTP/3 control stream.
+ // TODO(renjietang): Create incoming control stream.
+ break;
+ case kServerPushStream: { // Push Stream.
+ QuicSpdyStream* stream = CreateIncomingStream(std::move(*pending));
+ stream->SetUnblocked();
+ return true;
+ }
+ case kQpackEncoderStream: // QPACK encoder stream.
+ // TODO(bnc): Create QPACK encoder stream.
+ break;
+ case kQpackDecoderStream: // QPACK decoder stream.
+ // TODO(bnc): Create QPACK decoder stream.
+ break;
+ default:
+ SendStopSending(kHttpUnknownStreamType, pending->id());
+ }
+ return false;
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.h
index 0ff1150293e..d0978c1e0ce 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
@@ -28,6 +28,12 @@ namespace test {
class QuicSpdySessionPeer;
} // namespace test
+// Unidirectional stream types define by IETF HTTP/3 draft in section 3.2.
+const uint64_t kControlStream = 0;
+const uint64_t kServerPushStream = 1;
+const uint64_t kQpackEncoderStream = 2;
+const uint64_t kQpackDecoderStream = 3;
+
// QuicHpackDebugVisitor gathers data used for understanding HPACK HoL
// dynamics. Specifically, it is to help predict the compression
// penalty of avoiding HoL by chagning how the dynamic table is used.
@@ -135,11 +141,19 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
spdy::SpdyHeaderBlock headers);
// Sends SETTINGS_MAX_HEADER_LIST_SIZE SETTINGS frame.
- size_t SendMaxHeaderListSize(size_t value);
+ void SendMaxHeaderListSize(size_t value);
QpackEncoder* qpack_encoder();
QpackDecoder* qpack_decoder();
- QuicHeadersStream* headers_stream() { return headers_stream_.get(); }
+ QuicHeadersStream* headers_stream() {
+ return eliminate_static_stream_map() ? unowned_headers_stream_
+ : headers_stream_.get();
+ }
+
+ const QuicHeadersStream* headers_stream() const {
+ return eliminate_static_stream_map() ? unowned_headers_stream_
+ : headers_stream_.get();
+ }
bool server_push_enabled() const { return server_push_enabled_; }
@@ -187,8 +201,13 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// Returns true if there are open HTTP requests.
bool ShouldKeepConnectionAlive() const override;
- // Overridden to buffer incoming streams for version 99.
- bool ShouldBufferIncomingStream(QuicStreamId id) const override;
+ // Overridden to buffer incoming unidirectional streams for version 99.
+ bool UsesPendingStreams() const override;
+
+ // Overridden to Process HTTP/3 stream types. H/3 streams will be created from
+ // pending streams accordingly if the stream type can be read. Returns true if
+ // unidirectional streams are created.
+ bool ProcessPendingStream(PendingStream* pending) override;
size_t WriteHeadersOnHeadersStreamImpl(
QuicStreamId id,
@@ -262,6 +281,13 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// TODO(123528590): Remove this member.
std::unique_ptr<QuicHeadersStream> headers_stream_;
+ // Unowned headers stream pointer that points to the stream
+ // in dynamic_stream_map.
+ // TODO(renjietang): Merge this with headers_stream_ and clean up other
+ // static_stream_map logic when flag eliminate_static_stream_map
+ // is deprecated.
+ QuicHeadersStream* unowned_headers_stream_;
+
// The maximum size of a header block that will be accepted from the peer,
// defined per spec as key + value + overhead per field (uncompressed).
size_t max_inbound_header_list_size_;
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 04605e1faf7..942688a62e7 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
@@ -69,7 +69,7 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
kInitialStreamFlowControlWindowForTest);
session()->config()->SetInitialSessionFlowControlWindowToSend(
kInitialSessionFlowControlWindowForTest);
- session()->config()->ToHandshakeMessage(&msg);
+ session()->config()->ToHandshakeMessage(&msg, transport_version());
const QuicErrorCode error =
session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
EXPECT_EQ(QUIC_NO_ERROR, error);
@@ -94,7 +94,7 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
MOCK_METHOD0(OnCanWrite, void());
- bool HasPendingCryptoRetransmission() override { return false; }
+ bool HasPendingCryptoRetransmission() const override { return false; }
MOCK_CONST_METHOD0(HasPendingRetransmission, bool());
@@ -241,9 +241,8 @@ class TestSession : public QuicSpdySession {
QuicConsumedData SendStreamData(QuicStream* stream) {
struct iovec iov;
- if ((QuicVersionUsesCryptoFrames(connection()->transport_version()) ||
- stream->id() !=
- QuicUtils::GetCryptoStreamId(connection()->transport_version())) &&
+ if (!QuicUtils::IsCryptoStreamId(connection()->transport_version(),
+ stream->id()) &&
connection()->encryption_level() != ENCRYPTION_FORWARD_SECURE) {
this->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
}
@@ -267,7 +266,8 @@ class TestSession : public QuicSpdySession {
using QuicSession::closed_streams;
using QuicSession::zombie_streams;
- using QuicSpdySession::ShouldBufferIncomingStream;
+ using QuicSpdySession::ProcessPendingStream;
+ using QuicSpdySession::UsesPendingStreams;
private:
StrictMock<TestCryptoStream> crypto_stream_;
@@ -277,8 +277,8 @@ class TestSession : public QuicSpdySession {
class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
public:
- bool ClearMaxStreamIdControlFrame(const QuicFrame& frame) {
- if (frame.type == MAX_STREAM_ID_FRAME) {
+ bool ClearMaxStreamsControlFrame(const QuicFrame& frame) {
+ if (frame.type == MAX_STREAMS_FRAME) {
DeleteFrame(&const_cast<QuicFrame&>(frame));
return true;
}
@@ -380,6 +380,24 @@ class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
return QuicUtils::StreamIdDelta(connection_->transport_version());
}
+ QuicStreamId StreamCountToId(QuicStreamCount stream_count,
+ Perspective perspective,
+ bool bidirectional) {
+ // Calculate and build up stream ID rather than use
+ // GetFirst... because the test that relies on this method
+ // needs to do the stream count where #1 is 0/1/2/3, and not
+ // take into account that stream 0 is special.
+ QuicStreamId id =
+ ((stream_count - 1) * QuicUtils::StreamIdDelta(QUIC_VERSION_99));
+ if (!bidirectional) {
+ id |= 0x2;
+ }
+ if (perspective == Perspective::IS_SERVER) {
+ id |= 0x1;
+ }
+ return id;
+ }
+
MockQuicConnectionHelper helper_;
MockAlarmFactory alarm_factory_;
StrictMock<MockQuicConnection>* connection_;
@@ -398,22 +416,11 @@ INSTANTIATE_TEST_SUITE_P(Tests,
QuicSpdySessionTestServer,
::testing::ValuesIn(AllSupportedVersions()));
-TEST_P(QuicSpdySessionTestServer, ShouldBufferIncomingStreamUnidirectional) {
- if (!IsVersion99()) {
+TEST_P(QuicSpdySessionTestServer, UsesPendingStreams) {
+ if (!VersionHasStreamType(transport_version())) {
return;
}
- EXPECT_TRUE(session_.ShouldBufferIncomingStream(
- QuicUtils::GetFirstUnidirectionalStreamId(
- connection_->transport_version(), Perspective::IS_CLIENT)));
-}
-
-TEST_P(QuicSpdySessionTestServer, ShouldBufferIncomingStreamBidirectional) {
- if (!IsVersion99()) {
- return;
- }
- EXPECT_FALSE(session_.ShouldBufferIncomingStream(
- QuicUtils::GetFirstBidirectionalStreamId(connection_->transport_version(),
- Perspective::IS_CLIENT)));
+ EXPECT_TRUE(session_.UsesPendingStreams());
}
TEST_P(QuicSpdySessionTestServer, PeerAddress) {
@@ -426,6 +433,7 @@ TEST_P(QuicSpdySessionTestServer, SelfAddress) {
}
TEST_P(QuicSpdySessionTestServer, IsCryptoHandshakeConfirmed) {
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _));
EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed());
CryptoHandshakeMessage message;
session_.GetMutableCryptoStream()->OnHandshakeMessage(message);
@@ -496,28 +504,35 @@ TEST_P(QuicSpdySessionTestServer, MaximumAvailableOpenedStreams) {
// stream ID, the next ID should fail. Since the actual limit
// is not the number of open streams, we allocate the max and the max+2.
// Get the max allowed stream ID, this should succeed.
- EXPECT_NE(nullptr,
- session_.GetOrCreateDynamicStream(
- QuicSessionPeer::v99_streamid_manager(&session_)
- ->actual_max_allowed_incoming_bidirectional_stream_id()));
- EXPECT_NE(
- nullptr,
- session_.GetOrCreateDynamicStream(
- QuicSessionPeer::v99_streamid_manager(&session_)
- ->actual_max_allowed_incoming_unidirectional_stream_id()));
- EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(1);
- // Get the (max allowed stream ID)++, this should fail.
- EXPECT_EQ(nullptr,
- session_.GetOrCreateDynamicStream(
- QuicSessionPeer::v99_streamid_manager(&session_)
- ->actual_max_allowed_incoming_bidirectional_stream_id() +
- IdDelta()));
- EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(1);
- EXPECT_EQ(nullptr,
- session_.GetOrCreateDynamicStream(
- QuicSessionPeer::v99_streamid_manager(&session_)
- ->actual_max_allowed_incoming_unidirectional_stream_id() +
- IdDelta()));
+ QuicStreamId stream_id = StreamCountToId(
+ QuicSessionPeer::v99_streamid_manager(&session_)
+ ->actual_max_allowed_incoming_bidirectional_streams(),
+ Perspective::IS_CLIENT, // Client initates stream, allocs stream id.
+ /*bidirectional=*/true);
+ EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id));
+ stream_id = StreamCountToId(
+ QuicSessionPeer::v99_streamid_manager(&session_)
+ ->actual_max_allowed_incoming_unidirectional_streams(),
+ Perspective::IS_CLIENT,
+ /*bidirectional=*/false);
+ EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id));
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(2);
+ // Get the (max allowed stream ID)++. These should all fail.
+ stream_id = StreamCountToId(
+ QuicSessionPeer::v99_streamid_manager(&session_)
+ ->actual_max_allowed_incoming_bidirectional_streams() +
+ 1,
+ Perspective::IS_CLIENT,
+ /*bidirectional=*/true);
+ EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(stream_id));
+
+ stream_id = StreamCountToId(
+ QuicSessionPeer::v99_streamid_manager(&session_)
+ ->actual_max_allowed_incoming_unidirectional_streams() +
+ 1,
+ Perspective::IS_CLIENT,
+ /*bidirectional=*/false);
+ EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(stream_id));
} else {
QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
session_.GetOrCreateDynamicStream(stream_id);
@@ -550,15 +565,20 @@ TEST_P(QuicSpdySessionTestServer, TooManyAvailableStreams) {
TEST_P(QuicSpdySessionTestServer, ManyAvailableStreams) {
// When max_open_streams_ is 200, should be able to create 200 streams
// out-of-order, that is, creating the one with the largest stream ID first.
- QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
+ if (IsVersion99()) {
+ QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_, 200);
+ } else {
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
+ }
QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
// Create one stream.
session_.GetOrCreateDynamicStream(stream_id);
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
// Stream count is 200, GetNth... starts counting at 0, so the 200'th stream
- // is 199.
+ // is 199. BUT actually we need to do 198 because the crypto stream (Stream
+ // ID 0) has not been registered, but GetNth... assumes that it has.
EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(
- GetNthClientInitiatedBidirectionalId(199)));
+ GetNthClientInitiatedBidirectionalId(198)));
}
TEST_P(QuicSpdySessionTestServer,
@@ -679,7 +699,7 @@ TEST_P(QuicSpdySessionTestServer, OnCanWriteBundlesStreams) {
if (IsVersion99()) {
EXPECT_CALL(*connection_, SendControlFrame(_))
.WillRepeatedly(Invoke(
- this, &QuicSpdySessionTestServer::ClearMaxStreamIdControlFrame));
+ this, &QuicSpdySessionTestServer::ClearMaxStreamsControlFrame));
}
// Encryption needs to be established before data can be sent.
CryptoHandshakeMessage msg;
@@ -796,6 +816,12 @@ TEST_P(QuicSpdySessionTestServer, OnCanWriteWriterBlocks) {
}
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())) {
+ return;
+ }
session_.set_writev_consumes_all_data(true);
EXPECT_FALSE(session_.HasPendingHandshake()); // Default value.
@@ -883,8 +909,10 @@ TEST_P(QuicSpdySessionTestServer,
// Mark the crypto and headers streams as write blocked, we expect them to be
// allowed to write later.
- session_.MarkConnectionLevelWriteBlocked(
- QuicUtils::GetCryptoStreamId(connection_->transport_version()));
+ if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ session_.MarkConnectionLevelWriteBlocked(
+ QuicUtils::GetCryptoStreamId(connection_->transport_version()));
+ }
// Create a data stream, and although it is write blocked we never expect it
// to be allowed to write as we are connection level flow control blocked.
@@ -894,11 +922,21 @@ TEST_P(QuicSpdySessionTestServer,
// The crypto and headers streams should be called even though we are
// connection flow control blocked.
- TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
- EXPECT_CALL(*crypto_stream, OnCanWrite());
- QuicSpdySessionPeer::SetHeadersStream(&session_, nullptr);
- TestHeadersStream* headers_stream = new TestHeadersStream(&session_);
- QuicSpdySessionPeer::SetHeadersStream(&session_, headers_stream);
+ if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
+ EXPECT_CALL(*crypto_stream, OnCanWrite());
+ }
+ TestHeadersStream* headers_stream;
+ if (!GetQuicReloadableFlag(quic_eliminate_static_stream_map_3) &&
+ !QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ QuicSpdySessionPeer::SetHeadersStream(&session_, nullptr);
+ headers_stream = new TestHeadersStream(&session_);
+ QuicSpdySessionPeer::SetHeadersStream(&session_, headers_stream);
+ } else {
+ QuicSpdySessionPeer::SetUnownedHeadersStream(&session_, nullptr);
+ headers_stream = new TestHeadersStream(&session_);
+ QuicSpdySessionPeer::SetUnownedHeadersStream(&session_, headers_stream);
+ }
session_.MarkConnectionLevelWriteBlocked(
QuicUtils::GetHeadersStreamId(connection_->transport_version()));
EXPECT_CALL(*headers_stream, OnCanWrite());
@@ -983,6 +1021,7 @@ TEST_P(QuicSpdySessionTestServer, ServerReplyToConnecitivityProbe) {
}
TEST_P(QuicSpdySessionTestServer, IncreasedTimeoutAfterCryptoHandshake) {
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _));
EXPECT_EQ(kInitialIdleTimeoutSecs + 3,
QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
CryptoHandshakeMessage msg;
@@ -1034,7 +1073,7 @@ TEST_P(QuicSpdySessionTestServer, RstStreamBeforeHeadersDecompressed) {
TEST_P(QuicSpdySessionTestServer, OnStreamFrameFinStaticStreamId) {
// Send two bytes of payload.
QuicStreamFrame data1(
- QuicUtils::GetCryptoStreamId(connection_->transport_version()), true, 0,
+ QuicUtils::GetHeadersStreamId(connection_->transport_version()), true, 0,
QuicStringPiece("HT"));
EXPECT_CALL(*connection_,
CloseConnection(
@@ -1047,7 +1086,7 @@ TEST_P(QuicSpdySessionTestServer, OnRstStreamStaticStreamId) {
// Send two bytes of payload.
QuicRstStreamFrame rst1(
kInvalidControlFrameId,
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ QuicUtils::GetHeadersStreamId(connection_->transport_version()),
QUIC_ERROR_PROCESSING_STREAM, 0);
EXPECT_CALL(*connection_,
CloseConnection(
@@ -1145,7 +1184,7 @@ TEST_P(QuicSpdySessionTestServer,
QuicStreamOffset offset = crypto_stream->stream_bytes_written();
QuicConfig config;
CryptoHandshakeMessage crypto_message;
- config.ToHandshakeMessage(&crypto_message);
+ config.ToHandshakeMessage(&crypto_message, transport_version());
crypto_stream->SendHandshakeMessage(crypto_message);
char buf[1000];
QuicDataWriter writer(1000, buf, NETWORK_BYTE_ORDER);
@@ -1179,6 +1218,18 @@ TEST_P(QuicSpdySessionTestServer,
// various names that are dependent on the parameters passed.
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())) {
+ return;
+ }
+
+ // This test depends on the headers stream, which does not exist when QPACK is
+ // used.
+ if (VersionUsesQpack(transport_version())) {
+ return;
+ }
+
// Test that if the header stream is flow control blocked, then if the SHLO
// contains a larger send window offset, the stream becomes unblocked.
session_.set_writev_consumes_all_data(true);
@@ -1461,7 +1512,22 @@ TEST_P(QuicSpdySessionTestServer,
// with a FIN or RST then we send an RST to refuse streams for versions other
// than version 99. In version 99 the connection gets closed.
const QuicStreamId kMaxStreams = 5;
- QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
+ if (IsVersion99()) {
+ QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
+ kMaxStreams);
+ } else {
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
+ }
+ // GetNth assumes that both the crypto and header streams have been
+ // open, but the stream id manager, using GetFirstBidirectional... only
+ // assumes that the crypto stream is open. This means that GetNth...(0)
+ // Will return stream ID == 8 (with id ==0 for crypto and id==4 for headers).
+ // It also means that GetNth(kMax..=5) returns 28 (streams 0/1/2/3/4 are ids
+ // 8, 12, 16, 20, 24, respectively, so stream#5 is stream id 28).
+ // However, the stream ID manager does not assume stream 4 is for headers.
+ // The ID manager would assume that stream#5 is streamid 24.
+ // In order to make this all work out properly, kFinalStreamId will
+ // be set to GetNth...(kMaxStreams-1)... but only for V99
const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);
const QuicStreamId kFinalStreamId =
GetNthClientInitiatedBidirectionalId(kMaxStreams);
@@ -1498,8 +1564,10 @@ TEST_P(QuicSpdySessionTestServer,
.Times(1);
} else {
// On version 99 opening such a stream results in a connection close.
- EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID,
- "Stream id 28 above 24", _));
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_INVALID_STREAM_ID,
+ "Stream id 24 would exceed stream count limit 6", _));
}
// Create one more data streams to exceed limit of open stream.
QuicStreamFrame data1(kFinalStreamId, false, 0, QuicStringPiece("HT"));
@@ -1511,10 +1579,10 @@ TEST_P(QuicSpdySessionTestServer, DrainingStreamsDoNotCountAsOpened) {
// it) does not count against the open quota (because it is closed from the
// protocol point of view).
if (IsVersion99()) {
- // Version 99 will result in a MAX_STREAM_ID frame as streams are consumed
+ // Version 99 will result in a MAX_STREAMS frame as streams are consumed
// (via the OnStreamFrame call) and then released (via
// StreamDraining). Eventually this node will believe that the peer is
- // running low on available stream ids and then send a MAX_STREAM_ID frame,
+ // running low on available stream ids and then send a MAX_STREAMS frame,
// caught by this EXPECT_CALL.
EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
} else {
@@ -1522,7 +1590,12 @@ TEST_P(QuicSpdySessionTestServer, DrainingStreamsDoNotCountAsOpened) {
}
EXPECT_CALL(*connection_, OnStreamReset(_, QUIC_REFUSED_STREAM)).Times(0);
const QuicStreamId kMaxStreams = 5;
- QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
+ if (IsVersion99()) {
+ QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
+ kMaxStreams);
+ } else {
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
+ }
// Create kMaxStreams + 1 data streams, and mark them draining.
const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);
@@ -1547,6 +1620,13 @@ INSTANTIATE_TEST_SUITE_P(Tests,
QuicSpdySessionTestClient,
::testing::ValuesIn(AllSupportedVersions()));
+TEST_P(QuicSpdySessionTestClient, UsesPendingStreams) {
+ if (!VersionHasStreamType(transport_version())) {
+ return;
+ }
+ EXPECT_TRUE(session_.UsesPendingStreams());
+}
+
TEST_P(QuicSpdySessionTestClient, AvailableStreamsClient) {
ASSERT_TRUE(session_.GetOrCreateDynamicStream(
GetNthServerInitiatedBidirectionalId(2)) != nullptr);
@@ -1597,9 +1677,17 @@ TEST_P(QuicSpdySessionTestClient, RecordFinAfterReadSideClosed) {
}
TEST_P(QuicSpdySessionTestClient, WritePriority) {
- QuicSpdySessionPeer::SetHeadersStream(&session_, nullptr);
- TestHeadersStream* headers_stream = new TestHeadersStream(&session_);
- QuicSpdySessionPeer::SetHeadersStream(&session_, headers_stream);
+ TestHeadersStream* headers_stream;
+ if (!GetQuicReloadableFlag(quic_eliminate_static_stream_map_3) &&
+ !QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ QuicSpdySessionPeer::SetHeadersStream(&session_, nullptr);
+ headers_stream = new TestHeadersStream(&session_);
+ QuicSpdySessionPeer::SetHeadersStream(&session_, headers_stream);
+ } else {
+ QuicSpdySessionPeer::SetUnownedHeadersStream(&session_, nullptr);
+ headers_stream = new TestHeadersStream(&session_);
+ QuicSpdySessionPeer::SetUnownedHeadersStream(&session_, headers_stream);
+ }
// Make packet writer blocked so |headers_stream| will buffer its write data.
MockPacketWriter* writer = static_cast<MockPacketWriter*>(
@@ -1632,6 +1720,55 @@ TEST_P(QuicSpdySessionTestClient, WritePriority) {
}
}
+TEST_P(QuicSpdySessionTestClient, Http3ServerPush) {
+ if (!VersionHasStreamType(transport_version())) {
+ return;
+ }
+
+ char type[] = {0x01};
+ std::string data = std::string(type, 1) + "header";
+ EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
+ QuicStreamId stream_id1 =
+ GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
+ QuicStreamFrame data1(stream_id1, false, 0, QuicStringPiece(data));
+ session_.OnStreamFrame(data1);
+ EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
+ QuicStream* stream = session_.GetOrCreateDynamicStream(stream_id1);
+ EXPECT_EQ(1u, stream->flow_controller()->bytes_consumed());
+ EXPECT_EQ(1u, session_.flow_controller()->bytes_consumed());
+
+ char unoptimized_type[] = {0x80, 0x00, 0x00, 0x01};
+ data = std::string(unoptimized_type, 4) + "header";
+ QuicStreamId stream_id2 =
+ GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 1);
+ QuicStreamFrame data2(stream_id2, false, 0, QuicStringPiece(data));
+ session_.OnStreamFrame(data2);
+ EXPECT_EQ(2u, session_.GetNumOpenIncomingStreams());
+ stream = session_.GetOrCreateDynamicStream(stream_id2);
+ EXPECT_EQ(4u, stream->flow_controller()->bytes_consumed());
+ EXPECT_EQ(5u, session_.flow_controller()->bytes_consumed());
+}
+
+TEST_P(QuicSpdySessionTestClient, Http3ServerPushOutofOrderFrame) {
+ if (!VersionHasStreamType(transport_version())) {
+ return;
+ }
+
+ char type[] = {0x01};
+ EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
+ QuicStreamFrame data1(
+ GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0),
+ false, 1, QuicStringPiece("header"));
+ session_.OnStreamFrame(data1);
+ EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
+
+ QuicStreamFrame data2(
+ GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0),
+ false, 0, QuicStringPiece(type, 1));
+ session_.OnStreamFrame(data2);
+ EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
+}
+
TEST_P(QuicSpdySessionTestServer, ZombieStreams) {
TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
QuicStreamPeer::SetStreamBytesWritten(3, stream2);
@@ -1803,6 +1940,75 @@ TEST_P(QuicSpdySessionTestServer, OnPriorityFrame) {
EXPECT_EQ(kV3HighestPriority, stream->priority());
}
+TEST_P(QuicSpdySessionTestServer, SimplePendingStreamType) {
+ if (!VersionHasStreamType(transport_version())) {
+ return;
+ }
+ PendingStream pending(QuicUtils::GetFirstUnidirectionalStreamId(
+ transport_version(), Perspective::IS_CLIENT),
+ &session_);
+ char input[] = {// type
+ 0x04,
+ // data
+ 'a', 'b', 'c'};
+ QuicStreamFrame data(pending.id(), true, 0, QuicStringPiece(input, 4));
+ pending.OnStreamFrame(data);
+
+ // A stop sending frame will be sent to indicate unknown type.
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ session_.ProcessPendingStream(&pending);
+}
+
+TEST_P(QuicSpdySessionTestServer, SimplePendingStreamTypeOutOfOrderDelivery) {
+ if (!VersionHasStreamType(transport_version())) {
+ return;
+ }
+ PendingStream pending(QuicUtils::GetFirstUnidirectionalStreamId(
+ transport_version(), Perspective::IS_CLIENT),
+ &session_);
+ char input[] = {// type
+ 0x04,
+ // data
+ 'a', 'b', 'c'};
+ QuicStreamFrame data1(pending.id(), true, 1, QuicStringPiece(&input[1], 3));
+ pending.OnStreamFrame(data1);
+ session_.ProcessPendingStream(&pending);
+
+ QuicStreamFrame data2(pending.id(), false, 0, QuicStringPiece(input, 1));
+ pending.OnStreamFrame(data2);
+
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ session_.ProcessPendingStream(&pending);
+}
+
+TEST_P(QuicSpdySessionTestServer,
+ MultipleBytesPendingStreamTypeOutOfOrderDelivery) {
+ if (!VersionHasStreamType(transport_version())) {
+ return;
+ }
+ PendingStream pending(QuicUtils::GetFirstUnidirectionalStreamId(
+ transport_version(), Perspective::IS_CLIENT),
+ &session_);
+ char input[] = {// type (256)
+ 0x40 + 0x01, 0x00,
+ // data
+ 'a', 'b', 'c'};
+
+ QuicStreamFrame data1(pending.id(), true, 2, QuicStringPiece(&input[2], 3));
+ pending.OnStreamFrame(data1);
+ session_.ProcessPendingStream(&pending);
+
+ QuicStreamFrame data2(pending.id(), false, 0, QuicStringPiece(input, 1));
+ pending.OnStreamFrame(data2);
+ session_.ProcessPendingStream(&pending);
+
+ QuicStreamFrame data3(pending.id(), false, 1, QuicStringPiece(&input[1], 1));
+ pending.OnStreamFrame(data3);
+
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ session_.ProcessPendingStream(&pending);
+}
+
} // 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 674b0760d23..d424cc04bc7 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
@@ -4,13 +4,19 @@
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h"
+#include <limits>
#include <string>
#include <utility>
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_session.h"
#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
@@ -139,19 +145,23 @@ QuicSpdyStream::QuicSpdyStream(QuicStreamId id,
StreamType type)
: QuicStream(id, spdy_session, /*is_static=*/false, type),
spdy_session_(spdy_session),
+ on_body_available_called_because_sequencer_is_closed_(false),
visitor_(nullptr),
headers_decompressed_(false),
+ headers_length_(0, 0),
+ trailers_length_(0, 0),
trailers_decompressed_(false),
trailers_consumed_(false),
http_decoder_visitor_(new HttpDecoderVisitor(this)),
body_buffer_(sequencer()),
ack_listener_(nullptr) {
- DCHECK_NE(QuicUtils::GetCryptoStreamId(
- spdy_session->connection()->transport_version()),
- id);
- // Don't receive any callbacks from the sequencer until headers
- // are complete.
- sequencer()->SetBlockedUntilFlush();
+ DCHECK(!QuicUtils::IsCryptoStreamId(
+ spdy_session->connection()->transport_version(), id));
+ // If headers are sent on the headers stream, then do not receive any
+ // callbacks from the sequencer until headers are complete.
+ if (!VersionUsesQpack(spdy_session_->connection()->transport_version())) {
+ sequencer()->SetBlockedUntilFlush();
+ }
if (VersionHasDataFrameHeader(
spdy_session_->connection()->transport_version())) {
@@ -163,21 +173,25 @@ QuicSpdyStream::QuicSpdyStream(QuicStreamId id,
QuicSpdyStream::QuicSpdyStream(PendingStream pending,
QuicSpdySession* spdy_session,
StreamType type)
- : QuicStream(std::move(pending), type),
+ : QuicStream(std::move(pending), type, /*is_static=*/false),
spdy_session_(spdy_session),
+ on_body_available_called_because_sequencer_is_closed_(false),
visitor_(nullptr),
headers_decompressed_(false),
+ headers_length_(0, 0),
+ trailers_length_(0, 0),
trailers_decompressed_(false),
trailers_consumed_(false),
http_decoder_visitor_(new HttpDecoderVisitor(this)),
body_buffer_(sequencer()),
ack_listener_(nullptr) {
- DCHECK_NE(QuicUtils::GetCryptoStreamId(
- spdy_session->connection()->transport_version()),
- id());
- // Don't receive any callbacks from the sequencer until headers
- // are complete.
- sequencer()->SetBlockedUntilFlush();
+ DCHECK(!QuicUtils::IsCryptoStreamId(
+ spdy_session->connection()->transport_version(), id()));
+ // If headers are sent on the headers stream, then do not receive any
+ // callbacks from the sequencer until headers are complete.
+ if (!VersionUsesQpack(spdy_session_->connection()->transport_version())) {
+ sequencer()->SetBlockedUntilFlush();
+ }
if (VersionHasDataFrameHeader(
spdy_session_->connection()->transport_version())) {
@@ -192,9 +206,30 @@ size_t QuicSpdyStream::WriteHeaders(
SpdyHeaderBlock header_block,
bool fin,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
+ QuicConnection::ScopedPacketFlusher flusher(
+ spdy_session_->connection(), QuicConnection::SEND_ACK_IF_PENDING);
+ // Send stream type for server push stream
+ if (VersionHasStreamType(session()->connection()->transport_version()) &&
+ type() == WRITE_UNIDIRECTIONAL && send_buffer().stream_offset() == 0) {
+ char data[sizeof(kServerPushStream)];
+ QuicDataWriter writer(QUIC_ARRAYSIZE(data), data);
+ writer.WriteVarInt62(kServerPushStream);
+
+ // Similar to frame headers, stream type byte shouldn't be exposed to upper
+ // layer applications.
+ unacked_frame_headers_offsets_.Add(0, writer.length());
+
+ QUIC_LOG(INFO) << "Stream " << id() << " is writing type as server push";
+ WriteOrBufferData(QuicStringPiece(writer.data(), writer.length()), false,
+ nullptr);
+ }
size_t bytes_written =
WriteHeadersImpl(std::move(header_block), fin, std::move(ack_listener));
- if (fin) {
+ if (!VersionUsesQpack(spdy_session_->connection()->transport_version()) &&
+ fin) {
+ // If HEADERS are sent on the headers stream, then |fin_sent_| needs to be
+ // set and write side needs to be closed without actually sending a FIN on
+ // this stream.
// TODO(rch): Add test to ensure fin_sent_ is set whenever a fin is sent.
set_fin_sent(true);
CloseWriteSide();
@@ -219,13 +254,15 @@ void QuicSpdyStream::WriteOrBufferBody(QuicStringPiece data, bool fin) {
unacked_frame_headers_offsets_.Add(
send_buffer().stream_offset(),
send_buffer().stream_offset() + header_length);
- QUIC_DLOG(INFO) << "Stream " << id() << " is writing header of length "
+ QUIC_DLOG(INFO) << "Stream " << id()
+ << " is writing DATA frame header of length "
<< header_length;
WriteOrBufferData(QuicStringPiece(buffer.get(), header_length), false,
nullptr);
// Write body.
- QUIC_DLOG(INFO) << "Stream " << id() << " is writing body of length "
+ QUIC_DLOG(INFO) << "Stream " << id()
+ << " is writing DATA frame payload of length "
<< data.length();
WriteOrBufferData(data, fin, nullptr);
}
@@ -238,26 +275,33 @@ size_t QuicSpdyStream::WriteTrailers(
return 0;
}
- // The header block must contain the final offset for this stream, as the
- // trailers may be processed out of order at the peer.
- QUIC_DLOG(INFO) << "Inserting trailer: (" << kFinalOffsetHeaderKey << ", "
- << stream_bytes_written() + BufferedDataBytes() << ")";
- trailer_block.insert(
- std::make_pair(kFinalOffsetHeaderKey,
- QuicTextUtils::Uint64ToString(stream_bytes_written() +
- BufferedDataBytes())));
+ if (!VersionUsesQpack(spdy_session_->connection()->transport_version())) {
+ // The header block must contain the final offset for this stream, as the
+ // trailers may be processed out of order at the peer.
+ const QuicStreamOffset final_offset =
+ stream_bytes_written() + BufferedDataBytes();
+ QUIC_DLOG(INFO) << "Inserting trailer: (" << kFinalOffsetHeaderKey << ", "
+ << final_offset << ")";
+ trailer_block.insert(std::make_pair(
+ kFinalOffsetHeaderKey, QuicTextUtils::Uint64ToString(final_offset)));
+ }
// Write the trailing headers with a FIN, and close stream for writing:
// trailers are the last thing to be sent on a stream.
const bool kFin = true;
size_t bytes_written =
WriteHeadersImpl(std::move(trailer_block), kFin, std::move(ack_listener));
- set_fin_sent(kFin);
- // Trailers are the last thing to be sent on a stream, but if there is still
- // queued data then CloseWriteSide() will cause it never to be sent.
- if (BufferedDataBytes() == 0) {
- CloseWriteSide();
+ // If trailers are sent on the headers stream, then |fin_sent_| needs to be
+ // set without actually sending a FIN on this stream.
+ if (!VersionUsesQpack(spdy_session_->connection()->transport_version())) {
+ set_fin_sent(kFin);
+
+ // Also, write side of this stream needs to be closed. However, only do
+ // this if there is no more buffered data, otherwise it will never be sent.
+ if (BufferedDataBytes() == 0) {
+ CloseWriteSide();
+ }
}
return bytes_written;
@@ -300,12 +344,14 @@ QuicConsumedData QuicSpdyStream::WriteBodySlices(QuicMemSliceSpan slices,
unacked_frame_headers_offsets_.Add(
send_buffer().stream_offset(),
send_buffer().stream_offset() + header_length);
- QUIC_DLOG(INFO) << "Stream " << id() << " is writing header of length "
+ QUIC_DLOG(INFO) << "Stream " << id()
+ << " is writing DATA frame header of length "
<< header_length;
WriteMemSlices(storage.ToSpan(), false);
// Write body.
- QUIC_DLOG(INFO) << "Stream " << id() << " is writing body of length "
+ QUIC_DLOG(INFO) << "Stream " << id()
+ << " is writing DATA frame payload of length "
<< slices.total_length();
return WriteMemSlices(slices, fin);
}
@@ -354,6 +400,15 @@ bool QuicSpdyStream::HasBytesToRead() const {
}
void QuicSpdyStream::MarkTrailersConsumed() {
+ if (VersionUsesQpack(spdy_session_->connection()->transport_version()) &&
+ !reading_stopped()) {
+ const QuicByteCount trailers_total_length =
+ trailers_length_.header_length + trailers_length_.payload_length;
+ if (trailers_total_length > 0) {
+ sequencer()->MarkConsumed(trailers_total_length);
+ }
+ }
+
trailers_consumed_ = true;
}
@@ -367,8 +422,35 @@ uint64_t QuicSpdyStream::total_body_bytes_read() const {
void QuicSpdyStream::ConsumeHeaderList() {
header_list_.Clear();
- if (FinishedReadingHeaders()) {
- sequencer()->SetUnblocked();
+
+ if (!VersionUsesQpack(spdy_session_->connection()->transport_version())) {
+ if (FinishedReadingHeaders()) {
+ sequencer()->SetUnblocked();
+ }
+ return;
+ }
+
+ if (!reading_stopped()) {
+ const QuicByteCount headers_total_length =
+ headers_length_.header_length + headers_length_.payload_length;
+ if (headers_total_length > 0) {
+ sequencer()->MarkConsumed(headers_total_length);
+ }
+ }
+
+ if (!FinishedReadingHeaders()) {
+ return;
+ }
+
+ if (body_buffer_.HasBytesToRead()) {
+ OnBodyAvailable();
+ return;
+ }
+
+ if (sequencer()->IsClosed() &&
+ !on_body_available_called_because_sequencer_is_closed_) {
+ on_body_available_called_because_sequencer_is_closed_ = true;
+ OnBodyAvailable();
}
}
@@ -400,7 +482,15 @@ void QuicSpdyStream::OnStreamHeaderList(bool fin,
}
void QuicSpdyStream::OnHeadersTooLarge() {
- Reset(QUIC_HEADERS_TOO_LARGE);
+ if (VersionUsesQpack(spdy_session_->connection()->transport_version())) {
+ // TODO(124216424): Use HTTP_EXCESSIVE_LOAD error code.
+ std::string error_message =
+ QuicStrCat("Too large headers received on stream ", id());
+ CloseConnectionWithDetails(QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE,
+ error_message);
+ } else {
+ Reset(QUIC_HEADERS_TOO_LARGE);
+ }
}
void QuicSpdyStream::OnInitialHeadersComplete(
@@ -409,8 +499,20 @@ void QuicSpdyStream::OnInitialHeadersComplete(
const QuicHeaderList& header_list) {
headers_decompressed_ = true;
header_list_ = header_list;
+
+ if (VersionUsesQpack(spdy_session_->connection()->transport_version())) {
+ if (fin) {
+ OnStreamFrame(
+ QuicStreamFrame(id(), /* fin = */ true,
+ flow_controller()->highest_received_byte_offset(),
+ QuicStringPiece()));
+ }
+ return;
+ }
+
if (fin) {
- OnStreamFrame(QuicStreamFrame(id(), fin, 0, QuicStringPiece()));
+ OnStreamFrame(
+ QuicStreamFrame(id(), fin, /* offset = */ 0, QuicStringPiece()));
}
if (FinishedReadingHeaders()) {
sequencer()->SetUnblocked();
@@ -433,15 +535,20 @@ void QuicSpdyStream::OnTrailingHeadersComplete(
size_t /*frame_len*/,
const QuicHeaderList& header_list) {
DCHECK(!trailers_decompressed_);
- if (fin_received()) {
- QUIC_DLOG(ERROR) << "Received Trailers after FIN, on stream: " << id();
+ if ((VersionUsesQpack(spdy_session_->connection()->transport_version()) &&
+ sequencer()->IsClosed()) ||
+ (!VersionUsesQpack(spdy_session_->connection()->transport_version()) &&
+ fin_received())) {
+ QUIC_DLOG(INFO) << "Received Trailers after FIN, on stream: " << id();
session()->connection()->CloseConnection(
QUIC_INVALID_HEADERS_STREAM_DATA, "Trailers after fin",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return;
}
- if (!fin) {
- QUIC_DLOG(ERROR) << "Trailers must have FIN set, on stream: " << id();
+
+ if (!VersionUsesQpack(spdy_session_->connection()->transport_version()) &&
+ !fin) {
+ QUIC_DLOG(INFO) << "Trailers must have FIN set, on stream: " << id();
session()->connection()->CloseConnection(
QUIC_INVALID_HEADERS_STREAM_DATA, "Fin missing from trailers",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -449,8 +556,9 @@ void QuicSpdyStream::OnTrailingHeadersComplete(
}
size_t final_byte_offset = 0;
- if (!SpdyUtils::CopyAndValidateTrailers(header_list,
- /* expect_final_byte_offset = */ true,
+ const bool expect_final_byte_offset =
+ !VersionUsesQpack(spdy_session_->connection()->transport_version());
+ if (!SpdyUtils::CopyAndValidateTrailers(header_list, expect_final_byte_offset,
&final_byte_offset,
&received_trailers_)) {
QUIC_DLOG(ERROR) << "Trailers for stream " << id() << " are malformed.";
@@ -460,16 +568,12 @@ void QuicSpdyStream::OnTrailingHeadersComplete(
return;
}
trailers_decompressed_ = true;
+ const QuicStreamOffset offset =
+ VersionUsesQpack(spdy_session_->connection()->transport_version())
+ ? flow_controller()->highest_received_byte_offset()
+ : final_byte_offset;
OnStreamFrame(
- QuicStreamFrame(id(), fin, final_byte_offset, QuicStringPiece()));
-}
-
-size_t QuicSpdyStream::WriteHeadersImpl(
- spdy::SpdyHeaderBlock header_block,
- bool fin,
- QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
- return spdy_session_->WriteHeadersOnHeadersStream(
- id(), std::move(header_block), fin, priority(), std::move(ack_listener));
+ QuicStreamFrame(id(), /* fin = */ true, offset, QuicStringPiece()));
}
void QuicSpdyStream::OnPriorityFrame(SpdyPriority priority) {
@@ -490,7 +594,10 @@ void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) {
}
void QuicSpdyStream::OnDataAvailable() {
- DCHECK(FinishedReadingHeaders());
+ if (!VersionUsesQpack(spdy_session_->connection()->transport_version())) {
+ // Sequencer must be blocked until headers are consumed.
+ DCHECK(FinishedReadingHeaders());
+ }
if (!VersionHasDataFrameHeader(
session()->connection()->transport_version())) {
@@ -504,14 +611,20 @@ void QuicSpdyStream::OnDataAvailable() {
iov.iov_len);
}
+ // Do not call OnBodyAvailable() until headers are consumed.
+ if (!FinishedReadingHeaders()) {
+ return;
+ }
+
if (body_buffer_.HasBytesToRead()) {
OnBodyAvailable();
return;
}
- if (sequencer()->IsClosed()) {
+ if (sequencer()->IsClosed() &&
+ !on_body_available_called_because_sequencer_is_closed_) {
+ on_body_available_called_because_sequencer_is_closed_ = true;
OnBodyAvailable();
- return;
}
}
@@ -594,8 +707,8 @@ void QuicSpdyStream::OnDataFramePayload(QuicStringPiece payload) {
void QuicSpdyStream::OnDataFrameEnd() {
DCHECK(
VersionHasDataFrameHeader(session()->connection()->transport_version()));
- DVLOG(1) << "Reaches the end of a data frame. Total bytes received are "
- << body_buffer_.total_body_bytes_received();
+ QUIC_DVLOG(1) << "Reaches the end of a data frame. Total bytes received are "
+ << body_buffer_.total_body_bytes_received();
}
bool QuicSpdyStream::OnStreamFrameAcked(QuicStreamOffset offset,
@@ -647,14 +760,96 @@ QuicByteCount QuicSpdyStream::GetNumFrameHeadersInInterval(
void QuicSpdyStream::OnHeadersFrameStart(Http3FrameLengths frame_length) {
DCHECK(VersionUsesQpack(spdy_session_->connection()->transport_version()));
+ DCHECK(!qpack_decoded_headers_accumulator_);
+
+ if (headers_decompressed_) {
+ trailers_length_ = frame_length;
+ } else {
+ headers_length_ = frame_length;
+ }
+
+ qpack_decoded_headers_accumulator_ =
+ QuicMakeUnique<QpackDecodedHeadersAccumulator>(
+ id(), spdy_session_->qpack_decoder(),
+ spdy_session_->max_inbound_header_list_size());
}
void QuicSpdyStream::OnHeadersFramePayload(QuicStringPiece payload) {
DCHECK(VersionUsesQpack(spdy_session_->connection()->transport_version()));
+
+ if (!qpack_decoded_headers_accumulator_->Decode(payload)) {
+ // 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;
+ }
}
void QuicSpdyStream::OnHeadersFrameEnd() {
DCHECK(VersionUsesQpack(spdy_session_->connection()->transport_version()));
+
+ if (!qpack_decoded_headers_accumulator_->EndHeaderBlock()) {
+ // 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;
+ }
+
+ const QuicByteCount frame_length = headers_decompressed_
+ ? trailers_length_.payload_length
+ : headers_length_.payload_length;
+ OnStreamHeaderList(/* fin = */ false, frame_length,
+ qpack_decoded_headers_accumulator_->quic_header_list());
+
+ qpack_decoded_headers_accumulator_.reset();
+}
+
+size_t QuicSpdyStream::WriteHeadersImpl(
+ spdy::SpdyHeaderBlock header_block,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
+ if (!VersionUsesQpack(spdy_session_->connection()->transport_version())) {
+ return spdy_session_->WriteHeadersOnHeadersStream(
+ id(), std::move(header_block), fin, priority(),
+ std::move(ack_listener));
+ }
+
+ // Encode header list.
+ auto progressive_encoder = spdy_session_->qpack_encoder()->EncodeHeaderList(
+ /* stream_id = */ id(), &header_block);
+ std::string encoded_headers;
+ while (progressive_encoder->HasNext()) {
+ progressive_encoder->Next(
+ /* max_encoded_bytes = */ std::numeric_limits<size_t>::max(),
+ &encoded_headers);
+ }
+
+ // 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);
+ unacked_frame_headers_offsets_.Add(
+ send_buffer().stream_offset(),
+ send_buffer().stream_offset() + headers_frame_header_length);
+
+ QUIC_DLOG(INFO) << "Stream " << id()
+ << " is writing HEADERS frame header of length "
+ << headers_frame_header_length;
+ WriteOrBufferData(
+ QuicStringPiece(headers_frame_header.get(), headers_frame_header_length),
+ /* fin = */ false, /* ack_listener = */ nullptr);
+
+ QUIC_DLOG(INFO) << "Stream " << id()
+ << " is writing HEADERS frame payload of length "
+ << encoded_headers.length();
+ WriteOrBufferData(encoded_headers, fin, nullptr);
+
+ return encoded_headers.size();
}
#undef ENDPOINT // undef for jumbo builds
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 f81a421a44b..dc0d6f5a318 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
@@ -34,6 +34,7 @@ class QuicSpdyStreamPeer;
class QuicStreamPeer;
} // namespace test
+class QpackDecodedHeadersAccumulator;
class QuicSpdySession;
// A QUIC stream that can send and receive HTTP2 (SPDY) headers.
@@ -105,8 +106,8 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream : public QuicStream {
// Called in OnDataAvailable() after it finishes the decoding job.
virtual void OnBodyAvailable() = 0;
- // Writes the headers contained in |header_block| to the dedicated
- // headers stream.
+ // Writes the headers contained in |header_block| on the dedicated headers
+ // stream or on this stream, depending on VersionUsesQpack().
virtual size_t WriteHeaders(
spdy::SpdyHeaderBlock header_block,
bool fin,
@@ -115,8 +116,9 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream : public QuicStream {
// Sends |data| to the peer, or buffers if it can't be sent immediately.
void WriteOrBufferBody(QuicStringPiece data, bool fin);
- // Writes the trailers contained in |trailer_block| to the dedicated
- // headers stream. Trailers will always have the FIN set.
+ // Writes the trailers contained in |trailer_block| on the dedicated headers
+ // stream or on this stream, depending on VersionUsesQpack(). Trailers will
+ // always have the FIN flag set.
virtual size_t WriteTrailers(
spdy::SpdyHeaderBlock trailer_block,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
@@ -151,6 +153,8 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream : public QuicStream {
// Clears |header_list_|.
void ConsumeHeaderList();
+ void SetUnblocked() { sequencer()->SetUnblocked(); }
+
// This block of functions wraps the sequencer's functions of the same
// name. These methods return uncompressed data until that has
// been fully processed. Then they simply delegate to the sequencer.
@@ -247,12 +251,18 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream : public QuicStream {
QuicSpdySession* spdy_session_;
+ bool on_body_available_called_because_sequencer_is_closed_;
+
Visitor* visitor_;
// True if the headers have been completely decompressed.
bool headers_decompressed_;
// Contains a copy of the decompressed header (name, value) pairs until they
// are consumed via Readv.
QuicHeaderList header_list_;
+ // Length of HEADERS frame, including frame header and payload.
+ Http3FrameLengths headers_length_;
+ // Length of TRAILERS frame, including frame header and payload.
+ Http3FrameLengths trailers_length_;
// True if the trailers have been completely decompressed.
bool trailers_decompressed_;
@@ -265,6 +275,9 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream : public QuicStream {
HttpEncoder encoder_;
// Http decoder for processing raw incoming stream frames.
HttpDecoder decoder_;
+ // Headers accumulator for decoding HEADERS frame payload.
+ std::unique_ptr<QpackDecodedHeadersAccumulator>
+ qpack_decoded_headers_accumulator_;
// Visitor of the HttpDecoder.
std::unique_ptr<HttpDecoderVisitor> http_decoder_visitor_;
// Buffer that contains decoded data of the stream.
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_buffer_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_buffer_test.cc
index ba2dbca22e3..6e8e20d23dd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_buffer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_body_buffer_test.cc
@@ -6,7 +6,6 @@
#include <string>
-#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
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 1451533e8e0..eb9a0b3dbb2 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
@@ -78,6 +78,11 @@ class TestStream : public QuicSpdyStream {
ack_listener) override {
saved_headers_ = std::move(header_block);
WriteHeadersMock(fin);
+ if (VersionUsesQpack(transport_version())) {
+ // In this case, call QuicSpdyStream::WriteHeadersImpl() that does the
+ // actual work of closing the stream.
+ QuicSpdyStream::WriteHeadersImpl(saved_headers_.Clone(), fin, nullptr);
+ }
return 0;
}
@@ -212,10 +217,23 @@ TEST_P(QuicSpdyStreamTest, ProcessTooLargeHeaderList) {
QuicHeaderList headers;
stream_->OnStreamHeadersPriority(kV3HighestPriority);
- EXPECT_CALL(*session_,
- SendRstStream(stream_->id(), QUIC_HEADERS_TOO_LARGE, 0));
+ const bool version_uses_qpack =
+ VersionUsesQpack(connection_->transport_version());
+
+ if (version_uses_qpack) {
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE,
+ "Too large headers received on stream 4", _));
+ } else {
+ EXPECT_CALL(*session_,
+ SendRstStream(stream_->id(), QUIC_HEADERS_TOO_LARGE, 0));
+ }
+
stream_->OnStreamHeaderList(false, 1 << 20, headers);
- EXPECT_EQ(QUIC_HEADERS_TOO_LARGE, stream_->stream_error());
+
+ if (!version_uses_qpack) {
+ EXPECT_EQ(QUIC_HEADERS_TOO_LARGE, stream_->stream_error());
+ }
}
TEST_P(QuicSpdyStreamTest, ProcessHeaderListWithFin) {
@@ -331,7 +349,7 @@ TEST_P(QuicSpdyStreamTest, ProcessWrongFramesOnSpdyStream) {
connection_->ReallyCloseConnection(error, error_details,
connection_close_behavior);
})));
- EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
+ EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _));
EXPECT_CALL(*session_, OnConnectionClosed(_, _, _))
.WillOnce(
Invoke([this](QuicErrorCode error, const std::string& error_details,
@@ -919,7 +937,11 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersViaHeaderList) {
trailers_block["key2"] = "value2";
trailers_block["key3"] = "value3";
SpdyHeaderBlock trailers_block_with_final_offset = trailers_block.Clone();
- trailers_block_with_final_offset[kFinalOffsetHeaderKey] = "0";
+ if (!VersionUsesQpack(GetParam().transport_version)) {
+ // :final-offset pseudo-header is only added if trailers are sent
+ // on the headers stream.
+ trailers_block_with_final_offset[kFinalOffsetHeaderKey] = "0";
+ }
total_bytes = 0;
QuicHeaderList trailers;
for (const auto& p : trailers_block_with_final_offset) {
@@ -943,6 +965,12 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithOffset) {
// body, stream is closed at the right offset.
Initialize(kShouldProcessData);
+ // kFinalOffsetHeaderKey is not used when HEADERS are sent on the
+ // request/response stream.
+ if (VersionUsesQpack(GetParam().transport_version)) {
+ return;
+ }
+
// Receive initial headers.
QuicHeaderList headers = ProcessHeaders(false, headers_);
stream_->ConsumeHeaderList();
@@ -988,6 +1016,12 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutOffset) {
// Test that receiving trailers without a final offset field is an error.
Initialize(kShouldProcessData);
+ // kFinalOffsetHeaderKey is not used when HEADERS are sent on the
+ // request/response stream.
+ if (VersionUsesQpack(GetParam().transport_version)) {
+ return;
+ }
+
// Receive initial headers.
ProcessHeaders(false, headers_);
stream_->ConsumeHeaderList();
@@ -1010,10 +1044,60 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutOffset) {
trailers.uncompressed_header_bytes(), trailers);
}
+TEST_P(QuicSpdyStreamTest, ReceivingTrailersOnRequestStream) {
+ Initialize(kShouldProcessData);
+
+ if (!VersionUsesQpack(GetParam().transport_version)) {
+ return;
+ }
+
+ // Receive initial headers.
+ QuicHeaderList headers = ProcessHeaders(false, headers_);
+ stream_->ConsumeHeaderList();
+
+ const std::string body = "this is the body";
+ std::unique_ptr<char[]> buf;
+ QuicByteCount header_length =
+ encoder_.SerializeDataFrameHeader(body.length(), &buf);
+ std::string header = std::string(buf.get(), header_length);
+ std::string data = HasFrameHeader() ? header + body : body;
+
+ // Receive trailing headers.
+ SpdyHeaderBlock trailers_block;
+ trailers_block["key1"] = "value1";
+ trailers_block["key2"] = "value2";
+ trailers_block["key3"] = "value3";
+
+ QuicHeaderList trailers = ProcessHeaders(true, trailers_block);
+
+ // The trailers should be decompressed, and readable from the stream.
+ EXPECT_TRUE(stream_->trailers_decompressed());
+
+ EXPECT_EQ(trailers_block, stream_->received_trailers());
+
+ // Consuming the trailers erases them from the stream.
+ stream_->MarkTrailersConsumed();
+ EXPECT_TRUE(stream_->FinishedReadingTrailers());
+ EXPECT_TRUE(stream_->IsDoneReading());
+
+ // Receive and consume body.
+ QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), /*fin=*/false,
+ 0, data);
+ stream_->OnStreamFrame(frame);
+ EXPECT_EQ(body, stream_->data());
+ EXPECT_TRUE(stream_->IsDoneReading());
+}
+
TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutFin) {
// Test that received Trailers must always have the FIN set.
Initialize(kShouldProcessData);
+ // In IETF QUIC, there is no such thing as FIN flag on HTTP/3 frames like the
+ // HEADERS frame.
+ if (VersionUsesQpack(GetParam().transport_version)) {
+ return;
+ }
+
// Receive initial headers.
auto headers = AsHeaderList(headers_);
stream_->OnStreamHeaderList(/*fin=*/false,
@@ -1053,6 +1137,13 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailersAfterBodyWithFin) {
// If body data are received with a FIN, no trailers should then arrive.
Initialize(kShouldProcessData);
+ // 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 (VersionUsesQpack(GetParam().transport_version)) {
+ return;
+ }
+
// Receive initial headers without FIN set.
ProcessHeaders(false, headers_);
stream_->ConsumeHeaderList();
@@ -1101,6 +1192,12 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersSendsAFin) {
// to be sent on a stream.
Initialize(kShouldProcessData);
+ if (VersionUsesQpack(GetParam().transport_version)) {
+ // In this case, TestStream::WriteHeadersImpl() does not prevent writes.
+ EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _))
+ .Times(AtLeast(1));
+ }
+
// Write the initial headers, without a FIN.
EXPECT_CALL(*stream_, WriteHeadersMock(false));
stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
@@ -1118,6 +1215,12 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {
// peer contain the final offset field indicating last byte of data.
Initialize(kShouldProcessData);
+ if (VersionUsesQpack(GetParam().transport_version)) {
+ // In this case, TestStream::WriteHeadersImpl() does not prevent writes.
+ EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _))
+ .Times(AtLeast(1));
+ }
+
// Write the initial headers.
EXPECT_CALL(*stream_, WriteHeadersMock(false));
stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
@@ -1137,12 +1240,18 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {
// number of body bytes written (including queued bytes).
SpdyHeaderBlock trailers;
trailers["trailer key"] = "trailer value";
- SpdyHeaderBlock trailers_with_offset(trailers.Clone());
- trailers_with_offset[kFinalOffsetHeaderKey] =
- QuicTextUtils::Uint64ToString(body.length() + header_length);
+
+ SpdyHeaderBlock expected_trailers(trailers.Clone());
+ // :final-offset pseudo-header is only added if trailers are sent
+ // on the headers stream.
+ if (!VersionUsesQpack(GetParam().transport_version)) {
+ expected_trailers[kFinalOffsetHeaderKey] =
+ QuicTextUtils::Uint64ToString(body.length() + header_length);
+ }
+
EXPECT_CALL(*stream_, WriteHeadersMock(true));
stream_->WriteTrailers(std::move(trailers), nullptr);
- EXPECT_EQ(trailers_with_offset, stream_->saved_headers());
+ EXPECT_EQ(expected_trailers, stream_->saved_headers());
}
TEST_P(QuicSpdyStreamTest, WritingTrailersClosesWriteSide) {
@@ -1150,12 +1259,16 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersClosesWriteSide) {
// (headers and body), that this closes the stream for writing.
Initialize(kShouldProcessData);
+ // Expect data being written on the stream. In addition to that, headers are
+ // also written on the stream in case of IETF QUIC.
+ EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _))
+ .Times(AtLeast(1));
+
// Write the initial headers.
EXPECT_CALL(*stream_, WriteHeadersMock(false));
stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
// Write non-zero body data.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
const int kBodySize = 1 * 1024; // 1 kB
stream_->WriteOrBufferBody(std::string(kBodySize, 'x'), false);
EXPECT_EQ(0u, stream_->BufferedDataBytes());
@@ -1168,6 +1281,13 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersClosesWriteSide) {
}
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 (VersionUsesQpack(GetParam().transport_version)) {
+ return;
+ }
+
// Test that the stream is not closed for writing when trailers are sent
// while there are still body bytes queued.
testing::InSequence seq;
@@ -1202,7 +1322,10 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersWithQueuedBytes) {
TEST_P(QuicSpdyStreamTest, WritingTrailersAfterFIN) {
// EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
- if (GetParam() != AllSupportedVersions()[0]) {
+ // In IETF QUIC, there is no such thing as FIN flag on HTTP/3 frames like the
+ // HEADERS frame. That is version 99, which is element 0 of the array, so
+ // pick another element.
+ if (GetParam() != AllSupportedVersions()[1]) {
return;
}
@@ -1554,6 +1677,65 @@ TEST_P(QuicSpdyStreamTest, HeaderBytesNotReportedOnRetransmission) {
QuicSpdyStreamPeer::unacked_frame_headers_offsets(stream_).Empty());
}
+TEST_P(QuicSpdyStreamTest, HeadersFrameOnRequestStream) {
+ if (!VersionUsesQpack(GetParam().transport_version)) {
+ return;
+ }
+
+ Initialize(kShouldProcessData);
+
+ // QPACK encoded header block with single header field "foo: bar".
+ std::string headers_frame_payload =
+ QuicTextUtils::HexDecode("00002a94e703626172");
+ std::unique_ptr<char[]> headers_buffer;
+ QuicByteCount headers_frame_header_length =
+ encoder_.SerializeHeadersFrameHeader(headers_frame_payload.length(),
+ &headers_buffer);
+ QuicStringPiece headers_frame_header(headers_buffer.get(),
+ headers_frame_header_length);
+
+ std::string data_frame_payload = "some data";
+ std::unique_ptr<char[]> data_buffer;
+ QuicByteCount data_frame_header_length = encoder_.SerializeDataFrameHeader(
+ data_frame_payload.length(), &data_buffer);
+ QuicStringPiece data_frame_header(data_buffer.get(),
+ data_frame_header_length);
+
+ // QPACK encoded header block with single header field
+ // "custom-key: custom-value".
+ std::string trailers_frame_payload =
+ QuicTextUtils::HexDecode("00002f0125a849e95ba97d7f8925a849e95bb8e8b4bf");
+ std::unique_ptr<char[]> trailers_buffer;
+ QuicByteCount trailers_frame_header_length =
+ encoder_.SerializeHeadersFrameHeader(trailers_frame_payload.length(),
+ &trailers_buffer);
+ QuicStringPiece trailers_frame_header(trailers_buffer.get(),
+ trailers_frame_header_length);
+
+ std::string stream_frame_payload = QuicStrCat(
+ headers_frame_header, headers_frame_payload, data_frame_header,
+ data_frame_payload, trailers_frame_header, trailers_frame_payload);
+ QuicStreamFrame frame(stream_->id(), false, 0, stream_frame_payload);
+ stream_->OnStreamFrame(frame);
+
+ auto it = stream_->header_list().begin();
+ ASSERT_TRUE(it != stream_->header_list().end());
+ EXPECT_EQ("foo", it->first);
+ EXPECT_EQ("bar", it->second);
+ ++it;
+ EXPECT_TRUE(it == stream_->header_list().end());
+
+ // QuicSpdyStream only calls OnBodyAvailable()
+ // after the header list has been consumed.
+ EXPECT_EQ("", stream_->data());
+ stream_->ConsumeHeaderList();
+ EXPECT_EQ("some data", stream_->data());
+
+ const spdy::SpdyHeaderBlock& trailers = stream_->received_trailers();
+ EXPECT_THAT(trailers, testing::ElementsAre(
+ testing::Pair("custom-key", "custom-value")));
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc b/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc
index 6fb662a2008..447f16d84bd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc
@@ -19,14 +19,18 @@ LegacyQuicStreamIdManager::LegacyQuicStreamIdManager(
: session_(session),
max_open_outgoing_streams_(max_open_outgoing_streams),
max_open_incoming_streams_(max_open_incoming_streams),
- next_outgoing_stream_id_(
- QuicUtils::GetCryptoStreamId(
- session->connection()->transport_version()) +
- (session->perspective() == Perspective::IS_SERVER ? 1 : 2)),
+ next_outgoing_stream_id_(QuicUtils::GetFirstBidirectionalStreamId(
+ session->connection()->transport_version(),
+ session->perspective())),
largest_peer_created_stream_id_(
session->perspective() == Perspective::IS_SERVER
- ? QuicUtils::GetCryptoStreamId(
- session->connection()->transport_version())
+ ? (QuicVersionUsesCryptoFrames(
+ session->connection()->transport_version())
+ ? QuicUtils::GetFirstBidirectionalStreamId(
+ session->connection()->transport_version(),
+ Perspective::IS_CLIENT)
+ : QuicUtils::GetCryptoStreamId(
+ session->connection()->transport_version()))
: QuicUtils::GetInvalidStreamId(
session->connection()->transport_version())) {}
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
new file mode 100644
index 00000000000..4f6697c66b5
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/offline/README.md
@@ -0,0 +1,28 @@
+# 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_decoder_stream_receiver_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver_test.cc
index fc7225f8139..29a00d15a79 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver_test.cc
@@ -4,8 +4,6 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_receiver.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.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"
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 cc957591083..c7c132e0a27 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,8 +4,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_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"
@@ -16,19 +15,12 @@ namespace quic {
namespace test {
namespace {
-class MockSenderDelegate : public QpackDecoderStreamSender::Delegate {
- public:
- ~MockSenderDelegate() override = default;
-
- MOCK_METHOD1(WriteDecoderStreamData, void(QuicStringPiece data));
-};
-
class QpackDecoderStreamSenderTest : public QuicTest {
protected:
QpackDecoderStreamSenderTest() : stream_(&delegate_) {}
~QpackDecoderStreamSenderTest() override = default;
- StrictMock<MockSenderDelegate> delegate_;
+ StrictMock<MockDecoderStreamSenderDelegate> delegate_;
QpackDecoderStreamSender stream_;
};
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/core/qpack/qpack_decoder_test_utils.cc
index e8bbd178e62..9fc29deb779 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.cc
@@ -8,7 +8,7 @@
#include <cstddef>
#include <utility>
-#include "testing/gmock/include/gmock/gmock.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
namespace quic {
namespace test {
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/core/qpack/qpack_decoder_test_utils.h
index ca5b60818fa..55761b6c388 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.h
@@ -5,11 +5,11 @@
#ifndef QUICHE_QUIC_CORE_QPACK_QPACK_DECODER_TEST_UTILS_H_
#define QUICHE_QUIC_CORE_QPACK_QPACK_DECODER_TEST_UTILS_H_
-#include "testing/gmock/include/gmock/gmock.h"
#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/spdy/core/spdy_header_block.h"
namespace quic {
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 108ffd57ee4..09c42869544 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
@@ -9,7 +9,6 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_progressive_encoder.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
namespace quic {
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 4e655329b5f..2c450b17c9d 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
@@ -13,6 +13,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h"
namespace spdy {
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver_test.cc
index dcb2039ccfd..f0123902979 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver_test.cc
@@ -4,8 +4,6 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.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"
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 a2e73763dea..ee8f399690d 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,8 +4,6 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_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"
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 fb07d49e1ad..8200e14f8a3 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
@@ -6,7 +6,6 @@
#include <string>
-#include "testing/gtest/include/gtest/gtest.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/platform/api/quic_test.h"
@@ -163,6 +162,19 @@ TEST_P(QpackEncoderTest, DecoderStreamError) {
QuicTextUtils::HexDecode("ffffffffffffffffffffff"));
}
+TEST_P(QpackEncoderTest, SplitAlongNullCharacter) {
+ spdy::SpdyHeaderBlock header_list;
+ header_list["foo"] = QuicStringPiece("bar\0bar\0baz", 11);
+ std::string output = Encode(&header_list);
+
+ EXPECT_EQ(QuicTextUtils::HexDecode("0000" // prefix
+ "2a94e703626172" // foo: bar
+ "2a94e703626172" // foo: bar
+ "2a94e70362617a" // foo: baz
+ ),
+ output);
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table_test.cc
index f3ac5b5d3ef..6f9009d8aa4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_header_table_test.cc
@@ -4,7 +4,6 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h"
-#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_static_table.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
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 f0d1d1d0564..175d39dc6bf 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,8 +6,6 @@
#include <algorithm>
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
#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/platform/api/quic_logging.h"
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 8f6aeaab97a..738a1b7bc9c 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
@@ -4,8 +4,6 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.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"
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_encoder.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_encoder.cc
index 05a025b28be..731ec102866 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_encoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_encoder.cc
@@ -22,7 +22,7 @@ QpackProgressiveEncoder::QpackProgressiveEncoder(
header_table_(header_table),
encoder_stream_sender_(encoder_stream_sender),
header_list_(header_list),
- header_list_iterator_(header_list_->begin()),
+ header_list_iterator_(header_list_.begin()),
prefix_encoded_(false) {
// TODO(bnc): Use |stream_id_| for dynamic table entry management, and
// remove this dummy DCHECK.
@@ -30,11 +30,10 @@ QpackProgressiveEncoder::QpackProgressiveEncoder(
DCHECK(header_table_);
DCHECK(encoder_stream_sender_);
- DCHECK(header_list_);
}
bool QpackProgressiveEncoder::HasNext() const {
- return header_list_iterator_ != header_list_->end() || !prefix_encoded_;
+ return header_list_iterator_ != header_list_.end() || !prefix_encoded_;
}
void QpackProgressiveEncoder::Next(size_t max_encoded_bytes,
@@ -61,7 +60,7 @@ void QpackProgressiveEncoder::Next(size_t max_encoded_bytes,
}
do {
- // Call QpackInstructionEncoder::Encode for |*header_list_iterator_| if it
+ // Call QpackInstructionEncoder::Encode() for |*header_list_iterator_| if it
// has not been called yet.
if (!instruction_encoder_.HasNext()) {
DCHECK(prefix_encoded_);
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_encoder.h b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_encoder.h
index 8e204e23b38..98a3cfeacea 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_encoder.h
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_progressive_encoder.h
@@ -9,6 +9,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.h"
+#include "net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.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/spdy/core/hpack/hpack_encoder.h"
@@ -24,6 +25,8 @@ class QUIC_EXPORT_PRIVATE QpackProgressiveEncoder
: public spdy::HpackEncoder::ProgressiveEncoder {
public:
QpackProgressiveEncoder() = delete;
+ // |header_table|, |encoder_stream_sender|, and |header_list| must all outlive
+ // this object.
QpackProgressiveEncoder(QuicStreamId stream_id,
QpackHeaderTable* header_table,
QpackEncoderStreamSender* encoder_stream_sender,
@@ -43,10 +46,10 @@ class QUIC_EXPORT_PRIVATE QpackProgressiveEncoder
QpackInstructionEncoder instruction_encoder_;
const QpackHeaderTable* const header_table_;
QpackEncoderStreamSender* const encoder_stream_sender_;
- const spdy::SpdyHeaderBlock* const header_list_;
+ const ValueSplittingHeaderList header_list_;
// Header field currently being encoded.
- spdy::SpdyHeaderBlock::const_iterator header_list_iterator_;
+ ValueSplittingHeaderList::const_iterator header_list_iterator_;
// False until prefix is fully encoded.
bool prefix_encoded_;
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 9b2df550b88..45ad667f0d0 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,7 +5,6 @@
#include <string>
#include <tuple>
-#include "testing/gtest/include/gtest/gtest.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_encoder_test_utils.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h"
@@ -132,6 +131,14 @@ TEST_P(QpackRoundTripTest, StaticTable) {
}
}
+TEST_P(QpackRoundTripTest, ValueHasNullCharacter) {
+ spdy::SpdyHeaderBlock header_list;
+ header_list["foo"] = QuicStringPiece("bar\0bar\0baz", 11);
+
+ spdy::SpdyHeaderBlock output = EncodeThenDecode(header_list);
+ EXPECT_EQ(header_list, output);
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table_test.cc
index 50289f2e298..1742502e35b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_static_table_test.cc
@@ -6,9 +6,9 @@
#include <set>
-#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.cc
new file mode 100644
index 00000000000..d8a0ee81766
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.cc
@@ -0,0 +1,88 @@
+// 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/qpack/value_splitting_header_list.h"
+
+namespace quic {
+
+ValueSplittingHeaderList::const_iterator::const_iterator(
+ const spdy::SpdyHeaderBlock* header_list,
+ spdy::SpdyHeaderBlock::const_iterator header_list_iterator)
+ : header_list_(header_list),
+ header_list_iterator_(header_list_iterator),
+ value_start_(0) {
+ UpdateHeaderField();
+}
+
+bool ValueSplittingHeaderList::const_iterator::operator==(
+ const const_iterator& other) const {
+ return header_list_iterator_ == other.header_list_iterator_ &&
+ value_start_ == other.value_start_;
+}
+
+bool ValueSplittingHeaderList::const_iterator::operator!=(
+ const const_iterator& other) const {
+ return !(*this == other);
+}
+
+const ValueSplittingHeaderList::const_iterator&
+ValueSplittingHeaderList::const_iterator::operator++() {
+ if (value_end_ == QuicStringPiece::npos) {
+ // This was the last frament within |*header_list_iterator_|,
+ // move on to the next header element of |header_list_|.
+ ++header_list_iterator_;
+ value_start_ = 0;
+ } else {
+ // Find the next fragment within |*header_list_iterator_|.
+ value_start_ = value_end_ + 1;
+ }
+ UpdateHeaderField();
+
+ return *this;
+}
+
+const ValueSplittingHeaderList::value_type&
+ ValueSplittingHeaderList::const_iterator::operator*() const {
+ return header_field_;
+}
+const ValueSplittingHeaderList::value_type*
+ ValueSplittingHeaderList::const_iterator::operator->() const {
+ return &header_field_;
+}
+
+void ValueSplittingHeaderList::const_iterator::UpdateHeaderField() {
+ DCHECK(value_start_ != QuicStringPiece::npos);
+
+ if (header_list_iterator_ == header_list_->end()) {
+ return;
+ }
+
+ const QuicStringPiece name = header_list_iterator_->first;
+
+ value_end_ = header_list_iterator_->second.find('\0', value_start_);
+ const QuicStringPiece::size_type value_length =
+ value_end_ == QuicStringPiece::npos ? QuicStringPiece::npos
+ : value_end_ - value_start_;
+ const QuicStringPiece value =
+ header_list_iterator_->second.substr(value_start_, value_length);
+
+ header_field_ = std::make_pair(name, value);
+}
+
+ValueSplittingHeaderList::ValueSplittingHeaderList(
+ const spdy::SpdyHeaderBlock* header_list)
+ : header_list_(header_list) {
+ DCHECK(header_list_);
+}
+
+ValueSplittingHeaderList::const_iterator ValueSplittingHeaderList::begin()
+ const {
+ return const_iterator(header_list_, header_list_->begin());
+}
+
+ValueSplittingHeaderList::const_iterator ValueSplittingHeaderList::end() const {
+ return const_iterator(header_list_, header_list_->end());
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.h b/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.h
new file mode 100644
index 00000000000..8d994aeff6d
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list.h
@@ -0,0 +1,61 @@
+// 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_VALUE_SPLITTING_HEADER_LIST_H_
+#define QUICHE_QUIC_CORE_QPACK_VALUE_SPLITTING_HEADER_LIST_H_
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
+
+namespace quic {
+
+// A wrapper class around SpdyHeaderBlock that splits header values along '\0'
+// characters.
+class QUIC_EXPORT_PRIVATE ValueSplittingHeaderList {
+ public:
+ using value_type = spdy::SpdyHeaderBlock::value_type;
+
+ class QUIC_EXPORT_PRIVATE const_iterator {
+ public:
+ // |header_list| must outlive this object.
+ const_iterator(const spdy::SpdyHeaderBlock* header_list,
+ spdy::SpdyHeaderBlock::const_iterator header_list_iterator);
+ const_iterator(const const_iterator&) = default;
+ const_iterator& operator=(const const_iterator&) = delete;
+
+ bool operator==(const const_iterator& other) const;
+ bool operator!=(const const_iterator& other) const;
+
+ const const_iterator& operator++();
+
+ const value_type& operator*() const;
+ const value_type* operator->() const;
+
+ private:
+ // Find next '\0' character; update |value_end_| and |header_field_|.
+ void UpdateHeaderField();
+
+ const spdy::SpdyHeaderBlock* const header_list_;
+ spdy::SpdyHeaderBlock::const_iterator header_list_iterator_;
+ QuicStringPiece::size_type value_start_;
+ QuicStringPiece::size_type value_end_;
+ value_type header_field_;
+ };
+
+ // |header_list| must outlive this object.
+ explicit ValueSplittingHeaderList(const spdy::SpdyHeaderBlock* header_list);
+ ValueSplittingHeaderList(const ValueSplittingHeaderList&) = delete;
+ ValueSplittingHeaderList& operator=(const ValueSplittingHeaderList&) = delete;
+
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ private:
+ const spdy::SpdyHeaderBlock* const header_list_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QPACK_VALUE_SPLITTING_HEADER_LIST_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
new file mode 100644
index 00000000000..9ece65d9673
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/value_splitting_header_list_test.cc
@@ -0,0 +1,121 @@
+// 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/qpack/value_splitting_header_list.h"
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+
+namespace quic {
+namespace test {
+namespace {
+
+using ::testing::ElementsAre;
+using ::testing::Pair;
+
+TEST(ValueSplittingHeaderListTest, Comparison) {
+ spdy::SpdyHeaderBlock block;
+ block["foo"] = QuicStringPiece("bar\0baz", 7);
+ block["baz"] = "qux";
+
+ ValueSplittingHeaderList headers(&block);
+ ValueSplittingHeaderList::const_iterator it1 = headers.begin();
+ const int kEnd = 4;
+ for (int i = 0; i < kEnd; ++i) {
+ // Compare to begin().
+ if (i == 0) {
+ EXPECT_TRUE(it1 == headers.begin());
+ EXPECT_TRUE(headers.begin() == it1);
+ EXPECT_FALSE(it1 != headers.begin());
+ EXPECT_FALSE(headers.begin() != it1);
+ } else {
+ EXPECT_FALSE(it1 == headers.begin());
+ EXPECT_FALSE(headers.begin() == it1);
+ EXPECT_TRUE(it1 != headers.begin());
+ EXPECT_TRUE(headers.begin() != it1);
+ }
+
+ // Compare to end().
+ if (i == kEnd - 1) {
+ EXPECT_TRUE(it1 == headers.end());
+ EXPECT_TRUE(headers.end() == it1);
+ EXPECT_FALSE(it1 != headers.end());
+ EXPECT_FALSE(headers.end() != it1);
+ } else {
+ EXPECT_FALSE(it1 == headers.end());
+ EXPECT_FALSE(headers.end() == it1);
+ EXPECT_TRUE(it1 != headers.end());
+ EXPECT_TRUE(headers.end() != it1);
+ }
+
+ // Compare to another iterator walking through the container.
+ ValueSplittingHeaderList::const_iterator it2 = headers.begin();
+ for (int j = 0; j < kEnd; ++j) {
+ if (i == j) {
+ EXPECT_TRUE(it1 == it2);
+ EXPECT_FALSE(it1 != it2);
+ } else {
+ EXPECT_FALSE(it1 == it2);
+ EXPECT_TRUE(it1 != it2);
+ }
+ ++it2;
+ }
+
+ ++it1;
+ }
+}
+
+TEST(ValueSplittingHeaderListTest, Empty) {
+ spdy::SpdyHeaderBlock block;
+
+ ValueSplittingHeaderList headers(&block);
+ EXPECT_THAT(headers, ElementsAre());
+ EXPECT_EQ(headers.begin(), headers.end());
+}
+
+TEST(ValueSplittingHeaderListTest, Simple) {
+ spdy::SpdyHeaderBlock block;
+ block["foo"] = "bar";
+ block["baz"] = "qux";
+
+ ValueSplittingHeaderList headers(&block);
+ EXPECT_THAT(headers, ElementsAre(Pair("foo", "bar"), Pair("baz", "qux")));
+ EXPECT_NE(headers.begin(), headers.end());
+}
+
+TEST(ValueSplittingHeaderListTest, EmptyValue) {
+ spdy::SpdyHeaderBlock block;
+ block["foo"] = "";
+
+ ValueSplittingHeaderList headers(&block);
+ EXPECT_THAT(headers, ElementsAre(Pair("foo", "")));
+}
+
+TEST(ValueSplittingHeaderListTest, SimpleSplit) {
+ spdy::SpdyHeaderBlock block;
+ block["foo"] = QuicStringPiece("bar\0baz", 7);
+ block["baz"] = QuicStringPiece("foo\0foo", 7);
+
+ ValueSplittingHeaderList headers(&block);
+ EXPECT_THAT(headers, ElementsAre(Pair("foo", "bar"), Pair("foo", "baz"),
+ Pair("baz", "foo"), Pair("baz", "foo")));
+}
+
+TEST(ValueSplittingHeaderListTest, EmptyFragments) {
+ spdy::SpdyHeaderBlock block;
+ block["foo"] = QuicStringPiece("\0", 1);
+ block["bar"] = QuicStringPiece("foo\0", 4);
+ block["baz"] = QuicStringPiece("\0bar", 4);
+ block["qux"] = QuicStringPiece("\0foobar\0", 8);
+
+ ValueSplittingHeaderList headers(&block);
+ EXPECT_THAT(
+ headers,
+ ElementsAre(Pair("foo", ""), Pair("foo", ""), Pair("bar", "foo"),
+ Pair("bar", ""), Pair("baz", ""), Pair("baz", "bar"),
+ Pair("qux", ""), Pair("qux", "foobar"), Pair("qux", "")));
+}
+
+} // namespace
+} // namespace test
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.cc b/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.cc
index a1dbf67c99c..9fcc3b986ae 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.cc
@@ -11,7 +11,7 @@
namespace quic {
-std::string QuicBandwidth::ToDebugValue() const {
+std::string QuicBandwidth::ToDebuggingValue() const {
if (bits_per_second_ < 80000) {
return QuicStringPrintf("%" PRId64 " bits/s (%" PRId64 " bytes/s)",
bits_per_second_, bits_per_second_ / 8);
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.h b/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.h
index 5b747446d18..a5bb30697bc 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth.h
@@ -77,6 +77,9 @@ class QUIC_EXPORT_PRIVATE QuicBandwidth {
}
inline bool IsZero() const { return bits_per_second_ == 0; }
+ inline bool IsInfinite() const {
+ return bits_per_second_ == Infinite().ToBitsPerSecond();
+ }
inline QuicTime::Delta TransferTime(QuicByteCount bytes) const {
if (bits_per_second_ == 0) {
@@ -86,7 +89,7 @@ class QUIC_EXPORT_PRIVATE QuicBandwidth {
bits_per_second_);
}
- std::string ToDebugValue() const;
+ std::string ToDebuggingValue() const;
private:
explicit constexpr QuicBandwidth(int64_t bits_per_second)
@@ -143,7 +146,7 @@ inline QuicByteCount operator*(QuicTime::Delta lhs, QuicBandwidth rhs) {
// Override stream output operator for gtest.
inline std::ostream& operator<<(std::ostream& output,
const QuicBandwidth bandwidth) {
- output << bandwidth.ToDebugValue();
+ output << bandwidth.ToDebuggingValue();
return output;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth_test.cc
index ed23dac1675..22a510752bb 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_bandwidth_test.cc
@@ -3,6 +3,9 @@
// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
+
+#include <limits>
+
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
@@ -102,20 +105,32 @@ TEST_F(QuicBandwidthTest, RelOps) {
EXPECT_GE(b2, b1);
}
-TEST_F(QuicBandwidthTest, DebugValue) {
+TEST_F(QuicBandwidthTest, DebuggingValue) {
EXPECT_EQ("128 bits/s (16 bytes/s)",
- QuicBandwidth::FromBytesPerSecond(16).ToDebugValue());
+ QuicBandwidth::FromBytesPerSecond(16).ToDebuggingValue());
EXPECT_EQ("4096 bits/s (512 bytes/s)",
- QuicBandwidth::FromBytesPerSecond(512).ToDebugValue());
+ QuicBandwidth::FromBytesPerSecond(512).ToDebuggingValue());
QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond(1000 * 50);
- EXPECT_EQ("400.00 kbits/s (50.00 kbytes/s)", bandwidth.ToDebugValue());
+ EXPECT_EQ("400.00 kbits/s (50.00 kbytes/s)", bandwidth.ToDebuggingValue());
bandwidth = bandwidth * 1000;
- EXPECT_EQ("400.00 Mbits/s (50.00 Mbytes/s)", bandwidth.ToDebugValue());
+ EXPECT_EQ("400.00 Mbits/s (50.00 Mbytes/s)", bandwidth.ToDebuggingValue());
bandwidth = bandwidth * 1000;
- EXPECT_EQ("400.00 Gbits/s (50.00 Gbytes/s)", bandwidth.ToDebugValue());
+ EXPECT_EQ("400.00 Gbits/s (50.00 Gbytes/s)", bandwidth.ToDebuggingValue());
+}
+
+TEST_F(QuicBandwidthTest, SpecialValues) {
+ EXPECT_EQ(0, QuicBandwidth::Zero().ToBitsPerSecond());
+ EXPECT_EQ(std::numeric_limits<int64_t>::max(),
+ QuicBandwidth::Infinite().ToBitsPerSecond());
+
+ EXPECT_TRUE(QuicBandwidth::Zero().IsZero());
+ EXPECT_FALSE(QuicBandwidth::Zero().IsInfinite());
+
+ EXPECT_TRUE(QuicBandwidth::Infinite().IsInfinite());
+ EXPECT_FALSE(QuicBandwidth::Infinite().IsZero());
}
} // namespace test
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 25b549cdafe..09148092165 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
@@ -5,10 +5,12 @@
#include "net/third_party/quiche/src/quic/core/quic_config.h"
#include <algorithm>
+#include <cstring>
#include <string>
#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_constants.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_bug_tracker.h"
@@ -17,7 +19,9 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_macros.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_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_uint128.h"
namespace quic {
@@ -400,7 +404,7 @@ QuicConfig::QuicConfig()
client_connection_options_(kCLOP, PRESENCE_OPTIONAL),
idle_network_timeout_seconds_(kICSL, PRESENCE_REQUIRED),
silent_close_(kSCLS, PRESENCE_OPTIONAL),
- max_incoming_dynamic_streams_(kMIDS, PRESENCE_REQUIRED),
+ max_incoming_bidirectional_streams_(kMIBS, PRESENCE_REQUIRED),
bytes_for_connection_id_(kTCID, PRESENCE_OPTIONAL),
initial_round_trip_time_us_(kIRTT, PRESENCE_OPTIONAL),
initial_stream_flow_control_window_bytes_(kSFCW, PRESENCE_OPTIONAL),
@@ -408,7 +412,8 @@ QuicConfig::QuicConfig()
connection_migration_disabled_(kNCMR, PRESENCE_OPTIONAL),
alternate_server_address_(kASAD, PRESENCE_OPTIONAL),
support_max_header_list_size_(kSMHL, PRESENCE_OPTIONAL),
- stateless_reset_token_(kSRST, PRESENCE_OPTIONAL) {
+ stateless_reset_token_(kSRST, PRESENCE_OPTIONAL),
+ max_incoming_unidirectional_streams_(kMIUS, PRESENCE_OPTIONAL) {
SetDefaults();
}
@@ -501,21 +506,38 @@ bool QuicConfig::SilentClose() const {
return silent_close_.GetUint32() > 0;
}
-void QuicConfig::SetMaxIncomingDynamicStreamsToSend(
- uint32_t max_incoming_dynamic_streams) {
- max_incoming_dynamic_streams_.SetSendValue(max_incoming_dynamic_streams);
+void QuicConfig::SetMaxIncomingBidirectionalStreamsToSend(
+ uint32_t max_streams) {
+ max_incoming_bidirectional_streams_.SetSendValue(max_streams);
}
-uint32_t QuicConfig::GetMaxIncomingDynamicStreamsToSend() {
- return max_incoming_dynamic_streams_.GetSendValue();
+uint32_t QuicConfig::GetMaxIncomingBidirectionalStreamsToSend() {
+ return max_incoming_bidirectional_streams_.GetSendValue();
}
-bool QuicConfig::HasReceivedMaxIncomingDynamicStreams() {
- return max_incoming_dynamic_streams_.HasReceivedValue();
+bool QuicConfig::HasReceivedMaxIncomingBidirectionalStreams() {
+ return max_incoming_bidirectional_streams_.HasReceivedValue();
}
-uint32_t QuicConfig::ReceivedMaxIncomingDynamicStreams() {
- return max_incoming_dynamic_streams_.GetReceivedValue();
+uint32_t QuicConfig::ReceivedMaxIncomingBidirectionalStreams() {
+ return max_incoming_bidirectional_streams_.GetReceivedValue();
+}
+
+void QuicConfig::SetMaxIncomingUnidirectionalStreamsToSend(
+ uint32_t max_streams) {
+ max_incoming_unidirectional_streams_.SetSendValue(max_streams);
+}
+
+uint32_t QuicConfig::GetMaxIncomingUnidirectionalStreamsToSend() {
+ return max_incoming_unidirectional_streams_.GetSendValue();
+}
+
+bool QuicConfig::HasReceivedMaxIncomingUnidirectionalStreams() {
+ return max_incoming_unidirectional_streams_.HasReceivedValue();
+}
+
+uint32_t QuicConfig::ReceivedMaxIncomingUnidirectionalStreams() {
+ return max_incoming_unidirectional_streams_.GetReceivedValue();
}
bool QuicConfig::HasSetBytesForConnectionIdToSend() const {
@@ -558,7 +580,7 @@ void QuicConfig::SetInitialStreamFlowControlWindowToSend(
uint32_t window_bytes) {
if (window_bytes < kMinimumFlowControlSendWindow) {
QUIC_BUG << "Initial stream flow control receive window (" << window_bytes
- << ") cannot be set lower than default ("
+ << ") cannot be set lower than minimum ("
<< kMinimumFlowControlSendWindow << ").";
window_bytes = kMinimumFlowControlSendWindow;
}
@@ -660,7 +682,8 @@ void QuicConfig::SetDefaults() {
idle_network_timeout_seconds_.set(kMaximumIdleTimeoutSecs,
kDefaultIdleTimeoutSecs);
silent_close_.set(1, 0);
- SetMaxIncomingDynamicStreamsToSend(kDefaultMaxStreamsPerConnection);
+ SetMaxIncomingBidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection);
+ SetMaxIncomingUnidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection);
max_time_before_crypto_handshake_ =
QuicTime::Delta::FromSeconds(kMaxTimeForCryptoHandshakeSecs);
max_idle_time_before_crypto_handshake_ =
@@ -672,10 +695,18 @@ void QuicConfig::SetDefaults() {
SetSupportMaxHeaderListSize();
}
-void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
+void QuicConfig::ToHandshakeMessage(
+ CryptoHandshakeMessage* out,
+ QuicTransportVersion transport_version) const {
idle_network_timeout_seconds_.ToHandshakeMessage(out);
silent_close_.ToHandshakeMessage(out);
- max_incoming_dynamic_streams_.ToHandshakeMessage(out);
+ // Do not need a version check here, max...bi... will encode
+ // as "MIDS" -- the max initial dynamic streams tag -- if
+ // doing some version other than IETF QUIC/V99.
+ max_incoming_bidirectional_streams_.ToHandshakeMessage(out);
+ if (transport_version == QUIC_VERSION_99) {
+ max_incoming_unidirectional_streams_.ToHandshakeMessage(out);
+ }
bytes_for_connection_id_.ToHandshakeMessage(out);
initial_round_trip_time_us_.ToHandshakeMessage(out);
initial_stream_flow_control_window_bytes_.ToHandshakeMessage(out);
@@ -703,7 +734,11 @@ QuicErrorCode QuicConfig::ProcessPeerHello(
silent_close_.ProcessPeerHello(peer_hello, hello_type, error_details);
}
if (error == QUIC_NO_ERROR) {
- error = max_incoming_dynamic_streams_.ProcessPeerHello(
+ error = max_incoming_bidirectional_streams_.ProcessPeerHello(
+ peer_hello, hello_type, error_details);
+ }
+ if (error == QUIC_NO_ERROR) {
+ error = max_incoming_unidirectional_streams_.ProcessPeerHello(
peer_hello, hello_type, error_details);
}
if (error == QUIC_NO_ERROR) {
@@ -746,25 +781,47 @@ QuicErrorCode QuicConfig::ProcessPeerHello(
}
bool QuicConfig::FillTransportParameters(TransportParameters* params) const {
- params->initial_max_stream_data =
- initial_stream_flow_control_window_bytes_.GetSendValue();
- params->initial_max_data =
- initial_session_flow_control_window_bytes_.GetSendValue();
-
- uint32_t idle_timeout = idle_network_timeout_seconds_.GetUint32();
- if (idle_timeout > std::numeric_limits<uint16_t>::max()) {
- QUIC_BUG << "idle network timeout set too large";
- return false;
- }
- params->idle_timeout = idle_timeout;
-
- uint32_t initial_max_streams = max_incoming_dynamic_streams_.GetSendValue();
- if (initial_max_streams > std::numeric_limits<uint16_t>::max()) {
- QUIC_BUG << "max incoming streams set too large";
- return false;
+ params->idle_timeout_milliseconds.set_value(
+ idle_network_timeout_seconds_.GetUint32() * kNumMillisPerSecond);
+
+ if (stateless_reset_token_.HasSendValue()) {
+ QuicUint128 stateless_reset_token = stateless_reset_token_.GetSendValue();
+ params->stateless_reset_token.assign(
+ reinterpret_cast<const char*>(&stateless_reset_token),
+ reinterpret_cast<const char*>(&stateless_reset_token) +
+ sizeof(stateless_reset_token));
+ }
+
+ params->max_packet_size.set_value(kMaxIncomingPacketSize);
+ params->initial_max_data.set_value(
+ initial_session_flow_control_window_bytes_.GetSendValue());
+ params->initial_max_stream_data_bidi_local.set_value(
+ initial_stream_flow_control_window_bytes_.GetSendValue());
+ params->initial_max_stream_data_bidi_remote.set_value(
+ initial_stream_flow_control_window_bytes_.GetSendValue());
+ params->initial_max_stream_data_uni.set_value(
+ initial_stream_flow_control_window_bytes_.GetSendValue());
+ params->initial_max_streams_bidi.set_value(
+ max_incoming_bidirectional_streams_.GetSendValue());
+ params->initial_max_streams_uni.set_value(
+ max_incoming_unidirectional_streams_.GetSendValue());
+ params->max_ack_delay.set_value(kDefaultDelayedAckTimeMs);
+ params->disable_migration =
+ connection_migration_disabled_.HasSendValue() &&
+ connection_migration_disabled_.GetSendValue() != 0;
+
+ if (alternate_server_address_.HasSendValue()) {
+ TransportParameters::PreferredAddress preferred_address;
+ QuicSocketAddress socket_address = alternate_server_address_.GetSendValue();
+ if (socket_address.host().IsIPv6()) {
+ preferred_address.ipv6_socket_address = socket_address;
+ } else {
+ preferred_address.ipv4_socket_address = socket_address;
+ }
+ params->preferred_address =
+ QuicMakeUnique<TransportParameters::PreferredAddress>(
+ preferred_address);
}
- params->initial_max_bidi_streams.present = true;
- params->initial_max_bidi_streams.value = initial_max_streams;
if (!params->google_quic_params) {
params->google_quic_params = QuicMakeUnique<CryptoHandshakeMessage>();
@@ -773,6 +830,7 @@ bool QuicConfig::FillTransportParameters(TransportParameters* params) const {
initial_round_trip_time_us_.ToHandshakeMessage(
params->google_quic_params.get());
connection_options_.ToHandshakeMessage(params->google_quic_params.get());
+
return true;
}
@@ -780,12 +838,69 @@ QuicErrorCode QuicConfig::ProcessTransportParameters(
const TransportParameters& params,
HelloType hello_type,
std::string* error_details) {
+ // Intentionally round down to probe too often rather than not often enough.
+ uint64_t idle_timeout_seconds =
+ params.idle_timeout_milliseconds.value() / kNumMillisPerSecond;
+ // An idle timeout of zero indicates it is disabled (in other words, it is
+ // set to infinity). When the idle timeout is very high, we set it to our
+ // preferred maximum and still probe that often.
+ if (idle_timeout_seconds > kMaximumIdleTimeoutSecs ||
+ idle_timeout_seconds == 0) {
+ idle_timeout_seconds = kMaximumIdleTimeoutSecs;
+ }
QuicErrorCode error = idle_network_timeout_seconds_.ReceiveValue(
- params.idle_timeout, hello_type, error_details);
+ idle_timeout_seconds, hello_type, error_details);
if (error != QUIC_NO_ERROR) {
DCHECK(!error_details->empty());
return error;
}
+
+ if (!params.stateless_reset_token.empty()) {
+ QuicUint128 stateless_reset_token;
+ if (params.stateless_reset_token.size() != sizeof(stateless_reset_token)) {
+ QUIC_BUG << "Bad stateless reset token length "
+ << params.stateless_reset_token.size();
+ *error_details = "Bad stateless reset token length";
+ return QUIC_INTERNAL_ERROR;
+ }
+ memcpy(&stateless_reset_token, params.stateless_reset_token.data(),
+ params.stateless_reset_token.size());
+ stateless_reset_token_.SetReceivedValue(stateless_reset_token);
+ }
+
+ if (params.max_packet_size.value() < kMaxOutgoingPacketSize) {
+ // 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(
+ std::min<uint64_t>(params.initial_max_data.value(),
+ std::numeric_limits<uint32_t>::max()));
+ max_incoming_bidirectional_streams_.SetReceivedValue(
+ std::min<uint64_t>(params.initial_max_streams_bidi.value(),
+ std::numeric_limits<uint32_t>::max()));
+ max_incoming_unidirectional_streams_.SetReceivedValue(
+ std::min<uint64_t>(params.initial_max_streams_uni.value(),
+ std::numeric_limits<uint32_t>::max()));
+
+ initial_stream_flow_control_window_bytes_.SetReceivedValue(
+ std::min<uint64_t>(params.initial_max_stream_data_bidi_local.value(),
+ std::numeric_limits<uint32_t>::max()));
+
+ connection_migration_disabled_.SetReceivedValue(
+ params.disable_migration ? 1u : 0u);
+
+ if (params.preferred_address != nullptr) {
+ if (params.preferred_address->ipv6_socket_address.port() != 0) {
+ alternate_server_address_.SetReceivedValue(
+ params.preferred_address->ipv6_socket_address);
+ } else if (params.preferred_address->ipv4_socket_address.port() != 0) {
+ alternate_server_address_.SetReceivedValue(
+ params.preferred_address->ipv4_socket_address);
+ }
+ }
+
const CryptoHandshakeMessage* peer_params = params.google_quic_params.get();
if (peer_params != nullptr) {
error =
@@ -808,18 +923,6 @@ QuicErrorCode QuicConfig::ProcessTransportParameters(
}
}
- initial_stream_flow_control_window_bytes_.SetReceivedValue(
- params.initial_max_stream_data);
- initial_session_flow_control_window_bytes_.SetReceivedValue(
- params.initial_max_data);
- if (params.initial_max_bidi_streams.present) {
- max_incoming_dynamic_streams_.SetReceivedValue(
- params.initial_max_bidi_streams.value);
- } else {
- // An absent value for initial_max_bidi_streams is treated as a value of 0.
- max_incoming_dynamic_streams_.SetReceivedValue(0);
- }
-
return QUIC_NO_ERROR;
}
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 8ad161db9ec..ae15b6aae38 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_config.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_config.h
@@ -305,14 +305,24 @@ class QUIC_EXPORT_PRIVATE QuicConfig {
bool SilentClose() const;
- void SetMaxIncomingDynamicStreamsToSend(
- uint32_t max_incoming_dynamic_streams);
-
- uint32_t GetMaxIncomingDynamicStreamsToSend();
-
- bool HasReceivedMaxIncomingDynamicStreams();
-
- uint32_t ReceivedMaxIncomingDynamicStreams();
+ // Configuration for the Google QUIC and IETF QUIC stream ID managers. Note
+ // that the naming is a bit weird; it is from the perspective of the node
+ // generating (sending) the configuration and, thus, The "incoming" counts are
+ // the number of streams that the node sending the configuration is willing to
+ // accept and therefore the number that the node receiving the confguration
+ // can create .. the number of outbound streams that may be intiated..
+ // There are two sets, one for unidirectional streams and one for
+ // bidirectional. The bidirectional set also covers Google-QUICs
+ // dynamic stream count (which are bidirectional streams).
+ void SetMaxIncomingBidirectionalStreamsToSend(uint32_t max_streams);
+ uint32_t GetMaxIncomingBidirectionalStreamsToSend();
+ bool HasReceivedMaxIncomingBidirectionalStreams();
+ uint32_t ReceivedMaxIncomingBidirectionalStreams();
+
+ void SetMaxIncomingUnidirectionalStreamsToSend(uint32_t max_streams);
+ uint32_t GetMaxIncomingUnidirectionalStreamsToSend();
+ bool HasReceivedMaxIncomingUnidirectionalStreams();
+ uint32_t ReceivedMaxIncomingUnidirectionalStreams();
void set_max_time_before_crypto_handshake(
QuicTime::Delta max_time_before_crypto_handshake) {
@@ -412,7 +422,8 @@ class QUIC_EXPORT_PRIVATE QuicConfig {
// ToHandshakeMessage serialises the settings in this object as a series of
// tags /value pairs and adds them to |out|.
- void ToHandshakeMessage(CryptoHandshakeMessage* out) const;
+ void ToHandshakeMessage(CryptoHandshakeMessage* out,
+ QuicTransportVersion transport_version) const;
// Calls ProcessPeerHello on each negotiable parameter. On failure returns
// the corresponding QuicErrorCode and sets detailed error in |error_details|.
@@ -456,8 +467,10 @@ class QUIC_EXPORT_PRIVATE QuicConfig {
QuicNegotiableUint32 idle_network_timeout_seconds_;
// Whether to use silent close. Defaults to 0 (false) and is otherwise true.
QuicNegotiableUint32 silent_close_;
- // Maximum number of incoming dynamic streams that the connection can support.
- QuicFixedUint32 max_incoming_dynamic_streams_;
+ // Maximum number of incoming dynamic streams that a Google QUIC connection
+ // can support or the maximum number of incoming bidirectional streams that
+ // an IETF QUIC connection can support.
+ QuicFixedUint32 max_incoming_bidirectional_streams_;
// The number of bytes required for the connection ID.
QuicFixedUint32 bytes_for_connection_id_;
// Initial round trip time estimate in microseconds.
@@ -484,6 +497,10 @@ class QUIC_EXPORT_PRIVATE QuicConfig {
// be created. This allows for CHLOs that are larger than a single
// packet to be processed.
QuicTagVector create_session_tag_indicators_;
+
+ // Maximum number of incoming unidirectional streams that the connection can
+ // support.
+ QuicFixedUint32 max_incoming_unidirectional_streams_;
};
} // namespace quic
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 c18c5200708..84e89c17d2d 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,12 +21,17 @@ namespace quic {
namespace test {
namespace {
-class QuicConfigTest : public QuicTest {
+class QuicConfigTest : public QuicTestWithParam<QuicTransportVersion> {
protected:
QuicConfig config_;
};
-TEST_F(QuicConfigTest, ToHandshakeMessage) {
+// Run all tests with all versions of QUIC.
+INSTANTIATE_TEST_SUITE_P(QuicConfigTests,
+ QuicConfigTest,
+ ::testing::ValuesIn(AllSupportedTransportVersions()));
+
+TEST_P(QuicConfigTest, ToHandshakeMessage) {
config_.SetInitialStreamFlowControlWindowToSend(
kInitialStreamFlowControlWindowForTest);
config_.SetInitialSessionFlowControlWindowToSend(
@@ -34,7 +39,7 @@ TEST_F(QuicConfigTest, ToHandshakeMessage) {
config_.SetIdleNetworkTimeout(QuicTime::Delta::FromSeconds(5),
QuicTime::Delta::FromSeconds(2));
CryptoHandshakeMessage msg;
- config_.ToHandshakeMessage(&msg);
+ config_.ToHandshakeMessage(&msg, GetParam());
uint32_t value;
QuicErrorCode error = msg.GetUint32(kICSL, &value);
@@ -50,7 +55,7 @@ TEST_F(QuicConfigTest, ToHandshakeMessage) {
EXPECT_EQ(kInitialSessionFlowControlWindowForTest, value);
}
-TEST_F(QuicConfigTest, ProcessClientHello) {
+TEST_P(QuicConfigTest, ProcessClientHello) {
QuicConfig client_config;
QuicTagVector cgst;
cgst.push_back(kQBIC);
@@ -66,7 +71,7 @@ TEST_F(QuicConfigTest, ProcessClientHello) {
copt.push_back(kTBBR);
client_config.SetConnectionOptionsToSend(copt);
CryptoHandshakeMessage msg;
- client_config.ToHandshakeMessage(&msg);
+ client_config.ToHandshakeMessage(&msg, GetParam());
std::string error_details;
QuicTagVector initial_received_options;
@@ -96,7 +101,7 @@ TEST_F(QuicConfigTest, ProcessClientHello) {
2 * kInitialSessionFlowControlWindowForTest);
}
-TEST_F(QuicConfigTest, ProcessServerHello) {
+TEST_P(QuicConfigTest, ProcessServerHello) {
QuicIpAddress host;
host.FromString("127.0.3.1");
const QuicSocketAddress kTestServerAddress = QuicSocketAddress(host, 1234);
@@ -115,7 +120,7 @@ TEST_F(QuicConfigTest, ProcessServerHello) {
server_config.SetAlternateServerAddressToSend(kTestServerAddress);
server_config.SetStatelessResetTokenToSend(kTestResetToken);
CryptoHandshakeMessage msg;
- server_config.ToHandshakeMessage(&msg);
+ server_config.ToHandshakeMessage(&msg, GetParam());
std::string error_details;
const QuicErrorCode error =
config_.ProcessPeerHello(msg, SERVER, &error_details);
@@ -134,13 +139,13 @@ TEST_F(QuicConfigTest, ProcessServerHello) {
EXPECT_EQ(kTestResetToken, config_.ReceivedStatelessResetToken());
}
-TEST_F(QuicConfigTest, MissingOptionalValuesInCHLO) {
+TEST_P(QuicConfigTest, MissingOptionalValuesInCHLO) {
CryptoHandshakeMessage msg;
msg.SetValue(kICSL, 1);
// Set all REQUIRED tags.
msg.SetValue(kICSL, 1);
- msg.SetValue(kMIDS, 1);
+ msg.SetValue(kMIBS, 1);
// No error, as rest are optional.
std::string error_details;
@@ -150,12 +155,12 @@ TEST_F(QuicConfigTest, MissingOptionalValuesInCHLO) {
EXPECT_TRUE(config_.negotiated());
}
-TEST_F(QuicConfigTest, MissingOptionalValuesInSHLO) {
+TEST_P(QuicConfigTest, MissingOptionalValuesInSHLO) {
CryptoHandshakeMessage msg;
// Set all REQUIRED tags.
msg.SetValue(kICSL, 1);
- msg.SetValue(kMIDS, 1);
+ msg.SetValue(kMIBS, 1);
// No error, as rest are optional.
std::string error_details;
@@ -165,7 +170,7 @@ TEST_F(QuicConfigTest, MissingOptionalValuesInSHLO) {
EXPECT_TRUE(config_.negotiated());
}
-TEST_F(QuicConfigTest, MissingValueInCHLO) {
+TEST_P(QuicConfigTest, MissingValueInCHLO) {
// Server receives CHLO with missing kICSL.
CryptoHandshakeMessage msg;
std::string error_details;
@@ -174,7 +179,7 @@ TEST_F(QuicConfigTest, MissingValueInCHLO) {
EXPECT_EQ(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND, error);
}
-TEST_F(QuicConfigTest, MissingValueInSHLO) {
+TEST_P(QuicConfigTest, MissingValueInSHLO) {
// Client receives SHLO with missing kICSL.
CryptoHandshakeMessage msg;
std::string error_details;
@@ -183,21 +188,21 @@ TEST_F(QuicConfigTest, MissingValueInSHLO) {
EXPECT_EQ(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND, error);
}
-TEST_F(QuicConfigTest, OutOfBoundSHLO) {
+TEST_P(QuicConfigTest, OutOfBoundSHLO) {
QuicConfig server_config;
server_config.SetIdleNetworkTimeout(
QuicTime::Delta::FromSeconds(2 * kMaximumIdleTimeoutSecs),
QuicTime::Delta::FromSeconds(2 * kMaximumIdleTimeoutSecs));
CryptoHandshakeMessage msg;
- server_config.ToHandshakeMessage(&msg);
+ server_config.ToHandshakeMessage(&msg, GetParam());
std::string error_details;
const QuicErrorCode error =
config_.ProcessPeerHello(msg, SERVER, &error_details);
EXPECT_EQ(QUIC_INVALID_NEGOTIATED_VALUE, error);
}
-TEST_F(QuicConfigTest, InvalidFlowControlWindow) {
+TEST_P(QuicConfigTest, InvalidFlowControlWindow) {
// QuicConfig should not accept an invalid flow control window to send to the
// peer: the receive window must be at least the default of 16 Kb.
QuicConfig config;
@@ -210,7 +215,7 @@ TEST_F(QuicConfigTest, InvalidFlowControlWindow) {
config.GetInitialStreamFlowControlWindowToSend());
}
-TEST_F(QuicConfigTest, HasClientSentConnectionOption) {
+TEST_P(QuicConfigTest, HasClientSentConnectionOption) {
QuicConfig client_config;
QuicTagVector copt;
copt.push_back(kTBBR);
@@ -219,7 +224,7 @@ TEST_F(QuicConfigTest, HasClientSentConnectionOption) {
kTBBR, Perspective::IS_CLIENT));
CryptoHandshakeMessage msg;
- client_config.ToHandshakeMessage(&msg);
+ client_config.ToHandshakeMessage(&msg, GetParam());
std::string error_details;
const QuicErrorCode error =
@@ -233,14 +238,14 @@ TEST_F(QuicConfigTest, HasClientSentConnectionOption) {
config_.HasClientSentConnectionOption(kTBBR, Perspective::IS_SERVER));
}
-TEST_F(QuicConfigTest, DontSendClientConnectionOptions) {
+TEST_P(QuicConfigTest, DontSendClientConnectionOptions) {
QuicConfig client_config;
QuicTagVector copt;
copt.push_back(kTBBR);
client_config.SetClientConnectionOptions(copt);
CryptoHandshakeMessage msg;
- client_config.ToHandshakeMessage(&msg);
+ client_config.ToHandshakeMessage(&msg, GetParam());
std::string error_details;
const QuicErrorCode error =
@@ -251,7 +256,7 @@ TEST_F(QuicConfigTest, DontSendClientConnectionOptions) {
EXPECT_FALSE(config_.HasReceivedConnectionOptions());
}
-TEST_F(QuicConfigTest, HasClientRequestedIndependentOption) {
+TEST_P(QuicConfigTest, HasClientRequestedIndependentOption) {
QuicConfig client_config;
QuicTagVector client_opt;
client_opt.push_back(kRENO);
@@ -267,7 +272,7 @@ TEST_F(QuicConfigTest, HasClientRequestedIndependentOption) {
kTBBR, Perspective::IS_CLIENT));
CryptoHandshakeMessage msg;
- client_config.ToHandshakeMessage(&msg);
+ client_config.ToHandshakeMessage(&msg, GetParam());
std::string error_details;
const QuicErrorCode error =
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 cb901bafaf3..226a4ccf0eb 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
@@ -16,12 +16,14 @@
#include <utility>
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
+#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
#include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters.pb.h"
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
#include "net/third_party/quiche/src/quic/core/quic_config.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
+#include "net/third_party/quiche/src/quic/core/quic_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"
@@ -181,21 +183,6 @@ class MtuDiscoveryAlarmDelegate : public QuicAlarm::Delegate {
QuicConnection* connection_;
};
-class RetransmittableOnWireAlarmDelegate : public QuicAlarm::Delegate {
- public:
- explicit RetransmittableOnWireAlarmDelegate(QuicConnection* connection)
- : connection_(connection) {}
- RetransmittableOnWireAlarmDelegate(
- const RetransmittableOnWireAlarmDelegate&) = delete;
- RetransmittableOnWireAlarmDelegate& operator=(
- const RetransmittableOnWireAlarmDelegate&) = delete;
-
- void OnAlarm() override { connection_->OnPingTimeout(); }
-
- private:
- QuicConnection* connection_;
-};
-
class ProcessUndecryptablePacketsAlarmDelegate : public QuicAlarm::Delegate {
public:
explicit ProcessUndecryptablePacketsAlarmDelegate(QuicConnection* connection)
@@ -232,7 +219,7 @@ bool PacketCanReplaceConnectionId(const QuicPacketHeader& header,
(perspective_ == Perspective::IS_SERVER ? "Server: " : "Client: ")
QuicConnection::QuicConnection(
- QuicConnectionId connection_id,
+ QuicConnectionId server_connection_id,
QuicSocketAddress initial_peer_address,
QuicConnectionHelperInterface* helper,
QuicAlarmFactory* alarm_factory,
@@ -243,7 +230,7 @@ QuicConnection::QuicConnection(
: framer_(supported_versions,
helper->GetClock()->ApproximateNow(),
perspective,
- connection_id.length()),
+ server_connection_id.length()),
current_packet_content_(NO_FRAMES_RECEIVED),
is_current_packet_connectivity_probing_(false),
current_effective_peer_migration_type_(NO_CHANGE),
@@ -255,7 +242,7 @@ QuicConnection::QuicConnection(
encryption_level_(ENCRYPTION_INITIAL),
clock_(helper->GetClock()),
random_generator_(helper->GetRandomGenerator()),
- connection_id_(connection_id),
+ server_connection_id_(server_connection_id),
peer_address_(initial_peer_address),
direct_peer_address_(initial_peer_address),
active_effective_peer_migration_type_(NO_CHANGE),
@@ -315,7 +302,10 @@ QuicConnection::QuicConnection(
&arena_)),
visitor_(nullptr),
debug_visitor_(nullptr),
- packet_generator_(connection_id_, &framer_, random_generator_, this),
+ packet_generator_(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_(
@@ -328,6 +318,7 @@ QuicConnection::QuicConnection(
sent_packet_manager_(
perspective,
clock_,
+ random_generator_,
&stats_,
GetQuicReloadableFlag(quic_default_to_bbr) ? kBBR : kCubicBytes,
kNack),
@@ -358,9 +349,8 @@ QuicConnection::QuicConnection(
supports_release_time_(false),
release_time_into_future_(QuicTime::Delta::Zero()),
no_version_negotiation_(supported_versions.size() == 1),
- fix_termination_packets_(
- GetQuicReloadableFlag(quic_fix_termination_packets)),
send_ack_when_on_can_write_(false),
+ retry_has_been_parsed_(false),
validate_packet_number_post_decryption_(
GetQuicReloadableFlag(quic_validate_packet_number_post_decryption)),
use_uber_received_packet_manager_(
@@ -386,14 +376,14 @@ QuicConnection::QuicConnection(
if (use_uber_received_packet_manager_) {
QUIC_RELOADABLE_FLAG_COUNT(quic_use_uber_received_packet_manager);
}
- QUIC_DLOG(INFO) << ENDPOINT
- << "Created connection with connection_id: " << connection_id
+ QUIC_DLOG(INFO) << ENDPOINT << "Created connection with server connection ID "
+ << server_connection_id
<< " and version: " << ParsedQuicVersionToString(version());
- QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(connection_id,
+ QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(server_connection_id,
transport_version()))
- << "QuicConnection: attempted to use connection ID " << connection_id
- << " which is invalid with version "
+ << "QuicConnection: attempted to use server connection ID "
+ << server_connection_id << " which is invalid with version "
<< QuicVersionToString(transport_version());
framer_.set_visitor(this);
@@ -421,6 +411,19 @@ QuicConnection::QuicConnection(
DCHECK(!GetQuicRestartFlag(quic_no_server_conn_ver_negotiation2) ||
perspective_ == Perspective::IS_CLIENT ||
supported_versions.size() == 1);
+ InstallInitialCrypters();
+}
+
+void QuicConnection::InstallInitialCrypters() {
+ if (version().handshake_protocol != PROTOCOL_TLS1_3) {
+ // Initial crypters are currently only supported with TLS.
+ return;
+ }
+ CrypterPair crypters;
+ CryptoUtils::CreateTlsInitialCrypters(perspective_, transport_version(),
+ server_connection_id_, &crypters);
+ SetEncrypter(ENCRYPTION_INITIAL, std::move(crypters.encrypter));
+ InstallDecrypter(ENCRYPTION_INITIAL, std::move(crypters.decrypter));
}
QuicConnection::~QuicConnection() {
@@ -457,7 +460,7 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
sent_packet_manager_.SetFromConfig(config);
if (config.HasReceivedBytesForConnectionId() &&
can_truncate_connection_ids_) {
- packet_generator_.SetConnectionIdLength(
+ packet_generator_.SetServerConnectionIdLength(
config.ReceivedBytesForConnectionId());
}
max_undecryptable_packets_ = config.max_undecryptable_packets();
@@ -559,8 +562,10 @@ void QuicConnection::SetMaxPacingRate(QuicBandwidth max_pacing_rate) {
}
void QuicConnection::AdjustNetworkParameters(QuicBandwidth bandwidth,
- QuicTime::Delta rtt) {
- sent_packet_manager_.AdjustNetworkParameters(bandwidth, rtt);
+ QuicTime::Delta rtt,
+ bool allow_cwnd_to_decrease) {
+ sent_packet_manager_.AdjustNetworkParameters(bandwidth, rtt,
+ allow_cwnd_to_decrease);
}
QuicBandwidth QuicConnection::MaxPacingRate() const {
@@ -603,7 +608,7 @@ void QuicConnection::OnPublicResetPacket(const QuicPublicResetPacket& packet) {
// Check that any public reset packet with a different connection ID that was
// routed to this QuicConnection has been redirected before control reaches
// here. (Check for a bug regression.)
- DCHECK_EQ(connection_id_, packet.connection_id);
+ DCHECK_EQ(server_connection_id_, packet.connection_id);
DCHECK_EQ(perspective_, Perspective::IS_CLIENT);
if (debug_visitor_ != nullptr) {
debug_visitor_->OnPublicResetPacket(packet);
@@ -626,8 +631,8 @@ bool QuicConnection::OnProtocolVersionMismatch(
if (perspective_ == Perspective::IS_CLIENT) {
const std::string error_details = "Protocol version mismatch.";
QUIC_BUG << ENDPOINT << error_details;
- TearDownLocalConnectionState(QUIC_INTERNAL_ERROR, error_details,
- ConnectionCloseSource::FROM_SELF);
+ CloseConnection(QUIC_INTERNAL_ERROR, error_details,
+ ConnectionCloseBehavior::SILENT_CLOSE);
return false;
}
if (no_version_negotiation_) {
@@ -694,14 +699,14 @@ void QuicConnection::OnVersionNegotiationPacket(
// Check that any public reset packet with a different connection ID that was
// routed to this QuicConnection has been redirected before control reaches
// here. (Check for a bug regression.)
- DCHECK_EQ(connection_id_, packet.connection_id);
+ DCHECK_EQ(server_connection_id_, packet.connection_id);
if (perspective_ == Perspective::IS_SERVER) {
const std::string error_details =
- "Server receieved version negotiation packet.";
+ "Server received version negotiation packet.";
QUIC_BUG << error_details;
QUIC_CODE_COUNT(quic_tear_down_local_connection_on_version_negotiation);
- TearDownLocalConnectionState(QUIC_INTERNAL_ERROR, error_details,
- ConnectionCloseSource::FROM_SELF);
+ CloseConnection(QUIC_INTERNAL_ERROR, error_details,
+ ConnectionCloseBehavior::SILENT_CLOSE);
return;
}
if (debug_visitor_ != nullptr) {
@@ -718,9 +723,8 @@ void QuicConnection::OnVersionNegotiationPacket(
"Server already supports client's version and should have accepted the "
"connection.";
QUIC_DLOG(WARNING) << error_details;
- TearDownLocalConnectionState(QUIC_INVALID_VERSION_NEGOTIATION_PACKET,
- error_details,
- ConnectionCloseSource::FROM_SELF);
+ CloseConnection(QUIC_INVALID_VERSION_NEGOTIATION_PACKET, error_details,
+ ConnectionCloseBehavior::SILENT_CLOSE);
return;
}
@@ -740,6 +744,7 @@ void QuicConnection::OnVersionNegotiationPacket(
return;
}
+ ParsedQuicVersion original_version = version();
if (!SelectMutualVersion(packet.versions)) {
CloseConnection(
QUIC_INVALID_VERSION,
@@ -752,13 +757,56 @@ void QuicConnection::OnVersionNegotiationPacket(
return;
}
+ if (original_version.handshake_protocol != version().handshake_protocol) {
+ const std::string error_details =
+ "In-connection version negotiation between mismatched handshake "
+ " protocols " +
+ ParsedQuicVersionToString(original_version) + " and " +
+ ParsedQuicVersionToString(version()) + " is currently unsupported.";
+ QUIC_DLOG(WARNING) << error_details;
+ CloseConnection(QUIC_INVALID_VERSION, error_details,
+ ConnectionCloseBehavior::SILENT_CLOSE);
+ return;
+ }
+
QUIC_DLOG(INFO) << ENDPOINT << "Negotiated version: "
- << QuicVersionToString(transport_version());
+ << ParsedQuicVersionToString(version());
no_stop_waiting_frames_ = transport_version() > QUIC_VERSION_43;
version_negotiation_state_ = NEGOTIATION_IN_PROGRESS;
+
RetransmitUnackedPackets(ALL_UNACKED_RETRANSMISSION);
}
+// Handles retry for client connection.
+void QuicConnection::OnRetryPacket(QuicConnectionId original_connection_id,
+ QuicConnectionId new_connection_id,
+ QuicStringPiece retry_token) {
+ DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
+ if (original_connection_id != server_connection_id_) {
+ QUIC_DLOG(ERROR) << "Ignoring RETRY with original connection ID "
+ << original_connection_id << " not matching expected "
+ << server_connection_id_ << " token "
+ << QuicTextUtils::HexEncode(retry_token);
+ return;
+ }
+ if (retry_has_been_parsed_) {
+ QUIC_DLOG(ERROR) << "Ignoring non-first RETRY with token "
+ << QuicTextUtils::HexEncode(retry_token);
+ return;
+ }
+ retry_has_been_parsed_ = true;
+ QUIC_DLOG(INFO) << "Received RETRY, replacing connection ID "
+ << server_connection_id_ << " with " << new_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);
+
+ // Reinstall initial crypters because the connection ID changed.
+ InstallInitialCrypters();
+}
+
bool QuicConnection::HasIncomingConnectionId(QuicConnectionId connection_id) {
for (QuicConnectionId const& incoming_connection_id :
incoming_connection_ids_) {
@@ -778,25 +826,28 @@ void QuicConnection::AddIncomingConnectionId(QuicConnectionId connection_id) {
bool QuicConnection::OnUnauthenticatedPublicHeader(
const QuicPacketHeader& header) {
- if (header.destination_connection_id == connection_id_ ||
- HasIncomingConnectionId(header.destination_connection_id)) {
+ QuicConnectionId server_connection_id =
+ GetServerConnectionIdAsRecipient(header, perspective_);
+
+ if (server_connection_id == server_connection_id_ ||
+ HasIncomingConnectionId(server_connection_id)) {
return true;
}
if (PacketCanReplaceConnectionId(header, perspective_)) {
QUIC_DLOG(INFO) << ENDPOINT << "Accepting packet with new connection ID "
- << header.destination_connection_id << " instead of "
- << connection_id_;
+ << server_connection_id << " instead of "
+ << server_connection_id_;
return true;
}
++stats_.packets_dropped;
QUIC_DLOG(INFO) << ENDPOINT
<< "Ignoring packet from unexpected ConnectionId: "
- << header.destination_connection_id << " instead of "
- << connection_id_;
+ << server_connection_id << " instead of "
+ << server_connection_id_;
if (debug_visitor_ != nullptr) {
- debug_visitor_->OnIncorrectConnectionId(header.destination_connection_id);
+ debug_visitor_->OnIncorrectConnectionId(server_connection_id);
}
// If this is a server, the dispatcher routes each packet to the
// QuicConnection responsible for the packet's connection ID. So if control
@@ -813,8 +864,10 @@ bool QuicConnection::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
// Check that any public reset packet with a different connection ID that was
// routed to this QuicConnection has been redirected before control reaches
// here.
- DCHECK(header.destination_connection_id == connection_id_ ||
- HasIncomingConnectionId(header.destination_connection_id) ||
+ DCHECK(GetServerConnectionIdAsRecipient(header, perspective_) ==
+ server_connection_id_ ||
+ HasIncomingConnectionId(
+ GetServerConnectionIdAsRecipient(header, perspective_)) ||
PacketCanReplaceConnectionId(header, perspective_));
if (!packet_generator_.IsPendingPacketEmpty()) {
@@ -988,7 +1041,7 @@ bool QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) {
if (debug_visitor_ != nullptr) {
debug_visitor_->OnStreamFrame(frame);
}
- if (frame.stream_id != QuicUtils::GetCryptoStreamId(transport_version()) &&
+ if (!QuicUtils::IsCryptoStreamId(transport_version(), frame.stream_id) &&
last_decrypted_packet_level_ == ENCRYPTION_INITIAL) {
if (MaybeConsiderAsMemoryCorruption(frame)) {
CloseConnection(QUIC_MAYBE_CORRUPTED_MEMORY,
@@ -1001,7 +1054,7 @@ bool QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) {
<< "Received an unencrypted data frame: closing connection"
<< " packet_number:" << last_header_.packet_number
<< " stream_id:" << frame.stream_id
- << " received_packets:" << GetUpdatedAckFrame();
+ << " received_packets:" << ack_frame();
CloseConnection(QUIC_UNENCRYPTED_STREAM_DATA,
"Unencrypted stream data seen.",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -1070,7 +1123,7 @@ bool QuicConnection::OnAckFrameStart(QuicPacketNumber largest_acked,
<< " packet_number:" << last_header_.packet_number
<< " largest seen with ack:"
<< GetLargestReceivedPacketWithAck()
- << " connection_id: " << connection_id_;
+ << " server_connection_id: " << server_connection_id_;
// A new ack has a diminished largest_observed value.
// If this was an old packet, we wouldn't even have checked.
CloseConnection(QUIC_INVALID_ACK_DATA, "Largest observed too low.",
@@ -1150,7 +1203,13 @@ 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.
- PostProcessAfterAckFrame(GetLeastUnacked() > start,
+ 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;
+ }
+ PostProcessAfterAckFrame(send_stop_waiting,
ack_result == PACKETS_NEWLY_ACKED);
processing_ack_frame_ = false;
@@ -1335,13 +1394,13 @@ bool QuicConnection::OnConnectionCloseFrame(
return connected_;
}
-bool QuicConnection::OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) {
- return visitor_->OnMaxStreamIdFrame(frame);
+bool QuicConnection::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
+ return visitor_->OnMaxStreamsFrame(frame);
}
-bool QuicConnection::OnStreamIdBlockedFrame(
- const QuicStreamIdBlockedFrame& frame) {
- return visitor_->OnStreamIdBlockedFrame(frame);
+bool QuicConnection::OnStreamsBlockedFrame(
+ const QuicStreamsBlockedFrame& frame) {
+ return visitor_->OnStreamsBlockedFrame(frame);
}
bool QuicConnection::OnGoAwayFrame(const QuicGoAwayFrame& frame) {
@@ -1442,7 +1501,8 @@ void QuicConnection::OnPacketComplete() {
}
QUIC_DVLOG(1) << ENDPOINT << "Got packet " << last_header_.packet_number
- << " for " << last_header_.destination_connection_id;
+ << " for "
+ << GetServerConnectionIdAsRecipient(last_header_, perspective_);
QUIC_DLOG_IF(INFO, current_packet_content_ == SECOND_FRAME_IS_PADDING)
<< ENDPOINT << "Received a padded PING packet. is_probing: "
@@ -1451,7 +1511,8 @@ void QuicConnection::OnPacketComplete() {
if (perspective_ == Perspective::IS_CLIENT) {
QUIC_DVLOG(1) << ENDPOINT
<< "Received a speculative connectivity probing packet for "
- << last_header_.destination_connection_id
+ << GetServerConnectionIdAsRecipient(last_header_,
+ perspective_)
<< " from ip:port: " << last_packet_source_address_.ToString()
<< " to ip:port: "
<< last_packet_destination_address_.ToString();
@@ -1462,7 +1523,8 @@ void QuicConnection::OnPacketComplete() {
// This node is not a client (is a server) AND the received packet was
// connectivity-probing, send an appropriate response.
QUIC_DVLOG(1) << ENDPOINT << "Received a connectivity probing packet for "
- << last_header_.destination_connection_id
+ << GetServerConnectionIdAsRecipient(last_header_,
+ perspective_)
<< " from ip:port: " << last_packet_source_address_.ToString()
<< " to ip:port: "
<< last_packet_destination_address_.ToString();
@@ -1502,11 +1564,31 @@ void QuicConnection::OnPacketComplete() {
if (received_packet_manager_.decide_when_to_send_acks()) {
if (use_uber_received_packet_manager_) {
- uber_received_packet_manager_.MaybeUpdateAckTimeout(
- should_last_packet_instigate_acks_, last_decrypted_packet_level_,
- last_header_.packet_number, time_of_last_received_packet_,
- clock_->ApproximateNow(), sent_packet_manager_.GetRttStats(),
- sent_packet_manager_.delayed_ack_time());
+ // Some encryption levels share a packet number space, it is therefore
+ // possible for us to want to ack some packets even though we do not yet
+ // have the appropriate keys to encrypt the acks. In this scenario we
+ // do not update the ACK timeout. This can happen for example with
+ // IETF QUIC on the server when we receive 0-RTT packets and do not yet
+ // have 1-RTT keys (0-RTT packets are acked at the 1-RTT level).
+ // Note that this could cause slight performance degradations in the edge
+ // case where one packet is received, then the encrypter is installed,
+ // then a second packet is received; as that could cause the ACK for the
+ // second packet to be delayed instead of immediate. This is currently
+ // considered to be small enough of an edge case to not be optimized for.
+ if (!SupportsMultiplePacketNumberSpaces() ||
+ framer_.HasEncrypterOfEncryptionLevel(QuicUtils::GetEncryptionLevel(
+ QuicUtils::GetPacketNumberSpace(last_decrypted_packet_level_)))) {
+ uber_received_packet_manager_.MaybeUpdateAckTimeout(
+ should_last_packet_instigate_acks_, last_decrypted_packet_level_,
+ last_header_.packet_number, time_of_last_received_packet_,
+ clock_->ApproximateNow(), sent_packet_manager_.GetRttStats(),
+ sent_packet_manager_.delayed_ack_time());
+ } else {
+ QUIC_DLOG(INFO) << ENDPOINT << "Not updating ACK timeout for "
+ << QuicUtils::EncryptionLevelToString(
+ last_decrypted_packet_level_)
+ << " as we do not have the corresponding encrypter";
+ }
} else {
received_packet_manager_.MaybeUpdateAckTimeout(
should_last_packet_instigate_acks_, last_header_.packet_number,
@@ -1725,10 +1807,15 @@ void QuicConnection::SendVersionNegotiationPacket(bool ietf_quic) {
QUIC_DLOG(INFO) << ENDPOINT << "Sending version negotiation packet: {"
<< ParsedQuicVersionVectorToString(
framer_.supported_versions())
- << "}, ietf_quic: " << ietf_quic;
+ << "}, " << (ietf_quic ? "" : "!") << "ietf_quic";
std::unique_ptr<QuicEncryptedPacket> version_packet(
packet_generator_.SerializeVersionNegotiationPacket(
ietf_quic, framer_.supported_versions()));
+ QUIC_DVLOG(2) << ENDPOINT << "Sending version negotiation packet: {"
+ << ParsedQuicVersionVectorToString(framer_.supported_versions())
+ << "}, " << (ietf_quic ? "" : "!") << "ietf_quic:" << std::endl
+ << QuicTextUtils::HexDump(QuicStringPiece(
+ version_packet->data(), version_packet->length()));
WriteResult result = writer_->WritePacket(
version_packet->data(), version_packet->length(), self_address().host(),
peer_address(), per_packet_options_);
@@ -1779,13 +1866,19 @@ QuicConsumedData QuicConnection::SendStreamData(QuicStreamId id,
}
bool QuicConnection::SendControlFrame(const QuicFrame& frame) {
- if (!CanWrite(HAS_RETRANSMITTABLE_DATA) && frame.type != PING_FRAME) {
+ if (!packet_generator_.deprecate_queued_control_frames() &&
+ !CanWrite(HAS_RETRANSMITTABLE_DATA) && frame.type != PING_FRAME) {
QUIC_DVLOG(1) << ENDPOINT << "Failed to send control frame: " << frame;
// Do not check congestion window for ping.
return false;
}
ScopedPacketFlusher flusher(this, SEND_ACK_IF_PENDING);
- packet_generator_.AddControlFrame(frame);
+ const bool consumed =
+ packet_generator_.ConsumeRetransmittableControlFrame(frame);
+ if (packet_generator_.deprecate_queued_control_frames() && !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();
@@ -1922,6 +2015,7 @@ void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address,
// If we are unable to decrypt this packet, it might be
// because the CHLO or SHLO packet was lost.
if (framer_.error() == QUIC_DECRYPTION_FAILURE) {
+ ++stats_.undecryptable_packets_received;
if (encryption_level_ != ENCRYPTION_FORWARD_SECURE &&
undecryptable_packets_.size() < max_undecryptable_packets_) {
QueueUndecryptablePacket(packet);
@@ -2064,11 +2158,12 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
}
if (PacketCanReplaceConnectionId(header, perspective_) &&
- connection_id_ != header.source_connection_id) {
- QUIC_DLOG(INFO) << ENDPOINT << "Replacing connection ID " << connection_id_
- << " with " << header.source_connection_id;
- connection_id_ = header.source_connection_id;
- packet_generator_.SetConnectionId(connection_id_);
+ server_connection_id_ != header.source_connection_id) {
+ QUIC_DLOG(INFO) << ENDPOINT << "Replacing connection ID "
+ << server_connection_id_ << " with "
+ << header.source_connection_id;
+ server_connection_id_ = header.source_connection_id;
+ packet_generator_.SetServerConnectionId(server_connection_id_);
}
if (!ValidateReceivedPacketNumber(header.packet_number)) {
@@ -2260,10 +2355,7 @@ void QuicConnection::WritePendingRetransmissions() {
void QuicConnection::SendProbingRetransmissions() {
while (sent_packet_manager_.GetSendAlgorithm()->ShouldSendProbingPacket() &&
CanWrite(HAS_RETRANSMITTABLE_DATA)) {
- const bool can_retransmit =
- sent_packet_manager_.MaybeRetransmitOldestPacket(
- PROBING_RETRANSMISSION);
- if (!can_retransmit) {
+ if (!visitor_->SendProbingData()) {
QUIC_DVLOG(1)
<< "Cannot send probing retransmissions: nothing to retransmit.";
break;
@@ -2324,7 +2416,14 @@ const QuicFrames QuicConnection::MaybeBundleAckOpportunistically() {
ResetAckStates();
QUIC_DVLOG(1) << ENDPOINT << "Bundle an ACK opportunistically";
- frames.push_back(GetUpdatedAckFrame());
+ QuicFrame updated_ack_frame = GetUpdatedAckFrame();
+ QUIC_BUG_IF(updated_ack_frame.ack_frame->packets.Empty())
+ << ENDPOINT << "Attempted to opportunistically bundle an empty "
+ << QuicUtils::EncryptionLevelToString(encryption_level_) << " ACK, "
+ << (has_pending_ack ? "" : "!") << "has_pending_ack, stop_waiting_count_ "
+ << stop_waiting_count_;
+ frames.push_back(updated_ack_frame);
+
if (!no_stop_waiting_frames_) {
QuicStopWaitingFrame stop_waiting;
PopulateStopWaitingFrame(&stop_waiting);
@@ -2623,9 +2722,8 @@ void QuicConnection::OnWriteError(int error_code) {
QUIC_LOG_FIRST_N(ERROR, 2) << ENDPOINT << error_details;
switch (error_code) {
case QUIC_EMSGSIZE:
- CloseConnection(
- QUIC_PACKET_WRITE_ERROR, error_details,
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET_WITH_NO_ACK);
+ CloseConnection(QUIC_PACKET_WRITE_ERROR, error_details,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
break;
default:
// We can't send an error as the socket is presumably borked.
@@ -2635,8 +2733,8 @@ void QuicConnection::OnWriteError(int error_code) {
QUIC_CODE_COUNT(
quic_tear_down_local_connection_on_write_error_non_ietf);
}
- TearDownLocalConnectionState(QUIC_PACKET_WRITE_ERROR, error_details,
- ConnectionCloseSource::FROM_SELF);
+ CloseConnection(QUIC_PACKET_WRITE_ERROR, error_details,
+ ConnectionCloseBehavior::SILENT_CLOSE);
}
}
@@ -2647,7 +2745,7 @@ char* QuicConnection::GetPacketBuffer() {
void QuicConnection::OnSerializedPacket(SerializedPacket* serialized_packet) {
if (serialized_packet->encrypted_buffer == nullptr) {
// We failed to serialize the packet, so close the connection.
- // TearDownLocalConnectionState does not send close packet, so no infinite
+ // Specify that the close is silent, that no packet be sent, so no infinite
// loop here.
// TODO(ianswett): This is actually an internal error, not an
// encryption failure.
@@ -2658,10 +2756,9 @@ void QuicConnection::OnSerializedPacket(SerializedPacket* serialized_packet) {
QUIC_CODE_COUNT(
quic_tear_down_local_connection_on_serialized_packet_non_ietf);
}
- TearDownLocalConnectionState(
- QUIC_ENCRYPTION_FAILURE,
- "Serialized packet does not have an encrypted buffer.",
- ConnectionCloseSource::FROM_SELF);
+ CloseConnection(QUIC_ENCRYPTION_FAILURE,
+ "Serialized packet does not have an encrypted buffer.",
+ ConnectionCloseBehavior::SILENT_CLOSE);
return;
}
@@ -2677,8 +2774,7 @@ void QuicConnection::OnSerializedPacket(SerializedPacket* serialized_packet) {
}
void QuicConnection::OnUnrecoverableError(QuicErrorCode error,
- const std::string& error_details,
- ConnectionCloseSource source) {
+ const std::string& error_details) {
// The packet creator or generator encountered an unrecoverable error: tear
// down local connection state immediately.
if (transport_version() > QUIC_VERSION_43) {
@@ -2688,7 +2784,7 @@ void QuicConnection::OnUnrecoverableError(QuicErrorCode error,
QUIC_CODE_COUNT(
quic_tear_down_local_connection_on_unrecoverable_error_non_ietf);
}
- TearDownLocalConnectionState(error, error_details, source);
+ CloseConnection(error, error_details, ConnectionCloseBehavior::SILENT_CLOSE);
}
void QuicConnection::OnCongestionChange() {
@@ -2749,11 +2845,13 @@ void QuicConnection::OnPingTimeout() {
sent_packet_manager_.enable_half_rtt_tail_loss_probe();
if (enable_half_rtt_tail_loss_probe &&
GetQuicReloadableFlag(quic_ignore_tlpr_if_sending_ping)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_ignore_tlpr_if_sending_ping, 1, 2);
sent_packet_manager_.set_enable_half_rtt_tail_loss_probe(false);
}
visitor_->SendPing();
if (enable_half_rtt_tail_loss_probe &&
GetQuicReloadableFlag(quic_ignore_tlpr_if_sending_ping)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_ignore_tlpr_if_sending_ping, 2, 2);
sent_packet_manager_.set_enable_half_rtt_tail_loss_probe(true);
}
}
@@ -2977,6 +3075,7 @@ void QuicConnection::MaybeProcessCoalescedPackets() {
// If we are unable to decrypt this packet, it might be
// because the CHLO or SHLO packet was lost.
if (framer_.error() == QUIC_DECRYPTION_FAILURE) {
+ ++stats_.undecryptable_packets_received;
if (encryption_level_ != ENCRYPTION_FORWARD_SECURE &&
undecryptable_packets_.size() < max_undecryptable_packets_) {
QueueUndecryptablePacket(*packet);
@@ -3007,13 +3106,8 @@ void QuicConnection::CloseConnection(
<< ", with error: " << QuicErrorCodeToString(error) << " ("
<< error << "), and details: " << error_details;
- if (connection_close_behavior ==
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET) {
- SendConnectionClosePacket(error, error_details, SEND_ACK);
- } else if (connection_close_behavior ==
- ConnectionCloseBehavior::
- SEND_CONNECTION_CLOSE_PACKET_WITH_NO_ACK) {
- SendConnectionClosePacket(error, error_details, NO_ACK);
+ if (connection_close_behavior != ConnectionCloseBehavior::SILENT_CLOSE) {
+ SendConnectionClosePacket(error, error_details);
}
ConnectionCloseSource source = ConnectionCloseSource::FROM_SELF;
@@ -3022,18 +3116,17 @@ void QuicConnection::CloseConnection(
// Regard stateless rejected connection as closed by server.
source = ConnectionCloseSource::FROM_PEER;
}
+
TearDownLocalConnectionState(error, error_details, source);
}
void QuicConnection::SendConnectionClosePacket(QuicErrorCode error,
- const std::string& details,
- AckBundling ack_mode) {
+ const std::string& details) {
QUIC_DLOG(INFO) << ENDPOINT << "Sending connection close packet.";
- if (fix_termination_packets_) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_fix_termination_packets);
- SetDefaultEncryptionLevel(GetConnectionCloseEncryptionLevel());
- }
+ SetDefaultEncryptionLevel(GetConnectionCloseEncryptionLevel());
ClearQueuedPackets();
+ // If there was a packet write error, write the smallest close possible.
+ AckBundling ack_mode = (error == QUIC_PACKET_WRITE_ERROR) ? NO_ACK : SEND_ACK;
ScopedPacketFlusher flusher(this, ack_mode);
// When multiple packet number spaces is supported, an ACK frame will be
// bundled when connection is not write blocked.
@@ -3049,7 +3142,7 @@ void QuicConnection::SendConnectionClosePacket(QuicErrorCode error,
if (transport_version() == QUIC_VERSION_99) {
frame->close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE;
}
- packet_generator_.AddControlFrame(QuicFrame(frame));
+ packet_generator_.ConsumeRetransmittableControlFrame(QuicFrame(frame));
packet_generator_.FlushAllQueuedFrames();
}
@@ -3085,6 +3178,7 @@ void QuicConnection::CancelAllAlarms() {
timeout_alarm_->Cancel();
mtu_discovery_alarm_->Cancel();
path_degrading_alarm_->Cancel();
+ process_undecryptable_packets_alarm_->Cancel();
}
QuicByteCount QuicConnection::max_packet_length() const {
@@ -3204,12 +3298,13 @@ void QuicConnection::SetTimeoutAlarm() {
void QuicConnection::SetPingAlarm() {
if (perspective_ == Perspective::IS_SERVER) {
- // Only clients send pings.
+ // Only clients send pings to avoid NATs from timing out.
return;
}
if (!visitor_->ShouldKeepConnectionAlive()) {
ping_alarm_->Cancel();
- // Don't send a ping unless there are open streams.
+ // Don't send a ping unless the application (ie: HTTP/3) says to, usually
+ // because it is expecting a response from the server.
return;
}
if (retransmittable_on_wire_timeout_.IsInfinite() ||
@@ -3517,7 +3612,7 @@ bool QuicConnection::SendGenericPathProbePacket(
QUIC_DLOG(INFO) << ENDPOINT
<< "Sending path probe packet for connection_id = "
- << connection_id_;
+ << server_connection_id_;
OwningSerializedPacketPointer probing_packet;
if (transport_version() != QUIC_VERSION_99) {
@@ -3559,6 +3654,12 @@ bool QuicConnection::SendGenericPathProbePacket(
DCHECK_EQ(IsRetransmittable(*probing_packet), NO_RETRANSMITTABLE_DATA);
const QuicTime packet_send_time = clock_->Now();
+ QUIC_DVLOG(2) << ENDPOINT
+ << "Sending path probe packet for server connection ID "
+ << server_connection_id_ << std::endl
+ << QuicTextUtils::HexDump(
+ QuicStringPiece(probing_packet->encrypted_buffer,
+ probing_packet->encrypted_length));
WriteResult result = probing_writer->WritePacket(
probing_packet->encrypted_buffer, probing_packet->encrypted_length,
self_address().host(), peer_address, per_packet_options_);
@@ -3683,7 +3784,7 @@ QuicStringPiece QuicConnection::GetCurrentPacket() {
bool QuicConnection::MaybeConsiderAsMemoryCorruption(
const QuicStreamFrame& frame) {
- if (frame.stream_id == QuicUtils::GetCryptoStreamId(transport_version()) ||
+ if (QuicUtils::IsCryptoStreamId(transport_version(), frame.stream_id) ||
last_decrypted_packet_level_ != ENCRYPTION_INITIAL) {
return false;
}
@@ -3830,8 +3931,6 @@ void QuicConnection::PostProcessAfterAckFrame(bool send_stop_waiting,
SetRetransmissionAlarm();
MaybeSetPathDegradingAlarm(acked_new_packet);
- // TODO(ianswett): Only increment stop_waiting_count_ if StopWaiting frames
- // are sent.
if (send_stop_waiting) {
++stop_waiting_count_;
} else {
@@ -3948,13 +4047,14 @@ bool QuicConnection::ShouldSetAckAlarm() const {
}
EncryptionLevel QuicConnection::GetConnectionCloseEncryptionLevel() const {
- DCHECK(fix_termination_packets_);
if (perspective_ == Perspective::IS_CLIENT) {
return encryption_level_;
}
if (sent_packet_manager_.handshake_confirmed()) {
// A forward secure packet has been received.
- QUIC_BUG_IF(encryption_level_ != ENCRYPTION_FORWARD_SECURE);
+ QUIC_BUG_IF(encryption_level_ != ENCRYPTION_FORWARD_SECURE)
+ << ENDPOINT << "Unexpected connection close encryption level "
+ << QuicUtils::EncryptionLevelToString(encryption_level_);
return ENCRYPTION_FORWARD_SECURE;
}
if (framer_.HasEncrypterOfEncryptionLevel(ENCRYPTION_ZERO_RTT)) {
@@ -3982,6 +4082,13 @@ void QuicConnection::SendAllPendingAcks() {
ack_timeout > clock_->ApproximateNow()) {
continue;
}
+ if (!framer_.HasEncrypterOfEncryptionLevel(
+ QuicUtils::GetEncryptionLevel(static_cast<PacketNumberSpace>(i)))) {
+ QUIC_BUG << ENDPOINT << "Cannot send ACKs for packet number space "
+ << static_cast<uint32_t>(i)
+ << " without corresponding encrypter";
+ continue;
+ }
QUIC_DVLOG(1) << ENDPOINT << "Sending ACK of packet number space: "
<< static_cast<uint32_t>(i);
// Switch to the appropriate encryption level.
@@ -4137,5 +4244,16 @@ void QuicConnection::set_ack_frequency_before_ack_decimation(size_t new_value) {
}
}
+const QuicAckFrame& QuicConnection::ack_frame() const {
+ if (SupportsMultiplePacketNumberSpaces()) {
+ return uber_received_packet_manager_.GetAckFrame(
+ QuicUtils::GetPacketNumberSpace(last_decrypted_packet_level_));
+ }
+ if (use_uber_received_packet_manager_) {
+ return uber_received_packet_manager_.ack_frame();
+ }
+ return received_packet_manager_.ack_frame();
+}
+
#undef ENDPOINT // undef for jumbo builds
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection.h b/chromium/net/third_party/quiche/src/quic/core/quic_connection.h
index c921d1b202a..9392f26e949 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
@@ -116,12 +116,11 @@ class QUIC_EXPORT_PRIVATE QuicConnectionVisitorInterface {
// Called when |message| has been received.
virtual void OnMessageReceived(QuicStringPiece message) = 0;
- // Called when a MAX_STREAM_ID frame has been received from the peer.
- virtual bool OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) = 0;
+ // Called when a MAX_STREAMS frame has been received from the peer.
+ virtual bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) = 0;
- // Called when a STREAM_ID_BLOCKED frame has been received from the peer.
- virtual bool OnStreamIdBlockedFrame(
- const QuicStreamIdBlockedFrame& frame) = 0;
+ // Called when a STREAMS_BLOCKED frame has been received from the peer.
+ virtual bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) = 0;
// Called when the connection is closed either locally by the framer, or
// remotely by the peer.
@@ -144,6 +143,10 @@ class QUIC_EXPORT_PRIVATE QuicConnectionVisitorInterface {
// Called when a blocked socket becomes writable.
virtual void OnCanWrite() = 0;
+ // Called when the connection needs more data to probe for additional
+ // bandwidth. Returns true if data was sent, false otherwise.
+ virtual bool SendProbingData() = 0;
+
// Called when the connection experiences a change in congestion window.
virtual void OnCongestionWindowChange(QuicTime now) = 0;
@@ -338,7 +341,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// |initial_peer_address| using |writer| to write packets. |owns_writer|
// specifies whether the connection takes ownership of |writer|. |helper| must
// outlive this connection.
- QuicConnection(QuicConnectionId connection_id,
+ QuicConnection(QuicConnectionId server_connection_id,
QuicSocketAddress initial_peer_address,
QuicConnectionHelperInterface* helper,
QuicAlarmFactory* alarm_factory,
@@ -371,7 +374,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Allows the client to adjust network parameters based on external
// information.
- void AdjustNetworkParameters(QuicBandwidth bandwidth, QuicTime::Delta rtt);
+ void AdjustNetworkParameters(QuicBandwidth bandwidth,
+ QuicTime::Delta rtt,
+ bool allow_cwnd_to_decrease);
// Returns the max pacing rate for the connection.
virtual QuicBandwidth MaxPacingRate() const;
@@ -478,6 +483,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
void OnPublicResetPacket(const QuicPublicResetPacket& packet) override;
void OnVersionNegotiationPacket(
const QuicVersionNegotiationPacket& packet) override;
+ void OnRetryPacket(QuicConnectionId original_connection_id,
+ QuicConnectionId new_connection_id,
+ QuicStringPiece retry_token) override;
bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override;
bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
void OnDecryptedPacket(EncryptionLevel level) override;
@@ -500,8 +508,8 @@ class QUIC_EXPORT_PRIVATE QuicConnection
bool OnPathChallengeFrame(const QuicPathChallengeFrame& frame) override;
bool OnPathResponseFrame(const QuicPathResponseFrame& frame) override;
bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override;
- bool OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) override;
- bool OnStreamIdBlockedFrame(const QuicStreamIdBlockedFrame& frame) override;
+ bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override;
+ bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
bool OnBlockedFrame(const QuicBlockedFrame& frame) override;
bool OnNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame) override;
@@ -514,21 +522,20 @@ class QUIC_EXPORT_PRIVATE QuicConnection
void OnAuthenticatedIetfStatelessResetPacket(
const QuicIetfStatelessResetPacket& packet) override;
- // QuicConnectionCloseDelegateInterface
- void OnUnrecoverableError(QuicErrorCode error,
- const std::string& error_details,
- ConnectionCloseSource source) override;
-
// QuicPacketGenerator::DelegateInterface
bool ShouldGeneratePacket(HasRetransmittableData retransmittable,
IsHandshake handshake) override;
const QuicFrames MaybeBundleAckOpportunistically() override;
+ // Please note, this is not a const function. For logging purpose, please use
+ // ack_frame().
const QuicFrame GetUpdatedAckFrame() override;
void PopulateStopWaitingFrame(QuicStopWaitingFrame* stop_waiting) override;
// QuicPacketCreator::DelegateInterface
char* GetPacketBuffer() override;
void OnSerializedPacket(SerializedPacket* packet) override;
+ void OnUnrecoverableError(QuicErrorCode error,
+ const std::string& error_details) override;
// QuicSentPacketManager::NetworkChangeVisitor
void OnCongestionChange() override;
@@ -574,7 +581,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
const QuicSocketAddress& effective_peer_address() const {
return effective_peer_address_;
}
- QuicConnectionId connection_id() const { return connection_id_; }
+ QuicConnectionId connection_id() const { return server_connection_id_; }
const QuicClock* clock() const { return clock_; }
QuicRandom* random_generator() const { return random_generator_; }
QuicByteCount max_packet_length() const;
@@ -833,8 +840,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
bool session_decides_what_to_write() const;
- void SetRetransmittableOnWireAlarm();
-
// 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.
@@ -883,6 +888,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Returns true if this connection supports multiple packet number spaces.
bool SupportsMultiplePacketNumberSpaces() const;
+ // For logging purpose.
+ const QuicAckFrame& ack_frame() const;
+
protected:
// Calls cancel() on all the alarms owned by this connection.
void CancelAllAlarms();
@@ -930,13 +938,10 @@ class QUIC_EXPORT_PRIVATE QuicConnection
return active_effective_peer_migration_type_;
}
- // Sends the connection close packet to the peer. |ack_mode| determines
- // whether ack frame will be bundled with the connection close packet.
- // TODO(fayang): change |ack_mode| to bool |force_sending_ack| when
- // deprecating quic_deprecate_ack_bundling_mode.
+ // Sends a connection close packet to the peer and includes an ACK if the ACK
+ // is not empty, the |error| is not PACKET_WRITE_ERROR, and it fits.
virtual void SendConnectionClosePacket(QuicErrorCode error,
- const std::string& details,
- AckBundling ack_mode);
+ const std::string& details);
// Returns true if the packet should be discarded and not sent.
virtual bool ShouldDiscardPacket(const SerializedPacket& packet);
@@ -968,7 +973,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
typedef std::list<SerializedPacket> QueuedPacketList;
// Notifies the visitor of the close and marks the connection as disconnected.
- // Does not send a connection close frame to the peer.
+ // Does not send a connection close frame to the peer. It should only be
+ // called by CloseConnection or OnConnectionCloseFrame, OnPublicResetPacket,
+ // and OnAuthenticatedIetfStatelessResetPacket.
void TearDownLocalConnectionState(QuicErrorCode error,
const std::string& details,
ConnectionCloseSource source);
@@ -1137,6 +1144,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Whether incoming_connection_ids_ contains connection_id.
bool HasIncomingConnectionId(QuicConnectionId connection_id);
+ // Install encrypter and decrypter for ENCRYPTION_INITIAL.
+ void InstallInitialCrypters();
+
QuicFramer framer_;
// Contents received in the current packet, especially used to identify
@@ -1162,7 +1172,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
const QuicClock* clock_;
QuicRandom* random_generator_;
- QuicConnectionId connection_id_;
+ QuicConnectionId server_connection_id_;
// Address on the last successfully processed packet received from the
// direct peer.
QuicSocketAddress self_address_;
@@ -1278,6 +1288,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
QuicPacketCount num_packets_received_since_last_ack_sent_;
// 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.
int stop_waiting_count_;
// TODO(fayang): Remove ack_mode_, ack_decimation_delay_,
// unlimited_ack_decimation_, fast_ack_after_quiescence_ when deprecating
@@ -1502,9 +1513,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// vector to improve performance since it is expected to be very small.
std::vector<QuicConnectionId> incoming_connection_ids_;
- // Latched value of quic_fix_termination_packets.
- const bool fix_termination_packets_;
-
// Indicates whether an ACK needs to be sent in OnCanWrite(). Only used when
// deprecate_ack_bundling_mode is true.
// TODO(fayang): Remove this when ACK sending logic is moved to received
@@ -1512,6 +1520,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// needs to be sent.
bool send_ack_when_on_can_write_;
+ // Indicates whether a RETRY packet has been parsed.
+ bool retry_has_been_parsed_;
+
// Latched value of quic_validate_packet_number_post_decryption.
const bool validate_packet_number_post_decryption_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_close_delegate_interface.h b/chromium/net/third_party/quiche/src/quic/core/quic_connection_close_delegate_interface.h
deleted file mode 100644
index b245f4c16a9..00000000000
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection_close_delegate_interface.h
+++ /dev/null
@@ -1,29 +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_CONNECTION_CLOSE_DELEGATE_INTERFACE_H_
-#define QUICHE_QUIC_CORE_QUIC_CONNECTION_CLOSE_DELEGATE_INTERFACE_H_
-
-#include <string>
-
-#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
-#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-
-namespace quic {
-
-// Pure virtual class to close connection on unrecoverable errors.
-class QUIC_EXPORT_PRIVATE QuicConnectionCloseDelegateInterface {
- public:
- virtual ~QuicConnectionCloseDelegateInterface() {}
-
- // Called when an unrecoverable error is encountered.
- virtual void OnUnrecoverableError(QuicErrorCode error,
- const std::string& error_details,
- ConnectionCloseSource source) = 0;
-};
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_CORE_QUIC_CONNECTION_CLOSE_DELEGATE_INTERFACE_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_test.cc
index c855192c8c8..bbe04f95c2c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection_id_test.cc
@@ -8,7 +8,6 @@
#include <cstring>
#include <string>
-#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
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 4d5c578c3a6..246b9f1200c 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
@@ -29,6 +29,7 @@ QuicConnectionStats::QuicConnectionStats()
slowstart_duration(QuicTime::Delta::Zero()),
slowstart_start_time(QuicTime::Zero()),
packets_dropped(0),
+ undecryptable_packets_received(0),
crypto_retransmit_count(0),
loss_timeout_count(0),
tlp_count(0),
@@ -71,6 +72,7 @@ std::ostream& operator<<(std::ostream& os, const QuicConnectionStats& s) {
os << " slowstart_packets_lost: " << s.slowstart_packets_lost;
os << " slowstart_bytes_lost: " << s.slowstart_bytes_lost;
os << " packets_dropped: " << s.packets_dropped;
+ os << " undecryptable_packets_received: " << s.undecryptable_packets_received;
os << " crypto_retransmit_count: " << s.crypto_retransmit_count;
os << " loss_timeout_count: " << s.loss_timeout_count;
os << " tlp_count: " << s.tlp_count;
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 df2f7f8ba7d..5317c7a6180 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
@@ -66,6 +66,10 @@ struct QUIC_EXPORT_PRIVATE QuicConnectionStats {
QuicTime slowstart_start_time;
QuicPacketCount packets_dropped; // Duplicate or less than least unacked.
+
+ // Packets that failed to decrypt when they were first received.
+ QuicPacketCount undecryptable_packets_received;
+
size_t crypto_retransmit_count;
// Count of times the loss detection alarm fired. At least one packet should
// be lost when the alarm fires.
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 56b0453b51a..554f71a59c9 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
@@ -65,8 +65,8 @@ namespace quic {
namespace test {
namespace {
-const char data1[] = "foo";
-const char data2[] = "bar";
+const char data1[] = "foo data";
+const char data2[] = "bar data";
const bool kHasStopWaiting = true;
@@ -660,7 +660,7 @@ class TestConnection : public QuicConnection {
QuicStreamOffset offset,
StreamSendingState state) {
ScopedPacketFlusher flusher(this, NO_ACK);
- if (id != QuicUtils::GetCryptoStreamId(transport_version()) &&
+ if (!QuicUtils::IsCryptoStreamId(transport_version(), id) &&
this->encryption_level() == ENCRYPTION_INITIAL) {
this->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
}
@@ -709,6 +709,11 @@ class TestConnection : public QuicConnection {
QuicConsumedData SendCryptoStreamData() {
QuicStreamOffset offset = 0;
QuicStringPiece data("chlo");
+ return SendCryptoDataWithString(data, offset);
+ }
+
+ QuicConsumedData SendCryptoDataWithString(QuicStringPiece data,
+ QuicStreamOffset offset) {
if (!QuicVersionUsesCryptoFrames(transport_version())) {
return SendStreamDataWithString(
QuicUtils::GetCryptoStreamId(transport_version()), data, offset,
@@ -806,8 +811,7 @@ class TestConnection : public QuicConnection {
}
QuicByteCount GetBytesInFlight() {
- return QuicSentPacketManagerPeer::GetBytesInFlight(
- QuicConnectionPeer::GetSentPacketManager(this));
+ return QuicConnectionPeer::GetSentPacketManager(this)->GetBytesInFlight();
}
void set_notifier(SimpleSessionNotifier* notifier) { notifier_ = notifier; }
@@ -816,6 +820,8 @@ class TestConnection : public QuicConnection {
next_effective_peer_addr_ = QuicMakeUnique<QuicSocketAddress>(addr);
}
+ SimpleDataProducer* producer() { return &producer_; }
+
using QuicConnection::active_effective_peer_migration_type;
using QuicConnection::IsCurrentPacketConnectivityProbing;
using QuicConnection::SelectMutualVersion;
@@ -869,7 +875,7 @@ struct TestParams {
// Constructs various test permutations.
std::vector<TestParams> GetTestParams() {
QuicFlagSaver flags;
- SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
std::vector<TestParams> params;
ParsedQuicVersionVector all_supported_versions = AllSupportedVersions();
for (size_t i = 0; i < all_supported_versions.size(); ++i) {
@@ -877,11 +883,11 @@ std::vector<TestParams> GetTestParams() {
{AckResponse::kDefer, AckResponse::kImmediate}) {
for (bool no_stop_waiting : {true, false}) {
// After version 43, never use STOP_WAITING.
- if (all_supported_versions[i].transport_version <= QUIC_VERSION_43 ||
- no_stop_waiting) {
- params.push_back(TestParams(all_supported_versions[i], ack_response,
- no_stop_waiting));
- }
+ params.push_back(TestParams(
+ all_supported_versions[i], ack_response,
+ all_supported_versions[i].transport_version <= QUIC_VERSION_43
+ ? no_stop_waiting
+ : true));
}
}
}
@@ -918,21 +924,29 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
creator_(QuicConnectionPeer::GetPacketCreator(&connection_)),
generator_(QuicConnectionPeer::GetPacketGenerator(&connection_)),
manager_(QuicConnectionPeer::GetSentPacketManager(&connection_)),
- frame1_(QuicUtils::GetCryptoStreamId(version().transport_version),
- false,
- 0,
- QuicStringPiece(data1)),
- frame2_(QuicUtils::GetCryptoStreamId(version().transport_version),
- false,
- 3,
- QuicStringPiece(data2)),
+ frame1_(0, false, 0, QuicStringPiece(data1)),
+ frame2_(0, false, 3, QuicStringPiece(data2)),
+ crypto_frame_(ENCRYPTION_INITIAL, 0, QuicStringPiece(data1)),
packet_number_length_(PACKET_4BYTE_PACKET_NUMBER),
connection_id_included_(CONNECTION_ID_PRESENT),
notifier_(&connection_) {
- SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
connection_.set_defer_send_in_response_to_packets(GetParam().ack_response ==
AckResponse::kDefer);
- QuicFramerPeer::SetLastSerializedConnectionId(
+ for (EncryptionLevel level :
+ {ENCRYPTION_ZERO_RTT, ENCRYPTION_FORWARD_SECURE}) {
+ peer_creator_.SetEncrypter(
+ level, QuicMakeUnique<NullEncrypter>(peer_framer_.perspective()));
+ }
+ if (version().handshake_protocol == PROTOCOL_TLS1_3) {
+ connection_.SetEncrypter(
+ ENCRYPTION_INITIAL,
+ QuicMakeUnique<NullEncrypter>(Perspective::IS_CLIENT));
+ connection_.InstallDecrypter(
+ ENCRYPTION_INITIAL,
+ QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT));
+ }
+ QuicFramerPeer::SetLastSerializedServerConnectionId(
QuicConnectionPeer::GetFramer(&connection_), connection_id_);
if (version().transport_version > QUIC_VERSION_43) {
EXPECT_TRUE(QuicConnectionPeer::GetNoStopWaitingFrames(&connection_));
@@ -940,6 +954,15 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
QuicConnectionPeer::SetNoStopWaitingFrames(&connection_,
GetParam().no_stop_waiting);
}
+ QuicStreamId stream_id;
+ if (QuicVersionUsesCryptoFrames(version().transport_version)) {
+ stream_id = QuicUtils::GetFirstBidirectionalStreamId(
+ version().transport_version, Perspective::IS_CLIENT);
+ } else {
+ stream_id = QuicUtils::GetCryptoStreamId(version().transport_version);
+ }
+ frame1_.stream_id = stream_id;
+ frame2_.stream_id = stream_id;
connection_.set_visitor(&visitor_);
if (connection_.session_decides_what_to_write()) {
connection_.SetSessionNotifier(&notifier_);
@@ -1052,13 +1075,6 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
frames.push_back(QuicFrame(frame));
QuicPacketCreatorPeer::SetSendVersionInPacket(
&peer_creator_, connection_.perspective() == Perspective::IS_SERVER);
- if (QuicPacketCreatorPeer::GetEncryptionLevel(&peer_creator_) >
- ENCRYPTION_INITIAL) {
- // Set peer_framer_'s corresponding encrypter.
- peer_creator_.SetEncrypter(
- QuicPacketCreatorPeer::GetEncryptionLevel(&peer_creator_),
- QuicMakeUnique<NullEncrypter>(peer_framer_.perspective()));
- }
char buffer[kMaxOutgoingPacketSize];
SerializedPacket serialized_packet =
@@ -1110,7 +1126,8 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
header.destination_connection_id = connection_id_;
header.packet_number_length = packet_number_length_;
header.destination_connection_id_included = connection_id_included_;
- if (peer_framer_.transport_version() > QUIC_VERSION_43 &&
+ if ((peer_framer_.transport_version() > QUIC_VERSION_43 ||
+ GetQuicRestartFlag(quic_do_not_override_connection_id)) &&
peer_framer_.perspective() == Perspective::IS_SERVER) {
header.destination_connection_id_included = CONNECTION_ID_ABSENT;
}
@@ -1119,10 +1136,14 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
header.version_flag = true;
header.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1;
header.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2;
- if (peer_framer_.perspective() == Perspective::IS_SERVER) {
- header.source_connection_id = connection_id_;
- header.source_connection_id_included = CONNECTION_ID_PRESENT;
- }
+ }
+ if ((GetQuicRestartFlag(quic_do_not_override_connection_id) ||
+ (level == ENCRYPTION_INITIAL &&
+ peer_framer_.version().KnowsWhichDecrypterToUse())) &&
+ header.version_flag &&
+ peer_framer_.perspective() == Perspective::IS_SERVER) {
+ header.source_connection_id = connection_id_;
+ header.source_connection_id_included = CONNECTION_ID_PRESENT;
}
header.packet_number = QuicPacketNumber(number);
QuicFrames frames;
@@ -1163,11 +1184,12 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
}
size_t ProcessDataPacket(uint64_t number) {
- return ProcessDataPacketAtLevel(number, false, ENCRYPTION_INITIAL);
+ return ProcessDataPacketAtLevel(number, false, ENCRYPTION_FORWARD_SECURE);
}
size_t ProcessDataPacket(QuicPacketNumber packet_number) {
- return ProcessDataPacketAtLevel(packet_number, false, ENCRYPTION_INITIAL);
+ return ProcessDataPacketAtLevel(packet_number, false,
+ ENCRYPTION_FORWARD_SECURE);
}
size_t ProcessDataPacketAtLevel(QuicPacketNumber packet_number,
@@ -1177,6 +1199,29 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
level);
}
+ size_t ProcessCryptoPacketAtLevel(uint64_t number, EncryptionLevel level) {
+ QuicPacketHeader header = ConstructPacketHeader(1000, ENCRYPTION_INITIAL);
+ QuicFrames frames;
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ frames.push_back(QuicFrame(&crypto_frame_));
+ } else {
+ frames.push_back(QuicFrame(frame1_));
+ }
+ std::unique_ptr<QuicPacket> packet = ConstructPacket(header, frames);
+ char buffer[kMaxOutgoingPacketSize];
+ peer_creator_.set_encryption_level(ENCRYPTION_INITIAL);
+ size_t encrypted_length =
+ peer_framer_.EncryptPayload(ENCRYPTION_INITIAL, QuicPacketNumber(1000),
+ *packet, buffer, kMaxOutgoingPacketSize);
+ connection_.ProcessUdpPacket(
+ kSelfAddress, kPeerAddress,
+ QuicReceivedPacket(buffer, encrypted_length, clock_.Now(), false));
+ if (connection_.GetSendAlarm()->IsSet()) {
+ connection_.GetSendAlarm()->Fire();
+ }
+ return encrypted_length;
+ }
+
size_t ProcessDataPacketAtLevel(uint64_t number,
bool has_stop_waiting,
EncryptionLevel level) {
@@ -1299,9 +1344,8 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
return packet;
}
- std::unique_ptr<QuicPacket> ConstructDataPacket(uint64_t number,
- bool has_stop_waiting,
- EncryptionLevel level) {
+ QuicPacketHeader ConstructPacketHeader(uint64_t number,
+ EncryptionLevel level) {
QuicPacketHeader header;
if (peer_framer_.transport_version() > QUIC_VERSION_43 &&
level < ENCRYPTION_FORWARD_SECURE) {
@@ -1318,9 +1362,15 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
}
// Set connection_id to peer's in memory representation as this data packet
// is created by peer_framer.
- header.destination_connection_id = connection_id_;
- header.packet_number_length = packet_number_length_;
- header.destination_connection_id_included = connection_id_included_;
+ if (GetQuicRestartFlag(quic_do_not_override_connection_id) &&
+ peer_framer_.perspective() == Perspective::IS_SERVER) {
+ header.source_connection_id = connection_id_;
+ header.source_connection_id_included = connection_id_included_;
+ header.destination_connection_id_included = CONNECTION_ID_ABSENT;
+ } else {
+ header.destination_connection_id = connection_id_;
+ header.destination_connection_id_included = connection_id_included_;
+ }
if (peer_framer_.transport_version() > QUIC_VERSION_43 &&
peer_framer_.perspective() == Perspective::IS_SERVER) {
header.destination_connection_id_included = CONNECTION_ID_ABSENT;
@@ -1333,8 +1383,15 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
}
}
}
+ header.packet_number_length = packet_number_length_;
header.packet_number = QuicPacketNumber(number);
+ return header;
+ }
+ std::unique_ptr<QuicPacket> ConstructDataPacket(uint64_t number,
+ bool has_stop_waiting,
+ EncryptionLevel level) {
+ QuicPacketHeader header = ConstructPacketHeader(number, level);
QuicFrames frames;
frames.push_back(QuicFrame(frame1_));
if (has_stop_waiting) {
@@ -1359,13 +1416,22 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
QuicPacketHeader header;
// Set connection_id to peer's in memory representation as this connection
// close packet is created by peer_framer.
- header.destination_connection_id = connection_id_;
- header.packet_number = QuicPacketNumber(number);
- if (peer_framer_.transport_version() > QUIC_VERSION_43 &&
+ if (GetQuicRestartFlag(quic_do_not_override_connection_id) &&
peer_framer_.perspective() == Perspective::IS_SERVER) {
+ header.source_connection_id = connection_id_;
header.destination_connection_id_included = CONNECTION_ID_ABSENT;
+ if (peer_framer_.transport_version() <= QUIC_VERSION_43) {
+ header.source_connection_id_included = CONNECTION_ID_PRESENT;
+ }
+ } else {
+ header.destination_connection_id = connection_id_;
+ if (peer_framer_.transport_version() > QUIC_VERSION_43) {
+ header.destination_connection_id_included = CONNECTION_ID_ABSENT;
+ }
}
+ header.packet_number = QuicPacketNumber(number);
+
QuicConnectionCloseFrame qccf(QUIC_PEER_GOING_AWAY);
if (peer_framer_.transport_version() == QUIC_VERSION_99) {
// Default close-type is Google QUIC. If doing IETF/V99 then
@@ -1495,6 +1561,7 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
QuicStreamFrame frame1_;
QuicStreamFrame frame2_;
+ QuicCryptoFrame crypto_frame_;
QuicAckFrame ack_;
QuicStopWaitingFrame stop_waiting_;
QuicPacketNumberLength packet_number_length_;
@@ -1509,34 +1576,36 @@ INSTANTIATE_TEST_SUITE_P(SupportedVersion,
::testing::ValuesIn(GetTestParams()));
TEST_P(QuicConnectionTest, SelfAddressChangeAtClient) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
EXPECT_TRUE(connection_.connected());
- QuicStreamFrame stream_frame(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), false, 0u,
- QuicStringPiece());
- EXPECT_CALL(visitor_, OnStreamFrame(_));
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kPeerAddress);
+ QuicFrame frame;
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ frame = QuicFrame(&crypto_frame_);
+ EXPECT_CALL(visitor_, OnCryptoFrame(_));
+ } else {
+ frame = QuicFrame(QuicStreamFrame(
+ QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
+ 0u, QuicStringPiece()));
+ EXPECT_CALL(visitor_, OnStreamFrame(_));
+ }
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
// Cause change in self_address.
QuicIpAddress host;
host.FromString("1.1.1.1");
QuicSocketAddress self_address(host, 123);
- EXPECT_CALL(visitor_, OnStreamFrame(_));
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), self_address,
- kPeerAddress);
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ EXPECT_CALL(visitor_, OnCryptoFrame(_));
+ } else {
+ EXPECT_CALL(visitor_, OnStreamFrame(_));
+ }
+ ProcessFramePacketWithAddresses(frame, self_address, kPeerAddress);
EXPECT_TRUE(connection_.connected());
}
TEST_P(QuicConnectionTest, SelfAddressChangeAtServer) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
@@ -1545,27 +1614,28 @@ TEST_P(QuicConnectionTest, SelfAddressChangeAtServer) {
EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
EXPECT_TRUE(connection_.connected());
- QuicStreamFrame stream_frame(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), false, 0u,
- QuicStringPiece());
- EXPECT_CALL(visitor_, OnStreamFrame(_));
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kPeerAddress);
+ QuicFrame frame;
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ frame = QuicFrame(&crypto_frame_);
+ EXPECT_CALL(visitor_, OnCryptoFrame(_));
+ } else {
+ frame = QuicFrame(QuicStreamFrame(
+ QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
+ 0u, QuicStringPiece()));
+ EXPECT_CALL(visitor_, OnStreamFrame(_));
+ }
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
// Cause change in self_address.
QuicIpAddress host;
host.FromString("1.1.1.1");
QuicSocketAddress self_address(host, 123);
EXPECT_CALL(visitor_, AllowSelfAddressChange()).WillOnce(Return(false));
EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_ERROR_MIGRATING_ADDRESS, _, _));
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), self_address,
- kPeerAddress);
+ ProcessFramePacketWithAddresses(frame, self_address, kPeerAddress);
EXPECT_FALSE(connection_.connected());
}
TEST_P(QuicConnectionTest, AllowSelfAddressChangeToMappedIpv4AddressAtServer) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
@@ -1574,33 +1644,33 @@ TEST_P(QuicConnectionTest, AllowSelfAddressChangeToMappedIpv4AddressAtServer) {
EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
EXPECT_TRUE(connection_.connected());
- QuicStreamFrame stream_frame(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), false, 0u,
- QuicStringPiece());
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(3);
+ QuicFrame frame;
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ frame = QuicFrame(&crypto_frame_);
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(3);
+ } else {
+ frame = QuicFrame(QuicStreamFrame(
+ QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
+ 0u, QuicStringPiece()));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(3);
+ }
QuicIpAddress host;
host.FromString("1.1.1.1");
QuicSocketAddress self_address1(host, 443);
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), self_address1,
- kPeerAddress);
+ ProcessFramePacketWithAddresses(frame, self_address1, kPeerAddress);
// Cause self_address change to mapped Ipv4 address.
QuicIpAddress host2;
host2.FromString(
QuicStrCat("::ffff:", connection_.self_address().host().ToString()));
QuicSocketAddress self_address2(host2, connection_.self_address().port());
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), self_address2,
- kPeerAddress);
+ ProcessFramePacketWithAddresses(frame, self_address2, kPeerAddress);
EXPECT_TRUE(connection_.connected());
// self_address change back to Ipv4 address.
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), self_address1,
- kPeerAddress);
+ ProcessFramePacketWithAddresses(frame, self_address1, kPeerAddress);
EXPECT_TRUE(connection_.connected());
}
TEST_P(QuicConnectionTest, ClientAddressChangeAndPacketReordered) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
@@ -1612,16 +1682,21 @@ TEST_P(QuicConnectionTest, ClientAddressChangeAndPacketReordered) {
QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
QuicSocketAddress());
+ QuicFrame frame;
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ frame = QuicFrame(&crypto_frame_);
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(AnyNumber());
+ } else {
+ frame = QuicFrame(QuicStreamFrame(
+ QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
+ 0u, QuicStringPiece()));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
+ }
QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 5);
- QuicStreamFrame stream_frame(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), false, 0u,
- QuicStringPiece());
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
const QuicSocketAddress kNewPeerAddress =
QuicSocketAddress(QuicIpAddress::Loopback6(),
/*port=*/23456);
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kNewPeerAddress);
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kNewPeerAddress);
EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
@@ -1629,16 +1704,12 @@ TEST_P(QuicConnectionTest, ClientAddressChangeAndPacketReordered) {
QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 4);
// This is an old packet, do not migrate.
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kPeerAddress);
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
}
TEST_P(QuicConnectionTest, PeerAddressChangeAtServer) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
@@ -1652,12 +1723,17 @@ TEST_P(QuicConnectionTest, PeerAddressChangeAtServer) {
QuicSocketAddress());
EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
- QuicStreamFrame stream_frame(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), false, 0u,
- QuicStringPiece());
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kPeerAddress);
+ QuicFrame frame;
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ frame = QuicFrame(&crypto_frame_);
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(AnyNumber());
+ } else {
+ frame = QuicFrame(QuicStreamFrame(
+ QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
+ 0u, QuicStringPiece()));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
+ }
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
@@ -1666,16 +1742,12 @@ TEST_P(QuicConnectionTest, PeerAddressChangeAtServer) {
const QuicSocketAddress kNewPeerAddress =
QuicSocketAddress(QuicIpAddress::Loopback6(), /*port=*/23456);
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(1);
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kNewPeerAddress);
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kNewPeerAddress);
EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
}
TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
@@ -1691,12 +1763,17 @@ TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
QuicSocketAddress(QuicIpAddress::Loopback6(), /*port=*/43210);
connection_.ReturnEffectivePeerAddressForNextPacket(kEffectivePeerAddress);
- QuicStreamFrame stream_frame(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), false, 0u,
- QuicStringPiece());
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kPeerAddress);
+ QuicFrame frame;
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ frame = QuicFrame(&crypto_frame_);
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(AnyNumber());
+ } else {
+ frame = QuicFrame(QuicStreamFrame(
+ QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
+ 0u, QuicStringPiece()));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
+ }
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kEffectivePeerAddress, connection_.effective_peer_address());
@@ -1706,8 +1783,7 @@ TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
QuicSocketAddress(QuicIpAddress::Loopback6(), /*port=*/54321);
connection_.ReturnEffectivePeerAddressForNextPacket(kNewEffectivePeerAddress);
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(1);
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kPeerAddress);
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kNewEffectivePeerAddress, connection_.effective_peer_address());
@@ -1736,8 +1812,7 @@ TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
connection_.ReturnEffectivePeerAddressForNextPacket(
kNewerEffectivePeerAddress);
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(1);
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kFinalPeerAddress);
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kFinalPeerAddress);
EXPECT_EQ(kFinalPeerAddress, connection_.peer_address());
EXPECT_EQ(kNewerEffectivePeerAddress, connection_.effective_peer_address());
EXPECT_EQ(PORT_CHANGE, connection_.active_effective_peer_migration_type());
@@ -1751,8 +1826,7 @@ TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
kNewestEffectivePeerAddress);
EXPECT_CALL(visitor_, OnConnectionMigration(IPV6_TO_IPV4_CHANGE)).Times(1);
EXPECT_CALL(*send_algorithm_, OnConnectionMigration()).Times(1);
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kFinalPeerAddress);
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kFinalPeerAddress);
EXPECT_EQ(kFinalPeerAddress, connection_.peer_address());
EXPECT_EQ(kNewestEffectivePeerAddress, connection_.effective_peer_address());
EXPECT_EQ(IPV6_TO_IPV4_CHANGE,
@@ -1760,9 +1834,6 @@ TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
}
TEST_P(QuicConnectionTest, ReceivePaddedPingAtServer) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
@@ -1776,12 +1847,17 @@ TEST_P(QuicConnectionTest, ReceivePaddedPingAtServer) {
QuicSocketAddress());
EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
- QuicStreamFrame stream_frame(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), false, 0u,
- QuicStringPiece());
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kPeerAddress);
+ QuicFrame frame;
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ frame = QuicFrame(&crypto_frame_);
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(AnyNumber());
+ } else {
+ frame = QuicFrame(QuicStreamFrame(
+ QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
+ 0u, QuicStringPiece()));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
+ }
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
@@ -1845,9 +1921,6 @@ TEST_P(QuicConnectionTest, WriteOutOfOrderQueuedPackets) {
}
TEST_P(QuicConnectionTest, DiscardQueuedPacketsAfterConnectionClose) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Regression test for b/74073386.
{
InSequence seq;
@@ -1873,9 +1946,6 @@ TEST_P(QuicConnectionTest, DiscardQueuedPacketsAfterConnectionClose) {
}
TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtServer) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
@@ -1889,12 +1959,17 @@ TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtServer) {
QuicSocketAddress());
EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
- QuicStreamFrame stream_frame(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), false, 0u,
- QuicStringPiece());
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kPeerAddress);
+ QuicFrame frame;
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ frame = QuicFrame(&crypto_frame_);
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(AnyNumber());
+ } else {
+ frame = QuicFrame(QuicStreamFrame(
+ QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
+ 0u, QuicStringPiece()));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
+ }
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
@@ -1924,16 +1999,12 @@ TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtServer) {
// Process another packet with the old peer address on server side will not
// start peer migration.
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kPeerAddress);
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
}
TEST_P(QuicConnectionTest, ReceiveReorderedConnectivityProbingAtServer) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
@@ -1947,13 +2018,18 @@ TEST_P(QuicConnectionTest, ReceiveReorderedConnectivityProbingAtServer) {
QuicSocketAddress());
EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
+ QuicFrame frame;
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ frame = QuicFrame(&crypto_frame_);
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(AnyNumber());
+ } else {
+ frame = QuicFrame(QuicStreamFrame(
+ QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
+ 0u, QuicStringPiece()));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
+ }
QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 5);
- QuicStreamFrame stream_frame(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), false, 0u,
- QuicStringPiece());
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kPeerAddress);
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
@@ -1986,9 +2062,6 @@ TEST_P(QuicConnectionTest, ReceiveReorderedConnectivityProbingAtServer) {
}
TEST_P(QuicConnectionTest, MigrateAfterProbingAtServer) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
@@ -2002,12 +2075,17 @@ TEST_P(QuicConnectionTest, MigrateAfterProbingAtServer) {
QuicSocketAddress());
EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
- QuicStreamFrame stream_frame(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), false, 0u,
- QuicStringPiece());
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kPeerAddress);
+ QuicFrame frame;
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ frame = QuicFrame(&crypto_frame_);
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(AnyNumber());
+ } else {
+ frame = QuicFrame(QuicStreamFrame(
+ QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
+ 0u, QuicStringPiece()));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
+ }
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
@@ -2032,16 +2110,12 @@ TEST_P(QuicConnectionTest, MigrateAfterProbingAtServer) {
// side will start peer migration.
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(1);
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kNewPeerAddress);
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kNewPeerAddress);
EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
}
TEST_P(QuicConnectionTest, ReceivePaddedPingAtClient) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_CLIENT);
EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
@@ -2054,12 +2128,17 @@ TEST_P(QuicConnectionTest, ReceivePaddedPingAtClient) {
QuicSocketAddress());
EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
- QuicStreamFrame stream_frame(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), false, 0u,
- QuicStringPiece());
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kPeerAddress);
+ QuicFrame frame;
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ frame = QuicFrame(&crypto_frame_);
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(AnyNumber());
+ } else {
+ frame = QuicFrame(QuicStreamFrame(
+ QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
+ 0u, QuicStringPiece()));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
+ }
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
@@ -2084,9 +2163,6 @@ TEST_P(QuicConnectionTest, ReceivePaddedPingAtClient) {
}
TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtClient) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_CLIENT);
EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
@@ -2099,12 +2175,17 @@ TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtClient) {
QuicSocketAddress());
EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
- QuicStreamFrame stream_frame(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), false, 0u,
- QuicStringPiece());
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kPeerAddress);
+ QuicFrame frame;
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ frame = QuicFrame(&crypto_frame_);
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(AnyNumber());
+ } else {
+ frame = QuicFrame(QuicStreamFrame(
+ QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
+ 0u, QuicStringPiece()));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
+ }
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
@@ -2132,9 +2213,6 @@ TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtClient) {
}
TEST_P(QuicConnectionTest, PeerAddressChangeAtClient) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_CLIENT);
EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
@@ -2147,12 +2225,17 @@ TEST_P(QuicConnectionTest, PeerAddressChangeAtClient) {
QuicSocketAddress());
EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
- QuicStreamFrame stream_frame(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), false, 0u,
- QuicStringPiece());
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kPeerAddress);
+ QuicFrame frame;
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ frame = QuicFrame(&crypto_frame_);
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(AnyNumber());
+ } else {
+ frame = QuicFrame(QuicStreamFrame(
+ QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
+ 0u, QuicStringPiece()));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
+ }
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
@@ -2161,24 +2244,17 @@ TEST_P(QuicConnectionTest, PeerAddressChangeAtClient) {
const QuicSocketAddress kNewPeerAddress =
QuicSocketAddress(QuicIpAddress::Loopback6(), /*port=*/23456);
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kNewPeerAddress);
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kNewPeerAddress);
EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
}
TEST_P(QuicConnectionTest, MaxPacketSize) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
EXPECT_EQ(1350u, connection_.max_packet_length());
}
TEST_P(QuicConnectionTest, SmallerServerMaxPacketSize) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
TestConnection connection(TestConnectionId(), kPeerAddress, helper_.get(),
alarm_factory_.get(), writer_.get(),
Perspective::IS_SERVER, version());
@@ -2187,9 +2263,6 @@ TEST_P(QuicConnectionTest, SmallerServerMaxPacketSize) {
}
TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSize) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
@@ -2209,7 +2282,11 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSize) {
QuicFrames frames;
QuicPaddingFrame padding;
- frames.push_back(QuicFrame(frame1_));
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ frames.push_back(QuicFrame(&crypto_frame_));
+ } else {
+ frames.push_back(QuicFrame(frame1_));
+ }
frames.push_back(QuicFrame(padding));
std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxOutgoingPacketSize];
@@ -2219,7 +2296,11 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSize) {
EXPECT_EQ(kMaxOutgoingPacketSize, encrypted_length);
framer_.set_version(version());
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(1);
+ } else {
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+ }
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
@@ -2228,9 +2309,6 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSize) {
}
TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSizeWhileWriterLimited) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
const QuicByteCount lower_max_packet_size = 1240;
@@ -2253,7 +2331,11 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSizeWhileWriterLimited) {
QuicFrames frames;
QuicPaddingFrame padding;
- frames.push_back(QuicFrame(frame1_));
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ frames.push_back(QuicFrame(&crypto_frame_));
+ } else {
+ frames.push_back(QuicFrame(frame1_));
+ }
frames.push_back(QuicFrame(padding));
std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxOutgoingPacketSize];
@@ -2263,7 +2345,11 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSizeWhileWriterLimited) {
EXPECT_EQ(kMaxOutgoingPacketSize, encrypted_length);
framer_.set_version(version());
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(1);
+ } else {
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+ }
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
@@ -2274,9 +2360,6 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSizeWhileWriterLimited) {
}
TEST_P(QuicConnectionTest, LimitMaxPacketSizeByWriter) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
const QuicByteCount lower_max_packet_size = 1240;
writer_->set_max_packet_size(lower_max_packet_size);
@@ -2288,9 +2371,6 @@ TEST_P(QuicConnectionTest, LimitMaxPacketSizeByWriter) {
}
TEST_P(QuicConnectionTest, LimitMaxPacketSizeByWriterForNewConnection) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
const QuicConnectionId connection_id = TestConnectionId(17);
const QuicByteCount lower_max_packet_size = 1240;
writer_->set_max_packet_size(lower_max_packet_size);
@@ -2413,9 +2493,6 @@ TEST_P(QuicConnectionTest, RejectPacketTooFarOut) {
}
TEST_P(QuicConnectionTest, RejectUnencryptedStreamData) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
if (!IsDefaultTestConfiguration()) {
return;
@@ -2426,20 +2503,18 @@ TEST_P(QuicConnectionTest, RejectUnencryptedStreamData) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_UNENCRYPTED_STREAM_DATA, _,
ConnectionCloseSource::FROM_SELF));
- EXPECT_QUIC_PEER_BUG(ProcessDataPacket(1), "");
+ EXPECT_QUIC_PEER_BUG(ProcessDataPacketAtLevel(1, false, ENCRYPTION_INITIAL),
+ "");
EXPECT_FALSE(QuicConnectionPeer::GetConnectionClosePacket(&connection_) ==
nullptr);
const std::vector<QuicConnectionCloseFrame>& connection_close_frames =
writer_->connection_close_frames();
- EXPECT_EQ(1u, connection_close_frames.size());
+ ASSERT_EQ(1u, connection_close_frames.size());
EXPECT_EQ(QUIC_UNENCRYPTED_STREAM_DATA,
connection_close_frames[0].quic_error_code);
}
TEST_P(QuicConnectionTest, OutOfOrderReceiptCausesAckSend) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessPacket(3);
@@ -2478,9 +2553,6 @@ TEST_P(QuicConnectionTest, OutOfOrderReceiptCausesAckSend) {
}
TEST_P(QuicConnectionTest, OutOfOrderAckReceiptCausesNoAck) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr);
@@ -2500,9 +2572,6 @@ TEST_P(QuicConnectionTest, OutOfOrderAckReceiptCausesNoAck) {
}
TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
QuicPacketNumber original, second;
@@ -2543,7 +2612,8 @@ TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) {
OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA));
connection_.SendStreamDataWithString(3, "foo", 6, NO_FIN);
// No ack sent.
- EXPECT_EQ(1u, writer_->frame_count());
+ size_t padding_frame_count = writer_->padding_frames().size();
+ EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
EXPECT_EQ(1u, writer_->stream_frames().size());
// No more packet loss for the rest of the test.
@@ -2552,15 +2622,25 @@ TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) {
ProcessAckPacket(&frame2);
EXPECT_CALL(*send_algorithm_,
OnPacketSent(_, _, _, _, HAS_RETRANSMITTABLE_DATA));
- connection_.SendStreamDataWithString(3, "foo", 9, NO_FIN);
+ connection_.SendStreamDataWithString(3, "foofoofoo", 9, NO_FIN);
// Ack bundled.
if (GetParam().no_stop_waiting) {
- EXPECT_EQ(2u, writer_->frame_count());
+ if (GetQuicReloadableFlag(quic_simplify_stop_waiting)) {
+ // Do not ACK acks.
+ EXPECT_EQ(1u, writer_->frame_count());
+ } else {
+ EXPECT_EQ(2u, writer_->frame_count());
+ }
} else {
EXPECT_EQ(3u, writer_->frame_count());
}
EXPECT_EQ(1u, writer_->stream_frames().size());
- EXPECT_FALSE(writer_->ack_frames().empty());
+ if (GetParam().no_stop_waiting &&
+ GetQuicReloadableFlag(quic_simplify_stop_waiting)) {
+ EXPECT_TRUE(writer_->ack_frames().empty());
+ } else {
+ EXPECT_FALSE(writer_->ack_frames().empty());
+ }
// But an ack with no missing packets will not send an ack.
AckPacket(original, &frame2);
@@ -2569,9 +2649,6 @@ TEST_P(QuicConnectionTest, AckReceiptCausesAckSend) {
}
TEST_P(QuicConnectionTest, AckSentEveryNthPacket) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
connection_.set_ack_frequency_before_ack_decimation(3);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -2586,9 +2663,6 @@ TEST_P(QuicConnectionTest, AckSentEveryNthPacket) {
}
TEST_P(QuicConnectionTest, AckDecimationReducesAcks) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
const size_t kMinRttMs = 40;
RttStats* rtt_stats = const_cast<RttStats*>(manager_->GetRttStats());
rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(kMinRttMs),
@@ -2616,9 +2690,7 @@ TEST_P(QuicConnectionTest, AckDecimationReducesAcks) {
}
TEST_P(QuicConnectionTest, AckNeedsRetransmittableFrames) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(99);
@@ -2646,7 +2718,8 @@ TEST_P(QuicConnectionTest, AckNeedsRetransmittableFrames) {
}
// Send a packet containing stream frame.
SendStreamDataToPeer(
- QuicUtils::GetCryptoStreamId(connection_.version().transport_version),
+ QuicUtils::GetFirstBidirectionalStreamId(
+ connection_.version().transport_version, Perspective::IS_CLIENT),
"bar", 0, NO_FIN, nullptr);
// Session will not be informed until receiving another 20 packets.
@@ -2705,9 +2778,6 @@ TEST_P(QuicConnectionTest, LeastUnackedLower) {
}
TEST_P(QuicConnectionTest, TooManySentPackets) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
QuicPacketCount max_tracked_packets = 50;
@@ -2731,9 +2801,6 @@ TEST_P(QuicConnectionTest, TooManySentPackets) {
}
TEST_P(QuicConnectionTest, LargestObservedLower) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr);
@@ -2758,9 +2825,6 @@ TEST_P(QuicConnectionTest, LargestObservedLower) {
}
TEST_P(QuicConnectionTest, AckUnsentData) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Ack a packet which has not been sent.
EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_ACK_DATA, _,
ConnectionCloseSource::FROM_SELF));
@@ -2866,9 +2930,6 @@ TEST_P(QuicConnectionTest, BasicSending) {
// QuicConnection should record the packet sent-time prior to sending the
// packet.
TEST_P(QuicConnectionTest, RecordSentTimeBeforePacketSent) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// We're using a MockClock for the tests, so we have complete control over the
// time.
// Our recorded timestamp for the last packet sent time will be passed in to
@@ -2900,9 +2961,6 @@ TEST_P(QuicConnectionTest, RecordSentTimeBeforePacketSent) {
}
TEST_P(QuicConnectionTest, FramePacking) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Send two stream frames in 1 packet by queueing them.
connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
{
@@ -2935,9 +2993,6 @@ TEST_P(QuicConnectionTest, FramePacking) {
}
TEST_P(QuicConnectionTest, FramePackingNonCryptoThenCrypto) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Send two stream frames (one non-crypto, then one crypto) in 2 packets by
// queueing them.
connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
@@ -2964,9 +3019,6 @@ TEST_P(QuicConnectionTest, FramePackingNonCryptoThenCrypto) {
}
TEST_P(QuicConnectionTest, FramePackingCryptoThenNonCrypto) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Send two stream frames (one crypto, then one non-crypto) in 2 packets by
// queueing them.
{
@@ -2981,7 +3033,8 @@ TEST_P(QuicConnectionTest, FramePackingCryptoThenNonCrypto) {
EXPECT_FALSE(connection_.HasQueuedData());
// Parse the last packet and ensure it's the stream frame from stream 3.
- EXPECT_EQ(1u, writer_->frame_count());
+ size_t padding_frame_count = writer_->padding_frames().size();
+ EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
ASSERT_EQ(1u, writer_->stream_frames().size());
EXPECT_EQ(GetNthClientInitiatedStreamId(1, connection_.transport_version()),
writer_->stream_frames()[0]->stream_id);
@@ -2996,9 +3049,13 @@ TEST_P(QuicConnectionTest, FramePackingAckResponse) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacket(1);
QuicPacketNumber last_packet;
- SendStreamDataToPeer(
- QuicUtils::GetCryptoStreamId(connection_.version().transport_version),
- "foo", 0, NO_FIN, &last_packet);
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ connection_.SendCryptoDataWithString("foo", 0);
+ } else {
+ SendStreamDataToPeer(
+ QuicUtils::GetCryptoStreamId(connection_.transport_version()), "foo", 0,
+ NO_FIN, &last_packet);
+ }
// Verify ack is bundled with outging packet.
EXPECT_FALSE(writer_->ack_frames().empty());
@@ -3016,7 +3073,7 @@ TEST_P(QuicConnectionTest, FramePackingAckResponse) {
QuicMakeUnique<TaggingEncrypter>(0x01));
SetDecrypter(ENCRYPTION_FORWARD_SECURE,
QuicMakeUnique<StrictTaggingDecrypter>(0x01));
- ProcessDataPacketAtLevel(2, false, ENCRYPTION_FORWARD_SECURE);
+ ProcessDataPacket(2);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_FALSE(connection_.HasQueuedData());
@@ -3039,9 +3096,7 @@ TEST_P(QuicConnectionTest, FramePackingAckResponse) {
}
TEST_P(QuicConnectionTest, FramePackingSendv) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
// Send data in 1 packet by writing multiple blocks in a single iovector
// using writev.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
@@ -3052,28 +3107,25 @@ TEST_P(QuicConnectionTest, FramePackingSendv) {
iov[0].iov_len = 4;
iov[1].iov_base = data + 4;
iov[1].iov_len = 2;
- connection_.SaveAndSendStreamData(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), iov, 2, 6,
- 0, NO_FIN);
+ QuicStreamId stream_id = QuicUtils::GetFirstBidirectionalStreamId(
+ connection_.transport_version(), Perspective::IS_CLIENT);
+ connection_.SaveAndSendStreamData(stream_id, iov, 2, 6, 0, NO_FIN);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_FALSE(connection_.HasQueuedData());
// Parse the last packet and ensure multiple iovector blocks have
// been packed into a single stream frame from one stream.
- EXPECT_EQ(2u, writer_->frame_count());
+ EXPECT_EQ(1u, writer_->frame_count());
EXPECT_EQ(1u, writer_->stream_frames().size());
- EXPECT_EQ(1u, writer_->padding_frames().size());
+ EXPECT_EQ(0u, writer_->padding_frames().size());
QuicStreamFrame* frame = writer_->stream_frames()[0].get();
- EXPECT_EQ(QuicUtils::GetCryptoStreamId(connection_.transport_version()),
- frame->stream_id);
+ EXPECT_EQ(stream_id, frame->stream_id);
EXPECT_EQ("ABCDEF", QuicStringPiece(frame->data_buffer, frame->data_length));
}
TEST_P(QuicConnectionTest, FramePackingSendvQueued) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
// Try to send two stream frames in 1 packet by using writev.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
@@ -3084,9 +3136,9 @@ TEST_P(QuicConnectionTest, FramePackingSendvQueued) {
iov[0].iov_len = 4;
iov[1].iov_base = data + 4;
iov[1].iov_len = 2;
- connection_.SaveAndSendStreamData(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), iov, 2, 6,
- 0, NO_FIN);
+ QuicStreamId stream_id = QuicUtils::GetFirstBidirectionalStreamId(
+ connection_.transport_version(), Perspective::IS_CLIENT);
+ connection_.SaveAndSendStreamData(stream_id, iov, 2, 6, 0, NO_FIN);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
EXPECT_TRUE(connection_.HasQueuedData());
@@ -3097,39 +3149,38 @@ TEST_P(QuicConnectionTest, FramePackingSendvQueued) {
EXPECT_EQ(0u, connection_.NumQueuedPackets());
// Parse the last packet and ensure it's one stream frame from one stream.
- EXPECT_EQ(2u, writer_->frame_count());
+ EXPECT_EQ(1u, writer_->frame_count());
EXPECT_EQ(1u, writer_->stream_frames().size());
- EXPECT_EQ(1u, writer_->padding_frames().size());
- EXPECT_EQ(QuicUtils::GetCryptoStreamId(connection_.transport_version()),
- writer_->stream_frames()[0]->stream_id);
+ EXPECT_EQ(0u, writer_->padding_frames().size());
+ EXPECT_EQ(stream_id, writer_->stream_frames()[0]->stream_id);
}
TEST_P(QuicConnectionTest, SendingZeroBytes) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
// Send a zero byte write with a fin using writev.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
- connection_.SaveAndSendStreamData(
- QuicUtils::GetHeadersStreamId(connection_.transport_version()), nullptr,
- 0, 0, 0, FIN);
+ QuicStreamId stream_id = QuicUtils::GetFirstBidirectionalStreamId(
+ connection_.transport_version(), Perspective::IS_CLIENT);
+ connection_.SaveAndSendStreamData(stream_id, nullptr, 0, 0, 0, FIN);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_FALSE(connection_.HasQueuedData());
+ // Padding frames are added by v99 to ensure a minimum packet size.
+ size_t extra_padding_frames = 0;
+ if (GetParam().version.HasHeaderProtection()) {
+ extra_padding_frames = 1;
+ }
+
// Parse the last packet and ensure it's one stream frame from one stream.
- EXPECT_EQ(1u, writer_->frame_count());
- EXPECT_EQ(1u, writer_->stream_frames().size());
- EXPECT_EQ(QuicUtils::GetHeadersStreamId(connection_.transport_version()),
- writer_->stream_frames()[0]->stream_id);
+ EXPECT_EQ(1u + extra_padding_frames, writer_->frame_count());
+ EXPECT_EQ(extra_padding_frames, writer_->padding_frames().size());
+ ASSERT_EQ(1u, writer_->stream_frames().size());
+ EXPECT_EQ(stream_id, writer_->stream_frames()[0]->stream_id);
EXPECT_TRUE(writer_->stream_frames()[0]->fin);
}
TEST_P(QuicConnectionTest, LargeSendWithPendingAck) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
// Set the ack alarm by processing a ping frame.
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -3158,7 +3209,7 @@ TEST_P(QuicConnectionTest, LargeSendWithPendingAck) {
// Parse the last packet and ensure it's one stream frame with a fin.
EXPECT_EQ(1u, writer_->frame_count());
- EXPECT_EQ(1u, writer_->stream_frames().size());
+ ASSERT_EQ(1u, writer_->stream_frames().size());
EXPECT_EQ(QuicUtils::GetHeadersStreamId(connection_.transport_version()),
writer_->stream_frames()[0]->stream_id);
EXPECT_TRUE(writer_->stream_frames()[0]->fin);
@@ -3167,9 +3218,6 @@ TEST_P(QuicConnectionTest, LargeSendWithPendingAck) {
}
TEST_P(QuicConnectionTest, OnCanWrite) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Visitor's OnCanWrite will send data, but will have more pending writes.
EXPECT_CALL(visitor_, OnCanWrite())
.WillOnce(DoAll(IgnoreResult(InvokeWithoutArgs(
@@ -3199,9 +3247,6 @@ TEST_P(QuicConnectionTest, OnCanWrite) {
}
TEST_P(QuicConnectionTest, RetransmitOnNack) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
QuicPacketNumber last_packet;
QuicByteCount second_packet_size;
SendStreamDataToPeer(3, "foo", 0, NO_FIN, &last_packet); // Packet 1
@@ -3230,9 +3275,6 @@ TEST_P(QuicConnectionTest, RetransmitOnNack) {
}
TEST_P(QuicConnectionTest, DoNotSendQueuedPacketForResetStream) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Block the connection to queue the packet.
BlockOnNextWrite();
@@ -3251,14 +3293,12 @@ TEST_P(QuicConnectionTest, DoNotSendQueuedPacketForResetStream) {
connection_.SendControlFrame(QuicFrame(new QuicRstStreamFrame(
1, stream_id, QUIC_ERROR_PROCESSING_STREAM, 14)));
}
- EXPECT_EQ(1u, writer_->frame_count());
+ 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());
}
TEST_P(QuicConnectionTest, SendQueuedPacketForQuicRstStreamNoError) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Block the connection to queue the packet.
BlockOnNextWrite();
@@ -3278,14 +3318,12 @@ TEST_P(QuicConnectionTest, SendQueuedPacketForQuicRstStreamNoError) {
connection_.SendControlFrame(QuicFrame(
new QuicRstStreamFrame(1, stream_id, QUIC_STREAM_NO_ERROR, 14)));
}
- EXPECT_EQ(1u, writer_->frame_count());
+ 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());
}
TEST_P(QuicConnectionTest, DoNotRetransmitForResetStreamOnNack) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
QuicStreamId stream_id = 2;
QuicPacketNumber last_packet;
SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet);
@@ -3305,9 +3343,6 @@ TEST_P(QuicConnectionTest, DoNotRetransmitForResetStreamOnNack) {
}
TEST_P(QuicConnectionTest, RetransmitForQuicRstStreamNoErrorOnNack) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
QuicStreamId stream_id = 2;
QuicPacketNumber last_packet;
SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet);
@@ -3330,9 +3365,6 @@ TEST_P(QuicConnectionTest, RetransmitForQuicRstStreamNoErrorOnNack) {
}
TEST_P(QuicConnectionTest, DoNotRetransmitForResetStreamOnRTO) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
QuicStreamId stream_id = 2;
QuicPacketNumber last_packet;
SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet);
@@ -3344,7 +3376,8 @@ TEST_P(QuicConnectionTest, DoNotRetransmitForResetStreamOnRTO) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
clock_.AdvanceTime(DefaultRetransmissionTime());
connection_.GetRetransmissionAlarm()->Fire();
- EXPECT_EQ(1u, writer_->frame_count());
+ 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());
EXPECT_EQ(stream_id, writer_->rst_stream_frames().front().stream_id);
}
@@ -3352,9 +3385,6 @@ TEST_P(QuicConnectionTest, DoNotRetransmitForResetStreamOnRTO) {
// Ensure that if the only data in flight is non-retransmittable, the
// retransmission alarm is not set.
TEST_P(QuicConnectionTest, CancelRetransmissionAlarmAfterResetStream) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
QuicStreamId stream_id = 2;
QuicPacketNumber last_data_packet;
SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_data_packet);
@@ -3375,20 +3405,17 @@ TEST_P(QuicConnectionTest, CancelRetransmissionAlarmAfterResetStream) {
// Ensure that the data is still in flight, but the retransmission alarm is no
// longer set.
- EXPECT_GT(QuicSentPacketManagerPeer::GetBytesInFlight(manager_), 0u);
+ EXPECT_GT(manager_->GetBytesInFlight(), 0u);
if (GetQuicReloadableFlag(quic_optimize_inflight_check)) {
EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
// Firing the alarm should remove all bytes_in_flight.
connection_.GetRetransmissionAlarm()->Fire();
- EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
+ EXPECT_EQ(0u, manager_->GetBytesInFlight());
}
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
}
TEST_P(QuicConnectionTest, RetransmitForQuicRstStreamNoErrorOnRTO) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
connection_.SetMaxTailLossProbes(0);
QuicStreamId stream_id = 2;
@@ -3403,15 +3430,13 @@ TEST_P(QuicConnectionTest, RetransmitForQuicRstStreamNoErrorOnRTO) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(2));
clock_.AdvanceTime(DefaultRetransmissionTime());
connection_.GetRetransmissionAlarm()->Fire();
- EXPECT_EQ(1u, writer_->frame_count());
+ size_t padding_frame_count = writer_->padding_frames().size();
+ EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
ASSERT_EQ(1u, writer_->rst_stream_frames().size());
EXPECT_EQ(stream_id, writer_->rst_stream_frames().front().stream_id);
}
TEST_P(QuicConnectionTest, DoNotSendPendingRetransmissionForResetStream) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
QuicStreamId stream_id = 2;
QuicPacketNumber last_packet;
SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet);
@@ -3439,15 +3464,13 @@ TEST_P(QuicConnectionTest, DoNotSendPendingRetransmissionForResetStream) {
connection_.SendControlFrame(QuicFrame(new QuicRstStreamFrame(
1, stream_id, QUIC_ERROR_PROCESSING_STREAM, 14)));
}
- EXPECT_EQ(1u, writer_->frame_count());
+ size_t padding_frame_count = writer_->padding_frames().size();
+ EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
ASSERT_EQ(1u, writer_->rst_stream_frames().size());
EXPECT_EQ(stream_id, writer_->rst_stream_frames().front().stream_id);
}
TEST_P(QuicConnectionTest, SendPendingRetransmissionForQuicRstStreamNoError) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
QuicStreamId stream_id = 2;
QuicPacketNumber last_packet;
SendStreamDataToPeer(stream_id, "foo", 0, NO_FIN, &last_packet);
@@ -3477,14 +3500,12 @@ TEST_P(QuicConnectionTest, SendPendingRetransmissionForQuicRstStreamNoError) {
// retransmission.
connection_.SendControlFrame(QuicFrame(
new QuicRstStreamFrame(1, stream_id, QUIC_STREAM_NO_ERROR, 14)));
- EXPECT_EQ(1u, writer_->frame_count());
+ 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());
}
TEST_P(QuicConnectionTest, RetransmitAckedPacket) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
QuicPacketNumber last_packet;
SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet); // Packet 1
SendStreamDataToPeer(1, "foos", 3, NO_FIN, &last_packet); // Packet 2
@@ -3527,9 +3548,6 @@ TEST_P(QuicConnectionTest, RetransmitAckedPacket) {
}
TEST_P(QuicConnectionTest, RetransmitNackedLargestObserved) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
QuicPacketNumber original, second;
@@ -3557,9 +3575,6 @@ TEST_P(QuicConnectionTest, RetransmitNackedLargestObserved) {
}
TEST_P(QuicConnectionTest, QueueAfterTwoRTOs) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
connection_.SetMaxTailLossProbes(0);
for (int i = 0; i < 10; ++i) {
@@ -3591,9 +3606,6 @@ TEST_P(QuicConnectionTest, QueueAfterTwoRTOs) {
}
TEST_P(QuicConnectionTest, WriteBlockedBufferedThenSent) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
BlockOnNextWrite();
writer_->set_is_write_blocked_data_buffered(true);
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
@@ -3606,9 +3618,6 @@ TEST_P(QuicConnectionTest, WriteBlockedBufferedThenSent) {
}
TEST_P(QuicConnectionTest, WriteBlockedThenSent) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
BlockOnNextWrite();
connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN);
@@ -3628,9 +3637,6 @@ TEST_P(QuicConnectionTest, WriteBlockedThenSent) {
}
TEST_P(QuicConnectionTest, RetransmitWriteBlockedAckedOriginalThenSent) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN);
EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
@@ -3654,16 +3660,13 @@ TEST_P(QuicConnectionTest, RetransmitWriteBlockedAckedOriginalThenSent) {
EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
// Firing the alarm should remove all bytes_in_flight.
connection_.GetRetransmissionAlarm()->Fire();
- EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(manager_));
+ EXPECT_EQ(0u, manager_->GetBytesInFlight());
}
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
EXPECT_FALSE(QuicConnectionPeer::HasRetransmittableFrames(&connection_, 2));
}
TEST_P(QuicConnectionTest, AlarmsWhenWriteBlocked) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Block the connection.
BlockOnNextWrite();
connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN);
@@ -3678,9 +3681,6 @@ TEST_P(QuicConnectionTest, AlarmsWhenWriteBlocked) {
}
TEST_P(QuicConnectionTest, NoSendAlarmAfterProcessPacketWhenWriteBlocked) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Block the connection.
@@ -3698,7 +3698,7 @@ TEST_P(QuicConnectionTest, NoSendAlarmAfterProcessPacketWhenWriteBlocked) {
const bool has_stop_waiting = false;
const EncryptionLevel level = ENCRYPTION_INITIAL;
std::unique_ptr<QuicPacket> packet(ConstructDataPacket(
- received_packet_num, has_stop_waiting, ENCRYPTION_INITIAL));
+ received_packet_num, has_stop_waiting, ENCRYPTION_FORWARD_SECURE));
char buffer[kMaxOutgoingPacketSize];
size_t encrypted_length =
peer_framer_.EncryptPayload(level, QuicPacketNumber(received_packet_num),
@@ -3712,9 +3712,6 @@ TEST_P(QuicConnectionTest, NoSendAlarmAfterProcessPacketWhenWriteBlocked) {
}
TEST_P(QuicConnectionTest, AddToWriteBlockedListIfWriterBlockedWhenProcessing) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr);
@@ -3729,9 +3726,6 @@ TEST_P(QuicConnectionTest, AddToWriteBlockedListIfWriterBlockedWhenProcessing) {
}
TEST_P(QuicConnectionTest, DoNotAddToWriteBlockedListAfterDisconnect) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
writer_->SetBatchMode(true);
EXPECT_TRUE(connection_.connected());
EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, _,
@@ -3751,9 +3745,6 @@ TEST_P(QuicConnectionTest, DoNotAddToWriteBlockedListAfterDisconnect) {
}
TEST_P(QuicConnectionTest, AddToWriteBlockedListIfBlockedOnFlushPackets) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
writer_->SetBatchMode(true);
writer_->BlockOnNextFlush();
@@ -3767,9 +3758,6 @@ TEST_P(QuicConnectionTest, AddToWriteBlockedListIfBlockedOnFlushPackets) {
}
TEST_P(QuicConnectionTest, NoLimitPacketsPerNack) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
int offset = 0;
// Send packets 1 to 15.
@@ -3902,9 +3890,6 @@ TEST_P(QuicConnectionTest, DontLatchUnackedPacket) {
}
TEST_P(QuicConnectionTest, TLP) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
connection_.SetMaxTailLossProbes(1);
SendStreamDataToPeer(3, "foo", 0, NO_FIN, nullptr);
@@ -3925,9 +3910,6 @@ TEST_P(QuicConnectionTest, TLP) {
}
TEST_P(QuicConnectionTest, TailLossProbeDelayForStreamDataInTLPR) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Set TLPR from QuicConfig.
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
QuicConfig config;
@@ -3959,9 +3941,6 @@ TEST_P(QuicConnectionTest, TailLossProbeDelayForStreamDataInTLPR) {
}
TEST_P(QuicConnectionTest, TailLossProbeDelayForNonStreamDataInTLPR) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Set TLPR from QuicConfig.
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
QuicConfig config;
@@ -4083,9 +4062,6 @@ TEST_P(QuicConnectionTest, TailLossProbeDelayForNonStreamDataInTLPR) {
}
TEST_P(QuicConnectionTest, RTO) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
connection_.SetMaxTailLossProbes(0);
QuicTime default_retransmission_time =
@@ -4106,18 +4082,17 @@ TEST_P(QuicConnectionTest, RTO) {
}
TEST_P(QuicConnectionTest, RetransmitWithSameEncryptionLevel) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
use_tagging_decrypter();
// A TaggingEncrypter puts kTagSize copies of the given byte (0x01 here) at
// the end of the packet. We can test this to check which encrypter was used.
connection_.SetEncrypter(ENCRYPTION_INITIAL,
QuicMakeUnique<TaggingEncrypter>(0x01));
- SendStreamDataToPeer(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), "foo", 0,
- NO_FIN, nullptr);
+ QuicByteCount packet_size;
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .WillOnce(SaveArg<3>(&packet_size));
+ connection_.SendCryptoDataWithString("foo", 0);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AnyNumber());
EXPECT_EQ(0x01010101u, writer_->final_bytes_of_last_packet());
connection_.SetEncrypter(ENCRYPTION_ZERO_RTT,
@@ -4145,9 +4120,6 @@ TEST_P(QuicConnectionTest, RetransmitWithSameEncryptionLevel) {
}
TEST_P(QuicConnectionTest, SendHandshakeMessages) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
use_tagging_decrypter();
// A TaggingEncrypter puts kTagSize copies of the given byte (0x01 here) at
// the end of the packet. We can test this to check which encrypter was used.
@@ -4157,9 +4129,7 @@ TEST_P(QuicConnectionTest, SendHandshakeMessages) {
// Attempt to send a handshake message and have the socket block.
EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
BlockOnNextWrite();
- connection_.SendStreamDataWithString(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), "foo", 0,
- NO_FIN);
+ connection_.SendCryptoDataWithString("foo", 0);
// The packet should be serialized, but not queued.
EXPECT_EQ(1u, connection_.NumQueuedPackets());
@@ -4180,9 +4150,6 @@ TEST_P(QuicConnectionTest, SendHandshakeMessages) {
TEST_P(QuicConnectionTest,
DropRetransmitsForNullEncryptedPacketAfterForwardSecure) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
use_tagging_decrypter();
connection_.SetEncrypter(ENCRYPTION_INITIAL,
QuicMakeUnique<TaggingEncrypter>(0x01));
@@ -4209,17 +4176,12 @@ TEST_P(QuicConnectionTest,
}
TEST_P(QuicConnectionTest, RetransmitPacketsWithInitialEncryption) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
use_tagging_decrypter();
connection_.SetEncrypter(ENCRYPTION_INITIAL,
QuicMakeUnique<TaggingEncrypter>(0x01));
connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
- SendStreamDataToPeer(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), "foo", 0,
- NO_FIN, nullptr);
+ connection_.SendCryptoDataWithString("foo", 0);
connection_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(0x02));
@@ -4267,9 +4229,6 @@ TEST_P(QuicConnectionTest, BufferNonDecryptablePackets) {
}
TEST_P(QuicConnectionTest, TestRetransmitOrder) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
connection_.SetMaxTailLossProbes(0);
QuicByteCount first_packet_size;
@@ -4343,9 +4302,6 @@ TEST_P(QuicConnectionTest, Buffer100NonDecryptablePacketsThenKeyChange) {
}
TEST_P(QuicConnectionTest, SetRTOAfterWritingToSocket) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
BlockOnNextWrite();
connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN);
// Make sure that RTO is not started when the packet is queued.
@@ -4358,9 +4314,6 @@ TEST_P(QuicConnectionTest, SetRTOAfterWritingToSocket) {
}
TEST_P(QuicConnectionTest, DelayRTOWithAckReceipt) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
connection_.SetMaxTailLossProbes(0);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -4404,9 +4357,6 @@ TEST_P(QuicConnectionTest, DelayRTOWithAckReceipt) {
}
TEST_P(QuicConnectionTest, TestQueued) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
connection_.SetMaxTailLossProbes(0);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
@@ -4421,9 +4371,6 @@ TEST_P(QuicConnectionTest, TestQueued) {
}
TEST_P(QuicConnectionTest, InitialTimeout) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_TRUE(connection_.connected());
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AnyNumber());
EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
@@ -4452,12 +4399,10 @@ TEST_P(QuicConnectionTest, InitialTimeout) {
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
EXPECT_FALSE(connection_.GetSendAlarm()->IsSet());
EXPECT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet());
+ EXPECT_FALSE(connection_.GetProcessUndecryptablePacketsAlarm()->IsSet());
}
TEST_P(QuicConnectionTest, IdleTimeoutAfterFirstSentPacket) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_TRUE(connection_.connected());
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AnyNumber());
EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
@@ -4509,9 +4454,6 @@ TEST_P(QuicConnectionTest, IdleTimeoutAfterFirstSentPacket) {
}
TEST_P(QuicConnectionTest, IdleTimeoutAfterSendTwoPackets) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_TRUE(connection_.connected());
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AnyNumber());
EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
@@ -4572,9 +4514,6 @@ TEST_P(QuicConnectionTest, IdleTimeoutAfterSendTwoPackets) {
}
TEST_P(QuicConnectionTest, HandshakeTimeout) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Use a shorter handshake timeout than idle timeout for this test.
const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(5);
connection_.SetNetworkTimeouts(timeout, timeout);
@@ -4655,7 +4594,8 @@ TEST_P(QuicConnectionTest, PingAfterSend) {
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(15));
EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() { SendPing(); }));
connection_.GetPingAlarm()->Fire();
- EXPECT_EQ(1u, writer_->frame_count());
+ size_t padding_frame_count = writer_->padding_frames().size();
+ EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
ASSERT_EQ(1u, writer_->ping_frames().size());
writer_->Reset();
@@ -4710,7 +4650,8 @@ TEST_P(QuicConnectionTest, ReducedPingTimeout) {
connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
}));
connection_.GetPingAlarm()->Fire();
- EXPECT_EQ(1u, writer_->frame_count());
+ size_t padding_frame_count = writer_->padding_frames().size();
+ EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
ASSERT_EQ(1u, writer_->ping_frames().size());
writer_->Reset();
@@ -4767,9 +4708,6 @@ 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) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_TRUE(connection_.connected());
const QuicPacketCount packets_between_probes_base = 10;
@@ -4786,9 +4724,6 @@ TEST_P(QuicConnectionTest, MtuDiscoveryDisabled) {
// Tests whether MTU discovery works when the probe gets acknowledged on the
// first try.
TEST_P(QuicConnectionTest, MtuDiscoveryEnabled) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_TRUE(connection_.connected());
connection_.EnablePathMtuDiscovery(send_algorithm_);
@@ -4837,9 +4772,6 @@ TEST_P(QuicConnectionTest, MtuDiscoveryEnabled) {
// Tests whether MTU discovery works correctly when the probes never get
// acknowledged.
TEST_P(QuicConnectionTest, MtuDiscoveryFailed) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_TRUE(connection_.connected());
connection_.EnablePathMtuDiscovery(send_algorithm_);
@@ -4922,9 +4854,6 @@ TEST_P(QuicConnectionTest, MtuDiscoveryFailed) {
// Tests whether MTU discovery works when the writer has a limit on how large a
// packet can be.
TEST_P(QuicConnectionTest, MtuDiscoveryWriterLimited) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_TRUE(connection_.connected());
const QuicByteCount mtu_limit = kMtuDiscoveryTargetPacketSizeHigh - 1;
@@ -4975,9 +4904,6 @@ TEST_P(QuicConnectionTest, MtuDiscoveryWriterLimited) {
// Tests whether MTU discovery works when the writer returns an error despite
// advertising higher packet length.
TEST_P(QuicConnectionTest, MtuDiscoveryWriterFailed) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_TRUE(connection_.connected());
const QuicByteCount mtu_limit = kMtuDiscoveryTargetPacketSizeHigh - 1;
@@ -5030,9 +4956,6 @@ TEST_P(QuicConnectionTest, MtuDiscoveryWriterFailed) {
}
TEST_P(QuicConnectionTest, NoMtuDiscoveryAfterConnectionClosed) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_TRUE(connection_.connected());
connection_.EnablePathMtuDiscovery(send_algorithm_);
@@ -5057,9 +4980,6 @@ TEST_P(QuicConnectionTest, NoMtuDiscoveryAfterConnectionClosed) {
}
TEST_P(QuicConnectionTest, TimeoutAfterSend) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_TRUE(connection_.connected());
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
QuicConfig config;
@@ -5109,9 +5029,6 @@ TEST_P(QuicConnectionTest, TimeoutAfterSend) {
}
TEST_P(QuicConnectionTest, TimeoutAfterRetransmission) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_TRUE(connection_.connected());
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
@@ -5187,9 +5104,6 @@ TEST_P(QuicConnectionTest, TimeoutAfterRetransmission) {
}
TEST_P(QuicConnectionTest, NewTimeoutAfterSendSilentClose) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Same test as above, but complete a handshake which enables silent close,
// causing no connection close packet to be sent.
EXPECT_TRUE(connection_.connected());
@@ -5207,7 +5121,7 @@ TEST_P(QuicConnectionTest, NewTimeoutAfterSendSilentClose) {
client_config.SetIdleNetworkTimeout(
QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs),
QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs));
- client_config.ToHandshakeMessage(&msg);
+ client_config.ToHandshakeMessage(&msg, connection_.transport_version());
const QuicErrorCode error =
config.ProcessPeerHello(msg, CLIENT, &error_details);
EXPECT_EQ(QUIC_NO_ERROR, error);
@@ -5257,9 +5171,6 @@ TEST_P(QuicConnectionTest, NewTimeoutAfterSendSilentClose) {
}
TEST_P(QuicConnectionTest, TimeoutAfterSendSilentCloseAndTLP) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Same test as above, but complete a handshake which enables silent close,
// but sending TLPs causes the connection close to be sent.
EXPECT_TRUE(connection_.connected());
@@ -5277,7 +5188,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterSendSilentCloseAndTLP) {
client_config.SetIdleNetworkTimeout(
QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs),
QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs));
- client_config.ToHandshakeMessage(&msg);
+ client_config.ToHandshakeMessage(&msg, connection_.transport_version());
const QuicErrorCode error =
config.ProcessPeerHello(msg, CLIENT, &error_details);
EXPECT_EQ(QUIC_NO_ERROR, error);
@@ -5316,9 +5227,6 @@ TEST_P(QuicConnectionTest, TimeoutAfterSendSilentCloseAndTLP) {
}
TEST_P(QuicConnectionTest, TimeoutAfterSendSilentCloseWithOpenStreams) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Same test as above, but complete a handshake which enables silent close,
// but having open streams causes the connection close to be sent.
EXPECT_TRUE(connection_.connected());
@@ -5336,7 +5244,7 @@ TEST_P(QuicConnectionTest, TimeoutAfterSendSilentCloseWithOpenStreams) {
client_config.SetIdleNetworkTimeout(
QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs),
QuicTime::Delta::FromSeconds(kDefaultIdleTimeoutSecs));
- client_config.ToHandshakeMessage(&msg);
+ client_config.ToHandshakeMessage(&msg, connection_.transport_version());
const QuicErrorCode error =
config.ProcessPeerHello(msg, CLIENT, &error_details);
EXPECT_EQ(QUIC_NO_ERROR, error);
@@ -5373,9 +5281,6 @@ TEST_P(QuicConnectionTest, TimeoutAfterSendSilentCloseWithOpenStreams) {
}
TEST_P(QuicConnectionTest, TimeoutAfterReceive) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_TRUE(connection_.connected());
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
@@ -5426,9 +5331,6 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceive) {
}
TEST_P(QuicConnectionTest, TimeoutAfterReceiveNotSendWhenUnacked) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_TRUE(connection_.connected());
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
@@ -5491,9 +5393,6 @@ TEST_P(QuicConnectionTest, TimeoutAfterReceiveNotSendWhenUnacked) {
}
TEST_P(QuicConnectionTest, TimeoutAfter5ClientRTOs) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
connection_.SetMaxTailLossProbes(2);
EXPECT_TRUE(connection_.connected());
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
@@ -5528,9 +5427,6 @@ TEST_P(QuicConnectionTest, TimeoutAfter5ClientRTOs) {
}
TEST_P(QuicConnectionTest, SendScheduler) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Test that if we send a packet without delay, it is not queued.
QuicFramerPeer::SetPerspective(&peer_framer_, Perspective::IS_CLIENT);
std::unique_ptr<QuicPacket> packet =
@@ -5543,9 +5439,6 @@ TEST_P(QuicConnectionTest, SendScheduler) {
}
TEST_P(QuicConnectionTest, FailToSendFirstPacket) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Test that the connection does not crash when it fails to send the first
// packet at which point self_address_ might be uninitialized.
QuicFramerPeer::SetPerspective(&peer_framer_, Perspective::IS_CLIENT);
@@ -5559,9 +5452,6 @@ TEST_P(QuicConnectionTest, FailToSendFirstPacket) {
}
TEST_P(QuicConnectionTest, SendSchedulerEAGAIN) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
QuicFramerPeer::SetPerspective(&peer_framer_, Perspective::IS_CLIENT);
std::unique_ptr<QuicPacket> packet =
ConstructDataPacket(1, !kHasStopWaiting, ENCRYPTION_INITIAL);
@@ -5575,10 +5465,6 @@ TEST_P(QuicConnectionTest, SendSchedulerEAGAIN) {
}
TEST_P(QuicConnectionTest, TestQueueLimitsOnSendStreamData) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
-
// Queue the first packet.
size_t payload_length = connection_.max_packet_length();
EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(testing::Return(false));
@@ -5593,10 +5479,6 @@ TEST_P(QuicConnectionTest, TestQueueLimitsOnSendStreamData) {
}
TEST_P(QuicConnectionTest, SendingThreePackets) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
-
// Make the payload twice the size of the packet, so 3 packets are written.
size_t total_payload_length = 2 * connection_.max_packet_length();
const std::string payload(total_payload_length, 'a');
@@ -5610,9 +5492,6 @@ TEST_P(QuicConnectionTest, SendingThreePackets) {
}
TEST_P(QuicConnectionTest, LoopThroughSendingPacketsWithTruncation) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
set_perspective(Perspective::IS_SERVER);
if (GetParam().version.transport_version <= QUIC_VERSION_43) {
// For IETF QUIC, encryption level will be switched to FORWARD_SECURE in
@@ -5653,9 +5532,6 @@ TEST_P(QuicConnectionTest, LoopThroughSendingPacketsWithTruncation) {
}
TEST_P(QuicConnectionTest, SendDelayedAck) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
QuicTime ack_time = clock_.ApproximateNow() + DefaultDelayedAckTime();
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
@@ -5679,11 +5555,12 @@ TEST_P(QuicConnectionTest, SendDelayedAck) {
clock_.AdvanceTime(DefaultDelayedAckTime());
connection_.GetAckAlarm()->Fire();
// Check that ack is sent and that delayed ack alarm is reset.
+ size_t padding_frame_count = writer_->padding_frames().size();
if (GetParam().no_stop_waiting) {
- EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
EXPECT_TRUE(writer_->stop_waiting_frames().empty());
} else {
- EXPECT_EQ(2u, writer_->frame_count());
+ EXPECT_EQ(padding_frame_count + 2u, writer_->frame_count());
EXPECT_FALSE(writer_->stop_waiting_frames().empty());
}
EXPECT_FALSE(writer_->ack_frames().empty());
@@ -5691,9 +5568,6 @@ TEST_P(QuicConnectionTest, SendDelayedAck) {
}
TEST_P(QuicConnectionTest, SendDelayedAfterQuiescence) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
QuicConnectionPeer::SetFastAckAfterQuiescence(&connection_, true);
// The beginning of the connection counts as quiescence.
@@ -5721,11 +5595,12 @@ TEST_P(QuicConnectionTest, SendDelayedAfterQuiescence) {
clock_.AdvanceTime(DefaultDelayedAckTime());
connection_.GetAckAlarm()->Fire();
// Check that ack is sent and that delayed ack alarm is reset.
+ size_t padding_frame_count = writer_->padding_frames().size();
if (GetParam().no_stop_waiting) {
- EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
EXPECT_TRUE(writer_->stop_waiting_frames().empty());
} else {
- EXPECT_EQ(2u, writer_->frame_count());
+ EXPECT_EQ(padding_frame_count + 2u, writer_->frame_count());
EXPECT_FALSE(writer_->stop_waiting_frames().empty());
}
EXPECT_FALSE(writer_->ack_frames().empty());
@@ -5744,11 +5619,12 @@ TEST_P(QuicConnectionTest, SendDelayedAfterQuiescence) {
clock_.AdvanceTime(DefaultDelayedAckTime());
connection_.GetAckAlarm()->Fire();
// Check that ack is sent and that delayed ack alarm is reset.
+ padding_frame_count = writer_->padding_frames().size();
if (GetParam().no_stop_waiting) {
- EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
EXPECT_TRUE(writer_->stop_waiting_frames().empty());
} else {
- EXPECT_EQ(2u, writer_->frame_count());
+ EXPECT_EQ(padding_frame_count + 2u, writer_->frame_count());
EXPECT_FALSE(writer_->stop_waiting_frames().empty());
}
EXPECT_FALSE(writer_->ack_frames().empty());
@@ -5766,9 +5642,6 @@ TEST_P(QuicConnectionTest, SendDelayedAfterQuiescence) {
}
TEST_P(QuicConnectionTest, SendDelayedAckDecimation) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber());
QuicConnectionPeer::SetAckMode(&connection_, ACK_DECIMATION);
@@ -5827,9 +5700,6 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimation) {
}
TEST_P(QuicConnectionTest, SendDelayedAckAckDecimationAfterQuiescence) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber());
QuicConnectionPeer::SetAckMode(&connection_, ACK_DECIMATION);
QuicConnectionPeer::SetFastAckAfterQuiescence(&connection_, true);
@@ -5864,11 +5734,12 @@ TEST_P(QuicConnectionTest, SendDelayedAckAckDecimationAfterQuiescence) {
clock_.AdvanceTime(DefaultDelayedAckTime());
connection_.GetAckAlarm()->Fire();
// Check that ack is sent and that delayed ack alarm is reset.
+ size_t padding_frame_count = writer_->padding_frames().size();
if (GetParam().no_stop_waiting) {
- EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
EXPECT_TRUE(writer_->stop_waiting_frames().empty());
} else {
- EXPECT_EQ(2u, writer_->frame_count());
+ EXPECT_EQ(padding_frame_count + 2u, writer_->frame_count());
EXPECT_FALSE(writer_->stop_waiting_frames().empty());
}
EXPECT_FALSE(writer_->ack_frames().empty());
@@ -5887,11 +5758,12 @@ TEST_P(QuicConnectionTest, SendDelayedAckAckDecimationAfterQuiescence) {
clock_.AdvanceTime(DefaultDelayedAckTime());
connection_.GetAckAlarm()->Fire();
// Check that ack is sent and that delayed ack alarm is reset.
+ padding_frame_count = writer_->padding_frames().size();
if (GetParam().no_stop_waiting) {
- EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
EXPECT_TRUE(writer_->stop_waiting_frames().empty());
} else {
- EXPECT_EQ(2u, writer_->frame_count());
+ EXPECT_EQ(padding_frame_count + 2u, writer_->frame_count());
EXPECT_FALSE(writer_->stop_waiting_frames().empty());
}
EXPECT_FALSE(writer_->ack_frames().empty());
@@ -5959,9 +5831,6 @@ TEST_P(QuicConnectionTest, SendDelayedAckAckDecimationAfterQuiescence) {
}
TEST_P(QuicConnectionTest, SendDelayedAckDecimationUnlimitedAggregation) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber());
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
QuicConfig config;
@@ -6021,9 +5890,6 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationUnlimitedAggregation) {
}
TEST_P(QuicConnectionTest, SendDelayedAckDecimationEighthRtt) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber());
QuicConnectionPeer::SetAckMode(&connection_, ACK_DECIMATION);
QuicConnectionPeer::SetAckDecimationDelay(&connection_, 0.125);
@@ -6083,9 +5949,6 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationEighthRtt) {
}
TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReordering) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber());
QuicConnectionPeer::SetAckMode(&connection_, ACK_DECIMATION_WITH_REORDERING);
@@ -6150,9 +6013,6 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReordering) {
}
TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReordering) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber());
QuicConnectionPeer::SetAckMode(&connection_, ACK_DECIMATION_WITH_REORDERING);
@@ -6236,9 +6096,6 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReordering) {
}
TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReorderingEighthRtt) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber());
QuicConnectionPeer::SetAckMode(&connection_, ACK_DECIMATION_WITH_REORDERING);
QuicConnectionPeer::SetAckDecimationDelay(&connection_, 0.125);
@@ -6307,9 +6164,6 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReorderingEighthRtt) {
TEST_P(QuicConnectionTest,
SendDelayedAckDecimationWithLargeReorderingEighthRtt) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber());
QuicConnectionPeer::SetAckMode(&connection_, ACK_DECIMATION_WITH_REORDERING);
QuicConnectionPeer::SetAckDecimationDelay(&connection_, 0.125);
@@ -6394,9 +6248,6 @@ TEST_P(QuicConnectionTest,
}
TEST_P(QuicConnectionTest, SendDelayedAckOnHandshakeConfirmed) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessPacket(1);
// Check that ack is sent and that delayed ack alarm is set.
@@ -6418,18 +6269,16 @@ TEST_P(QuicConnectionTest, SendDelayedAckOnHandshakeConfirmed) {
}
TEST_P(QuicConnectionTest, SendDelayedAckOnSecondPacket) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessPacket(1);
ProcessPacket(2);
// Check that ack is sent and that delayed ack alarm is reset.
+ size_t padding_frame_count = writer_->padding_frames().size();
if (GetParam().no_stop_waiting) {
- EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
EXPECT_TRUE(writer_->stop_waiting_frames().empty());
} else {
- EXPECT_EQ(2u, writer_->frame_count());
+ EXPECT_EQ(padding_frame_count + 2u, writer_->frame_count());
EXPECT_FALSE(writer_->stop_waiting_frames().empty());
}
EXPECT_FALSE(writer_->ack_frames().empty());
@@ -6437,9 +6286,6 @@ TEST_P(QuicConnectionTest, SendDelayedAckOnSecondPacket) {
}
TEST_P(QuicConnectionTest, NoAckOnOldNacks) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Drop one packet, triggering a sequence of acks.
if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
@@ -6450,14 +6296,16 @@ TEST_P(QuicConnectionTest, NoAckOnOldNacks) {
ProcessPacket(2);
size_t frames_per_ack = GetParam().no_stop_waiting ? 1 : 2;
if (!GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
- EXPECT_EQ(frames_per_ack, writer_->frame_count());
+ size_t padding_frame_count = writer_->padding_frames().size();
+ EXPECT_EQ(padding_frame_count + frames_per_ack, writer_->frame_count());
EXPECT_FALSE(writer_->ack_frames().empty());
writer_->Reset();
}
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
ProcessPacket(3);
- EXPECT_EQ(frames_per_ack, writer_->frame_count());
+ size_t padding_frame_count = writer_->padding_frames().size();
+ EXPECT_EQ(padding_frame_count + frames_per_ack, writer_->frame_count());
EXPECT_FALSE(writer_->ack_frames().empty());
writer_->Reset();
@@ -6470,35 +6318,34 @@ TEST_P(QuicConnectionTest, NoAckOnOldNacks) {
if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
EXPECT_EQ(0u, writer_->frame_count());
} else {
- EXPECT_EQ(frames_per_ack, writer_->frame_count());
+ EXPECT_EQ(padding_frame_count + frames_per_ack, writer_->frame_count());
EXPECT_FALSE(writer_->ack_frames().empty());
writer_->Reset();
}
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
ProcessPacket(5);
- EXPECT_EQ(frames_per_ack, writer_->frame_count());
+ padding_frame_count = writer_->padding_frames().size();
+ EXPECT_EQ(padding_frame_count + frames_per_ack, writer_->frame_count());
EXPECT_FALSE(writer_->ack_frames().empty());
writer_->Reset();
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
// Now only set the timer on the 6th packet, instead of sending another ack.
ProcessPacket(6);
- EXPECT_EQ(0u, writer_->frame_count());
+ padding_frame_count = writer_->padding_frames().size();
+ EXPECT_EQ(padding_frame_count, writer_->frame_count());
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
}
TEST_P(QuicConnectionTest, SendDelayedAckOnOutgoingPacket) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(visitor_, OnStreamFrame(_));
peer_framer_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
QuicMakeUnique<TaggingEncrypter>(0x01));
SetDecrypter(ENCRYPTION_FORWARD_SECURE,
QuicMakeUnique<StrictTaggingDecrypter>(0x01));
- ProcessDataPacketAtLevel(1, false, ENCRYPTION_FORWARD_SECURE);
+ ProcessDataPacket(1);
connection_.SendStreamDataWithString(
GetNthClientInitiatedStreamId(1, connection_.transport_version()), "foo",
0, NO_FIN);
@@ -6521,9 +6368,7 @@ TEST_P(QuicConnectionTest, SendDelayedAckOnOutgoingCryptoPacket) {
}
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessPacket(1);
- connection_.SendStreamDataWithString(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), "foo", 0,
- NO_FIN);
+ connection_.SendCryptoDataWithString("foo", 0);
// Check that ack is bundled with outgoing crypto data.
if (GetParam().no_stop_waiting) {
EXPECT_EQ(3u, writer_->frame_count());
@@ -6536,21 +6381,14 @@ TEST_P(QuicConnectionTest, SendDelayedAckOnOutgoingCryptoPacket) {
}
TEST_P(QuicConnectionTest, BlockAndBufferOnFirstCHLOPacketOfTwo) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessPacket(1);
BlockOnNextWrite();
writer_->set_is_write_blocked_data_buffered(true);
- connection_.SendStreamDataWithString(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), "foo", 0,
- NO_FIN);
+ connection_.SendCryptoDataWithString("foo", 0);
EXPECT_TRUE(writer_->IsWriteBlocked());
EXPECT_FALSE(connection_.HasQueuedData());
- connection_.SendStreamDataWithString(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), "bar", 3,
- NO_FIN);
+ connection_.SendCryptoDataWithString("bar", 3);
EXPECT_TRUE(writer_->IsWriteBlocked());
EXPECT_TRUE(connection_.HasQueuedData());
}
@@ -6624,9 +6462,6 @@ TEST_P(QuicConnectionTest, BundleAckForSecondCHLOTwoPacketReject) {
}
TEST_P(QuicConnectionTest, BundleAckWithDataOnIncomingAck) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
connection_.SendStreamDataWithString(
GetNthClientInitiatedStreamId(1, connection_.transport_version()), "foo",
@@ -6643,7 +6478,8 @@ TEST_P(QuicConnectionTest, BundleAckWithDataOnIncomingAck) {
.WillOnce(SetArgPointee<5>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
ProcessAckPacket(&ack);
- EXPECT_EQ(1u, writer_->frame_count());
+ size_t padding_frame_count = writer_->padding_frames().size();
+ EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
EXPECT_EQ(1u, writer_->stream_frames().size());
writer_->Reset();
@@ -6670,22 +6506,30 @@ TEST_P(QuicConnectionTest, BundleAckWithDataOnIncomingAck) {
// Check that ack is bundled with outgoing data and the delayed ack
// alarm is reset.
if (GetParam().no_stop_waiting) {
- EXPECT_EQ(2u, writer_->frame_count());
- EXPECT_TRUE(writer_->stop_waiting_frames().empty());
+ 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());
+ }
} else {
EXPECT_EQ(3u, writer_->frame_count());
EXPECT_FALSE(writer_->stop_waiting_frames().empty());
}
- EXPECT_FALSE(writer_->ack_frames().empty());
- EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(writer_->ack_frames().front()));
+ if (GetParam().no_stop_waiting &&
+ GetQuicReloadableFlag(quic_simplify_stop_waiting)) {
+ EXPECT_TRUE(writer_->ack_frames().empty());
+ } else {
+ EXPECT_FALSE(writer_->ack_frames().empty());
+ EXPECT_EQ(QuicPacketNumber(3u),
+ LargestAcked(writer_->ack_frames().front()));
+ }
EXPECT_EQ(1u, writer_->stream_frames().size());
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
}
TEST_P(QuicConnectionTest, NoAckSentForClose) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessPacket(1);
EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, _,
@@ -6695,9 +6539,6 @@ TEST_P(QuicConnectionTest, NoAckSentForClose) {
}
TEST_P(QuicConnectionTest, SendWhenDisconnected) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_TRUE(connection_.connected());
EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, _,
ConnectionCloseSource::FROM_SELF));
@@ -6738,9 +6579,6 @@ TEST_P(QuicConnectionTest, SendConnectivityProbingWhenDisconnected) {
}
TEST_P(QuicConnectionTest, WriteBlockedAfterClientSendsConnectivityProbe) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
TestPacketWriter probing_writer(version(), &clock_);
// Block next write so that sending connectivity probe will encounter a
@@ -6757,9 +6595,6 @@ TEST_P(QuicConnectionTest, WriteBlockedAfterClientSendsConnectivityProbe) {
}
TEST_P(QuicConnectionTest, WriterBlockedAfterServerSendsConnectivityProbe) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
@@ -6777,9 +6612,6 @@ TEST_P(QuicConnectionTest, WriterBlockedAfterServerSendsConnectivityProbe) {
}
TEST_P(QuicConnectionTest, WriterErrorWhenClientSendsConnectivityProbe) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
TestPacketWriter probing_writer(version(), &clock_);
probing_writer.SetShouldWriteFail();
@@ -6795,9 +6627,6 @@ TEST_P(QuicConnectionTest, WriterErrorWhenClientSendsConnectivityProbe) {
}
TEST_P(QuicConnectionTest, WriterErrorWhenServerSendsConnectivityProbe) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
@@ -6868,9 +6697,6 @@ TEST_P(QuicConnectionTest, GoAway) {
}
TEST_P(QuicConnectionTest, WindowUpdate) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
QuicWindowUpdateFrame window_update;
@@ -6881,9 +6707,6 @@ TEST_P(QuicConnectionTest, WindowUpdate) {
}
TEST_P(QuicConnectionTest, Blocked) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
QuicBlockedFrame blocked;
@@ -6895,9 +6718,6 @@ TEST_P(QuicConnectionTest, Blocked) {
}
TEST_P(QuicConnectionTest, ZeroBytePacket) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Don't close the connection for zero byte packets.
EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _)).Times(0);
QuicReceivedPacket encrypted(nullptr, 0, QuicTime::Zero());
@@ -6905,8 +6725,7 @@ TEST_P(QuicConnectionTest, ZeroBytePacket) {
}
TEST_P(QuicConnectionTest, MissingPacketsBeforeLeastUnacked) {
- if (GetParam().version.transport_version > QUIC_VERSION_43 ||
- connection_.SupportsMultiplePacketNumberSpaces()) {
+ if (GetParam().version.transport_version > QUIC_VERSION_43) {
return;
}
// Set the packet number of the ack packet to be least unacked (4).
@@ -6917,9 +6736,6 @@ TEST_P(QuicConnectionTest, MissingPacketsBeforeLeastUnacked) {
}
TEST_P(QuicConnectionTest, ServerSendsVersionNegotiationPacket) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Turn off QUIC_VERSION_99.
SetQuicReloadableFlag(quic_enable_version_99, false);
connection_.SetSupportedVersions(CurrentSupportedVersions());
@@ -6973,9 +6789,6 @@ TEST_P(QuicConnectionTest, ServerSendsVersionNegotiationPacket) {
}
TEST_P(QuicConnectionTest, ServerSendsVersionNegotiationPacketSocketBlocked) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Turn off QUIC_VERSION_99.
SetQuicReloadableFlag(quic_enable_version_99, false);
connection_.SetSupportedVersions(CurrentSupportedVersions());
@@ -7036,9 +6849,6 @@ TEST_P(QuicConnectionTest, ServerSendsVersionNegotiationPacketSocketBlocked) {
TEST_P(QuicConnectionTest,
ServerSendsVersionNegotiationPacketSocketBlockedDataBuffered) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Turn off QUIC_VERSION_99.
SetQuicReloadableFlag(quic_enable_version_99, false);
connection_.SetSupportedVersions(CurrentSupportedVersions());
@@ -7085,30 +6895,28 @@ TEST_P(QuicConnectionTest,
}
TEST_P(QuicConnectionTest, ClientHandlesVersionNegotiation) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
- // Start out with some unsupported version.
+ const bool expect_failure =
+ GetQuicReloadableFlag(quic_no_client_conn_ver_negotiation) ||
+ connection_.version().handshake_protocol !=
+ QuicVersionReservedForNegotiation().handshake_protocol;
+ // Start out with an unsupported version.
QuicConnectionPeer::GetFramer(&connection_)
- ->set_version_for_tests(ParsedQuicVersion(
- PROTOCOL_UNSUPPORTED,
- GetParam().version.transport_version == QUIC_VERSION_99
- ? QUIC_VERSION_99
- : QUIC_VERSION_UNSUPPORTED));
+ ->set_version_for_tests(QuicVersionReservedForNegotiation());
// Send a version negotiation packet.
std::unique_ptr<QuicEncryptedPacket> encrypted(
- peer_framer_.BuildVersionNegotiationPacket(
- connection_id_, connection_.transport_version() > QUIC_VERSION_43,
+ QuicFramer::BuildVersionNegotiationPacket(
+ connection_id_, EmptyQuicConnectionId(),
+ connection_.transport_version() > QUIC_VERSION_43,
AllSupportedVersions()));
std::unique_ptr<QuicReceivedPacket> received(
ConstructReceivedPacket(*encrypted, QuicTime::Zero()));
- if (GetQuicReloadableFlag(quic_no_client_conn_ver_negotiation)) {
+ if (expect_failure) {
EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_VERSION, _,
ConnectionCloseSource::FROM_SELF));
}
connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received);
- if (GetQuicReloadableFlag(quic_no_client_conn_ver_negotiation)) {
+ if (expect_failure) {
EXPECT_FALSE(connection_.connected());
return;
}
@@ -7116,8 +6924,12 @@ TEST_P(QuicConnectionTest, ClientHandlesVersionNegotiation) {
// Now force another packet. The connection should transition into
// NEGOTIATED_VERSION state and tell the packet creator to StopSendingVersion.
QuicPacketHeader header;
- header.destination_connection_id = connection_id_;
header.destination_connection_id_included = CONNECTION_ID_ABSENT;
+ if (!GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ header.destination_connection_id = connection_id_;
+ } else {
+ header.source_connection_id = connection_id_;
+ }
header.packet_number = QuicPacketNumber(12);
header.version_flag = false;
QuicFrames frames;
@@ -7143,17 +6955,15 @@ TEST_P(QuicConnectionTest, ClientHandlesVersionNegotiation) {
}
TEST_P(QuicConnectionTest, BadVersionNegotiation) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Send a version negotiation packet with the version the client started with.
// It should be rejected.
EXPECT_CALL(visitor_,
OnConnectionClosed(QUIC_INVALID_VERSION_NEGOTIATION_PACKET, _,
ConnectionCloseSource::FROM_SELF));
std::unique_ptr<QuicEncryptedPacket> encrypted(
- framer_.BuildVersionNegotiationPacket(
- connection_id_, connection_.transport_version() > QUIC_VERSION_43,
+ QuicFramer::BuildVersionNegotiationPacket(
+ connection_id_, EmptyQuicConnectionId(),
+ connection_.transport_version() > QUIC_VERSION_43,
AllSupportedVersions()));
std::unique_ptr<QuicReceivedPacket> received(
ConstructReceivedPacket(*encrypted, QuicTime::Zero()));
@@ -7161,9 +6971,6 @@ TEST_P(QuicConnectionTest, BadVersionNegotiation) {
}
TEST_P(QuicConnectionTest, CheckSendStats) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
connection_.SetMaxTailLossProbes(0);
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
@@ -7221,14 +7028,20 @@ TEST_P(QuicConnectionTest, CheckSendStats) {
}
TEST_P(QuicConnectionTest, ProcessFramesIfPacketClosedConnection) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Construct a packet with stream frame and connection close frame.
QuicPacketHeader header;
- header.destination_connection_id = connection_id_;
- if (peer_framer_.transport_version() > QUIC_VERSION_43) {
+ if (GetQuicRestartFlag(quic_do_not_override_connection_id) &&
+ peer_framer_.perspective() == Perspective::IS_SERVER) {
+ header.source_connection_id = connection_id_;
header.destination_connection_id_included = CONNECTION_ID_ABSENT;
+ if (peer_framer_.transport_version() <= QUIC_VERSION_43) {
+ header.source_connection_id_included = CONNECTION_ID_PRESENT;
+ }
+ } else {
+ header.destination_connection_id = connection_id_;
+ if (peer_framer_.transport_version() > QUIC_VERSION_43) {
+ header.destination_connection_id_included = CONNECTION_ID_ABSENT;
+ }
}
header.packet_number = QuicPacketNumber(1);
header.version_flag = false;
@@ -7261,9 +7074,6 @@ TEST_P(QuicConnectionTest, ProcessFramesIfPacketClosedConnection) {
}
TEST_P(QuicConnectionTest, SelectMutualVersion) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
connection_.SetSupportedVersions(AllSupportedVersions());
// Set the connection to speak the lowest quic version.
connection_.set_version(QuicVersionMin());
@@ -7290,9 +7100,6 @@ TEST_P(QuicConnectionTest, SelectMutualVersion) {
}
TEST_P(QuicConnectionTest, ConnectionCloseWhenWritable) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_FALSE(writer_->IsWriteBlocked());
// Send a packet.
@@ -7305,9 +7112,6 @@ TEST_P(QuicConnectionTest, ConnectionCloseWhenWritable) {
}
TEST_P(QuicConnectionTest, ConnectionCloseGettingWriteBlocked) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
BlockOnNextWrite();
TriggerConnectionClose();
EXPECT_EQ(1u, writer_->packets_write_attempts());
@@ -7315,9 +7119,6 @@ TEST_P(QuicConnectionTest, ConnectionCloseGettingWriteBlocked) {
}
TEST_P(QuicConnectionTest, ConnectionCloseWhenWriteBlocked) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
BlockOnNextWrite();
connection_.SendStreamDataWithString(1, "foo", 0, NO_FIN);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
@@ -7328,9 +7129,6 @@ TEST_P(QuicConnectionTest, ConnectionCloseWhenWriteBlocked) {
}
TEST_P(QuicConnectionTest, OnPacketSentDebugVisitor) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
MockQuicConnectionDebugVisitor debug_visitor;
connection_.set_debug_visitor(&debug_visitor);
@@ -7343,9 +7141,6 @@ TEST_P(QuicConnectionTest, OnPacketSentDebugVisitor) {
}
TEST_P(QuicConnectionTest, OnPacketHeaderDebugVisitor) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
QuicPacketHeader header;
header.packet_number = QuicPacketNumber(1);
if (GetParam().version.transport_version > QUIC_VERSION_43) {
@@ -7361,9 +7156,6 @@ TEST_P(QuicConnectionTest, OnPacketHeaderDebugVisitor) {
}
TEST_P(QuicConnectionTest, Pacing) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
TestConnection server(connection_id_, kSelfAddress, helper_.get(),
alarm_factory_.get(), writer_.get(),
Perspective::IS_SERVER, version());
@@ -7379,9 +7171,6 @@ TEST_P(QuicConnectionTest, Pacing) {
}
TEST_P(QuicConnectionTest, WindowUpdateInstigateAcks) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Send a WINDOW_UPDATE frame.
@@ -7397,9 +7186,6 @@ TEST_P(QuicConnectionTest, WindowUpdateInstigateAcks) {
}
TEST_P(QuicConnectionTest, BlockedFrameInstigateAcks) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Send a BLOCKED frame.
@@ -7414,9 +7200,6 @@ TEST_P(QuicConnectionTest, BlockedFrameInstigateAcks) {
}
TEST_P(QuicConnectionTest, ReevaluateTimeUntilSendOnAck) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Enable pacing.
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
QuicConfig config;
@@ -7455,7 +7238,8 @@ TEST_P(QuicConnectionTest, ReevaluateTimeUntilSendOnAck) {
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
ProcessAckPacket(&ack);
- EXPECT_EQ(1u, writer_->frame_count());
+ size_t padding_frame_count = writer_->padding_frames().size();
+ EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
EXPECT_EQ(1u, writer_->stream_frames().size());
EXPECT_TRUE(connection_.GetSendAlarm()->IsSet());
EXPECT_EQ(scheduled_pacing_time, connection_.GetSendAlarm()->deadline());
@@ -7474,9 +7258,6 @@ TEST_P(QuicConnectionTest, SendAcksImmediately) {
}
TEST_P(QuicConnectionTest, SendPingImmediately) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
MockQuicConnectionDebugVisitor debug_visitor;
connection_.set_debug_visitor(&debug_visitor);
@@ -7489,9 +7270,6 @@ TEST_P(QuicConnectionTest, SendPingImmediately) {
}
TEST_P(QuicConnectionTest, SendBlockedImmediately) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
MockQuicConnectionDebugVisitor debug_visitor;
connection_.set_debug_visitor(&debug_visitor);
@@ -7504,9 +7282,6 @@ TEST_P(QuicConnectionTest, SendBlockedImmediately) {
}
TEST_P(QuicConnectionTest, SendingUnencryptedStreamDataFails) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
if (!IsDefaultTestConfiguration()) {
return;
@@ -7518,14 +7293,11 @@ TEST_P(QuicConnectionTest, SendingUnencryptedStreamDataFails) {
struct iovec iov;
MakeIOVector("", &iov);
EXPECT_QUIC_BUG(connection_.SaveAndSendStreamData(3, &iov, 1, 0, 0, FIN),
- "Cannot send stream data without encryption.");
+ "Cannot send stream data with level: ENCRYPTION_INITIAL");
EXPECT_FALSE(connection_.connected());
}
TEST_P(QuicConnectionTest, SetRetransmissionAlarmForCryptoPacket) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_TRUE(connection_.connected());
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
@@ -7547,9 +7319,6 @@ TEST_P(QuicConnectionTest, SetRetransmissionAlarmForCryptoPacket) {
}
TEST_P(QuicConnectionTest, PathDegradingAlarmForCryptoPacket) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_TRUE(connection_.connected());
EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
EXPECT_FALSE(connection_.IsPathDegrading());
@@ -7575,9 +7344,6 @@ TEST_P(QuicConnectionTest, PathDegradingAlarmForCryptoPacket) {
// Includes regression test for b/69979024.
TEST_P(QuicConnectionTest, PathDegradingAlarmForNonCryptoPackets) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_TRUE(connection_.connected());
EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
EXPECT_FALSE(connection_.IsPathDegrading());
@@ -7652,9 +7418,6 @@ TEST_P(QuicConnectionTest, PathDegradingAlarmForNonCryptoPackets) {
}
TEST_P(QuicConnectionTest, RetransmittableOnWireSetsPingAlarm) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
const QuicTime::Delta retransmittable_on_wire_timeout =
QuicTime::Delta::FromMilliseconds(50);
connection_.set_retransmittable_on_wire_timeout(
@@ -7726,9 +7489,6 @@ TEST_P(QuicConnectionTest, RetransmittableOnWireSetsPingAlarm) {
// spin timer to detect path degrading when a new packet is sent on the
// degraded path.
TEST_P(QuicConnectionTest, NoPathDegradingAlarmIfPathIsDegrading) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_TRUE(connection_.connected());
EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
EXPECT_FALSE(connection_.IsPathDegrading());
@@ -7795,9 +7555,6 @@ TEST_P(QuicConnectionTest, NoPathDegradingAlarmIfPathIsDegrading) {
// the timer to detect future path degrading when forward progress is made
// after path has been marked degrading.
TEST_P(QuicConnectionTest, UnmarkPathDegradingOnForwardProgress) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_TRUE(connection_.connected());
EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
EXPECT_FALSE(connection_.IsPathDegrading());
@@ -7910,9 +7667,6 @@ TEST_P(QuicConnectionTest, NoPathDegradingAfterSendingAck) {
}
TEST_P(QuicConnectionTest, MultipleCallsToCloseConnection) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Verifies that multiple calls to CloseConnection do not
// result in multiple attempts to close the connection - it will be marked as
// disconnected after the first call.
@@ -7924,9 +7678,6 @@ TEST_P(QuicConnectionTest, MultipleCallsToCloseConnection) {
}
TEST_P(QuicConnectionTest, ServerReceivesChloOnNonCryptoStream) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
@@ -7946,9 +7697,6 @@ TEST_P(QuicConnectionTest, ServerReceivesChloOnNonCryptoStream) {
}
TEST_P(QuicConnectionTest, ClientReceivesRejOnNonCryptoStream) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
CryptoHandshakeMessage message;
@@ -7965,9 +7713,6 @@ TEST_P(QuicConnectionTest, ClientReceivesRejOnNonCryptoStream) {
}
TEST_P(QuicConnectionTest, CloseConnectionOnPacketTooLarge) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
SimulateNextPacketTooLarge();
// A connection close packet is sent
EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PACKET_WRITE_ERROR, _,
@@ -7977,9 +7722,6 @@ TEST_P(QuicConnectionTest, CloseConnectionOnPacketTooLarge) {
}
TEST_P(QuicConnectionTest, AlwaysGetPacketTooLarge) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// Test even we always get packet too large, we do not infinitely try to send
// close packet.
AlwaysGetPacketTooLarge();
@@ -7992,9 +7734,6 @@ TEST_P(QuicConnectionTest, AlwaysGetPacketTooLarge) {
// Verify that if connection has no outstanding data, it notifies the send
// algorithm after the write.
TEST_P(QuicConnectionTest, SendDataAndBecomeApplicationLimited) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(1);
{
InSequence seq;
@@ -8010,9 +7749,6 @@ TEST_P(QuicConnectionTest, SendDataAndBecomeApplicationLimited) {
// Verify that the connection does not become app-limited if there is
// outstanding data to send after the write.
TEST_P(QuicConnectionTest, NotBecomeApplicationLimitedIfMoreDataAvailable) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(0);
{
InSequence seq;
@@ -8026,9 +7762,6 @@ TEST_P(QuicConnectionTest, NotBecomeApplicationLimitedIfMoreDataAvailable) {
// Verify that the connection does not become app-limited after blocked write
// even if there is outstanding data to send after the write.
TEST_P(QuicConnectionTest, NotBecomeApplicationLimitedDueToWriteBlock) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(*send_algorithm_, OnApplicationLimited(_)).Times(0);
EXPECT_CALL(visitor_, WillingAndAbleToWrite()).WillRepeatedly(Return(true));
BlockOnNextWrite();
@@ -8051,9 +7784,6 @@ TEST_P(QuicConnectionTest, NotBecomeApplicationLimitedDueToWriteBlock) {
// Test the mode in which the link is filled up with probing retransmissions if
// the connection becomes application-limited.
TEST_P(QuicConnectionTest, SendDataWhenApplicationLimited) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, ShouldSendProbingPacket())
.WillRepeatedly(Return(true));
@@ -8064,6 +7794,10 @@ TEST_P(QuicConnectionTest, SendDataWhenApplicationLimited) {
EXPECT_CALL(visitor_, WillingAndAbleToWrite())
.WillRepeatedly(Return(false));
}
+ EXPECT_CALL(visitor_, SendProbingData()).WillRepeatedly([this] {
+ return connection_.sent_packet_manager().MaybeRetransmitOldestPacket(
+ PROBING_RETRANSMISSION);
+ });
// Fix congestion window to be 20,000 bytes.
EXPECT_CALL(*send_algorithm_, CanSend(Ge(20000u)))
.WillRepeatedly(Return(false));
@@ -8097,9 +7831,6 @@ TEST_P(QuicConnectionTest, SendDataWhenApplicationLimited) {
}
TEST_P(QuicConnectionTest, DonotForceSendingAckOnPacketTooLarge) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Send an ack by simulating delayed ack alarm firing.
ProcessPacket(1);
@@ -8117,9 +7848,6 @@ TEST_P(QuicConnectionTest, DonotForceSendingAckOnPacketTooLarge) {
}
TEST_P(QuicConnectionTest, CloseConnectionForStatelessReject) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
std::string error_details("stateless reject");
EXPECT_CALL(visitor_, OnConnectionClosed(
QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT,
@@ -8132,9 +7860,6 @@ TEST_P(QuicConnectionTest, CloseConnectionForStatelessReject) {
// Regression test for b/63620844.
TEST_P(QuicConnectionTest, FailedToWriteHandshakePacket) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
SimulateNextPacketTooLarge();
EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PACKET_WRITE_ERROR, _,
ConnectionCloseSource::FROM_SELF))
@@ -8143,18 +7868,12 @@ TEST_P(QuicConnectionTest, FailedToWriteHandshakePacket) {
}
TEST_P(QuicConnectionTest, MaxPacingRate) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_EQ(0, connection_.MaxPacingRate().ToBytesPerSecond());
connection_.SetMaxPacingRate(QuicBandwidth::FromBytesPerSecond(100));
EXPECT_EQ(100, connection_.MaxPacingRate().ToBytesPerSecond());
}
TEST_P(QuicConnectionTest, ClientAlwaysSendConnectionId) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN);
@@ -8174,9 +7893,6 @@ TEST_P(QuicConnectionTest, ClientAlwaysSendConnectionId) {
}
TEST_P(QuicConnectionTest, SendProbingRetransmissions) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
MockQuicConnectionDebugVisitor debug_visitor;
connection_.set_debug_visitor(&debug_visitor);
@@ -8210,6 +7926,10 @@ TEST_P(QuicConnectionTest, SendProbingRetransmissions) {
}));
EXPECT_CALL(*send_algorithm_, ShouldSendProbingPacket())
.WillRepeatedly(Return(true));
+ EXPECT_CALL(visitor_, SendProbingData()).WillRepeatedly([this] {
+ return connection_.sent_packet_manager().MaybeRetransmitOldestPacket(
+ PROBING_RETRANSMISSION);
+ });
connection_.SendProbingRetransmissions();
@@ -8223,9 +7943,6 @@ TEST_P(QuicConnectionTest, SendProbingRetransmissions) {
// there are no outstanding packets.
TEST_P(QuicConnectionTest,
SendProbingRetransmissionsFailsWhenNothingToRetransmit) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
ASSERT_TRUE(connection_.sent_packet_manager().unacked_packets().empty());
MockQuicConnectionDebugVisitor debug_visitor;
@@ -8233,14 +7950,15 @@ TEST_P(QuicConnectionTest,
EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _)).Times(0);
EXPECT_CALL(*send_algorithm_, ShouldSendProbingPacket())
.WillRepeatedly(Return(true));
+ EXPECT_CALL(visitor_, SendProbingData()).WillRepeatedly([this] {
+ return connection_.sent_packet_manager().MaybeRetransmitOldestPacket(
+ PROBING_RETRANSMISSION);
+ });
connection_.SendProbingRetransmissions();
}
TEST_P(QuicConnectionTest, PingAfterLastRetransmittablePacketAcked) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
const QuicTime::Delta retransmittable_on_wire_timeout =
QuicTime::Delta::FromMilliseconds(50);
connection_.set_retransmittable_on_wire_timeout(
@@ -8324,18 +8042,16 @@ TEST_P(QuicConnectionTest, PingAfterLastRetransmittablePacketAcked) {
connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
}));
connection_.GetPingAlarm()->Fire();
+ size_t padding_frame_count = writer_->padding_frames().size();
if (GetParam().no_stop_waiting) {
- EXPECT_EQ(2u, writer_->frame_count());
+ EXPECT_EQ(padding_frame_count + 2u, writer_->frame_count());
} else {
- EXPECT_EQ(3u, writer_->frame_count());
+ EXPECT_EQ(padding_frame_count + 3u, writer_->frame_count());
}
ASSERT_EQ(1u, writer_->ping_frames().size());
}
TEST_P(QuicConnectionTest, NoPingIfRetransmittablePacketSent) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
const QuicTime::Delta retransmittable_on_wire_timeout =
QuicTime::Delta::FromMilliseconds(50);
connection_.set_retransmittable_on_wire_timeout(
@@ -8399,18 +8115,21 @@ TEST_P(QuicConnectionTest, NoPingIfRetransmittablePacketSent) {
connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
}));
connection_.GetPingAlarm()->Fire();
+ size_t padding_frame_count = writer_->padding_frames().size();
if (GetParam().no_stop_waiting) {
- EXPECT_EQ(2u, writer_->frame_count());
+ 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());
+ }
} else {
- EXPECT_EQ(3u, writer_->frame_count());
+ EXPECT_EQ(padding_frame_count + 3u, writer_->frame_count());
}
ASSERT_EQ(1u, writer_->ping_frames().size());
}
TEST_P(QuicConnectionTest, OnForwardProgressConfirmed) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnForwardProgressConfirmed()).Times(Exactly(0));
EXPECT_TRUE(connection_.connected());
@@ -8450,9 +8169,6 @@ TEST_P(QuicConnectionTest, OnForwardProgressConfirmed) {
}
TEST_P(QuicConnectionTest, ValidStatelessResetToken) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
const QuicUint128 kTestToken = 1010101;
const QuicUint128 kWrongTestToken = 1010100;
QuicConfig config;
@@ -8471,9 +8187,6 @@ TEST_P(QuicConnectionTest, ValidStatelessResetToken) {
}
TEST_P(QuicConnectionTest, WriteBlockedWithInvalidAck) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_ACK_DATA, _, _));
@@ -8551,6 +8264,7 @@ TEST_P(QuicConnectionTest, PathChallengeResponse) {
connection_.peer_address());
// Save the random contents of the challenge for later comparison to the
// response.
+ ASSERT_GE(writer_->path_challenge_frames().size(), 1u);
QuicPathFrameBuffer challenge_data =
writer_->path_challenge_frames().front().data_buffer;
@@ -8578,9 +8292,6 @@ TEST_P(QuicConnectionTest, PathChallengeResponse) {
// Regression test for b/110259444
TEST_P(QuicConnectionTest, DoNotScheduleSpuriousAckAlarm) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
SetQuicReloadableFlag(quic_fix_spurious_ack_alarm, true);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(visitor_, OnWriteBlocked()).Times(AtLeast(1));
@@ -8602,9 +8313,6 @@ TEST_P(QuicConnectionTest, DoNotScheduleSpuriousAckAlarm) {
}
TEST_P(QuicConnectionTest, DisablePacingOffloadConnectionOptions) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
EXPECT_FALSE(QuicConnectionPeer::SupportsReleaseTime(&connection_));
writer_->set_supports_release_time(true);
QuicConfig config;
@@ -8624,9 +8332,6 @@ TEST_P(QuicConnectionTest, DisablePacingOffloadConnectionOptions) {
// Regression test for b/110259444
// Get a path response without having issued a path challenge...
TEST_P(QuicConnectionTest, OrphanPathResponse) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
QuicPathFrameBuffer data = {{0, 1, 2, 3, 4, 5, 6, 7}};
QuicPathResponseFrame frame(99, data);
@@ -8642,9 +8347,6 @@ TEST_P(QuicConnectionTest, OrphanPathResponse) {
// Regression test for b/120791670
TEST_P(QuicConnectionTest, StopProcessingGQuicPacketInIetfQuicConnection) {
- if (connection_.SupportsMultiplePacketNumberSpaces()) {
- return;
- }
// This test mimics a problematic scenario where an IETF QUIC connection
// receives a Google QUIC packet and continue processing it using Google QUIC
// wire format.
@@ -8652,13 +8354,18 @@ TEST_P(QuicConnectionTest, StopProcessingGQuicPacketInIetfQuicConnection) {
return;
}
set_perspective(Perspective::IS_SERVER);
- QuicStreamFrame stream_frame(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), false, 0u,
- QuicStringPiece());
+ QuicFrame frame;
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ frame = QuicFrame(&crypto_frame_);
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(1);
+ } else {
+ frame = QuicFrame(QuicStreamFrame(
+ QuicUtils::GetCryptoStreamId(connection_.transport_version()), false,
+ 0u, QuicStringPiece()));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+ }
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessFramePacketWithAddresses(QuicFrame(stream_frame), kSelfAddress,
- kPeerAddress);
+ ProcessFramePacketWithAddresses(frame, kSelfAddress, kPeerAddress);
// Let connection process a Google QUIC packet.
peer_framer_.set_version_for_tests(
@@ -8777,10 +8484,13 @@ TEST_P(QuicConnectionTest, MultiplePacketNumberSpacesBasicReceiving) {
return;
}
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(AnyNumber());
+ }
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
use_tagging_decrypter();
// Receives packet 1000 in initial data.
- ProcessDataPacketAtLevel(1000, false, ENCRYPTION_INITIAL);
+ ProcessCryptoPacketAtLevel(1000, ENCRYPTION_INITIAL);
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
peer_framer_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(0x02));
@@ -8816,7 +8526,7 @@ TEST_P(QuicConnectionTest, MultiplePacketNumberSpacesBasicReceiving) {
QuicMakeUnique<StrictTaggingDecrypter>(0x02));
// Verify zero rtt and forward secure packets get acked in the same packet.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- ProcessDataPacketAtLevel(1003, false, ENCRYPTION_FORWARD_SECURE);
+ ProcessDataPacket(1003);
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
}
@@ -8825,10 +8535,13 @@ TEST_P(QuicConnectionTest, CancelAckAlarmOnWriteBlocked) {
return;
}
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(AnyNumber());
+ }
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
use_tagging_decrypter();
// Receives packet 1000 in initial data.
- ProcessDataPacketAtLevel(1000, false, ENCRYPTION_INITIAL);
+ ProcessCryptoPacketAtLevel(1000, ENCRYPTION_INITIAL);
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
peer_framer_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(0x02));
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 4181cb7449b..caac2c76295 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
@@ -21,8 +21,9 @@ namespace quic {
const uint64_t kNumSecondsPerMinute = 60;
const uint64_t kNumSecondsPerHour = kNumSecondsPerMinute * 60;
const uint64_t kNumSecondsPerWeek = kNumSecondsPerHour * 24 * 7;
+const uint64_t kNumMillisPerSecond = 1000;
const uint64_t kNumMicrosPerMilli = 1000;
-const uint64_t kNumMicrosPerSecond = 1000 * 1000;
+const uint64_t kNumMicrosPerSecond = kNumMicrosPerMilli * kNumMillisPerSecond;
// Default number of connections for N-connection emulation.
const uint32_t kDefaultNumConnections = 2;
@@ -57,8 +58,17 @@ const QuicByteCount kMinPacketSizeForVersionNegotiation = 1200;
// We match SPDY's use of 32 (since we'd compete with SPDY).
const QuicPacketCount kInitialCongestionWindow = 32;
+// Do not allow initial congestion window to be greater than 200 packets.
+const QuicPacketCount kMaxInitialCongestionWindow = 200;
+
+// Do not allow initial congestion window to be smaller than 10 packets.
+const QuicPacketCount kMinInitialCongestionWindow = 10;
+
// Minimum size of initial flow control window, for both stream and session.
+// This is only enforced when version.AllowsLowFlowControlLimits() is false.
const uint32_t kMinimumFlowControlSendWindow = 16 * 1024; // 16 KB
+// Default size of initial flow control window, for both stream and session.
+const uint32_t kDefaultFlowControlSendWindow = 16 * 1024; // 16 KB
// Maximum flow control receive window limits for connection and stream.
const QuicByteCount kStreamReceiveWindowLimit = 16 * 1024 * 1024; // 16 MB
@@ -211,6 +221,9 @@ const uint64_t kMaxIetfVarInt = UINT64_C(0x3fffffffffffffff);
// TODO(fkastenholz): Should update this to 64 bits for IETF Quic.
const QuicStreamId kMaxQuicStreamId = 0xffffffff;
+// The maximum value that can be stored in a 32-bit QuicStreamCount.
+const QuicStreamCount kMaxQuicStreamCount = 0xffffffff;
+
// Number of bytes reserved for packet header type.
const size_t kPacketHeaderTypeSize = 1;
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 ed178f44594..511ef2be82b 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
@@ -68,18 +68,20 @@ void QuicControlFrameManager::WriteOrBufferBlocked(QuicStreamId id) {
QuicFrame(new QuicBlockedFrame(++last_control_frame_id_, id)));
}
-void QuicControlFrameManager::WriteOrBufferStreamIdBlocked(QuicStreamId id) {
- QUIC_DVLOG(1) << "Writing STREAM_ID_BLOCKED Frame";
- QUIC_CODE_COUNT(stream_id_blocked_transmits);
- WriteOrBufferQuicFrame(
- QuicFrame(QuicStreamIdBlockedFrame(++last_control_frame_id_, id)));
+void QuicControlFrameManager::WriteOrBufferStreamsBlocked(QuicStreamCount count,
+ bool unidirectional) {
+ QUIC_DVLOG(1) << "Writing STREAMS_BLOCKED Frame";
+ QUIC_CODE_COUNT(quic_streams_blocked_transmits);
+ WriteOrBufferQuicFrame(QuicFrame(QuicStreamsBlockedFrame(
+ ++last_control_frame_id_, count, unidirectional)));
}
-void QuicControlFrameManager::WriteOrBufferMaxStreamId(QuicStreamId id) {
- QUIC_DVLOG(1) << "Writing MAX_STREAM_ID Frame";
- QUIC_CODE_COUNT(max_stream_id_transmits);
- WriteOrBufferQuicFrame(
- QuicFrame(QuicMaxStreamIdFrame(++last_control_frame_id_, id)));
+void QuicControlFrameManager::WriteOrBufferMaxStreams(QuicStreamCount count,
+ bool unidirectional) {
+ QUIC_DVLOG(1) << "Writing MAX_STREAMS Frame";
+ QUIC_CODE_COUNT(quic_max_streams_transmits);
+ WriteOrBufferQuicFrame(QuicFrame(
+ QuicMaxStreamsFrame(++last_control_frame_id_, count, unidirectional)));
}
void QuicControlFrameManager::WriteOrBufferStopSending(uint16_t code,
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 a5213c42b41..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
@@ -54,13 +54,13 @@ class QUIC_EXPORT_PRIVATE QuicControlFrameManager {
// immediately.
void WriteOrBufferBlocked(QuicStreamId id);
- // Tries to send a STREAM_ID_BLOCKED Frame. Buffers the frame if it cannot be
+ // Tries to send a STREAMS_BLOCKED Frame. Buffers the frame if it cannot be
// sent immediately.
- void WriteOrBufferStreamIdBlocked(QuicStreamId id);
+ void WriteOrBufferStreamsBlocked(QuicStreamCount count, bool unidirectional);
- // Tries to send a MAX_STREAM_ID Frame. Buffers the frame if it cannot be sent
+ // Tries to send a MAX_STREAMS Frame. Buffers the frame if it cannot be sent
// immediately.
- void WriteOrBufferMaxStreamId(QuicStreamId id);
+ void WriteOrBufferMaxStreams(QuicStreamCount count, bool unidirectional);
// Tries to send an IETF-QUIC STOP_SENDING frame. The frame is buffered if it
// can not be sent immediately.
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 d6c9af4bf04..bf432ff4967 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
@@ -17,32 +17,6 @@
namespace quic {
-QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl::
- ChannelIDSourceCallbackImpl(QuicCryptoClientHandshaker* parent)
- : parent_(parent) {}
-
-QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl::
- ~ChannelIDSourceCallbackImpl() {}
-
-void QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl::Run(
- std::unique_ptr<ChannelIDKey>* channel_id_key) {
- if (parent_ == nullptr) {
- return;
- }
-
- parent_->channel_id_key_ = std::move(*channel_id_key);
- parent_->channel_id_source_callback_run_ = true;
- parent_->channel_id_source_callback_ = nullptr;
- parent_->DoHandshakeLoop(nullptr);
-
- // The ChannelIDSource owns this object and will delete it when this method
- // returns.
-}
-
-void QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl::Cancel() {
- parent_ = nullptr;
-}
-
QuicCryptoClientHandshaker::ProofVerifierCallbackImpl::
ProofVerifierCallbackImpl(QuicCryptoClientHandshaker* parent)
: parent_(parent) {}
@@ -87,14 +61,10 @@ QuicCryptoClientHandshaker::QuicCryptoClientHandshaker(
crypto_config_(crypto_config),
server_id_(server_id),
generation_counter_(0),
- channel_id_sent_(false),
- channel_id_source_callback_run_(false),
- channel_id_source_callback_(nullptr),
verify_context_(std::move(verify_context)),
proof_verify_callback_(nullptr),
proof_handler_(proof_handler),
verify_ok_(false),
- stateless_reject_received_(false),
proof_verify_start_time_(QuicTime::Zero()),
num_scup_messages_received_(0),
encryption_established_(false),
@@ -102,9 +72,6 @@ QuicCryptoClientHandshaker::QuicCryptoClientHandshaker(
crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {}
QuicCryptoClientHandshaker::~QuicCryptoClientHandshaker() {
- if (channel_id_source_callback_) {
- channel_id_source_callback_->Cancel();
- }
if (proof_verify_callback_) {
proof_verify_callback_->Cancel();
}
@@ -153,14 +120,6 @@ int QuicCryptoClientHandshaker::num_scup_messages_received() const {
return num_scup_messages_received_;
}
-bool QuicCryptoClientHandshaker::WasChannelIDSent() const {
- return channel_id_sent_;
-}
-
-bool QuicCryptoClientHandshaker::WasChannelIDSourceCallbackRun() const {
- return channel_id_source_callback_run_;
-}
-
std::string QuicCryptoClientHandshaker::chlo_hash() const {
return chlo_hash_;
}
@@ -234,12 +193,6 @@ void QuicCryptoClientHandshaker::DoHandshakeLoop(
case STATE_VERIFY_PROOF_COMPLETE:
DoVerifyProofComplete(cached);
break;
- case STATE_GET_CHANNEL_ID:
- rv = DoGetChannelID(cached);
- break;
- case STATE_GET_CHANNEL_ID_COMPLETE:
- DoGetChannelIDComplete();
- break;
case STATE_RECV_SHLO:
DoReceiveSHLO(in, cached);
break;
@@ -272,26 +225,12 @@ void QuicCryptoClientHandshaker::DoInitialize(
// If the cached state needs to be verified, do it now.
next_state_ = STATE_VERIFY_PROOF;
} else {
- next_state_ = STATE_GET_CHANNEL_ID;
+ next_state_ = STATE_SEND_CHLO;
}
}
void QuicCryptoClientHandshaker::DoSendCHLO(
QuicCryptoClientConfig::CachedState* cached) {
- if (stateless_reject_received_) {
- // If we've gotten to this point, we've sent at least one hello
- // and received a stateless reject in response. We cannot
- // continue to send hellos because the server has abandoned state
- // for this connection. Abandon further handshakes.
- next_state_ = STATE_NONE;
- if (session()->connection()->connected()) {
- session()->connection()->CloseConnection(
- QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, "stateless reject received",
- ConnectionCloseBehavior::SILENT_CLOSE);
- }
- return;
- }
-
// Send the client hello in plaintext.
session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
encryption_established_ = false;
@@ -309,7 +248,7 @@ void QuicCryptoClientHandshaker::DoSendCHLO(
DCHECK(session()->config() != nullptr);
// Send all the options, regardless of whether we're sending an
// inchoate or subsequent hello.
- session()->config()->ToHandshakeMessage(&out);
+ session()->config()->ToHandshakeMessage(&out, session()->transport_version());
if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
crypto_config_->FillInchoateClientHello(
@@ -341,22 +280,13 @@ void QuicCryptoClientHandshaker::DoSendCHLO(
return;
}
- // If the server nonce is empty, copy over the server nonce from a previous
- // SREJ, if there is one.
- if (GetQuicReloadableFlag(enable_quic_stateless_reject_support) &&
- crypto_negotiated_params_->server_nonce.empty() &&
- cached->has_server_nonce()) {
- crypto_negotiated_params_->server_nonce = cached->GetNextServerNonce();
- DCHECK(!crypto_negotiated_params_->server_nonce.empty());
- }
-
std::string error_details;
QuicErrorCode error = crypto_config_->FillClientHello(
server_id_, session()->connection()->connection_id(),
session()->supported_versions().front(), cached,
session()->connection()->clock()->WallNow(),
- session()->connection()->random_generator(), channel_id_key_.get(),
- crypto_negotiated_params_, &out, &error_details);
+ session()->connection()->random_generator(), crypto_negotiated_params_,
+ &out, &error_details);
if (error != QUIC_NO_ERROR) {
// Flush the cached config so that, if it's bad, the server has a
// chance to send us another in the future.
@@ -365,7 +295,6 @@ void QuicCryptoClientHandshaker::DoSendCHLO(
return;
}
chlo_hash_ = CryptoUtils::HashHandshakeMessage(out, Perspective::IS_CLIENT);
- channel_id_sent_ = (channel_id_key_ != nullptr);
if (cached->proof_verify_details()) {
proof_handler_->OnProofVerifyDetailsAvailable(
*cached->proof_verify_details());
@@ -405,7 +334,7 @@ void QuicCryptoClientHandshaker::DoReceiveREJ(
// perform a handshake, or we sent a full hello that the server
// rejected. Here we hope to have a REJ that contains the information
// that we need.
- if ((in->tag() != kREJ) && (in->tag() != kSREJ)) {
+ if (in->tag() != kREJ) {
next_state_ = STATE_NONE;
stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
"Expected REJ");
@@ -425,7 +354,7 @@ void QuicCryptoClientHandshaker::DoReceiveREJ(
static_cast<HandshakeFailureReason>(reject_reasons[i]);
packed_error |= 1 << (reason - 1);
}
- DVLOG(1) << "Reasons for rejection: " << packed_error;
+ QUIC_DVLOG(1) << "Reasons for rejection: " << packed_error;
if (num_client_hellos_ == QuicCryptoClientStream::kMaxClientHellos) {
QuicClientSparseHistogram("QuicClientHelloRejectReasons.TooMany",
packed_error);
@@ -438,7 +367,6 @@ void QuicCryptoClientHandshaker::DoReceiveREJ(
// so we can cancel and retransmissions.
session()->NeuterUnencryptedData();
- stateless_reject_received_ = in->tag() == kSREJ;
std::string error_details;
QuicErrorCode error = crypto_config_->ProcessRejection(
*in, session()->connection()->clock()->WallNow(),
@@ -461,7 +389,7 @@ void QuicCryptoClientHandshaker::DoReceiveREJ(
return;
}
}
- next_state_ = STATE_GET_CHANNEL_ID;
+ next_state_ = STATE_SEND_CHLO;
}
QuicAsyncStatus QuicCryptoClientHandshaker::DoVerifyProof(
@@ -531,7 +459,7 @@ void QuicCryptoClientHandshaker::DoVerifyProofComplete(
SetCachedProofValid(cached);
cached->SetProofVerifyDetails(verify_details_.release());
if (!handshake_confirmed()) {
- next_state_ = STATE_GET_CHANNEL_ID;
+ next_state_ = STATE_SEND_CHLO;
} else {
// TODO: Enable Expect-Staple. https://crbug.com/631101
next_state_ = STATE_NONE;
@@ -539,48 +467,6 @@ void QuicCryptoClientHandshaker::DoVerifyProofComplete(
}
}
-QuicAsyncStatus QuicCryptoClientHandshaker::DoGetChannelID(
- QuicCryptoClientConfig::CachedState* cached) {
- next_state_ = STATE_GET_CHANNEL_ID_COMPLETE;
- channel_id_key_.reset();
- if (!RequiresChannelID(cached)) {
- next_state_ = STATE_SEND_CHLO;
- return QUIC_SUCCESS;
- }
-
- ChannelIDSourceCallbackImpl* channel_id_source_callback =
- new ChannelIDSourceCallbackImpl(this);
- QuicAsyncStatus status = crypto_config_->channel_id_source()->GetChannelIDKey(
- server_id_.host(), &channel_id_key_, channel_id_source_callback);
-
- switch (status) {
- case QUIC_PENDING:
- channel_id_source_callback_ = channel_id_source_callback;
- QUIC_DVLOG(1) << "Looking up channel ID";
- break;
- case QUIC_FAILURE:
- next_state_ = STATE_NONE;
- delete channel_id_source_callback;
- stream_->CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
- "Channel ID lookup failed");
- break;
- case QUIC_SUCCESS:
- delete channel_id_source_callback;
- break;
- }
- return status;
-}
-
-void QuicCryptoClientHandshaker::DoGetChannelIDComplete() {
- if (!channel_id_key_.get()) {
- next_state_ = STATE_NONE;
- stream_->CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
- "Channel ID lookup failed");
- return;
- }
- next_state_ = STATE_SEND_CHLO;
-}
-
void QuicCryptoClientHandshaker::DoReceiveSHLO(
const CryptoHandshakeMessage* in,
QuicCryptoClientConfig::CachedState* cached) {
@@ -589,7 +475,7 @@ void QuicCryptoClientHandshaker::DoReceiveSHLO(
// hoping for a SHLO from the server to confirm that. First check
// to see whether the response was a reject, and if so, move on to
// the reject-processing state.
- if ((in->tag() == kREJ) || (in->tag() == kSREJ)) {
+ if (in->tag() == kREJ) {
// A reject message must be sent in ENCRYPTION_INITIAL.
if (session()->connection()->last_decrypted_level() != ENCRYPTION_INITIAL) {
// The rejection was sent encrypted!
@@ -677,26 +563,4 @@ void QuicCryptoClientHandshaker::SetCachedProofValid(
proof_handler_->OnProofValid(*cached);
}
-bool QuicCryptoClientHandshaker::RequiresChannelID(
- QuicCryptoClientConfig::CachedState* cached) {
- if (server_id_.privacy_mode_enabled() ||
- !crypto_config_->channel_id_source()) {
- return false;
- }
- const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
- if (!scfg) { // scfg may be null then we send an inchoate CHLO.
- return false;
- }
- QuicTagVector their_proof_demands;
- if (scfg->GetTaglist(kPDMD, &their_proof_demands) != QUIC_NO_ERROR) {
- return false;
- }
- for (const QuicTag tag : their_proof_demands) {
- if (tag == kCHID) {
- return true;
- }
- }
- return false;
-}
-
} // namespace quic
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 4aa5d469dcb..5b7ce35e29b 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
@@ -7,7 +7,6 @@
#include <string>
-#include "net/third_party/quiche/src/quic/core/crypto/channel_id.h"
#include "net/third_party/quiche/src/quic/core/crypto/proof_verifier.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h"
@@ -39,8 +38,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientHandshaker
bool CryptoConnect() override;
int num_sent_client_hellos() const override;
int num_scup_messages_received() const override;
- bool WasChannelIDSent() const override;
- bool WasChannelIDSourceCallbackRun() const override;
std::string chlo_hash() const override;
bool encryption_established() const override;
bool handshake_confirmed() const override;
@@ -59,25 +56,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientHandshaker
void DoSendCHLO(QuicCryptoClientConfig::CachedState* cached);
private:
- // ChannelIDSourceCallbackImpl is passed as the callback method to
- // GetChannelIDKey. The ChannelIDSource calls this class with the result of
- // channel ID lookup when lookup is performed asynchronously.
- class ChannelIDSourceCallbackImpl : public ChannelIDSourceCallback {
- public:
- explicit ChannelIDSourceCallbackImpl(QuicCryptoClientHandshaker* parent);
- ~ChannelIDSourceCallbackImpl() override;
-
- // ChannelIDSourceCallback interface.
- void Run(std::unique_ptr<ChannelIDKey>* channel_id_key) override;
-
- // Cancel causes any future callbacks to be ignored. It must be called on
- // the same thread as the callback will be made on.
- void Cancel();
-
- private:
- QuicCryptoClientHandshaker* parent_;
- };
-
// 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.
@@ -106,8 +84,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientHandshaker
STATE_RECV_REJ,
STATE_VERIFY_PROOF,
STATE_VERIFY_PROOF_COMPLETE,
- STATE_GET_CHANNEL_ID,
- STATE_GET_CHANNEL_ID_COMPLETE,
STATE_RECV_SHLO,
STATE_INITIALIZE_SCUP,
STATE_NONE,
@@ -137,15 +113,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientHandshaker
// server config). If not, it closes the connection.
void DoVerifyProofComplete(QuicCryptoClientConfig::CachedState* cached);
- // Start the look up of Channel ID process. Returns either QUIC_SUCCESS if
- // RequiresChannelID returns false or QuicAsyncStatus returned by
- // GetChannelIDKey.
- QuicAsyncStatus DoGetChannelID(QuicCryptoClientConfig::CachedState* cached);
-
- // If there is no channel ID, then close the connection otherwise transtion to
- // STATE_SEND_CHLO state.
- void DoGetChannelIDComplete();
-
// Process SHLO message from the server.
void DoReceiveSHLO(const CryptoHandshakeMessage* in,
QuicCryptoClientConfig::CachedState* cached);
@@ -159,10 +126,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientHandshaker
// OnProofValid() method.
void SetCachedProofValid(QuicCryptoClientConfig::CachedState* cached);
- // Returns true if the server crypto config in |cached| requires a ChannelID
- // and the client config settings also allow sending a ChannelID.
- bool RequiresChannelID(QuicCryptoClientConfig::CachedState* cached);
-
QuicCryptoClientStream* stream_;
QuicSession* session_;
@@ -183,22 +146,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientHandshaker
// Generation counter from QuicCryptoClientConfig's CachedState.
uint64_t generation_counter_;
- // True if a channel ID was sent.
- bool channel_id_sent_;
-
- // True if channel_id_source_callback_ was run.
- bool channel_id_source_callback_run_;
-
- // channel_id_source_callback_ contains the callback object that we passed
- // to an asynchronous channel ID lookup. The ChannelIDSource owns this
- // object.
- ChannelIDSourceCallbackImpl* channel_id_source_callback_;
-
- // These members are used to store the result of an asynchronous channel ID
- // lookup. These members must not be used after
- // STATE_GET_CHANNEL_ID_COMPLETE.
- std::unique_ptr<ChannelIDKey> channel_id_key_;
-
// verify_context_ contains the context object that we pass to asynchronous
// proof verifications.
std::unique_ptr<ProofVerifyContext> verify_context_;
@@ -217,11 +164,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientHandshaker
std::string verify_error_details_;
std::unique_ptr<ProofVerifyDetails> verify_details_;
- // True if the server responded to a previous CHLO with a stateless
- // reject. Used for book-keeping between the STATE_RECV_REJ,
- // STATE_VERIFY_PROOF*, and subsequent STATE_SEND_CHLO state.
- bool stateless_reject_received_;
-
QuicTime proof_verify_start_time_;
int num_scup_messages_received_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker_test.cc
index 992df8f0378..92cfab1f3e0 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker_test.cc
@@ -3,11 +3,11 @@
// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
+
#include "net/third_party/quiche/src/quic/core/proto/crypto_server_config.pb.h"
#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
namespace quic {
@@ -49,6 +49,8 @@ class InsecureProofVerifier : public ProofVerifier {
QuicAsyncStatus VerifyCertChain(
const std::string& hostname,
const std::vector<std::string>& certs,
+ const std::string& ocsp_response,
+ const std::string& cert_sct,
const ProofVerifyContext* context,
std::string* error_details,
std::unique_ptr<ProofVerifyDetails>* details,
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 7c2aa404989..93f2a61104a 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
@@ -84,14 +84,6 @@ CryptoMessageParser* QuicCryptoClientStream::crypto_message_parser() {
return handshaker_->crypto_message_parser();
}
-bool QuicCryptoClientStream::WasChannelIDSent() const {
- return handshaker_->WasChannelIDSent();
-}
-
-bool QuicCryptoClientStream::WasChannelIDSourceCallbackRun() const {
- return handshaker_->WasChannelIDSourceCallbackRun();
-}
-
std::string QuicCryptoClientStream::chlo_hash() const {
return handshaker_->chlo_hash();
}
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 d0e4ee1e3b1..b8dff7e9d34 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
@@ -9,7 +9,6 @@
#include <memory>
#include <string>
-#include "net/third_party/quiche/src/quic/core/crypto/channel_id.h"
#include "net/third_party/quiche/src/quic/core/crypto/proof_verifier.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"
@@ -85,13 +84,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
// to handshake confirmation.
virtual int num_scup_messages_received() const = 0;
- // Returns true if a channel ID was sent on this connection.
- virtual bool WasChannelIDSent() const = 0;
-
- // Returns true if our ChannelIDSourceCallback was run, which implies the
- // ChannelIDSource operated asynchronously. Intended for testing.
- virtual bool WasChannelIDSourceCallbackRun() const = 0;
-
virtual std::string chlo_hash() const = 0;
// Returns true once any encrypter (initial/0RTT or final/1RTT) has been set
@@ -151,13 +143,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
const override;
CryptoMessageParser* crypto_message_parser() override;
- // Returns true if a channel ID was sent on this connection.
- bool WasChannelIDSent() const;
-
- // Returns true if our ChannelIDSourceCallback was run, which implies the
- // ChannelIDSource operated asynchronously. Intended for testing.
- bool WasChannelIDSourceCallbackRun() const;
-
std::string chlo_hash() const;
protected:
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 5839477b8fc..e09546d93ca 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
@@ -64,9 +64,8 @@ class QuicCryptoClientStreamTest : public QuicTest {
.Times(testing::AnyNumber());
stream()->CryptoConnect();
QuicConfig config;
- crypto_test_utils::HandshakeWithFakeServer(&config, &server_helper_,
- &alarm_factory_, connection_,
- stream(), server_options_);
+ crypto_test_utils::HandshakeWithFakeServer(
+ &config, &server_helper_, &alarm_factory_, connection_, stream());
}
QuicCryptoClientStream* stream() {
@@ -82,7 +81,6 @@ class QuicCryptoClientStreamTest : public QuicTest {
QuicServerId server_id_;
CryptoHandshakeMessage message_;
QuicCryptoClientConfig crypto_config_;
- crypto_test_utils::FakeServerOptions server_options_;
};
TEST_F(QuicCryptoClientStreamTest, NotInitiallyConected) {
@@ -97,7 +95,7 @@ TEST_F(QuicCryptoClientStreamTest, ConnectedAfterSHLO) {
}
TEST_F(QuicCryptoClientStreamTest, ConnectedAfterTlsHandshake) {
- FLAGS_quic_supports_tls_handshake = true;
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
supported_versions_.clear();
for (QuicTransportVersion transport_version :
AllSupportedTransportVersions()) {
@@ -262,9 +260,8 @@ TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdateWithCert) {
QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(),
crypto_test_utils::ProofSourceForTesting(), KeyExchangeSource::Default(),
TlsServerHandshaker::CreateSslCtx());
- crypto_test_utils::FakeServerOptions options;
crypto_test_utils::SetupCryptoServerConfigForTest(
- connection_->clock(), QuicRandom::GetInstance(), &crypto_config, options);
+ connection_->clock(), QuicRandom::GetInstance(), &crypto_config);
SourceAddressTokens tokens;
QuicCompressedCertsCache cache(1);
CachedNetworkParameters network_params;
@@ -321,14 +318,6 @@ TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdateBeforeHandshake) {
stream(), server_config_update, Perspective::IS_SERVER);
}
-TEST_F(QuicCryptoClientStreamTest, NoChannelID) {
- crypto_config_.SetChannelIDSource(nullptr);
-
- CompleteCryptoHandshake();
- EXPECT_FALSE(stream()->WasChannelIDSent());
- EXPECT_FALSE(stream()->WasChannelIDSourceCallbackRun());
-}
-
TEST_F(QuicCryptoClientStreamTest, PreferredVersion) {
// This mimics the case where client receives version negotiation packet, such
// that, the preferred version is different from the packets' version.
@@ -360,115 +349,6 @@ TEST_F(QuicCryptoClientStreamTest, PreferredVersion) {
client_version_label);
}
-class QuicCryptoClientStreamStatelessTest : public QuicTest {
- public:
- QuicCryptoClientStreamStatelessTest()
- : client_crypto_config_(crypto_test_utils::ProofVerifierForTesting(),
- TlsClientHandshaker::CreateSslCtx()),
- server_crypto_config_(QuicCryptoServerConfig::TESTING,
- QuicRandom::GetInstance(),
- crypto_test_utils::ProofSourceForTesting(),
- KeyExchangeSource::Default(),
- TlsServerHandshaker::CreateSslCtx()),
- server_compressed_certs_cache_(
- QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
- server_id_(kServerHostname, kServerPort, false) {
- TestQuicSpdyClientSession* client_session = nullptr;
- CreateClientSessionForTest(server_id_,
- /* supports_stateless_rejects= */ true,
- QuicTime::Delta::FromSeconds(100000),
- AllSupportedVersions(), &helper_,
- &alarm_factory_, &client_crypto_config_,
- &client_connection_, &client_session);
- CHECK(client_session);
- client_session_.reset(client_session);
- }
-
- QuicCryptoServerStream* server_stream() {
- return server_session_->GetMutableCryptoStream();
- }
-
- void AdvanceHandshakeWithFakeServer() {
- client_session_->GetMutableCryptoStream()->CryptoConnect();
- EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
- .Times(testing::AnyNumber());
- EXPECT_CALL(*server_session_->helper(), GenerateConnectionIdForReject(_, _))
- .Times(testing::AnyNumber());
- crypto_test_utils::AdvanceHandshake(
- client_connection_, client_session_->GetMutableCryptoStream(), 0,
- server_connection_, server_stream(), 0);
- }
-
- // Initializes the server_stream_ for stateless rejects.
- void InitializeFakeStatelessRejectServer() {
- TestQuicSpdyServerSession* server_session = nullptr;
- CreateServerSessionForTest(
- server_id_, QuicTime::Delta::FromSeconds(100000),
- ParsedVersionOfIndex(AllSupportedVersions(), 0), &helper_,
- &alarm_factory_, &server_crypto_config_,
- &server_compressed_certs_cache_, &server_connection_, &server_session);
- CHECK(server_session);
- server_session_.reset(server_session);
- server_session_->OnSuccessfulVersionNegotiation(AllSupportedVersions()[0]);
- crypto_test_utils::FakeServerOptions options;
- crypto_test_utils::SetupCryptoServerConfigForTest(
- server_connection_->clock(), server_connection_->random_generator(),
- &server_crypto_config_, options);
- SetQuicReloadableFlag(enable_quic_stateless_reject_support, true);
- }
-
- MockQuicConnectionHelper helper_;
- MockAlarmFactory alarm_factory_;
-
- // Client crypto stream state
- PacketSavingConnection* client_connection_;
- std::unique_ptr<TestQuicSpdyClientSession> client_session_;
- QuicCryptoClientConfig client_crypto_config_;
-
- // Server crypto stream state
- PacketSavingConnection* server_connection_;
- std::unique_ptr<TestQuicSpdyServerSession> server_session_;
- QuicCryptoServerConfig server_crypto_config_;
- QuicCompressedCertsCache server_compressed_certs_cache_;
- QuicServerId server_id_;
-};
-
-TEST_F(QuicCryptoClientStreamStatelessTest, StatelessReject) {
- SetQuicReloadableFlag(enable_quic_stateless_reject_support, true);
-
- QuicCryptoClientConfig::CachedState* client_state =
- client_crypto_config_.LookupOrCreate(server_id_);
-
- EXPECT_FALSE(client_state->has_server_designated_connection_id());
- EXPECT_CALL(*client_session_, OnProofValid(testing::_));
-
- InitializeFakeStatelessRejectServer();
- EXPECT_CALL(*client_connection_,
- CloseConnection(QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, _, _));
- EXPECT_CALL(*server_connection_,
- CloseConnection(QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, _, _));
- AdvanceHandshakeWithFakeServer();
-
- EXPECT_EQ(1, server_stream()->NumHandshakeMessages());
- EXPECT_EQ(0, server_stream()->NumHandshakeMessagesWithServerNonces());
-
- EXPECT_FALSE(client_session_->IsEncryptionEstablished());
- EXPECT_FALSE(client_session_->IsCryptoHandshakeConfirmed());
- // Even though the handshake was not complete, the cached client_state is
- // complete, and can be used for a subsequent successful handshake.
- EXPECT_TRUE(client_state->IsComplete(QuicWallTime::FromUNIXSeconds(0)));
-
- ASSERT_TRUE(client_state->has_server_nonce());
- ASSERT_FALSE(client_state->GetNextServerNonce().empty());
- ASSERT_TRUE(client_state->has_server_designated_connection_id());
- QuicConnectionId server_designated_id =
- client_state->GetNextServerDesignatedConnectionId();
- QuicConnectionId expected_id = QuicUtils::CreateRandomConnectionId(
- server_session_->connection()->random_generator());
- EXPECT_EQ(expected_id, server_designated_id);
- EXPECT_FALSE(client_state->has_server_designated_connection_id());
-}
-
} // namespace
} // namespace test
} // namespace quic
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 c0e61efb21f..f345a147208 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
@@ -138,18 +138,11 @@ void QuicCryptoServerHandshaker::FinishProcessingHandshakeMessage(
QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
result,
std::unique_ptr<ProofSource::Details> details) {
- const CryptoHandshakeMessage& message = result->client_hello;
-
// Clear the callback that got us here.
DCHECK(validate_client_hello_cb_ != nullptr);
DCHECK(process_client_hello_cb_ == nullptr);
validate_client_hello_cb_ = nullptr;
- if (stream_->UseStatelessRejectsIfPeerSupported()) {
- stream_->SetPeerSupportsStatelessRejects(
- QuicCryptoServerStreamBase::DoesPeerSupportStatelessRejects(message));
- }
-
std::unique_ptr<ProcessClientHelloCallback> cb(
new ProcessClientHelloCallback(this, result));
process_client_hello_cb_ = cb.get();
@@ -176,29 +169,9 @@ void QuicCryptoServerHandshaker::
}
if (reply->tag() != kSHLO) {
- if (reply->tag() == kSREJ) {
- DCHECK(stream_->UseStatelessRejectsIfPeerSupported());
- DCHECK(stream_->PeerSupportsStatelessRejects());
- // Before sending the SREJ, cause the connection to save crypto packets
- // so that they can be added to the time wait list manager and
- // retransmitted.
- session()->connection()->EnableSavingCryptoPackets();
- }
session()->connection()->set_fully_pad_crypto_hadshake_packets(
crypto_config_->pad_rej());
SendHandshakeMessage(*reply);
-
- if (reply->tag() == kSREJ) {
- DCHECK(stream_->UseStatelessRejectsIfPeerSupported());
- DCHECK(stream_->PeerSupportsStatelessRejects());
- DCHECK(!handshake_confirmed());
- QUIC_DLOG(INFO) << "Closing connection "
- << session()->connection()->connection_id()
- << " because of a stateless reject.";
- session()->connection()->CloseConnection(
- QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, "stateless reject",
- ConnectionCloseBehavior::SILENT_CLOSE);
- }
return;
}
@@ -217,7 +190,7 @@ void QuicCryptoServerHandshaker::
session()->OnConfigNegotiated();
- config->ToHandshakeMessage(reply.get());
+ config->ToHandshakeMessage(reply.get(), session()->transport_version());
// Receiving a full CHLO implies the client is prepared to decrypt with
// the new server write key. We can start to encrypt with the new server
@@ -431,16 +404,13 @@ void QuicCryptoServerHandshaker::ProcessClientHello(
}
previous_source_address_tokens_ = result->info.source_address_tokens;
- const bool use_stateless_rejects_in_crypto_config =
- stream_->UseStatelessRejectsIfPeerSupported() &&
- stream_->PeerSupportsStatelessRejects();
QuicConnection* connection = session()->connection();
const QuicConnectionId server_designated_connection_id =
- GenerateConnectionIdForReject(use_stateless_rejects_in_crypto_config);
+ GenerateConnectionIdForReject(/*use_stateless_rejects=*/false);
crypto_config_->ProcessClientHello(
result, /*reject_only=*/false, connection->connection_id(),
connection->self_address(), GetClientAddress(), connection->version(),
- session()->supported_versions(), use_stateless_rejects_in_crypto_config,
+ session()->supported_versions(), /*use_stateless_rejects=*/false,
server_designated_connection_id, connection->clock(),
connection->random_generator(), compressed_certs_cache_,
crypto_negotiated_params_, signed_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 010ac361ea9..a6486d88014 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
@@ -28,34 +28,12 @@ namespace quic {
QuicCryptoServerStreamBase::QuicCryptoServerStreamBase(QuicSession* session)
: QuicCryptoStream(session) {}
-// TODO(jokulik): Once stateless rejects support is inherent in the version
-// number, this function will likely go away entirely.
-// static
-bool QuicCryptoServerStreamBase::DoesPeerSupportStatelessRejects(
- const CryptoHandshakeMessage& message) {
- QuicTagVector received_tags;
- QuicErrorCode error = message.GetTaglist(kCOPT, &received_tags);
- if (error != QUIC_NO_ERROR) {
- return false;
- }
- for (const QuicTag tag : received_tags) {
- if (tag == kSREJ) {
- return true;
- }
- }
- return false;
-}
-
QuicCryptoServerStream::QuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
- bool use_stateless_rejects_if_peer_supported,
QuicSession* session,
Helper* helper)
: QuicCryptoServerStreamBase(session),
- use_stateless_rejects_if_peer_supported_(
- use_stateless_rejects_if_peer_supported),
- peer_supports_stateless_rejects_(false),
crypto_config_(crypto_config),
compressed_certs_cache_(compressed_certs_cache),
helper_(helper) {
@@ -97,23 +75,10 @@ QuicCryptoServerStream::PreviousCachedNetworkParams() const {
return handshaker()->PreviousCachedNetworkParams();
}
-bool QuicCryptoServerStream::UseStatelessRejectsIfPeerSupported() const {
- return use_stateless_rejects_if_peer_supported_;
-}
-
-bool QuicCryptoServerStream::PeerSupportsStatelessRejects() const {
- return peer_supports_stateless_rejects_;
-}
-
bool QuicCryptoServerStream::ZeroRttAttempted() const {
return handshaker()->ZeroRttAttempted();
}
-void QuicCryptoServerStream::SetPeerSupportsStatelessRejects(
- bool peer_supports_stateless_rejects) {
- peer_supports_stateless_rejects_ = peer_supports_stateless_rejects;
-}
-
void QuicCryptoServerStream::SetPreviousCachedNetworkParams(
CachedNetworkParameters cached_network_params) {
handshaker()->SetPreviousCachedNetworkParams(cached_network_params);
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 a00302779d9..71ce29700ff 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
@@ -51,19 +51,11 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStreamBase : public QuicCryptoStream {
// These are all accessors and setters to their respective counters.
virtual uint8_t NumHandshakeMessages() const = 0;
virtual uint8_t NumHandshakeMessagesWithServerNonces() const = 0;
- virtual bool UseStatelessRejectsIfPeerSupported() const = 0;
- virtual bool PeerSupportsStatelessRejects() const = 0;
virtual bool ZeroRttAttempted() const = 0;
- virtual void SetPeerSupportsStatelessRejects(bool set) = 0;
virtual const CachedNetworkParameters* PreviousCachedNetworkParams()
const = 0;
virtual void SetPreviousCachedNetworkParams(
CachedNetworkParameters cached_network_params) = 0;
-
- // Checks the options on the handshake-message to see whether the
- // peer supports stateless-rejects.
- static bool DoesPeerSupportStatelessRejects(
- const CryptoHandshakeMessage& message);
};
class QUIC_EXPORT_PRIVATE QuicCryptoServerStream
@@ -154,7 +146,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream
// |helper| must outlive the stream.
QuicCryptoServerStream(const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
- bool use_stateless_rejects_if_peer_supported,
QuicSession* session,
Helper* helper);
QuicCryptoServerStream(const QuicCryptoServerStream&) = delete;
@@ -171,11 +162,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream
uint8_t NumHandshakeMessagesWithServerNonces() const override;
int NumServerConfigUpdateMessagesSent() const override;
const CachedNetworkParameters* PreviousCachedNetworkParams() const override;
- bool UseStatelessRejectsIfPeerSupported() const override;
- bool PeerSupportsStatelessRejects() const override;
bool ZeroRttAttempted() const override;
- void SetPeerSupportsStatelessRejects(
- bool peer_supports_stateless_rejects) override;
void SetPreviousCachedNetworkParams(
CachedNetworkParameters cached_network_params) override;
@@ -201,17 +188,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerStream
private:
std::unique_ptr<HandshakerDelegate> handshaker_;
- // If true, the server should use stateless rejects, so long as the
- // client supports them, as indicated by
- // peer_supports_stateless_rejects_.
- bool use_stateless_rejects_if_peer_supported_;
-
- // Set to true, once the server has received information from the
- // client that it supports stateless reject.
- // TODO(jokulik): Remove once client stateless reject support
- // becomes the default.
- bool peer_supports_stateless_rejects_;
-
// Arguments from QuicCryptoServerStream constructor that might need to be
// passed to the HandshakerDelegate constructor in its late construction.
const QuicCryptoServerConfig* crypto_config_;
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 660c588377b..5105a27b53c 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
@@ -45,14 +45,6 @@ using testing::NiceMock;
namespace quic {
namespace test {
-class QuicCryptoServerStreamPeer {
- public:
- static bool DoesPeerSupportStatelessRejects(
- const CryptoHandshakeMessage& message) {
- return QuicCryptoServerStream::DoesPeerSupportStatelessRejects(message);
- }
-};
-
namespace {
const char kServerHostname[] = "test.example.com";
@@ -74,9 +66,7 @@ class QuicCryptoServerStreamTest : public QuicTestWithParam<bool> {
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
server_id_(kServerHostname, kServerPort, false),
client_crypto_config_(crypto_test_utils::ProofVerifierForTesting(),
- TlsClientHandshaker::CreateSslCtx()) {
- SetQuicReloadableFlag(enable_quic_stateless_reject_support, false);
- }
+ TlsClientHandshaker::CreateSslCtx()) {}
void Initialize() { InitializeServer(); }
@@ -106,11 +96,9 @@ class QuicCryptoServerStreamTest : public QuicTestWithParam<bool> {
.Times(testing::AnyNumber());
EXPECT_CALL(*server_session_->helper(), GenerateConnectionIdForReject(_, _))
.Times(testing::AnyNumber());
- crypto_test_utils::FakeServerOptions options;
- options.token_binding_params = QuicTagVector{kTB10};
crypto_test_utils::SetupCryptoServerConfigForTest(
server_connection_->clock(), server_connection_->random_generator(),
- &server_crypto_config_, options);
+ &server_crypto_config_);
server_session_->GetMutableCryptoStream()->OnSuccessfulVersionNegotiation(
supported_versions_.front());
}
@@ -125,13 +113,12 @@ class QuicCryptoServerStreamTest : public QuicTestWithParam<bool> {
// Initializes a fake client, and all its associated state, for
// testing. May be called multiple times.
- void InitializeFakeClient(bool supports_stateless_rejects) {
+ void InitializeFakeClient() {
TestQuicSpdyClientSession* client_session = nullptr;
helpers_.push_back(QuicMakeUnique<NiceMock<MockQuicConnectionHelper>>());
alarm_factories_.push_back(QuicMakeUnique<MockAlarmFactory>());
CreateClientSessionForTest(
- server_id_, supports_stateless_rejects,
- QuicTime::Delta::FromSeconds(100000), supported_versions_,
+ server_id_, QuicTime::Delta::FromSeconds(100000), supported_versions_,
helpers_.back().get(), alarm_factories_.back().get(),
&client_crypto_config_, &client_connection_, &client_session);
CHECK(client_session);
@@ -197,12 +184,6 @@ TEST_P(QuicCryptoServerStreamTest, NotInitiallyConected) {
EXPECT_FALSE(server_stream()->handshake_confirmed());
}
-TEST_P(QuicCryptoServerStreamTest, NotInitiallySendingStatelessRejects) {
- Initialize();
- EXPECT_FALSE(server_stream()->UseStatelessRejectsIfPeerSupported());
- EXPECT_FALSE(server_stream()->PeerSupportsStatelessRejects());
-}
-
TEST_P(QuicCryptoServerStreamTest, ConnectedAfterCHLO) {
// CompleteCryptoHandshake returns the number of client hellos sent. This
// test should send:
@@ -215,7 +196,7 @@ TEST_P(QuicCryptoServerStreamTest, ConnectedAfterCHLO) {
}
TEST_P(QuicCryptoServerStreamTest, ConnectedAfterTlsHandshake) {
- FLAGS_quic_supports_tls_handshake = true;
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
client_options_.only_tls_versions = true;
supported_versions_.clear();
for (QuicTransportVersion transport_version :
@@ -232,7 +213,7 @@ TEST_P(QuicCryptoServerStreamTest, ConnectedAfterTlsHandshake) {
TEST_P(QuicCryptoServerStreamTest, ForwardSecureAfterCHLO) {
Initialize();
- InitializeFakeClient(/* supports_stateless_rejects= */ false);
+ InitializeFakeClient();
// Do a first handshake in order to prime the client config with the server's
// information.
@@ -242,7 +223,7 @@ TEST_P(QuicCryptoServerStreamTest, ForwardSecureAfterCHLO) {
// Now do another handshake, with the blocking SHLO connection option.
InitializeServer();
- InitializeFakeClient(/* supports_stateless_rejects= */ false);
+ InitializeFakeClient();
AdvanceHandshakeWithFakeClient();
EXPECT_TRUE(server_stream()->encryption_established());
@@ -251,112 +232,9 @@ TEST_P(QuicCryptoServerStreamTest, ForwardSecureAfterCHLO) {
server_session_->connection()->encryption_level());
}
-TEST_P(QuicCryptoServerStreamTest, StatelessRejectAfterCHLO) {
- SetQuicReloadableFlag(enable_quic_stateless_reject_support, true);
- Initialize();
-
- InitializeFakeClient(/* supports_stateless_rejects= */ true);
- EXPECT_CALL(*server_connection_,
- CloseConnection(QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, _, _));
- EXPECT_CALL(*client_connection_,
- CloseConnection(QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, _, _));
- AdvanceHandshakeWithFakeClient();
-
- // Check the server to make the sure the handshake did not succeed.
- EXPECT_FALSE(server_stream()->encryption_established());
- EXPECT_FALSE(server_stream()->handshake_confirmed());
-
- // Check the client state to make sure that it received a server-designated
- // connection id.
- QuicCryptoClientConfig::CachedState* client_state =
- client_crypto_config_.LookupOrCreate(server_id_);
-
- ASSERT_TRUE(client_state->has_server_nonce());
- ASSERT_FALSE(client_state->GetNextServerNonce().empty());
- ASSERT_FALSE(client_state->has_server_nonce());
-
- ASSERT_TRUE(client_state->has_server_designated_connection_id());
- const QuicConnectionId server_designated_connection_id =
- client_state->GetNextServerDesignatedConnectionId();
- const QuicConnectionId expected_id = QuicUtils::CreateRandomConnectionId(
- server_connection_->random_generator());
- EXPECT_EQ(expected_id, server_designated_connection_id);
- EXPECT_FALSE(client_state->has_server_designated_connection_id());
- ASSERT_TRUE(client_state->IsComplete(QuicWallTime::FromUNIXSeconds(0)));
-}
-
-TEST_P(QuicCryptoServerStreamTest, ConnectedAfterStatelessHandshake) {
- SetQuicReloadableFlag(enable_quic_stateless_reject_support, true);
- Initialize();
-
- InitializeFakeClient(/* supports_stateless_rejects= */ true);
- EXPECT_CALL(*server_connection_,
- CloseConnection(QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, _, _));
- EXPECT_CALL(*client_connection_,
- CloseConnection(QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, _, _));
- AdvanceHandshakeWithFakeClient();
-
- // On the first round, encryption will not be established.
- EXPECT_FALSE(server_stream()->encryption_established());
- EXPECT_FALSE(server_stream()->handshake_confirmed());
- EXPECT_EQ(1, server_stream()->NumHandshakeMessages());
- EXPECT_EQ(0, server_stream()->NumHandshakeMessagesWithServerNonces());
-
- // Now check the client state.
- QuicCryptoClientConfig::CachedState* client_state =
- client_crypto_config_.LookupOrCreate(server_id_);
-
- ASSERT_TRUE(client_state->has_server_designated_connection_id());
- const QuicConnectionId server_designated_connection_id =
- client_state->GetNextServerDesignatedConnectionId();
- const QuicConnectionId expected_id = QuicUtils::CreateRandomConnectionId(
- server_connection_->random_generator());
- EXPECT_EQ(expected_id, server_designated_connection_id);
- EXPECT_FALSE(client_state->has_server_designated_connection_id());
- ASSERT_TRUE(client_state->IsComplete(QuicWallTime::FromUNIXSeconds(0)));
-
- // Now create new client and server streams with the existing config
- // and try the handshake again (0-RTT handshake).
- InitializeServer();
-
- InitializeFakeClient(/* supports_stateless_rejects= */ true);
- // In the stateless case, the second handshake contains a server-nonce, so the
- // AsyncStrikeRegisterVerification() case will still succeed (unlike a 0-RTT
- // handshake).
- AdvanceHandshakeWithFakeClient();
-
- // On the second round, encryption will be established.
- EXPECT_TRUE(server_stream()->encryption_established());
- EXPECT_TRUE(server_stream()->handshake_confirmed());
- EXPECT_EQ(1, server_stream()->NumHandshakeMessages());
- EXPECT_EQ(1, server_stream()->NumHandshakeMessagesWithServerNonces());
-}
-
-TEST_P(QuicCryptoServerStreamTest, NoStatelessRejectIfNoClientSupport) {
- SetQuicReloadableFlag(enable_quic_stateless_reject_support, true);
- Initialize();
-
- // The server is configured to use stateless rejects, but the client does not
- // support it.
- InitializeFakeClient(/* supports_stateless_rejects= */ false);
- AdvanceHandshakeWithFakeClient();
-
- // Check the server to make the sure the handshake did not succeed.
- EXPECT_FALSE(server_stream()->encryption_established());
- EXPECT_FALSE(server_stream()->handshake_confirmed());
-
- // Check the client state to make sure that it did not receive a
- // server-designated connection id.
- QuicCryptoClientConfig::CachedState* client_state =
- client_crypto_config_.LookupOrCreate(server_id_);
-
- ASSERT_FALSE(client_state->has_server_designated_connection_id());
- ASSERT_TRUE(client_state->IsComplete(QuicWallTime::FromUNIXSeconds(0)));
-}
-
TEST_P(QuicCryptoServerStreamTest, ZeroRTT) {
Initialize();
- InitializeFakeClient(/* supports_stateless_rejects= */ false);
+ InitializeFakeClient();
// Do a first handshake in order to prime the client config with the server's
// information.
@@ -365,7 +243,7 @@ TEST_P(QuicCryptoServerStreamTest, ZeroRTT) {
// Now do another handshake, hopefully in 0-RTT.
QUIC_LOG(INFO) << "Resetting for 0-RTT handshake attempt";
- InitializeFakeClient(/* supports_stateless_rejects= */ false);
+ InitializeFakeClient();
InitializeServer();
EXPECT_CALL(*client_session_, OnProofValid(_)).Times(testing::AnyNumber());
@@ -387,7 +265,7 @@ TEST_P(QuicCryptoServerStreamTest, ZeroRTT) {
TEST_P(QuicCryptoServerStreamTest, FailByPolicy) {
Initialize();
- InitializeFakeClient(/* supports_stateless_rejects= */ false);
+ InitializeFakeClient();
EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
.WillOnce(testing::Return(false));
@@ -418,30 +296,6 @@ TEST_P(QuicCryptoServerStreamTest, BadMessageType) {
Perspective::IS_SERVER);
}
-TEST_P(QuicCryptoServerStreamTest, ChannelID) {
- Initialize();
-
- client_options_.channel_id_enabled = true;
- client_options_.channel_id_source_async = false;
- // CompleteCryptoHandshake verifies
- // server_stream()->crypto_negotiated_params().channel_id is correct.
- EXPECT_EQ(2, CompleteCryptoHandshake());
- EXPECT_TRUE(server_stream()->encryption_established());
- EXPECT_TRUE(server_stream()->handshake_confirmed());
-}
-
-TEST_P(QuicCryptoServerStreamTest, ChannelIDAsync) {
- Initialize();
-
- client_options_.channel_id_enabled = true;
- client_options_.channel_id_source_async = true;
- // CompleteCryptoHandshake verifies
- // server_stream()->crypto_negotiated_params().channel_id is correct.
- EXPECT_EQ(2, CompleteCryptoHandshake());
- EXPECT_TRUE(server_stream()->encryption_established());
- EXPECT_TRUE(server_stream()->handshake_confirmed());
-}
-
TEST_P(QuicCryptoServerStreamTest, OnlySendSCUPAfterHandshakeComplete) {
// An attempt to send a SCUP before completing handshake should fail.
Initialize();
@@ -453,7 +307,7 @@ TEST_P(QuicCryptoServerStreamTest, OnlySendSCUPAfterHandshakeComplete) {
TEST_P(QuicCryptoServerStreamTest, SendSCUPAfterHandshakeComplete) {
Initialize();
- InitializeFakeClient(/* supports_stateless_rejects= */ false);
+ InitializeFakeClient();
// Do a first handshake in order to prime the client config with the server's
// information.
@@ -461,7 +315,7 @@ TEST_P(QuicCryptoServerStreamTest, SendSCUPAfterHandshakeComplete) {
// Now do another handshake, with the blocking SHLO connection option.
InitializeServer();
- InitializeFakeClient(/* supports_stateless_rejects= */ false);
+ InitializeFakeClient();
AdvanceHandshakeWithFakeClient();
// Send a SCUP message and ensure that the client was able to verify it.
@@ -474,21 +328,6 @@ TEST_P(QuicCryptoServerStreamTest, SendSCUPAfterHandshakeComplete) {
EXPECT_EQ(1, client_stream()->num_scup_messages_received());
}
-TEST_P(QuicCryptoServerStreamTest, DoesPeerSupportStatelessRejects) {
- Initialize();
-
- QuicConfig stateless_reject_config = DefaultQuicConfigStatelessRejects();
- stateless_reject_config.ToHandshakeMessage(&message_);
- EXPECT_TRUE(
- QuicCryptoServerStreamPeer::DoesPeerSupportStatelessRejects(message_));
-
- message_.Clear();
- QuicConfig stateful_reject_config = DefaultQuicConfig();
- stateful_reject_config.ToHandshakeMessage(&message_);
- EXPECT_FALSE(
- QuicCryptoServerStreamPeer::DoesPeerSupportStatelessRejects(message_));
-}
-
class QuicCryptoServerStreamTestWithFailingProofSource
: public QuicCryptoServerStreamTest {
public:
@@ -503,7 +342,7 @@ INSTANTIATE_TEST_SUITE_P(MoreTests,
TEST_P(QuicCryptoServerStreamTestWithFailingProofSource, Test) {
Initialize();
- InitializeFakeClient(/* supports_stateless_rejects= */ false);
+ InitializeFakeClient();
EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
.WillOnce(testing::Return(true));
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 836fbac67ab..f394b3d5110 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
@@ -24,11 +24,18 @@ namespace quic {
" ")
QuicCryptoStream::QuicCryptoStream(QuicSession* session)
- : QuicStream(QuicUtils::GetCryptoStreamId(
- session->connection()->transport_version()),
+ : QuicStream(QuicVersionUsesCryptoFrames(
+ session->connection()->transport_version())
+ ? QuicUtils::GetInvalidStreamId(
+ session->connection()->transport_version())
+ : QuicUtils::GetCryptoStreamId(
+ session->connection()->transport_version()),
session,
/*is_static=*/true,
- BIDIRECTIONAL),
+ QuicVersionUsesCryptoFrames(
+ session->connection()->transport_version())
+ ? CRYPTO
+ : BIDIRECTIONAL),
substreams_{{this, ENCRYPTION_INITIAL},
{this, ENCRYPTION_HANDSHAKE},
{this, ENCRYPTION_ZERO_RTT},
@@ -156,6 +163,9 @@ void QuicCryptoStream::WriteCryptoData(EncryptionLevel level,
size_t bytes_consumed =
session()->connection()->SendCryptoData(level, data.length(), offset);
session()->connection()->SetDefaultEncryptionLevel(current_level);
+ // Since CRYPTO frames aren't flow controlled, SendCryptoData should have sent
+ // all data we asked it to send.
+ DCHECK_EQ(bytes_consumed, data.length());
send_buffer->OnStreamDataConsumed(bytes_consumed);
}
@@ -210,7 +220,7 @@ void QuicCryptoStream::OnStreamDataConsumed(size_t bytes_consumed) {
QuicStream::OnStreamDataConsumed(bytes_consumed);
}
-bool QuicCryptoStream::HasPendingCryptoRetransmission() {
+bool QuicCryptoStream::HasPendingCryptoRetransmission() const {
if (!QuicVersionUsesCryptoFrames(
session()->connection()->transport_version())) {
return false;
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 0c6d08aa607..1b641b19cec 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
@@ -92,7 +92,7 @@ class QUIC_EXPORT_PRIVATE QuicCryptoStream : public QuicStream {
// Returns whether there are any bytes pending retransmission in CRYPTO
// frames.
- virtual bool HasPendingCryptoRetransmission();
+ virtual bool HasPendingCryptoRetransmission() const;
// Writes any pending CRYPTO frame retransmissions.
void WritePendingCryptoRetransmission();
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 0488fd39d00..ef094830a09 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
@@ -12,6 +12,9 @@
namespace quic {
+QuicDataReader::QuicDataReader(QuicStringPiece data)
+ : QuicDataReader(data.data(), data.length(), NETWORK_BYTE_ORDER) {}
+
QuicDataReader::QuicDataReader(const char* data, const size_t len)
: QuicDataReader(data, len, NETWORK_BYTE_ORDER) {}
@@ -180,6 +183,15 @@ bool QuicDataReader::ReadBytes(void* result, size_t size) {
return true;
}
+bool QuicDataReader::Seek(size_t size) {
+ if (!CanRead(size)) {
+ OnFailure();
+ return false;
+ }
+ pos_ += size;
+ return true;
+}
+
bool QuicDataReader::IsDoneReading() const {
return len_ == pos_;
}
@@ -295,7 +307,7 @@ bool QuicDataReader::ReadVarInt62(uint64_t* result) {
return false;
}
-bool QuicDataReader::ReadVarIntStreamId(QuicStreamId* result) {
+bool QuicDataReader::ReadVarIntU32(uint32_t* result) {
uint64_t temp_uint64;
// TODO(fkastenholz): We should disambiguate read-errors from
// value errors.
@@ -305,7 +317,7 @@ bool QuicDataReader::ReadVarIntStreamId(QuicStreamId* result) {
if (temp_uint64 > kMaxQuicStreamId) {
return false;
}
- *result = static_cast<QuicStreamId>(temp_uint64);
+ *result = static_cast<uint32_t>(temp_uint64);
return true;
}
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 3426e48efc6..a03b92751a5 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
@@ -33,6 +33,9 @@ class QUIC_EXPORT_PRIVATE QuicDataReader {
public:
// Constructs a reader using NETWORK_BYTE_ORDER endianness.
// Caller must provide an underlying buffer to work on.
+ explicit QuicDataReader(QuicStringPiece data);
+ // Constructs a reader using NETWORK_BYTE_ORDER endianness.
+ // Caller must provide an underlying buffer to work on.
QuicDataReader(const char* data, const size_t len);
// Constructs a reader using the specified endianness.
// Caller must provide an underlying buffer to work on.
@@ -108,6 +111,11 @@ class QUIC_EXPORT_PRIVATE QuicDataReader {
// Returns true on success, false otherwise.
bool ReadBytes(void* result, size_t size);
+ // Skips over |size| bytes from the buffer and forwards the internal iterator.
+ // Returns true if there are at least |size| bytes remaining to read, false
+ // otherwise.
+ bool Seek(size_t size);
+
// Returns true if the entirety of the underlying buffer has been read via
// Read*() calls.
bool IsDoneReading() const;
@@ -142,11 +150,11 @@ class QUIC_EXPORT_PRIVATE QuicDataReader {
// and that the integers in the range 0 ... (2^62)-1.
bool ReadVarInt62(uint64_t* result);
- // Convenience method that reads a StreamId.
- // Atempts to read a Stream ID into |result| using ReadVarInt62 and
+ // Convenience method that reads a uint32_t.
+ // Attempts to read a varint into a uint32_t. using ReadVarInt62 and
// returns false if there is a read error or if the value is
// greater than (2^32)-1.
- bool ReadVarIntStreamId(QuicStreamId* result);
+ bool ReadVarIntU32(uint32_t* result);
std::string DebugString() const;
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 7116853e77d..42f1e4e2092 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
@@ -196,6 +196,14 @@ bool QuicDataWriter::WriteRandomBytes(QuicRandom* random, size_t length) {
return true;
}
+bool QuicDataWriter::Seek(size_t length) {
+ if (!BeginWrite(length)) {
+ return false;
+ }
+ length_ += length;
+ return true;
+}
+
// Converts a uint64_t into an IETF/Quic formatted Variable Length
// Integer. IETF Variable Length Integers have 62 significant bits, so
// the value to write must be in the range of 0..(2^62)-1.
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 bd1ded6c6da..d2d2b6bf3df 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
@@ -117,6 +117,11 @@ class QUIC_EXPORT_PRIVATE QuicDataWriter {
// Write |length| random bytes generated by |random|.
bool WriteRandomBytes(QuicRandom* random, size_t length);
+ // Advance the writer's position for writing by |length| bytes without writing
+ // anything. This method only makes sense to be used on a buffer that has
+ // already been written to (and is having certain parts rewritten).
+ bool Seek(size_t length);
+
size_t capacity() const { return capacity_; }
size_t remaining() const { return capacity_ - length_; }
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 031620df4e8..07f0313f9ef 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
@@ -1026,7 +1026,7 @@ void EncodeDecodeStreamId(uint64_t value_in, bool expected_decode_result) {
QuicDataReader reader(buffer, sizeof(buffer), Endianness::NETWORK_BYTE_ORDER);
QuicStreamId received_stream_id;
- bool read_result = reader.ReadVarIntStreamId(&received_stream_id);
+ bool read_result = reader.ReadVarIntU32(&received_stream_id);
EXPECT_EQ(expected_decode_result, read_result);
if (read_result) {
EXPECT_EQ(value_in, received_stream_id);
@@ -1114,6 +1114,74 @@ TEST_P(QuicDataWriterTest, InvalidConnectionIdLengthRead) {
EXPECT_FALSE(ok);
}
+// Test that ReadVarIntU32 works properly. Tests a valid stream count
+// (a 32 bit number) and an invalid one (a >32 bit number)
+TEST_P(QuicDataWriterTest, ValidU32) {
+ char buffer[1024];
+ memset(buffer, 0, sizeof(buffer));
+ QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
+ Endianness::NETWORK_BYTE_ORDER);
+ QuicDataReader reader(buffer, sizeof(buffer));
+ const QuicStreamCount write_stream_count = 0xffeeddcc;
+ EXPECT_TRUE(writer.WriteVarInt62(write_stream_count));
+ QuicStreamCount read_stream_count;
+ EXPECT_TRUE(reader.ReadVarIntU32(&read_stream_count));
+ EXPECT_EQ(write_stream_count, read_stream_count);
+}
+
+TEST_P(QuicDataWriterTest, InvalidU32) {
+ char buffer[1024];
+ memset(buffer, 0, sizeof(buffer));
+ QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
+ Endianness::NETWORK_BYTE_ORDER);
+ QuicDataReader reader(buffer, sizeof(buffer));
+ EXPECT_TRUE(writer.WriteVarInt62(UINT64_C(0x1ffeeddcc)));
+ QuicStreamCount read_stream_count = 123456;
+ EXPECT_FALSE(reader.ReadVarIntU32(&read_stream_count));
+ // If the value is bad, read_stream_count ought not change.
+ EXPECT_EQ(123456u, read_stream_count);
+}
+
+TEST_P(QuicDataWriterTest, Seek) {
+ char buffer[3] = {};
+ QuicDataWriter writer(QUIC_ARRAYSIZE(buffer), buffer, GetParam().endianness);
+ EXPECT_TRUE(writer.WriteUInt8(42));
+ EXPECT_TRUE(writer.Seek(1));
+ EXPECT_TRUE(writer.WriteUInt8(3));
+
+ char expected[] = {42, 0, 3};
+ for (size_t i = 0; i < QUIC_ARRAYSIZE(expected); ++i) {
+ EXPECT_EQ(buffer[i], expected[i]);
+ }
+}
+
+TEST_P(QuicDataWriterTest, SeekTooFarFails) {
+ char buffer[20];
+
+ // Check that one can seek to the end of the writer, but not past.
+ {
+ QuicDataWriter writer(QUIC_ARRAYSIZE(buffer), buffer,
+ GetParam().endianness);
+ EXPECT_TRUE(writer.Seek(20));
+ EXPECT_FALSE(writer.Seek(1));
+ }
+
+ // Seeking several bytes past the end fails.
+ {
+ QuicDataWriter writer(QUIC_ARRAYSIZE(buffer), buffer,
+ GetParam().endianness);
+ EXPECT_FALSE(writer.Seek(100));
+ }
+
+ // Seeking so far that arithmetic overflow could occur also fails.
+ {
+ QuicDataWriter writer(QUIC_ARRAYSIZE(buffer), buffer,
+ GetParam().endianness);
+ EXPECT_TRUE(writer.Seek(10));
+ EXPECT_FALSE(writer.Seek(std::numeric_limits<size_t>::max()));
+ }
+}
+
} // namespace
} // namespace test
} // namespace quic
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 75b3c30ffc6..5bf072d7e09 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
@@ -10,10 +10,10 @@
#include "net/third_party/quiche/src/quic/core/chlo_extractor.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/core/stateless_rejector.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"
@@ -21,6 +21,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_stack_trace.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
namespace quic {
@@ -71,8 +72,7 @@ class PacketCollector : public QuicPacketCreator::DelegateInterface,
}
void OnUnrecoverableError(QuicErrorCode error,
- const std::string& error_details,
- ConnectionCloseSource source) override {}
+ const std::string& error_details) override {}
void SaveStatelessRejectFrameData(QuicStringPiece reject) {
struct iovec iovec;
@@ -114,21 +114,24 @@ class PacketCollector : public QuicPacketCreator::DelegateInterface,
// list manager.
class StatelessConnectionTerminator {
public:
- StatelessConnectionTerminator(QuicConnectionId connection_id,
- QuicFramer* framer,
+ StatelessConnectionTerminator(QuicConnectionId server_connection_id,
+ const ParsedQuicVersion version,
QuicConnectionHelperInterface* helper,
QuicTimeWaitListManager* time_wait_list_manager)
- : connection_id_(connection_id),
- framer_(framer),
+ : server_connection_id_(server_connection_id),
+ framer_(ParsedQuicVersionVector{version},
+ /*unused*/ QuicTime::Zero(),
+ Perspective::IS_SERVER,
+ /*unused*/ kQuicDefaultConnectionIdLength),
collector_(helper->GetStreamSendBufferAllocator()),
- creator_(connection_id, framer, &collector_),
+ creator_(server_connection_id, &framer_, &collector_),
time_wait_list_manager_(time_wait_list_manager) {
- framer_->set_data_producer(&collector_);
+ framer_.set_data_producer(&collector_);
}
~StatelessConnectionTerminator() {
// Clear framer's producer.
- framer_->set_data_producer(nullptr);
+ framer_.set_data_producer(nullptr);
}
// Generates a packet containing a CONNECTION_CLOSE frame specifying
@@ -138,8 +141,7 @@ class StatelessConnectionTerminator {
bool ietf_quic) {
QuicConnectionCloseFrame* frame =
new QuicConnectionCloseFrame(error_code, error_details);
- // TODO(fkastenholz): The framer version may be incorrect in some cases.
- if (framer_->transport_version() == QUIC_VERSION_99) {
+ if (framer_.transport_version() == QUIC_VERSION_99) {
frame->close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE;
}
@@ -151,7 +153,7 @@ class StatelessConnectionTerminator {
creator_.Flush();
DCHECK_EQ(1u, collector_.packets()->size());
time_wait_list_manager_->AddConnectionIdToTimeWait(
- connection_id_, ietf_quic,
+ server_connection_id_, ietf_quic,
QuicTimeWaitListManager::SEND_TERMINATION_PACKETS,
quic::ENCRYPTION_INITIAL, collector_.packets());
}
@@ -164,9 +166,9 @@ class StatelessConnectionTerminator {
collector_.SaveStatelessRejectFrameData(reject);
while (offset < reject.length()) {
QuicFrame frame;
- if (!QuicVersionUsesCryptoFrames(framer_->transport_version())) {
+ if (!QuicVersionUsesCryptoFrames(framer_.transport_version())) {
if (!creator_.ConsumeData(
- QuicUtils::GetCryptoStreamId(framer_->transport_version()),
+ QuicUtils::GetCryptoStreamId(framer_.transport_version()),
reject.length() - offset, offset,
/*fin=*/false,
/*needs_full_padding=*/true, NOT_RETRANSMISSION, &frame)) {
@@ -175,31 +177,33 @@ class StatelessConnectionTerminator {
}
offset += frame.stream_frame.data_length;
} else {
- if (!creator_.ConsumeCryptoData(ENCRYPTION_INITIAL,
- reject.length() - offset, offset,
- NOT_RETRANSMISSION, &frame)) {
+ if (!creator_.ConsumeCryptoData(
+ ENCRYPTION_INITIAL, reject.length() - offset, offset,
+ /*needs_full_padding=*/true, NOT_RETRANSMISSION, &frame)) {
QUIC_BUG << "Unable to consume crypto data into an empty packet.";
return;
}
offset += frame.crypto_frame->data_length;
}
- if (offset < reject.length()) {
+ if (offset < reject.length() &&
+ !QuicVersionUsesCryptoFrames(framer_.transport_version())) {
DCHECK(!creator_.HasRoomForStreamFrame(
- QuicUtils::GetCryptoStreamId(framer_->transport_version()), offset,
+ QuicUtils::GetCryptoStreamId(framer_.transport_version()), offset,
frame.stream_frame.data_length));
}
creator_.Flush();
}
time_wait_list_manager_->AddConnectionIdToTimeWait(
- connection_id_, ietf_quic,
+ server_connection_id_, ietf_quic,
QuicTimeWaitListManager::SEND_TERMINATION_PACKETS, ENCRYPTION_INITIAL,
collector_.packets());
- DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id_));
+ DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(
+ server_connection_id_));
}
private:
- QuicConnectionId connection_id_;
- QuicFramer* framer_; // Unowned.
+ QuicConnectionId server_connection_id_;
+ QuicFramer framer_;
// Set as the visitor of |creator_| to collect any generated packets.
PacketCollector collector_;
QuicPacketCreator creator_;
@@ -210,7 +214,7 @@ class StatelessConnectionTerminator {
class ChloAlpnExtractor : public ChloExtractor::Delegate {
public:
void OnChlo(QuicTransportVersion version,
- QuicConnectionId connection_id,
+ QuicConnectionId server_connection_id,
const CryptoHandshakeMessage& chlo) override {
QuicStringPiece alpn_value;
if (chlo.GetStringPiece(kALPN, &alpn_value)) {
@@ -224,54 +228,6 @@ class ChloAlpnExtractor : public ChloExtractor::Delegate {
std::string alpn_;
};
-// Class which sits between the ChloExtractor and the StatelessRejector
-// to give the QuicDispatcher a chance to apply policy checks to the CHLO.
-class ChloValidator : public ChloAlpnExtractor {
- public:
- ChloValidator(QuicCryptoServerStream::Helper* helper,
- const QuicSocketAddress& client_address,
- const QuicSocketAddress& peer_address,
- const QuicSocketAddress& self_address,
- StatelessRejector* rejector)
- : helper_(helper),
- client_address_(client_address),
- peer_address_(peer_address),
- self_address_(self_address),
- rejector_(rejector),
- can_accept_(false),
- error_details_("CHLO not processed") {}
-
- // ChloExtractor::Delegate implementation.
- void OnChlo(QuicTransportVersion version,
- QuicConnectionId connection_id,
- const CryptoHandshakeMessage& chlo) override {
- // Extract the ALPN
- ChloAlpnExtractor::OnChlo(version, connection_id, chlo);
- if (helper_->CanAcceptClientHello(chlo, client_address_, peer_address_,
- self_address_, &error_details_)) {
- can_accept_ = true;
- rejector_->OnChlo(
- version, connection_id,
- helper_->GenerateConnectionIdForReject(version, connection_id), chlo);
- }
- }
-
- bool can_accept() const { return can_accept_; }
-
- const std::string& error_details() const { return error_details_; }
-
- private:
- QuicCryptoServerStream::Helper* helper_; // Unowned.
- // client_address_ and peer_address_ could be different values for proxy
- // connections.
- QuicSocketAddress client_address_;
- QuicSocketAddress peer_address_;
- QuicSocketAddress self_address_;
- StatelessRejector* rejector_; // Unowned.
- bool can_accept_;
- std::string error_details_;
-};
-
} // namespace
QuicDispatcher::QuicDispatcher(
@@ -281,7 +237,7 @@ QuicDispatcher::QuicDispatcher(
std::unique_ptr<QuicConnectionHelperInterface> helper,
std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
- uint8_t expected_connection_id_length)
+ uint8_t expected_server_connection_id_length)
: config_(config),
crypto_config_(crypto_config),
compressed_certs_cache_(
@@ -297,12 +253,19 @@ QuicDispatcher::QuicDispatcher(
framer_(GetSupportedVersions(),
/*unused*/ QuicTime::Zero(),
Perspective::IS_SERVER,
- expected_connection_id_length),
+ expected_server_connection_id_length),
last_error_(QUIC_NO_ERROR),
new_sessions_allowed_per_event_loop_(0u),
accept_new_connections_(true),
- allow_short_initial_connection_ids_(false) {
- framer_.set_visitor(this);
+ allow_short_initial_server_connection_ids_(false),
+ last_version_label_(0),
+ expected_server_connection_id_length_(
+ expected_server_connection_id_length),
+ should_update_expected_server_connection_id_length_(false),
+ no_framer_(GetQuicRestartFlag(quic_no_framer_object_in_dispatcher)) {
+ if (!no_framer_) {
+ framer_.set_visitor(this);
+ }
}
QuicDispatcher::~QuicDispatcher() {
@@ -319,48 +282,93 @@ void QuicDispatcher::InitializeWithWriter(QuicPacketWriter* writer) {
void QuicDispatcher::ProcessPacket(const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
const QuicReceivedPacket& packet) {
+ QUIC_DVLOG(2) << "Dispatcher received encrypted " << packet.length()
+ << " bytes:" << std::endl
+ << QuicTextUtils::HexDump(
+ QuicStringPiece(packet.data(), packet.length()));
current_self_address_ = self_address;
current_peer_address_ = peer_address;
// GetClientAddress must be called after current_peer_address_ is set.
current_client_address_ = GetClientAddress();
current_packet_ = &packet;
- // ProcessPacket will cause the packet to be dispatched in
- // OnUnauthenticatedPublicHeader, or sent to the time wait list manager
- // in OnUnauthenticatedHeader.
- framer_.ProcessPacket(packet);
- // TODO(rjshade): Return a status describing if/why a packet was dropped,
- // and log somehow. Maybe expose as a varz.
- // TODO(wub): Consider invalidate the current_* variables so processing of the
- // next packet does not use them incorrectly.
-}
-
-QuicConnectionId QuicDispatcher::MaybeReplaceConnectionId(
- QuicConnectionId connection_id,
+ if (!no_framer_) {
+ // ProcessPacket will cause the packet to be dispatched in
+ // OnUnauthenticatedPublicHeader, or sent to the time wait list manager
+ // in OnUnauthenticatedHeader.
+ framer_.ProcessPacket(packet);
+ // TODO(rjshade): Return a status describing if/why a packet was dropped,
+ // and log somehow. Maybe expose as a varz.
+ return;
+ }
+ QUIC_RESTART_FLAG_COUNT(quic_no_framer_object_in_dispatcher);
+ QuicPacketHeader header;
+ uint8_t destination_connection_id_length;
+ std::string detailed_error;
+ const QuicErrorCode error = QuicFramer::ProcessPacketDispatcher(
+ packet, expected_server_connection_id_length_, &header.form,
+ &header.version_flag, &last_version_label_,
+ &destination_connection_id_length, &header.destination_connection_id,
+ &detailed_error);
+ if (error != QUIC_NO_ERROR) {
+ // Packet has framing error.
+ SetLastError(error);
+ QUIC_DLOG(ERROR) << detailed_error;
+ return;
+ }
+ header.version = ParseQuicVersionLabel(last_version_label_);
+ if (destination_connection_id_length !=
+ expected_server_connection_id_length_ &&
+ !should_update_expected_server_connection_id_length_ &&
+ !QuicUtils::VariableLengthConnectionIdAllowedForVersion(
+ header.version.transport_version)) {
+ SetLastError(QUIC_INVALID_PACKET_HEADER);
+ QUIC_DLOG(ERROR) << "Invalid Connection Id Length";
+ return;
+ }
+ if (should_update_expected_server_connection_id_length_) {
+ expected_server_connection_id_length_ = destination_connection_id_length;
+ }
+ // TODO(fayang): Instead of passing in QuicPacketHeader, pass format,
+ // version_flag, version and destination_connection_id. Combine
+ // OnUnauthenticatedPublicHeader and OnUnauthenticatedHeader to a single
+ // function when deprecating quic_no_framer_object_in_dispatcher.
+ if (!OnUnauthenticatedPublicHeader(header)) {
+ return;
+ }
+ OnUnauthenticatedHeader(header);
+ // TODO(wub): Consider invalidate the current_* variables so processing of
+ // the next packet does not use them incorrectly.
+}
+
+QuicConnectionId QuicDispatcher::MaybeReplaceServerConnectionId(
+ QuicConnectionId server_connection_id,
ParsedQuicVersion version) {
- const uint8_t expected_connection_id_length =
- framer_.GetExpectedConnectionIdLength();
- if (connection_id.length() == expected_connection_id_length) {
- return connection_id;
+ const uint8_t expected_server_connection_id_length =
+ no_framer_ ? expected_server_connection_id_length_
+ : framer_.GetExpectedServerConnectionIdLength();
+ if (server_connection_id.length() == expected_server_connection_id_length) {
+ return server_connection_id;
}
DCHECK(QuicUtils::VariableLengthConnectionIdAllowedForVersion(
version.transport_version));
- auto it = connection_id_map_.find(connection_id);
+ auto it = connection_id_map_.find(server_connection_id);
if (it != connection_id_map_.end()) {
return it->second;
}
QuicConnectionId new_connection_id =
session_helper_->GenerateConnectionIdForReject(version.transport_version,
- connection_id);
- DCHECK_EQ(expected_connection_id_length, new_connection_id.length());
- connection_id_map_.insert(std::make_pair(connection_id, new_connection_id));
- QUIC_DLOG(INFO) << "Replacing incoming connection ID " << connection_id
+ server_connection_id);
+ DCHECK_EQ(expected_server_connection_id_length, new_connection_id.length());
+ connection_id_map_.insert(
+ std::make_pair(server_connection_id, new_connection_id));
+ QUIC_DLOG(INFO) << "Replacing incoming connection ID " << server_connection_id
<< " with " << new_connection_id;
return new_connection_id;
}
bool QuicDispatcher::OnUnauthenticatedPublicHeader(
const QuicPacketHeader& header) {
- current_connection_id_ = header.destination_connection_id;
+ current_server_connection_id_ = header.destination_connection_id;
// Port zero is only allowed for unidirectional UDP, so is disallowed by QUIC.
// Given that we can't even send a reply rejecting the packet, just drop the
@@ -374,50 +382,53 @@ bool QuicDispatcher::OnUnauthenticatedPublicHeader(
if (header.destination_connection_id_included != CONNECTION_ID_PRESENT) {
return false;
}
- QuicConnectionId connection_id = header.destination_connection_id;
+ QuicConnectionId server_connection_id = header.destination_connection_id;
// The IETF spec requires the client to generate an initial server
// connection ID that is at least 64 bits long. After that initial
// connection ID, the dispatcher picks a new one of its expected length.
// Therefore we should never receive a connection ID that is smaller
// than 64 bits and smaller than what we expect.
- if (connection_id.length() < kQuicMinimumInitialConnectionIdLength &&
- connection_id.length() < framer_.GetExpectedConnectionIdLength() &&
- !allow_short_initial_connection_ids_) {
+ const uint8_t expected_server_connection_id_length =
+ no_framer_ ? expected_server_connection_id_length_
+ : framer_.GetExpectedServerConnectionIdLength();
+ if (server_connection_id.length() < kQuicMinimumInitialConnectionIdLength &&
+ server_connection_id.length() < expected_server_connection_id_length &&
+ !allow_short_initial_server_connection_ids_) {
DCHECK(header.version_flag);
DCHECK(QuicUtils::VariableLengthConnectionIdAllowedForVersion(
header.version.transport_version));
QUIC_DLOG(INFO) << "Packet with short destination connection ID "
- << connection_id << " expected "
- << static_cast<int>(
- framer_.GetExpectedConnectionIdLength());
- ProcessUnauthenticatedHeaderFate(kFateTimeWait, connection_id, header.form,
+ << server_connection_id << " expected "
+ << static_cast<int>(expected_server_connection_id_length);
+ ProcessUnauthenticatedHeaderFate(kFateTimeWait, server_connection_id,
+ header.form, header.version_flag,
header.version);
return false;
}
// Packets with connection IDs for active connections are processed
// immediately.
- auto it = session_map_.find(connection_id);
+ auto it = session_map_.find(server_connection_id);
if (it != session_map_.end()) {
- DCHECK(!buffered_packets_.HasBufferedPackets(connection_id));
+ DCHECK(!buffered_packets_.HasBufferedPackets(server_connection_id));
it->second->ProcessUdpPacket(current_self_address_, current_peer_address_,
*current_packet_);
return false;
}
- if (buffered_packets_.HasChloForConnection(connection_id)) {
- BufferEarlyPacket(connection_id, header.form != GOOGLE_QUIC_PACKET,
+ if (buffered_packets_.HasChloForConnection(server_connection_id)) {
+ BufferEarlyPacket(server_connection_id, header.form != GOOGLE_QUIC_PACKET,
header.version);
return false;
}
// Check if we are buffering packets for this connection ID
- if (temporarily_buffered_connections_.find(connection_id) !=
+ if (temporarily_buffered_connections_.find(server_connection_id) !=
temporarily_buffered_connections_.end()) {
// This packet was received while the a CHLO for the same connection ID was
// being processed. Buffer it.
- BufferEarlyPacket(connection_id, header.form != GOOGLE_QUIC_PACKET,
+ BufferEarlyPacket(server_connection_id, header.form != GOOGLE_QUIC_PACKET,
header.version);
return false;
}
@@ -432,7 +443,7 @@ bool QuicDispatcher::OnUnauthenticatedPublicHeader(
return false;
}
- if (time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)) {
+ if (time_wait_list_manager_->IsConnectionIdInTimeWait(server_connection_id)) {
// This connection ID is already in time-wait state.
time_wait_list_manager_->ProcessPacket(
current_self_address_, current_peer_address_,
@@ -447,12 +458,14 @@ bool QuicDispatcher::OnUnauthenticatedPublicHeader(
ParsedQuicVersion version = GetSupportedVersions().front();
if (header.version_flag) {
ParsedQuicVersion packet_version = header.version;
- if (framer_.supported_versions() != GetSupportedVersions()) {
+ if (!no_framer_ && framer_.supported_versions() != GetSupportedVersions()) {
// Reset framer's version if version flags change in flight.
framer_.SetSupportedVersions(GetSupportedVersions());
}
- if (!framer_.IsSupportedVersion(packet_version)) {
- if (ShouldCreateSessionForUnknownVersion(framer_.last_version_label())) {
+ if (!IsSupportedVersion(packet_version)) {
+ if (ShouldCreateSessionForUnknownVersion(
+ no_framer_ ? last_version_label_
+ : framer_.last_version_label())) {
return true;
}
if (!crypto_config()->validate_chlo_size() ||
@@ -460,41 +473,52 @@ bool QuicDispatcher::OnUnauthenticatedPublicHeader(
// Since the version is not supported, send a version negotiation
// packet and stop processing the current packet.
time_wait_list_manager()->SendVersionNegotiationPacket(
- connection_id, header.form != GOOGLE_QUIC_PACKET,
- GetSupportedVersions(), current_self_address_,
- current_peer_address_, GetPerPacketContext());
+ server_connection_id, EmptyQuicConnectionId(),
+ header.form != GOOGLE_QUIC_PACKET, GetSupportedVersions(),
+ current_self_address_, current_peer_address_,
+ GetPerPacketContext());
}
return false;
}
version = packet_version;
}
- // Set the framer's version and continue processing.
- framer_.set_version(version);
+ if (!no_framer_) {
+ // Set the framer's version and continue processing.
+ framer_.set_version(version);
+ }
+
+ if (version.HasHeaderProtection()) {
+ ProcessHeader(header);
+ return false;
+ }
return true;
}
bool QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
- QuicConnectionId connection_id = header.destination_connection_id;
+ ProcessHeader(header);
+ return false;
+}
+
+void QuicDispatcher::ProcessHeader(const QuicPacketHeader& header) {
+ QuicConnectionId server_connection_id = header.destination_connection_id;
// Packet's connection ID is unknown. Apply the validity checks.
QuicPacketFate fate = ValidityChecks(header);
if (fate == kFateProcess) {
- // Execute stateless rejection logic to determine the packet fate, then
- // invoke ProcessUnauthenticatedHeaderFate.
- MaybeRejectStatelessly(connection_id, header.form, header.version);
+ ProcessOrBufferPacket(server_connection_id, header.form,
+ header.version_flag, header.version);
} else {
// If the fate is already known, process it without executing stateless
// rejection logic.
- ProcessUnauthenticatedHeaderFate(fate, connection_id, header.form,
- header.version);
+ ProcessUnauthenticatedHeaderFate(fate, server_connection_id, header.form,
+ header.version_flag, header.version);
}
-
- return false;
}
void QuicDispatcher::ProcessUnauthenticatedHeaderFate(
QuicPacketFate fate,
- QuicConnectionId connection_id,
+ QuicConnectionId server_connection_id,
PacketHeaderFormat form,
+ bool version_flag,
ParsedQuicVersion version) {
switch (fate) {
case kFateProcess: {
@@ -502,36 +526,34 @@ void QuicDispatcher::ProcessUnauthenticatedHeaderFate(
break;
}
case kFateTimeWait:
- // MaybeRejectStatelessly or OnExpiredPackets might have already added the
- // connection to time wait, in which case it should not be added again.
- if (!GetQuicReloadableFlag(quic_use_cheap_stateless_rejects) ||
- !time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)) {
- // Add this connection_id to the time-wait state, to safely reject
- // future packets.
- QUIC_DLOG(INFO) << "Adding connection ID " << connection_id
- << " to time-wait list.";
- QUIC_CODE_COUNT(quic_reject_fate_time_wait);
- StatelesslyTerminateConnection(
- connection_id, form, version, QUIC_HANDSHAKE_FAILED,
- "Reject connection",
- quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
- }
- DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
+ // Add this connection_id to the time-wait state, to safely reject
+ // future packets.
+ QUIC_DLOG(INFO) << "Adding connection ID " << server_connection_id
+ << " to time-wait list.";
+ QUIC_CODE_COUNT(quic_reject_fate_time_wait);
+ StatelesslyTerminateConnection(
+ server_connection_id, form, version_flag, version,
+ QUIC_HANDSHAKE_FAILED, "Reject connection",
+ quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
+
+ DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(
+ server_connection_id));
time_wait_list_manager_->ProcessPacket(
- current_self_address_, current_peer_address_, connection_id, form,
- GetPerPacketContext());
+ current_self_address_, current_peer_address_, server_connection_id,
+ form, GetPerPacketContext());
// Any packets which were buffered while the stateless rejector logic was
// running should be discarded. Do not inform the time wait list manager,
// which should already have a made a decision about sending a reject
// based on the CHLO alone.
- buffered_packets_.DiscardPackets(connection_id);
+ buffered_packets_.DiscardPackets(server_connection_id);
break;
case kFateBuffer:
// This packet is a non-CHLO packet which has arrived before the
// corresponding CHLO, *or* this packet was received while the
// corresponding CHLO was being processed. Buffer it.
- BufferEarlyPacket(connection_id, form != GOOGLE_QUIC_PACKET, version);
+ BufferEarlyPacket(server_connection_id, form != GOOGLE_QUIC_PACKET,
+ version);
break;
case kFateDrop:
// Do nothing with the packet.
@@ -561,31 +583,38 @@ QuicDispatcher::QuicPacketFate QuicDispatcher::ValidityChecks(
return kFateTimeWait;
}
- // initial packet number of 0 is always invalid.
- if (!header.packet_number.IsInitialized()) {
- return kFateTimeWait;
+ if (no_framer_) {
+ // Let the connection parse and validate packet number.
+ return kFateProcess;
}
- if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
- QUIC_RESTART_FLAG_COUNT_N(quic_enable_accept_random_ipn, 1, 2);
- // Accepting Initial Packet Numbers in 1...((2^31)-1) range... check
- // maximum accordingly.
- if (header.packet_number > MaxRandomInitialPacketNumber()) {
+
+ // initial packet number of 0 is always invalid.
+ if (!framer_.version().HasHeaderProtection()) {
+ if (!header.packet_number.IsInitialized()) {
return kFateTimeWait;
}
- } else {
- // Count those that would have been accepted if FLAGS..random_ipn
- // were true -- to detect/diagnose potential issues prior to
- // enabling the flag.
- if ((header.packet_number >
- QuicPacketNumber(kMaxReasonableInitialPacketNumber)) &&
- (header.packet_number <= MaxRandomInitialPacketNumber())) {
- QUIC_CODE_COUNT_N(had_possibly_random_ipn, 1, 2);
- }
- // Check that the sequence number is within the range that the client is
- // expected to send before receiving a response from the server.
- if (header.packet_number >
- QuicPacketNumber(kMaxReasonableInitialPacketNumber)) {
- return kFateTimeWait;
+ if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
+ QUIC_RESTART_FLAG_COUNT_N(quic_enable_accept_random_ipn, 1, 2);
+ // Accepting Initial Packet Numbers in 1...((2^31)-1) range... check
+ // maximum accordingly.
+ if (header.packet_number > MaxRandomInitialPacketNumber()) {
+ return kFateTimeWait;
+ }
+ } else {
+ // Count those that would have been accepted if FLAGS..random_ipn
+ // were true -- to detect/diagnose potential issues prior to
+ // enabling the flag.
+ if ((header.packet_number >
+ QuicPacketNumber(kMaxReasonableInitialPacketNumber)) &&
+ (header.packet_number <= MaxRandomInitialPacketNumber())) {
+ QUIC_CODE_COUNT_N(had_possibly_random_ipn, 1, 2);
+ }
+ // Check that the sequence number is within the range that the client is
+ // expected to send before receiving a response from the server.
+ if (header.packet_number >
+ QuicPacketNumber(kMaxReasonableInitialPacketNumber)) {
+ return kFateTimeWait;
+ }
}
}
return kFateProcess;
@@ -605,15 +634,23 @@ void QuicDispatcher::CleanUpSession(SessionMap::iterator it,
if (connection->termination_packets() != nullptr &&
!connection->termination_packets()->empty()) {
action = QuicTimeWaitListManager::SEND_TERMINATION_PACKETS;
- } else if (connection->transport_version() > QUIC_VERSION_43) {
+ } else if (connection->transport_version() > QUIC_VERSION_43 ||
+ GetQuicReloadableFlag(quic_terminate_gquic_connection_as_ietf)) {
if (!connection->IsHandshakeConfirmed()) {
- QUIC_CODE_COUNT(quic_v44_add_to_time_wait_list_with_handshake_failed);
+ if (connection->transport_version() <= QUIC_VERSION_43) {
+ QUIC_CODE_COUNT(gquic_add_to_time_wait_list_with_handshake_failed);
+ } else {
+ QUIC_CODE_COUNT(quic_v44_add_to_time_wait_list_with_handshake_failed);
+ }
action = QuicTimeWaitListManager::SEND_TERMINATION_PACKETS;
// This serializes a connection close termination packet with error code
// QUIC_HANDSHAKE_FAILED and adds the connection to the time wait list.
StatelesslyTerminateConnection(
- connection->connection_id(), IETF_QUIC_LONG_HEADER_PACKET,
- connection->version(), QUIC_HANDSHAKE_FAILED,
+ connection->connection_id(),
+ connection->transport_version() > QUIC_VERSION_43
+ ? IETF_QUIC_LONG_HEADER_PACKET
+ : GOOGLE_QUIC_PACKET,
+ /*version_flag=*/true, connection->version(), QUIC_HANDSHAKE_FAILED,
"Connection is closed by server before handshake confirmed",
// Although it is our intention to send termination packets, the
// |action| argument is not used by this call to
@@ -695,13 +732,13 @@ void QuicDispatcher::Shutdown() {
DeleteSessions();
}
-void QuicDispatcher::OnConnectionClosed(QuicConnectionId connection_id,
+void QuicDispatcher::OnConnectionClosed(QuicConnectionId server_connection_id,
QuicErrorCode error,
const std::string& error_details,
ConnectionCloseSource source) {
- auto it = session_map_.find(connection_id);
+ auto it = session_map_.find(server_connection_id);
if (it == session_map_.end()) {
- QUIC_BUG << "ConnectionId " << connection_id
+ QUIC_BUG << "ConnectionId " << server_connection_id
<< " does not exist in the session map. Error: "
<< QuicErrorCodeToString(error);
QUIC_BUG << QuicStackTrace();
@@ -709,7 +746,7 @@ void QuicDispatcher::OnConnectionClosed(QuicConnectionId connection_id,
}
QUIC_DLOG_IF(INFO, error != QUIC_NO_ERROR)
- << "Closing connection (" << connection_id
+ << "Closing connection (" << server_connection_id
<< ") due to error: " << QuicErrorCodeToString(error)
<< ", with details: " << error_details;
@@ -748,53 +785,55 @@ void QuicDispatcher::OnRstStreamReceived(const QuicRstStreamFrame& frame) {}
void QuicDispatcher::OnStopSendingReceived(const QuicStopSendingFrame& frame) {}
void QuicDispatcher::OnConnectionAddedToTimeWaitList(
- QuicConnectionId connection_id) {
- QUIC_DLOG(INFO) << "Connection " << connection_id
+ QuicConnectionId server_connection_id) {
+ QUIC_DLOG(INFO) << "Connection " << server_connection_id
<< " added to time wait list.";
}
void QuicDispatcher::StatelesslyTerminateConnection(
- QuicConnectionId connection_id,
+ QuicConnectionId server_connection_id,
PacketHeaderFormat format,
+ bool version_flag,
ParsedQuicVersion version,
QuicErrorCode error_code,
const std::string& error_details,
QuicTimeWaitListManager::TimeWaitAction action) {
- if (format != IETF_QUIC_LONG_HEADER_PACKET) {
- QUIC_DVLOG(1) << "Statelessly terminating " << connection_id
+ if (format != IETF_QUIC_LONG_HEADER_PACKET &&
+ (!GetQuicReloadableFlag(quic_terminate_gquic_connection_as_ietf) ||
+ !version_flag)) {
+ QUIC_DVLOG(1) << "Statelessly terminating " << server_connection_id
<< " based on a non-ietf-long packet, action:" << action
<< ", error_code:" << error_code
<< ", error_details:" << error_details;
time_wait_list_manager_->AddConnectionIdToTimeWait(
- connection_id, format != GOOGLE_QUIC_PACKET, action, ENCRYPTION_INITIAL,
- nullptr);
+ server_connection_id, format != GOOGLE_QUIC_PACKET, action,
+ ENCRYPTION_INITIAL, nullptr);
return;
}
// If the version is known and supported by framer, send a connection close.
- if (framer_.IsSupportedVersion(version)) {
+ if (IsSupportedVersion(version)) {
QUIC_DVLOG(1)
- << "Statelessly terminating " << connection_id
+ << "Statelessly terminating " << server_connection_id
<< " based on an ietf-long packet, which has a supported version:"
<< version << ", error_code:" << error_code
<< ", error_details:" << error_details;
- // Set framer_ to the packet's version such that the connection close can be
- // processed by the client.
- ParsedQuicVersion original_version = framer_.version();
- framer_.set_version(version);
- StatelessConnectionTerminator terminator(
- connection_id, &framer_, helper_.get(), time_wait_list_manager_.get());
+ StatelessConnectionTerminator terminator(server_connection_id, version,
+ helper_.get(),
+ time_wait_list_manager_.get());
// This also adds the connection to time wait list.
- terminator.CloseConnection(error_code, error_details, true);
-
- // Restore framer_ to the original version, as if nothing changed in it.
- framer_.set_version(original_version);
+ if (format == GOOGLE_QUIC_PACKET) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_terminate_gquic_connection_as_ietf, 1,
+ 2);
+ }
+ terminator.CloseConnection(error_code, error_details,
+ format != GOOGLE_QUIC_PACKET);
return;
}
QUIC_DVLOG(1)
- << "Statelessly terminating " << connection_id
+ << "Statelessly terminating " << server_connection_id
<< " based on an ietf-long packet, which has an unsupported version:"
<< version << ", error_code:" << error_code
<< ", error_details:" << error_details;
@@ -802,10 +841,14 @@ void QuicDispatcher::StatelesslyTerminateConnection(
// with an empty version list, which can be understood by the client.
std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets;
termination_packets.push_back(QuicFramer::BuildVersionNegotiationPacket(
- connection_id, /*ietf_quic=*/true,
+ server_connection_id, EmptyQuicConnectionId(),
+ /*ietf_quic=*/format != GOOGLE_QUIC_PACKET,
ParsedQuicVersionVector{UnsupportedQuicVersion()}));
+ if (format == GOOGLE_QUIC_PACKET) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_terminate_gquic_connection_as_ietf, 2, 2);
+ }
time_wait_list_manager()->AddConnectionIdToTimeWait(
- connection_id, /*ietf_quic=*/true,
+ server_connection_id, /*ietf_quic=*/format != GOOGLE_QUIC_PACKET,
QuicTimeWaitListManager::SEND_TERMINATION_PACKETS, ENCRYPTION_INITIAL,
&termination_packets);
}
@@ -826,9 +869,10 @@ bool QuicDispatcher::ShouldCreateSessionForUnknownVersion(
bool QuicDispatcher::OnProtocolVersionMismatch(
ParsedQuicVersion /*received_version*/,
PacketHeaderFormat /*form*/) {
+ DCHECK(!no_framer_);
QUIC_BUG_IF(
!time_wait_list_manager_->IsConnectionIdInTimeWait(
- current_connection_id_) &&
+ current_server_connection_id_) &&
!ShouldCreateSessionForUnknownVersion(framer_.last_version_label()))
<< "Unexpected version mismatch: "
<< QuicVersionLabelToString(framer_.last_version_label());
@@ -848,6 +892,12 @@ void QuicDispatcher::OnVersionNegotiationPacket(
DCHECK(false);
}
+void QuicDispatcher::OnRetryPacket(QuicConnectionId /*original_connection_id*/,
+ QuicConnectionId /*new_connection_id*/,
+ QuicStringPiece /*retry_token*/) {
+ DCHECK(false);
+}
+
void QuicDispatcher::OnDecryptedPacket(EncryptionLevel level) {
DCHECK(false);
}
@@ -920,12 +970,12 @@ bool QuicDispatcher::OnConnectionCloseFrame(
return false;
}
-bool QuicDispatcher::OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) {
+bool QuicDispatcher::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
return true;
}
-bool QuicDispatcher::OnStreamIdBlockedFrame(
- const QuicStreamIdBlockedFrame& frame) {
+bool QuicDispatcher::OnStreamsBlockedFrame(
+ const QuicStreamsBlockedFrame& frame) {
return true;
}
@@ -999,15 +1049,15 @@ void QuicDispatcher::OnAuthenticatedIetfStatelessResetPacket(
}
void QuicDispatcher::OnExpiredPackets(
- QuicConnectionId connection_id,
+ QuicConnectionId server_connection_id,
BufferedPacketList early_arrived_packets) {
QUIC_CODE_COUNT(quic_reject_buffered_packets_expired);
StatelesslyTerminateConnection(
- connection_id,
+ server_connection_id,
early_arrived_packets.ietf_quic ? IETF_QUIC_LONG_HEADER_PACKET
: GOOGLE_QUIC_PACKET,
- early_arrived_packets.version, QUIC_HANDSHAKE_FAILED,
- "Packets buffered for too long",
+ /*version_flag=*/true, early_arrived_packets.version,
+ QUIC_HANDSHAKE_FAILED, "Packets buffered for too long",
quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
}
@@ -1016,24 +1066,26 @@ void QuicDispatcher::ProcessBufferedChlos(size_t max_connections_to_create) {
new_sessions_allowed_per_event_loop_ = max_connections_to_create;
for (; new_sessions_allowed_per_event_loop_ > 0;
--new_sessions_allowed_per_event_loop_) {
- QuicConnectionId connection_id;
+ QuicConnectionId server_connection_id;
BufferedPacketList packet_list =
- buffered_packets_.DeliverPacketsForNextConnection(&connection_id);
+ buffered_packets_.DeliverPacketsForNextConnection(
+ &server_connection_id);
const std::list<BufferedPacket>& packets = packet_list.buffered_packets;
if (packets.empty()) {
return;
}
- QuicConnectionId original_connection_id = connection_id;
- connection_id =
- MaybeReplaceConnectionId(connection_id, packet_list.version);
+ QuicConnectionId original_connection_id = server_connection_id;
+ server_connection_id = MaybeReplaceServerConnectionId(server_connection_id,
+ packet_list.version);
QuicSession* session =
- CreateQuicSession(connection_id, packets.front().peer_address,
+ CreateQuicSession(server_connection_id, packets.front().peer_address,
packet_list.alpn, packet_list.version);
- if (original_connection_id != connection_id) {
+ if (original_connection_id != server_connection_id) {
session->connection()->AddIncomingConnectionId(original_connection_id);
}
- QUIC_DLOG(INFO) << "Created new session for " << connection_id;
- session_map_.insert(std::make_pair(connection_id, QuicWrapUnique(session)));
+ QUIC_DLOG(INFO) << "Created new session for " << server_connection_id;
+ session_map_.insert(
+ std::make_pair(server_connection_id, QuicWrapUnique(session)));
DeliverPacketsToSession(packets, session);
}
}
@@ -1043,25 +1095,23 @@ bool QuicDispatcher::HasChlosBuffered() const {
}
bool QuicDispatcher::ShouldCreateOrBufferPacketForConnection(
- QuicConnectionId connection_id,
+ QuicConnectionId server_connection_id,
bool ietf_quic) {
- VLOG(1) << "Received packet from new connection " << connection_id;
+ QUIC_VLOG(1) << "Received packet from new connection "
+ << server_connection_id;
return true;
}
// Return true if there is any packet buffered in the store.
-bool QuicDispatcher::HasBufferedPackets(QuicConnectionId connection_id) {
- return buffered_packets_.HasBufferedPackets(connection_id);
+bool QuicDispatcher::HasBufferedPackets(QuicConnectionId server_connection_id) {
+ return buffered_packets_.HasBufferedPackets(server_connection_id);
}
-void QuicDispatcher::OnBufferPacketFailure(EnqueuePacketResult result,
- QuicConnectionId connection_id) {
- QUIC_DLOG(INFO) << "Fail to buffer packet on connection " << connection_id
- << " because of " << result;
-}
-
-bool QuicDispatcher::ShouldAttemptCheapStatelessRejection() {
- return true;
+void QuicDispatcher::OnBufferPacketFailure(
+ EnqueuePacketResult result,
+ QuicConnectionId server_connection_id) {
+ QUIC_DLOG(INFO) << "Fail to buffer packet on connection "
+ << server_connection_id << " because of " << result;
}
QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() {
@@ -1069,21 +1119,22 @@ QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() {
alarm_factory_.get());
}
-void QuicDispatcher::BufferEarlyPacket(QuicConnectionId connection_id,
+void QuicDispatcher::BufferEarlyPacket(QuicConnectionId server_connection_id,
bool ietf_quic,
ParsedQuicVersion version) {
- bool is_new_connection = !buffered_packets_.HasBufferedPackets(connection_id);
- if (is_new_connection &&
- !ShouldCreateOrBufferPacketForConnection(connection_id, ietf_quic)) {
+ bool is_new_connection =
+ !buffered_packets_.HasBufferedPackets(server_connection_id);
+ if (is_new_connection && !ShouldCreateOrBufferPacketForConnection(
+ server_connection_id, ietf_quic)) {
return;
}
EnqueuePacketResult rs = buffered_packets_.EnqueuePacket(
- connection_id, ietf_quic, *current_packet_, current_self_address_,
+ server_connection_id, ietf_quic, *current_packet_, current_self_address_,
current_peer_address_, /*is_chlo=*/false,
/*alpn=*/"", version);
if (rs != EnqueuePacketResult::SUCCESS) {
- OnBufferPacketFailure(rs, connection_id);
+ OnBufferPacketFailure(rs, server_connection_id);
}
}
@@ -1093,49 +1144,52 @@ void QuicDispatcher::ProcessChlo(PacketHeaderFormat form,
// Don't any create new connection.
QUIC_CODE_COUNT(quic_reject_stop_accepting_new_connections);
StatelesslyTerminateConnection(
- current_connection_id(), form, version, QUIC_HANDSHAKE_FAILED,
- "Stop accepting new connections",
+ current_server_connection_id(), form, /*version_flag=*/true, version,
+ QUIC_HANDSHAKE_FAILED, "Stop accepting new connections",
quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
// Time wait list will reject the packet correspondingly.
time_wait_list_manager()->ProcessPacket(
- current_self_address(), current_peer_address(), current_connection_id(),
- form, GetPerPacketContext());
+ current_self_address(), current_peer_address(),
+ current_server_connection_id(), form, GetPerPacketContext());
return;
}
- if (!buffered_packets_.HasBufferedPackets(current_connection_id_) &&
- !ShouldCreateOrBufferPacketForConnection(current_connection_id_,
+ if (!buffered_packets_.HasBufferedPackets(current_server_connection_id_) &&
+ !ShouldCreateOrBufferPacketForConnection(current_server_connection_id_,
form != GOOGLE_QUIC_PACKET)) {
return;
}
if (FLAGS_quic_allow_chlo_buffering &&
new_sessions_allowed_per_event_loop_ <= 0) {
// Can't create new session any more. Wait till next event loop.
- QUIC_BUG_IF(buffered_packets_.HasChloForConnection(current_connection_id_));
+ QUIC_BUG_IF(
+ buffered_packets_.HasChloForConnection(current_server_connection_id_));
EnqueuePacketResult rs = buffered_packets_.EnqueuePacket(
- current_connection_id_, form != GOOGLE_QUIC_PACKET, *current_packet_,
- current_self_address_, current_peer_address_,
- /*is_chlo=*/true, current_alpn_, framer_.version());
+ current_server_connection_id_, form != GOOGLE_QUIC_PACKET,
+ *current_packet_, current_self_address_, current_peer_address_,
+ /*is_chlo=*/true, current_alpn_, version);
if (rs != EnqueuePacketResult::SUCCESS) {
- OnBufferPacketFailure(rs, current_connection_id_);
+ OnBufferPacketFailure(rs, current_server_connection_id_);
}
return;
}
- QuicConnectionId original_connection_id = current_connection_id_;
- current_connection_id_ =
- MaybeReplaceConnectionId(current_connection_id_, framer_.version());
+ QuicConnectionId original_connection_id = current_server_connection_id_;
+ current_server_connection_id_ =
+ MaybeReplaceServerConnectionId(current_server_connection_id_, version);
// Creates a new session and process all buffered packets for this connection.
QuicSession* session =
- CreateQuicSession(current_connection_id_, current_peer_address_,
- current_alpn_, framer_.version());
- if (original_connection_id != current_connection_id_) {
+ CreateQuicSession(current_server_connection_id_, current_peer_address_,
+ current_alpn_, version);
+ if (original_connection_id != current_server_connection_id_) {
session->connection()->AddIncomingConnectionId(original_connection_id);
}
- QUIC_DLOG(INFO) << "Created new session for " << current_connection_id_;
+ QUIC_DLOG(INFO) << "Created new session for "
+ << current_server_connection_id_;
session_map_.insert(
- std::make_pair(current_connection_id_, QuicWrapUnique(session)));
+ std::make_pair(current_server_connection_id_, QuicWrapUnique(session)));
std::list<BufferedPacket> packets =
- buffered_packets_.DeliverPackets(current_connection_id_).buffered_packets;
+ buffered_packets_.DeliverPackets(current_server_connection_id_)
+ .buffered_packets;
// Process CHLO at first.
session->ProcessUdpPacket(current_self_address_, current_peer_address_,
*current_packet_);
@@ -1163,221 +1217,31 @@ bool QuicDispatcher::OnUnauthenticatedUnknownPublicHeader(
return true;
}
-class StatelessRejectorProcessDoneCallback
- : public StatelessRejector::ProcessDoneCallback {
- public:
- StatelessRejectorProcessDoneCallback(QuicDispatcher* dispatcher,
- ParsedQuicVersion first_version,
- PacketHeaderFormat form)
- : dispatcher_(dispatcher),
- current_client_address_(dispatcher->current_client_address_),
- current_peer_address_(dispatcher->current_peer_address_),
- current_self_address_(dispatcher->current_self_address_),
- additional_context_(dispatcher->GetPerPacketContext()),
- current_packet_(
- dispatcher->current_packet_->Clone()), // Note: copies the packet
- first_version_(first_version),
- current_packet_format_(form) {}
-
- void Run(std::unique_ptr<StatelessRejector> rejector) override {
- if (additional_context_ != nullptr) {
- dispatcher_->RestorePerPacketContext(std::move(additional_context_));
- }
- dispatcher_->OnStatelessRejectorProcessDone(
- std::move(rejector), current_client_address_, current_peer_address_,
- current_self_address_, std::move(current_packet_), first_version_,
- current_packet_format_);
- }
-
- private:
- QuicDispatcher* dispatcher_;
- QuicSocketAddress current_client_address_;
- QuicSocketAddress current_peer_address_;
- QuicSocketAddress current_self_address_;
- // TODO(wub): Wrap all current_* variables into PerPacketContext. And rename
- // |additional_context_| to |context_|.
- std::unique_ptr<QuicPerPacketContext> additional_context_;
- std::unique_ptr<QuicReceivedPacket> current_packet_;
- ParsedQuicVersion first_version_;
- const PacketHeaderFormat current_packet_format_;
-};
-
-void QuicDispatcher::MaybeRejectStatelessly(QuicConnectionId connection_id,
-
- PacketHeaderFormat form,
- ParsedQuicVersion version) {
+void QuicDispatcher::ProcessOrBufferPacket(
+ QuicConnectionId server_connection_id,
+ PacketHeaderFormat form,
+ bool version_flag,
+ ParsedQuicVersion version) {
if (version.handshake_protocol == PROTOCOL_TLS1_3) {
- ProcessUnauthenticatedHeaderFate(kFateProcess, connection_id, form,
- version);
+ ProcessUnauthenticatedHeaderFate(kFateProcess, server_connection_id, form,
+ version_flag, version);
return;
// TODO(nharper): Support buffering non-ClientHello packets when using TLS.
}
- // TODO(rch): This logic should probably live completely inside the rejector.
- if (!FLAGS_quic_allow_chlo_buffering ||
- !GetQuicReloadableFlag(quic_use_cheap_stateless_rejects) ||
- !GetQuicReloadableFlag(enable_quic_stateless_reject_support) ||
- !ShouldAttemptCheapStatelessRejection()) {
- // Not use cheap stateless reject.
- ChloAlpnExtractor alpn_extractor;
- if (FLAGS_quic_allow_chlo_buffering &&
- !ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
- config_->create_session_tag_indicators(),
- &alpn_extractor, connection_id.length())) {
- // Buffer non-CHLO packets.
- ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id, form,
- version);
- return;
- }
- current_alpn_ = alpn_extractor.ConsumeAlpn();
- ProcessUnauthenticatedHeaderFate(kFateProcess, connection_id, form,
- version);
- return;
- }
- std::unique_ptr<StatelessRejector> rejector(new StatelessRejector(
- version, GetSupportedVersions(), crypto_config_, &compressed_certs_cache_,
- helper()->GetClock(), helper()->GetRandomGenerator(),
- current_packet_->length(), current_client_address_,
- current_self_address_));
- ChloValidator validator(session_helper_.get(), current_client_address_,
- current_peer_address_, current_self_address_,
- rejector.get());
- if (!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
+ ChloAlpnExtractor alpn_extractor;
+ if (FLAGS_quic_allow_chlo_buffering &&
+ !ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
config_->create_session_tag_indicators(),
- &validator, connection_id.length())) {
- ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id, form, version);
- return;
- }
- current_alpn_ = validator.ConsumeAlpn();
-
- if (!validator.can_accept()) {
- // This CHLO is prohibited by policy.
- QUIC_CODE_COUNT(quic_reject_cant_accept_chlo);
- StatelessConnectionTerminator terminator(connection_id, &framer_, helper(),
- time_wait_list_manager_.get());
- terminator.CloseConnection(QUIC_HANDSHAKE_FAILED, validator.error_details(),
- form != GOOGLE_QUIC_PACKET);
- QuicSession::RecordConnectionCloseAtServer(
- QUIC_HANDSHAKE_FAILED, ConnectionCloseSource::FROM_SELF);
- ProcessUnauthenticatedHeaderFate(kFateTimeWait, connection_id, form,
- version);
+ &alpn_extractor, server_connection_id.length())) {
+ // Buffer non-CHLO packets.
+ ProcessUnauthenticatedHeaderFate(kFateBuffer, server_connection_id, form,
+ version_flag, version);
return;
}
-
- // If we were able to make a decision about this CHLO based purely on the
- // information available in OnChlo, just invoke the done callback immediately.
- if (rejector->state() != StatelessRejector::UNKNOWN) {
- ProcessStatelessRejectorState(std::move(rejector),
- version.transport_version, form);
- return;
- }
-
- // Insert into set of connection IDs to buffer
- const bool ok =
- temporarily_buffered_connections_.insert(connection_id).second;
- QUIC_BUG_IF(!ok)
- << "Processing multiple stateless rejections for connection ID "
- << connection_id;
-
- // Continue stateless rejector processing
- std::unique_ptr<StatelessRejectorProcessDoneCallback> cb(
- new StatelessRejectorProcessDoneCallback(this, version, form));
- StatelessRejector::Process(std::move(rejector), std::move(cb));
-}
-
-void QuicDispatcher::OnStatelessRejectorProcessDone(
- std::unique_ptr<StatelessRejector> rejector,
- const QuicSocketAddress& current_client_address,
- const QuicSocketAddress& current_peer_address,
- const QuicSocketAddress& current_self_address,
- std::unique_ptr<QuicReceivedPacket> current_packet,
- ParsedQuicVersion first_version,
- PacketHeaderFormat current_packet_format) {
- // Reset current_* to correspond to the packet which initiated the stateless
- // reject logic.
- current_client_address_ = current_client_address;
- current_peer_address_ = current_peer_address;
- current_self_address_ = current_self_address;
- current_packet_ = current_packet.get();
- current_connection_id_ = rejector->connection_id();
- framer_.set_version(first_version);
-
- // Stop buffering packets on this connection
- const auto num_erased =
- temporarily_buffered_connections_.erase(rejector->connection_id());
- QUIC_BUG_IF(num_erased != 1) << "Completing stateless rejection logic for "
- "non-buffered connection ID "
- << rejector->connection_id();
-
- // If this connection has gone into time-wait during the async processing,
- // don't proceed.
- if (time_wait_list_manager_->IsConnectionIdInTimeWait(
- rejector->connection_id())) {
- time_wait_list_manager_->ProcessPacket(
- current_self_address, current_peer_address, rejector->connection_id(),
- current_packet_format, GetPerPacketContext());
- return;
- }
-
- ProcessStatelessRejectorState(std::move(rejector),
- first_version.transport_version,
- current_packet_format);
-}
-
-void QuicDispatcher::ProcessStatelessRejectorState(
- std::unique_ptr<StatelessRejector> rejector,
- QuicTransportVersion first_version,
- PacketHeaderFormat form) {
- QuicPacketFate fate;
- switch (rejector->state()) {
- case StatelessRejector::FAILED: {
- // There was an error processing the client hello.
- QUIC_CODE_COUNT(quic_reject_error_processing_chlo);
- StatelessConnectionTerminator terminator(rejector->connection_id(),
- &framer_, helper(),
- time_wait_list_manager_.get());
- terminator.CloseConnection(rejector->error(), rejector->error_details(),
- form != GOOGLE_QUIC_PACKET);
- fate = kFateTimeWait;
- break;
- }
-
- case StatelessRejector::UNSUPPORTED:
- // Cheap stateless rejects are not supported so process the packet.
- fate = kFateProcess;
- break;
-
- case StatelessRejector::ACCEPTED:
- // Contains a valid CHLO, so process the packet and create a connection.
- fate = kFateProcess;
- break;
-
- case StatelessRejector::REJECTED: {
- QUIC_BUG_IF(first_version != framer_.transport_version())
- << "SREJ: Client's version: " << QuicVersionToString(first_version)
- << " is different from current dispatcher framer's version: "
- << QuicVersionToString(framer_.transport_version());
- StatelessConnectionTerminator terminator(rejector->connection_id(),
- &framer_, helper(),
- time_wait_list_manager_.get());
- terminator.RejectConnection(
- rejector->reply().GetSerialized().AsStringPiece(),
- form != GOOGLE_QUIC_PACKET);
- QuicSession::RecordConnectionCloseAtServer(
- QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT,
- ConnectionCloseSource::FROM_SELF);
- OnConnectionRejectedStatelessly();
- fate = kFateTimeWait;
- break;
- }
-
- default:
- QUIC_BUG << "Rejector has invalid state " << rejector->state();
- fate = kFateDrop;
- break;
- }
- ProcessUnauthenticatedHeaderFate(fate, rejector->connection_id(), form,
- rejector->version());
+ current_alpn_ = alpn_extractor.ConsumeAlpn();
+ ProcessUnauthenticatedHeaderFate(kFateProcess, server_connection_id, form,
+ version_flag, version);
}
const QuicTransportVersionVector&
@@ -1399,7 +1263,22 @@ void QuicDispatcher::DeliverPacketsToSession(
}
void QuicDispatcher::DisableFlagValidation() {
- framer_.set_validate_flags(false);
+ if (!no_framer_) {
+ framer_.set_validate_flags(false);
+ }
+}
+
+bool QuicDispatcher::IsSupportedVersion(const ParsedQuicVersion version) {
+ if (!no_framer_) {
+ return framer_.IsSupportedVersion(version);
+ }
+ for (const ParsedQuicVersion& supported_version :
+ version_manager_->GetSupportedVersions()) {
+ if (version == supported_version) {
+ return true;
+ }
+ }
+ return false;
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h
index a6d7e37ca21..790d4d2b8ad 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
@@ -23,7 +23,6 @@
#include "net/third_party/quiche/src/quic/core/quic_session.h"
#include "net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h"
#include "net/third_party/quiche/src/quic/core/quic_version_manager.h"
-#include "net/third_party/quiche/src/quic/core/stateless_rejector.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
@@ -49,7 +48,7 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
std::unique_ptr<QuicConnectionHelperInterface> helper,
std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
- uint8_t expected_connection_id_length);
+ uint8_t expected_server_connection_id_length);
QuicDispatcher(const QuicDispatcher&) = delete;
QuicDispatcher& operator=(const QuicDispatcher&) = delete;
@@ -76,7 +75,7 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
// QuicSession::Visitor interface implementation (via inheritance of
// QuicTimeWaitListManager::Visitor):
// Ensure that the closed connection is cleaned up asynchronously.
- void OnConnectionClosed(QuicConnectionId connection_id,
+ void OnConnectionClosed(QuicConnectionId server_connection_id,
QuicErrorCode error,
const std::string& error_details,
ConnectionCloseSource source) override;
@@ -99,7 +98,8 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
// QuicTimeWaitListManager::Visitor interface implementation
// Called whenever the time wait list manager adds a new connection to the
// time-wait list.
- void OnConnectionAddedToTimeWaitList(QuicConnectionId connection_id) override;
+ void OnConnectionAddedToTimeWaitList(
+ QuicConnectionId server_connection_id) override;
using SessionMap = QuicUnorderedMap<QuicConnectionId,
std::unique_ptr<QuicSession>,
@@ -131,11 +131,15 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
// QuicFramerVisitorInterface implementation. Not expected to be called
// outside of this class.
+ // TODO(fayang): Make QuicDispatcher no longer implement
+ // QuicFramerVisitorInterface when deprecating
+ // quic_no_framer_object_in_dispatcher.
void OnPacket() override;
- // Called when the public header has been parsed.
+ // Called when the public header has been parsed. Returns false when just the
+ // public header is enough to dispatch the packet; true if the framer needs to
+ // continue parsing the packet.
bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override;
- // Called when the private header has been parsed of a data packet that is
- // destined for the time wait manager.
+ // Called when the private header has been parsed.
bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
void OnError(QuicFramer* framer) override;
bool OnProtocolVersionMismatch(ParsedQuicVersion received_version,
@@ -149,6 +153,9 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
void OnPublicResetPacket(const QuicPublicResetPacket& packet) override;
void OnVersionNegotiationPacket(
const QuicVersionNegotiationPacket& packet) override;
+ void OnRetryPacket(QuicConnectionId original_connection_id,
+ QuicConnectionId new_connection_id,
+ QuicStringPiece retry_token) override;
void OnDecryptedPacket(EncryptionLevel level) override;
bool OnPacketHeader(const QuicPacketHeader& header) override;
void OnCoalescedPacket(const QuicEncryptedPacket& packet) override;
@@ -169,8 +176,8 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
bool OnPathChallengeFrame(const QuicPathChallengeFrame& frame) override;
bool OnPathResponseFrame(const QuicPathResponseFrame& frame) override;
bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override;
- bool OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) override;
- bool OnStreamIdBlockedFrame(const QuicStreamIdBlockedFrame& frame) override;
+ bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override;
+ bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
bool OnBlockedFrame(const QuicBlockedFrame& frame) override;
bool OnNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame) override;
@@ -184,7 +191,7 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
const QuicIetfStatelessResetPacket& packet) override;
// QuicBufferedPacketStore::VisitorInterface implementation.
- void OnExpiredPackets(QuicConnectionId connection_id,
+ void OnExpiredPackets(QuicConnectionId server_connection_id,
QuicBufferedPacketStore::BufferedPacketList
early_arrived_packets) override;
@@ -195,17 +202,11 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
virtual bool HasChlosBuffered() const;
protected:
- virtual QuicSession* CreateQuicSession(QuicConnectionId connection_id,
+ virtual QuicSession* CreateQuicSession(QuicConnectionId server_connection_id,
const QuicSocketAddress& peer_address,
QuicStringPiece alpn,
const ParsedQuicVersion& version) = 0;
- // Called when a connection is rejected statelessly.
- virtual void OnConnectionRejectedStatelessly() {}
-
- // Returns true if cheap stateless rejection should be attempted.
- virtual bool ShouldAttemptCheapStatelessRejection();
-
// Values to be returned by ValidityChecks() to indicate what should be done
// with a packet. Fates with greater values are considered to be higher
// priority, in that if one validity check indicates a lower-valued fate and
@@ -231,9 +232,9 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
// will be owned by the dispatcher as time_wait_list_manager_
virtual QuicTimeWaitListManager* CreateQuicTimeWaitListManager();
- // Called when |connection_id| doesn't have an open connection yet, to buffer
- // |current_packet_| until it can be delivered to the connection.
- void BufferEarlyPacket(QuicConnectionId connection_id,
+ // Called when |server_connection_id| doesn't have an open connection yet,
+ // to buffer |current_packet_| until it can be delivered to the connection.
+ void BufferEarlyPacket(QuicConnectionId server_connection_id,
bool ietf_quic,
ParsedQuicVersion version);
@@ -262,8 +263,8 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
const ParsedQuicVersionVector& GetSupportedVersions();
- QuicConnectionId current_connection_id() const {
- return current_connection_id_;
+ QuicConnectionId current_server_connection_id() const {
+ return current_server_connection_id_;
}
const QuicSocketAddress& current_self_address() const {
return current_self_address_;
@@ -312,15 +313,15 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
// for CHLO. Returns true if a new connection should be created or its packets
// should be buffered, false otherwise.
virtual bool ShouldCreateOrBufferPacketForConnection(
- QuicConnectionId connection_id,
+ QuicConnectionId server_connection_id,
bool ietf_quic);
- bool HasBufferedPackets(QuicConnectionId connection_id);
+ bool HasBufferedPackets(QuicConnectionId server_connection_id);
// Called when BufferEarlyPacket() fail to buffer the packet.
virtual void OnBufferPacketFailure(
QuicBufferedPacketStore::EnqueuePacketResult result,
- QuicConnectionId connection_id);
+ QuicConnectionId server_connection_id);
// Removes the session from the session map and write blocked list, and adds
// the ConnectionId to the time-wait list. If |session_closed_statelessly| is
@@ -337,8 +338,9 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
// connection to time wait list or 2) directly add connection to time wait
// list with |action|.
void StatelesslyTerminateConnection(
- QuicConnectionId connection_id,
+ QuicConnectionId server_connection_id,
PacketHeaderFormat format,
+ bool version_flag,
ParsedQuicVersion version,
QuicErrorCode error_code,
const std::string& error_details,
@@ -354,33 +356,42 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
// If true, our framer will change its expected connection ID length
// to the received destination connection ID length of all IETF long headers.
- void SetShouldUpdateExpectedConnectionIdLength(
- bool should_update_expected_connection_id_length) {
- framer_.SetShouldUpdateExpectedConnectionIdLength(
- should_update_expected_connection_id_length);
+ void SetShouldUpdateExpectedServerConnectionIdLength(
+ bool should_update_expected_server_connection_id_length) {
+ if (!no_framer_) {
+ framer_.SetShouldUpdateExpectedServerConnectionIdLength(
+ should_update_expected_server_connection_id_length);
+ return;
+ }
+ should_update_expected_server_connection_id_length_ =
+ should_update_expected_server_connection_id_length;
}
// If true, the dispatcher will allow incoming initial packets that have
- // connection IDs shorter than 64 bits.
- void SetAllowShortInitialConnectionIds(
- bool allow_short_initial_connection_ids) {
- allow_short_initial_connection_ids_ = allow_short_initial_connection_ids;
+ // destination connection IDs shorter than 64 bits.
+ void SetAllowShortInitialServerConnectionIds(
+ bool allow_short_initial_server_connection_ids) {
+ allow_short_initial_server_connection_ids_ =
+ allow_short_initial_server_connection_ids;
}
private:
friend class test::QuicDispatcherPeer;
- friend class StatelessRejectorProcessDoneCallback;
typedef QuicUnorderedSet<QuicConnectionId, QuicConnectionIdHash>
QuicConnectionIdSet;
- // Attempts to reject the connection statelessly, if stateless rejects are
- // possible and if the current packet contains a CHLO message. Determines a
- // fate which describes what subsequent processing should be performed on the
- // packets, like ValidityChecks, and invokes ProcessUnauthenticatedHeaderFate.
- void MaybeRejectStatelessly(QuicConnectionId connection_id,
- PacketHeaderFormat form,
- ParsedQuicVersion version);
+ // Based on an unauthenticated packet header |header|, calls ValidityChecks
+ // and then ProcessUnauthenticatedHeaderFate.
+ void ProcessHeader(const QuicPacketHeader& header);
+
+ // TODO(wub): Move the body to ProcessHeader, then remove this function.
+ // Determine whether the current packet needs to be processed now or buffered
+ // for later processing, then invokes ProcessUnauthenticatedHeaderFate.
+ void ProcessOrBufferPacket(QuicConnectionId server_connection_id,
+ PacketHeaderFormat form,
+ bool version_flag,
+ ParsedQuicVersion version);
// Deliver |packets| to |session| for further processing.
void DeliverPacketsToSession(
@@ -390,37 +401,20 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
// Perform the appropriate actions on the current packet based on |fate| -
// either process, buffer, or drop it.
void ProcessUnauthenticatedHeaderFate(QuicPacketFate fate,
- QuicConnectionId connection_id,
+ QuicConnectionId server_connection_id,
PacketHeaderFormat form,
+ bool version_flag,
ParsedQuicVersion version);
- // Invoked when StatelessRejector::Process completes. |first_version| is the
- // version of the packet which initiated the stateless reject.
- // WARNING: This function can be called when a async proof returns, i.e. not
- // from a stack traceable to ProcessPacket().
- // TODO(fayang): maybe consider not using callback when there is no crypto
- // involved.
- void OnStatelessRejectorProcessDone(
- std::unique_ptr<StatelessRejector> rejector,
- const QuicSocketAddress& current_client_address,
- const QuicSocketAddress& current_peer_address,
- const QuicSocketAddress& current_self_address,
- std::unique_ptr<QuicReceivedPacket> current_packet,
- ParsedQuicVersion first_version,
- PacketHeaderFormat current_packet_format);
-
- // Examine the state of the rejector and decide what to do with the current
- // packet.
- void ProcessStatelessRejectorState(
- std::unique_ptr<StatelessRejector> rejector,
- QuicTransportVersion first_version,
- PacketHeaderFormat form);
-
// If the connection ID length is different from what the dispatcher expects,
// replace the connection ID with a random one of the right length,
// and save it to make sure the mapping is persistent.
- QuicConnectionId MaybeReplaceConnectionId(QuicConnectionId connection_id,
- ParsedQuicVersion version);
+ QuicConnectionId MaybeReplaceServerConnectionId(
+ QuicConnectionId server_connection_id,
+ ParsedQuicVersion version);
+
+ // Returns true if |version| is a supported protocol version.
+ bool IsSupportedVersion(const ParsedQuicVersion version);
void set_new_sessions_allowed_per_event_loop(
int16_t new_sessions_allowed_per_event_loop) {
@@ -481,7 +475,7 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
const QuicReceivedPacket* current_packet_;
// If |current_packet_| is a CHLO packet, the extracted alpn.
std::string current_alpn_;
- QuicConnectionId current_connection_id_;
+ QuicConnectionId current_server_connection_id_;
// Used to get the supported versions based on flag. Does not own.
QuicVersionManager* version_manager_;
@@ -500,8 +494,32 @@ class QuicDispatcher : public QuicTimeWaitListManager::Visitor,
bool accept_new_connections_;
// If false, the dispatcher follows the IETF spec and rejects packets with
- // invalid connection IDs lengths below 64 bits. If true they are allowed.
- bool allow_short_initial_connection_ids_;
+ // invalid destination connection IDs lengths below 64 bits.
+ // If true they are allowed.
+ bool allow_short_initial_server_connection_ids_;
+
+ // The last QUIC version label received. Used when no_framer_ is true.
+ // TODO(fayang): remove this member variable, instead, add an argument to
+ // OnUnauthenticatedPublicHeader when deprecating
+ // quic_no_framer_object_in_dispatcher.
+ QuicVersionLabel last_version_label_;
+
+ // IETF short headers contain a destination connection ID but do not
+ // encode its length. This variable contains the length we expect to read.
+ // This is also used to signal an error when a long header packet with
+ // different destination connection ID length is received when
+ // should_update_expected_server_connection_id_length_ is false and packet's
+ // version does not allow variable length connection ID. Used when no_framer_
+ // is true.
+ uint8_t expected_server_connection_id_length_;
+
+ // If true, change expected_server_connection_id_length_ to be the received
+ // destination connection ID length of all IETF long headers. Used when
+ // no_framer_ is true.
+ bool should_update_expected_server_connection_id_length_;
+
+ // Latched value of quic_no_framer_object_in_dispatcher.
+ const bool no_framer_;
};
} // namespace quic
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 1e646af3445..105bd0028d6 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
@@ -19,7 +19,6 @@
#include "net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/core/stateless_rejector.h"
#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
@@ -86,10 +85,8 @@ class TestQuicSpdyServerSession : public QuicServerSessionBase {
QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache) override {
- return new QuicCryptoServerStream(
- crypto_config, compressed_certs_cache,
- GetQuicReloadableFlag(enable_quic_stateless_reject_support), this,
- stream_helper());
+ return new QuicCryptoServerStream(crypto_config, compressed_certs_cache,
+ this, stream_helper());
}
void SetCryptoStream(QuicCryptoServerStream* crypto_stream) {
@@ -158,7 +155,7 @@ class TestDispatcher : public QuicDispatcher {
using QuicDispatcher::current_client_address;
using QuicDispatcher::current_peer_address;
using QuicDispatcher::current_self_address;
- using QuicDispatcher::SetAllowShortInitialConnectionIds;
+ using QuicDispatcher::SetAllowShortInitialServerConnectionIds;
using QuicDispatcher::writer;
};
@@ -195,7 +192,7 @@ class QuicDispatcherTest : public QuicTest {
: QuicDispatcherTest(crypto_test_utils::ProofSourceForTesting()) {}
ParsedQuicVersionVector AllSupportedVersionsIncludingTls() {
- SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
return AllSupportedVersions();
}
@@ -380,7 +377,7 @@ TEST_F(QuicDispatcherTest, TlsClientHelloCreatesSession) {
// TLS is only supported in versions 47 and greater.
return;
}
- FLAGS_quic_supports_tls_handshake = true;
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
EXPECT_CALL(*dispatcher_,
@@ -495,7 +492,7 @@ TEST_F(QuicDispatcherTest, StatelessVersionNegotiation) {
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_,
- SendVersionNegotiationPacket(_, _, _, _, _, _))
+ SendVersionNegotiationPacket(_, _, _, _, _, _, _))
.Times(1);
QuicTransportVersion version =
static_cast<QuicTransportVersion>(QuicTransportVersionMin() - 1);
@@ -514,7 +511,7 @@ TEST_F(QuicDispatcherTest, NoVersionNegotiationWithSmallPacket) {
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_,
- SendVersionNegotiationPacket(_, _, _, _, _, _))
+ SendVersionNegotiationPacket(_, _, _, _, _, _, _))
.Times(0);
QuicTransportVersion version =
static_cast<QuicTransportVersion>(QuicTransportVersionMin() - 1);
@@ -540,7 +537,7 @@ TEST_F(QuicDispatcherTest, VersionNegotiationWithoutChloSizeValidation) {
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_,
- SendVersionNegotiationPacket(_, _, _, _, _, _))
+ SendVersionNegotiationPacket(_, _, _, _, _, _, _))
.Times(1);
QuicTransportVersion version =
static_cast<QuicTransportVersion>(QuicTransportVersionMin() - 1);
@@ -688,7 +685,7 @@ TEST_F(QuicDispatcherTest, InvalidShortConnectionIdLengthReplaced) {
QuicUtils::CreateRandomConnectionId(mock_helper_.GetRandomGenerator());
// Disable validation of invalid short connection IDs.
- dispatcher_->SetAllowShortInitialConnectionIds(true);
+ dispatcher_->SetAllowShortInitialServerConnectionIds(true);
// Note that StrayPacketTruncatedConnectionId covers the case where the
// validation is still enabled.
@@ -815,6 +812,12 @@ TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) {
}
TEST_F(QuicDispatcherTest, TooBigSeqNoPacketToTimeWaitListManager) {
+ if (CurrentSupportedVersions().front().HasHeaderProtection() ||
+ GetQuicRestartFlag(quic_no_framer_object_in_dispatcher)) {
+ // When header protection is in use, we don't put packets in the time wait
+ // list manager based on packet number.
+ return;
+ }
CreateTimeWaitListManager();
SetQuicRestartFlag(quic_enable_accept_random_ipn, false);
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
@@ -850,7 +853,6 @@ TEST_F(QuicDispatcherTest, SupportedTransportVersionsChangeInFlight) {
static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
"Supported versions out of sync");
SetQuicReloadableFlag(quic_disable_version_39, false);
- SetQuicReloadableFlag(quic_enable_version_43, true);
SetQuicReloadableFlag(quic_enable_version_44, true);
SetQuicReloadableFlag(quic_enable_version_46, true);
SetQuicReloadableFlag(quic_enable_version_47, true);
@@ -1005,39 +1007,6 @@ TEST_F(QuicDispatcherTest, SupportedTransportVersionsChangeInFlight) {
SerializeCHLO(), CONNECTION_ID_PRESENT,
PACKET_4BYTE_PACKET_NUMBER, 1);
- // Turn off version 43.
- SetQuicReloadableFlag(quic_enable_version_43, false);
- connection_id = TestConnectionId(++conn_id);
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq"), _))
- .Times(0);
- ProcessPacket(client_address, connection_id, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43),
- SerializeCHLO(), CONNECTION_ID_PRESENT,
- PACKET_4BYTE_PACKET_NUMBER, 1);
-
- // Turn on version 43.
- SetQuicReloadableFlag(quic_enable_version_43, true);
- connection_id = TestConnectionId(++conn_id);
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq"), _))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, connection_id, client_address,
- &mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(connection_id, packet);
- })));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(connection_id, _));
- ProcessPacket(client_address, connection_id, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43),
- SerializeCHLO(), CONNECTION_ID_PRESENT,
- PACKET_4BYTE_PACKET_NUMBER, 1);
-
// Turn off version 39.
SetQuicReloadableFlag(quic_disable_version_39, true);
connection_id = TestConnectionId(++conn_id);
@@ -1079,12 +1048,10 @@ class MockQuicCryptoServerStream : public QuicCryptoServerStream {
QuicCompressedCertsCache* compressed_certs_cache,
QuicServerSessionBase* session,
QuicCryptoServerStream::Helper* helper)
- : QuicCryptoServerStream(
- &crypto_config,
- compressed_certs_cache,
- GetQuicReloadableFlag(enable_quic_stateless_reject_support),
- session,
- helper),
+ : QuicCryptoServerStream(&crypto_config,
+ compressed_certs_cache,
+ session,
+ helper),
handshake_confirmed_(false) {}
MockQuicCryptoServerStream(const MockQuicCryptoServerStream&) = delete;
MockQuicCryptoServerStream& operator=(const MockQuicCryptoServerStream&) =
@@ -1100,262 +1067,6 @@ class MockQuicCryptoServerStream : public QuicCryptoServerStream {
bool handshake_confirmed_;
};
-struct StatelessRejectTestParams {
- StatelessRejectTestParams(bool enable_stateless_rejects_via_flag,
- bool client_supports_statelesss_rejects,
- bool crypto_handshake_successful)
- : enable_stateless_rejects_via_flag(enable_stateless_rejects_via_flag),
- client_supports_statelesss_rejects(client_supports_statelesss_rejects),
- crypto_handshake_successful(crypto_handshake_successful) {}
-
- friend std::ostream& operator<<(std::ostream& os,
- const StatelessRejectTestParams& p) {
- os << "{ enable_stateless_rejects_via_flag: "
- << p.enable_stateless_rejects_via_flag << std::endl;
- os << " client_supports_statelesss_rejects: "
- << p.client_supports_statelesss_rejects << std::endl;
- os << " crypto_handshake_successful: " << p.crypto_handshake_successful
- << " }";
- return os;
- }
-
- // This only enables the stateless reject feature via the feature-flag.
- // This should be a no-op if the peer does not support them.
- bool enable_stateless_rejects_via_flag;
- // Whether or not the client supports stateless rejects.
- bool client_supports_statelesss_rejects;
- // Should the initial crypto handshake succeed or not.
- bool crypto_handshake_successful;
-};
-
-// Constructs various test permutations for stateless rejects.
-std::vector<StatelessRejectTestParams> GetStatelessRejectTestParams() {
- std::vector<StatelessRejectTestParams> params;
- for (bool enable_stateless_rejects_via_flag : {true, false}) {
- for (bool client_supports_statelesss_rejects : {true, false}) {
- for (bool crypto_handshake_successful : {true, false}) {
- params.push_back(StatelessRejectTestParams(
- enable_stateless_rejects_via_flag,
- client_supports_statelesss_rejects, crypto_handshake_successful));
- }
- }
- }
- return params;
-}
-
-class QuicDispatcherStatelessRejectTest
- : public QuicDispatcherTest,
- public testing::WithParamInterface<StatelessRejectTestParams> {
- public:
- QuicDispatcherStatelessRejectTest()
- : QuicDispatcherTest(), crypto_stream1_(nullptr) {}
-
- ~QuicDispatcherStatelessRejectTest() override {
- if (crypto_stream1_) {
- delete crypto_stream1_;
- }
- }
-
- // This test setup assumes that all testing will be done using
- // crypto_stream1_.
- void SetUp() override {
- QuicDispatcherTest::SetUp();
- SetQuicReloadableFlag(enable_quic_stateless_reject_support,
- GetParam().enable_stateless_rejects_via_flag);
- }
-
- // Returns true or false, depending on whether the server will emit
- // a stateless reject, depending upon the parameters of the test.
- bool ExpectStatelessReject() {
- return GetParam().enable_stateless_rejects_via_flag &&
- !GetParam().crypto_handshake_successful &&
- GetParam().client_supports_statelesss_rejects;
- }
-
- // Sets up dispatcher_, session1_, and crypto_stream1_ based on
- // the test parameters.
- QuicServerSessionBase* CreateSessionBasedOnTestParams(
- QuicConnectionId connection_id,
- const QuicSocketAddress& client_address) {
- CreateSession(dispatcher_.get(), config_, connection_id, client_address,
- &mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_);
-
- crypto_stream1_ = new MockQuicCryptoServerStream(
- crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
- session1_, session1_->stream_helper());
- session1_->SetCryptoStream(crypto_stream1_);
- crypto_stream1_->set_handshake_confirmed_for_testing(
- GetParam().crypto_handshake_successful);
- crypto_stream1_->SetPeerSupportsStatelessRejects(
- GetParam().client_supports_statelesss_rejects);
- return session1_;
- }
-
- MockQuicCryptoServerStream* crypto_stream1_;
-};
-
-// Parameterized test for stateless rejects. Should test all
-// combinations of enabling/disabling, reject/no-reject for stateless
-// rejects.
-INSTANTIATE_TEST_SUITE_P(QuicDispatcherStatelessRejectTests,
- QuicDispatcherStatelessRejectTest,
- ::testing::ValuesIn(GetStatelessRejectTestParams()));
-
-TEST_P(QuicDispatcherStatelessRejectTest, ParameterizedBasicTest) {
- CreateTimeWaitListManager();
-
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- QuicConnectionId connection_id = TestConnectionId(1);
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq"), _))
- .WillOnce(testing::Return(
- CreateSessionBasedOnTestParams(connection_id, client_address)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(connection_id, packet);
- })));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(connection_id, _))
- .Times(1);
-
- // Process the first packet for the connection.
- ProcessPacket(client_address, connection_id, true, SerializeCHLO());
- if (ExpectStatelessReject()) {
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- CloseConnection(QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, _, _));
- // If this is a stateless reject, the crypto stream will close the
- // connection.
- session1_->connection()->CloseConnection(
- QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, "stateless reject",
- ConnectionCloseBehavior::SILENT_CLOSE);
- }
-
- // Send a second packet and check the results. If this is a stateless reject,
- // the existing connection_id will go on the time-wait list.
- EXPECT_EQ(ExpectStatelessReject(),
- time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
- if (ExpectStatelessReject()) {
- // The second packet will be processed on the time-wait list.
- EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, _, connection_id, _, _))
- .Times(1);
- } else {
- // The second packet will trigger a packet-validation
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .Times(1)
- .WillOnce(WithArg<2>(
- Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(connection_id, packet);
- })));
- }
- ProcessPacket(client_address, connection_id, true, "data");
-}
-
-TEST_P(QuicDispatcherStatelessRejectTest, CheapRejects) {
- SetQuicReloadableFlag(quic_use_cheap_stateless_rejects, true);
- CreateTimeWaitListManager();
-
- QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- QuicConnectionId connection_id = TestConnectionId(1);
- if (GetParam().enable_stateless_rejects_via_flag) {
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(connection_id, client_address, _, _))
- .Times(0);
- } else {
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("h2"), _))
- .WillOnce(testing::Return(
- CreateSessionBasedOnTestParams(connection_id, client_address)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(connection_id, packet);
- })));
- }
-
- QUIC_LOG(INFO) << "ExpectStatelessReject: " << ExpectStatelessReject();
- QUIC_LOG(INFO) << "Params: " << GetParam();
- // Process the first packet for the connection.
- CryptoHandshakeMessage client_hello =
- crypto_test_utils::CreateCHLO({{"AEAD", "AESG"},
- {"KEXS", "C255"},
- {"COPT", "SREJ"},
- {"NONC", "1234567890123456789012"},
- {"ALPN", "h2"},
- {"VER\0", "Q025"}},
- kClientHelloMinimumSize);
-
- if (GetParam().enable_stateless_rejects_via_flag) {
- EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, _, connection_id, _, _))
- .Times(1);
- } else {
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(connection_id, _))
- .Times(1);
- }
- ProcessPacket(client_address, connection_id, true,
- std::string(client_hello.GetSerialized().AsStringPiece()));
-
- if (GetParam().enable_stateless_rejects_via_flag) {
- EXPECT_EQ(true,
- time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
- }
-}
-
-TEST_P(QuicDispatcherStatelessRejectTest, BufferNonChlo) {
- SetQuicReloadableFlag(quic_use_cheap_stateless_rejects, true);
- CreateTimeWaitListManager();
-
- const QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- const QuicConnectionId connection_id = TestConnectionId(1);
-
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(connection_id, _))
- .Times(1);
- ProcessPacket(client_address, connection_id, true, "NOT DATA FOR A CHLO");
-
- // Process the first packet for the connection.
- CryptoHandshakeMessage client_hello =
- crypto_test_utils::CreateCHLO({{"AEAD", "AESG"},
- {"KEXS", "C255"},
- {"NONC", "1234567890123456789012"},
- {"ALPN", "h3"},
- {"VER\0", "Q025"}},
- kClientHelloMinimumSize);
-
- // If stateless rejects are enabled then a connection will be created now
- // and the buffered packet will be processed
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("h3"), _))
- .WillOnce(testing::Return(
- CreateSessionBasedOnTestParams(connection_id, client_address)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, client_address, _))
- .WillOnce(WithArg<2>(
- Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(connection_id, packet);
- })));
- // Expect both packets to be passed to ProcessUdpPacket(). And one of them
- // is already expected in CreateSessionBasedOnTestParams().
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, client_address, _))
- .WillOnce(WithArg<2>(
- Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(connection_id, packet);
- })))
- .RetiresOnSaturation();
- ProcessPacket(client_address, connection_id, true,
- std::string(client_hello.GetSerialized().AsStringPiece()));
- EXPECT_FALSE(
- time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
-}
-
// Verify the stopgap test: Packets with truncated connection IDs should be
// dropped.
class QuicDispatcherTestStrayPacketConnectionId : public QuicDispatcherTest {};
@@ -1689,56 +1400,14 @@ TEST_F(QuicDispatcherWriteBlockedListTest,
MarkSession1Deleted();
}
-// Tests that bufferring packets works in stateful reject, expensive stateless
-// reject and cheap stateless reject.
-struct BufferedPacketStoreTestParams {
- BufferedPacketStoreTestParams(bool enable_stateless_rejects_via_flag,
- bool support_cheap_stateless_reject)
- : enable_stateless_rejects_via_flag(enable_stateless_rejects_via_flag),
- support_cheap_stateless_reject(support_cheap_stateless_reject) {}
-
- friend std::ostream& operator<<(std::ostream& os,
- const BufferedPacketStoreTestParams& p) {
- os << "{ enable_stateless_rejects_via_flag: "
- << p.enable_stateless_rejects_via_flag << std::endl;
- os << " support_cheap_stateless_reject: "
- << p.support_cheap_stateless_reject << " }";
- return os;
- }
-
- // This only enables the stateless reject feature via the feature-flag.
- // This should be a no-op if the peer does not support them.
- bool enable_stateless_rejects_via_flag;
- // Whether to do cheap stateless or not.
- bool support_cheap_stateless_reject;
-};
-
-std::vector<BufferedPacketStoreTestParams> GetBufferedPacketStoreTestParams() {
- std::vector<BufferedPacketStoreTestParams> params;
- for (bool enable_stateless_rejects_via_flag : {true, false}) {
- for (bool support_cheap_stateless_reject : {true, false}) {
- params.push_back(BufferedPacketStoreTestParams(
- enable_stateless_rejects_via_flag, support_cheap_stateless_reject));
- }
- }
- return params;
-}
-
// A dispatcher whose stateless rejector will always ACCEPTs CHLO.
-class BufferedPacketStoreTest
- : public QuicDispatcherTest,
- public testing::WithParamInterface<BufferedPacketStoreTestParams> {
+class BufferedPacketStoreTest : public QuicDispatcherTest {
public:
BufferedPacketStoreTest()
: QuicDispatcherTest(),
server_addr_(QuicSocketAddress(QuicIpAddress::Any4(), 5)),
client_addr_(QuicIpAddress::Loopback4(), 1234),
- signed_config_(new QuicSignedServerConfig) {
- SetQuicReloadableFlag(quic_use_cheap_stateless_rejects,
- GetParam().support_cheap_stateless_reject);
- SetQuicReloadableFlag(enable_quic_stateless_reject_support,
- GetParam().enable_stateless_rejects_via_flag);
- }
+ signed_config_(new QuicSignedServerConfig) {}
void SetUp() override {
QuicDispatcherTest::SetUp();
@@ -1748,7 +1417,6 @@ class BufferedPacketStoreTest
CryptoHandshakeMessage chlo =
crypto_test_utils::GenerateDefaultInchoateCHLO(clock_, version,
&crypto_config_);
- chlo.SetVector(kCOPT, QuicTagVector{kSREJ});
// Pass an inchoate CHLO.
crypto_test_utils::GenerateFullCHLO(
chlo, &crypto_config_, server_addr_, client_addr_, version, clock_,
@@ -1768,12 +1436,7 @@ class BufferedPacketStoreTest
CryptoHandshakeMessage full_chlo_;
};
-INSTANTIATE_TEST_SUITE_P(
- BufferedPacketStoreTests,
- BufferedPacketStoreTest,
- ::testing::ValuesIn(GetBufferedPacketStoreTestParams()));
-
-TEST_P(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
+TEST_F(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
InSequence s;
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId conn_id = TestConnectionId(1);
@@ -1812,7 +1475,7 @@ TEST_P(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
}
-TEST_P(BufferedPacketStoreTest,
+TEST_F(BufferedPacketStoreTest,
ProcessNonChloPacketsForDifferentConnectionsUptoLimit) {
InSequence s;
// A bunch of non-CHLO should be buffered upon arrival.
@@ -1866,7 +1529,7 @@ TEST_P(BufferedPacketStoreTest,
}
// Tests that store delivers empty packet list if CHLO arrives firstly.
-TEST_P(BufferedPacketStoreTest, DeliverEmptyPackets) {
+TEST_F(BufferedPacketStoreTest, DeliverEmptyPackets) {
QuicConnectionId conn_id = TestConnectionId(1);
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
EXPECT_CALL(*dispatcher_,
@@ -1884,7 +1547,7 @@ TEST_P(BufferedPacketStoreTest, DeliverEmptyPackets) {
// Tests that a retransmitted CHLO arrives after a connection for the
// CHLO has been created.
-TEST_P(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) {
+TEST_F(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) {
InSequence s;
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId conn_id = TestConnectionId(1);
@@ -1914,7 +1577,7 @@ TEST_P(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) {
}
// Tests that expiration of a connection add connection id to time wait list.
-TEST_P(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) {
+TEST_F(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) {
InSequence s;
CreateTimeWaitListManager();
QuicBufferedPacketStore* store =
@@ -1940,7 +1603,7 @@ TEST_P(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) {
ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
}
-TEST_P(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
+TEST_F(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
// Process more than (|kMaxNumSessionsToCreate| +
// |kDefaultMaxConnectionsInStore|) CHLOs,
// the first |kMaxNumSessionsToCreate| should create connections immediately,
@@ -2017,7 +1680,7 @@ TEST_P(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
}
// Duplicated CHLO shouldn't be buffered.
-TEST_P(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
+TEST_F(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
for (uint64_t conn_id = 1; conn_id <= kMaxNumSessionsToCreate + 1;
++conn_id) {
// Last CHLO will be buffered. Others will create connection right away.
@@ -2066,7 +1729,7 @@ TEST_P(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
}
-TEST_P(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
+TEST_F(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
uint64_t last_conn_id = kMaxNumSessionsToCreate + 1;
QuicConnectionId last_connection_id = TestConnectionId(last_conn_id);
for (uint64_t conn_id = 1; conn_id <= last_conn_id; ++conn_id) {
@@ -2120,7 +1783,7 @@ TEST_P(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
// Tests that when dispatcher's packet buffer is full, a CHLO on connection
// which doesn't have buffered CHLO should be buffered.
-TEST_P(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) {
+TEST_F(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) {
QuicBufferedPacketStore* store =
QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
@@ -2165,7 +1828,7 @@ TEST_P(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) {
}
// Regression test for b/117874922.
-TEST_P(BufferedPacketStoreTest, ProcessBufferedChloWithDifferentVersion) {
+TEST_F(BufferedPacketStoreTest, ProcessBufferedChloWithDifferentVersion) {
// Turn off version 99, such that the preferred version is not supported by
// the server.
SetQuicReloadableFlag(quic_enable_version_99, false);
@@ -2219,667 +1882,6 @@ TEST_P(BufferedPacketStoreTest, ProcessBufferedChloWithDifferentVersion) {
dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
}
-// Test which exercises the async GetProof codepaths, especially in the context
-// of stateless rejection.
-class AsyncGetProofTest : public QuicDispatcherTest {
- public:
- AsyncGetProofTest()
- : QuicDispatcherTest(
- std::unique_ptr<FakeProofSource>(new FakeProofSource())),
- client_addr_(QuicIpAddress::Loopback4(), 1234),
- client_addr_2_(QuicIpAddress::Loopback4(), 1357),
- crypto_config_peer_(&crypto_config_),
- server_addr_(QuicIpAddress::Any4(), 5),
- signed_config_(new QuicSignedServerConfig) {
- SetQuicReloadableFlag(enable_quic_stateless_reject_support, true);
- SetQuicReloadableFlag(quic_use_cheap_stateless_rejects, true);
- }
-
- void SetUp() override {
- QuicDispatcherTest::SetUp();
-
- clock_ = QuicDispatcherPeer::GetHelper(dispatcher_.get())->GetClock();
- QuicTransportVersion version = AllSupportedTransportVersions().front();
- chlo_ = crypto_test_utils::GenerateDefaultInchoateCHLO(clock_, version,
- &crypto_config_);
- chlo_.SetVector(kCOPT, QuicTagVector{kSREJ});
- chlo_.SetStringPiece(kALPN, "HTTP/1");
- // Pass an inchoate CHLO.
- crypto_test_utils::GenerateFullCHLO(
- chlo_, &crypto_config_, server_addr_, client_addr_, version, clock_,
- signed_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
- &full_chlo_);
-
- crypto_test_utils::GenerateFullCHLO(
- chlo_, &crypto_config_, server_addr_, client_addr_2_, version, clock_,
- signed_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
- &full_chlo_2_);
-
- GetFakeProofSource()->Activate();
- }
-
- FakeProofSource* GetFakeProofSource() const {
- return static_cast<FakeProofSource*>(crypto_config_peer_.GetProofSource());
- }
-
- std::string SerializeFullCHLO() {
- return std::string(full_chlo_.GetSerialized().AsStringPiece());
- }
-
- std::string SerializeFullCHLOForClient2() {
- return std::string(full_chlo_2_.GetSerialized().AsStringPiece());
- }
-
- std::string SerializeCHLO() {
- return std::string(chlo_.GetSerialized().AsStringPiece());
- }
-
- // Sets up a session, and crypto stream based on the test parameters.
- QuicServerSessionBase* GetSession(QuicConnectionId connection_id,
- QuicSocketAddress client_address) {
- auto it = sessions_.find(connection_id);
- if (it != sessions_.end()) {
- return it->second.session;
- }
-
- TestQuicSpdyServerSession* session;
- CreateSession(dispatcher_.get(), config_, connection_id, client_address,
- &mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session);
-
- std::unique_ptr<MockQuicCryptoServerStream> crypto_stream(
- new MockQuicCryptoServerStream(
- crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
- session, session->stream_helper()));
- session->SetCryptoStream(crypto_stream.get());
- crypto_stream->SetPeerSupportsStatelessRejects(true);
- const bool ok =
- sessions_
- .insert(std::make_pair(
- connection_id, SessionInfo{session, std::move(crypto_stream)}))
- .second;
- CHECK(ok);
- return session;
- }
-
- protected:
- const QuicSocketAddress client_addr_;
- const QuicSocketAddress client_addr_2_;
- CryptoHandshakeMessage chlo_;
-
- private:
- QuicCryptoServerConfigPeer crypto_config_peer_;
- QuicSocketAddress server_addr_;
- QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
- const QuicClock* clock_;
- CryptoHandshakeMessage full_chlo_; // CHLO for client_addr_
- CryptoHandshakeMessage full_chlo_2_; // CHLO for client_addr_2_
-
- struct SessionInfo {
- TestQuicSpdyServerSession* session;
- std::unique_ptr<MockQuicCryptoServerStream> crypto_stream;
- };
- std::map<QuicConnectionId, SessionInfo> sessions_;
-};
-
-// Test a simple situation of connections which the StatelessRejector will
-// accept.
-TEST_F(AsyncGetProofTest, BasicAccept) {
- QuicConnectionId conn_id = TestConnectionId(1);
-
- testing::MockFunction<void(int check_point)> check;
- {
- InSequence s;
-
- EXPECT_CALL(check, Call(1));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(conn_id, _));
- EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_addr_,
- QuicStringPiece("HTTP/1"), _))
- .WillOnce(testing::Return(GetSession(conn_id, client_addr_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
- GetSession(conn_id, client_addr_)->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id, packet);
- })));
-
- EXPECT_CALL(check, Call(2));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
- GetSession(conn_id, client_addr_)->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id, packet);
- })));
- }
-
- // Send a CHLO that the StatelessRejector will accept.
- ProcessPacket(client_addr_, conn_id, true, SerializeFullCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-
- check.Call(1);
- // Complete the ProofSource::GetProof call and verify that a session is
- // created.
- GetFakeProofSource()->InvokePendingCallback(0);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
-
- check.Call(2);
- // Verify that a data packet gets processed immediately.
- ProcessPacket(client_addr_, conn_id, true, "My name is Data");
-}
-
-TEST_F(AsyncGetProofTest, RestorePacketContext) {
- QuicConnectionId conn_id_1 = TestConnectionId(1);
- QuicConnectionId conn_id_2 = TestConnectionId(2);
-
- testing::MockFunction<void(int check_point)> check;
- {
- InSequence s;
- EXPECT_CALL(check, Call(1));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(conn_id_1, _));
-
- EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_1, client_addr_,
- QuicStringPiece("HTTP/1"), _))
- .WillOnce(testing::Return(GetSession(conn_id_1, client_addr_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
- GetSession(conn_id_1, client_addr_)->connection()),
- ProcessUdpPacket(_, _, _))
- .WillRepeatedly(WithArg<2>(
- Invoke([this, conn_id_1](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id_1, packet);
- })));
-
- EXPECT_CALL(check, Call(2));
-
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(conn_id_2, _));
- EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_2, client_addr_2_,
- QuicStringPiece("HTTP/1"), _))
- .WillOnce(testing::Return(GetSession(conn_id_2, client_addr_2_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
- GetSession(conn_id_2, client_addr_2_)->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, conn_id_2](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id_2, packet);
- })));
- }
-
- // Send a CHLO that the StatelessRejector will accept.
- dispatcher_->custom_packet_context_ = "connection 1";
- ProcessPacket(client_addr_, conn_id_1, true, SerializeFullCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-
- // Send another CHLO that the StatelessRejector will accept.
- dispatcher_->custom_packet_context_ = "connection 2";
- ProcessPacket(client_addr_2_, conn_id_2, true, SerializeFullCHLOForClient2());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2);
-
- // Complete the first ProofSource::GetProof call and verify that a session is
- // created.
- check.Call(1);
-
- EXPECT_EQ(client_addr_2_, dispatcher_->current_client_address());
- EXPECT_EQ(client_addr_2_, dispatcher_->current_peer_address());
- EXPECT_EQ("connection 2", dispatcher_->custom_packet_context_);
-
- // Runs the async proof callback for conn_id_1 from client_addr_.
- GetFakeProofSource()->InvokePendingCallback(0);
-
- EXPECT_EQ(client_addr_, dispatcher_->current_client_address());
- EXPECT_EQ(client_addr_, dispatcher_->current_peer_address());
- EXPECT_EQ("connection 1", dispatcher_->custom_packet_context_);
-
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-
- // Complete the second ProofSource::GetProof call and verify that a session is
- // created.
- check.Call(2);
-
- EXPECT_EQ(client_addr_, dispatcher_->current_client_address());
- EXPECT_EQ(client_addr_, dispatcher_->current_peer_address());
- EXPECT_EQ("connection 1", dispatcher_->custom_packet_context_);
-
- // Runs the async proof callback for conn_id_2 from client_addr_2_.
- GetFakeProofSource()->InvokePendingCallback(0);
-
- EXPECT_EQ(client_addr_2_, dispatcher_->current_client_address());
- EXPECT_EQ(client_addr_2_, dispatcher_->current_peer_address());
- EXPECT_EQ("connection 2", dispatcher_->custom_packet_context_);
-
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
-}
-
-// Test a simple situation of connections which the StatelessRejector will
-// reject.
-TEST_F(AsyncGetProofTest, BasicReject) {
- CreateTimeWaitListManager();
-
- QuicConnectionId conn_id = TestConnectionId(1);
-
- testing::MockFunction<void(int check_point)> check;
- {
- InSequence s;
- EXPECT_CALL(check, Call(1));
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(conn_id, _, _, _, _));
- EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, client_addr_, conn_id, _, _));
-
- EXPECT_CALL(check, Call(2));
- EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_addr_,
- QuicStringPiece("hq"), _))
- .Times(0);
- EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, client_addr_, conn_id, _, _));
- }
-
- // Send a CHLO that the StatelessRejector will reject.
- ProcessPacket(client_addr_, conn_id, true, SerializeCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-
- // Complete the ProofSource::GetProof call and verify that the connection and
- // packet are processed by the time wait list manager.
- check.Call(1);
- GetFakeProofSource()->InvokePendingCallback(0);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
-
- // Verify that a data packet is passed to the time wait list manager.
- check.Call(2);
- ProcessPacket(client_addr_, conn_id, true, "My name is Data");
-}
-
-// Test a situation with multiple interleaved connections which the
-// StatelessRejector will accept.
-TEST_F(AsyncGetProofTest, MultipleAccept) {
- QuicConnectionId conn_id_1 = TestConnectionId(1);
- QuicConnectionId conn_id_2 = TestConnectionId(2);
- QuicBufferedPacketStore* store =
- QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
-
- testing::MockFunction<void(int check_point)> check;
- {
- InSequence s;
- EXPECT_CALL(check, Call(1));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(conn_id_2, _));
- EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_2, client_addr_,
- QuicStringPiece("HTTP/1"), _))
- .WillOnce(testing::Return(GetSession(conn_id_2, client_addr_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
- GetSession(conn_id_2, client_addr_)->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, conn_id_2](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id_2, packet);
- })));
-
- EXPECT_CALL(check, Call(2));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
- GetSession(conn_id_2, client_addr_)->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, conn_id_2](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id_2, packet);
- })));
-
- EXPECT_CALL(check, Call(3));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(conn_id_1, _));
-
- EXPECT_CALL(check, Call(4));
- EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_1, client_addr_,
- QuicStringPiece("HTTP/1"), _))
- .WillOnce(testing::Return(GetSession(conn_id_1, client_addr_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
- GetSession(conn_id_1, client_addr_)->connection()),
- ProcessUdpPacket(_, _, _))
- .WillRepeatedly(WithArg<2>(
- Invoke([this, conn_id_1](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id_1, packet);
- })));
- }
-
- // Send a CHLO that the StatelessRejector will accept.
- ProcessPacket(client_addr_, conn_id_1, true, SerializeFullCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-
- // Send another CHLO that the StatelessRejector will accept.
- ProcessPacket(client_addr_, conn_id_2, true, SerializeFullCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2);
-
- // Complete the second ProofSource::GetProof call and verify that a session is
- // created.
- check.Call(1);
- GetFakeProofSource()->InvokePendingCallback(1);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-
- // Verify that a data packet on that connection gets processed immediately.
- check.Call(2);
- ProcessPacket(client_addr_, conn_id_2, true, "My name is Data");
-
- // Verify that a data packet on the other connection does not get processed
- // yet.
- check.Call(3);
- ProcessPacket(client_addr_, conn_id_1, true, "My name is Data");
- EXPECT_TRUE(store->HasBufferedPackets(conn_id_1));
- EXPECT_FALSE(store->HasBufferedPackets(conn_id_2));
-
- // Complete the first ProofSource::GetProof call and verify that a session is
- // created and the buffered packet is processed.
- check.Call(4);
- GetFakeProofSource()->InvokePendingCallback(0);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
-}
-
-// Test a situation with multiple interleaved connections which the
-// StatelessRejector will reject.
-TEST_F(AsyncGetProofTest, MultipleReject) {
- CreateTimeWaitListManager();
-
- QuicConnectionId conn_id_1 = TestConnectionId(1);
- QuicConnectionId conn_id_2 = TestConnectionId(2);
- QuicBufferedPacketStore* store =
- QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
-
- testing::MockFunction<void(int check_point)> check;
- {
- InSequence s;
-
- EXPECT_CALL(check, Call(1));
- EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_2, client_addr_, _, _))
- .Times(0);
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(conn_id_2, _, _, _, _));
- EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, client_addr_, conn_id_2, _, _));
-
- EXPECT_CALL(check, Call(2));
- EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, client_addr_, conn_id_2, _, _));
-
- EXPECT_CALL(check, Call(3));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(conn_id_1, _));
-
- EXPECT_CALL(check, Call(4));
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(conn_id_1, _, _, _, _));
- EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, client_addr_, conn_id_1, _, _));
- }
-
- // Send a CHLO that the StatelessRejector will reject.
- ProcessPacket(client_addr_, conn_id_1, true, SerializeCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-
- // Send another CHLO that the StatelessRejector will reject.
- ProcessPacket(client_addr_, conn_id_2, true, SerializeCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2);
-
- // Complete the second ProofSource::GetProof call and verify that the
- // connection and packet are processed by the time wait manager.
- check.Call(1);
- GetFakeProofSource()->InvokePendingCallback(1);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-
- // Verify that a data packet on that connection gets processed immediately by
- // the time wait manager.
- check.Call(2);
- ProcessPacket(client_addr_, conn_id_2, true, "My name is Data");
-
- // Verify that a data packet on the first connection gets buffered.
- check.Call(3);
- ProcessPacket(client_addr_, conn_id_1, true, "My name is Data");
- EXPECT_TRUE(store->HasBufferedPackets(conn_id_1));
- EXPECT_FALSE(store->HasBufferedPackets(conn_id_2));
-
- // Complete the first ProofSource::GetProof call and verify that the CHLO is
- // processed by the time wait manager and the remaining packets are discarded.
- check.Call(4);
- GetFakeProofSource()->InvokePendingCallback(0);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
- EXPECT_FALSE(store->HasBufferedPackets(conn_id_1));
- EXPECT_FALSE(store->HasBufferedPackets(conn_id_2));
-}
-
-// Test a situation with multiple identical CHLOs which the StatelessRejector
-// will reject.
-TEST_F(AsyncGetProofTest, MultipleIdenticalReject) {
- CreateTimeWaitListManager();
-
- QuicConnectionId conn_id_1 = TestConnectionId(1);
- QuicBufferedPacketStore* store =
- QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
-
- testing::MockFunction<void(int check_point)> check;
- {
- InSequence s;
- EXPECT_CALL(check, Call(1));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(conn_id_1, _));
-
- EXPECT_CALL(check, Call(2));
- EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_1, client_addr_,
- QuicStringPiece(), _))
- .Times(0);
- EXPECT_CALL(*time_wait_list_manager_,
- AddConnectionIdToTimeWait(conn_id_1, _, _, _, _));
- EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, client_addr_, conn_id_1, _, _));
- }
-
- // Send a CHLO that the StatelessRejector will reject.
- ProcessPacket(client_addr_, conn_id_1, true, SerializeCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
- EXPECT_FALSE(store->HasBufferedPackets(conn_id_1));
-
- // Send an identical CHLO which should get buffered.
- check.Call(1);
- ProcessPacket(client_addr_, conn_id_1, true, SerializeCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
- EXPECT_TRUE(store->HasBufferedPackets(conn_id_1));
-
- // Complete the ProofSource::GetProof call and verify that the CHLO is
- // rejected and the copy is discarded.
- check.Call(2);
- GetFakeProofSource()->InvokePendingCallback(0);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
- EXPECT_FALSE(store->HasBufferedPackets(conn_id_1));
-}
-
-// Test dispatcher behavior when packets time out of the buffer while CHLO
-// validation is still pending.
-TEST_F(AsyncGetProofTest, BufferTimeout) {
- CreateTimeWaitListManager();
-
- QuicConnectionId conn_id = TestConnectionId(1);
- QuicBufferedPacketStore* store =
- QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
- QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock());
-
- testing::MockFunction<void(int check_point)> check;
- {
- InSequence s;
- EXPECT_CALL(check, Call(1));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(conn_id, _));
-
- EXPECT_CALL(check, Call(2));
- EXPECT_CALL(*time_wait_list_manager_,
- ProcessPacket(_, client_addr_, conn_id, _, _));
- EXPECT_CALL(*dispatcher_,
- CreateQuicSession(conn_id, client_addr_, QuicStringPiece(), _))
- .Times(0);
- }
-
- // Send a CHLO that the StatelessRejector will accept.
- ProcessPacket(client_addr_, conn_id, true, SerializeFullCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
- EXPECT_FALSE(store->HasBufferedPackets(conn_id));
-
- // Send a data packet that will get buffered
- check.Call(1);
- ProcessPacket(client_addr_, conn_id, true, "My name is Data");
- EXPECT_TRUE(store->HasBufferedPackets(conn_id));
-
- // Pretend that enough time has gone by for the packets to get expired out of
- // the buffer
- mock_helper_.AdvanceTime(
- QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs));
- QuicBufferedPacketStorePeer::expiration_alarm(store)->Cancel();
- store->OnExpirationTimeout();
- EXPECT_FALSE(store->HasBufferedPackets(conn_id));
- EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
-
- // Now allow the CHLO validation to complete, and verify that no connection
- // gets created.
- check.Call(2);
- GetFakeProofSource()->InvokePendingCallback(0);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
- EXPECT_FALSE(store->HasBufferedPackets(conn_id));
- EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
-}
-
-// Test behavior when packets time out of the buffer *and* the connection times
-// out of the time wait manager while CHLO validation is still pending. This
-// *should* be impossible, but anything can happen with timing conditions.
-TEST_F(AsyncGetProofTest, TimeWaitTimeout) {
- QuicConnectionId conn_id = TestConnectionId(1);
- QuicBufferedPacketStore* store =
- QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
- QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock());
- CreateTimeWaitListManager();
- QuicTimeWaitListManagerPeer::set_clock(time_wait_list_manager_,
- mock_helper_.GetClock());
-
- testing::MockFunction<void(int check_point)> check;
- {
- InSequence s;
- EXPECT_CALL(check, Call(1));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(conn_id, _));
-
- EXPECT_CALL(check, Call(2));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(conn_id, _));
- EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_addr_,
- QuicStringPiece("HTTP/1"), _))
- .WillOnce(testing::Return(GetSession(conn_id, client_addr_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
- GetSession(conn_id, client_addr_)->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(conn_id, packet);
- })));
- }
-
- // Send a CHLO that the StatelessRejector will accept.
- ProcessPacket(client_addr_, conn_id, true, SerializeFullCHLO());
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
- EXPECT_FALSE(store->HasBufferedPackets(conn_id));
-
- // Send a data packet that will get buffered
- check.Call(1);
- ProcessPacket(client_addr_, conn_id, true, "My name is Data");
- EXPECT_TRUE(store->HasBufferedPackets(conn_id));
-
- // Pretend that enough time has gone by for the packets to get expired out of
- // the buffer
- mock_helper_.AdvanceTime(
- QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs));
- QuicBufferedPacketStorePeer::expiration_alarm(store)->Cancel();
- store->OnExpirationTimeout();
- EXPECT_FALSE(store->HasBufferedPackets(conn_id));
- EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
-
- // Pretend that enough time has gone by for the connection ID to be removed
- // from the time wait manager
- mock_helper_.AdvanceTime(
- QuicTimeWaitListManagerPeer::time_wait_period(time_wait_list_manager_));
- QuicTimeWaitListManagerPeer::expiration_alarm(time_wait_list_manager_)
- ->Cancel();
- time_wait_list_manager_->CleanUpOldConnectionIds();
- EXPECT_FALSE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
-
- // Now allow the CHLO validation to complete. Expect that a connection is
- // indeed created, since QUIC has forgotten that this connection ever existed.
- // This is a miniscule corner case which should never happen in the wild, so
- // really we are just verifying that the dispatcher does not explode in this
- // situation.
- check.Call(2);
- GetFakeProofSource()->InvokePendingCallback(0);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
- EXPECT_FALSE(store->HasBufferedPackets(conn_id));
- EXPECT_FALSE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
-}
-
-// Regression test for
-// https://bugs.chromium.org/p/chromium/issues/detail?id=748289
-TEST_F(AsyncGetProofTest, DispatcherFailedToPickUpVersionForAsyncProof) {
- // This test mimics the scenario that dispatcher's framer can have different
- // version when async proof returns.
- // When dispatcher sends SREJ, the SREJ frame can be serialized in
- // different endianness which causes the client to close the connection
- // because of QUIC_INVALID_STREAM_DATA.
-
- SetQuicReloadableFlag(quic_disable_version_39, false);
- SetQuicReloadableFlag(quic_enable_version_43, true);
- ParsedQuicVersion chlo_version(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43);
- chlo_.SetVersion(kVER, chlo_version);
- // Send a CHLO with v43. Dispatcher framer's version is set to v43.
- ProcessPacket(client_addr_, TestConnectionId(1), true, chlo_version,
- SerializeCHLO(), CONNECTION_ID_PRESENT,
- PACKET_4BYTE_PACKET_NUMBER, 1);
-
- // Send another CHLO with v39. Dispatcher framer's version is set to v39.
- chlo_version.transport_version = QUIC_VERSION_39;
- chlo_.SetVersion(kVER, chlo_version);
- // Invalidate the cached serialized form.
- chlo_.MarkDirty();
- ProcessPacket(client_addr_, TestConnectionId(2), true, chlo_version,
- SerializeCHLO(), CONNECTION_ID_PRESENT,
- PACKET_4BYTE_PACKET_NUMBER, 1);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2);
-
- // Complete the ProofSource::GetProof call for v43. This would cause the
- // version mismatch between the CHLO packet and the dispatcher.
- GetFakeProofSource()->InvokePendingCallback(0);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-}
-
-// Regression test for b/116200989.
-TEST_F(AsyncGetProofTest, DispatcherHasWrongLastPacketIsIetfQuic) {
- // Process a packet of v44.
- ParsedQuicVersion chlo_version(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_44);
- chlo_.SetVersion(kVER, chlo_version);
- ProcessPacket(client_addr_, TestConnectionId(1), true, chlo_version,
- SerializeCHLO(), CONNECTION_ID_PRESENT,
- PACKET_4BYTE_PACKET_NUMBER, 1);
-
- // Process another packet of v43.
- chlo_version.transport_version = QUIC_VERSION_43;
- chlo_.SetVersion(kVER, chlo_version);
- // Invalidate the cached serialized form.
- chlo_.MarkDirty();
- ProcessPacket(client_addr_, TestConnectionId(2), true, chlo_version,
- SerializeCHLO(), CONNECTION_ID_PRESENT,
- PACKET_4BYTE_PACKET_NUMBER, 1);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2);
-
- // Complete the ProofSource::GetProof call for v44.
- GetFakeProofSource()->InvokePendingCallback(0);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
-
- // Complete the ProofSource::GetProof call for v43.
- GetFakeProofSource()->InvokePendingCallback(0);
- ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
-}
-
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc b/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc
index e2a14ade998..86c0896f22e 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
@@ -138,8 +138,8 @@ const char* QuicErrorCodeToString(QuicErrorCode error) {
RETURN_STRING_LITERAL(QUIC_INVALID_MAX_DATA_FRAME_DATA);
RETURN_STRING_LITERAL(QUIC_INVALID_MAX_STREAM_DATA_FRAME_DATA);
RETURN_STRING_LITERAL(QUIC_INVALID_STREAM_BLOCKED_DATA);
- RETURN_STRING_LITERAL(QUIC_MAX_STREAM_ID_DATA);
- RETURN_STRING_LITERAL(QUIC_STREAM_ID_BLOCKED_DATA);
+ RETURN_STRING_LITERAL(QUIC_MAX_STREAMS_DATA);
+ RETURN_STRING_LITERAL(QUIC_STREAMS_BLOCKED_DATA);
RETURN_STRING_LITERAL(QUIC_INVALID_NEW_CONNECTION_ID_DATA);
RETURN_STRING_LITERAL(QUIC_INVALID_RETIRE_CONNECTION_ID_DATA);
RETURN_STRING_LITERAL(QUIC_INVALID_STOP_SENDING_FRAME_DATA);
@@ -151,8 +151,8 @@ const char* QuicErrorCodeToString(QuicErrorCode error) {
RETURN_STRING_LITERAL(QUIC_INVALID_NEW_TOKEN);
RETURN_STRING_LITERAL(QUIC_DATA_RECEIVED_ON_WRITE_UNIDIRECTIONAL_STREAM);
RETURN_STRING_LITERAL(QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM);
- RETURN_STRING_LITERAL(QUIC_STREAM_ID_BLOCKED_ERROR);
- RETURN_STRING_LITERAL(QUIC_MAX_STREAM_ID_ERROR);
+ RETURN_STRING_LITERAL(QUIC_STREAMS_BLOCKED_ERROR);
+ RETURN_STRING_LITERAL(QUIC_MAX_STREAMS_ERROR);
RETURN_STRING_LITERAL(QUIC_HTTP_DECODER_ERROR);
RETURN_STRING_LITERAL(QUIC_STALE_CONNECTION_CANCELLED);
RETURN_STRING_LITERAL(QUIC_IETF_GQUIC_ERROR_MISSING);
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 b06cc7f57d3..c8259f723c3 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
@@ -290,10 +290,10 @@ enum QuicErrorCode {
QUIC_INVALID_MAX_DATA_FRAME_DATA = 102,
// Received a MAX STREAM DATA frame with errors.
QUIC_INVALID_MAX_STREAM_DATA_FRAME_DATA = 103,
- // Received a MAX_STREAM_ID frame with bad data
- QUIC_MAX_STREAM_ID_DATA = 104,
- // Received a STREAM_ID_BLOCKED frame with bad data
- QUIC_STREAM_ID_BLOCKED_DATA = 105,
+ // Received a MAX_STREAMS frame with bad data
+ QUIC_MAX_STREAMS_DATA = 104,
+ // Received a STREAMS_BLOCKED frame with bad data
+ QUIC_STREAMS_BLOCKED_DATA = 105,
// Error deframing a STREAM BLOCKED frame.
QUIC_INVALID_STREAM_BLOCKED_DATA = 106,
// NEW CONNECTION ID frame data is malformed.
@@ -315,13 +315,11 @@ enum QuicErrorCode {
// RETIRE CONNECTION ID frame data is malformed.
QUIC_INVALID_RETIRE_CONNECTION_ID_DATA = 117,
- //
- // Error in a received STREAM ID BLOCKED frame. -- the stream ID is not
- // consistent with the state of the endpoint.
- QUIC_STREAM_ID_BLOCKED_ERROR = 118,
- // Error in a received MAX STREAM ID frame -- the stream ID is not
- // consistent with the state of the endpoint.
- QUIC_MAX_STREAM_ID_ERROR = 119,
+
+ // Error in a received STREAMS BLOCKED frame.
+ QUIC_STREAMS_BLOCKED_ERROR = 118,
+ // Error in a received MAX STREAMS frame
+ QUIC_MAX_STREAMS_ERROR = 119,
// Error in Http decoder
QUIC_HTTP_DECODER_ERROR = 120,
// Connection from stale host needs to be cancelled.
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 0c65dc226e4..7e34b3b6259 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
@@ -10,8 +10,10 @@
#include <string>
#include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
+#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
+#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.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"
@@ -21,6 +23,7 @@
#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_socket_address_coder.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"
@@ -280,7 +283,7 @@ bool GetLongHeaderType(QuicTransportVersion version,
break;
default:
QUIC_BUG << "Unreachable statement";
- *long_header_type = VERSION_NEGOTIATION;
+ *long_header_type = INVALID_PACKET_TYPE;
return false;
}
return true;
@@ -404,67 +407,10 @@ bool IsValidFullPacketNumber(uint64_t full_packet_number,
return full_packet_number > 0 || version == QUIC_VERSION_99;
}
-// Convert a stream ID to a count of streams, for IETF QUIC/Version 99 only.
-// There is no need to take into account whether the ID is for uni- or
-// bi-directional streams, or whether it's server- or client- initiated. It
-// always returns a valid count.
-QuicStreamId StreamIdToCount(QuicTransportVersion version,
- QuicStreamId stream_id) {
- DCHECK_EQ(QUIC_VERSION_99, version);
- if ((stream_id & 0x3) == 0) {
- return (stream_id / QuicUtils::StreamIdDelta(version));
- }
- return (stream_id / QuicUtils::StreamIdDelta(version)) + 1;
-}
-
-// Returns the maximum value that a stream count may have, taking into account
-// the fact that bidirectional, client initiated, streams have one fewer stream
-// available than the others. This is because the old crypto streams, with ID ==
-// 0 are not included in the count.
-// The version is not included in the call, nor does the method take the version
-// into account, because this is called only from code used for IETF QUIC.
-// TODO(fkastenholz): Remove this method and replace calls to it with direct
-// references to kMaxQuicStreamIdCount when streamid 0 becomes a normal stream
-// id.
-QuicStreamId GetMaxStreamCount(bool unidirectional, Perspective perspective) {
- if (!unidirectional && perspective == Perspective::IS_CLIENT) {
- return kMaxQuicStreamId >> 2;
- }
- return (kMaxQuicStreamId >> 2) + 1;
-}
-
-// Convert a stream count to the maximum stream ID for that count.
-// Needs to know whether the resulting stream ID should be uni-directional,
-// bi-directional, server-initiated, or client-initiated.
-// Returns true if it works, false if not. The only error condition is that
-// the stream_count is too big and it would generate a stream id that is larger
-// than the implementation's maximum stream id value.
-bool StreamCountToId(QuicStreamId stream_count,
- bool unidirectional,
- Perspective perspective,
- QuicTransportVersion version,
- QuicStreamId* generated_stream_id) {
- DCHECK_EQ(QUIC_VERSION_99, version);
- // TODO(fkastenholz): when the MAX_STREAMS and STREAMS_BLOCKED frames
- // are connected all the way up to the stream_id_manager, handle count==0
- // properly (interpret it as "can open 0 streams") and the count being too
- // large (close the connection).
- if ((stream_count == 0) ||
- (stream_count > GetMaxStreamCount(unidirectional, perspective))) {
- return false;
- }
- *generated_stream_id =
- ((unidirectional)
- ? QuicUtils::GetFirstUnidirectionalStreamId(version, perspective)
- : QuicUtils::GetFirstBidirectionalStreamId(version, perspective)) +
- ((stream_count - 1) * QuicUtils::StreamIdDelta(version));
- return true;
-}
-
-bool AppendIetfConnectionIdsNew(bool version_flag,
- QuicConnectionId destination_connection_id,
- QuicConnectionId source_connection_id,
- QuicDataWriter* writer) {
+bool AppendIetfConnectionIds(bool version_flag,
+ QuicConnectionId destination_connection_id,
+ QuicConnectionId source_connection_id,
+ QuicDataWriter* writer) {
if (!version_flag) {
return writer->WriteConnectionId(destination_connection_id);
}
@@ -503,15 +449,20 @@ void RecordDroppedPacketReason(DroppedPacketReason reason) {
"each time such a packet is dropped");
}
+PacketHeaderFormat GetIetfPacketHeaderFormat(uint8_t type_byte) {
+ return type_byte & FLAGS_LONG_HEADER ? IETF_QUIC_LONG_HEADER_PACKET
+ : IETF_QUIC_SHORT_HEADER_PACKET;
+}
+
} // namespace
QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions,
QuicTime creation_time,
Perspective perspective,
- uint8_t expected_connection_id_length)
+ uint8_t expected_server_connection_id_length)
: visitor_(nullptr),
error_(QUIC_NO_ERROR),
- last_serialized_connection_id_(EmptyQuicConnectionId()),
+ last_serialized_server_connection_id_(EmptyQuicConnectionId()),
last_version_label_(0),
version_(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
supported_versions_(supported_versions),
@@ -527,9 +478,11 @@ QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions,
data_producer_(nullptr),
infer_packet_header_type_from_version_(perspective ==
Perspective::IS_CLIENT),
- expected_connection_id_length_(expected_connection_id_length),
- should_update_expected_connection_id_length_(false),
- supports_multiple_packet_number_spaces_(false) {
+ expected_server_connection_id_length_(
+ expected_server_connection_id_length),
+ should_update_expected_server_connection_id_length_(false),
+ supports_multiple_packet_number_spaces_(false),
+ last_written_packet_number_length_(0) {
DCHECK(!supported_versions.empty());
version_ = supported_versions_[0];
decrypter_[ENCRYPTION_INITIAL] = QuicMakeUnique<NullDecrypter>(perspective);
@@ -610,31 +563,31 @@ size_t QuicFramer::GetRstStreamFrameSize(QuicTransportVersion version,
}
// static
-size_t QuicFramer::GetMinConnectionCloseFrameSize(
+size_t QuicFramer::GetConnectionCloseFrameSize(
QuicTransportVersion version,
const QuicConnectionCloseFrame& frame) {
- if (version == QUIC_VERSION_99) {
- // TODO(fkastenholz): For complete support of IETF QUIC CONNECTION_CLOSE,
- // check if the frame is a Transport close and if the frame's
- // extracted_error_code is not QUIC_IETF_GQUIC_ERROR_MISSING. If so,
- // extend the error string to include " QuicErrorCode: #"
- if (frame.close_type == IETF_QUIC_APPLICATION_CONNECTION_CLOSE) {
- // Application close variant does not include the transport close frame
- // type field.
- return QuicDataWriter::GetVarInt62Len(
- TruncatedErrorStringSize(frame.error_details)) +
- kQuicFrameTypeSize + kQuicIetfQuicErrorCodeSize;
- }
- QUIC_BUG_IF(frame.close_type != IETF_QUIC_TRANSPORT_CONNECTION_CLOSE)
- << "IETF QUIC Connection close and QuicConnectionCloseFrame type is "
- "not IETF ConnectionClose";
- return QuicDataWriter::GetVarInt62Len(
- TruncatedErrorStringSize(frame.error_details)) +
- QuicDataWriter::GetVarInt62Len(frame.transport_close_frame_type) +
- kQuicFrameTypeSize + kQuicIetfQuicErrorCodeSize;
- }
- // Not version 99/IETF QUIC, return Google QUIC CONNECTION CLOSE frame size.
- return kQuicFrameTypeSize + kQuicErrorCodeSize + kQuicErrorDetailsLengthSize;
+ if (version != QUIC_VERSION_99) {
+ // Not version 99/IETF QUIC, return Google QUIC CONNECTION CLOSE frame size.
+ return kQuicFrameTypeSize + kQuicErrorCodeSize +
+ kQuicErrorDetailsLengthSize +
+ TruncatedErrorStringSize(frame.error_details);
+ }
+ // TODO(fkastenholz): For complete support of IETF QUIC CONNECTION_CLOSE,
+ // check if the frame is a Transport close and if the frame's
+ // extracted_error_code is not QUIC_IETF_GQUIC_ERROR_MISSING. If so,
+ // extend the error string to include " QuicErrorCode: #"
+ const size_t truncated_error_string_size =
+ TruncatedErrorStringSize(frame.error_details);
+ const size_t frame_size =
+ truncated_error_string_size +
+ QuicDataWriter::GetVarInt62Len(truncated_error_string_size) +
+ kQuicFrameTypeSize + kQuicIetfQuicErrorCodeSize;
+ if (frame.close_type == IETF_QUIC_APPLICATION_CONNECTION_CLOSE) {
+ return frame_size;
+ }
+ // frame includes the transport_close_frame_type, so include its length.
+ return frame_size +
+ QuicDataWriter::GetVarInt62Len(frame.transport_close_frame_type);
}
// static
@@ -664,31 +617,26 @@ size_t QuicFramer::GetWindowUpdateFrameSize(
// static
size_t QuicFramer::GetMaxStreamsFrameSize(QuicTransportVersion version,
- const QuicMaxStreamIdFrame& frame) {
+ const QuicMaxStreamsFrame& frame) {
if (version != QUIC_VERSION_99) {
QUIC_BUG << "In version " << version
- << " - not 99 - and tried to serialize MaxStreamId Frame.";
+ << " - not 99 - and tried to serialize MaxStreams Frame.";
}
-
- // Convert from the stream id on which the connection is blocked to a count
- QuicStreamId stream_count = StreamIdToCount(version, frame.max_stream_id);
-
- return kQuicFrameTypeSize + QuicDataWriter::GetVarInt62Len(stream_count);
+ return kQuicFrameTypeSize +
+ QuicDataWriter::GetVarInt62Len(frame.stream_count);
}
// static
size_t QuicFramer::GetStreamsBlockedFrameSize(
QuicTransportVersion version,
- const QuicStreamIdBlockedFrame& frame) {
+ const QuicStreamsBlockedFrame& frame) {
if (version != QUIC_VERSION_99) {
QUIC_BUG << "In version " << version
- << " - not 99 - and tried to serialize StreamIdBlocked Frame.";
+ << " - not 99 - and tried to serialize StreamsBlocked Frame.";
}
- // Convert from the stream id on which the connection is blocked to a count
- QuicStreamId stream_count = StreamIdToCount(version, frame.stream_id);
-
- return kQuicFrameTypeSize + QuicDataWriter::GetVarInt62Len(stream_count);
+ return kQuicFrameTypeSize +
+ QuicDataWriter::GetVarInt62Len(frame.stream_count);
}
// static
@@ -735,10 +683,8 @@ size_t QuicFramer::GetRetransmittableControlFrameSize(
case RST_STREAM_FRAME:
return GetRstStreamFrameSize(version, *frame.rst_stream_frame);
case CONNECTION_CLOSE_FRAME:
- return GetMinConnectionCloseFrameSize(version,
- *frame.connection_close_frame) +
- TruncatedErrorStringSize(
- frame.connection_close_frame->error_details);
+ return GetConnectionCloseFrameSize(version,
+ *frame.connection_close_frame);
case GOAWAY_FRAME:
return GetMinGoAwayFrameSize() +
TruncatedErrorStringSize(frame.goaway_frame->reason_phrase);
@@ -755,10 +701,10 @@ size_t QuicFramer::GetRetransmittableControlFrameSize(
return GetRetireConnectionIdFrameSize(*frame.retire_connection_id_frame);
case NEW_TOKEN_FRAME:
return GetNewTokenFrameSize(*frame.new_token_frame);
- case MAX_STREAM_ID_FRAME:
- return GetMaxStreamsFrameSize(version, frame.max_stream_id_frame);
- case STREAM_ID_BLOCKED_FRAME:
- return GetStreamsBlockedFrameSize(version, frame.stream_id_blocked_frame);
+ case MAX_STREAMS_FRAME:
+ return GetMaxStreamsFrameSize(version, frame.max_streams_frame);
+ case STREAMS_BLOCKED_FRAME:
+ return GetStreamsBlockedFrameSize(version, frame.streams_blocked_frame);
case PATH_RESPONSE_FRAME:
return GetPathResponseFrameSize(*frame.path_response_frame);
case PATH_CHALLENGE_FRAME:
@@ -1063,13 +1009,13 @@ size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header,
set_detailed_error(
"Attempt to append NEW_TOKEN_ID frame and not in version 99.");
return RaiseError(QUIC_INTERNAL_ERROR);
- case MAX_STREAM_ID_FRAME:
+ case MAX_STREAMS_FRAME:
set_detailed_error(
- "Attempt to append MAX_STREAM_ID frame and not in version 99.");
+ "Attempt to append MAX_STREAMS frame and not in version 99.");
return RaiseError(QUIC_INTERNAL_ERROR);
- case STREAM_ID_BLOCKED_FRAME:
+ case STREAMS_BLOCKED_FRAME:
set_detailed_error(
- "Attempt to append STREAM_ID_BLOCKED frame and not in version 99.");
+ "Attempt to append STREAMS_BLOCKED frame and not in version 99.");
return RaiseError(QUIC_INTERNAL_ERROR);
case PATH_RESPONSE_FRAME:
set_detailed_error(
@@ -1195,14 +1141,14 @@ size_t QuicFramer::AppendIetfFrames(const QuicFrames& frames,
return 0;
}
break;
- case MAX_STREAM_ID_FRAME:
- if (!AppendMaxStreamsFrame(frame.max_stream_id_frame, writer)) {
+ case MAX_STREAMS_FRAME:
+ if (!AppendMaxStreamsFrame(frame.max_streams_frame, writer)) {
QUIC_BUG << "AppendMaxStreamsFrame failed" << detailed_error();
return 0;
}
break;
- case STREAM_ID_BLOCKED_FRAME:
- if (!AppendStreamsBlockedFrame(frame.stream_id_blocked_frame, writer)) {
+ case STREAMS_BLOCKED_FRAME:
+ if (!AppendStreamsBlockedFrame(frame.streams_blocked_frame, writer)) {
QUIC_BUG << "AppendStreamsBlockedFrame failed" << detailed_error();
return 0;
}
@@ -1442,14 +1388,20 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildIetfStatelessResetPacket(
// static
std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildVersionNegotiationPacket(
- QuicConnectionId connection_id,
+ QuicConnectionId server_connection_id,
+ QuicConnectionId client_connection_id,
bool ietf_quic,
const ParsedQuicVersionVector& versions) {
if (ietf_quic) {
- return BuildIetfVersionNegotiationPacket(connection_id, versions);
+ return BuildIetfVersionNegotiationPacket(server_connection_id,
+ client_connection_id, versions);
}
+
+ // The GQUIC encoding does not support encoding client connection IDs.
+ DCHECK(client_connection_id.IsEmpty());
+
DCHECK(!versions.empty());
- size_t len = kPublicFlagsSize + connection_id.length() +
+ size_t len = kPublicFlagsSize + server_connection_id.length() +
versions.size() * kQuicVersionSize;
std::unique_ptr<char[]> buffer(new char[len]);
// Endianness is not a concern here, version negotiation packet does not have
@@ -1464,7 +1416,7 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildVersionNegotiationPacket(
return nullptr;
}
- if (!writer.WriteConnectionId(connection_id)) {
+ if (!writer.WriteConnectionId(server_connection_id)) {
return nullptr;
}
@@ -1482,18 +1434,26 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildVersionNegotiationPacket(
// static
std::unique_ptr<QuicEncryptedPacket>
QuicFramer::BuildIetfVersionNegotiationPacket(
- QuicConnectionId connection_id,
+ QuicConnectionId server_connection_id,
+ QuicConnectionId client_connection_id,
const ParsedQuicVersionVector& versions) {
- QUIC_DVLOG(1) << "Building IETF version negotiation packet.";
+ QUIC_DVLOG(1) << "Building IETF version negotiation packet: "
+ << ParsedQuicVersionVectorToString(versions);
+ DCHECK(client_connection_id.IsEmpty() ||
+ GetQuicRestartFlag(quic_do_not_override_connection_id));
DCHECK(!versions.empty());
size_t len = kPacketHeaderTypeSize + kConnectionIdLengthSize +
- connection_id.length() +
+ client_connection_id.length() + server_connection_id.length() +
(versions.size() + 1) * kQuicVersionSize;
std::unique_ptr<char[]> buffer(new char[len]);
QuicDataWriter writer(len, buffer.get());
// TODO(fayang): Randomly select a value for the type.
- uint8_t type = static_cast<uint8_t>(FLAGS_LONG_HEADER | VERSION_NEGOTIATION);
+ uint8_t type = static_cast<uint8_t>(FLAGS_LONG_HEADER);
+ if (GetQuicReloadableFlag(quic_send_version_negotiation_fixed_bit)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_send_version_negotiation_fixed_bit);
+ type |= static_cast<uint8_t>(FLAGS_FIXED_BIT);
+ }
if (!writer.WriteUInt8(type)) {
return nullptr;
}
@@ -1502,18 +1462,9 @@ QuicFramer::BuildIetfVersionNegotiationPacket(
return nullptr;
}
- if (!GetQuicReloadableFlag(quic_use_new_append_connection_id)) {
- if (!AppendIetfConnectionId(true, EmptyQuicConnectionId(),
- PACKET_0BYTE_CONNECTION_ID, connection_id,
- PACKET_8BYTE_CONNECTION_ID, &writer)) {
- return nullptr;
- }
- } else {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_new_append_connection_id, 1, 2);
- if (!AppendIetfConnectionIdsNew(true, EmptyQuicConnectionId(),
- connection_id, &writer)) {
- return nullptr;
- }
+ if (!AppendIetfConnectionIds(true, client_connection_id, server_connection_id,
+ &writer)) {
+ return nullptr;
}
for (const ParsedQuicVersion& version : versions) {
@@ -1559,18 +1510,42 @@ bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) {
return true;
}
- if (perspective_ == Perspective::IS_SERVER && header.version_flag &&
- header.version != version_) {
- if (!visitor_->OnProtocolVersionMismatch(header.version, header.form)) {
- RecordDroppedPacketReason(DroppedPacketReason::VERSION_MISMATCH);
- return true;
+ if (IsVersionNegotiation(header, packet_has_ietf_packet_header)) {
+ if (!GetQuicRestartFlag(quic_server_drop_version_negotiation)) {
+ QUIC_DVLOG(1) << ENDPOINT << "Received version negotiation packet";
+ return ProcessVersionNegotiationPacket(&reader, header);
+ }
+ QUIC_RESTART_FLAG_COUNT_N(quic_server_drop_version_negotiation, 1, 2);
+ if (perspective_ == Perspective::IS_CLIENT) {
+ QUIC_DVLOG(1) << "Client received version negotiation packet";
+ return ProcessVersionNegotiationPacket(&reader, header);
+ } else {
+ QUIC_DLOG(ERROR) << "Server received version negotiation packet";
+ set_detailed_error("Server received version negotiation packet.");
+ return RaiseError(QUIC_INVALID_VERSION_NEGOTIATION_PACKET);
+ }
+ }
+
+ if (header.version_flag && header.version != version_) {
+ if (perspective_ == Perspective::IS_SERVER) {
+ if (!visitor_->OnProtocolVersionMismatch(header.version, header.form)) {
+ RecordDroppedPacketReason(DroppedPacketReason::VERSION_MISMATCH);
+ return true;
+ }
+ } else {
+ // A client received a packet of a different version but that packet is
+ // not a version negotiation packet. It is therefore invalid and dropped.
+ QUIC_DLOG(ERROR) << "Client received unexpected version "
+ << ParsedQuicVersionToString(header.version)
+ << " instead of " << ParsedQuicVersionToString(version_);
+ set_detailed_error("Client received unexpected version.");
+ return RaiseError(QUIC_INVALID_VERSION);
}
}
bool rv;
- if (IsVersionNegotiation(header, packet_has_ietf_packet_header)) {
- QUIC_DVLOG(1) << ENDPOINT << "Received version negotiation packet";
- rv = ProcessVersionNegotiationPacket(&reader, header);
+ if (header.long_packet_type == RETRY) {
+ rv = ProcessRetryPacket(&reader, header);
} else if (header.reset_flag) {
rv = ProcessPublicResetPacket(&reader, header);
} else if (packet.length() <= kMaxIncomingPacketSize) {
@@ -1605,25 +1580,50 @@ bool QuicFramer::ProcessVersionNegotiationPacket(
const QuicPacketHeader& header) {
DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
- QuicVersionNegotiationPacket packet(header.destination_connection_id);
+ QuicVersionNegotiationPacket packet(
+ GetServerConnectionIdAsRecipient(header, perspective_));
// Try reading at least once to raise error if the packet is invalid.
do {
QuicVersionLabel version_label;
- if (!reader->ReadTag(&version_label)) {
+ if (!ProcessVersionLabel(reader, &version_label)) {
set_detailed_error("Unable to read supported version in negotiation.");
RecordDroppedPacketReason(
DroppedPacketReason::INVALID_VERSION_NEGOTIATION_PACKET);
return RaiseError(QUIC_INVALID_VERSION_NEGOTIATION_PACKET);
}
- // TODO(rch): Use ReadUInt32() once QUIC_VERSION_35 is removed.
- version_label = QuicEndian::NetToHost32(version_label);
packet.versions.push_back(ParseQuicVersionLabel(version_label));
} while (!reader->IsDoneReading());
+ QUIC_DLOG(INFO) << ENDPOINT << "parsed version negotiation: "
+ << ParsedQuicVersionVectorToString(packet.versions);
+
visitor_->OnVersionNegotiationPacket(packet);
return true;
}
+bool QuicFramer::ProcessRetryPacket(QuicDataReader* reader,
+ const QuicPacketHeader& header) {
+ DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
+
+ // Parse Original Destination Connection ID Length.
+ uint8_t odcil = header.type_byte & 0xf;
+ if (odcil != 0) {
+ odcil += kConnectionIdLengthAdjustment;
+ }
+
+ // Parse Original Destination Connection ID.
+ QuicConnectionId original_destination_connection_id;
+ if (!reader->ReadConnectionId(&original_destination_connection_id, odcil)) {
+ set_detailed_error("Unable to read Original Destination ConnectionId.");
+ return false;
+ }
+
+ QuicStringPiece retry_token = reader->ReadRemainingPayload();
+ visitor_->OnRetryPacket(original_destination_connection_id,
+ header.source_connection_id, retry_token);
+ return true;
+}
+
bool QuicFramer::MaybeProcessIetfInitialRetryToken(
QuicDataReader* encrypted_reader,
QuicPacketHeader* header) {
@@ -1770,26 +1770,43 @@ bool QuicFramer::ProcessIetfDataPacket(QuicDataReader* encrypted_reader,
return false;
}
+ QuicStringPiece associated_data;
+ std::vector<char> ad_storage;
if (header->form == IETF_QUIC_SHORT_HEADER_PACKET ||
header->long_packet_type != VERSION_NEGOTIATION) {
+ DCHECK(header->form == IETF_QUIC_SHORT_HEADER_PACKET ||
+ header->long_packet_type == INITIAL ||
+ header->long_packet_type == HANDSHAKE ||
+ header->long_packet_type == ZERO_RTT_PROTECTED);
// Process packet number.
QuicPacketNumber base_packet_number;
if (supports_multiple_packet_number_spaces_) {
- base_packet_number =
- largest_decrypted_packet_numbers_[GetPacketNumberSpace(*header)];
+ PacketNumberSpace pn_space = GetPacketNumberSpace(*header);
+ if (pn_space == NUM_PACKET_NUMBER_SPACES) {
+ return RaiseError(QUIC_INVALID_PACKET_HEADER);
+ }
+ base_packet_number = largest_decrypted_packet_numbers_[pn_space];
} else {
base_packet_number = largest_packet_number_;
}
uint64_t full_packet_number;
- if (!ProcessAndCalculatePacketNumber(
- encrypted_reader, header->packet_number_length, base_packet_number,
- &full_packet_number)) {
+ bool hp_removal_failed = false;
+ if (version_.HasHeaderProtection()) {
+ if (!RemoveHeaderProtection(encrypted_reader, packet, header,
+ &full_packet_number, &ad_storage)) {
+ hp_removal_failed = true;
+ }
+ associated_data = QuicStringPiece(ad_storage.data(), ad_storage.size());
+ } else if (!ProcessAndCalculatePacketNumber(
+ encrypted_reader, header->packet_number_length,
+ base_packet_number, &full_packet_number)) {
set_detailed_error("Unable to read packet number.");
RecordDroppedPacketReason(DroppedPacketReason::INVALID_PACKET_NUMBER);
return RaiseError(QUIC_INVALID_PACKET_HEADER);
}
- if (!IsValidFullPacketNumber(full_packet_number, transport_version())) {
+ if (hp_removal_failed ||
+ !IsValidFullPacketNumber(full_packet_number, transport_version())) {
if (IsIetfStatelessResetPacket(*header)) {
// This is a stateless reset packet.
QuicIetfStatelessResetPacket packet(
@@ -1797,6 +1814,10 @@ bool QuicFramer::ProcessIetfDataPacket(QuicDataReader* encrypted_reader,
visitor_->OnAuthenticatedIetfStatelessResetPacket(packet);
return true;
}
+ if (hp_removal_failed) {
+ set_detailed_error("Unable to decrypt header protection.");
+ return RaiseError(QUIC_DECRYPTION_FAILURE);
+ }
RecordDroppedPacketReason(DroppedPacketReason::INVALID_PACKET_NUMBER);
set_detailed_error("packet numbers cannot be 0.");
return RaiseError(QUIC_INVALID_PACKET_HEADER);
@@ -1831,13 +1852,15 @@ bool QuicFramer::ProcessIetfDataPacket(QuicDataReader* encrypted_reader,
}
QuicStringPiece encrypted = encrypted_reader->ReadRemainingPayload();
- QuicStringPiece associated_data = GetAssociatedDataFromEncryptedPacket(
- version_.transport_version, packet,
- GetIncludedDestinationConnectionIdLength(*header),
- GetIncludedSourceConnectionIdLength(*header), header->version_flag,
- header->nonce != nullptr, header->packet_number_length,
- header->retry_token_length_length, header->retry_token.length(),
- header->length_length);
+ if (!version_.HasHeaderProtection()) {
+ associated_data = GetAssociatedDataFromEncryptedPacket(
+ version_.transport_version, packet,
+ GetIncludedDestinationConnectionIdLength(*header),
+ GetIncludedSourceConnectionIdLength(*header), header->version_flag,
+ header->nonce != nullptr, header->packet_number_length,
+ header->retry_token_length_length, header->retry_token.length(),
+ header->length_length);
+ }
size_t decrypted_length = 0;
EncryptionLevel decrypted_level;
@@ -1970,7 +1993,8 @@ bool QuicFramer::ProcessDataPacket(QuicDataReader* encrypted_reader,
bool QuicFramer::ProcessPublicResetPacket(QuicDataReader* reader,
const QuicPacketHeader& header) {
- QuicPublicResetPacket packet(header.destination_connection_id);
+ QuicPublicResetPacket packet(
+ GetServerConnectionIdAsRecipient(header, perspective_));
std::unique_ptr<CryptoHandshakeMessage> reset(
CryptoFramer::ParseMessage(reader->ReadRemainingPayload()));
@@ -2049,8 +2073,15 @@ bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header,
DCHECK_EQ(Perspective::IS_SERVER, perspective_);
public_flags |= PACKET_PUBLIC_FLAGS_NONCE;
}
- DCHECK_EQ(CONNECTION_ID_ABSENT, header.source_connection_id_included);
- switch (header.destination_connection_id_included) {
+
+ QuicConnectionId server_connection_id =
+ GetServerConnectionIdAsSender(header, perspective_);
+ QuicConnectionIdIncluded server_connection_id_included =
+ GetServerConnectionIdIncludedAsSender(header, perspective_);
+ DCHECK_EQ(CONNECTION_ID_ABSENT,
+ GetClientConnectionIdIncludedAsSender(header, perspective_));
+
+ switch (server_connection_id_included) {
case CONNECTION_ID_ABSENT:
if (!writer->WriteUInt8(public_flags |
PACKET_PUBLIC_FLAGS_0BYTE_CONNECTION_ID)) {
@@ -2059,10 +2090,9 @@ bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header,
break;
case CONNECTION_ID_PRESENT:
QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
- header.destination_connection_id, transport_version()))
+ server_connection_id, transport_version()))
<< "AppendPacketHeader: attempted to use connection ID "
- << header.destination_connection_id
- << " which is invalid with version "
+ << server_connection_id << " which is invalid with version "
<< QuicVersionToString(transport_version());
public_flags |= PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID;
@@ -2070,12 +2100,12 @@ bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header,
public_flags |= PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID_OLD;
}
if (!writer->WriteUInt8(public_flags) ||
- !writer->WriteConnectionId(header.destination_connection_id)) {
+ !writer->WriteConnectionId(server_connection_id)) {
return false;
}
break;
}
- last_serialized_connection_id_ = header.destination_connection_id;
+ last_serialized_server_connection_id_ = server_connection_id;
if (header.version_flag) {
DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
@@ -2141,10 +2171,12 @@ bool QuicFramer::AppendIetfPacketHeader(const QuicPacketHeader& header,
QuicDataWriter* writer,
size_t* length_field_offset) {
QUIC_DVLOG(1) << ENDPOINT << "Appending IETF header: " << header;
- QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
- header.destination_connection_id, transport_version()))
+ QuicConnectionId server_connection_id =
+ GetServerConnectionIdAsSender(header, perspective_);
+ QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(server_connection_id,
+ transport_version()))
<< "AppendIetfPacketHeader: attempted to use connection ID "
- << header.destination_connection_id << " which is invalid with version "
+ << server_connection_id << " which is invalid with version "
<< QuicVersionToString(transport_version());
if (!AppendIetfHeaderTypeByte(header, writer)) {
return false;
@@ -2160,31 +2192,19 @@ bool QuicFramer::AppendIetfPacketHeader(const QuicPacketHeader& header,
}
// Append connection ID.
- if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- transport_version()) &&
- !GetQuicReloadableFlag(quic_use_new_append_connection_id)) {
- if (!AppendIetfConnectionId(
- header.version_flag, header.destination_connection_id,
- GetIncludedDestinationConnectionIdLength(header),
- header.source_connection_id,
- GetIncludedSourceConnectionIdLength(header), writer)) {
- return false;
- }
- } else {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_new_append_connection_id, 2, 2);
- if (!AppendIetfConnectionIdsNew(
- header.version_flag,
- header.destination_connection_id_included != CONNECTION_ID_ABSENT
- ? header.destination_connection_id
- : EmptyQuicConnectionId(),
- header.source_connection_id_included != CONNECTION_ID_ABSENT
- ? header.source_connection_id
- : EmptyQuicConnectionId(),
- writer)) {
- return false;
- }
+ if (!AppendIetfConnectionIds(
+ header.version_flag,
+ header.destination_connection_id_included != CONNECTION_ID_ABSENT
+ ? header.destination_connection_id
+ : EmptyQuicConnectionId(),
+ header.source_connection_id_included != CONNECTION_ID_ABSENT
+ ? header.source_connection_id
+ : EmptyQuicConnectionId(),
+ writer)) {
+ return false;
}
- last_serialized_connection_id_ = header.destination_connection_id;
+
+ last_serialized_server_connection_id_ = server_connection_id;
if (QuicVersionHasLongHeaderLengths(transport_version()) &&
header.version_flag) {
@@ -2214,6 +2234,7 @@ bool QuicFramer::AppendIetfPacketHeader(const QuicPacketHeader& header,
writer)) {
return false;
}
+ last_written_packet_number_length_ = header.packet_number_length;
if (!header.version_flag) {
return true;
@@ -2306,18 +2327,26 @@ bool QuicFramer::ProcessPublicHeader(QuicDataReader* reader,
return false;
}
+ QuicConnectionId* header_connection_id = &header->destination_connection_id;
+ QuicConnectionIdIncluded* header_connection_id_included =
+ &header->destination_connection_id_included;
+ if (perspective_ == Perspective::IS_CLIENT &&
+ GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ header_connection_id = &header->source_connection_id;
+ header_connection_id_included = &header->source_connection_id_included;
+ }
switch (public_flags & PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID) {
case PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID:
- if (!reader->ReadConnectionId(&header->destination_connection_id,
+ if (!reader->ReadConnectionId(header_connection_id,
kQuicDefaultConnectionIdLength)) {
set_detailed_error("Unable to read ConnectionId.");
return false;
}
- header->destination_connection_id_included = CONNECTION_ID_PRESENT;
+ *header_connection_id_included = CONNECTION_ID_PRESENT;
break;
case PACKET_PUBLIC_FLAGS_0BYTE_CONNECTION_ID:
- header->destination_connection_id_included = CONNECTION_ID_ABSENT;
- header->destination_connection_id = last_serialized_connection_id_;
+ *header_connection_id_included = CONNECTION_ID_ABSENT;
+ *header_connection_id = last_serialized_server_connection_id_;
break;
}
@@ -2328,13 +2357,10 @@ bool QuicFramer::ProcessPublicHeader(QuicDataReader* reader,
// version flag from the server means version negotiation packet.
if (header->version_flag && perspective_ == Perspective::IS_SERVER) {
QuicVersionLabel version_label;
- if (!reader->ReadTag(&version_label)) {
+ if (!ProcessVersionLabel(reader, &version_label)) {
set_detailed_error("Unable to read protocol version.");
return false;
}
- // TODO(rch): Use ReadUInt32() once QUIC_VERSION_35 is removed.
- version_label = QuicEndian::NetToHost32(version_label);
-
// If the version from the new packet is the same as the version of this
// framer, then the public flags should be set to something we understand.
// If not, this raises an error.
@@ -2441,8 +2467,12 @@ bool QuicFramer::ProcessUnauthenticatedHeader(QuicDataReader* encrypted_reader,
QuicPacketHeader* header) {
QuicPacketNumber base_packet_number;
if (supports_multiple_packet_number_spaces_) {
- base_packet_number =
- largest_decrypted_packet_numbers_[GetPacketNumberSpace(*header)];
+ PacketNumberSpace pn_space = GetPacketNumberSpace(*header);
+ if (pn_space == NUM_PACKET_NUMBER_SPACES) {
+ set_detailed_error("Unable to determine packet number space.");
+ return RaiseError(QUIC_INVALID_PACKET_HEADER);
+ }
+ base_packet_number = largest_decrypted_packet_numbers_[pn_space];
} else {
base_packet_number = largest_packet_number_;
}
@@ -2465,6 +2495,22 @@ bool QuicFramer::ProcessUnauthenticatedHeader(QuicDataReader* encrypted_reader,
"Visitor asked to stop processing of unauthenticated header.");
return false;
}
+ // The function we are in is called because the framer believes that it is
+ // processing a packet that uses the non-IETF (i.e. Google QUIC) packet header
+ // type. Usually, the framer makes that decision based on the framer's
+ // version, but when the framer is used with Perspective::IS_SERVER, then
+ // before version negotiation is complete (specifically, before
+ // InferPacketHeaderTypeFromVersion is called), this decision is made based on
+ // the type byte of the packet.
+ //
+ // If the framer's version KnowsWhichDecrypterToUse, then that version expects
+ // to use the IETF packet header type. If that's the case and we're in this
+ // function, then the packet received is invalid: the framer was expecting an
+ // IETF packet header and didn't get one.
+ if (version().KnowsWhichDecrypterToUse()) {
+ set_detailed_error("Invalid public header type for expected version.");
+ return RaiseError(QUIC_INVALID_PACKET_HEADER);
+ }
return true;
}
@@ -2475,9 +2521,9 @@ bool QuicFramer::ProcessIetfHeaderTypeByte(QuicDataReader* reader,
set_detailed_error("Unable to read type.");
return false;
}
+ header->type_byte = type;
// Determine whether this is a long or short header.
- header->form = type & FLAGS_LONG_HEADER ? IETF_QUIC_LONG_HEADER_PACKET
- : IETF_QUIC_SHORT_HEADER_PACKET;
+ header->form = GetIetfPacketHeaderFormat(type);
if (header->form == IETF_QUIC_LONG_HEADER_PACKET) {
// Version is always present in long headers.
header->version_flag = true;
@@ -2492,12 +2538,10 @@ bool QuicFramer::ProcessIetfHeaderTypeByte(QuicDataReader* reader,
: CONNECTION_ID_ABSENT;
// Read version tag.
QuicVersionLabel version_label;
- if (!reader->ReadTag(&version_label)) {
+ if (!ProcessVersionLabel(reader, &version_label)) {
set_detailed_error("Unable to read protocol version.");
return false;
}
- // TODO(rch): Use ReadUInt32() once QUIC_VERSION_35 is removed.
- version_label = QuicEndian::NetToHost32(version_label);
if (!version_label) {
// Version label is 0 indicating this is a version negotiation packet.
header->long_packet_type = VERSION_NEGOTIATION;
@@ -2514,8 +2558,19 @@ bool QuicFramer::ProcessIetfHeaderTypeByte(QuicDataReader* reader,
set_detailed_error("Illegal long header type value.");
return false;
}
- header->packet_number_length = GetLongHeaderPacketNumberLength(
- header->version.transport_version, type);
+ if (header->long_packet_type == RETRY) {
+ if (!version().SupportsRetry()) {
+ set_detailed_error("RETRY not supported in this version.");
+ return false;
+ }
+ if (perspective_ == Perspective::IS_SERVER) {
+ set_detailed_error("Client-initiated RETRY is invalid.");
+ return false;
+ }
+ } else if (!header->version.HasHeaderProtection()) {
+ header->packet_number_length = GetLongHeaderPacketNumberLength(
+ header->version.transport_version, type);
+ }
}
}
if (header->long_packet_type != VERSION_NEGOTIATION) {
@@ -2543,7 +2598,8 @@ bool QuicFramer::ProcessIetfHeaderTypeByte(QuicDataReader* reader,
set_detailed_error("Fixed bit is 0 in short header.");
return false;
}
- if (!GetShortHeaderPacketNumberLength(transport_version(), type,
+ if (!header->version.HasHeaderProtection() &&
+ !GetShortHeaderPacketNumberLength(transport_version(), type,
infer_packet_header_type_from_version_,
&header->packet_number_length)) {
set_detailed_error("Illegal short header type value.");
@@ -2553,6 +2609,64 @@ bool QuicFramer::ProcessIetfHeaderTypeByte(QuicDataReader* reader,
return true;
}
+// static
+bool QuicFramer::ProcessVersionLabel(QuicDataReader* reader,
+ QuicVersionLabel* version_label) {
+ if (!reader->ReadTag(version_label)) {
+ return false;
+ }
+ // TODO(rch): Use ReadUInt32() once QUIC_VERSION_35 is removed.
+ *version_label = QuicEndian::NetToHost32(*version_label);
+ return true;
+}
+
+// static
+bool QuicFramer::ProcessAndValidateIetfConnectionIdLength(
+ QuicDataReader* reader,
+ ParsedQuicVersion version,
+ bool should_update_expected_server_connection_id_length,
+ uint8_t* expected_server_connection_id_length,
+ uint8_t* destination_connection_id_length,
+ uint8_t* source_connection_id_length,
+ std::string* detailed_error) {
+ uint8_t connection_id_lengths_byte;
+ if (!reader->ReadBytes(&connection_id_lengths_byte, 1)) {
+ *detailed_error = "Unable to read ConnectionId length.";
+ return false;
+ }
+ uint8_t dcil =
+ (connection_id_lengths_byte & kDestinationConnectionIdLengthMask) >> 4;
+ if (dcil != 0) {
+ dcil += kConnectionIdLengthAdjustment;
+ }
+ if (should_update_expected_server_connection_id_length &&
+ *expected_server_connection_id_length != dcil) {
+ QUIC_DVLOG(1) << "Updating expected_server_connection_id_length: "
+ << static_cast<int>(*expected_server_connection_id_length)
+ << " -> " << static_cast<int>(dcil);
+ *expected_server_connection_id_length = dcil;
+ }
+ uint8_t scil = connection_id_lengths_byte & kSourceConnectionIdLengthMask;
+ if (scil != 0) {
+ scil += kConnectionIdLengthAdjustment;
+ }
+ if (!should_update_expected_server_connection_id_length &&
+ (dcil != *destination_connection_id_length ||
+ scil != *source_connection_id_length) &&
+ !QuicUtils::VariableLengthConnectionIdAllowedForVersion(
+ version.transport_version)) {
+ // TODO(dschinazi): use the framer's version once the
+ // OnProtocolVersionMismatch call is moved to before this is run.
+ QUIC_DVLOG(1) << "dcil: " << static_cast<uint32_t>(dcil)
+ << ", scil: " << static_cast<uint32_t>(scil);
+ *detailed_error = "Invalid ConnectionId length.";
+ return false;
+ }
+ *destination_connection_id_length = dcil;
+ *source_connection_id_length = scil;
+ return true;
+}
+
bool QuicFramer::ProcessIetfPacketHeader(QuicDataReader* reader,
QuicPacketHeader* header) {
if (!ProcessIetfHeaderTypeByte(reader, header)) {
@@ -2561,49 +2675,21 @@ bool QuicFramer::ProcessIetfPacketHeader(QuicDataReader* reader,
uint8_t destination_connection_id_length =
header->destination_connection_id_included == CONNECTION_ID_PRESENT
- ? expected_connection_id_length_
+ ? expected_server_connection_id_length_
: 0;
uint8_t source_connection_id_length =
header->source_connection_id_included == CONNECTION_ID_PRESENT
- ? expected_connection_id_length_
+ ? expected_server_connection_id_length_
: 0;
if (header->form == IETF_QUIC_LONG_HEADER_PACKET) {
- // Read and validate connection ID length.
- uint8_t connection_id_lengths_byte;
- if (!reader->ReadBytes(&connection_id_lengths_byte, 1)) {
- set_detailed_error("Unable to read ConnectionId length.");
+ if (!ProcessAndValidateIetfConnectionIdLength(
+ reader, header->version,
+ should_update_expected_server_connection_id_length_,
+ &expected_server_connection_id_length_,
+ &destination_connection_id_length, &source_connection_id_length,
+ &detailed_error_)) {
return false;
}
- uint8_t dcil =
- (connection_id_lengths_byte & kDestinationConnectionIdLengthMask) >> 4;
- if (dcil != 0) {
- dcil += kConnectionIdLengthAdjustment;
- }
- if (should_update_expected_connection_id_length_ &&
- expected_connection_id_length_ != dcil) {
- QUIC_DVLOG(1) << ENDPOINT << "Updating expected_connection_id_length: "
- << static_cast<int>(expected_connection_id_length_)
- << " -> " << static_cast<int>(dcil);
- expected_connection_id_length_ = dcil;
- }
- uint8_t scil = connection_id_lengths_byte & kSourceConnectionIdLengthMask;
- if (scil != 0) {
- scil += kConnectionIdLengthAdjustment;
- }
- if ((dcil != destination_connection_id_length ||
- scil != source_connection_id_length) &&
- !should_update_expected_connection_id_length_ &&
- !QuicUtils::VariableLengthConnectionIdAllowedForVersion(
- header->version.transport_version)) {
- // TODO(dschinazi): use the framer's version once the
- // OnProtocolVersionMismatch call is moved to before this is run.
- QUIC_DVLOG(1) << "dcil: " << static_cast<uint32_t>(dcil)
- << ", scil: " << static_cast<uint32_t>(scil);
- set_detailed_error("Invalid ConnectionId length.");
- return false;
- }
- destination_connection_id_length = dcil;
- source_connection_id_length = scil;
}
DCHECK_LE(destination_connection_id_length, kQuicMaxConnectionIdLength);
@@ -2622,13 +2708,26 @@ bool QuicFramer::ProcessIetfPacketHeader(QuicDataReader* reader,
return false;
}
- if (header->source_connection_id_included == CONNECTION_ID_PRESENT) {
- // Set destination connection ID to source connection ID.
- DCHECK_EQ(EmptyQuicConnectionId(), header->destination_connection_id);
- header->destination_connection_id = header->source_connection_id;
- } else if (header->destination_connection_id_included ==
- CONNECTION_ID_ABSENT) {
- header->destination_connection_id = last_serialized_connection_id_;
+ if (!GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ if (header->source_connection_id_included == CONNECTION_ID_PRESENT) {
+ DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
+ DCHECK_EQ(IETF_QUIC_LONG_HEADER_PACKET, header->form);
+ if (!header->destination_connection_id.IsEmpty()) {
+ set_detailed_error("Client connection ID not supported yet.");
+ return false;
+ }
+ // Set destination connection ID to source connection ID.
+ header->destination_connection_id = header->source_connection_id;
+ } else if (header->destination_connection_id_included ==
+ CONNECTION_ID_ABSENT) {
+ header->destination_connection_id = last_serialized_server_connection_id_;
+ }
+ } else {
+ QUIC_RESTART_FLAG_COUNT_N(quic_do_not_override_connection_id, 5, 5);
+ if (header->source_connection_id_included == CONNECTION_ID_ABSENT) {
+ DCHECK_EQ(EmptyQuicConnectionId(), header->source_connection_id);
+ header->source_connection_id = last_serialized_server_connection_id_;
+ }
}
return true;
@@ -2783,6 +2882,12 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader,
}
case STOP_WAITING_FRAME: {
+ if (GetQuicReloadableFlag(quic_do_not_accept_stop_waiting) &&
+ version_.transport_version >= QUIC_VERSION_44) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_do_not_accept_stop_waiting);
+ set_detailed_error("STOP WAITING not supported in version 44+.");
+ return RaiseError(QUIC_INVALID_STOP_WAITING_DATA);
+ }
QuicStopWaitingFrame stop_waiting_frame;
if (!ProcessStopWaitingFrame(reader, header, &stop_waiting_frame)) {
return RaiseError(QUIC_INVALID_STOP_WAITING_DATA);
@@ -2963,12 +3068,12 @@ bool QuicFramer::ProcessIetfFrameData(QuicDataReader* reader,
}
case IETF_MAX_STREAMS_BIDIRECTIONAL:
case IETF_MAX_STREAMS_UNIDIRECTIONAL: {
- QuicMaxStreamIdFrame frame;
+ QuicMaxStreamsFrame frame;
if (!ProcessMaxStreamsFrame(reader, &frame, frame_type)) {
- return RaiseError(QUIC_MAX_STREAM_ID_DATA);
+ return RaiseError(QUIC_MAX_STREAMS_DATA);
}
- QUIC_CODE_COUNT_N(max_stream_id_received, 1, 2);
- if (!visitor_->OnMaxStreamIdFrame(frame)) {
+ QUIC_CODE_COUNT_N(quic_max_streams_received, 1, 2);
+ if (!visitor_->OnMaxStreamsFrame(frame)) {
QUIC_DVLOG(1) << "Visitor asked to stop further processing.";
// Returning true since there was no parsing error.
return true;
@@ -3011,12 +3116,12 @@ bool QuicFramer::ProcessIetfFrameData(QuicDataReader* reader,
}
case IETF_STREAMS_BLOCKED_UNIDIRECTIONAL:
case IETF_STREAMS_BLOCKED_BIDIRECTIONAL: {
- QuicStreamIdBlockedFrame frame;
+ QuicStreamsBlockedFrame frame;
if (!ProcessStreamsBlockedFrame(reader, &frame, frame_type)) {
- return RaiseError(QUIC_STREAM_ID_BLOCKED_DATA);
+ return RaiseError(QUIC_STREAMS_BLOCKED_DATA);
}
- QUIC_CODE_COUNT_N(stream_id_blocked_received, 1, 2);
- if (!visitor_->OnStreamIdBlockedFrame(frame)) {
+ QUIC_CODE_COUNT_N(quic_streams_blocked_received, 1, 2);
+ if (!visitor_->OnStreamsBlockedFrame(frame)) {
QUIC_DVLOG(1) << "Visitor asked to stop further processing.";
// Returning true since there was no parsing error.
return true;
@@ -3235,7 +3340,7 @@ bool QuicFramer::ProcessIetfStreamFrame(QuicDataReader* reader,
uint8_t frame_type,
QuicStreamFrame* frame) {
// Read stream id from the frame. It's always present.
- if (!reader->ReadVarIntStreamId(&frame->stream_id)) {
+ if (!reader->ReadVarIntU32(&frame->stream_id)) {
set_detailed_error("Unable to read stream_id.");
return false;
}
@@ -3958,10 +4063,228 @@ size_t QuicFramer::EncryptInPlace(EncryptionLevel level,
RaiseError(QUIC_ENCRYPTION_FAILURE);
return 0;
}
+ if (version_.HasHeaderProtection() &&
+ !ApplyHeaderProtection(level, buffer, ad_len + output_length, ad_len)) {
+ QUIC_DLOG(ERROR) << "Applying header protection failed.";
+ RaiseError(QUIC_ENCRYPTION_FAILURE);
+ return 0;
+ }
return ad_len + output_length;
}
+namespace {
+
+const size_t kHPSampleLen = 16;
+
+constexpr bool IsLongHeader(uint8_t type_byte) {
+ return (type_byte & FLAGS_LONG_HEADER) != 0;
+}
+
+} // namespace
+
+bool QuicFramer::ApplyHeaderProtection(EncryptionLevel level,
+ char* buffer,
+ size_t buffer_len,
+ size_t ad_len) {
+ QuicDataReader buffer_reader(buffer, buffer_len);
+ QuicDataWriter buffer_writer(buffer_len, buffer);
+ // The sample starts 4 bytes after the start of the packet number.
+ if (ad_len < last_written_packet_number_length_) {
+ return false;
+ }
+ size_t pn_offset = ad_len - last_written_packet_number_length_;
+ // Sample the ciphertext and generate the mask to use for header protection.
+ size_t sample_offset = pn_offset + 4;
+ QuicDataReader sample_reader(buffer, buffer_len);
+ QuicStringPiece sample;
+ if (!sample_reader.Seek(sample_offset) ||
+ !sample_reader.ReadStringPiece(&sample, kHPSampleLen)) {
+ QUIC_BUG << "Not enough bytes to sample: sample_offset " << sample_offset
+ << ", sample len: " << kHPSampleLen
+ << ", buffer len: " << buffer_len;
+ return false;
+ }
+
+ std::string mask = encrypter_[level]->GenerateHeaderProtectionMask(sample);
+ if (mask.empty()) {
+ QUIC_BUG << "Unable to generate header protection mask.";
+ return false;
+ }
+ QuicDataReader mask_reader(mask.data(), mask.size());
+
+ // Apply the mask to the 4 or 5 least significant bits of the first byte.
+ uint8_t bitmask = 0x1f;
+ uint8_t type_byte;
+ if (!buffer_reader.ReadUInt8(&type_byte)) {
+ return false;
+ }
+ QuicLongHeaderType header_type;
+ if (IsLongHeader(type_byte)) {
+ bitmask = 0x0f;
+ if (!GetLongHeaderType(version_.transport_version, type_byte,
+ &header_type)) {
+ return false;
+ }
+ }
+ uint8_t mask_byte;
+ if (!mask_reader.ReadUInt8(&mask_byte) ||
+ !buffer_writer.WriteUInt8(type_byte ^ (mask_byte & bitmask))) {
+ return false;
+ }
+
+ // Adjust |pn_offset| to account for the diversification nonce.
+ if (IsLongHeader(type_byte) && header_type == ZERO_RTT_PROTECTED &&
+ perspective_ == Perspective::IS_SERVER &&
+ version_.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
+ if (pn_offset <= kDiversificationNonceSize) {
+ QUIC_BUG << "Expected diversification nonce, but not enough bytes";
+ return false;
+ }
+ pn_offset -= kDiversificationNonceSize;
+ }
+ // Advance the reader and writer to the packet number. Both the reader and
+ // writer have each read/written one byte.
+ if (!buffer_writer.Seek(pn_offset - 1) ||
+ !buffer_reader.Seek(pn_offset - 1)) {
+ return false;
+ }
+ // Apply the rest of the mask to the packet number.
+ for (size_t i = 0; i < last_written_packet_number_length_; ++i) {
+ uint8_t buffer_byte;
+ uint8_t mask_byte;
+ if (!mask_reader.ReadUInt8(&mask_byte) ||
+ !buffer_reader.ReadUInt8(&buffer_byte) ||
+ !buffer_writer.WriteUInt8(buffer_byte ^ mask_byte)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool QuicFramer::RemoveHeaderProtection(QuicDataReader* reader,
+ const QuicEncryptedPacket& packet,
+ QuicPacketHeader* header,
+ uint64_t* full_packet_number,
+ std::vector<char>* associated_data) {
+ EncryptionLevel expected_decryption_level = GetEncryptionLevel(*header);
+ QuicDecrypter* decrypter = decrypter_[expected_decryption_level].get();
+ if (decrypter == nullptr) {
+ QUIC_DVLOG(1)
+ << "No decrypter available for removing header protection at level "
+ << expected_decryption_level;
+ return false;
+ }
+
+ bool has_diversification_nonce =
+ header->form == IETF_QUIC_LONG_HEADER_PACKET &&
+ header->long_packet_type == ZERO_RTT_PROTECTED &&
+ perspective_ == Perspective::IS_CLIENT &&
+ version_.handshake_protocol == PROTOCOL_QUIC_CRYPTO;
+
+ // Read a sample from the ciphertext and compute the mask to use for header
+ // protection.
+ QuicStringPiece remaining_packet = reader->PeekRemainingPayload();
+ QuicDataReader sample_reader(remaining_packet);
+
+ // The sample starts 4 bytes after the start of the packet number.
+ QuicStringPiece pn;
+ if (!sample_reader.ReadStringPiece(&pn, 4)) {
+ QUIC_DVLOG(1) << "Not enough data to sample";
+ return false;
+ }
+ if (has_diversification_nonce) {
+ // In Google QUIC, the diversification nonce comes between the packet number
+ // and the sample.
+ if (!sample_reader.Seek(kDiversificationNonceSize)) {
+ QUIC_DVLOG(1) << "No diversification nonce to skip over";
+ return false;
+ }
+ }
+ std::string mask = decrypter->GenerateHeaderProtectionMask(&sample_reader);
+ QuicDataReader mask_reader(mask.data(), mask.size());
+ if (mask.empty()) {
+ QUIC_DVLOG(1) << "Failed to compute mask";
+ return false;
+ }
+
+ // Unmask the rest of the type byte.
+ uint8_t bitmask = 0x1f;
+ if (IsLongHeader(header->type_byte)) {
+ bitmask = 0x0f;
+ }
+ uint8_t mask_byte;
+ if (!mask_reader.ReadUInt8(&mask_byte)) {
+ QUIC_DVLOG(1) << "No first byte to read from mask";
+ return false;
+ }
+ header->type_byte ^= (mask_byte & bitmask);
+
+ // Compute the packet number length.
+ header->packet_number_length =
+ static_cast<QuicPacketNumberLength>((header->type_byte & 0x03) + 1);
+
+ char pn_buffer[IETF_MAX_PACKET_NUMBER_LENGTH] = {};
+ QuicDataWriter pn_writer(QUIC_ARRAYSIZE(pn_buffer), pn_buffer);
+
+ // Read the (protected) packet number from the reader and unmask the packet
+ // number.
+ for (size_t i = 0; i < header->packet_number_length; ++i) {
+ uint8_t protected_pn_byte, mask_byte;
+ if (!mask_reader.ReadUInt8(&mask_byte) ||
+ !reader->ReadUInt8(&protected_pn_byte) ||
+ !pn_writer.WriteUInt8(protected_pn_byte ^ mask_byte)) {
+ QUIC_DVLOG(1) << "Failed to unmask packet number";
+ return false;
+ }
+ }
+ QuicDataReader packet_number_reader(pn_writer.data(), pn_writer.length());
+ QuicPacketNumber base_packet_number;
+ if (supports_multiple_packet_number_spaces_) {
+ PacketNumberSpace pn_space = GetPacketNumberSpace(*header);
+ if (pn_space == NUM_PACKET_NUMBER_SPACES) {
+ return false;
+ }
+ base_packet_number = largest_decrypted_packet_numbers_[pn_space];
+ } else {
+ base_packet_number = largest_packet_number_;
+ }
+ if (!ProcessAndCalculatePacketNumber(
+ &packet_number_reader, header->packet_number_length,
+ base_packet_number, full_packet_number)) {
+ return false;
+ }
+
+ // Get the associated data, and apply the same unmasking operations to it.
+ QuicStringPiece ad = GetAssociatedDataFromEncryptedPacket(
+ version_.transport_version, packet,
+ GetIncludedDestinationConnectionIdLength(*header),
+ GetIncludedSourceConnectionIdLength(*header), header->version_flag,
+ has_diversification_nonce, header->packet_number_length,
+ header->retry_token_length_length, header->retry_token.length(),
+ header->length_length);
+ *associated_data = std::vector<char>(ad.begin(), ad.end());
+ QuicDataWriter ad_writer(associated_data->size(), associated_data->data());
+
+ // Apply the unmasked type byte and packet number to |associated_data|.
+ if (!ad_writer.WriteUInt8(header->type_byte)) {
+ return false;
+ }
+ // Put the packet number at the end of the AD, or if there's a diversification
+ // nonce, before that (which is at the end of the AD).
+ size_t seek_len = ad_writer.remaining() - header->packet_number_length;
+ if (has_diversification_nonce) {
+ seek_len -= kDiversificationNonceSize;
+ }
+ if (!ad_writer.Seek(seek_len) ||
+ !ad_writer.WriteBytes(pn_writer.data(), pn_writer.length())) {
+ QUIC_DVLOG(1) << "Failed to apply unmasking operations to AD";
+ return false;
+ }
+
+ return true;
+}
+
size_t QuicFramer::EncryptPayload(EncryptionLevel level,
QuicPacketNumber packet_number,
const QuicPacket& packet,
@@ -3990,6 +4313,12 @@ size_t QuicFramer::EncryptPayload(EncryptionLevel level,
RaiseError(QUIC_ENCRYPTION_FAILURE);
return 0;
}
+ if (version_.HasHeaderProtection() &&
+ !ApplyHeaderProtection(level, buffer, ad_len + output_length, ad_len)) {
+ QUIC_DLOG(ERROR) << "Applying header protection failed.";
+ RaiseError(QUIC_ENCRYPTION_FAILURE);
+ return 0;
+ }
return ad_len + output_length;
}
@@ -4023,11 +4352,24 @@ bool QuicFramer::DecryptPayload(QuicStringPiece encrypted,
size_t buffer_length,
size_t* decrypted_length,
EncryptionLevel* decrypted_level) {
+ if (!EncryptionLevelIsValid(decrypter_level_)) {
+ QUIC_BUG << "Attempted to decrypt with bad decrypter_level_";
+ return false;
+ }
EncryptionLevel level = decrypter_level_;
QuicDecrypter* decrypter = decrypter_[level].get();
QuicDecrypter* alternative_decrypter = nullptr;
if (version().KnowsWhichDecrypterToUse()) {
+ if (header.form == GOOGLE_QUIC_PACKET) {
+ QUIC_BUG << "Attempted to decrypt GOOGLE_QUIC_PACKET with a version that "
+ "knows which decrypter to use";
+ return false;
+ }
level = GetEncryptionLevel(header);
+ if (!EncryptionLevelIsValid(level)) {
+ QUIC_BUG << "Attempted to decrypt with bad level";
+ return false;
+ }
decrypter = decrypter_[level].get();
if (decrypter == nullptr) {
return false;
@@ -4037,10 +4379,18 @@ bool QuicFramer::DecryptPayload(QuicStringPiece encrypted,
decrypter->SetDiversificationNonce(*header.nonce);
}
} else if (alternative_decrypter_level_ != NUM_ENCRYPTION_LEVELS) {
+ if (!EncryptionLevelIsValid(alternative_decrypter_level_)) {
+ QUIC_BUG << "Attempted to decrypt with bad alternative_decrypter_level_";
+ return false;
+ }
alternative_decrypter = decrypter_[alternative_decrypter_level_].get();
}
- DCHECK(decrypter != nullptr);
+ if (decrypter == nullptr) {
+ QUIC_BUG << "Attempting to decrypt without decrypter, encryption level:"
+ << level << " version:" << version();
+ return false;
+ }
bool success = decrypter->DecryptPacket(
header.packet_number.ToUint64(), associated_data, encrypted,
@@ -4074,11 +4424,14 @@ bool QuicFramer::DecryptPayload(QuicStringPiece encrypted,
visitor_->OnDecryptedPacket(alternative_decrypter_level_);
*decrypted_level = decrypter_level_;
if (alternative_decrypter_latch_) {
+ if (!EncryptionLevelIsValid(alternative_decrypter_level_)) {
+ QUIC_BUG << "Attempted to latch alternate decrypter with bad "
+ "alternative_decrypter_level_";
+ return false;
+ }
// Switch to the alternative decrypter and latch so that we cannot
// switch back.
decrypter_level_ = alternative_decrypter_level_;
- decrypter_[decrypter_level_] =
- std::move(decrypter_[alternative_decrypter_level_]);
alternative_decrypter_level_ = NUM_ENCRYPTION_LEVELS;
} else {
// Switch the alternative decrypter so that we use it first next time.
@@ -4090,8 +4443,7 @@ bool QuicFramer::DecryptPayload(QuicStringPiece encrypted,
}
if (!success) {
- QUIC_DVLOG(1) << ENDPOINT << "DecryptPacket failed for packet_number:"
- << header.packet_number;
+ QUIC_DVLOG(1) << ENDPOINT << "DecryptPacket failed for: " << header;
return false;
}
@@ -4296,13 +4648,13 @@ bool QuicFramer::AppendTypeByte(const QuicFrame& frame,
set_detailed_error(
"Attempt to append NEW_TOKEN frame and not in version 99.");
return RaiseError(QUIC_INTERNAL_ERROR);
- case MAX_STREAM_ID_FRAME:
+ case MAX_STREAMS_FRAME:
set_detailed_error(
- "Attempt to append MAX_STREAM_ID frame and not in version 99.");
+ "Attempt to append MAX_STREAMS frame and not in version 99.");
return RaiseError(QUIC_INTERNAL_ERROR);
- case STREAM_ID_BLOCKED_FRAME:
+ case STREAMS_BLOCKED_FRAME:
set_detailed_error(
- "Attempt to append STREAM_ID_BLOCKED frame and not in version 99.");
+ "Attempt to append STREAMS_BLOCKED frame and not in version 99.");
return RaiseError(QUIC_INTERNAL_ERROR);
case PATH_RESPONSE_FRAME:
set_detailed_error(
@@ -4401,20 +4753,18 @@ bool QuicFramer::AppendIetfTypeByte(const QuicFrame& frame,
case NEW_TOKEN_FRAME:
type_byte = IETF_NEW_TOKEN;
break;
- case MAX_STREAM_ID_FRAME:
- if (QuicUtils::IsBidirectionalStreamId(
- frame.max_stream_id_frame.max_stream_id)) {
- type_byte = IETF_MAX_STREAMS_BIDIRECTIONAL;
- } else {
+ case MAX_STREAMS_FRAME:
+ if (frame.max_streams_frame.unidirectional) {
type_byte = IETF_MAX_STREAMS_UNIDIRECTIONAL;
+ } else {
+ type_byte = IETF_MAX_STREAMS_BIDIRECTIONAL;
}
break;
- case STREAM_ID_BLOCKED_FRAME:
- if (QuicUtils::IsBidirectionalStreamId(
- frame.max_stream_id_frame.max_stream_id)) {
- type_byte = IETF_STREAMS_BLOCKED_BIDIRECTIONAL;
- } else {
+ case STREAMS_BLOCKED_FRAME:
+ if (frame.streams_blocked_frame.unidirectional) {
type_byte = IETF_STREAMS_BLOCKED_UNIDIRECTIONAL;
+ } else {
+ type_byte = IETF_STREAMS_BLOCKED_BIDIRECTIONAL;
}
break;
case PATH_RESPONSE_FRAME:
@@ -4538,34 +4888,6 @@ bool QuicFramer::AppendStreamFrame(const QuicStreamFrame& frame,
return true;
}
-// static
-bool QuicFramer::AppendIetfConnectionId(
- bool version_flag,
- QuicConnectionId destination_connection_id,
- QuicConnectionIdLength destination_connection_id_length,
- QuicConnectionId source_connection_id,
- QuicConnectionIdLength source_connection_id_length,
- QuicDataWriter* writer) {
- if (version_flag) {
- // Append connection ID length byte.
- uint8_t dcil = GetConnectionIdLengthValue(destination_connection_id_length);
- uint8_t scil = GetConnectionIdLengthValue(source_connection_id_length);
- uint8_t connection_id_length = dcil << 4 | scil;
- if (!writer->WriteBytes(&connection_id_length, 1)) {
- return false;
- }
- }
- if (destination_connection_id_length == PACKET_8BYTE_CONNECTION_ID &&
- !writer->WriteConnectionId(destination_connection_id)) {
- return false;
- }
- if (source_connection_id_length == PACKET_8BYTE_CONNECTION_ID &&
- !writer->WriteConnectionId(source_connection_id)) {
- return false;
- }
- return true;
-}
-
bool QuicFramer::AppendNewTokenFrame(const QuicNewTokenFrame& frame,
QuicDataWriter* writer) {
if (!writer->WriteVarInt62(static_cast<uint64_t>(frame.token.length()))) {
@@ -5212,7 +5534,9 @@ bool QuicFramer::RaiseError(QuicErrorCode error) {
QUIC_DLOG(INFO) << ENDPOINT << "Error: " << QuicErrorCodeToString(error)
<< " detail: " << detailed_error_;
set_error(error);
- visitor_->OnError(this);
+ if (visitor_) {
+ visitor_->OnError(this);
+ }
return false;
}
@@ -5220,9 +5544,13 @@ bool QuicFramer::IsVersionNegotiation(
const QuicPacketHeader& header,
bool packet_has_ietf_packet_header) const {
if (perspective_ == Perspective::IS_SERVER) {
- return false;
+ if (!GetQuicRestartFlag(quic_server_drop_version_negotiation)) {
+ return false;
+ }
+ QUIC_RESTART_FLAG_COUNT_N(quic_server_drop_version_negotiation, 2, 2);
}
- if (!packet_has_ietf_packet_header) {
+ if (!packet_has_ietf_packet_header &&
+ perspective_ == Perspective::IS_CLIENT) {
return header.version_flag;
}
if (header.form == IETF_QUIC_SHORT_HEADER_PACKET) {
@@ -5372,7 +5700,7 @@ bool QuicFramer::ProcessIetfResetStreamFrame(QuicDataReader* reader,
// Get Stream ID from frame. ReadVarIntStreamID returns false
// if either A) there is a read error or B) the resulting value of
// the Stream ID is larger than the maximum allowed value.
- if (!reader->ReadVarIntStreamId(&frame->stream_id)) {
+ if (!reader->ReadVarIntU32(&frame->stream_id)) {
set_detailed_error("Unable to read rst stream stream id.");
return false;
}
@@ -5392,7 +5720,7 @@ bool QuicFramer::ProcessIetfResetStreamFrame(QuicDataReader* reader,
bool QuicFramer::ProcessStopSendingFrame(
QuicDataReader* reader,
QuicStopSendingFrame* stop_sending_frame) {
- if (!reader->ReadVarIntStreamId(&stop_sending_frame->stream_id)) {
+ if (!reader->ReadVarIntU32(&stop_sending_frame->stream_id)) {
set_detailed_error("Unable to read stop sending stream id.");
return false;
}
@@ -5454,7 +5782,7 @@ bool QuicFramer::AppendMaxStreamDataFrame(const QuicWindowUpdateFrame& frame,
bool QuicFramer::ProcessMaxStreamDataFrame(QuicDataReader* reader,
QuicWindowUpdateFrame* frame) {
- if (!reader->ReadVarIntStreamId(&frame->stream_id)) {
+ if (!reader->ReadVarIntU32(&frame->stream_id)) {
set_detailed_error("Can not read MAX_STREAM_DATA stream id");
return false;
}
@@ -5465,13 +5793,9 @@ bool QuicFramer::ProcessMaxStreamDataFrame(QuicDataReader* reader,
return true;
}
-bool QuicFramer::AppendMaxStreamsFrame(const QuicMaxStreamIdFrame& frame,
+bool QuicFramer::AppendMaxStreamsFrame(const QuicMaxStreamsFrame& frame,
QuicDataWriter* writer) {
- // Convert from the stream id on which the connection is blocked to a count
- QuicStreamId stream_count =
- StreamIdToCount(version_.transport_version, frame.max_stream_id);
-
- if (!writer->WriteVarInt62(stream_count)) {
+ if (!writer->WriteVarInt62(frame.stream_count)) {
set_detailed_error("Can not write MAX_STREAMS stream count");
return false;
}
@@ -5479,33 +5803,14 @@ bool QuicFramer::AppendMaxStreamsFrame(const QuicMaxStreamIdFrame& frame,
}
bool QuicFramer::ProcessMaxStreamsFrame(QuicDataReader* reader,
- QuicMaxStreamIdFrame* frame,
+ QuicMaxStreamsFrame* frame,
uint64_t frame_type) {
- QuicStreamId received_stream_count;
- if (!reader->ReadVarIntStreamId(&received_stream_count)) {
+ if (!reader->ReadVarIntU32(&frame->stream_count)) {
set_detailed_error("Can not read MAX_STREAMS stream count.");
return false;
}
- // TODO(fkastenholz): handle properly when the STREAMS_BLOCKED
- // frame is implemented and passed up to the stream ID manager.
- if (received_stream_count == 0) {
- set_detailed_error("MAX_STREAMS stream count of 0 not supported.");
- return false;
- }
- // Note that this code assumes that the only possible error that
- // StreamCountToId can detect is that the stream count is too big or is 0.
- // Too big is prevented by passing in the minimum of the received count
- // and the maximum supported count, ensuring that the stream ID is
- // pegged at the maximum allowed ID.
- // count==0 is handled above, so that detailed_error_ may be set
- // properly.
- return StreamCountToId(
- std::min(
- received_stream_count,
- GetMaxStreamCount((frame_type == IETF_MAX_STREAMS_UNIDIRECTIONAL),
- perspective_)),
- /*unidirectional=*/(frame_type == IETF_MAX_STREAMS_UNIDIRECTIONAL),
- perspective_, version_.transport_version, &frame->max_stream_id);
+ frame->unidirectional = (frame_type == IETF_MAX_STREAMS_UNIDIRECTIONAL);
+ return true;
}
bool QuicFramer::AppendIetfBlockedFrame(const QuicBlockedFrame& frame,
@@ -5543,7 +5848,7 @@ bool QuicFramer::AppendStreamBlockedFrame(const QuicBlockedFrame& frame,
bool QuicFramer::ProcessStreamBlockedFrame(QuicDataReader* reader,
QuicBlockedFrame* frame) {
- if (!reader->ReadVarIntStreamId(&frame->stream_id)) {
+ if (!reader->ReadVarIntU32(&frame->stream_id)) {
set_detailed_error("Can not read stream blocked stream id.");
return false;
}
@@ -5554,14 +5859,9 @@ bool QuicFramer::ProcessStreamBlockedFrame(QuicDataReader* reader,
return true;
}
-bool QuicFramer::AppendStreamsBlockedFrame(
- const QuicStreamIdBlockedFrame& frame,
- QuicDataWriter* writer) {
- // Convert from the stream id on which the connection is blocked to a count
- QuicStreamId stream_count =
- StreamIdToCount(version_.transport_version, frame.stream_id);
-
- if (!writer->WriteVarInt62(stream_count)) {
+bool QuicFramer::AppendStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame,
+ QuicDataWriter* writer) {
+ if (!writer->WriteVarInt62(frame.stream_count)) {
set_detailed_error("Can not write STREAMS_BLOCKED stream count");
return false;
}
@@ -5569,43 +5869,29 @@ bool QuicFramer::AppendStreamsBlockedFrame(
}
bool QuicFramer::ProcessStreamsBlockedFrame(QuicDataReader* reader,
- QuicStreamIdBlockedFrame* frame,
+ QuicStreamsBlockedFrame* frame,
uint64_t frame_type) {
- QuicStreamId received_stream_count;
- if (!reader->ReadVarIntStreamId(&received_stream_count)) {
- set_detailed_error("Can not read STREAMS_BLOCKED stream id.");
- return false;
- }
- // TODO(fkastenholz): handle properly when the STREAMS_BLOCKED
- // frame is implemented and passed up to the stream ID manager.
- if (received_stream_count == 0) {
- set_detailed_error("STREAMS_BLOCKED stream count 0 not supported.");
+ if (!reader->ReadVarIntU32(&frame->stream_count)) {
+ set_detailed_error("Can not read STREAMS_BLOCKED stream count.");
return false;
}
+ frame->unidirectional = (frame_type == IETF_STREAMS_BLOCKED_UNIDIRECTIONAL);
+
// TODO(fkastenholz): handle properly when the STREAMS_BLOCKED
// frame is implemented and passed up to the stream ID manager.
- if (received_stream_count >
- GetMaxStreamCount((frame_type == IETF_MAX_STREAMS_UNIDIRECTIONAL),
- ((perspective_ == Perspective::IS_CLIENT)
- ? Perspective::IS_SERVER
- : Perspective::IS_CLIENT))) {
+ if (frame->stream_count >
+ QuicUtils::GetMaxStreamCount(
+ (frame_type == IETF_STREAMS_BLOCKED_UNIDIRECTIONAL),
+ ((perspective_ == Perspective::IS_CLIENT)
+ ? Perspective::IS_SERVER
+ : Perspective::IS_CLIENT))) {
// If stream count is such that the resulting stream ID would exceed our
// implementation limit, generate an error.
set_detailed_error(
"STREAMS_BLOCKED stream count exceeds implementation limit.");
return false;
}
- // Convert the stream count to an ID that can be used.
- // The STREAMS_BLOCKED frame is a request for more streams
- // that the peer will initiate. If this node is a client, it
- // means that the peer is a server, and wants server-initiated
- // stream IDs.
- return StreamCountToId(
- received_stream_count,
- /*unidirectional=*/(frame_type == IETF_STREAMS_BLOCKED_UNIDIRECTIONAL),
- (perspective_ == Perspective::IS_CLIENT) ? Perspective::IS_SERVER
- : Perspective::IS_CLIENT,
- version_.transport_version, &frame->stream_id);
+ return true;
}
bool QuicFramer::AppendNewConnectionIdFrame(
@@ -5763,5 +6049,233 @@ void QuicFramer::EnableMultiplePacketNumberSpacesSupport() {
supports_multiple_packet_number_spaces_ = true;
}
+// static
+QuicErrorCode QuicFramer::ProcessPacketDispatcher(
+ const QuicEncryptedPacket& packet,
+ uint8_t expected_connection_id_length,
+ PacketHeaderFormat* format,
+ bool* version_flag,
+ QuicVersionLabel* version_label,
+ uint8_t* destination_connection_id_length,
+ QuicConnectionId* destination_connection_id,
+ std::string* detailed_error) {
+ QuicDataReader reader(packet.data(), packet.length());
+
+ uint8_t first_byte;
+ if (!reader.ReadBytes(&first_byte, 1)) {
+ *detailed_error = "Unable to read first byte.";
+ return QUIC_INVALID_PACKET_HEADER;
+ }
+ if (!QuicUtils::IsIetfPacketHeader(first_byte)) {
+ *format = GOOGLE_QUIC_PACKET;
+ *version_flag = (first_byte & PACKET_PUBLIC_FLAGS_VERSION) != 0;
+ *destination_connection_id_length =
+ first_byte & PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID;
+ if (*destination_connection_id_length == 0 ||
+ !reader.ReadConnectionId(destination_connection_id,
+ *destination_connection_id_length)) {
+ *detailed_error = "Unable to read ConnectionId.";
+ return QUIC_INVALID_PACKET_HEADER;
+ }
+ if (*version_flag && !ProcessVersionLabel(&reader, version_label)) {
+ *detailed_error = "Unable to read protocol version.";
+ return QUIC_INVALID_PACKET_HEADER;
+ }
+ return QUIC_NO_ERROR;
+ }
+
+ *format = GetIetfPacketHeaderFormat(first_byte);
+ QUIC_DVLOG(1) << "Dispatcher: Processing IETF QUIC packet, format: "
+ << *format;
+ *version_flag = *format == IETF_QUIC_LONG_HEADER_PACKET;
+ if (*format == IETF_QUIC_LONG_HEADER_PACKET) {
+ if (!ProcessVersionLabel(&reader, version_label)) {
+ *detailed_error = "Unable to read protocol version.";
+ return QUIC_INVALID_PACKET_HEADER;
+ }
+ // Set should_update_expected_server_connection_id_length to true to bypass
+ // connection ID lengths validation.
+ uint8_t unused_source_connection_id_length = 0;
+ uint8_t unused_expected_server_connection_id_length = 0;
+ if (!ProcessAndValidateIetfConnectionIdLength(
+ &reader, ParseQuicVersionLabel(*version_label),
+ /*should_update_expected_server_connection_id_length=*/true,
+ &unused_expected_server_connection_id_length,
+ destination_connection_id_length,
+ &unused_source_connection_id_length, detailed_error)) {
+ return QUIC_INVALID_PACKET_HEADER;
+ }
+ } else {
+ // For short header packets, expected_connection_id_length is used to
+ // determine the destination_connection_id_length.
+ *destination_connection_id_length = expected_connection_id_length;
+ }
+ // Read destination connection ID.
+ if (!reader.ReadConnectionId(destination_connection_id,
+ *destination_connection_id_length)) {
+ *detailed_error = "Unable to read Destination ConnectionId.";
+ return QUIC_INVALID_PACKET_HEADER;
+ }
+ return QUIC_NO_ERROR;
+}
+
+// static
+bool QuicFramer::WriteClientVersionNegotiationProbePacket(
+ char* packet_bytes,
+ QuicByteCount packet_length,
+ const char* destination_connection_id_bytes,
+ uint8_t destination_connection_id_length) {
+ if (packet_bytes == nullptr) {
+ QUIC_BUG << "Invalid packet_bytes";
+ return false;
+ }
+ if (packet_length < kMinPacketSizeForVersionNegotiation ||
+ packet_length > 65535) {
+ QUIC_BUG << "Invalid packet_length";
+ return false;
+ }
+ if (destination_connection_id_length > kQuicMaxConnectionIdLength ||
+ (destination_connection_id_length > 0 &&
+ destination_connection_id_length < 4)) {
+ QUIC_BUG << "Invalid connection_id_length";
+ return false;
+ }
+ // clang-format off
+ static const unsigned char packet_start_bytes[] = {
+ // IETF long header with fixed bit set, type initial, all-0 encrypted bits.
+ 0xc0,
+ // Version, part of the IETF space reserved for negotiation.
+ // This intentionally differs from QuicVersionReservedForNegotiation()
+ // to allow differentiating them over the wire.
+ 0xca, 0xba, 0xda, 0xba,
+ };
+ // clang-format on
+ static_assert(sizeof(packet_start_bytes) == 5, "bad packet_start_bytes size");
+ QuicDataWriter writer(packet_length, packet_bytes);
+ if (!writer.WriteBytes(packet_start_bytes, sizeof(packet_start_bytes))) {
+ QUIC_BUG << "Failed to write packet start";
+ return false;
+ }
+
+ QuicConnectionId destination_connection_id(destination_connection_id_bytes,
+ destination_connection_id_length);
+ if (!AppendIetfConnectionIds(/*version_flag=*/true, destination_connection_id,
+ EmptyQuicConnectionId(), &writer)) {
+ QUIC_BUG << "Failed to write connection IDs";
+ return false;
+ }
+ // Add 8 bytes of zeroes followed by 8 bytes of ones to ensure that this does
+ // not parse with any known version. The zeroes make sure that packet numbers,
+ // retry token lengths and payload lengths are parsed as zero, and if the
+ // zeroes are treated as padding frames, 0xff is known to not parse as a
+ // valid frame type.
+ if (!writer.WriteUInt64(0) ||
+ !writer.WriteUInt64(std::numeric_limits<uint64_t>::max())) {
+ QUIC_BUG << "Failed to write 18 bytes";
+ return false;
+ }
+ // Make sure the polite greeting below is padded to a 16-byte boundary to
+ // make it easier to read in tcpdump.
+ while (writer.length() % 16 != 0) {
+ if (!writer.WriteUInt8(0)) {
+ QUIC_BUG << "Failed to write padding byte";
+ return false;
+ }
+ }
+ // Add a polite greeting in case a human sees this in tcpdump.
+ static const char polite_greeting[] =
+ "This packet only exists to trigger IETF QUIC version negotiation. "
+ "Please respond with a Version Negotiation packet indicating what "
+ "versions you support. Thank you and have a nice day.";
+ if (!writer.WriteBytes(polite_greeting, sizeof(polite_greeting))) {
+ QUIC_BUG << "Failed to write polite greeting";
+ return false;
+ }
+ // Fill the rest of the packet with zeroes.
+ writer.WritePadding();
+ DCHECK_EQ(0u, writer.remaining());
+ return true;
+}
+
+// static
+bool QuicFramer::ParseServerVersionNegotiationProbeResponse(
+ const char* packet_bytes,
+ QuicByteCount packet_length,
+ char* source_connection_id_bytes,
+ uint8_t* source_connection_id_length_out,
+ std::string* detailed_error) {
+ if (detailed_error == nullptr) {
+ QUIC_BUG << "Invalid error_details";
+ return false;
+ }
+ *detailed_error = "";
+ if (packet_bytes == nullptr) {
+ *detailed_error = "Invalid packet_bytes";
+ return false;
+ }
+ if (packet_length < 6) {
+ *detailed_error = "Invalid packet_length";
+ return false;
+ }
+ if (source_connection_id_bytes == nullptr) {
+ *detailed_error = "Invalid source_connection_id_bytes";
+ return false;
+ }
+ if (source_connection_id_length_out == nullptr) {
+ *detailed_error = "Invalid source_connection_id_length_out";
+ return false;
+ }
+ QuicDataReader reader(packet_bytes, packet_length);
+ uint8_t type_byte = 0;
+ if (!reader.ReadUInt8(&type_byte)) {
+ *detailed_error = "Failed to read type byte";
+ return false;
+ }
+ if ((type_byte & 0x80) == 0) {
+ *detailed_error = "Packet does not have long header";
+ return false;
+ }
+ uint32_t version = 0;
+ if (!reader.ReadUInt32(&version)) {
+ *detailed_error = "Failed to read version";
+ return false;
+ }
+ if (version != 0) {
+ *detailed_error = "Packet is not a version negotiation packet";
+ return false;
+ }
+ uint8_t expected_server_connection_id_length = 0,
+ destination_connection_id_length = 0, source_connection_id_length = 0;
+ if (!ProcessAndValidateIetfConnectionIdLength(
+ &reader, UnsupportedQuicVersion(),
+ /*should_update_expected_server_connection_id_length=*/true,
+ &expected_server_connection_id_length,
+ &destination_connection_id_length, &source_connection_id_length,
+ detailed_error)) {
+ return false;
+ }
+ if (destination_connection_id_length != 0) {
+ *detailed_error = "Received unexpected destination connection ID length";
+ return false;
+ }
+ QuicConnectionId destination_connection_id, source_connection_id;
+ if (!reader.ReadConnectionId(&destination_connection_id,
+ destination_connection_id_length)) {
+ *detailed_error = "Failed to read destination connection ID";
+ return false;
+ }
+ if (!reader.ReadConnectionId(&source_connection_id,
+ source_connection_id_length)) {
+ *detailed_error = "Failed to read source connection ID";
+ return false;
+ }
+
+ memcpy(source_connection_id_bytes, source_connection_id.data(),
+ source_connection_id_length);
+ *source_connection_id_length_out = source_connection_id_length;
+
+ return true;
+}
+
#undef ENDPOINT // undef for jumbo builds
} // namespace quic
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 90ef99815f1..11d48bbafb2 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
@@ -13,6 +13,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
#include "net/third_party/quiche/src/quic/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_packets.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"
@@ -92,6 +93,12 @@ class QUIC_EXPORT_PRIVATE QuicFramerVisitorInterface {
virtual void OnVersionNegotiationPacket(
const QuicVersionNegotiationPacket& packet) = 0;
+ // Called only when |perspective_| is IS_CLIENT and a retry packet has been
+ // parsed.
+ virtual void OnRetryPacket(QuicConnectionId original_connection_id,
+ QuicConnectionId new_connection_id,
+ QuicStringPiece retry_token) = 0;
+
// Called when all fields except packet number has been parsed, but has not
// been authenticated. If it returns false, framing for this packet will
// cease.
@@ -201,12 +208,11 @@ class QUIC_EXPORT_PRIVATE QuicFramerVisitorInterface {
virtual void OnAuthenticatedIetfStatelessResetPacket(
const QuicIetfStatelessResetPacket& packet) = 0;
- // Called when an IETF MaxStreamId frame has been parsed.
- virtual bool OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) = 0;
+ // Called when an IETF MaxStreams frame has been parsed.
+ virtual bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) = 0;
- // Called when an IETF StreamIdBlocked frame has been parsed.
- virtual bool OnStreamIdBlockedFrame(
- const QuicStreamIdBlockedFrame& frame) = 0;
+ // Called when an IETF StreamsBlocked frame has been parsed.
+ virtual bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) = 0;
};
// Class for parsing and constructing QUIC packets. It has a
@@ -220,7 +226,7 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
QuicFramer(const ParsedQuicVersionVector& supported_versions,
QuicTime creation_time,
Perspective perspective,
- uint8_t expected_connection_id_length);
+ uint8_t expected_server_connection_id_length);
QuicFramer(const QuicFramer&) = delete;
QuicFramer& operator=(const QuicFramer&) = delete;
@@ -264,7 +270,7 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
}
// Pass a UDP packet into the framer for parsing.
- // Return true if the packet was processed succesfully. |packet| must be a
+ // Return true if the packet was processed successfully. |packet| must be a
// single, complete UDP packet (not a frame of a packet). This packet
// might be null padded past the end of the payload, which will be correctly
// ignored.
@@ -295,9 +301,9 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
// Size in bytes of all reset stream frame fields.
static size_t GetRstStreamFrameSize(QuicTransportVersion version,
const QuicRstStreamFrame& frame);
- // Size in bytes of all connection close frame fields without the error
- // details and the missing packets from the enclosed ack frame.
- static size_t GetMinConnectionCloseFrameSize(
+ // Size in bytes of all connection close frame fields, including the error
+ // details.
+ static size_t GetConnectionCloseFrameSize(
QuicTransportVersion version,
const QuicConnectionCloseFrame& frame);
// Size in bytes of all GoAway frame fields without the reason phrase.
@@ -309,11 +315,11 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
const QuicWindowUpdateFrame& frame);
// Size in bytes of all MaxStreams frame fields.
static size_t GetMaxStreamsFrameSize(QuicTransportVersion version,
- const QuicMaxStreamIdFrame& frame);
+ const QuicMaxStreamsFrame& frame);
// Size in bytes of all StreamsBlocked frame fields.
static size_t GetStreamsBlockedFrameSize(
QuicTransportVersion version,
- const QuicStreamIdBlockedFrame& frame);
+ const QuicStreamsBlockedFrame& frame);
// Size in bytes of all Blocked frame fields.
static size_t GetBlockedFrameSize(QuicTransportVersion version,
const QuicBlockedFrame& frame);
@@ -367,6 +373,21 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
uint64_t retry_token_length,
QuicVariableLengthIntegerLength length_length);
+ // Lightweight parsing of |packet| and populates |format|, |version_flag|,
+ // |version_label|, |destination_connection_id_length|,
+ // |destination_connection_id| and |detailed_error|. Please note,
+ // |expected_connection_id_length| is only used to determine IETF short header
+ // packet's destination connection ID length.
+ static QuicErrorCode ProcessPacketDispatcher(
+ const QuicEncryptedPacket& packet,
+ uint8_t expected_connection_id_length,
+ PacketHeaderFormat* format,
+ bool* version_flag,
+ QuicVersionLabel* version_label,
+ uint8_t* destination_connection_id_length,
+ QuicConnectionId* destination_connection_id,
+ std::string* detailed_error);
+
// Serializes a packet containing |frames| into |buffer|.
// Returns the length of the packet, which must not be longer than
// |packet_length|. Returns 0 if it fails to serialize.
@@ -414,13 +435,15 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
// Returns a new version negotiation packet.
static std::unique_ptr<QuicEncryptedPacket> BuildVersionNegotiationPacket(
- QuicConnectionId connection_id,
+ QuicConnectionId server_connection_id,
+ QuicConnectionId client_connection_id,
bool ietf_quic,
const ParsedQuicVersionVector& versions);
// Returns a new IETF version negotiation packet.
static std::unique_ptr<QuicEncryptedPacket> BuildIetfVersionNegotiationPacket(
- QuicConnectionId connection_id,
+ QuicConnectionId server_connection_id,
+ QuicConnectionId client_connection_id,
const ParsedQuicVersionVector& versions);
// If header.version_flag is set, the version in the
@@ -554,19 +577,52 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
// If true, QuicFramer will change its expected connection ID length
// to the received destination connection ID length of all IETF long headers.
- void SetShouldUpdateExpectedConnectionIdLength(
- bool should_update_expected_connection_id_length) {
- should_update_expected_connection_id_length_ =
- should_update_expected_connection_id_length;
+ void SetShouldUpdateExpectedServerConnectionIdLength(
+ bool should_update_expected_server_connection_id_length) {
+ should_update_expected_server_connection_id_length_ =
+ should_update_expected_server_connection_id_length;
}
- // The connection ID length the framer expects on incoming IETF short headers.
- uint8_t GetExpectedConnectionIdLength() {
- return expected_connection_id_length_;
+ // The connection ID length the framer expects on incoming IETF short headers
+ // on the server.
+ uint8_t GetExpectedServerConnectionIdLength() {
+ return expected_server_connection_id_length_;
}
void EnableMultiplePacketNumberSpacesSupport();
+ // Writes an array of bytes that, if sent as a UDP datagram, will trigger
+ // IETF QUIC Version Negotiation on servers. The bytes will be written to
+ // |packet_bytes|, which must point to |packet_length| bytes of memory.
+ // |packet_length| must be in the range [1200, 65535].
+ // |destination_connection_id_bytes| will be sent as the destination
+ // connection ID, and must point to |destination_connection_id_length| bytes
+ // of memory. |destination_connection_id_length| must be either 0 or in the
+ // range [4,18]. When targeting Google servers, it is recommended to use a
+ // |destination_connection_id_length| of 8.
+ static bool WriteClientVersionNegotiationProbePacket(
+ char* packet_bytes,
+ QuicByteCount packet_length,
+ const char* destination_connection_id_bytes,
+ uint8_t destination_connection_id_length);
+
+ // Parses a packet which a QUIC server sent in response to a packet sent by
+ // WriteClientVersionNegotiationProbePacket. |packet_bytes| must point to
+ // |packet_length| bytes in memory which represent the response.
+ // |packet_length| must be greater or equal to 6. This method will fill in
+ // |source_connection_id_bytes| which must point to at least 18 bytes in
+ // memory. |source_connection_id_length_out| will contain the length of the
+ // received source connection ID, which on success will match the contents of
+ // the destination connection ID passed in to
+ // WriteClientVersionNegotiationProbePacket. In the case of a failure,
+ // |detailed_error| will be filled in with an explanation of what failed.
+ static bool ParseServerVersionNegotiationProbeResponse(
+ const char* packet_bytes,
+ QuicByteCount packet_length,
+ char* source_connection_id_bytes,
+ uint8_t* source_connection_id_length_out,
+ std::string* detailed_error);
+
private:
friend class test::QuicFramerPeer;
@@ -585,6 +641,34 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
size_t num_ack_blocks;
};
+ // Applies header protection to an IETF QUIC packet header in |buffer| using
+ // the encrypter for level |level|. The buffer has |buffer_len| bytes of data,
+ // with the first protected packet bytes starting at |ad_len|.
+ bool ApplyHeaderProtection(EncryptionLevel level,
+ char* buffer,
+ size_t buffer_len,
+ size_t ad_len);
+
+ // Removes header protection from an IETF QUIC packet header.
+ //
+ // The packet number from the header is read from |reader|, where the packet
+ // number is the next contents in |reader|. |reader| is only advanced by the
+ // length of the packet number, but it is also used to peek the sample needed
+ // for removing header protection.
+ //
+ // Properties needed for removing header protection are read from |header|.
+ // The packet number length and type byte are written to |header|.
+ //
+ // The packet number, after removing header protection and decoding it, is
+ // written to |full_packet_number|. Finally, the header, with header
+ // protection removed, is written to |associated_data| to be used in packet
+ // decryption. |packet| is used in computing the asociated data.
+ bool RemoveHeaderProtection(QuicDataReader* reader,
+ const QuicEncryptedPacket& packet,
+ QuicPacketHeader* header,
+ uint64_t* full_packet_number,
+ std::vector<char>* associated_data);
+
bool ProcessDataPacket(QuicDataReader* reader,
QuicPacketHeader* header,
const QuicEncryptedPacket& packet,
@@ -603,6 +687,9 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
bool ProcessVersionNegotiationPacket(QuicDataReader* reader,
const QuicPacketHeader& header);
+ bool ProcessRetryPacket(QuicDataReader* reader,
+ const QuicPacketHeader& header);
+
bool MaybeProcessIetfInitialRetryToken(QuicDataReader* encrypted_reader,
QuicPacketHeader* header);
@@ -622,6 +709,21 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
bool ProcessUnauthenticatedHeader(QuicDataReader* encrypted_reader,
QuicPacketHeader* header);
+ // Processes the version label in the packet header.
+ static bool ProcessVersionLabel(QuicDataReader* reader,
+ QuicVersionLabel* version_label);
+
+ // Validates and updates |destination_connection_id_length| and
+ // |source_connection_id_length|.
+ static bool ProcessAndValidateIetfConnectionIdLength(
+ QuicDataReader* reader,
+ ParsedQuicVersion version,
+ bool should_update_expected_server_connection_id_length,
+ uint8_t* expected_server_connection_id_length,
+ uint8_t* destination_connection_id_length,
+ uint8_t* source_connection_id_length,
+ std::string* detailed_error);
+
bool ProcessIetfHeaderTypeByte(QuicDataReader* reader,
QuicPacketHeader* header);
bool ProcessIetfPacketHeader(QuicDataReader* reader,
@@ -721,14 +823,6 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
static AckFrameInfo GetAckFrameInfo(const QuicAckFrame& frame);
- static bool AppendIetfConnectionId(
- bool version_flag,
- QuicConnectionId destination_connection_id,
- QuicConnectionIdLength destination_connection_id_length,
- QuicConnectionId source_connection_id,
- QuicConnectionIdLength source_connection_id_length,
- QuicDataWriter* writer);
-
// The Append* methods attempt to write the provided header or frame using the
// |writer|, and return true if successful.
@@ -809,10 +903,10 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
bool ProcessMaxStreamDataFrame(QuicDataReader* reader,
QuicWindowUpdateFrame* frame);
- bool AppendMaxStreamsFrame(const QuicMaxStreamIdFrame& frame,
+ bool AppendMaxStreamsFrame(const QuicMaxStreamsFrame& frame,
QuicDataWriter* writer);
bool ProcessMaxStreamsFrame(QuicDataReader* reader,
- QuicMaxStreamIdFrame* frame,
+ QuicMaxStreamsFrame* frame,
uint64_t frame_type);
bool AppendIetfBlockedFrame(const QuicBlockedFrame& frame,
@@ -824,10 +918,10 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
bool ProcessStreamBlockedFrame(QuicDataReader* reader,
QuicBlockedFrame* frame);
- bool AppendStreamsBlockedFrame(const QuicStreamIdBlockedFrame& frame,
+ bool AppendStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame,
QuicDataWriter* writer);
bool ProcessStreamsBlockedFrame(QuicDataReader* reader,
- QuicStreamIdBlockedFrame* frame,
+ QuicStreamsBlockedFrame* frame,
uint64_t frame_type);
bool AppendNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame,
@@ -867,9 +961,11 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
// Largest successfully decrypted packet number per packet number space. Only
// used when supports_multiple_packet_number_spaces_ is true.
QuicPacketNumber largest_decrypted_packet_numbers_[NUM_PACKET_NUMBER_SPACES];
- // Updated by WritePacketHeader.
- QuicConnectionId last_serialized_connection_id_;
+ // Last server connection ID seen on the wire.
+ QuicConnectionId last_serialized_server_connection_id_;
// The last QUIC version label received.
+ // TODO(fayang): Remove this when deprecating
+ // quic_no_framer_object_in_dispatcher.
QuicVersionLabel last_version_label_;
// Version of the protocol being used.
ParsedQuicVersion version_;
@@ -924,14 +1020,21 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
// encode its length. This variable contains the length we expect to read.
// This is also used to validate the long header connection ID lengths in
// older versions of QUIC.
- uint8_t expected_connection_id_length_;
+ uint8_t expected_server_connection_id_length_;
- // When this is true, QuicFramer will change expected_connection_id_length_
- // to the received destination connection ID length of all IETF long headers.
- bool should_update_expected_connection_id_length_;
+ // When this is true, QuicFramer will change
+ // expected_server_connection_id_length_ to the received destination
+ // connection ID length of all IETF long headers.
+ // TODO(fayang): Remove this when deprecating
+ // quic_no_framer_object_in_dispatcher.
+ bool should_update_expected_server_connection_id_length_;
// Indicates whether this framer supports multiple packet number spaces.
bool supports_multiple_packet_number_spaces_;
+
+ // The length in bytes of the last packet number written to an IETF-framed
+ // packet.
+ size_t last_written_packet_number_length_;
};
} // namespace quic
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 2ffe54e02d2..13e448260c4 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
@@ -198,6 +198,16 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
QuicMakeUnique<QuicVersionNegotiationPacket>((packet));
}
+ void OnRetryPacket(QuicConnectionId original_connection_id,
+ QuicConnectionId new_connection_id,
+ QuicStringPiece retry_token) override {
+ retry_original_connection_id_ =
+ QuicMakeUnique<QuicConnectionId>(original_connection_id);
+ retry_new_connection_id_ =
+ QuicMakeUnique<QuicConnectionId>(new_connection_id);
+ retry_token_ = QuicMakeUnique<std::string>(std::string(retry_token));
+ }
+
bool OnProtocolVersionMismatch(ParsedQuicVersion received_version,
PacketHeaderFormat /*form*/) override {
QUIC_DLOG(INFO) << "QuicFramer Version Mismatch, version: "
@@ -335,13 +345,13 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
return true;
}
- bool OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) override {
- max_stream_id_frame_ = frame;
+ bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override {
+ max_streams_frame_ = frame;
return true;
}
- bool OnStreamIdBlockedFrame(const QuicStreamIdBlockedFrame& frame) override {
- stream_id_blocked_frame_ = frame;
+ bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override {
+ streams_blocked_frame_ = frame;
return true;
}
@@ -394,6 +404,9 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
std::unique_ptr<QuicPublicResetPacket> public_reset_packet_;
std::unique_ptr<QuicIetfStatelessResetPacket> stateless_reset_packet_;
std::unique_ptr<QuicVersionNegotiationPacket> version_negotiation_packet_;
+ std::unique_ptr<QuicConnectionId> retry_original_connection_id_;
+ std::unique_ptr<QuicConnectionId> retry_new_connection_id_;
+ std::unique_ptr<std::string> retry_token_;
std::vector<std::unique_ptr<QuicStreamFrame>> stream_frames_;
std::vector<std::unique_ptr<QuicCryptoFrame>> crypto_frames_;
std::vector<std::unique_ptr<QuicAckFrame>> ack_frames_;
@@ -410,8 +423,8 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
QuicPathResponseFrame path_response_frame_;
QuicWindowUpdateFrame window_update_frame_;
QuicBlockedFrame blocked_frame_;
- QuicStreamIdBlockedFrame stream_id_blocked_frame_;
- QuicMaxStreamIdFrame max_stream_id_frame_;
+ QuicStreamsBlockedFrame streams_blocked_frame_;
+ QuicMaxStreamsFrame max_streams_frame_;
QuicNewConnectionIdFrame new_connection_id_;
QuicRetireConnectionIdFrame retire_connection_id_;
QuicNewTokenFrame new_token_;
@@ -430,7 +443,7 @@ using PacketFragments = std::vector<struct PacketFragment>;
ParsedQuicVersionVector AllSupportedVersionsIncludingTls() {
QuicFlagSaver flags;
- SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
return AllSupportedVersions();
}
@@ -445,7 +458,7 @@ class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
start_,
Perspective::IS_SERVER,
kQuicDefaultConnectionIdLength) {
- SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
framer_.set_version(version_);
if (framer_.version().KnowsWhichDecrypterToUse()) {
framer_.InstallDecrypter(ENCRYPTION_INITIAL,
@@ -900,6 +913,22 @@ TEST_P(QuicFramerTest, PacketHeader) {
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER);
+
+ PacketHeaderFormat format;
+ bool version_flag;
+ uint8_t destination_connection_id_length;
+ QuicConnectionId destination_connection_id;
+ QuicVersionLabel version_label;
+ std::string detailed_error;
+ EXPECT_EQ(QUIC_NO_ERROR, QuicFramer::ProcessPacketDispatcher(
+ *encrypted, kQuicDefaultConnectionIdLength,
+ &format, &version_flag, &version_label,
+ &destination_connection_id_length,
+ &destination_connection_id, &detailed_error));
+ EXPECT_EQ(GOOGLE_QUIC_PACKET, format);
+ EXPECT_FALSE(version_flag);
+ EXPECT_EQ(kQuicDefaultConnectionIdLength, destination_connection_id_length);
+ EXPECT_EQ(FramerTestConnectionId(), destination_connection_id);
}
TEST_P(QuicFramerTest, LongPacketHeader) {
@@ -962,12 +991,28 @@ TEST_P(QuicFramerTest, LongPacketHeader) {
CheckFramingBoundaries(
framer_.transport_version() > QUIC_VERSION_44 ? packet46 : packet44,
QUIC_INVALID_PACKET_HEADER);
+
+ PacketHeaderFormat format;
+ bool version_flag;
+ uint8_t destination_connection_id_length;
+ QuicConnectionId destination_connection_id;
+ QuicVersionLabel version_label;
+ std::string detailed_error;
+ EXPECT_EQ(QUIC_NO_ERROR, QuicFramer::ProcessPacketDispatcher(
+ *encrypted, kQuicDefaultConnectionIdLength,
+ &format, &version_flag, &version_label,
+ &destination_connection_id_length,
+ &destination_connection_id, &detailed_error));
+ EXPECT_EQ(IETF_QUIC_LONG_HEADER_PACKET, format);
+ EXPECT_TRUE(version_flag);
+ EXPECT_EQ(kQuicDefaultConnectionIdLength, destination_connection_id_length);
+ EXPECT_EQ(FramerTestConnectionId(), destination_connection_id);
}
TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
- QuicFramerPeer::SetLastSerializedConnectionId(&framer_,
- FramerTestConnectionId());
+ QuicFramerPeer::SetLastSerializedServerConnectionId(&framer_,
+ FramerTestConnectionId());
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
// clang-format off
@@ -1000,19 +1045,36 @@ TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) {
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
+
+ PacketFragments packet_hp = {
+ // type (short header, 4 byte packet number)
+ {"Unable to read type.",
+ {0x43}},
+ // connection_id
+ // packet number
+ {"",
+ {0x12, 0x34, 0x56, 0x78}},
+ };
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() > QUIC_VERSION_44
- ? packet46
- : (framer_.transport_version() > QUIC_VERSION_43 ? packet44 : packet);
+ framer_.version().HasHeaderProtection()
+ ? packet_hp
+ : framer_.transport_version() > QUIC_VERSION_44
+ ? packet46
+ : (framer_.transport_version() > QUIC_VERSION_43 ? packet44
+ : packet);
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_EQ(FramerTestConnectionId(),
- visitor_.header_->destination_connection_id);
+ if (!GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ EXPECT_EQ(FramerTestConnectionId(),
+ visitor_.header_->destination_connection_id);
+ } else {
+ EXPECT_EQ(FramerTestConnectionId(), visitor_.header_->source_connection_id);
+ }
EXPECT_FALSE(visitor_.header_->reset_flag);
EXPECT_FALSE(visitor_.header_->version_flag);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
@@ -1160,12 +1222,27 @@ TEST_P(QuicFramerTest, PacketHeaderWith4BytePacketNumber) {
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
+
+ PacketFragments packet_hp = {
+ // type (short header, 4 byte packet number)
+ {"Unable to read type.",
+ {0x43}},
+ // connection_id
+ {"Unable to read Destination ConnectionId.",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x12, 0x34, 0x56, 0x78}},
+ };
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() > QUIC_VERSION_44
- ? packet46
- : (framer_.transport_version() > QUIC_VERSION_43 ? packet44 : packet);
+ framer_.version().HasHeaderProtection()
+ ? packet_hp
+ : framer_.transport_version() > QUIC_VERSION_44
+ ? packet46
+ : (framer_.transport_version() > QUIC_VERSION_43 ? packet44
+ : packet);
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
@@ -1220,16 +1297,38 @@ TEST_P(QuicFramerTest, PacketHeaderWith2BytePacketNumber) {
{"Unable to read packet number.",
{0x56, 0x78}},
};
+
+ PacketFragments packet_hp = {
+ // type (short header, 2 byte packet number)
+ {"Unable to read type.",
+ {0x41}},
+ // connection_id
+ {"Unable to read Destination ConnectionId.",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x56, 0x78}},
+ // padding
+ {"", {0x00, 0x00}},
+ };
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() > QUIC_VERSION_44
- ? packet46
- : (framer_.transport_version() > QUIC_VERSION_43 ? packet44 : packet);
+ framer_.version().HasHeaderProtection()
+ ? packet_hp
+ : (framer_.transport_version() > QUIC_VERSION_44
+ ? packet46
+ : (framer_.transport_version() > QUIC_VERSION_43 ? packet44
+ : packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
- EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
+ if (framer_.version().HasHeaderProtection()) {
+ EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ } else {
+ EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
+ EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
+ }
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
@@ -1282,16 +1381,38 @@ TEST_P(QuicFramerTest, PacketHeaderWith1BytePacketNumber) {
{0x78}},
};
+ PacketFragments packet_hp = {
+ // type (8 byte connection_id and 1 byte packet number)
+ {"Unable to read type.",
+ {0x40}},
+ // connection_id
+ {"Unable to read Destination ConnectionId.",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x78}},
+ // padding
+ {"", {0x00, 0x00, 0x00}},
+ };
+
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() > QUIC_VERSION_44
- ? packet46
- : (framer_.transport_version() > QUIC_VERSION_43 ? packet44 : packet);
+ framer_.version().HasHeaderProtection()
+ ? packet_hp
+ : (framer_.transport_version() > QUIC_VERSION_44
+ ? packet46
+ : (framer_.transport_version() > QUIC_VERSION_43 ? packet44
+ : packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
- EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
+ if (framer_.version().HasHeaderProtection()) {
+ EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ } else {
+ EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
+ EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
+ }
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
@@ -1523,20 +1644,41 @@ TEST_P(QuicFramerTest, LargePublicFlagWithMismatchedVersions) {
0x00,
0x00, 0x00, 0x00, 0x00
};
+
+ unsigned char packet45[] = {
+ // type (long header, ZERO_RTT_PROTECTED, 4-byte packet number)
+ 0xD3,
+ // version tag
+ 'Q', '0', '0', '0',
+ // connection_id length
+ 0x50,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (padding frame)
+ 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ };
// clang-format on
- QuicEncryptedPacket encrypted(
- AsChars(framer_.transport_version() > QUIC_VERSION_43 ? packet44
- : packet),
- framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet44)
- : QUIC_ARRAYSIZE(packet),
- false);
+ unsigned char* p = packet;
+ size_t p_size = QUIC_ARRAYSIZE(packet);
+ if (framer_.transport_version() > QUIC_VERSION_44) {
+ p = packet45;
+ p_size = QUIC_ARRAYSIZE(packet45);
+ } else if (framer_.transport_version() > QUIC_VERSION_43) {
+ p = packet44;
+ p_size = QUIC_ARRAYSIZE(packet44);
+ }
+ QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(0, visitor_.frame_count_);
EXPECT_EQ(1, visitor_.version_mismatch_);
- EXPECT_EQ(1u, visitor_.padding_frames_.size());
+ ASSERT_EQ(1u, visitor_.padding_frames_.size());
EXPECT_EQ(5, visitor_.padding_frames_[0]->num_padding_bytes);
}
@@ -1984,7 +2126,10 @@ TEST_P(QuicFramerTest, MissingDiversificationNonce) {
}
QuicEncryptedPacket encrypted(AsChars(p), p_length, false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
- if (framer_.transport_version() >= QUIC_VERSION_44) {
+ if (framer_.version().HasHeaderProtection()) {
+ EXPECT_EQ(QUIC_DECRYPTION_FAILURE, framer_.error());
+ EXPECT_EQ("Unable to decrypt header protection.", framer_.detailed_error());
+ } else if (framer_.transport_version() >= QUIC_VERSION_44) {
// Cannot read diversification nonce.
EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
EXPECT_EQ("Unable to read nonce.", framer_.detailed_error());
@@ -3252,6 +3397,7 @@ TEST_P(QuicFramerTest, AckFrameFirstAckBlockLengthZero) {
// not arise.
return;
}
+ SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// clang-format off
PacketFragments packet = {
@@ -3833,6 +3979,7 @@ TEST_P(QuicFramerTest, AckFrameTwoTimeStampsMultipleAckBlocks) {
}
TEST_P(QuicFramerTest, AckFrameTimeStampDeltaTooHigh) {
+ SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
@@ -3924,6 +4071,7 @@ TEST_P(QuicFramerTest, AckFrameTimeStampDeltaTooHigh) {
}
TEST_P(QuicFramerTest, AckFrameTimeStampSecondDeltaTooHigh) {
+ SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
@@ -4030,6 +4178,7 @@ TEST_P(QuicFramerTest, NewStopWaitingFrame) {
if (version_.transport_version == QUIC_VERSION_99) {
return;
}
+ SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// clang-format off
PacketFragments packet = {
// public flags (8 byte connection_id)
@@ -4093,6 +4242,15 @@ TEST_P(QuicFramerTest, NewStopWaitingFrame) {
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
+ if (GetQuicReloadableFlag(quic_do_not_accept_stop_waiting) &&
+ version_.transport_version >= QUIC_VERSION_44) {
+ EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
+ EXPECT_EQ(QUIC_INVALID_STOP_WAITING_DATA, framer_.error());
+ EXPECT_EQ("STOP WAITING not supported in version 44+.",
+ framer_.detailed_error());
+ return;
+ }
+
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -4110,9 +4268,12 @@ TEST_P(QuicFramerTest, NewStopWaitingFrame) {
}
TEST_P(QuicFramerTest, InvalidNewStopWaitingFrame) {
- if (version_.transport_version == QUIC_VERSION_99) {
+ if (version_.transport_version == QUIC_VERSION_99 ||
+ (GetQuicReloadableFlag(quic_do_not_accept_stop_waiting) &&
+ version_.transport_version >= QUIC_VERSION_44)) {
return;
}
+ SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
@@ -4509,6 +4670,7 @@ TEST_P(QuicFramerTest, GoAwayFrame) {
// This frame is not supported in version 99.
return;
}
+ SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// clang-format off
PacketFragments packet = {
// public flags (8 byte connection_id)
@@ -4634,6 +4796,7 @@ TEST_P(QuicFramerTest, WindowUpdateFrame) {
// for Version 99 equivalents.
return;
}
+ SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// clang-format off
PacketFragments packet = {
// public flags (8 byte connection_id)
@@ -5367,7 +5530,7 @@ TEST_P(QuicFramerTest, IetfStatelessResetPacketInvalidStatelessResetToken) {
ASSERT_FALSE(visitor_.stateless_reset_packet_);
}
-TEST_P(QuicFramerTest, VersionNegotiationPacket) {
+TEST_P(QuicFramerTest, VersionNegotiationPacketClient) {
// clang-format off
PacketFragments packet = {
// public flags (version, 8 byte connection_id)
@@ -5422,6 +5585,39 @@ TEST_P(QuicFramerTest, VersionNegotiationPacket) {
CheckFramingBoundaries(fragments, QUIC_INVALID_VERSION_NEGOTIATION_PACKET);
}
+TEST_P(QuicFramerTest, VersionNegotiationPacketServer) {
+ if (!GetQuicRestartFlag(quic_server_drop_version_negotiation)) {
+ return;
+ }
+ if (framer_.transport_version() < QUIC_VERSION_44) {
+ return;
+ }
+
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (long header with all ignored bits set)
+ 0xFF,
+ // version
+ 0x00, 0x00, 0x00, 0x00,
+ // connection ID lengths
+ 0x50,
+ // destination connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x11,
+ // supported versions
+ QUIC_VERSION_BYTES,
+ 'Q', '2', '.', '0',
+ };
+ // clang-format on
+
+ QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
+ EXPECT_FALSE(framer_.ProcessPacket(encrypted));
+ EXPECT_EQ(QUIC_INVALID_VERSION_NEGOTIATION_PACKET, framer_.error());
+ EXPECT_EQ("Server received version negotiation packet.",
+ framer_.detailed_error());
+ EXPECT_FALSE(visitor_.version_negotiation_packet_.get());
+}
+
TEST_P(QuicFramerTest, OldVersionNegotiationPacket) {
// clang-format off
PacketFragments packet = {
@@ -5461,7 +5657,80 @@ TEST_P(QuicFramerTest, OldVersionNegotiationPacket) {
CheckFramingBoundaries(packet, QUIC_INVALID_VERSION_NEGOTIATION_PACKET);
}
+TEST_P(QuicFramerTest, ParseIetfRetryPacket) {
+ if (!framer_.version().SupportsRetry()) {
+ return;
+ }
+ // IETF RETRY is only sent from client to server.
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (long header with packet type RETRY and ODCIL=8)
+ 0xF5,
+ // version
+ QUIC_VERSION_BYTES,
+ // connection ID lengths
+ 0x05,
+ // source connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x11,
+ // original destination connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // retry token
+ 'H', 'e', 'l', 'l', 'o', ' ', 't', 'h', 'i', 's',
+ ' ', 'i', 's', ' ', 'R', 'E', 'T', 'R', 'Y', '!',
+ };
+ // clang-format on
+
+ QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+
+ ASSERT_TRUE(visitor_.retry_original_connection_id_.get());
+ ASSERT_TRUE(visitor_.retry_new_connection_id_.get());
+ ASSERT_TRUE(visitor_.retry_token_.get());
+
+ EXPECT_EQ(FramerTestConnectionId(),
+ *visitor_.retry_original_connection_id_.get());
+ EXPECT_EQ(FramerTestConnectionIdPlusOne(),
+ *visitor_.retry_new_connection_id_.get());
+ EXPECT_EQ("Hello this is RETRY!", *visitor_.retry_token_.get());
+}
+
+TEST_P(QuicFramerTest, RejectIetfRetryPacketAsServer) {
+ if (!framer_.version().SupportsRetry()) {
+ return;
+ }
+ // IETF RETRY is only sent from client to server.
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (long header with packet type RETRY and ODCIL=8)
+ 0xF5,
+ // version
+ QUIC_VERSION_BYTES,
+ // connection ID lengths
+ 0x05,
+ // source connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x11,
+ // original destination connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // retry token
+ 'H', 'e', 'l', 'l', 'o', ' ', 't', 'h', 'i', 's',
+ ' ', 'i', 's', ' ', 'R', 'E', 'T', 'R', 'Y', '!',
+ };
+ // clang-format on
+
+ QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
+ EXPECT_FALSE(framer_.ProcessPacket(encrypted));
+
+ EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ EXPECT_EQ("Client-initiated RETRY is invalid.", framer_.detailed_error());
+}
+
TEST_P(QuicFramerTest, BuildPaddingFramePacket) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -5473,7 +5742,7 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) {
// clang-format off
unsigned char packet[kMaxOutgoingPacketSize] = {
// public flags (8 byte connection_id)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -5550,6 +5819,7 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) {
}
TEST_P(QuicFramerTest, BuildStreamFramePacketWithNewPaddingFrame) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -5564,7 +5834,7 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithNewPaddingFrame) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -5693,6 +5963,7 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithNewPaddingFrame) {
}
TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -5705,7 +5976,7 @@ TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) {
// clang-format off
unsigned char packet[kMaxOutgoingPacketSize] = {
// public flags (8 byte connection_id and 4 byte packet number)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -5782,6 +6053,7 @@ TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) {
}
TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -5794,7 +6066,7 @@ TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) {
// clang-format off
unsigned char packet[kMaxOutgoingPacketSize] = {
// public flags (8 byte connection_id and 2 byte packet number)
- 0x18,
+ 0x1C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -5871,6 +6143,7 @@ TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) {
}
TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -5883,7 +6156,7 @@ TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) {
// clang-format off
unsigned char packet[kMaxOutgoingPacketSize] = {
// public flags (8 byte connection_id and 1 byte packet number)
- 0x08,
+ 0x0C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -5960,6 +6233,7 @@ TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) {
}
TEST_P(QuicFramerTest, BuildStreamFramePacket) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -5977,7 +6251,7 @@ TEST_P(QuicFramerTest, BuildStreamFramePacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -6211,6 +6485,7 @@ TEST_P(QuicFramerTest, BuildCryptoFramePacket) {
// CRYPTO frames aren't supported prior to v46.
return;
}
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -6324,9 +6599,13 @@ TEST_P(QuicFramerTest, BuildVersionNegotiationPacket) {
// version tag
QUIC_VERSION_BYTES,
};
+ unsigned char type44 = 0x80;
+ if (GetQuicReloadableFlag(quic_send_version_negotiation_fixed_bit)) {
+ type44 = 0xC0;
+ }
unsigned char packet44[] = {
// type (long header)
- 0x80,
+ type44,
// version tag
0x00, 0x00, 0x00, 0x00,
// connection_id length
@@ -6346,14 +6625,57 @@ TEST_P(QuicFramerTest, BuildVersionNegotiationPacket) {
QuicConnectionId connection_id = FramerTestConnectionId();
std::unique_ptr<QuicEncryptedPacket> data(
- framer_.BuildVersionNegotiationPacket(
- connection_id, framer_.transport_version() > QUIC_VERSION_43,
+ QuicFramer::BuildVersionNegotiationPacket(
+ connection_id, EmptyQuicConnectionId(),
+ framer_.transport_version() > QUIC_VERSION_43,
SupportedVersions(GetParam())));
test::CompareCharArraysWithHexError("constructed packet", data->data(),
data->length(), AsChars(p), p_size);
}
+TEST_P(QuicFramerTest, BuildVersionNegotiationPacketWithClientConnectionId) {
+ if (framer_.transport_version() <= QUIC_VERSION_43) {
+ // The GQUIC encoding does not support encoding client connection IDs.
+ return;
+ }
+
+ // Client connection IDs cannot be used unless this flag is true.
+ SetQuicRestartFlag(quic_do_not_override_connection_id, true);
+
+ unsigned char type_byte = 0x80;
+ if (GetQuicReloadableFlag(quic_send_version_negotiation_fixed_bit)) {
+ type_byte = 0xC0;
+ }
+ // clang-format off
+ unsigned char packet[] = {
+ // type (long header)
+ type_byte,
+ // version tag
+ 0x00, 0x00, 0x00, 0x00,
+ // connection ID lengths
+ 0x55,
+ // client/destination connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x11,
+ // server/source connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // version tag
+ QUIC_VERSION_BYTES,
+ };
+ // clang-format on
+
+ QuicConnectionId server_connection_id = FramerTestConnectionId();
+ QuicConnectionId client_connection_id = FramerTestConnectionIdPlusOne();
+ std::unique_ptr<QuicEncryptedPacket> data(
+ QuicFramer::BuildVersionNegotiationPacket(server_connection_id,
+ client_connection_id, true,
+ SupportedVersions(GetParam())));
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ QUIC_ARRAYSIZE(packet));
+}
+
TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlock) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -6369,7 +6691,7 @@ TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlock) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -6470,6 +6792,7 @@ TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlock) {
}
TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlockMaxLength) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -6484,7 +6807,7 @@ TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlockMaxLength) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -6586,6 +6909,7 @@ TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlockMaxLength) {
}
TEST_P(QuicFramerTest, BuildAckFramePacketMultipleAckBlocks) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -6605,7 +6929,7 @@ TEST_P(QuicFramerTest, BuildAckFramePacketMultipleAckBlocks) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -6776,6 +7100,7 @@ TEST_P(QuicFramerTest, BuildAckFramePacketMultipleAckBlocks) {
}
TEST_P(QuicFramerTest, BuildAckFramePacketMaxAckBlocks) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -6797,7 +7122,7 @@ TEST_P(QuicFramerTest, BuildAckFramePacketMaxAckBlocks) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -7183,6 +7508,7 @@ TEST_P(QuicFramerTest, BuildNewStopWaitingPacket) {
if (version_.transport_version > QUIC_VERSION_43) {
return;
}
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -7197,7 +7523,7 @@ TEST_P(QuicFramerTest, BuildNewStopWaitingPacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -7220,6 +7546,7 @@ TEST_P(QuicFramerTest, BuildNewStopWaitingPacket) {
}
TEST_P(QuicFramerTest, BuildRstFramePacketQuic) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -7238,7 +7565,7 @@ TEST_P(QuicFramerTest, BuildRstFramePacketQuic) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -7336,6 +7663,7 @@ TEST_P(QuicFramerTest, BuildRstFramePacketQuic) {
}
TEST_P(QuicFramerTest, BuildCloseFramePacket) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -7358,7 +7686,7 @@ TEST_P(QuicFramerTest, BuildCloseFramePacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -7464,6 +7792,7 @@ TEST_P(QuicFramerTest, BuildCloseFramePacket) {
}
TEST_P(QuicFramerTest, BuildTruncatedCloseFramePacket) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -7484,7 +7813,7 @@ TEST_P(QuicFramerTest, BuildTruncatedCloseFramePacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -7706,6 +8035,7 @@ TEST_P(QuicFramerTest, BuildApplicationCloseFramePacket) {
// Versions other than 99 do not have ApplicationClose
return;
}
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -7756,6 +8086,7 @@ TEST_P(QuicFramerTest, BuildTruncatedApplicationCloseFramePacket) {
// Versions other than 99 do not have this frame.
return;
}
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -7833,6 +8164,7 @@ TEST_P(QuicFramerTest, BuildGoAwayPacket) {
// This frame type is not supported in version 99.
return;
}
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -7849,7 +8181,7 @@ TEST_P(QuicFramerTest, BuildGoAwayPacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -7940,6 +8272,7 @@ TEST_P(QuicFramerTest, BuildTruncatedGoAwayPacket) {
// This frame type is not supported in version 99.
return;
}
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -7956,7 +8289,7 @@ TEST_P(QuicFramerTest, BuildTruncatedGoAwayPacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -8126,6 +8459,7 @@ TEST_P(QuicFramerTest, BuildTruncatedGoAwayPacket) {
}
TEST_P(QuicFramerTest, BuildWindowUpdatePacket) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -8141,7 +8475,7 @@ TEST_P(QuicFramerTest, BuildWindowUpdatePacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -8233,6 +8567,7 @@ TEST_P(QuicFramerTest, BuildMaxStreamDataPacket) {
// This frame is available only in this version.
return;
}
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -8277,6 +8612,7 @@ TEST_P(QuicFramerTest, BuildMaxDataPacket) {
// This frame is available only in this version.
return;
}
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -8316,6 +8652,7 @@ TEST_P(QuicFramerTest, BuildMaxDataPacket) {
}
TEST_P(QuicFramerTest, BuildBlockedPacket) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -8339,7 +8676,7 @@ TEST_P(QuicFramerTest, BuildBlockedPacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -8415,6 +8752,7 @@ TEST_P(QuicFramerTest, BuildBlockedPacket) {
}
TEST_P(QuicFramerTest, BuildPingPacket) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -8426,7 +8764,7 @@ TEST_P(QuicFramerTest, BuildPingPacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -8495,6 +8833,7 @@ TEST_P(QuicFramerTest, BuildMessagePacket) {
if (framer_.transport_version() <= QUIC_VERSION_44) {
return;
}
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -8586,6 +8925,7 @@ TEST_P(QuicFramerTest, BuildMessagePacket) {
// Test that the connectivity probing packet is serialized correctly as a
// padded PING packet.
TEST_P(QuicFramerTest, BuildConnectivityProbingPacket) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -8595,7 +8935,7 @@ TEST_P(QuicFramerTest, BuildConnectivityProbingPacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -8933,6 +9273,7 @@ TEST_P(QuicFramerTest, BuildPathResponsePacket3ResponsesPadded) {
// Test that the MTU discovery packet is serialized correctly as a PING packet.
TEST_P(QuicFramerTest, BuildMtuDiscoveryPacket) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -8944,7 +9285,7 @@ TEST_P(QuicFramerTest, BuildMtuDiscoveryPacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x28,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -9268,12 +9609,15 @@ TEST_P(QuicFramerTest, EncryptPacket) {
'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p',
+ 'q', 'r', 's', 't',
};
// clang-format on
unsigned char* p = packet;
+ size_t p_size = QUIC_ARRAYSIZE(packet);
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
+ p_size = QUIC_ARRAYSIZE(packet99);
} else if (framer_.transport_version() > QUIC_VERSION_44) {
p = packet46;
} else if (framer_.transport_version() > QUIC_VERSION_43) {
@@ -9281,7 +9625,7 @@ TEST_P(QuicFramerTest, EncryptPacket) {
}
std::unique_ptr<QuicPacket> raw(new QuicPacket(
- AsChars(p), QUIC_ARRAYSIZE(packet), false, PACKET_8BYTE_CONNECTION_ID,
+ AsChars(p), p_size, false, PACKET_8BYTE_CONNECTION_ID,
PACKET_0BYTE_CONNECTION_ID, !kIncludeVersion,
!kIncludeDiversificationNonce, PACKET_4BYTE_PACKET_NUMBER,
VARIABLE_LENGTH_INTEGER_LENGTH_0, 0, VARIABLE_LENGTH_INTEGER_LENGTH_0));
@@ -9294,6 +9638,7 @@ TEST_P(QuicFramerTest, EncryptPacket) {
}
TEST_P(QuicFramerTest, EncryptPacketWithVersionFlag) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketNumber packet_number = kPacketNumber;
// clang-format off
unsigned char packet[] = {
@@ -9368,26 +9713,28 @@ TEST_P(QuicFramerTest, EncryptPacketWithVersionFlag) {
'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p',
+ 'q', 'r', 's', 't',
};
// clang-format on
unsigned char* p = packet;
+ size_t p_size = QUIC_ARRAYSIZE(packet);
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
+ p_size = QUIC_ARRAYSIZE(packet99);
} else if (framer_.transport_version() > QUIC_VERSION_44) {
p = packet46;
+ p_size = QUIC_ARRAYSIZE(packet46);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
+ p_size = QUIC_ARRAYSIZE(packet44);
}
std::unique_ptr<QuicPacket> raw(new QuicPacket(
- AsChars(p),
- framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet44)
- : QUIC_ARRAYSIZE(packet),
- false, PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID,
- kIncludeVersion, !kIncludeDiversificationNonce,
- PACKET_4BYTE_PACKET_NUMBER, VARIABLE_LENGTH_INTEGER_LENGTH_0, 0,
- VARIABLE_LENGTH_INTEGER_LENGTH_0));
+ AsChars(p), p_size, false, PACKET_8BYTE_CONNECTION_ID,
+ PACKET_0BYTE_CONNECTION_ID, kIncludeVersion,
+ !kIncludeDiversificationNonce, PACKET_4BYTE_PACKET_NUMBER,
+ VARIABLE_LENGTH_INTEGER_LENGTH_0, 0, VARIABLE_LENGTH_INTEGER_LENGTH_0));
char buffer[kMaxOutgoingPacketSize];
size_t encrypted_length = framer_.EncryptPayload(
ENCRYPTION_INITIAL, packet_number, *raw, buffer, kMaxOutgoingPacketSize);
@@ -9402,6 +9749,7 @@ TEST_P(QuicFramerTest, AckTruncationLargePacket) {
// effectively unlimited
return;
}
+ SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
@@ -9441,6 +9789,7 @@ TEST_P(QuicFramerTest, AckTruncationSmallPacket) {
// effectively unlimited
return;
}
+ SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
@@ -9481,6 +9830,7 @@ TEST_P(QuicFramerTest, CleanTruncation) {
// effectively unlimited
return;
}
+ SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
@@ -9704,7 +10054,7 @@ static char kTestString[] = "At least 20 characters.";
static QuicStreamId kTestQuicStreamId = 1;
static bool ExpectedStreamFrame(const QuicStreamFrame& frame) {
return (frame.stream_id == kTestQuicStreamId ||
- frame.stream_id == QuicUtils::GetCryptoStreamId(QUIC_VERSION_99)) &&
+ QuicUtils::IsCryptoStreamId(QUIC_VERSION_99, frame.stream_id)) &&
!frame.fin && frame.offset == 0 &&
std::string(frame.data_buffer, frame.data_length) == kTestString;
// FIN is hard-coded false in ConstructEncryptedPacket.
@@ -9758,12 +10108,12 @@ TEST_P(QuicFramerTest, ConstructEncryptedPacket) {
// Verify that the packet returned by ConstructMisFramedEncryptedPacket()
// does cause the framer to return an error.
TEST_P(QuicFramerTest, ConstructMisFramedEncryptedPacket) {
- SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// Since we are using ConstructEncryptedPacket, we have to set the framer's
// crypto to be Null.
if (framer_.version().KnowsWhichDecrypterToUse()) {
- framer_.InstallDecrypter(ENCRYPTION_INITIAL, QuicMakeUnique<NullDecrypter>(
- framer_.perspective()));
+ framer_.InstallDecrypter(
+ ENCRYPTION_FORWARD_SECURE,
+ QuicMakeUnique<NullDecrypter>(framer_.perspective()));
} else {
framer_.SetDecrypter(ENCRYPTION_INITIAL,
QuicMakeUnique<NullDecrypter>(framer_.perspective()));
@@ -10106,7 +10456,7 @@ TEST_P(QuicFramerTest, BuildIetfStreamBlockedPacket) {
QUIC_ARRAYSIZE(packet99));
}
-TEST_P(QuicFramerTest, ServerBiDiMaxStreamsFrame) {
+TEST_P(QuicFramerTest, BiDiMaxStreamsFrame) {
// This test only for version 99.
if (framer_.transport_version() != QUIC_VERSION_99) {
return;
@@ -10143,18 +10493,12 @@ TEST_P(QuicFramerTest, ServerBiDiMaxStreamsFrame) {
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
- // This test is a server receiving a MAX_STREAMS frame. The
- // stream ID that it generates should be a server-initiated
- // stream ID. The expected Stream ID is
- // ((0x3-1) * 4) | 0x1 = 0x9
- // count-to-id server inited, bidi
- EXPECT_EQ(GetNthStreamid(QUIC_VERSION_99, Perspective::IS_SERVER,
- /*bidirectional=*/true, 3),
- visitor_.max_stream_id_frame_.max_stream_id);
- CheckFramingBoundaries(packet99, QUIC_MAX_STREAM_ID_DATA);
+ EXPECT_EQ(3u, visitor_.max_streams_frame_.stream_count);
+ EXPECT_FALSE(visitor_.max_streams_frame_.unidirectional);
+ CheckFramingBoundaries(packet99, QUIC_MAX_STREAMS_DATA);
}
-TEST_P(QuicFramerTest, ClientBiDiMaxStreamsFrame) {
+TEST_P(QuicFramerTest, UniDiMaxStreamsFrame) {
// This test only for version 99.
if (framer_.transport_version() != QUIC_VERSION_99) {
return;
@@ -10170,9 +10514,9 @@ TEST_P(QuicFramerTest, ClientBiDiMaxStreamsFrame) {
// packet number
{"",
{0x12, 0x34, 0x9A, 0xBC}},
- // frame type (IETF_MAX_STREAMS_BIDIRECTIONAL)
+ // frame type (IETF_MAX_STREAMS_UNIDIRECTIONAL)
{"",
- {0x12}},
+ {0x13}},
// max. streams
{"Can not read MAX_STREAMS stream count.",
{kVarInt62OneByte + 0x03}},
@@ -10190,19 +10534,9 @@ TEST_P(QuicFramerTest, ClientBiDiMaxStreamsFrame) {
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_0BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
- // This test is a client receiving a MAX_STREAMS frame. The
- // stream ID that it generates should be a client-initiated
- // stream ID. The expected Stream ID is
- // ((0x3-1) * 4) = 0xc
- // It is not 8 because a client-initiated, bidi stream ID's
- // low bits are 00 - which means that the old crypto stream
- // falls into this category, and the first stream is streamid=4,
- // not streamid=0.
- EXPECT_EQ(GetNthStreamid(QUIC_VERSION_99, Perspective::IS_CLIENT,
- /*bidirectional=*/true, 3),
- visitor_.max_stream_id_frame_.max_stream_id);
-
- CheckFramingBoundaries(packet99, QUIC_MAX_STREAM_ID_DATA);
+ EXPECT_EQ(3u, visitor_.max_streams_frame_.stream_count);
+ EXPECT_TRUE(visitor_.max_streams_frame_.unidirectional);
+ CheckFramingBoundaries(packet99, QUIC_MAX_STREAMS_DATA);
}
TEST_P(QuicFramerTest, ServerUniDiMaxStreamsFrame) {
@@ -10242,16 +10576,9 @@ TEST_P(QuicFramerTest, ServerUniDiMaxStreamsFrame) {
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
- // This test is a server receiving a MAX_STREAMS frame. The
- // stream ID that it generates should be a server-initiated
- // stream ID. The expected Stream ID is
- // ((0x3-1) * 4) | 0x1 | 0x2 = 0xb
- // count-to-id server inited, unidi
- EXPECT_EQ(GetNthStreamid(QUIC_VERSION_99, Perspective::IS_SERVER,
- /*bidirectional=*/false, 3),
- visitor_.max_stream_id_frame_.max_stream_id);
-
- CheckFramingBoundaries(packet99, QUIC_MAX_STREAM_ID_DATA);
+ EXPECT_EQ(3u, visitor_.max_streams_frame_.stream_count);
+ EXPECT_TRUE(visitor_.max_streams_frame_.unidirectional);
+ CheckFramingBoundaries(packet99, QUIC_MAX_STREAMS_DATA);
}
TEST_P(QuicFramerTest, ClientUniDiMaxStreamsFrame) {
@@ -10290,16 +10617,9 @@ TEST_P(QuicFramerTest, ClientUniDiMaxStreamsFrame) {
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_0BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
- // This test is a client receiving a MAX_STREAMS frame. The
- // stream ID that it generates should be a client-initiated
- // stream ID. The expected Stream ID is
- // ((0x3-1) * 4) | 0x02= 0xa
- // count-to-id client/unidi
- EXPECT_EQ(GetNthStreamid(QUIC_VERSION_99, Perspective::IS_CLIENT,
- /*bidirectional=*/false, 3),
- visitor_.max_stream_id_frame_.max_stream_id);
-
- CheckFramingBoundaries(packet99, QUIC_MAX_STREAM_ID_DATA);
+ EXPECT_EQ(3u, visitor_.max_streams_frame_.stream_count);
+ EXPECT_TRUE(visitor_.max_streams_frame_.unidirectional);
+ CheckFramingBoundaries(packet99, QUIC_MAX_STREAMS_DATA);
}
// The following four tests ensure that the framer can deserialize a stream
@@ -10308,7 +10628,7 @@ TEST_P(QuicFramerTest, ClientUniDiMaxStreamsFrame) {
// the stream limit is pegged to the maximum supported value. There are four
// tests, for the four combinations of uni- and bi-directional, server- and
// client- initiated.
-TEST_P(QuicFramerTest, ServerBiDiMaxStreamsFrameTooBig) {
+TEST_P(QuicFramerTest, BiDiMaxStreamsFrameTooBig) {
// This test only for version 99.
if (framer_.transport_version() != QUIC_VERSION_99) {
return;
@@ -10342,14 +10662,8 @@ TEST_P(QuicFramerTest, ServerBiDiMaxStreamsFrameTooBig) {
encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
- // This test is a server receiving a MAX_STREAMS frame. The
- // stream ID that it generates should be a server-initiated
- // stream ID. The expected Stream ID is
- // 0xfffffffc | 0x01 --> 0xfffffffd
- // maxid server inited, bidi
- EXPECT_EQ(GetNthStreamid(QUIC_VERSION_99, Perspective::IS_SERVER,
- /*bidirectional=*/true, 0x40000000),
- visitor_.max_stream_id_frame_.max_stream_id);
+ EXPECT_EQ(0x40000000u, visitor_.max_streams_frame_.stream_count);
+ EXPECT_FALSE(visitor_.max_streams_frame_.unidirectional);
}
TEST_P(QuicFramerTest, ClientBiDiMaxStreamsFrameTooBig) {
@@ -10387,19 +10701,8 @@ TEST_P(QuicFramerTest, ClientBiDiMaxStreamsFrameTooBig) {
encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_0BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
- // This test is a client receiving a MAX_STREAMS frame. The
- // stream ID that it generates should be a client-initiated
- // stream ID. The expected Stream ID is
- // 0xfffffffc --> 0xfffffffc
- // max id bidi/client-inited
- // TODO(fkastenholz): Change -2 to -1 when stream id 0 is no longer
- // special.
- // Subtract 1 because client/bidi stream ids start counting at
- // 4, not 0. If we didn;t subtract 1, the resulting math would wrap to stream
- // id 0, not 0xfffffffc.
- EXPECT_EQ(GetNthStreamid(QUIC_VERSION_99, Perspective::IS_CLIENT,
- /*bidirectional=*/true, (0x40000000 - 1)),
- visitor_.max_stream_id_frame_.max_stream_id);
+ EXPECT_EQ(0x40000000u, visitor_.max_streams_frame_.stream_count);
+ EXPECT_FALSE(visitor_.max_streams_frame_.unidirectional);
}
TEST_P(QuicFramerTest, ServerUniDiMaxStreamsFrameTooBig) {
@@ -10437,14 +10740,8 @@ TEST_P(QuicFramerTest, ServerUniDiMaxStreamsFrameTooBig) {
encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
- // This test is a server receiving a MAX_STREAMS frame. The
- // stream ID that it generates should be a server-initiated
- // stream ID. The expected Stream ID is
- // 0xfffffffc | 0x1 | 0x2 = 0xffffffff
- // maxid server inited, unidi
- EXPECT_EQ(GetNthStreamid(QUIC_VERSION_99, Perspective::IS_SERVER,
- /*bidirectional=*/false, 0x40000000),
- visitor_.max_stream_id_frame_.max_stream_id);
+ EXPECT_EQ(0x40000000u, visitor_.max_streams_frame_.stream_count);
+ EXPECT_TRUE(visitor_.max_streams_frame_.unidirectional);
}
TEST_P(QuicFramerTest, ClientUniDiMaxStreamsFrameTooBig) {
@@ -10482,19 +10779,11 @@ TEST_P(QuicFramerTest, ClientUniDiMaxStreamsFrameTooBig) {
encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_0BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
- // This test is a client receiving a MAX_STREAMS frame. The
- // stream ID that it generates should be a client-initiated
- // stream ID. The expected Stream ID is
- // 0xfffffffc | 0x02= 0xfffffffe
- // maxid client/unidi
- EXPECT_EQ(GetNthStreamid(QUIC_VERSION_99, Perspective::IS_CLIENT,
- /*bidirectional=*/false, 0x40000000),
- visitor_.max_stream_id_frame_.max_stream_id);
+ EXPECT_EQ(0x40000000u, visitor_.max_streams_frame_.stream_count);
+ EXPECT_TRUE(visitor_.max_streams_frame_.unidirectional);
}
-// Check that a stream count of 0 is rejected.
-// Directionality and intiation are not important for
-// this test.
+// Specifically test that count==0 is accepted.
TEST_P(QuicFramerTest, MaxStreamsFrameZeroCount) {
// This test only for version 99.
if (framer_.transport_version() != QUIC_VERSION_99) {
@@ -10519,10 +10808,7 @@ TEST_P(QuicFramerTest, MaxStreamsFrameZeroCount) {
QuicEncryptedPacket encrypted(AsChars(packet99), QUIC_ARRAYSIZE(packet99),
false);
- EXPECT_FALSE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_MAX_STREAM_ID_DATA, framer_.error());
- EXPECT_EQ(framer_.detailed_error(),
- "MAX_STREAMS stream count of 0 not supported.");
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
}
TEST_P(QuicFramerTest, ServerBiDiStreamsBlockedFrame) {
@@ -10543,12 +10829,12 @@ TEST_P(QuicFramerTest, ServerBiDiStreamsBlockedFrame) {
// packet number
{"",
{0x12, 0x34, 0x9A, 0xBC}},
- // frame type (IETF_STREAMS_BLOCKED_BIDIRECTIONAL frame)
+ // frame type (IETF_MAX_STREAMS_UNIDIRECTIONAL frame)
{"",
- {0x16}},
- // stream id
- {"Can not read STREAMS_BLOCKED stream id.",
- {kVarInt62OneByte + 0x03}},
+ {0x13}},
+ // stream count
+ {"Can not read MAX_STREAMS stream count.",
+ {kVarInt62OneByte + 0x00}},
};
// clang-format on
@@ -10562,23 +10848,13 @@ TEST_P(QuicFramerTest, ServerBiDiStreamsBlockedFrame) {
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
- // This test is a server receiving a STREAMS_BLOCKED frame. The
- // stream ID that it generates should be a client-initiated
- // stream ID. The expected Stream ID is
- // ((0x3-1) * 4) = 0xc
- // count-to-id client inited, bidi
- // It is not 8 because a client-initiated, bidi stream ID's
- // low bits are 00 - which means that the old crypto stream
- // falls into this category, and the first stream is streamid=4,
- // not streamid=0.
- EXPECT_EQ(GetNthStreamid(QUIC_VERSION_99, Perspective::IS_CLIENT,
- /*bidirectional=*/true, 3),
- visitor_.stream_id_blocked_frame_.stream_id);
+ EXPECT_EQ(0u, visitor_.max_streams_frame_.stream_count);
+ EXPECT_TRUE(visitor_.max_streams_frame_.unidirectional);
- CheckFramingBoundaries(packet99, QUIC_STREAM_ID_BLOCKED_DATA);
+ CheckFramingBoundaries(packet99, QUIC_MAX_STREAMS_DATA);
}
-TEST_P(QuicFramerTest, ClientBiDiStreamsBlockedFrame) {
+TEST_P(QuicFramerTest, BiDiStreamsBlockedFrame) {
// This test only for version 99.
if (framer_.transport_version() != QUIC_VERSION_99) {
return;
@@ -10590,7 +10866,9 @@ TEST_P(QuicFramerTest, ClientBiDiStreamsBlockedFrame) {
// type (short header, 4 byte packet number)
{"",
{0x43}},
- // Test runs in client mode, no connection id
+ // connection_id
+ {"",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x9A, 0xBC}},
@@ -10598,35 +10876,28 @@ TEST_P(QuicFramerTest, ClientBiDiStreamsBlockedFrame) {
{"",
{0x16}},
// stream id
- {"Can not read STREAMS_BLOCKED stream id.",
+ {"Can not read STREAMS_BLOCKED stream count.",
{kVarInt62OneByte + 0x03}},
};
// clang-format on
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(packet99));
- QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
- PACKET_0BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
+ PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
- // This test is a client receiving a STREAMS_BLOCKED frame. The
- // stream ID that it generates should be a server-initiated
- // stream ID. The expected Stream ID is
- // ((0x3-1) * 4) | 0x01 = 0x9
- // count-to-id server inited, bidi
- EXPECT_EQ(GetNthStreamid(QUIC_VERSION_99, Perspective::IS_SERVER,
- /*bidirectional=*/true, 3),
- visitor_.stream_id_blocked_frame_.stream_id);
+ EXPECT_EQ(3u, visitor_.streams_blocked_frame_.stream_count);
+ EXPECT_FALSE(visitor_.streams_blocked_frame_.unidirectional);
- CheckFramingBoundaries(packet99, QUIC_STREAM_ID_BLOCKED_DATA);
+ CheckFramingBoundaries(packet99, QUIC_STREAMS_BLOCKED_DATA);
}
-TEST_P(QuicFramerTest, ServerUniDiStreamsBlockedFrame) {
+TEST_P(QuicFramerTest, UniDiStreamsBlockedFrame) {
// This test only for version 99.
if (framer_.transport_version() != QUIC_VERSION_99) {
return;
@@ -10648,7 +10919,7 @@ TEST_P(QuicFramerTest, ServerUniDiStreamsBlockedFrame) {
{"",
{0x17}},
// stream id
- {"Can not read STREAMS_BLOCKED stream id.",
+ {"Can not read STREAMS_BLOCKED stream count.",
{kVarInt62OneByte + 0x03}},
};
// clang-format on
@@ -10663,16 +10934,9 @@ TEST_P(QuicFramerTest, ServerUniDiStreamsBlockedFrame) {
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
- // This test is a server receiving a STREAMS_BLOCKED frame. The
- // stream ID that it generates should be a client-initiated
- // stream ID. The expected Stream ID is
- // ((0x3-1) * 4) | 0x2 = 0xa
- // count-to-id client inited, unidi
- EXPECT_EQ(GetNthStreamid(QUIC_VERSION_99, Perspective::IS_CLIENT,
- /*bidirectional=*/false, 3),
- visitor_.stream_id_blocked_frame_.stream_id);
-
- CheckFramingBoundaries(packet99, QUIC_STREAM_ID_BLOCKED_DATA);
+ EXPECT_EQ(3u, visitor_.streams_blocked_frame_.stream_count);
+ EXPECT_TRUE(visitor_.streams_blocked_frame_.unidirectional);
+ CheckFramingBoundaries(packet99, QUIC_STREAMS_BLOCKED_DATA);
}
TEST_P(QuicFramerTest, ClientUniDiStreamsBlockedFrame) {
@@ -10695,7 +10959,7 @@ TEST_P(QuicFramerTest, ClientUniDiStreamsBlockedFrame) {
{"",
{0x17}},
// stream id
- {"Can not read STREAMS_BLOCKED stream id.",
+ {"Can not read STREAMS_BLOCKED stream count.",
{kVarInt62OneByte + 0x03}},
};
// clang-format on
@@ -10711,16 +10975,9 @@ TEST_P(QuicFramerTest, ClientUniDiStreamsBlockedFrame) {
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_0BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
- // This test is a client receiving a STREAMS_BLOCKED frame. The
- // stream ID that it generates should be a server-initiated
- // stream ID. The expected Stream ID is
- // ((0x3-1) * 4) | 0x01 | 0x2 = 0xb
- // count-to-id server inited, bidi
- EXPECT_EQ(GetNthStreamid(QUIC_VERSION_99, Perspective::IS_SERVER,
- /*bidirectional=*/false, 3),
- visitor_.stream_id_blocked_frame_.stream_id);
-
- CheckFramingBoundaries(packet99, QUIC_STREAM_ID_BLOCKED_DATA);
+ EXPECT_EQ(3u, visitor_.streams_blocked_frame_.stream_count);
+ EXPECT_TRUE(visitor_.streams_blocked_frame_.unidirectional);
+ CheckFramingBoundaries(packet99, QUIC_STREAMS_BLOCKED_DATA);
}
// Check that when we get a STREAMS_BLOCKED frame that specifies too large
@@ -10742,7 +10999,7 @@ TEST_P(QuicFramerTest, StreamsBlockedFrameTooBig) {
// packet number
0x12, 0x34, 0x9A, 0xBC,
// frame type (IETF_STREAMS_BLOCKED_BIDIRECTIONAL)
- 0x17,
+ 0x16,
// max. streams. Max stream ID allowed is 0xffffffff
// This encodes a count of 0x40000000, leading to stream
@@ -10756,111 +11013,72 @@ TEST_P(QuicFramerTest, StreamsBlockedFrameTooBig) {
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_STREAM_ID_BLOCKED_DATA, framer_.error());
+ EXPECT_EQ(QUIC_STREAMS_BLOCKED_DATA, framer_.error());
EXPECT_EQ(framer_.detailed_error(),
"STREAMS_BLOCKED stream count exceeds implementation limit.");
}
-// Test that count==0 is rejected.
+// Specifically test that count==0 is accepted.
TEST_P(QuicFramerTest, StreamsBlockedFrameZeroCount) {
// This test only for version 99.
if (framer_.transport_version() != QUIC_VERSION_99) {
return;
}
+
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// clang-format off
- unsigned char packet99[] = {
- // type (short header, 4 byte packet number)
- 0x43,
- // Test runs in client mode, no connection id
- // packet number
- 0x12, 0x34, 0x9A, 0xBC,
- // frame type (IETF_STREAMS_BLOCKED_BIDIRECTIONAL)
- 0x17,
-
- // max. streams = 0
- kVarInt62OneByte + 0x00
+ PacketFragments packet99 = {
+ // type (short header, 4 byte packet number)
+ {"",
+ {0x43}},
+ // connection_id
+ {"",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x12, 0x34, 0x9A, 0xBC}},
+ // frame type (IETF_STREAMS_BLOCKED_UNIDIRECTIONAL frame)
+ {"",
+ {0x17}},
+ // stream id
+ {"Can not read STREAMS_BLOCKED stream count.",
+ {kVarInt62OneByte + 0x00}},
};
// clang-format on
- QuicEncryptedPacket encrypted(AsChars(packet99), QUIC_ARRAYSIZE(packet99),
- false);
- QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
- EXPECT_FALSE(framer_.ProcessPacket(encrypted));
-
- EXPECT_EQ(QUIC_STREAM_ID_BLOCKED_DATA, framer_.error());
- EXPECT_EQ(framer_.detailed_error(),
- "STREAMS_BLOCKED stream count 0 not supported.");
-}
-
-TEST_P(QuicFramerTest, BuildServerBiDiStreamsBlockedPacket) {
- // This test only for version 99.
- if (framer_.transport_version() != QUIC_VERSION_99) {
- return;
- }
-
- QuicPacketHeader header;
- header.destination_connection_id = FramerTestConnectionId();
- header.reset_flag = false;
- header.version_flag = false;
- header.packet_number = kPacketNumber;
-
- QuicStreamIdBlockedFrame frame;
- // A server building a STREAMS_BLOCKED frame generates
- // a server-initiated stream ID. This test is bidirectional.
- // The low two bits of the stream ID are 01
- // Expected value is 0x8u | 0x1u;
- frame.stream_id = GetNthStreamid(QUIC_VERSION_99, Perspective::IS_SERVER,
- /*bidirectional=*/true, 3);
-
- QuicFrames frames = {QuicFrame(frame)};
-
- // 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,
+ std::unique_ptr<QuicEncryptedPacket> encrypted(
+ AssemblePacketFromFragments(packet99));
+ EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
- // frame type (IETF_STREAMS_BLOCKED_BIDIRECTIONAL frame)
- 0x16,
- // Stream count
- kVarInt62OneByte + 0x03
- };
- // clang-format on
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+ EXPECT_TRUE(CheckDecryption(
+ *encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
+ PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
- std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
- ASSERT_TRUE(data != nullptr);
+ EXPECT_EQ(0u, visitor_.streams_blocked_frame_.stream_count);
+ EXPECT_TRUE(visitor_.streams_blocked_frame_.unidirectional);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
+ CheckFramingBoundaries(packet99, QUIC_STREAMS_BLOCKED_DATA);
}
-TEST_P(QuicFramerTest, BuildClientBiDiStreamsBlockedPacket) {
+TEST_P(QuicFramerTest, BuildBiDiStreamsBlockedPacket) {
// This test only for version 99.
if (framer_.transport_version() != QUIC_VERSION_99) {
return;
}
- // This test runs in client mode.
- QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
-
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
header.version_flag = false;
header.packet_number = kPacketNumber;
- QuicStreamIdBlockedFrame frame;
- // A client building a STREAMS_BLOCKED frame generates
- // a client-initiated stream ID. This test is bidirectional.
- // The low two bits of the stream ID are 00. Expected value is 0x8
- frame.stream_id = GetNthStreamid(QUIC_VERSION_99, Perspective::IS_CLIENT,
- /*bidirectional=*/true, 3);
+ QuicStreamsBlockedFrame frame;
+ frame.stream_count = 3;
+ frame.unidirectional = false;
+
QuicFrames frames = {QuicFrame(frame)};
// clang-format off
@@ -10887,7 +11105,7 @@ TEST_P(QuicFramerTest, BuildClientBiDiStreamsBlockedPacket) {
QUIC_ARRAYSIZE(packet99));
}
-TEST_P(QuicFramerTest, BuildServerUniStreamsBlockedPacket) {
+TEST_P(QuicFramerTest, BuildUniStreamsBlockedPacket) {
// This test only for version 99.
if (framer_.transport_version() != QUIC_VERSION_99) {
return;
@@ -10899,59 +11117,10 @@ TEST_P(QuicFramerTest, BuildServerUniStreamsBlockedPacket) {
header.version_flag = false;
header.packet_number = kPacketNumber;
- QuicStreamIdBlockedFrame frame;
- // A server building a STREAMS_BLOCKED frame generates
- // a server-initiated stream ID. This test is bidirectional.
- // The low two bits of the stream ID are 11. Expected value is 0xb
- frame.stream_id = GetNthStreamid(QUIC_VERSION_99, Perspective::IS_SERVER,
- /*bidirectional=*/false, 3);
- QuicFrames frames = {QuicFrame(frame)};
+ QuicStreamsBlockedFrame frame;
+ frame.stream_count = 3;
+ frame.unidirectional = true;
- // 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_STREAMS_BLOCKED_UNIDIRECTIONAL frame)
- 0x17,
- // Stream count
- kVarInt62OneByte + 0x03
- };
- // clang-format on
-
- std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
- ASSERT_TRUE(data != nullptr);
-
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
-}
-
-TEST_P(QuicFramerTest, BuildClientUniDiStreamsBlockedPacket) {
- // This test only for version 99.
- if (framer_.transport_version() != QUIC_VERSION_99) {
- return;
- }
-
- // This test runs in client mode.
- QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
-
- QuicPacketHeader header;
- header.destination_connection_id = FramerTestConnectionId();
- header.reset_flag = false;
- header.version_flag = false;
- header.packet_number = kPacketNumber;
-
- QuicStreamIdBlockedFrame frame;
- // A client building a STREAMS_BLOCKED frame generates
- // a client-initiated stream ID. This test is bidirectional.
- // The low two bits of the stream ID are 10. Expected value is 0xa
- frame.stream_id = GetNthStreamid(QUIC_VERSION_99, Perspective::IS_CLIENT,
- /*bidirectional=*/false, 3);
QuicFrames frames = {QuicFrame(frame)};
// clang-format off
@@ -10978,7 +11147,7 @@ TEST_P(QuicFramerTest, BuildClientUniDiStreamsBlockedPacket) {
QUIC_ARRAYSIZE(packet99));
}
-TEST_P(QuicFramerTest, BuildServerBiDiMaxStreamsPacket) {
+TEST_P(QuicFramerTest, BuildBiDiMaxStreamsPacket) {
// This test only for version 99.
if (framer_.transport_version() != QUIC_VERSION_99) {
return;
@@ -10990,61 +11159,10 @@ TEST_P(QuicFramerTest, BuildServerBiDiMaxStreamsPacket) {
header.version_flag = false;
header.packet_number = kPacketNumber;
- QuicMaxStreamIdFrame frame;
- // A server building a MAX_STREAMS frame generates
- // a client-initiated stream ID. This test is bidirectional.
- // The low two bits of the stream ID are 00. Expected value is 0xc
- // because streamid==0 is special and the first client/bidi
- // stream is 4, not 0.
- frame.max_stream_id = GetNthStreamid(QUIC_VERSION_99, Perspective::IS_CLIENT,
- /*bidirectional=*/true, 3);
- QuicFrames frames = {QuicFrame(frame)};
+ QuicMaxStreamsFrame frame;
+ frame.stream_count = 3;
+ frame.unidirectional = false;
- // 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_MAX_STREAMS_BIDIRECTIONAL frame)
- 0x12,
- // Stream count
- kVarInt62OneByte + 0x03
- };
- // clang-format on
-
- std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
- ASSERT_TRUE(data != nullptr);
-
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
-}
-
-TEST_P(QuicFramerTest, BuildClientBiDiMaxStreamsPacket) {
- // This test only for version 99.
- if (framer_.transport_version() != QUIC_VERSION_99) {
- return;
- }
-
- // This test runs in client mode.
- QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
-
- QuicPacketHeader header;
- header.destination_connection_id = FramerTestConnectionId();
- header.reset_flag = false;
- header.version_flag = false;
- header.packet_number = kPacketNumber;
-
- QuicMaxStreamIdFrame frame;
- // A client building a MAX_STREAMS frame generates
- // a server-initiated stream ID. This test is bidirectional.
- // The low two bits of the stream ID are 01. Expected value is 0x9
- frame.max_stream_id = GetNthStreamid(QUIC_VERSION_99, Perspective::IS_SERVER,
- /*bidirectional=*/true, 3);
QuicFrames frames = {QuicFrame(frame)};
// clang-format off
@@ -11071,51 +11189,7 @@ TEST_P(QuicFramerTest, BuildClientBiDiMaxStreamsPacket) {
QUIC_ARRAYSIZE(packet99));
}
-TEST_P(QuicFramerTest, BuildServerUniMaxStreamsPacket) {
- // This test only for version 99.
- if (framer_.transport_version() != QUIC_VERSION_99) {
- return;
- }
-
- QuicPacketHeader header;
- header.destination_connection_id = FramerTestConnectionId();
- header.reset_flag = false;
- header.version_flag = false;
- header.packet_number = kPacketNumber;
-
- QuicMaxStreamIdFrame frame;
- // A server building a MAX_STREAMS frame generates
- // a client-initiated stream ID. This test is bidirectional.
- // The low two bits of the stream ID are 10. Expected value is 0xa
- frame.max_stream_id = GetNthStreamid(QUIC_VERSION_99, Perspective::IS_CLIENT,
- /*bidirectional=*/false, 3);
- QuicFrames frames = {QuicFrame(frame)};
-
- // 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_MAX_STREAMS_UNIDIRECTIONAL frame)
- 0x13,
- // Stream count
- kVarInt62OneByte + 0x03
- };
- // clang-format on
-
- std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
- ASSERT_TRUE(data != nullptr);
-
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet99),
- QUIC_ARRAYSIZE(packet99));
-}
-
-TEST_P(QuicFramerTest, BuildClientUniDiMaxStreamsPacket) {
+TEST_P(QuicFramerTest, BuildUniDiMaxStreamsPacket) {
// This test only for version 99.
if (framer_.transport_version() != QUIC_VERSION_99) {
return;
@@ -11130,12 +11204,10 @@ TEST_P(QuicFramerTest, BuildClientUniDiMaxStreamsPacket) {
header.version_flag = false;
header.packet_number = kPacketNumber;
- QuicMaxStreamIdFrame frame;
- // A client building a MAX_STREAMS frame generates
- // a server-initiated stream ID. This test is bidirectional.
- // The low two bits of the stream ID are 11. Expected value is 0xb
- frame.max_stream_id = GetNthStreamid(QUIC_VERSION_99, Perspective::IS_SERVER,
- /*bidirectional=*/false, 3);
+ QuicMaxStreamsFrame frame;
+ frame.stream_count = 3;
+ frame.unidirectional = true;
+
QuicFrames frames = {QuicFrame(frame)};
// clang-format off
@@ -11323,6 +11395,7 @@ TEST_P(QuicFramerTest, BuildNewConnectionIdFramePacket) {
// This frame is only for version 99.
return;
}
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -11423,6 +11496,7 @@ TEST_P(QuicFramerTest, BuildNewTokenFramePacket) {
// This frame is only for version 99.
return;
}
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -11730,9 +11804,8 @@ TEST_P(QuicFramerTest, GetRetransmittableControlFrameSize) {
connection_close.close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE;
}
- EXPECT_EQ(QuicFramer::GetMinConnectionCloseFrameSize(
- framer_.transport_version(), connection_close) +
- 256,
+ EXPECT_EQ(QuicFramer::GetConnectionCloseFrameSize(framer_.transport_version(),
+ connection_close),
QuicFramer::GetRetransmittableControlFrameSize(
framer_.transport_version(), QuicFrame(&connection_close)));
@@ -11762,17 +11835,17 @@ TEST_P(QuicFramerTest, GetRetransmittableControlFrameSize) {
QuicFramer::GetRetransmittableControlFrameSize(
framer_.transport_version(), QuicFrame(&new_connection_id)));
- QuicMaxStreamIdFrame max_stream_id(6, 3);
+ QuicMaxStreamsFrame max_streams(6, 3, /*unidirectional=*/false);
EXPECT_EQ(QuicFramer::GetMaxStreamsFrameSize(framer_.transport_version(),
- max_stream_id),
+ max_streams),
QuicFramer::GetRetransmittableControlFrameSize(
- framer_.transport_version(), QuicFrame(max_stream_id)));
+ framer_.transport_version(), QuicFrame(max_streams)));
- QuicStreamIdBlockedFrame stream_id_blocked(7, 3);
+ QuicStreamsBlockedFrame streams_blocked(7, 3, /*unidirectional=*/false);
EXPECT_EQ(QuicFramer::GetStreamsBlockedFrameSize(framer_.transport_version(),
- stream_id_blocked),
+ streams_blocked),
QuicFramer::GetRetransmittableControlFrameSize(
- framer_.transport_version(), QuicFrame(stream_id_blocked)));
+ framer_.transport_version(), QuicFrame(streams_blocked)));
QuicPathFrameBuffer buffer = {
{0x80, 0x91, 0xa2, 0xb3, 0xc4, 0xd5, 0xe5, 0xf7}};
@@ -12486,6 +12559,7 @@ TEST_P(QuicFramerTest, BuildRetireConnectionIdFramePacket) {
// This frame is only for version 99.
return;
}
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
@@ -13110,6 +13184,90 @@ TEST_P(QuicFramerTest, InvalidCoalescedPacket) {
ASSERT_EQ(visitor_.coalesced_packets_.size(), 0u);
}
+// Some IETF implementations send an initial followed by zeroes instead of
+// padding inside the initial. We need to make sure that we still process
+// the initial correctly and ignore the zeroes.
+TEST_P(QuicFramerTest, CoalescedPacketWithZeroesRoundTrip) {
+ if (!QuicVersionHasLongHeaderLengths(framer_.transport_version())) {
+ return;
+ }
+ ASSERT_TRUE(framer_.version().KnowsWhichDecrypterToUse());
+ QuicConnectionId connection_id = FramerTestConnectionId();
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
+
+ CrypterPair client_crypters;
+ CryptoUtils::CreateTlsInitialCrypters(Perspective::IS_CLIENT,
+ framer_.transport_version(),
+ connection_id, &client_crypters);
+ framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ std::move(client_crypters.encrypter));
+
+ QuicPacketHeader header;
+ header.destination_connection_id = connection_id;
+ header.version_flag = true;
+ header.packet_number = kPacketNumber;
+ header.packet_number_length = PACKET_4BYTE_PACKET_NUMBER;
+ header.long_packet_type = INITIAL;
+ header.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2;
+ header.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1;
+ QuicFrames frames = {QuicFrame(QuicPingFrame())};
+
+ std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
+ ASSERT_NE(nullptr, data);
+
+ // Add zeroes after the valid initial packet.
+ unsigned char packet[kMaxOutgoingPacketSize] = {};
+ size_t encrypted_length =
+ framer_.EncryptPayload(ENCRYPTION_INITIAL, header.packet_number, *data,
+ AsChars(packet), QUIC_ARRAYSIZE(packet));
+ ASSERT_NE(0u, encrypted_length);
+
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
+ CrypterPair server_crypters;
+ CryptoUtils::CreateTlsInitialCrypters(Perspective::IS_SERVER,
+ framer_.transport_version(),
+ connection_id, &server_crypters);
+ framer_.InstallDecrypter(ENCRYPTION_INITIAL,
+ std::move(server_crypters.decrypter));
+
+ // Make sure the first long header initial packet parses correctly.
+ QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
+
+ // Make sure we discard the subsequent zeroes.
+ EXPECT_QUIC_PEER_BUG(EXPECT_TRUE(framer_.ProcessPacket(encrypted)),
+ "Server: Received mismatched coalesced header.*");
+}
+
+TEST_P(QuicFramerTest, ClientReceivesInvalidVersion) {
+ if (framer_.transport_version() < QUIC_VERSION_44) {
+ return;
+ }
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
+
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (long header with packet type INITIAL)
+ 0xFF,
+ // version that is different from the framer's version
+ 'Q', '0', '4', '3',
+ // connection ID lengths
+ 0x05,
+ // source connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x01,
+ // padding frame
+ 0x00,
+ };
+ // clang-format on
+
+ QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
+ EXPECT_FALSE(framer_.ProcessPacket(encrypted));
+
+ EXPECT_EQ(QUIC_INVALID_VERSION, framer_.error());
+ EXPECT_EQ("Client received unexpected version.", framer_.detailed_error());
+}
+
TEST_P(QuicFramerTest, PacketHeaderWithVariableLengthConnectionId) {
if (framer_.transport_version() < QUIC_VERSION_46) {
return;
@@ -13120,8 +13278,8 @@ TEST_P(QuicFramerTest, PacketHeaderWithVariableLengthConnectionId) {
QuicConnectionId connection_id(connection_id_bytes,
sizeof(connection_id_bytes));
QuicFramerPeer::SetLargestPacketNumber(&framer_, kPacketNumber - 2);
- QuicFramerPeer::SetExpectedConnectionIDLength(&framer_,
- connection_id.length());
+ QuicFramerPeer::SetExpectedServerConnectionIDLength(&framer_,
+ connection_id.length());
// clang-format off
PacketFragments packet = {
@@ -13135,12 +13293,33 @@ TEST_P(QuicFramerTest, PacketHeaderWithVariableLengthConnectionId) {
{"Unable to read packet number.",
{0x78}},
};
+
+ PacketFragments packet_with_padding = {
+ // type (8 byte connection_id and 1 byte packet number)
+ {"Unable to read type.",
+ {0x40}},
+ // connection_id
+ {"Unable to read Destination ConnectionId.",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0x42}},
+ // packet number
+ {"",
+ {0x78}},
+ // padding
+ {"", {0x00, 0x00, 0x00}},
+ };
// clang-format on
+ PacketFragments& fragments =
+ framer_.version().HasHeaderProtection() ? packet_with_padding : packet;
std::unique_ptr<QuicEncryptedPacket> encrypted(
- AssemblePacketFromFragments(packet));
- EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
- EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
+ AssemblePacketFromFragments(fragments));
+ if (framer_.version().HasHeaderProtection()) {
+ EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ } else {
+ EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
+ EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
+ }
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(connection_id, visitor_.header_->destination_connection_id);
EXPECT_FALSE(visitor_.header_->reset_flag);
@@ -13148,7 +13327,7 @@ TEST_P(QuicFramerTest, PacketHeaderWithVariableLengthConnectionId) {
EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, visitor_.header_->packet_number_length);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
- CheckFramingBoundaries(packet, QUIC_INVALID_PACKET_HEADER);
+ CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER);
}
TEST_P(QuicFramerTest, UpdateExpectedConnectionIdLength) {
@@ -13156,7 +13335,7 @@ TEST_P(QuicFramerTest, UpdateExpectedConnectionIdLength) {
return;
}
SetDecrypterLevel(ENCRYPTION_ZERO_RTT);
- framer_.SetShouldUpdateExpectedConnectionIdLength(true);
+ framer_.SetShouldUpdateExpectedServerConnectionIdLength(true);
// clang-format off
unsigned char long_header_packet[] = {
@@ -13234,13 +13413,41 @@ TEST_P(QuicFramerTest, UpdateExpectedConnectionIdLength) {
FramerTestConnectionIdNineBytes());
EXPECT_EQ(visitor_.header_.get()->packet_number,
QuicPacketNumber(UINT64_C(0x13374233)));
+
+ PacketHeaderFormat format;
+ bool version_flag;
+ uint8_t destination_connection_id_length;
+ QuicConnectionId destination_connection_id;
+ QuicVersionLabel version_label;
+ std::string detailed_error;
+ EXPECT_EQ(QUIC_NO_ERROR,
+ QuicFramer::ProcessPacketDispatcher(
+ QuicEncryptedPacket(AsChars(long_header_packet),
+ QUIC_ARRAYSIZE(long_header_packet)),
+ kQuicDefaultConnectionIdLength, &format, &version_flag,
+ &version_label, &destination_connection_id_length,
+ &destination_connection_id, &detailed_error));
+ EXPECT_EQ(IETF_QUIC_LONG_HEADER_PACKET, format);
+ EXPECT_TRUE(version_flag);
+ EXPECT_EQ(9, destination_connection_id_length);
+ EXPECT_EQ(FramerTestConnectionIdNineBytes(), destination_connection_id);
+
+ EXPECT_EQ(QUIC_NO_ERROR,
+ QuicFramer::ProcessPacketDispatcher(
+ short_header_encrypted, 9, &format, &version_flag,
+ &version_label, &destination_connection_id_length,
+ &destination_connection_id, &detailed_error));
+ EXPECT_EQ(IETF_QUIC_SHORT_HEADER_PACKET, format);
+ EXPECT_FALSE(version_flag);
+ EXPECT_EQ(9, destination_connection_id_length);
+ EXPECT_EQ(FramerTestConnectionIdNineBytes(), destination_connection_id);
}
TEST_P(QuicFramerTest, MultiplePacketNumberSpaces) {
if (framer_.transport_version() < QUIC_VERSION_46) {
return;
}
- framer_.SetShouldUpdateExpectedConnectionIdLength(true);
+ framer_.SetShouldUpdateExpectedServerConnectionIdLength(true);
framer_.EnableMultiplePacketNumberSpacesSupport();
// clang-format off
@@ -13314,7 +13521,7 @@ TEST_P(QuicFramerTest, MultiplePacketNumberSpaces) {
// packet number
0x79,
// padding frame
- 0x00,
+ 0x00, 0x00, 0x00,
};
// clang-format on
@@ -13341,6 +13548,298 @@ TEST_P(QuicFramerTest, MultiplePacketNumberSpaces) {
&framer_, APPLICATION_DATA));
}
+TEST_P(QuicFramerTest, IetfRetryPacketRejected) {
+ if (!framer_.version().KnowsWhichDecrypterToUse() ||
+ framer_.version().SupportsRetry()) {
+ return;
+ }
+
+ // clang-format off
+ PacketFragments packet = {
+ // public flags (IETF Retry packet, 0-length original destination CID)
+ {"Unable to read type.",
+ {0xf0}},
+ // version tag
+ {"Unable to read protocol version.",
+ {QUIC_VERSION_BYTES}},
+ // connection_id length
+ {"Illegal long header type value.",
+ {0x00}},
+ };
+ // clang-format on
+
+ // clang-format off
+ PacketFragments packet45 = {
+ // public flags (IETF Retry packet, 0-length original destination CID)
+ {"Unable to read type.",
+ {0xf0}},
+ // version tag
+ {"Unable to read protocol version.",
+ {QUIC_VERSION_BYTES}},
+ // connection_id length
+ {"RETRY not supported in this version.",
+ {0x00}},
+ };
+ // clang-format on
+
+ PacketFragments& fragments =
+ framer_.transport_version() > QUIC_VERSION_44 ? packet45 : packet;
+ std::unique_ptr<QuicEncryptedPacket> encrypted(
+ AssemblePacketFromFragments(fragments));
+
+ EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
+ EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER);
+}
+
+TEST_P(QuicFramerTest, RetryPacketRejectedWithMultiplePacketNumberSpaces) {
+ if (framer_.transport_version() < QUIC_VERSION_46 ||
+ framer_.version().SupportsRetry()) {
+ return;
+ }
+ framer_.EnableMultiplePacketNumberSpacesSupport();
+
+ // clang-format off
+ PacketFragments packet = {
+ // public flags (IETF Retry packet, 0-length original destination CID)
+ {"Unable to read type.",
+ {0xf0}},
+ // version tag
+ {"Unable to read protocol version.",
+ {QUIC_VERSION_BYTES}},
+ // connection_id length
+ {"RETRY not supported in this version.",
+ {0x00}},
+ };
+ // clang-format on
+
+ std::unique_ptr<QuicEncryptedPacket> encrypted(
+ AssemblePacketFromFragments(packet));
+
+ EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
+ EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ CheckFramingBoundaries(packet, QUIC_INVALID_PACKET_HEADER);
+}
+
+TEST_P(QuicFramerTest, ProcessPublicHeaderNoVersionInferredType) {
+ // The framer needs to have Perspective::IS_SERVER and configured to infer the
+ // packet header type from the packet (not the version). The framer's version
+ // needs to be one that uses the IETF packet format.
+ if (!framer_.version().KnowsWhichDecrypterToUse()) {
+ return;
+ }
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
+
+ // Prepare a packet that uses the Google QUIC packet header but has no version
+ // field.
+
+ // clang-format off
+ PacketFragments packet = {
+ // public flags (1-byte packet number, 8-byte connection_id, no version)
+ {"Unable to read public flags.",
+ {0x08}},
+ // connection_id
+ {"Unable to read ConnectionId.",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"Unable to read packet number.",
+ {0x01}},
+ // padding
+ {"Invalid public header type for expected version.",
+ {0x00}},
+ };
+ // clang-format on
+
+ PacketFragments& fragments = packet;
+
+ std::unique_ptr<QuicEncryptedPacket> encrypted(
+ AssemblePacketFromFragments(fragments));
+
+ EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
+ EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ EXPECT_EQ("Invalid public header type for expected version.",
+ framer_.detailed_error());
+ CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER);
+}
+
+TEST_P(QuicFramerTest, ProcessMismatchedHeaderVersion) {
+ // The framer needs to have Perspective::IS_SERVER and configured to infer the
+ // packet header type from the packet (not the version). The framer's version
+ // needs to be one that uses the IETF packet format.
+ if (!framer_.version().KnowsWhichDecrypterToUse()) {
+ return;
+ }
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
+
+ // clang-format off
+ PacketFragments packet = {
+ // public flags (Google QUIC header with version present)
+ {"Unable to read public flags.",
+ {0x09}},
+ // connection_id
+ {"Unable to read ConnectionId.",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // version tag
+ {"Unable to read protocol version.",
+ {QUIC_VERSION_BYTES}},
+ // packet number
+ {"Unable to read packet number.",
+ {0x01}},
+ };
+ // clang-format on
+
+ std::unique_ptr<QuicEncryptedPacket> encrypted(
+ AssemblePacketFromFragments(packet));
+ framer_.ProcessPacket(*encrypted);
+
+ EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
+ EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ EXPECT_EQ("Invalid public header type for expected version.",
+ framer_.detailed_error());
+ CheckFramingBoundaries(packet, QUIC_INVALID_PACKET_HEADER);
+}
+
+TEST_P(QuicFramerTest, WriteClientVersionNegotiationProbePacket) {
+ // clang-format off
+ static const char expected_packet[1200] = {
+ // IETF long header with fixed bit set, type initial, all-0 encrypted bits.
+ 0xc0,
+ // Version, part of the IETF space reserved for negotiation.
+ 0xca, 0xba, 0xda, 0xba,
+ // Destination connection ID length 8, source connection ID length 0.
+ 0x50,
+ // 8-byte destination connection ID.
+ 0x56, 0x4e, 0x20, 0x70, 0x6c, 0x7a, 0x20, 0x21,
+ // 8 bytes of zeroes followed by 8 bytes of ones to ensure that this does
+ // not parse with any known version.
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ // 2 bytes of zeroes to pad to 16 byte boundary.
+ 0x00, 0x00,
+ // A polite greeting in case a human sees this in tcpdump.
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x61, 0x63,
+ 0x6b, 0x65, 0x74, 0x20, 0x6f, 0x6e, 0x6c, 0x79,
+ 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x72, 0x69, 0x67, 0x67,
+ 0x65, 0x72, 0x20, 0x49, 0x45, 0x54, 0x46, 0x20,
+ 0x51, 0x55, 0x49, 0x43, 0x20, 0x76, 0x65, 0x72,
+ 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x65, 0x67,
+ 0x6f, 0x74, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x2e, 0x20, 0x50, 0x6c, 0x65, 0x61, 0x73, 0x65,
+ 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20,
+ 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20,
+ 0x4e, 0x65, 0x67, 0x6f, 0x74, 0x69, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x61, 0x63, 0x6b,
+ 0x65, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x63,
+ 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x68,
+ 0x61, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69,
+ 0x6f, 0x6e, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x20,
+ 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x2e,
+ 0x20, 0x54, 0x68, 0x61, 0x6e, 0x6b, 0x20, 0x79,
+ 0x6f, 0x75, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68,
+ 0x61, 0x76, 0x65, 0x20, 0x61, 0x20, 0x6e, 0x69,
+ 0x63, 0x65, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x00,
+ };
+ // clang-format on
+ char packet[1200];
+ char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
+ 0x6c, 0x7a, 0x20, 0x21};
+ EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
+ packet, sizeof(packet), destination_connection_id_bytes,
+ sizeof(destination_connection_id_bytes)));
+ test::CompareCharArraysWithHexError("constructed packet", expected_packet,
+ sizeof(expected_packet), packet,
+ sizeof(packet));
+ QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet),
+ sizeof(packet), false);
+ // Make sure we fail to parse this packet for the version under test.
+ EXPECT_FALSE(framer_.ProcessPacket(encrypted));
+ if (framer_.transport_version() <= QUIC_VERSION_43) {
+ // We can only parse the connection ID with an IETF parser.
+ return;
+ }
+ ASSERT_TRUE(visitor_.header_.get());
+ QuicConnectionId probe_payload_connection_id(
+ reinterpret_cast<const char*>(destination_connection_id_bytes),
+ sizeof(destination_connection_id_bytes));
+ EXPECT_EQ(probe_payload_connection_id,
+ visitor_.header_.get()->destination_connection_id);
+}
+
+TEST_P(QuicFramerTest, ParseServerVersionNegotiationProbeResponse) {
+ // clang-format off
+ const char packet[] = {
+ // IETF long header with fixed bit set, type initial, all-0 encrypted bits.
+ 0xc0,
+ // Version of 0, indicating version negotiation.
+ 0x00, 0x00, 0x00, 0x00,
+ // Destination connection ID length 0, source connection ID length 8.
+ 0x05,
+ // 8-byte source connection ID.
+ 0x56, 0x4e, 0x20, 0x70, 0x6c, 0x7a, 0x20, 0x21,
+ // A few supported versions.
+ 0xaa, 0xaa, 0xaa, 0xaa,
+ QUIC_VERSION_BYTES,
+ };
+ // clang-format on
+ char probe_payload_bytes[] = {0x56, 0x4e, 0x20, 0x70, 0x6c, 0x7a, 0x20, 0x21};
+ char parsed_probe_payload_bytes[kQuicMaxConnectionIdLength] = {};
+ uint8_t parsed_probe_payload_length = 0;
+ std::string parse_detailed_error = "";
+ EXPECT_TRUE(QuicFramer::ParseServerVersionNegotiationProbeResponse(
+ reinterpret_cast<const char*>(packet), sizeof(packet),
+ reinterpret_cast<char*>(parsed_probe_payload_bytes),
+ &parsed_probe_payload_length, &parse_detailed_error));
+ EXPECT_EQ("", parse_detailed_error);
+ test::CompareCharArraysWithHexError(
+ "parsed probe", probe_payload_bytes, sizeof(probe_payload_bytes),
+ parsed_probe_payload_bytes, parsed_probe_payload_length);
+}
+
+TEST_P(QuicFramerTest, ClientConnectionIdNotSupportedYet) {
+ if (GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ // This check is currently only performed when this flag is disabled.
+ return;
+ }
+ if (framer_.transport_version() <= QUIC_VERSION_43) {
+ // This test requires an IETF long header.
+ return;
+ }
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
+ const unsigned char type_byte =
+ framer_.transport_version() == QUIC_VERSION_44 ? 0xFC : 0xD3;
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (long header with packet type ZERO_RTT_PROTECTED and
+ // 4-byte packet number)
+ type_byte,
+ // version
+ QUIC_VERSION_BYTES,
+ // destination connection ID length
+ 0x50,
+ // destination connection ID
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // long header packet length
+ 0x05,
+ // packet number
+ 0x12, 0x34, 0x56, 0x00,
+ // padding frame
+ 0x00,
+ };
+ // clang-format on
+ EXPECT_FALSE(framer_.ProcessPacket(
+ QuicEncryptedPacket(AsChars(packet), QUIC_ARRAYSIZE(packet), false)));
+ EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ if (!QuicUtils::VariableLengthConnectionIdAllowedForVersion(
+ framer_.transport_version())) {
+ EXPECT_EQ("Invalid ConnectionId length.", framer_.detailed_error());
+ } else {
+ EXPECT_EQ("Client connection ID not supported yet.",
+ framer_.detailed_error());
+ }
+}
+
} // 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 b0c01257356..f30fc99cb55 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
@@ -96,6 +96,10 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
void OnVersionNegotiationPacket(
const QuicVersionNegotiationPacket& packet) override {}
+ void OnRetryPacket(QuicConnectionId original_connection_id,
+ QuicConnectionId new_connection_id,
+ QuicStringPiece retry_token) override {}
+
bool OnProtocolVersionMismatch(ParsedQuicVersion received_version,
PacketHeaderFormat form) override {
return true;
@@ -192,11 +196,11 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
void OnAuthenticatedIetfStatelessResetPacket(
const QuicIetfStatelessResetPacket& packet) override {}
- bool OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) override {
+ bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override {
return true;
}
- bool OnStreamIdBlockedFrame(const QuicStreamIdBlockedFrame& frame) override {
+ bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override {
return true;
}
};
@@ -455,28 +459,16 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
EXPECT_EQ(receive_frame.byte_offset, transmit_frame.byte_offset);
}
- void TryMaxStreamsFrame(QuicStreamId stream_id,
+ void TryMaxStreamsFrame(QuicStreamCount stream_count,
bool unidirectional,
bool stream_id_server_initiated) {
- if (!unidirectional && !stream_id_server_initiated && stream_id == 0) {
- // For bidirectional, client initiated, streams, 0 is not allowed,
- // it's used for the crypto stream and is not included in the counting.
- return;
- }
-
char packet_buffer[kNormalPacketBufferSize];
memset(packet_buffer, 0, sizeof(packet_buffer));
Perspective old_perspective = framer_.perspective();
- // Set up the writer and transmit QuicMaxStreamIdFrame
+ // Set up the writer and transmit QuicMaxStreamsFrame
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
NETWORK_BYTE_ORDER);
- if (stream_id_server_initiated) {
- stream_id |= 0x01;
- }
- if (unidirectional) {
- stream_id |= 0x02;
- }
// 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
@@ -485,7 +477,7 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
QuicFramerPeer::SetPerspective(&framer_, (stream_id_server_initiated)
? Perspective::IS_CLIENT
: Perspective::IS_SERVER);
- QuicMaxStreamIdFrame transmit_frame(0, stream_id);
+ QuicMaxStreamsFrame transmit_frame(0, stream_count, unidirectional);
// Add the frame.
EXPECT_TRUE(QuicFramerPeer::AppendMaxStreamsFrame(&framer_, transmit_frame,
@@ -502,7 +494,7 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
// Set up reader and empty receive QuicPaddingFrame.
QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
- QuicMaxStreamIdFrame receive_frame;
+ QuicMaxStreamsFrame receive_frame;
// Deframe it
EXPECT_TRUE(QuicFramerPeer::ProcessMaxStreamsFrame(
@@ -512,42 +504,30 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
<< " Error: " << framer_.detailed_error();
// Now check that received and sent data are equivalent
- EXPECT_EQ(stream_id, receive_frame.max_stream_id);
- EXPECT_EQ(transmit_frame.max_stream_id, receive_frame.max_stream_id);
+ EXPECT_EQ(stream_count, receive_frame.stream_count);
+ EXPECT_EQ(transmit_frame.stream_count, receive_frame.stream_count);
QuicFramerPeer::SetPerspective(&framer_, old_perspective);
}
- void TryStreamsBlockedFrame(QuicStreamId stream_id,
+ void TryStreamsBlockedFrame(QuicStreamCount stream_count,
bool unidirectional,
bool stream_id_server_initiated) {
- if (!unidirectional && !stream_id_server_initiated && stream_id == 0) {
- // For bidirectional, client initiated, streams, 0 is not allowed,
- // it's used for the crypto stream and is not included in the counting.
- return;
- }
-
char packet_buffer[kNormalPacketBufferSize];
memset(packet_buffer, 0, sizeof(packet_buffer));
Perspective old_perspective = framer_.perspective();
- // Set up the writer and transmit QuicMaxStreamIdFrame
+ // Set up the writer and transmit QuicStreamsBlockedFrame
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
NETWORK_BYTE_ORDER);
- if (stream_id_server_initiated) {
- stream_id |= 0x01;
- }
- if (unidirectional) {
- stream_id |= 0x02;
- }
// 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
+ // be server-initiated, then the sender of the STREAMS_BLOCKED should be
// a client, and vice versa. Do this prior to constructing the frame or
// generating the packet, so that any internal dependencies are satisfied.
QuicFramerPeer::SetPerspective(&framer_, (stream_id_server_initiated)
? Perspective::IS_SERVER
: Perspective::IS_CLIENT);
- QuicStreamIdBlockedFrame transmit_frame(0, stream_id);
+ QuicStreamsBlockedFrame transmit_frame(0, stream_count, unidirectional);
// Add the frame.
EXPECT_TRUE(QuicFramerPeer::AppendStreamsBlockedFrame(
@@ -564,7 +544,7 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
// Set up reader and empty receive QuicPaddingFrame.
QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
- QuicStreamIdBlockedFrame receive_frame;
+ QuicStreamsBlockedFrame receive_frame;
// Deframe it
EXPECT_TRUE(QuicFramerPeer::ProcessStreamsBlockedFrame(
@@ -573,8 +553,8 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
: IETF_STREAMS_BLOCKED_BIDIRECTIONAL));
// Now check that received and sent data are equivalent
- EXPECT_EQ(stream_id, receive_frame.stream_id);
- EXPECT_EQ(transmit_frame.stream_id, receive_frame.stream_id);
+ EXPECT_EQ(stream_count, receive_frame.stream_count);
+ EXPECT_EQ(transmit_frame.stream_count, receive_frame.stream_count);
QuicFramerPeer::SetPerspective(&framer_, old_perspective);
}
@@ -1264,19 +1244,18 @@ TEST_F(QuicIetfFramerTest, MaxStreamDataFrame) {
}
TEST_F(QuicIetfFramerTest, MaxStreamsFrame) {
- QuicIetfStreamId stream_ids[] = {kStreamId4, kStreamId2, kStreamId1,
- kStreamId0};
+ QuicStreamCount stream_counts[] = {0x3fffffff, 0x3fff, 0x3f, 0x1};
- for (QuicIetfStreamId stream_id : stream_ids) {
+ for (QuicStreamCount stream_count : stream_counts) {
// Cover all four combinations of uni/bi-directional and
// server-/client- initiation.
- TryMaxStreamsFrame(stream_id, /*unidirectional=*/true,
+ TryMaxStreamsFrame(stream_count, /*unidirectional=*/true,
/*stream_id_server_initiated=*/true);
- TryMaxStreamsFrame(stream_id, /*unidirectional=*/true,
+ TryMaxStreamsFrame(stream_count, /*unidirectional=*/true,
/*stream_id_server_initiated=*/false);
- TryMaxStreamsFrame(stream_id, /*unidirectional=*/false,
+ TryMaxStreamsFrame(stream_count, /*unidirectional=*/false,
/*stream_id_server_initiated=*/true);
- TryMaxStreamsFrame(stream_id, /*unidirectional=*/false,
+ TryMaxStreamsFrame(stream_count, /*unidirectional=*/false,
/*stream_id_server_initiated=*/false);
}
}
@@ -1362,20 +1341,19 @@ TEST_F(QuicIetfFramerTest, StreamBlockedFrame) {
}
TEST_F(QuicIetfFramerTest, StreamsBlockedFrame) {
- QuicIetfStreamId stream_ids[] = {kStreamId4, kStreamId2, kStreamId1,
- kStreamId0};
+ QuicStreamCount stream_counts[] = {0x3fffffff, 0x3fff, 0x3f, 0x1};
- for (QuicIetfStreamId stream_id : stream_ids) {
- TryStreamsBlockedFrame(stream_id,
+ for (QuicStreamCount stream_count : stream_counts) {
+ TryStreamsBlockedFrame(stream_count,
/*unidirectional=*/false,
/*stream_id_server_initiated=*/false);
- TryStreamsBlockedFrame(stream_id,
+ TryStreamsBlockedFrame(stream_count,
/*unidirectional=*/false,
/*stream_id_server_initiated=*/true);
- TryStreamsBlockedFrame(stream_id,
+ TryStreamsBlockedFrame(stream_count,
/*unidirectional=*/true,
/*stream_id_server_initiated=*/false);
- TryStreamsBlockedFrame(stream_id,
+ TryStreamsBlockedFrame(stream_count,
/*unidirectional=*/true,
/*stream_id_server_initiated=*/true);
}
@@ -1401,7 +1379,7 @@ TEST_F(QuicIetfFramerTest, NewConnectionIdFrame) {
memset(packet_buffer, 0, sizeof(packet_buffer));
- // Set up the writer and transmit QuicStreamIdBlockedFrame
+ // Set up the writer and transmit a QuicNewConnectionIdFrame
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
NETWORK_BYTE_ORDER);
@@ -1449,7 +1427,7 @@ TEST_F(QuicIetfFramerTest, RetireConnectionIdFrame) {
memset(packet_buffer, 0, sizeof(packet_buffer));
- // Set up the writer and transmit QuicStreamIdBlockedFrame
+ // Set up the writer and transmit QuicRetireConnectionIdFrame
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
NETWORK_BYTE_ORDER);
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 96b5bc6e089..7420c723074 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
@@ -22,6 +22,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_ptr_util.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
@@ -52,15 +53,15 @@ QuicLongHeaderType EncryptionlevelToLongHeaderType(EncryptionLevel level) {
#define ENDPOINT \
(framer_->perspective() == Perspective::IS_SERVER ? "Server: " : "Client: ")
-QuicPacketCreator::QuicPacketCreator(QuicConnectionId connection_id,
+QuicPacketCreator::QuicPacketCreator(QuicConnectionId server_connection_id,
QuicFramer* framer,
DelegateInterface* delegate)
- : QuicPacketCreator(connection_id,
+ : QuicPacketCreator(server_connection_id,
framer,
QuicRandom::GetInstance(),
delegate) {}
-QuicPacketCreator::QuicPacketCreator(QuicConnectionId connection_id,
+QuicPacketCreator::QuicPacketCreator(QuicConnectionId server_connection_id,
QuicFramer* framer,
QuicRandom* random,
DelegateInterface* delegate)
@@ -71,9 +72,9 @@ QuicPacketCreator::QuicPacketCreator(QuicConnectionId connection_id,
send_version_in_packet_(framer->perspective() == Perspective::IS_CLIENT),
have_diversification_nonce_(false),
max_packet_length_(0),
- connection_id_included_(CONNECTION_ID_PRESENT),
+ server_connection_id_included_(CONNECTION_ID_PRESENT),
packet_size_(0),
- connection_id_(connection_id),
+ server_connection_id_(server_connection_id),
packet_(QuicPacketNumber(),
PACKET_1BYTE_PACKET_NUMBER,
nullptr,
@@ -82,9 +83,7 @@ QuicPacketCreator::QuicPacketCreator(QuicConnectionId connection_id,
false),
pending_padding_bytes_(0),
needs_full_padding_(false),
- can_set_transmission_type_(false),
- set_transmission_type_for_next_frame_(
- GetQuicReloadableFlag(quic_set_transmission_type_for_next_frame)) {
+ can_set_transmission_type_(false) {
SetMaxPacketLength(kDefaultMaxPacketSize);
}
@@ -114,6 +113,9 @@ void QuicPacketCreator::SetMaxPacketLength(QuicByteCount length) {
max_packet_length_ = length;
max_plaintext_size_ = framer_->GetMaxPlaintextSize(max_packet_length_);
+ QUIC_BUG_IF(max_plaintext_size_ - PacketHeaderSize() <
+ MinPlaintextPacketSize(framer_->version()))
+ << "Attempted to set max packet length too small";
}
// Stops serializing version of the protocol in packets sent after this call.
@@ -159,6 +161,7 @@ void QuicPacketCreator::UpdatePacketNumberLength(
bool QuicPacketCreator::ConsumeCryptoData(EncryptionLevel level,
size_t write_length,
QuicStreamOffset offset,
+ bool needs_full_padding,
TransmissionType transmission_type,
QuicFrame* frame) {
if (!CreateCryptoFrame(level, write_length, offset, frame)) {
@@ -170,7 +173,9 @@ bool QuicPacketCreator::ConsumeCryptoData(EncryptionLevel level,
//
// TODO(nharper): Check what the IETF drafts say about padding out initial
// messages and change this as appropriate.
- needs_full_padding_ = true;
+ if (needs_full_padding) {
+ needs_full_padding_ = true;
+ }
return AddFrame(*frame, /*save_retransmittable_frames*/ true,
transmission_type);
}
@@ -195,8 +200,7 @@ bool QuicPacketCreator::ConsumeData(QuicStreamId id,
QUIC_BUG << error_details << " Constructed stream frame length: "
<< frame->stream_frame.data_length
<< " CHLO length: " << data_size;
- delegate_->OnUnrecoverableError(QUIC_CRYPTO_CHLO_TOO_LARGE, error_details,
- ConnectionCloseSource::FROM_SELF);
+ delegate_->OnUnrecoverableError(QUIC_CRYPTO_CHLO_TOO_LARGE, error_details);
return false;
}
if (!AddFrame(*frame, /*save_retransmittable_frames=*/true,
@@ -379,8 +383,7 @@ void QuicPacketCreator::OnSerializedPacket() {
const std::string error_details = "Failed to SerializePacket.";
QUIC_BUG << error_details;
delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET,
- error_details,
- ConnectionCloseSource::FROM_SELF);
+ error_details);
return;
}
@@ -395,9 +398,7 @@ void QuicPacketCreator::ClearPacket() {
packet_.has_crypto_handshake = NOT_HANDSHAKE;
packet_.num_padding_bytes = 0;
packet_.original_packet_number.Clear();
- if (!can_set_transmission_type_ || ShouldSetTransmissionTypeForNextFrame()) {
- packet_.transmission_type = NOT_RETRANSMISSION;
- }
+ packet_.transmission_type = NOT_RETRANSMISSION;
packet_.encrypted_buffer = nullptr;
packet_.encrypted_length = 0;
DCHECK(packet_.retransmittable_frames.empty());
@@ -442,6 +443,7 @@ void QuicPacketCreator::CreateAndSerializeStreamFrame(
max_plaintext_size_ - writer.length() - min_frame_size;
const size_t bytes_consumed =
std::min<size_t>(available_size, remaining_data_size);
+ const size_t plaintext_bytes_written = min_frame_size + bytes_consumed;
const bool set_fin = fin && (bytes_consumed == remaining_data_size);
QuicStreamFrame frame(id, set_fin, stream_offset, bytes_consumed);
@@ -462,15 +464,19 @@ void QuicPacketCreator::CreateAndSerializeStreamFrame(
QUIC_BUG << "AppendStreamFrame failed";
return;
}
+ if (plaintext_bytes_written < MinPlaintextPacketSize(framer_->version()) &&
+ !writer.WritePaddingBytes(MinPlaintextPacketSize(framer_->version()) -
+ plaintext_bytes_written)) {
+ QUIC_BUG << "Unable to add padding bytes";
+ return;
+ }
if (!framer_->WriteIetfLongHeaderLength(header, &writer, length_field_offset,
packet_.encryption_level)) {
return;
}
- if (ShouldSetTransmissionTypeForNextFrame()) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_set_transmission_type_for_next_frame, 1,
- 2);
+ if (can_set_transmission_type()) {
packet_.transmission_type = transmission_type;
}
@@ -542,11 +548,7 @@ size_t QuicPacketCreator::PacketSize() {
if (!queued_frames_.empty()) {
return packet_size_;
}
- packet_size_ = GetPacketHeaderSize(
- framer_->transport_version(), GetDestinationConnectionIdLength(),
- GetSourceConnectionIdLength(), IncludeVersionInHeader(),
- IncludeNonceInPublicHeader(), GetPacketNumberLength(),
- GetRetryTokenLengthLength(), GetRetryToken().length(), GetLengthLength());
+ packet_size_ = PacketHeaderSize();
return packet_size_;
}
@@ -622,8 +624,9 @@ QuicPacketCreator::SerializeVersionNegotiationPacket(
const ParsedQuicVersionVector& supported_versions) {
DCHECK_EQ(Perspective::IS_SERVER, framer_->perspective());
std::unique_ptr<QuicEncryptedPacket> encrypted =
- QuicFramer::BuildVersionNegotiationPacket(connection_id_, ietf_quic,
- supported_versions);
+ QuicFramer::BuildVersionNegotiationPacket(server_connection_id_,
+ EmptyQuicConnectionId(),
+ ietf_quic, supported_versions);
DCHECK(encrypted);
DCHECK_GE(max_packet_length_, encrypted->length());
return encrypted;
@@ -731,16 +734,39 @@ SerializedPacket QuicPacketCreator::NoPacket() {
nullptr, 0, false, false);
}
+QuicConnectionId QuicPacketCreator::GetDestinationConnectionId() const {
+ if (!GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ return server_connection_id_;
+ }
+ QUIC_RESTART_FLAG_COUNT_N(quic_do_not_override_connection_id, 1, 5);
+ if (framer_->perspective() == Perspective::IS_SERVER) {
+ return EmptyQuicConnectionId();
+ }
+ return server_connection_id_;
+}
+
+QuicConnectionId QuicPacketCreator::GetSourceConnectionId() const {
+ if (!GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ return server_connection_id_;
+ }
+ QUIC_RESTART_FLAG_COUNT_N(quic_do_not_override_connection_id, 6, 6);
+ if (framer_->perspective() == Perspective::IS_CLIENT) {
+ return EmptyQuicConnectionId();
+ }
+ return server_connection_id_;
+}
+
QuicConnectionIdIncluded QuicPacketCreator::GetDestinationConnectionIdIncluded()
const {
- if (framer_->transport_version() > QUIC_VERSION_43) {
+ if (framer_->transport_version() > QUIC_VERSION_43 ||
+ GetQuicRestartFlag(quic_do_not_override_connection_id)) {
// Packets sent by client always include destination connection ID, and
// those sent by the server do not include destination connection ID.
return framer_->perspective() == Perspective::IS_CLIENT
? CONNECTION_ID_PRESENT
: CONNECTION_ID_ABSENT;
}
- return connection_id_included_;
+ return server_connection_id_included_;
}
QuicConnectionIdIncluded QuicPacketCreator::GetSourceConnectionIdIncluded()
@@ -749,23 +775,30 @@ QuicConnectionIdIncluded QuicPacketCreator::GetSourceConnectionIdIncluded()
if (HasIetfLongHeader() && framer_->perspective() == Perspective::IS_SERVER) {
return CONNECTION_ID_PRESENT;
}
+ if (GetQuicRestartFlag(quic_do_not_override_connection_id) &&
+ framer_->perspective() == Perspective::IS_SERVER) {
+ QUIC_RESTART_FLAG_COUNT_N(quic_do_not_override_connection_id, 2, 5);
+ return server_connection_id_included_;
+ }
return CONNECTION_ID_ABSENT;
}
QuicConnectionIdLength QuicPacketCreator::GetDestinationConnectionIdLength()
const {
- DCHECK(QuicUtils::IsConnectionIdValidForVersion(connection_id_,
+ DCHECK(QuicUtils::IsConnectionIdValidForVersion(server_connection_id_,
transport_version()));
return GetDestinationConnectionIdIncluded() == CONNECTION_ID_PRESENT
- ? static_cast<QuicConnectionIdLength>(connection_id_.length())
+ ? static_cast<QuicConnectionIdLength>(
+ GetDestinationConnectionId().length())
: PACKET_0BYTE_CONNECTION_ID;
}
QuicConnectionIdLength QuicPacketCreator::GetSourceConnectionIdLength() const {
- DCHECK(QuicUtils::IsConnectionIdValidForVersion(connection_id_,
+ DCHECK(QuicUtils::IsConnectionIdValidForVersion(server_connection_id_,
transport_version()));
return GetSourceConnectionIdIncluded() == CONNECTION_ID_PRESENT
- ? static_cast<QuicConnectionIdLength>(connection_id_.length())
+ ? static_cast<QuicConnectionIdLength>(
+ GetSourceConnectionId().length())
: PACKET_0BYTE_CONNECTION_ID;
}
@@ -776,6 +809,14 @@ QuicPacketNumberLength QuicPacketCreator::GetPacketNumberLength() const {
return packet_.packet_number_length;
}
+size_t QuicPacketCreator::PacketHeaderSize() const {
+ return GetPacketHeaderSize(
+ framer_->transport_version(), GetDestinationConnectionIdLength(),
+ GetSourceConnectionIdLength(), IncludeVersionInHeader(),
+ IncludeNonceInPublicHeader(), GetPacketNumberLength(),
+ GetRetryTokenLengthLength(), GetRetryToken().length(), GetLengthLength());
+}
+
QuicVariableLengthIntegerLength QuicPacketCreator::GetRetryTokenLengthLength()
const {
if (QuicVersionHasLongHeaderLengths(framer_->transport_version()) &&
@@ -787,7 +828,12 @@ QuicVariableLengthIntegerLength QuicPacketCreator::GetRetryTokenLengthLength()
}
QuicStringPiece QuicPacketCreator::GetRetryToken() const {
- return retry_token_;
+ if (QuicVersionHasLongHeaderLengths(framer_->transport_version()) &&
+ HasIetfLongHeader() &&
+ EncryptionlevelToLongHeaderType(packet_.encryption_level) == INITIAL) {
+ return retry_token_;
+ }
+ return QuicStringPiece();
}
void QuicPacketCreator::SetRetryToken(QuicStringPiece retry_token) {
@@ -808,10 +854,10 @@ QuicVariableLengthIntegerLength QuicPacketCreator::GetLengthLength() const {
}
void QuicPacketCreator::FillPacketHeader(QuicPacketHeader* header) {
- header->destination_connection_id = connection_id_;
+ header->destination_connection_id = GetDestinationConnectionId();
header->destination_connection_id_included =
GetDestinationConnectionIdIncluded();
- header->source_connection_id = connection_id_;
+ header->source_connection_id = GetSourceConnectionId();
header->source_connection_id_included = GetSourceConnectionIdIncluded();
header->reset_flag = false;
header->version_flag = IncludeVersionInHeader();
@@ -821,11 +867,7 @@ void QuicPacketCreator::FillPacketHeader(QuicPacketHeader* header) {
} else {
header->nonce = nullptr;
}
- if (!packet_.packet_number.IsInitialized()) {
- packet_.packet_number = framer_->first_sending_packet_number();
- } else {
- ++packet_.packet_number;
- }
+ packet_.packet_number = NextSendingPacketNumber();
header->packet_number = packet_.packet_number;
header->packet_number_length = GetPacketNumberLength();
header->retry_token_length_length = GetRetryTokenLengthLength();
@@ -845,15 +887,16 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
QUIC_DVLOG(1) << ENDPOINT << "Adding frame with transmission type "
<< transmission_type << ": " << frame;
if (frame.type == STREAM_FRAME &&
- frame.stream_frame.stream_id !=
- QuicUtils::GetCryptoStreamId(framer_->transport_version()) &&
- packet_.encryption_level == ENCRYPTION_INITIAL) {
- const std::string error_details =
- "Cannot send stream data without encryption.";
+ !QuicUtils::IsCryptoStreamId(framer_->transport_version(),
+ frame.stream_frame.stream_id) &&
+ (packet_.encryption_level == ENCRYPTION_INITIAL ||
+ packet_.encryption_level == ENCRYPTION_HANDSHAKE)) {
+ const std::string error_details = QuicStrCat(
+ "Cannot send stream data with level: ",
+ QuicUtils::EncryptionLevelToString(packet_.encryption_level));
QUIC_BUG << error_details;
delegate_->OnUnrecoverableError(
- QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA, error_details,
- ConnectionCloseSource::FROM_SELF);
+ QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA, error_details);
return false;
}
size_t frame_len = framer_->GetSerializedFrameLength(
@@ -892,10 +935,8 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
// Packet transmission type is determined by the last added retransmittable
// frame.
- if (ShouldSetTransmissionTypeForNextFrame() &&
+ if (can_set_transmission_type() &&
QuicUtils::IsRetransmittableFrame(frame.type)) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_set_transmission_type_for_next_frame, 2,
- 2);
packet_.transmission_type = transmission_type;
}
return true;
@@ -914,11 +955,26 @@ void QuicPacketCreator::MaybeAddPadding() {
needs_full_padding_ = true;
}
- if (!needs_full_padding_ && pending_padding_bytes_ == 0) {
+ // Header protection requires a minimum plaintext packet size.
+ size_t extra_padding_bytes = 0;
+ if (framer_->version().HasHeaderProtection()) {
+ size_t frame_bytes = PacketSize() - PacketHeaderSize();
+
+ if (frame_bytes + pending_padding_bytes_ <
+ MinPlaintextPacketSize(framer_->version()) &&
+ !needs_full_padding_) {
+ extra_padding_bytes =
+ MinPlaintextPacketSize(framer_->version()) - frame_bytes;
+ }
+ }
+
+ if (!needs_full_padding_ && pending_padding_bytes_ == 0 &&
+ extra_padding_bytes == 0) {
// Do not need padding.
return;
}
+ int padding_bytes = -1;
if (needs_full_padding_) {
// Full padding does not consume pending padding bytes.
packet_.num_padding_bytes = -1;
@@ -926,11 +982,12 @@ void QuicPacketCreator::MaybeAddPadding() {
packet_.num_padding_bytes =
std::min<int16_t>(pending_padding_bytes_, BytesFree());
pending_padding_bytes_ -= packet_.num_padding_bytes;
+ padding_bytes =
+ std::max<int16_t>(packet_.num_padding_bytes, extra_padding_bytes);
}
- bool success =
- AddFrame(QuicFrame(QuicPaddingFrame(packet_.num_padding_bytes)), false,
- packet_.transmission_type);
+ bool success = AddFrame(QuicFrame(QuicPaddingFrame(padding_bytes)), false,
+ packet_.transmission_type);
DCHECK(success);
}
@@ -953,31 +1010,32 @@ void QuicPacketCreator::AddPendingPadding(QuicByteCount size) {
bool QuicPacketCreator::StreamFrameIsClientHello(
const QuicStreamFrame& frame) const {
if (framer_->perspective() == Perspective::IS_SERVER ||
- frame.stream_id !=
- QuicUtils::GetCryptoStreamId(framer_->transport_version())) {
+ !QuicUtils::IsCryptoStreamId(framer_->transport_version(),
+ frame.stream_id)) {
return false;
}
// The ClientHello is always sent with INITIAL encryption.
return packet_.encryption_level == ENCRYPTION_INITIAL;
}
-void QuicPacketCreator::SetConnectionIdIncluded(
- QuicConnectionIdIncluded connection_id_included) {
- DCHECK(connection_id_included == CONNECTION_ID_PRESENT ||
- connection_id_included == CONNECTION_ID_ABSENT);
+void QuicPacketCreator::SetServerConnectionIdIncluded(
+ QuicConnectionIdIncluded server_connection_id_included) {
+ DCHECK(server_connection_id_included == CONNECTION_ID_PRESENT ||
+ server_connection_id_included == CONNECTION_ID_ABSENT);
DCHECK(framer_->perspective() == Perspective::IS_SERVER ||
- connection_id_included != CONNECTION_ID_ABSENT);
- connection_id_included_ = connection_id_included;
+ server_connection_id_included != CONNECTION_ID_ABSENT);
+ server_connection_id_included_ = server_connection_id_included;
}
-void QuicPacketCreator::SetConnectionId(QuicConnectionId connection_id) {
- connection_id_ = connection_id;
+void QuicPacketCreator::SetServerConnectionId(
+ QuicConnectionId server_connection_id) {
+ server_connection_id_ = server_connection_id;
}
void QuicPacketCreator::SetTransmissionType(TransmissionType type) {
DCHECK(can_set_transmission_type_);
- if (!ShouldSetTransmissionTypeForNextFrame()) {
+ if (!can_set_transmission_type()) {
QUIC_DVLOG_IF(1, type != packet_.transmission_type)
<< ENDPOINT << "Setting Transmission type to "
<< QuicUtils::TransmissionTypeToString(type);
@@ -1037,5 +1095,39 @@ bool QuicPacketCreator::HasIetfLongHeader() const {
packet_.encryption_level < ENCRYPTION_FORWARD_SECURE;
}
+size_t QuicPacketCreator::MinPlaintextPacketSize(
+ const ParsedQuicVersion& version) {
+ if (!version.HasHeaderProtection()) {
+ return 0;
+ }
+ // Header protection samples 16 bytes of ciphertext starting 4 bytes after the
+ // packet number. In IETF QUIC, all AEAD algorithms have a 16-byte auth tag
+ // (i.e. the ciphertext is 16 bytes larger than the plaintext). Since packet
+ // numbers could be as small as 1 byte, but the sample starts 4 bytes after
+ // the packet number, at least 3 bytes of plaintext are needed to make sure
+ // that there is enough ciphertext to sample.
+ //
+ // Google QUIC crypto uses different AEAD algorithms - in particular the auth
+ // tags are only 12 bytes instead of 16 bytes. Since the auth tag is 4 bytes
+ // shorter, 4 more bytes of plaintext are needed to guarantee there is enough
+ // ciphertext to sample.
+ //
+ // This method could check for PROTOCOL_TLS1_3 vs PROTOCOL_QUIC_CRYPTO and
+ // return 3 when TLS 1.3 is in use (the use of IETF vs Google QUIC crypters is
+ // determined based on the handshake protocol used). However, even when TLS
+ // 1.3 is used, unittests still use NullEncrypter/NullDecrypter (and other
+ // test crypters) which also only use 12 byte tags.
+ //
+ // TODO(nharper): Set this based on the handshake protocol in use.
+ return 7;
+}
+
+QuicPacketNumber QuicPacketCreator::NextSendingPacketNumber() const {
+ if (!packet_number().IsInitialized()) {
+ return framer_->first_sending_packet_number();
+ }
+ return packet_number() + 1;
+}
+
#undef ENDPOINT // undef for jumbo builds
} // namespace quic
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 85e00917a15..a7b1d5cb3e3 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
@@ -13,7 +13,6 @@
#include <utility>
#include <vector>
-#include "net/third_party/quiche/src/quic/core/quic_connection_close_delegate_interface.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"
@@ -28,10 +27,9 @@ class QuicPacketCreatorPeer;
class QUIC_EXPORT_PRIVATE QuicPacketCreator {
public:
// A delegate interface for further processing serialized packet.
- class QUIC_EXPORT_PRIVATE DelegateInterface
- : public QuicConnectionCloseDelegateInterface {
+ class QUIC_EXPORT_PRIVATE DelegateInterface {
public:
- ~DelegateInterface() override {}
+ virtual ~DelegateInterface() {}
// Get a buffer of kMaxOutgoingPacketSize bytes to serialize the next
// packet. If return nullptr, QuicPacketCreator will serialize on a stack
// buffer.
@@ -40,6 +38,10 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// of |serialized_packet|, but takes ownership of any frames it removes
// from |packet.retransmittable_frames|.
virtual void OnSerializedPacket(SerializedPacket* serialized_packet) = 0;
+
+ // Called when an unrecoverable error is encountered.
+ virtual void OnUnrecoverableError(QuicErrorCode error,
+ const std::string& error_details) = 0;
};
// Interface which gets callbacks from the QuicPacketCreator at interesting
@@ -53,10 +55,10 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
virtual void OnFrameAddedToPacket(const QuicFrame& frame) {}
};
- QuicPacketCreator(QuicConnectionId connection_id,
+ QuicPacketCreator(QuicConnectionId server_connection_id,
QuicFramer* framer,
DelegateInterface* delegate);
- QuicPacketCreator(QuicConnectionId connection_id,
+ QuicPacketCreator(QuicConnectionId server_connection_id,
QuicFramer* framer,
QuicRandom* random,
DelegateInterface* delegate);
@@ -109,6 +111,7 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
bool ConsumeCryptoData(EncryptionLevel level,
size_t write_length,
QuicStreamOffset offset,
+ bool needs_full_padding,
TransmissionType transmission_type,
QuicFrame* frame);
@@ -206,17 +209,24 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// Returns a dummy packet that is valid but contains no useful information.
static SerializedPacket NoPacket();
+ // Returns the destination connection ID to send over the wire.
+ QuicConnectionId GetDestinationConnectionId() const;
+
+ // Returns the source connection ID to send over the wire.
+ QuicConnectionId GetSourceConnectionId() const;
+
// Returns length of destination connection ID to send over the wire.
QuicConnectionIdLength GetDestinationConnectionIdLength() const;
// Returns length of source connection ID to send over the wire.
QuicConnectionIdLength GetSourceConnectionIdLength() const;
- // Sets whether the connection ID should be sent over the wire.
- void SetConnectionIdIncluded(QuicConnectionIdIncluded connection_id_included);
+ // Sets whether the server connection ID should be sent over the wire.
+ void SetServerConnectionIdIncluded(
+ QuicConnectionIdIncluded server_connection_id_included);
- // Update the connection ID used in outgoing packets.
- void SetConnectionId(QuicConnectionId connection_id);
+ // Update the server connection ID used in outgoing packets.
+ void SetServerConnectionId(QuicConnectionId server_connection_id);
// Sets the encryption level that will be applied to new packets.
void set_encryption_level(EncryptionLevel level) {
@@ -252,7 +262,7 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// Sets transmission type of next constructed packets.
void SetTransmissionType(TransmissionType type);
- // Sets the retry token to be sent over the wire in v99 IETF Initial packets.
+ // Sets the retry token to be sent over the wire in IETF Initial packets.
void SetRetryToken(QuicStringPiece retry_token);
// Returns the largest payload that will fit into a single MESSAGE frame.
@@ -262,6 +272,9 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// connection ID lengths do not change.
QuicPacketLength GetGuaranteedLargestMessagePayload() const;
+ // Packet number of next created packet.
+ QuicPacketNumber NextSendingPacketNumber() const;
+
void set_debug_delegate(DebugDelegate* debug_delegate) {
debug_delegate_ = debug_delegate;
}
@@ -270,9 +283,7 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
can_set_transmission_type_ = can_set_transmission_type;
}
- bool ShouldSetTransmissionTypeForNextFrame() const {
- return can_set_transmission_type_ && set_transmission_type_for_next_frame_;
- }
+ bool can_set_transmission_type() const { return can_set_transmission_type_; }
QuicByteCount pending_padding_bytes() const { return pending_padding_bytes_; }
@@ -280,6 +291,9 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
return framer_->transport_version();
}
+ // Returns the minimum size that the plaintext of a packet must be.
+ static size_t MinPlaintextPacketSize(const ParsedQuicVersion& version);
+
private:
friend class test::QuicPacketCreatorPeer;
@@ -338,6 +352,9 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// function instead.
QuicPacketNumberLength GetPacketNumberLength() const;
+ // Returns the size in bytes of the packet header.
+ size_t PacketHeaderSize() const;
+
// Returns whether the destination connection ID is sent over the wire.
QuicConnectionIdIncluded GetDestinationConnectionIdIncluded() const;
@@ -379,8 +396,8 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// Maximum length including headers and encryption (UDP payload length.)
QuicByteCount max_packet_length_;
size_t max_plaintext_size_;
- // Whether the connection_id is sent over the wire.
- QuicConnectionIdIncluded connection_id_included_;
+ // Whether the server_connection_id is sent over the wire.
+ QuicConnectionIdIncluded server_connection_id_included_;
// Frames to be added to the next SerializedPacket
QuicFrames queued_frames_;
@@ -389,7 +406,7 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// TODO(ianswett): Move packet_size_ into SerializedPacket once
// QuicEncryptedPacket has been flattened into SerializedPacket.
size_t packet_size_;
- QuicConnectionId connection_id_;
+ QuicConnectionId server_connection_id_;
// Packet used to invoke OnSerializedPacket.
SerializedPacket packet_;
@@ -410,10 +427,6 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// If true, packet_'s transmission type is only set by
// SetPacketTransmissionType and does not get cleared in ClearPacket.
bool can_set_transmission_type_;
-
- // Latched value of --quic_set_transmission_type_for_next_frame. Don't use
- // this variable directly, use ShouldSetTransmissionTypeForNextFrame instead.
- bool set_transmission_type_for_next_frame_;
};
} // 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 2b71b06e684..bf695637322 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
@@ -295,7 +295,7 @@ TEST_P(QuicPacketCreatorTest, SerializeFrames) {
frames_.push_back(QuicFrame(new QuicAckFrame(InitAckFrame(1))));
QuicStreamId stream_id = QuicUtils::GetFirstBidirectionalStreamId(
client_framer_.transport_version(), Perspective::IS_CLIENT);
- if (level != ENCRYPTION_INITIAL) {
+ if (level != ENCRYPTION_INITIAL && level != ENCRYPTION_HANDSHAKE) {
frames_.push_back(
QuicFrame(QuicStreamFrame(stream_id, false, 0u, QuicStringPiece())));
frames_.push_back(
@@ -320,7 +320,7 @@ TEST_P(QuicPacketCreatorTest, SerializeFrames) {
.WillOnce(Return(true));
EXPECT_CALL(framer_visitor_, OnAckFrameEnd(QuicPacketNumber(1)))
.WillOnce(Return(true));
- if (level != ENCRYPTION_INITIAL) {
+ if (level != ENCRYPTION_INITIAL && level != ENCRYPTION_HANDSHAKE) {
EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
}
@@ -601,6 +601,7 @@ TEST_P(QuicPacketCreatorTest, ConsumeCryptoData) {
std::string data = "crypto data";
QuicFrame frame;
ASSERT_TRUE(creator_.ConsumeCryptoData(ENCRYPTION_INITIAL, data.length(), 0,
+ /*needs_full_padding=*/true,
NOT_RETRANSMISSION, &frame));
EXPECT_EQ(frame.crypto_frame->data_length, data.length());
EXPECT_TRUE(creator_.HasPendingFrames());
@@ -652,7 +653,10 @@ TEST_P(QuicPacketCreatorTest, CreateAllFreeBytesForStreamFrames) {
const size_t overhead =
GetPacketHeaderOverhead(client_framer_.transport_version()) +
GetEncryptionOverhead();
- for (size_t i = overhead; i < overhead + 100; ++i) {
+ for (size_t i = overhead + QuicPacketCreator::MinPlaintextPacketSize(
+ client_framer_.version());
+ i < overhead + 100; ++i) {
+ SCOPED_TRACE(i);
creator_.SetMaxPacketLength(i);
const bool should_have_room =
i >
@@ -743,9 +747,9 @@ TEST_P(QuicPacketCreatorTest, CryptoStreamFramePacketPadding) {
EXPECT_LT(0u, bytes_consumed);
} else {
producer_.SaveCryptoData(ENCRYPTION_INITIAL, kOffset, data);
- ASSERT_TRUE(creator_.ConsumeCryptoData(ENCRYPTION_INITIAL, data.length(),
- kOffset, NOT_RETRANSMISSION,
- &frame));
+ ASSERT_TRUE(creator_.ConsumeCryptoData(
+ 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);
}
@@ -1176,6 +1180,44 @@ TEST_P(QuicPacketCreatorTest, SerializeFrame) {
if (!GetParam().version_serialization) {
creator_.StopSendingVersion();
}
+ std::string data("test data");
+ 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())));
+ }
+ SerializedPacket serialized = SerializeAllFrames(frames_);
+
+ QuicPacketHeader header;
+ {
+ 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(_))
+ .WillOnce(DoAll(SaveArg<0>(&header), Return(true)));
+ if (QuicVersionUsesCryptoFrames(client_framer_.transport_version())) {
+ EXPECT_CALL(framer_visitor_, OnCryptoFrame(_));
+ } else {
+ EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
+ }
+ EXPECT_CALL(framer_visitor_, OnPacketComplete());
+ }
+ ProcessPacket(serialized);
+ EXPECT_EQ(GetParam().version_serialization, header.version_flag);
+ DeleteFrames(&frames_);
+}
+
+TEST_P(QuicPacketCreatorTest, SerializeFrameShortData) {
+ if (!GetParam().version_serialization) {
+ creator_.StopSendingVersion();
+ }
std::string data("a");
if (!QuicVersionUsesCryptoFrames(client_framer_.transport_version())) {
QuicStreamFrame stream_frame(
@@ -1203,6 +1245,9 @@ TEST_P(QuicPacketCreatorTest, SerializeFrame) {
} else {
EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
}
+ if (client_framer_.version().HasHeaderProtection()) {
+ EXPECT_CALL(framer_visitor_, OnPaddingFrame(_));
+ }
EXPECT_CALL(framer_visitor_, OnPacketComplete());
}
ProcessPacket(serialized);
@@ -1240,8 +1285,14 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndFlush) {
const size_t max_plaintext_size =
client_framer_.GetMaxPlaintextSize(creator_.max_packet_length());
EXPECT_FALSE(creator_.HasPendingFrames());
- EXPECT_FALSE(creator_.HasPendingStreamFramesOfStream(
- QuicUtils::GetCryptoStreamId(client_framer_.transport_version())));
+ creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
+ 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());
+ }
+ EXPECT_FALSE(creator_.HasPendingStreamFramesOfStream(stream_id));
EXPECT_EQ(max_plaintext_size -
GetPacketHeaderSize(
client_framer_.transport_version(),
@@ -1262,20 +1313,17 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndFlush) {
EXPECT_TRUE(
creator_.AddSavedFrame(QuicFrame(&ack_frame), NOT_RETRANSMISSION));
EXPECT_TRUE(creator_.HasPendingFrames());
- EXPECT_FALSE(creator_.HasPendingStreamFramesOfStream(
- QuicUtils::GetCryptoStreamId(client_framer_.transport_version())));
+ EXPECT_FALSE(creator_.HasPendingStreamFramesOfStream(stream_id));
QuicFrame frame;
MakeIOVector("test", &iov_);
EXPECT_CALL(debug, OnFrameAddedToPacket(_));
- ASSERT_TRUE(creator_.ConsumeData(
- QuicUtils::GetCryptoStreamId(client_framer_.transport_version()), &iov_,
- 1u, iov_.iov_len, 0u, 0u, false, false, NOT_RETRANSMISSION, &frame));
+ ASSERT_TRUE(creator_.ConsumeData(stream_id, &iov_, 1u, iov_.iov_len, 0u, 0u,
+ false, false, NOT_RETRANSMISSION, &frame));
size_t consumed = frame.stream_frame.data_length;
EXPECT_EQ(4u, consumed);
EXPECT_TRUE(creator_.HasPendingFrames());
- EXPECT_TRUE(creator_.HasPendingStreamFramesOfStream(
- QuicUtils::GetCryptoStreamId(client_framer_.transport_version())));
+ EXPECT_TRUE(creator_.HasPendingStreamFramesOfStream(stream_id));
QuicPaddingFrame padding_frame;
EXPECT_CALL(debug, OnFrameAddedToPacket(_));
@@ -1301,8 +1349,7 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndFlush) {
DeleteSerializedPacket();
EXPECT_FALSE(creator_.HasPendingFrames());
- EXPECT_FALSE(creator_.HasPendingStreamFramesOfStream(
- QuicUtils::GetCryptoStreamId(client_framer_.transport_version())));
+ EXPECT_FALSE(creator_.HasPendingStreamFramesOfStream(stream_id));
EXPECT_EQ(max_plaintext_size -
GetPacketHeaderSize(
client_framer_.transport_version(),
@@ -1355,13 +1402,29 @@ TEST_P(QuicPacketCreatorTest, AddUnencryptedStreamDataClosesConnection) {
}
creator_.set_encryption_level(ENCRYPTION_INITIAL);
- EXPECT_CALL(delegate_, OnUnrecoverableError(_, _, _));
+ EXPECT_CALL(delegate_, OnUnrecoverableError(_, _));
QuicStreamFrame stream_frame(
QuicUtils::GetHeadersStreamId(client_framer_.transport_version()),
/*fin=*/false, 0u, QuicStringPiece());
EXPECT_QUIC_BUG(
creator_.AddSavedFrame(QuicFrame(stream_frame), NOT_RETRANSMISSION),
- "Cannot send stream data without encryption.");
+ "Cannot send stream data with level: ENCRYPTION_INITIAL");
+}
+
+TEST_P(QuicPacketCreatorTest, SendStreamDataWithEncryptionHandshake) {
+ // EXPECT_QUIC_BUG tests are expensive so only run one instance of them.
+ if (!IsDefaultTestConfiguration()) {
+ return;
+ }
+
+ creator_.set_encryption_level(ENCRYPTION_HANDSHAKE);
+ EXPECT_CALL(delegate_, OnUnrecoverableError(_, _));
+ QuicStreamFrame stream_frame(
+ QuicUtils::GetHeadersStreamId(client_framer_.transport_version()),
+ /*fin=*/false, 0u, QuicStringPiece());
+ EXPECT_QUIC_BUG(
+ creator_.AddSavedFrame(QuicFrame(stream_frame), NOT_RETRANSMISSION),
+ "Cannot send stream data with level: ENCRYPTION_HANDSHAKE");
}
TEST_P(QuicPacketCreatorTest, ChloTooLarge) {
@@ -1388,8 +1451,7 @@ TEST_P(QuicPacketCreatorTest, ChloTooLarge) {
MakeIOVector(QuicStringPiece(message_data->data(), message_data->length()),
&iov);
QuicFrame frame;
- EXPECT_CALL(delegate_,
- OnUnrecoverableError(QUIC_CRYPTO_CHLO_TOO_LARGE, _, _));
+ EXPECT_CALL(delegate_, OnUnrecoverableError(QUIC_CRYPTO_CHLO_TOO_LARGE, _));
EXPECT_QUIC_BUG(creator_.ConsumeData(QuicUtils::GetCryptoStreamId(
client_framer_.transport_version()),
&iov, 1u, iov.iov_len, 0u, 0u, false,
@@ -1738,7 +1800,7 @@ TEST_P(QuicPacketCreatorTest, PacketTransmissionType) {
creator_.Flush();
ASSERT_TRUE(serialized_packet_.encrypted_buffer);
- if (creator_.ShouldSetTransmissionTypeForNextFrame()) {
+ 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);
@@ -1787,6 +1849,9 @@ TEST_P(QuicPacketCreatorTest, RetryToken) {
} else {
EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
}
+ if (client_framer_.version().HasHeaderProtection()) {
+ EXPECT_CALL(framer_visitor_, OnPaddingFrame(_));
+ }
EXPECT_CALL(framer_visitor_, OnPacketComplete());
}
ProcessPacket(serialized);
@@ -1799,6 +1864,16 @@ TEST_P(QuicPacketCreatorTest, RetryToken) {
DeleteFrames(&frames_);
}
+TEST_P(QuicPacketCreatorTest, GetConnectionId) {
+ if (!GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ EXPECT_EQ(TestConnectionId(2), creator_.GetDestinationConnectionId());
+ EXPECT_EQ(TestConnectionId(2), creator_.GetSourceConnectionId());
+ return;
+ }
+ EXPECT_EQ(TestConnectionId(2), creator_.GetDestinationConnectionId());
+ EXPECT_EQ(EmptyQuicConnectionId(), 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
index 6efadcf12c6..d57aad41f47 100644
--- 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
@@ -14,15 +14,16 @@
#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 connection_id,
+QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId server_connection_id,
QuicFramer* framer,
QuicRandom* random_generator,
DelegateInterface* delegate)
: delegate_(delegate),
- packet_creator_(connection_id, framer, random_generator, delegate),
+ packet_creator_(server_connection_id, framer, random_generator, delegate),
next_transmission_type_(NOT_RETRANSMISSION),
flusher_attached_(false),
should_send_ack_(false),
@@ -30,7 +31,10 @@ QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id,
random_generator_(random_generator),
fully_pad_crypto_handshake_packets_(true),
deprecate_ack_bundling_mode_(
- GetQuicReloadableFlag(quic_deprecate_ack_bundling_mode)) {}
+ GetQuicReloadableFlag(quic_deprecate_ack_bundling_mode)),
+ deprecate_queued_control_frames_(
+ deprecate_ack_bundling_mode_ &&
+ GetQuicReloadableFlag(quic_deprecate_queued_control_frames)) {}
QuicPacketGenerator::~QuicPacketGenerator() {
DeleteFrames(&queued_control_frames_);
@@ -53,14 +57,37 @@ void QuicPacketGenerator::SetShouldSendAck(bool also_send_stop_waiting) {
SendQueuedFrames(/*flush=*/false);
}
-void QuicPacketGenerator::AddControlFrame(const QuicFrame& frame) {
+bool QuicPacketGenerator::ConsumeRetransmittableControlFrame(
+ const QuicFrame& 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;
if (deprecate_ack_bundling_mode_) {
MaybeBundleAckOpportunistically();
}
+ if (deprecate_queued_control_frames_) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_deprecate_queued_control_frames);
+ 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;
+ }
queued_control_frames_.push_back(frame);
SendQueuedFrames(/*flush=*/false);
+ return true;
}
size_t QuicPacketGenerator::ConsumeCryptoData(EncryptionLevel level,
@@ -85,7 +112,8 @@ size_t QuicPacketGenerator::ConsumeCryptoData(EncryptionLevel level,
QuicFrame frame;
if (!packet_creator_.ConsumeCryptoData(
level, write_length - total_bytes_consumed,
- offset + total_bytes_consumed, next_transmission_type_, &frame)) {
+ 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.
@@ -111,7 +139,7 @@ QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id,
QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
"generator tries to write stream data.";
bool has_handshake =
- (id == QuicUtils::GetCryptoStreamId(packet_creator_.transport_version()));
+ QuicUtils::IsCryptoStreamId(packet_creator_.transport_version(), id);
if (deprecate_ack_bundling_mode_) {
MaybeBundleAckOpportunistically();
}
@@ -201,8 +229,7 @@ QuicConsumedData QuicPacketGenerator::ConsumeDataFastPath(
QuicStreamOffset offset,
bool fin,
size_t total_bytes_consumed) {
- DCHECK_NE(id,
- QuicUtils::GetCryptoStreamId(packet_creator_.transport_version()));
+ DCHECK(!QuicUtils::IsCryptoStreamId(packet_creator_.transport_version(), id));
while (total_bytes_consumed < write_length &&
delegate_->ShouldGeneratePacket(HAS_RETRANSMITTABLE_DATA,
@@ -275,8 +302,7 @@ void QuicPacketGenerator::SendQueuedFrames(bool flush) {
QUIC_LOG(INFO) << queued_control_frames_[0];
}
delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET,
- "Single frame cannot fit into a packet",
- ConnectionCloseSource::FROM_SELF);
+ "Single frame cannot fit into a packet");
return;
}
}
@@ -291,6 +317,9 @@ bool QuicPacketGenerator::PacketFlusherAttached() const {
void QuicPacketGenerator::AttachPacketFlusher() {
flusher_attached_ = true;
+ if (!write_start_packet_number_.IsInitialized()) {
+ write_start_packet_number_ = packet_creator_.NextSendingPacketNumber();
+ }
}
void QuicPacketGenerator::Flush() {
@@ -298,6 +327,17 @@ void QuicPacketGenerator::Flush() {
packet_creator_.Flush();
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() {
@@ -412,11 +452,11 @@ void QuicPacketGenerator::UpdatePacketNumberLength(
max_packets_in_flight);
}
-void QuicPacketGenerator::SetConnectionIdLength(uint32_t length) {
+void QuicPacketGenerator::SetServerConnectionIdLength(uint32_t length) {
if (length == 0) {
- packet_creator_.SetConnectionIdIncluded(CONNECTION_ID_ABSENT);
+ packet_creator_.SetServerConnectionIdIncluded(CONNECTION_ID_ABSENT);
} else {
- packet_creator_.SetConnectionIdIncluded(CONNECTION_ID_PRESENT);
+ packet_creator_.SetServerConnectionIdIncluded(CONNECTION_ID_PRESENT);
}
}
@@ -454,11 +494,15 @@ bool QuicPacketGenerator::HasPendingStreamFramesOfStream(
void QuicPacketGenerator::SetTransmissionType(TransmissionType type) {
packet_creator_.SetTransmissionType(type);
- if (packet_creator_.ShouldSetTransmissionTypeForNextFrame()) {
+ 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);
@@ -539,8 +583,9 @@ QuicPacketLength QuicPacketGenerator::GetGuaranteedLargestMessagePayload()
return packet_creator_.GetGuaranteedLargestMessagePayload();
}
-void QuicPacketGenerator::SetConnectionId(QuicConnectionId connection_id) {
- packet_creator_.SetConnectionId(connection_id);
+void QuicPacketGenerator::SetServerConnectionId(
+ QuicConnectionId server_connection_id) {
+ packet_creator_.SetServerConnectionId(server_connection_id);
}
} // 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
index dc191a0eba2..327cc47238b 100644
--- 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
@@ -76,7 +76,7 @@ class QUIC_EXPORT_PRIVATE QuicPacketGenerator {
QuicStopWaitingFrame* stop_waiting) = 0;
};
- QuicPacketGenerator(QuicConnectionId connection_id,
+ QuicPacketGenerator(QuicConnectionId server_connection_id,
QuicFramer* framer,
QuicRandom* random_generator,
DelegateInterface* delegate);
@@ -92,7 +92,9 @@ class QUIC_EXPORT_PRIVATE QuicPacketGenerator {
// CreateAckFrame() when the packet is serialized.
void SetShouldSendAck(bool also_send_stop_waiting);
- void AddControlFrame(const QuicFrame& frame);
+ // 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
@@ -183,8 +185,8 @@ class QUIC_EXPORT_PRIVATE QuicPacketGenerator {
void UpdatePacketNumberLength(QuicPacketNumber least_packet_awaited_by_peer,
QuicPacketCount max_packets_in_flight);
- // Set the minimum number of bytes for the connection id length;
- void SetConnectionIdLength(uint32_t length);
+ // 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,
@@ -215,6 +217,9 @@ class QUIC_EXPORT_PRIVATE QuicPacketGenerator {
// 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);
@@ -230,8 +235,8 @@ class QUIC_EXPORT_PRIVATE QuicPacketGenerator {
QuicPacketLength GetCurrentLargestMessagePayload() const;
QuicPacketLength GetGuaranteedLargestMessagePayload() const;
- // Update the connection ID used in outgoing packets.
- void SetConnectionId(QuicConnectionId connection_id);
+ // Update the server connection ID used in outgoing packets.
+ void SetServerConnectionId(QuicConnectionId server_connection_id);
void set_debug_delegate(QuicPacketCreator::DebugDelegate* debug_delegate) {
packet_creator_.set_debug_delegate(debug_delegate);
@@ -251,6 +256,10 @@ class QUIC_EXPORT_PRIVATE QuicPacketGenerator {
return deprecate_ack_bundling_mode_;
}
+ bool deprecate_queued_control_frames() const {
+ return deprecate_queued_control_frames_;
+ }
+
private:
friend class test::QuicPacketGeneratorPeer;
@@ -281,6 +290,8 @@ class QUIC_EXPORT_PRIVATE QuicPacketGenerator {
DelegateInterface* delegate_;
QuicPacketCreator packet_creator_;
+ // TODO(fayang): remove this when deprecating
+ // quic_deprecate_queued_control_frames.
QuicFrames queued_control_frames_;
// Transmission type of the next serialized packet.
@@ -307,8 +318,16 @@ class QUIC_EXPORT_PRIVATE QuicPacketGenerator {
// 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_;
+
// Latched value of quic_deprecate_ack_bundling_mode.
const bool deprecate_ack_bundling_mode_;
+
+ // Latched value of quic_deprecate_queued_control_frames.
+ const bool deprecate_queued_control_frames_;
};
} // namespace quic
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
index 1e12424743e..7212e22f76a 100644
--- 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
@@ -51,8 +51,7 @@ class MockDelegate : public QuicPacketGenerator::DelegateInterface {
MOCK_METHOD1(PopulateStopWaitingFrame, void(QuicStopWaitingFrame*));
MOCK_METHOD0(GetPacketBuffer, char*());
MOCK_METHOD1(OnSerializedPacket, void(SerializedPacket* packet));
- MOCK_METHOD3(OnUnrecoverableError,
- void(QuicErrorCode, const std::string&, ConnectionCloseSource));
+ MOCK_METHOD2(OnUnrecoverableError, void(QuicErrorCode, const std::string&));
void SetCanWriteAnything() {
EXPECT_CALL(*this, ShouldGeneratePacket(_, _)).WillRepeatedly(Return(true));
@@ -118,7 +117,8 @@ class TestPacketGenerator : public QuicPacketGenerator {
delegate_(static_cast<MockDelegate*>(delegate)),
producer_(producer) {}
- void AddControlFrame(const QuicFrame& frame, bool bundle_ack) {
+ bool ConsumeRetransmittableControlFrame(const QuicFrame& frame,
+ bool bundle_ack) {
if (GetQuicReloadableFlag(quic_deprecate_ack_bundling_mode) &&
!QuicPacketGeneratorPeer::GetPacketCreator(this)->has_ack()) {
QuicFrames frames;
@@ -131,7 +131,7 @@ class TestPacketGenerator : public QuicPacketGenerator {
.WillOnce(Return(frames));
}
}
- QuicPacketGenerator::AddControlFrame(frame);
+ return QuicPacketGenerator::ConsumeRetransmittableControlFrame(frame);
}
QuicConsumedData ConsumeDataFastPath(QuicStreamId id,
@@ -271,7 +271,11 @@ class QuicPacketGeneratorTest : public QuicTest {
ASSERT_TRUE(packet.encrypted_buffer != nullptr);
ASSERT_TRUE(simple_framer_.ProcessPacket(
QuicEncryptedPacket(packet.encrypted_buffer, packet.encrypted_length)));
- EXPECT_EQ(num_frames, simple_framer_.num_frames());
+ 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());
@@ -285,8 +289,10 @@ class QuicPacketGeneratorTest : public QuicTest {
simple_framer_.crypto_frames().size());
EXPECT_EQ(contents.num_stop_waiting_frames,
simple_framer_.stop_waiting_frames().size());
- EXPECT_EQ(contents.num_padding_frames,
- simple_framer_.padding_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,
@@ -414,26 +420,45 @@ TEST_F(QuicPacketGeneratorTest, ShouldSendAck_MultipleCalls) {
TEST_F(QuicPacketGeneratorTest, AddControlFrame_NotWritable) {
delegate_.SetCanNotWrite();
- generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame()),
- /*bundle_ack=*/false);
- EXPECT_TRUE(generator_.HasQueuedFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
+ QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
+ const bool consumed =
+ generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/false);
+ if (generator_.deprecate_queued_control_frames()) {
+ EXPECT_FALSE(consumed);
+ EXPECT_FALSE(generator_.HasQueuedFrames());
+ EXPECT_FALSE(generator_.HasRetransmittableFrames());
+ delete rst_frame;
+ } else {
+ EXPECT_TRUE(generator_.HasQueuedFrames());
+ EXPECT_TRUE(generator_.HasRetransmittableFrames());
+ }
}
TEST_F(QuicPacketGeneratorTest, AddControlFrame_OnlyAckWritable) {
delegate_.SetCanWriteOnlyNonRetransmittable();
- generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame()),
- /*bundle_ack=*/false);
- EXPECT_TRUE(generator_.HasQueuedFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
+ QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
+ const bool consumed =
+ generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/false);
+ if (generator_.deprecate_queued_control_frames()) {
+ EXPECT_FALSE(consumed);
+ EXPECT_FALSE(generator_.HasQueuedFrames());
+ EXPECT_FALSE(generator_.HasRetransmittableFrames());
+ delete rst_frame;
+ } else {
+ EXPECT_TRUE(generator_.HasQueuedFrames());
+ EXPECT_TRUE(generator_.HasRetransmittableFrames());
+ }
}
TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldNotFlush) {
delegate_.SetCanWriteAnything();
- generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame()),
- /*bundle_ack=*/false);
+ generator_.ConsumeRetransmittableControlFrame(
+ QuicFrame(CreateRstStreamFrame()),
+ /*bundle_ack=*/false);
EXPECT_TRUE(generator_.HasQueuedFrames());
EXPECT_TRUE(generator_.HasRetransmittableFrames());
}
@@ -441,8 +466,17 @@ TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldNotFlush) {
TEST_F(QuicPacketGeneratorTest, AddControlFrame_NotWritableBatchThenFlush) {
delegate_.SetCanNotWrite();
- generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame()),
- /*bundle_ack=*/false);
+ QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
+ const bool consumed =
+ generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/false);
+ if (generator_.deprecate_queued_control_frames()) {
+ EXPECT_FALSE(consumed);
+ EXPECT_FALSE(generator_.HasQueuedFrames());
+ EXPECT_FALSE(generator_.HasRetransmittableFrames());
+ delete rst_frame;
+ return;
+ }
EXPECT_TRUE(generator_.HasQueuedFrames());
EXPECT_TRUE(generator_.HasRetransmittableFrames());
generator_.Flush();
@@ -467,8 +501,9 @@ TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldFlush) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame()),
- /*bundle_ack=*/false);
+ generator_.ConsumeRetransmittableControlFrame(
+ QuicFrame(CreateRstStreamFrame()),
+ /*bundle_ack=*/false);
generator_.Flush();
EXPECT_FALSE(generator_.HasQueuedFrames());
EXPECT_FALSE(generator_.HasRetransmittableFrames());
@@ -551,16 +586,29 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_Handshake) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- MakeIOVector("foo", &iov_);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetCryptoStreamId(framer_.transport_version()), &iov_, 1u,
- iov_.iov_len, 0, NO_FIN);
- EXPECT_EQ(3u, consumed.bytes_consumed);
+ 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_.HasQueuedFrames());
EXPECT_FALSE(generator_.HasRetransmittableFrames());
PacketContents contents;
- contents.num_stream_frames = 1;
+ if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
+ contents.num_crypto_frames = 1;
+ } else {
+ contents.num_stream_frames = 1;
+ }
contents.num_padding_frames = 1;
CheckPacketContains(contents, 0);
@@ -578,16 +626,29 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_Handshake_PaddingDisabled) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- MakeIOVector("foo", &iov_);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetCryptoStreamId(framer_.transport_version()), &iov_, 1u,
- iov_.iov_len, 0, NO_FIN);
- EXPECT_EQ(3u, consumed.bytes_consumed);
+ 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_.HasQueuedFrames());
EXPECT_FALSE(generator_.HasRetransmittableFrames());
PacketContents contents;
- contents.num_stream_frames = 1;
+ if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
+ contents.num_crypto_frames = 1;
+ } else {
+ contents.num_stream_frames = 1;
+ }
contents.num_padding_frames = 0;
CheckPacketContains(contents, 0);
@@ -595,7 +656,16 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_Handshake_PaddingDisabled) {
// Packet is not fully padded, but we want to future packets to be larger.
ASSERT_EQ(kDefaultMaxPacketSize, generator_.GetCurrentMaxPacketLength());
- EXPECT_EQ(27, packets_[0].encrypted_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(QuicPacketGeneratorTest, ConsumeData_EmptyData) {
@@ -778,10 +848,18 @@ TEST_F(QuicPacketGeneratorTest, ConsumeDataLargeSendAckFalse) {
if (!GetQuicReloadableFlag(quic_deprecate_ack_bundling_mode)) {
generator_.SetShouldSendAck(false);
}
- generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame()),
- /*bundle_ack=*/true);
- EXPECT_TRUE(generator_.HasQueuedFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
+ QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
+ const bool success =
+ generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/true);
+ if (generator_.deprecate_queued_control_frames()) {
+ EXPECT_FALSE(success);
+ EXPECT_FALSE(generator_.HasQueuedFrames());
+ EXPECT_FALSE(generator_.HasRetransmittableFrames());
+ } else {
+ EXPECT_TRUE(generator_.HasQueuedFrames());
+ EXPECT_TRUE(generator_.HasRetransmittableFrames());
+ }
delegate_.SetCanWriteAnything();
@@ -789,11 +867,20 @@ TEST_F(QuicPacketGeneratorTest, ConsumeDataLargeSendAckFalse) {
EXPECT_CALL(delegate_, GetUpdatedAckFrame())
.WillOnce(Return(QuicFrame(&ack_frame_)));
}
+ if (generator_.deprecate_queued_control_frames()) {
+ generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/false);
+ }
// Create a 10000 byte IOVector.
CreateData(10000);
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
+ if (generator_.deprecate_queued_control_frames()) {
+ generator_.ConsumeRetransmittableControlFrame(
+ QuicFrame(CreateRstStreamFrame()),
+ /*bundle_ack=*/true);
+ }
QuicConsumedData consumed = generator_.ConsumeData(
QuicUtils::GetHeadersStreamId(framer_.transport_version()), &iov_, 1u,
iov_.iov_len, 0, FIN);
@@ -863,10 +950,18 @@ TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations) {
if (!GetQuicReloadableFlag(quic_deprecate_ack_bundling_mode)) {
generator_.SetShouldSendAck(false);
}
- generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame()),
- /*bundle_ack=*/true);
- EXPECT_TRUE(generator_.HasQueuedFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
+ QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
+ const bool consumed =
+ generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/true);
+ if (generator_.deprecate_queued_control_frames()) {
+ EXPECT_FALSE(consumed);
+ EXPECT_FALSE(generator_.HasQueuedFrames());
+ EXPECT_FALSE(generator_.HasRetransmittableFrames());
+ } else {
+ EXPECT_TRUE(generator_.HasQueuedFrames());
+ EXPECT_TRUE(generator_.HasRetransmittableFrames());
+ }
EXPECT_FALSE(generator_.HasPendingStreamFramesOfStream(3));
delegate_.SetCanWriteAnything();
@@ -877,13 +972,18 @@ TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations) {
EXPECT_CALL(delegate_, GetUpdatedAckFrame())
.WillOnce(Return(QuicFrame(&ack_frame_)));
}
-
+ if (generator_.deprecate_queued_control_frames()) {
+ 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 (framer_.transport_version() != QUIC_VERSION_99) {
- generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame()),
- /*bundle_ack=*/false);
+ generator_.ConsumeRetransmittableControlFrame(
+ QuicFrame(CreateGoAwayFrame()),
+ /*bundle_ack=*/false);
}
EXPECT_TRUE(generator_.HasPendingStreamFramesOfStream(3));
@@ -918,10 +1018,18 @@ TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) {
if (!GetQuicReloadableFlag(quic_deprecate_ack_bundling_mode)) {
generator_.SetShouldSendAck(false);
}
- generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame()),
- /*bundle_ack=*/true);
- EXPECT_TRUE(generator_.HasQueuedFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
+ QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
+ const bool success =
+ generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/true);
+ if (generator_.deprecate_queued_control_frames()) {
+ EXPECT_FALSE(success);
+ EXPECT_FALSE(generator_.HasQueuedFrames());
+ EXPECT_FALSE(generator_.HasRetransmittableFrames());
+ } else {
+ EXPECT_TRUE(generator_.HasQueuedFrames());
+ EXPECT_TRUE(generator_.HasRetransmittableFrames());
+ }
delegate_.SetCanWriteAnything();
@@ -940,7 +1048,11 @@ TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) {
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
}
-
+ if (generator_.deprecate_queued_control_frames()) {
+ 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);
@@ -949,8 +1061,9 @@ TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) {
EXPECT_EQ(data_len, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
if (framer_.transport_version() != QUIC_VERSION_99) {
- generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame()),
- /*bundle_ack=*/false);
+ generator_.ConsumeRetransmittableControlFrame(
+ QuicFrame(CreateGoAwayFrame()),
+ /*bundle_ack=*/false);
}
generator_.Flush();
@@ -1017,23 +1130,20 @@ TEST_F(QuicPacketGeneratorTest, PacketTransmissionType) {
ASSERT_EQ(1u, packets_[0].retransmittable_frames.size());
EXPECT_EQ(stream1_id,
packets_[0].retransmittable_frames[0].stream_frame.stream_id);
- if (GetQuicReloadableFlag(quic_set_transmission_type_for_next_frame)) {
- // 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);
- } else {
- EXPECT_EQ(packets_[0].transmission_type, NOT_RETRANSMISSION);
- }
+
+ // 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_.SetConnectionIdLength(0);
+ generator_.SetServerConnectionIdLength(0);
EXPECT_EQ(PACKET_0BYTE_CONNECTION_ID,
creator_->GetDestinationConnectionIdLength());
for (size_t i = 1; i < 10; i++) {
- generator_.SetConnectionIdLength(i);
+ generator_.SetServerConnectionIdLength(i);
if (framer_.transport_version() > QUIC_VERSION_43) {
EXPECT_EQ(PACKET_0BYTE_CONNECTION_ID,
creator_->GetDestinationConnectionIdLength());
@@ -1341,8 +1451,7 @@ TEST_F(QuicPacketGeneratorTest, DontCrashOnInvalidStopWaiting) {
// This will not serialize any packets, because of the invalid frame.
EXPECT_CALL(delegate_,
- OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET, _,
- ConnectionCloseSource::FROM_SELF));
+ OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET, _));
EXPECT_QUIC_BUG(generator_.Flush(),
"packet_number_length 1 is too small "
"for least_unacked_delta: 1001");
@@ -1358,7 +1467,8 @@ TEST_F(QuicPacketGeneratorTest, ConnectionCloseFrameLargerThanPacketSize) {
if (framer_.transport_version() == QUIC_VERSION_99) {
frame->close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE;
}
- generator_.AddControlFrame(QuicFrame(frame), /*bundle_ack=*/false);
+ generator_.ConsumeRetransmittableControlFrame(QuicFrame(frame),
+ /*bundle_ack=*/false);
EXPECT_TRUE(generator_.HasQueuedFrames());
EXPECT_TRUE(generator_.HasRetransmittableFrames());
}
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 5348abd7c69..0cf7f15d9f7 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
@@ -10,7 +10,6 @@
#include <string>
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.cc b/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.cc
index f03aa6d80fe..d2dfd2245fb 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packet_reader.cc
@@ -86,7 +86,7 @@ bool QuicPacketReader::ReadAndDispatchManyPackets(
DCHECK_LE(kMaxOutgoingPacketSize, packets_[i].iov.iov_len);
msghdr* hdr = &mmsg_hdr_[i].msg_hdr;
hdr->msg_namelen = sizeof(sockaddr_storage);
- DCHECK_EQ(1, hdr->msg_iovlen);
+ DCHECK_EQ(1u, hdr->msg_iovlen);
hdr->msg_controllen = kCmsgSpaceForReadPacket;
hdr->msg_flags = 0;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packets.cc b/chromium/net/third_party/quiche/src/quic/core/quic_packets.cc
index 9b2cb097a34..57bda5476a6 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
@@ -8,6 +8,7 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
@@ -16,6 +17,47 @@
namespace quic {
+QuicConnectionId GetServerConnectionIdAsRecipient(
+ const QuicPacketHeader& header,
+ Perspective perspective) {
+ if (perspective == Perspective::IS_SERVER ||
+ !GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ return header.destination_connection_id;
+ }
+ return header.source_connection_id;
+}
+
+QuicConnectionId GetServerConnectionIdAsSender(const QuicPacketHeader& header,
+ Perspective perspective) {
+ if (perspective == Perspective::IS_CLIENT ||
+ !GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ return header.destination_connection_id;
+ }
+ QUIC_RESTART_FLAG_COUNT_N(quic_do_not_override_connection_id, 3, 5);
+ return header.source_connection_id;
+}
+
+QuicConnectionIdIncluded GetServerConnectionIdIncludedAsSender(
+ const QuicPacketHeader& header,
+ Perspective perspective) {
+ if (perspective == Perspective::IS_CLIENT ||
+ !GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ return header.destination_connection_id_included;
+ }
+ QUIC_RESTART_FLAG_COUNT_N(quic_do_not_override_connection_id, 4, 5);
+ return header.source_connection_id_included;
+}
+
+QuicConnectionIdIncluded GetClientConnectionIdIncludedAsSender(
+ const QuicPacketHeader& header,
+ Perspective perspective) {
+ if (perspective == Perspective::IS_CLIENT ||
+ !GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ return header.source_connection_id_included;
+ }
+ return header.destination_connection_id_included;
+}
+
QuicConnectionIdLength GetIncludedConnectionIdLength(
QuicConnectionId connection_id,
QuicConnectionIdIncluded connection_id_included) {
@@ -74,7 +116,13 @@ size_t GetPacketHeaderSize(
return kPacketHeaderTypeSize + destination_connection_id_length +
packet_number_length;
}
+ // Google QUIC versions <= 43 can only carry one connection ID.
+ DCHECK(destination_connection_id_length == 0 ||
+ source_connection_id_length == 0);
+ DCHECK(source_connection_id_length == 0 ||
+ GetQuicRestartFlag(quic_do_not_override_connection_id));
return kPublicFlagsSize + destination_connection_id_length +
+ source_connection_id_length +
(include_version ? kQuicVersionSize : 0) + packet_number_length +
(include_diversification_nonce ? kDiversificationNonceSize : 0);
}
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 e745e072ced..d3c2600e818 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
@@ -32,6 +32,32 @@ namespace quic {
class QuicPacket;
struct QuicPacketHeader;
+// Returns the destination connection ID of |header| when |perspective| is
+// server, and the source connection ID when |perspective| is client.
+QUIC_EXPORT_PRIVATE QuicConnectionId
+GetServerConnectionIdAsRecipient(const QuicPacketHeader& header,
+ Perspective perspective);
+
+// Returns the destination connection ID of |header| when |perspective| is
+// client, and the source connection ID when |perspective| is server.
+QUIC_EXPORT_PRIVATE QuicConnectionId
+GetServerConnectionIdAsSender(const QuicPacketHeader& header,
+ Perspective perspective);
+
+// Returns the destination connection ID included of |header| when |perspective|
+// is client, and the source connection ID included when |perspective| is
+// server.
+QUIC_EXPORT_PRIVATE QuicConnectionIdIncluded
+GetServerConnectionIdIncludedAsSender(const QuicPacketHeader& header,
+ Perspective perspective);
+
+// Returns the destination connection ID included of |header| when |perspective|
+// is server, and the source connection ID included when |perspective| is
+// client.
+QUIC_EXPORT_PRIVATE QuicConnectionIdIncluded
+GetClientConnectionIdIncludedAsSender(const QuicPacketHeader& header,
+ Perspective perspective);
+
// Number of connection ID bytes that are actually included over the wire.
QUIC_EXPORT_PRIVATE QuicConnectionIdLength
GetIncludedConnectionIdLength(QuicConnectionId connection_id,
@@ -102,6 +128,7 @@ struct QUIC_EXPORT_PRIVATE QuicPacketHeader {
// parsed from the packet buffer. IETF QUIC only, always false for GQUIC.
bool has_possible_stateless_reset_token;
QuicPacketNumberLength packet_number_length;
+ uint8_t type_byte;
ParsedQuicVersion version;
// nonce contains an optional, 32-byte nonce value. If not included in the
// packet, |nonce| will be empty.
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
new file mode 100644
index 00000000000..9ea369e874b
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packets_test.cc
@@ -0,0 +1,91 @@
+// 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_packets.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 {
+
+QuicPacketHeader CreateFakePacketHeader() {
+ QuicPacketHeader header;
+ header.destination_connection_id = TestConnectionId(1);
+ header.destination_connection_id_included = CONNECTION_ID_PRESENT;
+ header.source_connection_id = TestConnectionId(2);
+ header.source_connection_id_included = CONNECTION_ID_ABSENT;
+ return header;
+}
+
+class QuicPacketsTest : public QuicTest {};
+
+TEST_F(QuicPacketsTest, GetServerConnectionIdAsRecipient) {
+ QuicPacketHeader header = CreateFakePacketHeader();
+ if (!GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ EXPECT_EQ(TestConnectionId(1),
+ GetServerConnectionIdAsRecipient(header, Perspective::IS_SERVER));
+ EXPECT_EQ(TestConnectionId(1),
+ GetServerConnectionIdAsRecipient(header, Perspective::IS_CLIENT));
+ return;
+ }
+
+ EXPECT_EQ(TestConnectionId(1),
+ GetServerConnectionIdAsRecipient(header, Perspective::IS_SERVER));
+ EXPECT_EQ(TestConnectionId(2),
+ GetServerConnectionIdAsRecipient(header, Perspective::IS_CLIENT));
+}
+
+TEST_F(QuicPacketsTest, GetServerConnectionIdAsSender) {
+ QuicPacketHeader header = CreateFakePacketHeader();
+ if (!GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ EXPECT_EQ(TestConnectionId(1),
+ GetServerConnectionIdAsSender(header, Perspective::IS_SERVER));
+ EXPECT_EQ(TestConnectionId(1),
+ GetServerConnectionIdAsSender(header, Perspective::IS_CLIENT));
+ return;
+ }
+
+ EXPECT_EQ(TestConnectionId(2),
+ GetServerConnectionIdAsSender(header, Perspective::IS_SERVER));
+ EXPECT_EQ(TestConnectionId(1),
+ GetServerConnectionIdAsSender(header, Perspective::IS_CLIENT));
+}
+
+TEST_F(QuicPacketsTest, GetServerConnectionIdIncludedAsSender) {
+ QuicPacketHeader header = CreateFakePacketHeader();
+ if (!GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ EXPECT_EQ(CONNECTION_ID_PRESENT, GetServerConnectionIdIncludedAsSender(
+ header, Perspective::IS_SERVER));
+ EXPECT_EQ(CONNECTION_ID_PRESENT, GetServerConnectionIdIncludedAsSender(
+ header, Perspective::IS_CLIENT));
+ return;
+ }
+
+ EXPECT_EQ(CONNECTION_ID_ABSENT, GetServerConnectionIdIncludedAsSender(
+ header, Perspective::IS_SERVER));
+ EXPECT_EQ(CONNECTION_ID_PRESENT, GetServerConnectionIdIncludedAsSender(
+ header, Perspective::IS_CLIENT));
+}
+
+TEST_F(QuicPacketsTest, GetClientConnectionIdIncludedAsSender) {
+ QuicPacketHeader header = CreateFakePacketHeader();
+ if (!GetQuicRestartFlag(quic_do_not_override_connection_id)) {
+ EXPECT_EQ(CONNECTION_ID_ABSENT, GetClientConnectionIdIncludedAsSender(
+ header, Perspective::IS_SERVER));
+ EXPECT_EQ(CONNECTION_ID_ABSENT, GetClientConnectionIdIncludedAsSender(
+ header, Perspective::IS_CLIENT));
+ return;
+ }
+
+ EXPECT_EQ(CONNECTION_ID_PRESENT, GetClientConnectionIdIncludedAsSender(
+ header, Perspective::IS_SERVER));
+ EXPECT_EQ(CONNECTION_ID_ABSENT, GetClientConnectionIdIncludedAsSender(
+ header, Perspective::IS_CLIENT));
+}
+
+} // namespace
+} // namespace test
+} // namespace quic
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 528b8665bb6..6fb8c493afa 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
@@ -132,7 +132,7 @@ void QuicReceivedPacketManager::RecordPacketReceived(
// The timestamp format only handles packets in time order.
if (!ack_frame_.received_packet_times.empty() &&
ack_frame_.received_packet_times.back().second > receipt_time) {
- LOG(WARNING)
+ QUIC_LOG(WARNING)
<< "Receive time went backwards from: "
<< ack_frame_.received_packet_times.back().second.ToDebuggingValue()
<< " to " << receipt_time.ToDebuggingValue();
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 456e81c18dd..527f820745b 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
@@ -66,6 +66,11 @@ inline bool ShouldForceRetransmission(TransmissionType transmission_type) {
transmission_type == RTO_RETRANSMISSION;
}
+// If pacing rate is accurate, > 2 burst token is not likely to help first ACK
+// to arrive earlier, and overly large burst token could cause incast packet
+// losses.
+static const uint32_t kConservativeUnpacedBurst = 2;
+
} // namespace
#define ENDPOINT \
@@ -75,11 +80,13 @@ inline bool ShouldForceRetransmission(TransmissionType transmission_type) {
QuicSentPacketManager::QuicSentPacketManager(
Perspective perspective,
const QuicClock* clock,
+ QuicRandom* random,
QuicConnectionStats* stats,
CongestionControlType congestion_control_type,
LossDetectionType loss_type)
: unacked_packets_(perspective),
clock_(clock),
+ random_(random),
stats_(stats),
debug_delegate_(nullptr),
network_change_visitor_(nullptr),
@@ -109,10 +116,15 @@ QuicSentPacketManager::QuicSentPacketManager(
QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs)),
rtt_updated_(false),
acked_packets_iter_(last_ack_frame_.packets.rbegin()),
- tolerate_reneging_(GetQuicReloadableFlag(quic_tolerate_reneging)) {
+ tolerate_reneging_(GetQuicReloadableFlag(quic_tolerate_reneging)),
+ loss_removes_from_inflight_(
+ GetQuicReloadableFlag(quic_loss_removes_from_inflight)) {
if (tolerate_reneging_) {
QUIC_RELOADABLE_FLAG_COUNT(quic_tolerate_reneging);
}
+ if (loss_removes_from_inflight_) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_loss_removes_from_inflight);
+ }
SetSendAlgorithm(congestion_control_type);
}
@@ -252,17 +264,28 @@ 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);
+ AdjustNetworkParameters(bandwidth, rtt, /*allow_cwnd_to_decrease=*/false);
}
-void QuicSentPacketManager::AdjustNetworkParameters(QuicBandwidth bandwidth,
- QuicTime::Delta rtt) {
+void QuicSentPacketManager::AdjustNetworkParameters(
+ QuicBandwidth bandwidth,
+ QuicTime::Delta rtt,
+ bool allow_cwnd_to_decrease) {
if (!rtt.IsZero()) {
SetInitialRtt(rtt);
}
- send_algorithm_->AdjustNetworkParameters(bandwidth, rtt);
+ const QuicByteCount old_cwnd = send_algorithm_->GetCongestionWindow();
+ if (GetQuicReloadableFlag(quic_conservative_bursts) && using_pacing_ &&
+ !bandwidth.IsZero()) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_conservative_bursts);
+ pacing_sender_.SetBurstTokens(kConservativeUnpacedBurst);
+ }
+ send_algorithm_->AdjustNetworkParameters(bandwidth, rtt,
+ allow_cwnd_to_decrease);
if (debug_delegate_ != nullptr) {
- debug_delegate_->OnAdjustNetworkParameters(bandwidth, rtt);
+ debug_delegate_->OnAdjustNetworkParameters(
+ bandwidth, rtt.IsZero() ? rtt_stats_.SmoothedOrInitialRtt() : rtt,
+ old_cwnd, send_algorithm_->GetCongestionWindow());
}
}
@@ -355,14 +378,25 @@ void QuicSentPacketManager::RetransmitUnackedPackets(
DCHECK(retransmission_type == ALL_UNACKED_RETRANSMISSION ||
retransmission_type == ALL_INITIAL_RETRANSMISSION);
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 ((retransmission_type == ALL_UNACKED_RETRANSMISSION ||
- it->encryption_level == ENCRYPTION_ZERO_RTT) &&
- unacked_packets_.HasRetransmittableFrames(*it)) {
- MarkForRetransmission(packet_number, retransmission_type);
+ it->encryption_level == ENCRYPTION_ZERO_RTT)) {
+ if (loss_removes_from_inflight_ && it->in_flight) {
+ // Remove 0-RTT packets and packets of the wrong version from flight,
+ // because neither can be processed by the peer.
+ unacked_packets_.RemoveFromInFlight(&*it);
+ }
+ if (unacked_packets_.HasRetransmittableFrames(*it)) {
+ MarkForRetransmission(packet_number, retransmission_type);
+ }
}
}
+ if (retransmission_type == ALL_UNACKED_RETRANSMISSION &&
+ unacked_packets_.bytes_in_flight() > 0) {
+ QUIC_BUG << "RetransmitUnackedPackets should remove all packets from flight"
+ << ", bytes_in_flight:" << unacked_packets_.bytes_in_flight();
+ }
}
void QuicSentPacketManager::NeuterUnencryptedPackets() {
@@ -382,15 +416,17 @@ void QuicSentPacketManager::NeuterUnencryptedPackets() {
}
for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
it != unacked_packets_.end(); ++it, ++packet_number) {
- if (it->encryption_level == ENCRYPTION_INITIAL &&
- unacked_packets_.HasRetransmittableFrames(*it)) {
- // 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);
- unacked_packets_.RemoveFromInFlight(packet_number);
- unacked_packets_.RemoveRetransmittability(packet_number);
+ if (it->encryption_level == ENCRYPTION_INITIAL) {
+ if (loss_removes_from_inflight_ ||
+ unacked_packets_.HasRetransmittableFrames(*it)) {
+ // 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);
+ unacked_packets_.RemoveFromInFlight(packet_number);
+ unacked_packets_.RemoveRetransmittability(packet_number);
+ }
}
}
}
@@ -435,7 +471,8 @@ void QuicSentPacketManager::MarkForRetransmission(
// Handshake packets should never be sent as probing retransmissions.
DCHECK(!transmission_info->has_crypto_handshake ||
transmission_type != PROBING_RETRANSMISSION);
- if (!RetransmissionLeavesBytesInFlight(transmission_type)) {
+ if (!loss_removes_from_inflight_ &&
+ !RetransmissionLeavesBytesInFlight(transmission_type)) {
unacked_packets_.RemoveFromInFlight(transmission_info);
}
@@ -852,6 +889,9 @@ void QuicSentPacketManager::InvokeLossDetection(QuicTime time) {
time);
}
+ if (loss_removes_from_inflight_) {
+ unacked_packets_.RemoveFromInFlight(packet.packet_number);
+ }
MarkForRetransmission(packet.packet_number, LOSS_RETRANSMISSION);
}
}
@@ -1054,8 +1094,8 @@ void QuicSentPacketManager::CancelRetransmissionsForStream(
void QuicSentPacketManager::SetSendAlgorithm(
CongestionControlType congestion_control_type) {
SetSendAlgorithm(SendAlgorithmInterface::Create(
- clock_, &rtt_stats_, &unacked_packets_, congestion_control_type,
- QuicRandom::GetInstance(), stats_, initial_congestion_window_));
+ clock_, &rtt_stats_, &unacked_packets_, congestion_control_type, random_,
+ stats_, initial_congestion_window_));
}
void QuicSentPacketManager::SetSendAlgorithm(
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 7e10b77048c..3df874dd873 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
@@ -70,7 +70,9 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
virtual void OnApplicationLimited() {}
virtual void OnAdjustNetworkParameters(QuicBandwidth bandwidth,
- QuicTime::Delta rtt) {}
+ QuicTime::Delta rtt,
+ QuicByteCount old_cwnd,
+ QuicByteCount new_cwnd) {}
};
// Interface which gets callbacks from the QuicSentPacketManager when
@@ -89,6 +91,7 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
QuicSentPacketManager(Perspective perspective,
const QuicClock* clock,
+ QuicRandom* random,
QuicConnectionStats* stats,
CongestionControlType congestion_control_type,
LossDetectionType loss_type);
@@ -127,7 +130,9 @@ 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);
+ void AdjustNetworkParameters(QuicBandwidth bandwidth,
+ QuicTime::Delta rtt,
+ bool allow_cwnd_to_decrease);
// Retransmits the oldest pending packet there is still a tail loss probe
// pending. Invoked after OnRetransmissionTimeout.
@@ -535,6 +540,7 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
PendingRetransmissionMap pending_retransmissions_;
const QuicClock* clock_;
+ QuicRandom* random_;
QuicConnectionStats* stats_;
DebugDelegate* debug_delegate_;
@@ -627,6 +633,9 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// Latched value of quic_tolerate_reneging.
const bool tolerate_reneging_;
+
+ // Latched value of quic_loss_removes_from_inflight.
+ const bool loss_removes_from_inflight_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc
index 08e307c1a06..c508cca89dc 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
@@ -80,7 +80,12 @@ class QuicSentPacketManagerTest : public QuicTestWithParam<bool> {
protected:
QuicSentPacketManagerTest()
- : manager_(Perspective::IS_SERVER, &clock_, &stats_, kCubicBytes, kNack),
+ : manager_(Perspective::IS_SERVER,
+ &clock_,
+ QuicRandom::GetInstance(),
+ &stats_,
+ kCubicBytes,
+ kNack),
send_algorithm_(new StrictMock<MockSendAlgorithm>),
network_change_visitor_(new StrictMock<MockNetworkChangeVisitor>) {
QuicSentPacketManagerPeer::SetSendAlgorithm(&manager_, send_algorithm_);
@@ -110,9 +115,7 @@ class QuicSentPacketManagerTest : public QuicTestWithParam<bool> {
~QuicSentPacketManagerTest() override {}
- QuicByteCount BytesInFlight() {
- return QuicSentPacketManagerPeer::GetBytesInFlight(&manager_);
- }
+ QuicByteCount BytesInFlight() { return manager_.GetBytesInFlight(); }
void VerifyUnackedPackets(uint64_t* packets, size_t num_packets) {
if (num_packets == 0) {
EXPECT_TRUE(manager_.unacked_packets().empty());
@@ -124,7 +127,8 @@ class QuicSentPacketManagerTest : public QuicTestWithParam<bool> {
EXPECT_FALSE(manager_.unacked_packets().empty());
EXPECT_EQ(QuicPacketNumber(packets[0]), manager_.GetLeastUnacked());
for (size_t i = 0; i < num_packets; ++i) {
- EXPECT_TRUE(QuicSentPacketManagerPeer::IsUnacked(&manager_, packets[i]))
+ EXPECT_TRUE(
+ manager_.unacked_packets().IsUnacked(QuicPacketNumber(packets[i])))
<< packets[i];
}
}
@@ -374,7 +378,7 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAck) {
// Packet 1 is unacked, pending, but not retransmittable.
uint64_t unacked[] = {1};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
+ EXPECT_TRUE(manager_.HasInFlightPackets());
VerifyRetransmittablePackets(nullptr, 0);
}
@@ -461,7 +465,7 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAckPrevious) {
// 2 remains unacked, but no packets have retransmittable data.
uint64_t unacked[] = {2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
+ EXPECT_TRUE(manager_.HasInFlightPackets());
VerifyRetransmittablePackets(nullptr, 0);
if (manager_.session_decides_what_to_write()) {
// Ack 2 causes 2 be considered as spurious retransmission.
@@ -535,7 +539,7 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAckPreviousThenNackRetransmit) {
// No packets remain unacked.
VerifyUnackedPackets(nullptr, 0);
}
- EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
+ EXPECT_FALSE(manager_.HasInFlightPackets());
VerifyRetransmittablePackets(nullptr, 0);
// Verify that the retransmission alarm would not fire,
@@ -568,7 +572,7 @@ TEST_P(QuicSentPacketManagerTest,
// Since 2 was marked for retransmit, when 1 is acked, 2 is kept for RTT.
uint64_t unacked[] = {2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
+ EXPECT_FALSE(manager_.HasInFlightPackets());
VerifyRetransmittablePackets(nullptr, 0);
// Verify that the retransmission alarm would not fire,
@@ -612,7 +616,7 @@ TEST_P(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
// 2 and 3 remain unacked, but no packets have retransmittable data.
uint64_t unacked[] = {2, 3};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
+ EXPECT_TRUE(manager_.HasInFlightPackets());
VerifyRetransmittablePackets(nullptr, 0);
// Ensure packet 2 is lost when 4 is sent and 3 and 4 are acked.
@@ -634,7 +638,7 @@ TEST_P(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
uint64_t unacked2[] = {2};
VerifyUnackedPackets(unacked2, QUIC_ARRAYSIZE(unacked2));
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
+ EXPECT_TRUE(manager_.HasInFlightPackets());
SendDataPacket(5);
ExpectAckAndLoss(true, 5, 2);
@@ -660,7 +664,7 @@ TEST_P(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
} else {
VerifyUnackedPackets(nullptr, 0);
}
- EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
+ 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.
@@ -884,7 +888,7 @@ TEST_P(QuicSentPacketManagerTest, TailLossProbeTimeout) {
EXPECT_EQ(PACKETS_NEWLY_ACKED,
manager_.OnAckFrameEnd(clock_.Now(), ENCRYPTION_INITIAL));
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
+ EXPECT_TRUE(manager_.HasInFlightPackets());
// Acking two more packets will lose both of them due to nacks.
SendDataPacket(4);
@@ -907,7 +911,7 @@ TEST_P(QuicSentPacketManagerTest, TailLossProbeTimeout) {
manager_.OnAckFrameEnd(clock_.Now(), ENCRYPTION_INITIAL));
EXPECT_FALSE(manager_.HasPendingRetransmissions());
- EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
+ EXPECT_FALSE(manager_.HasInFlightPackets());
EXPECT_EQ(2u, stats_.tlp_count);
EXPECT_EQ(0u, stats_.rto_count);
}
@@ -985,13 +989,11 @@ TEST_P(QuicSentPacketManagerTest, TailLossProbeThenRTO) {
EXPECT_EQ(1u, stats_.rto_count);
if (manager_.session_decides_what_to_write()) {
// There are 2 RTO retransmissions.
- EXPECT_EQ(104 * kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ 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,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(102 * kDefaultLength, manager_.GetBytesInFlight());
EXPECT_TRUE(manager_.HasPendingRetransmissions());
RetransmitNextPacket(103);
}
@@ -1017,9 +1019,9 @@ TEST_P(QuicSentPacketManagerTest, TailLossProbeThenRTO) {
// All packets before 103 should be lost.
if (manager_.session_decides_what_to_write()) {
// Packet 104 is still in flight.
- EXPECT_EQ(1000u, QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(1000u, manager_.GetBytesInFlight());
} else {
- EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(0u, manager_.GetBytesInFlight());
}
}
@@ -1033,7 +1035,8 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeout) {
for (size_t i = 1; i <= kNumSentDataPackets; ++i) {
SendDataPacket(kNumSentCryptoPackets + i);
}
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
+ EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
+ EXPECT_EQ(5 * kDefaultLength, manager_.GetBytesInFlight());
// The first retransmits 2 packets.
if (manager_.session_decides_what_to_write()) {
@@ -1049,7 +1052,11 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeout) {
RetransmitNextPacket(7);
EXPECT_FALSE(manager_.HasPendingRetransmissions());
}
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
+ // Expect all 4 handshake packets to be in flight and 3 data packets.
+ if (GetQuicReloadableFlag(quic_loss_removes_from_inflight)) {
+ EXPECT_EQ(7 * kDefaultLength, manager_.GetBytesInFlight());
+ }
+ EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
// The second retransmits 2 packets.
if (manager_.session_decides_what_to_write()) {
@@ -1065,12 +1072,26 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeout) {
RetransmitNextPacket(9);
EXPECT_FALSE(manager_.HasPendingRetransmissions());
}
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
+ if (GetQuicReloadableFlag(quic_loss_removes_from_inflight)) {
+ EXPECT_EQ(9 * kDefaultLength, manager_.GetBytesInFlight());
+ }
+ EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
// Now ack the two crypto packets and the speculatively encrypted request,
// and ensure the first four crypto packets get abandoned, but not lost.
- uint64_t acked[] = {3, 4, 5, 8, 9};
- ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+ if (GetQuicReloadableFlag(quic_loss_removes_from_inflight)) {
+ // Crypto packets remain in flight, so any that aren't acked will be lost.
+ uint64_t acked[] = {3, 4, 5, 8, 9};
+ uint64_t lost[] = {1, 2, 6};
+ ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), lost,
+ QUIC_ARRAYSIZE(lost));
+ if (manager_.session_decides_what_to_write()) {
+ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(3);
+ }
+ } else {
+ uint64_t acked[] = {3, 4, 5, 8, 9};
+ ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+ }
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, HasUnackedCryptoData())
.WillRepeatedly(Return(false));
@@ -1082,7 +1103,7 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeout) {
EXPECT_EQ(PACKETS_NEWLY_ACKED,
manager_.OnAckFrameEnd(clock_.Now(), ENCRYPTION_INITIAL));
- EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
+ EXPECT_FALSE(manager_.HasUnackedCryptoPackets());
}
TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeoutVersionNegotiation) {
@@ -1095,7 +1116,7 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeoutVersionNegotiation) {
for (size_t i = 1; i <= kNumSentDataPackets; ++i) {
SendDataPacket(kNumSentCryptoPackets + i);
}
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
+ EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, RetransmitFrames(_, _))
@@ -1109,7 +1130,7 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeoutVersionNegotiation) {
RetransmitNextPacket(7);
EXPECT_FALSE(manager_.HasPendingRetransmissions());
}
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
+ EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
// Now act like a version negotiation packet arrived, which would cause all
// unacked packets to be retransmitted.
@@ -1163,7 +1184,7 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeoutVersionNegotiation) {
TEST_P(QuicSentPacketManagerTest, CryptoHandshakeSpuriousRetransmission) {
// Send 1 crypto packet.
SendCryptoPacket(1);
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
+ EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
// Retransmit the crypto packet as 2.
if (manager_.session_decides_what_to_write()) {
@@ -1200,9 +1221,14 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeSpuriousRetransmission) {
EXPECT_EQ(PACKETS_NEWLY_ACKED,
manager_.OnAckFrameEnd(clock_.Now(), ENCRYPTION_INITIAL));
- EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
- uint64_t unacked[] = {3};
- VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ EXPECT_FALSE(manager_.HasUnackedCryptoPackets());
+ if (GetQuicReloadableFlag(quic_loss_removes_from_inflight)) {
+ uint64_t unacked[] = {1, 3};
+ VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ } else {
+ uint64_t unacked[] = {3};
+ VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
+ }
}
TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeoutUnsentDataPacket) {
@@ -1212,7 +1238,7 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeoutUnsentDataPacket) {
SendCryptoPacket(i);
}
SendDataPacket(3);
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
+ EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
// Retransmit 2 crypto packets, but not the serialized packet.
if (manager_.session_decides_what_to_write()) {
@@ -1227,7 +1253,7 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeoutUnsentDataPacket) {
RetransmitNextPacket(5);
EXPECT_FALSE(manager_.HasPendingRetransmissions());
}
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
+ EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
}
TEST_P(QuicSentPacketManagerTest,
@@ -1235,7 +1261,7 @@ TEST_P(QuicSentPacketManagerTest,
// Send 1 crypto packet.
SendCryptoPacket(1);
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
+ EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
// Retransmit the crypto packet as 2.
if (manager_.session_decides_what_to_write()) {
@@ -1254,8 +1280,8 @@ TEST_P(QuicSentPacketManagerTest,
manager_.RetransmitUnackedPackets(ALL_UNACKED_RETRANSMISSION);
if (manager_.session_decides_what_to_write()) {
// Both packets 1 and 2 are unackable.
- EXPECT_FALSE(QuicSentPacketManagerPeer::IsUnacked(&manager_, 1));
- EXPECT_FALSE(QuicSentPacketManagerPeer::IsUnacked(&manager_, 2));
+ 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.
@@ -1263,8 +1289,8 @@ TEST_P(QuicSentPacketManagerTest,
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
EXPECT_TRUE(manager_.HasPendingRetransmissions());
}
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
- EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
+ EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
+ EXPECT_FALSE(manager_.HasInFlightPackets());
}
TEST_P(QuicSentPacketManagerTest,
@@ -1272,7 +1298,7 @@ TEST_P(QuicSentPacketManagerTest,
// Send 1 crypto packet.
SendCryptoPacket(1);
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
+ EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
// Retransmit the crypto packet as 2.
if (manager_.session_decides_what_to_write()) {
@@ -1283,7 +1309,7 @@ TEST_P(QuicSentPacketManagerTest,
if (!manager_.session_decides_what_to_write()) {
RetransmitNextPacket(2);
}
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
+ EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
// Retransmit the crypto packet as 3.
if (manager_.session_decides_what_to_write()) {
@@ -1294,7 +1320,7 @@ TEST_P(QuicSentPacketManagerTest,
if (!manager_.session_decides_what_to_write()) {
RetransmitNextPacket(3);
}
- EXPECT_TRUE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
+ EXPECT_TRUE(manager_.HasUnackedCryptoPackets());
// Now neuter all unacked unencrypted packets, which occurs when the
// connection goes forward secure.
@@ -1304,13 +1330,13 @@ TEST_P(QuicSentPacketManagerTest,
.WillRepeatedly(Return(false));
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
}
- EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
+ EXPECT_FALSE(manager_.HasUnackedCryptoPackets());
uint64_t unacked[] = {1, 2, 3};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(nullptr, 0);
EXPECT_FALSE(manager_.HasPendingRetransmissions());
- EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
- EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
+ EXPECT_FALSE(manager_.HasUnackedCryptoPackets());
+ EXPECT_FALSE(manager_.HasInFlightPackets());
// Ensure both packets get discarded when packet 2 is acked.
uint64_t acked[] = {3};
@@ -1347,12 +1373,10 @@ TEST_P(QuicSentPacketManagerTest, RetransmissionTimeout) {
}
manager_.OnRetransmissionTimeout();
if (manager_.session_decides_what_to_write()) {
- EXPECT_EQ(102 * kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(102 * kDefaultLength, manager_.GetBytesInFlight());
} else {
ASSERT_TRUE(manager_.HasPendingRetransmissions());
- EXPECT_EQ(100 * kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(100 * kDefaultLength, manager_.GetBytesInFlight());
RetransmitNextPacket(101);
ASSERT_TRUE(manager_.HasPendingRetransmissions());
RetransmitNextPacket(102);
@@ -1422,12 +1446,10 @@ TEST_P(QuicSentPacketManagerTest, RetransmissionTimeoutOnePacket) {
}
manager_.OnRetransmissionTimeout();
if (manager_.session_decides_what_to_write()) {
- EXPECT_EQ(101 * kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(101 * kDefaultLength, manager_.GetBytesInFlight());
} else {
ASSERT_TRUE(manager_.HasPendingRetransmissions());
- EXPECT_EQ(100 * kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(100 * kDefaultLength, manager_.GetBytesInFlight());
RetransmitNextPacket(101);
EXPECT_FALSE(manager_.HasPendingRetransmissions());
}
@@ -1468,12 +1490,10 @@ TEST_P(QuicSentPacketManagerTest, NewRetransmissionTimeout) {
}
manager_.OnRetransmissionTimeout();
if (manager_.session_decides_what_to_write()) {
- EXPECT_EQ(102 * kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(102 * kDefaultLength, manager_.GetBytesInFlight());
} else {
EXPECT_TRUE(manager_.HasPendingRetransmissions());
- EXPECT_EQ(100 * kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(100 * kDefaultLength, manager_.GetBytesInFlight());
RetransmitNextPacket(101);
RetransmitNextPacket(102);
EXPECT_FALSE(manager_.HasPendingRetransmissions());
@@ -1511,12 +1531,10 @@ TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckSecond) {
}
manager_.OnRetransmissionTimeout();
if (manager_.session_decides_what_to_write()) {
- EXPECT_EQ(2 * kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(2 * kDefaultLength, manager_.GetBytesInFlight());
} else {
EXPECT_TRUE(manager_.HasPendingRetransmissions());
- EXPECT_EQ(kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(kDefaultLength, manager_.GetBytesInFlight());
RetransmitNextPacket(2);
EXPECT_FALSE(manager_.HasPendingRetransmissions());
}
@@ -1529,12 +1547,10 @@ TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckSecond) {
}
manager_.OnRetransmissionTimeout();
if (manager_.session_decides_what_to_write()) {
- EXPECT_EQ(3 * kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(3 * kDefaultLength, manager_.GetBytesInFlight());
} else {
EXPECT_TRUE(manager_.HasPendingRetransmissions());
- EXPECT_EQ(2 * kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(2 * kDefaultLength, manager_.GetBytesInFlight());
RetransmitNextPacket(3);
EXPECT_FALSE(manager_.HasPendingRetransmissions());
}
@@ -1549,8 +1565,7 @@ TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckSecond) {
manager_.OnAckFrameEnd(clock_.Now(), ENCRYPTION_INITIAL));
// The original packet and newest should be outstanding.
- EXPECT_EQ(2 * kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(2 * kDefaultLength, manager_.GetBytesInFlight());
}
TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckFirst) {
@@ -1564,12 +1579,10 @@ TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckFirst) {
}
manager_.OnRetransmissionTimeout();
if (manager_.session_decides_what_to_write()) {
- EXPECT_EQ(2 * kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(2 * kDefaultLength, manager_.GetBytesInFlight());
} else {
EXPECT_TRUE(manager_.HasPendingRetransmissions());
- EXPECT_EQ(kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(kDefaultLength, manager_.GetBytesInFlight());
RetransmitNextPacket(2);
EXPECT_FALSE(manager_.HasPendingRetransmissions());
}
@@ -1582,12 +1595,10 @@ TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckFirst) {
}
manager_.OnRetransmissionTimeout();
if (manager_.session_decides_what_to_write()) {
- EXPECT_EQ(3 * kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(3 * kDefaultLength, manager_.GetBytesInFlight());
} else {
EXPECT_TRUE(manager_.HasPendingRetransmissions());
- EXPECT_EQ(2 * kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(2 * kDefaultLength, manager_.GetBytesInFlight());
RetransmitNextPacket(3);
EXPECT_FALSE(manager_.HasPendingRetransmissions());
}
@@ -1602,8 +1613,7 @@ TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckFirst) {
manager_.OnAckFrameEnd(clock_.Now(), ENCRYPTION_INITIAL));
// The first two packets should still be outstanding.
- EXPECT_EQ(2 * kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(2 * kDefaultLength, manager_.GetBytesInFlight());
}
TEST_P(QuicSentPacketManagerTest, GetTransmissionTime) {
@@ -1779,14 +1789,12 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeSpuriousRTO) {
manager_.OnRetransmissionTimeout();
if (!manager_.session_decides_what_to_write()) {
// All packets are still considered inflight.
- EXPECT_EQ(4 * kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(4 * kDefaultLength, manager_.GetBytesInFlight());
RetransmitNextPacket(5);
RetransmitNextPacket(6);
}
// All previous packets are inflight, plus two rto retransmissions.
- EXPECT_EQ(6 * kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(6 * kDefaultLength, manager_.GetBytesInFlight());
EXPECT_FALSE(manager_.HasPendingRetransmissions());
// The delay should double the second time.
@@ -1804,8 +1812,7 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeSpuriousRTO) {
EXPECT_EQ(PACKETS_NEWLY_ACKED,
manager_.OnAckFrameEnd(clock_.Now(), ENCRYPTION_INITIAL));
EXPECT_FALSE(manager_.HasPendingRetransmissions());
- EXPECT_EQ(5 * kDefaultLength,
- QuicSentPacketManagerPeer::GetBytesInFlight(&manager_));
+ EXPECT_EQ(5 * kDefaultLength, manager_.GetBytesInFlight());
// Wait 2RTTs from now for the RTO, since it's the max of the RTO time
// and the TLP time. In production, there would always be two TLP's first.
@@ -2364,7 +2371,9 @@ TEST_P(QuicSentPacketManagerTest, ResumeConnectionState) {
cached_network_params.set_min_rtt_ms(kRtt.ToMilliseconds());
EXPECT_CALL(*send_algorithm_,
- AdjustNetworkParameters(QuicBandwidth::Zero(), kRtt));
+ AdjustNetworkParameters(QuicBandwidth::Zero(), kRtt, false));
+ EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+ .Times(testing::AnyNumber());
manager_.ResumeConnectionState(cached_network_params, false);
EXPECT_EQ(kRtt, manager_.GetRttStats()->initial_rtt());
}
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 36070a4c5b5..89e08efb3ad 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
@@ -51,23 +51,30 @@ QuicSession::QuicSession(QuicConnection* connection,
const ParsedQuicVersionVector& supported_versions)
: connection_(connection),
visitor_(owner),
- write_blocked_streams_(),
+ write_blocked_streams_(connection->transport_version()),
config_(config),
stream_id_manager_(this,
kDefaultMaxStreamsPerConnection,
- config_.GetMaxIncomingDynamicStreamsToSend()),
- v99_streamid_manager_(this,
- kDefaultMaxStreamsPerConnection,
- config_.GetMaxIncomingDynamicStreamsToSend()),
+ config_.GetMaxIncomingBidirectionalStreamsToSend()),
+ v99_streamid_manager_(
+ this,
+ kDefaultMaxStreamsPerConnection,
+ kDefaultMaxStreamsPerConnection,
+ config_.GetMaxIncomingBidirectionalStreamsToSend(),
+ config_.GetMaxIncomingUnidirectionalStreamsToSend()),
num_dynamic_incoming_streams_(0),
num_draining_incoming_streams_(0),
+ num_outgoing_static_streams_(0),
+ num_incoming_static_streams_(0),
num_locally_closed_incoming_streams_highest_offset_(0),
error_(QUIC_NO_ERROR),
flow_controller_(
this,
QuicUtils::GetInvalidStreamId(connection->transport_version()),
/*is_connection_flow_controller*/ true,
- kMinimumFlowControlSendWindow,
+ connection->version().AllowsLowFlowControlLimits()
+ ? 0
+ : kMinimumFlowControlSendWindow,
config_.GetInitialSessionFlowControlWindowToSend(),
kSessionReceiveWindowLimit,
perspective() == Perspective::IS_SERVER,
@@ -80,7 +87,10 @@ QuicSession::QuicSession(QuicConnection* connection,
control_frame_manager_(this),
last_message_id_(0),
closed_streams_clean_up_alarm_(nullptr),
- supported_versions_(supported_versions) {
+ supported_versions_(supported_versions),
+ eliminate_static_stream_map_(
+ GetQuicReloadableFlag(quic_eliminate_static_stream_map_3) ||
+ QuicVersionUsesCryptoFrames(connection->transport_version())) {
closed_streams_clean_up_alarm_ =
QuicWrapUnique<QuicAlarm>(connection_->alarm_factory()->CreateAlarm(
new ClosedStreamsCleanUpDelegate(this)));
@@ -92,11 +102,25 @@ void QuicSession::Initialize() {
connection_->SetDataProducer(this);
connection_->SetFromConfig(config_);
+ if (QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ return;
+ }
+
DCHECK_EQ(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
GetMutableCryptoStream()->id());
- RegisterStaticStream(
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- GetMutableCryptoStream());
+ if (!eliminate_static_stream_map_) {
+ RegisterStaticStream(
+ QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ GetMutableCryptoStream());
+ } else {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map_3, 10, 17);
+ QuicStreamId id =
+ QuicUtils::GetCryptoStreamId(connection_->transport_version());
+ largest_static_stream_id_ = std::max(id, largest_static_stream_id_);
+ if (connection_->transport_version() == QUIC_VERSION_99) {
+ v99_streamid_manager_.RegisterStaticStream(id);
+ }
+ }
}
QuicSession::~QuicSession() {
@@ -118,6 +142,43 @@ void QuicSession::RegisterStaticStream(QuicStreamId id, QuicStream* stream) {
}
}
+void QuicSession::RegisterStaticStreamNew(std::unique_ptr<QuicStream> stream) {
+ DCHECK(eliminate_static_stream_map_);
+ QuicStreamId stream_id = stream->id();
+ dynamic_stream_map_[stream_id] = std::move(stream);
+ if (connection_->transport_version() == QUIC_VERSION_99) {
+ v99_streamid_manager_.RegisterStaticStream(stream_id);
+ }
+ if (IsIncomingStream(stream_id)) {
+ ++num_incoming_static_streams_;
+ } else {
+ ++num_outgoing_static_streams_;
+ }
+}
+
+void QuicSession::PendingStreamOnStreamFrame(const QuicStreamFrame& frame) {
+ DCHECK(VersionHasStreamType(connection()->transport_version()));
+ QuicStreamId stream_id = frame.stream_id;
+
+ PendingStream* pending = GetOrCreatePendingStream(stream_id);
+
+ if (!pending) {
+ if (frame.fin) {
+ QuicStreamOffset final_byte_offset = frame.offset + frame.data_length;
+ OnFinalByteOffsetReceived(stream_id, final_byte_offset);
+ }
+ return;
+ }
+
+ pending->OnStreamFrame(frame);
+ if (ProcessPendingStream(pending)) {
+ // The pending stream should now be in the scope of normal streams.
+ DCHECK(IsClosedStream(stream_id) || IsOpenStream(stream_id))
+ << "Stream " << stream_id << " not created";
+ pending_stream_map_.erase(stream_id);
+ }
+}
+
void QuicSession::OnStreamFrame(const QuicStreamFrame& frame) {
// TODO(rch) deal with the error case of stream id 0.
QuicStreamId stream_id = frame.stream_id;
@@ -136,13 +197,19 @@ void QuicSession::OnStreamFrame(const QuicStreamFrame& frame) {
return;
}
- StreamHandler handler = GetOrCreateStreamImpl(stream_id, frame.offset != 0);
- if (handler.is_pending) {
- handler.pending->OnStreamFrame(frame);
+ if (VersionHasStreamType(connection()->transport_version()) &&
+ UsesPendingStreams() &&
+ QuicUtils::GetStreamType(stream_id, perspective(),
+ IsIncomingStream(stream_id)) ==
+ READ_UNIDIRECTIONAL &&
+ dynamic_stream_map_.find(stream_id) == dynamic_stream_map_.end()) {
+ PendingStreamOnStreamFrame(frame);
return;
}
- if (!handler.stream) {
+ QuicStream* stream = GetOrCreateStream(stream_id);
+
+ if (!stream) {
// The stream no longer exists, but we may still be interested in the
// final stream byte offset sent by the peer. A frame with a FIN can give
// us this offset.
@@ -152,7 +219,14 @@ void QuicSession::OnStreamFrame(const QuicStreamFrame& frame) {
}
return;
}
- handler.stream->OnStreamFrame(frame);
+ if (eliminate_static_stream_map_ && frame.fin && stream->is_static()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map_3, 1, 17);
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Attempt to close a static stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
+ stream->OnStreamFrame(frame);
}
void QuicSession::OnCryptoFrame(const QuicCryptoFrame& frame) {
@@ -183,7 +257,9 @@ bool QuicSession::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
// 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 (QuicContainsKey(static_stream_map_, stream_id)) {
+ if (QuicContainsKey(static_stream_map_, stream_id) ||
+ QuicUtils::IsCryptoStreamId(connection_->transport_version(),
+ stream_id)) {
QUIC_DVLOG(1) << ENDPOINT
<< "Received STOP_SENDING for a static stream, id: "
<< stream_id << " Closing connection";
@@ -220,16 +296,28 @@ bool QuicSession::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
// Get the QuicStream for this stream. Ignore the STOP_SENDING
// if the QuicStream pointer is NULL
- // QUESTION: 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).
+ // 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_DVLOG(1) << ENDPOINT
- << "Received STOP_SENDING for NULL QuicStream, stream_id: "
- << stream_id << ". Ignoring.";
+ QUIC_BUG << ENDPOINT
+ << "Received STOP_SENDING for NULL QuicStream, stream_id: "
+ << stream_id << ". Ignoring.";
return true;
}
+
+ if (eliminate_static_stream_map_ && stream->is_static()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map_3, 2, 17);
+ 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;
+ }
+
stream->OnStopSending(frame.application_error_code);
stream->set_stream_error(
@@ -243,6 +331,21 @@ bool QuicSession::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
return true;
}
+void QuicSession::PendingStreamOnRstStream(const QuicRstStreamFrame& frame) {
+ DCHECK(VersionHasStreamType(connection()->transport_version()));
+ QuicStreamId stream_id = frame.stream_id;
+
+ PendingStream* pending = GetOrCreatePendingStream(stream_id);
+
+ if (!pending) {
+ HandleRstOnValidNonexistentStream(frame);
+ return;
+ }
+
+ pending->OnRstStreamFrame(frame);
+ ClosePendingStream(stream_id);
+}
+
void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) {
QuicStreamId stream_id = frame.stream_id;
if (stream_id ==
@@ -264,20 +367,30 @@ void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) {
visitor_->OnRstStreamReceived(frame);
}
- // may_buffer is true here to allow subclasses to buffer streams until the
- // first byte of payload arrives which would allow sessions to delay
- // creation of the stream until the type is known.
- StreamHandler handler = GetOrCreateStreamImpl(stream_id, /*may_buffer=*/true);
- if (handler.is_pending) {
- handler.pending->OnRstStreamFrame(frame);
- ClosePendingStream(stream_id);
+ if (VersionHasStreamType(connection()->transport_version()) &&
+ UsesPendingStreams() &&
+ QuicUtils::GetStreamType(stream_id, perspective(),
+ IsIncomingStream(stream_id)) ==
+ READ_UNIDIRECTIONAL &&
+ dynamic_stream_map_.find(stream_id) == dynamic_stream_map_.end()) {
+ PendingStreamOnRstStream(frame);
return;
}
- if (!handler.stream) {
+
+ QuicStream* stream = GetOrCreateStream(stream_id);
+
+ if (!stream) {
HandleRstOnValidNonexistentStream(frame);
return; // Errors are handled by GetOrCreateStream.
}
- handler.stream->OnStreamReset(frame);
+ if (eliminate_static_stream_map_ && stream->is_static()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map_3, 3, 17);
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
+ stream->OnStreamReset(frame);
}
void QuicSession::OnGoAway(const QuicGoAwayFrame& frame) {
@@ -317,14 +430,35 @@ void QuicSession::OnConnectionClosed(QuicErrorCode error,
error_ = error;
}
- while (!dynamic_stream_map_.empty()) {
- DynamicStreamMap::iterator it = dynamic_stream_map_.begin();
- QuicStreamId id = it->first;
- it->second->OnConnectionClosed(error, source);
- // The stream should call CloseStream as part of OnConnectionClosed.
- if (dynamic_stream_map_.find(id) != dynamic_stream_map_.end()) {
- QUIC_BUG << ENDPOINT << "Stream failed to close under OnConnectionClosed";
- CloseStream(id);
+ if (!eliminate_static_stream_map_) {
+ while (!dynamic_stream_map_.empty()) {
+ DynamicStreamMap::iterator it = dynamic_stream_map_.begin();
+ QuicStreamId id = it->first;
+ it->second->OnConnectionClosed(error, source);
+ // The stream should call CloseStream as part of OnConnectionClosed.
+ if (dynamic_stream_map_.find(id) != dynamic_stream_map_.end()) {
+ QUIC_BUG << ENDPOINT << "Stream " << id
+ << " failed to close under OnConnectionClosed";
+ CloseStream(id);
+ }
+ }
+ } else {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map_3, 4, 17);
+ // Copy all non static streams in a new map for the ease of deleting.
+ QuicSmallMap<QuicStreamId, QuicStream*, 10> non_static_streams;
+ for (const auto& it : dynamic_stream_map_) {
+ if (!it.second->is_static()) {
+ non_static_streams[it.first] = it.second.get();
+ }
+ }
+ for (const auto& it : non_static_streams) {
+ QuicStreamId id = it.first;
+ it.second->OnConnectionClosed(error, source);
+ if (dynamic_stream_map_.find(id) != dynamic_stream_map_.end()) {
+ QUIC_BUG << ENDPOINT << "Stream " << id
+ << " failed to close under OnConnectionClosed";
+ CloseStream(id);
+ }
}
}
@@ -509,6 +643,14 @@ void QuicSession::OnCanWrite() {
}
}
+bool QuicSession::SendProbingData() {
+ if (connection()->sent_packet_manager().MaybeRetransmitOldestPacket(
+ PROBING_RETRANSMISSION)) {
+ return true;
+ }
+ return false;
+}
+
bool QuicSession::WillingAndAbleToWrite() const {
// Schedule a write when:
// 1) control frame manager has pending or new control frames, or
@@ -524,6 +666,11 @@ bool QuicSession::WillingAndAbleToWrite() const {
}
bool QuicSession::HasPendingHandshake() const {
+ if (QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ // Writing CRYPTO frames is not subject to flow control, so there can't be
+ // pending data to write, only pending retransmissions.
+ return GetCryptoStream()->HasPendingCryptoRetransmission();
+ }
return QuicContainsKey(
streams_with_pending_retransmission_,
QuicUtils::GetCryptoStreamId(connection_->transport_version())) ||
@@ -533,7 +680,8 @@ bool QuicSession::HasPendingHandshake() const {
uint64_t QuicSession::GetNumOpenDynamicStreams() const {
return dynamic_stream_map_.size() - draining_streams_.size() +
- locally_closed_streams_highest_offset_.size();
+ locally_closed_streams_highest_offset_.size() -
+ num_incoming_static_streams_ - num_outgoing_static_streams_;
}
void QuicSession::ProcessUdpPacket(const QuicSocketAddress& self_address,
@@ -552,7 +700,7 @@ QuicConsumedData QuicSession::WritevData(QuicStream* stream,
// it might end up resulting in unencrypted stream data being sent.
// While this is impossible to avoid given sufficient corruption, this
// seems like a reasonable mitigation.
- if (id == QuicUtils::GetCryptoStreamId(connection_->transport_version()) &&
+ if (QuicUtils::IsCryptoStreamId(connection_->transport_version(), id) &&
stream != GetMutableCryptoStream()) {
QUIC_BUG << "Stream id mismatch";
connection_->CloseConnection(
@@ -562,7 +710,7 @@ QuicConsumedData QuicSession::WritevData(QuicStream* stream,
return QuicConsumedData(0, false);
}
if (!IsEncryptionEstablished() &&
- id != QuicUtils::GetCryptoStreamId(connection_->transport_version())) {
+ !QuicUtils::IsCryptoStreamId(connection_->transport_version(), id)) {
// Do not let streams write without encryption. The calling stream will end
// up write blocked until OnCanWrite is next called.
return QuicConsumedData(0, false);
@@ -625,6 +773,16 @@ void QuicSession::SendRstStreamInner(QuicStreamId id,
DynamicStreamMap::iterator it = dynamic_stream_map_.find(id);
if (it != dynamic_stream_map_.end()) {
+ if (eliminate_static_stream_map_ && it->second->is_static()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map_3, 5, 17);
+ 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);
@@ -654,12 +812,15 @@ void QuicSession::SendWindowUpdate(QuicStreamId id,
control_frame_manager_.WriteOrBufferWindowUpdate(id, byte_offset);
}
-void QuicSession::SendMaxStreamId(QuicStreamId max_allowed_incoming_id) {
- control_frame_manager_.WriteOrBufferMaxStreamId(max_allowed_incoming_id);
+void QuicSession::SendMaxStreams(QuicStreamCount stream_count,
+ bool unidirectional) {
+ control_frame_manager_.WriteOrBufferMaxStreams(stream_count, unidirectional);
}
-void QuicSession::SendStreamIdBlocked(QuicStreamId max_allowed_outgoing_id) {
- control_frame_manager_.WriteOrBufferStreamIdBlocked(max_allowed_outgoing_id);
+void QuicSession::SendStreamsBlocked(QuicStreamCount stream_count,
+ bool unidirectional) {
+ control_frame_manager_.WriteOrBufferStreamsBlocked(stream_count,
+ unidirectional);
}
void QuicSession::CloseStream(QuicStreamId stream_id) {
@@ -687,6 +848,16 @@ void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool locally_reset) {
return;
}
QuicStream* stream = it->second.get();
+ if (eliminate_static_stream_map_ && stream->is_static()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map_3, 6, 17);
+ QUIC_DVLOG(1) << ENDPOINT
+ << "Try to close a static stream, id: " << stream_id
+ << " Closing connection";
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Try to close a static stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
// Tell the stream that a RST has been sent.
if (locally_reset) {
@@ -818,16 +989,33 @@ bool QuicSession::IsCryptoHandshakeConfirmed() const {
void QuicSession::OnConfigNegotiated() {
connection_->SetFromConfig(config_);
- uint32_t max_streams = 0;
- if (config_.HasReceivedMaxIncomingDynamicStreams()) {
- max_streams = config_.ReceivedMaxIncomingDynamicStreams();
- }
- QUIC_DVLOG(1) << "Setting max_open_outgoing_streams_ to " << max_streams;
if (connection_->transport_version() == QUIC_VERSION_99) {
- v99_streamid_manager_.SetMaxOpenOutgoingStreams(max_streams);
+ uint32_t max_streams = 0;
+ if (config_.HasReceivedMaxIncomingBidirectionalStreams()) {
+ max_streams = config_.ReceivedMaxIncomingBidirectionalStreams();
+ }
+ QUIC_DVLOG(1) << "Setting Bidirectional outgoing_max_streams_ to "
+ << max_streams;
+ v99_streamid_manager_.AdjustMaxOpenOutgoingBidirectionalStreams(
+ max_streams);
+
+ max_streams = 0;
+ if (config_.HasReceivedMaxIncomingUnidirectionalStreams()) {
+ max_streams = config_.ReceivedMaxIncomingUnidirectionalStreams();
+ }
+ QUIC_DVLOG(1) << "Setting Unidirectional outgoing_max_streams_ to "
+ << max_streams;
+ v99_streamid_manager_.AdjustMaxOpenOutgoingUnidirectionalStreams(
+ max_streams);
} else {
+ uint32_t max_streams = 0;
+ if (config_.HasReceivedMaxIncomingBidirectionalStreams()) {
+ max_streams = config_.ReceivedMaxIncomingBidirectionalStreams();
+ }
+ QUIC_DVLOG(1) << "Setting max_open_outgoing_streams_ to " << max_streams;
stream_id_manager_.set_max_open_outgoing_streams(max_streams);
}
+
if (perspective() == Perspective::IS_SERVER) {
if (config_.HasReceivedConnectionOptions()) {
// The following variations change the initial receive flow control
@@ -852,17 +1040,19 @@ void QuicSession::OnConfigNegotiated() {
config_.SetStatelessResetTokenToSend(GetStatelessResetToken());
}
- // A small number of additional incoming streams beyond the limit should be
- // allowed. This helps avoid early connection termination when FIN/RSTs for
- // old streams are lost or arrive out of order.
- // Use a minimum number of additional streams, or a percentage increase,
- // whichever is larger.
- uint32_t max_incoming_streams_to_send =
- config_.GetMaxIncomingDynamicStreamsToSend();
if (connection_->transport_version() == QUIC_VERSION_99) {
- v99_streamid_manager_.SetMaxOpenIncomingStreams(
- max_incoming_streams_to_send);
+ v99_streamid_manager_.SetMaxOpenIncomingBidirectionalStreams(
+ config_.GetMaxIncomingBidirectionalStreamsToSend());
+ v99_streamid_manager_.SetMaxOpenIncomingUnidirectionalStreams(
+ config_.GetMaxIncomingUnidirectionalStreamsToSend());
} else {
+ // A small number of additional incoming streams beyond the limit should be
+ // allowed. This helps avoid early connection termination when FIN/RSTs for
+ // old streams are lost or arrive out of order.
+ // Use a minimum number of additional streams, or a percentage increase,
+ // whichever is larger.
+ uint32_t max_incoming_streams_to_send =
+ config_.GetMaxIncomingBidirectionalStreamsToSend();
uint32_t max_incoming_streams =
std::max(max_incoming_streams_to_send + kMaxStreamsMinimumIncrement,
static_cast<uint32_t>(max_incoming_streams_to_send *
@@ -905,6 +1095,12 @@ void QuicSession::AdjustInitialFlowControlWindows(size_t stream_window) {
for (auto const& kv : dynamic_stream_map_) {
kv.second->flow_controller()->UpdateReceiveWindowSize(stream_window);
}
+ if (eliminate_static_stream_map_ &&
+ !QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map_3, 11, 17);
+ GetMutableCryptoStream()->flow_controller()->UpdateReceiveWindowSize(
+ stream_window);
+ }
}
void QuicSession::HandleFrameOnNonexistentOutgoingStream(
@@ -930,10 +1126,11 @@ void QuicSession::HandleRstOnValidNonexistentStream(
}
void QuicSession::OnNewStreamFlowControlWindow(QuicStreamOffset new_window) {
- if (new_window < kMinimumFlowControlSendWindow) {
+ if (new_window < kMinimumFlowControlSendWindow &&
+ !connection_->version().AllowsLowFlowControlLimits()) {
QUIC_LOG_FIRST_N(ERROR, 1)
<< "Peer sent us an invalid stream flow control send window: "
- << new_window << ", below default: " << kMinimumFlowControlSendWindow;
+ << new_window << ", below minimum: " << kMinimumFlowControlSendWindow;
if (connection_->connected()) {
connection_->CloseConnection(
QUIC_FLOW_CONTROL_INVALID_WINDOW, "New stream window too low",
@@ -949,10 +1146,16 @@ void QuicSession::OnNewStreamFlowControlWindow(QuicStreamOffset new_window) {
for (auto const& kv : dynamic_stream_map_) {
kv.second->UpdateSendWindowOffset(new_window);
}
+ if (eliminate_static_stream_map_ &&
+ !QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map_3, 12, 17);
+ GetMutableCryptoStream()->UpdateSendWindowOffset(new_window);
+ }
}
void QuicSession::OnNewSessionFlowControlWindow(QuicStreamOffset new_window) {
- if (new_window < kMinimumFlowControlSendWindow) {
+ if (new_window < kMinimumFlowControlSendWindow &&
+ !connection_->version().AllowsLowFlowControlLimits()) {
QUIC_LOG_FIRST_N(ERROR, 1)
<< "Peer sent us an invalid session flow control send window: "
<< new_window << ", below default: " << kMinimumFlowControlSendWindow;
@@ -1024,6 +1227,7 @@ QuicConfig* QuicSession::config() {
}
void QuicSession::ActivateStream(std::unique_ptr<QuicStream> stream) {
+ DCHECK(!stream->is_static());
QuicStreamId stream_id = stream->id();
QUIC_DVLOG(1) << ENDPOINT << "num_streams: " << dynamic_stream_map_.size()
<< ". activating " << stream_id;
@@ -1066,20 +1270,17 @@ bool QuicSession::CanOpenNextOutgoingUnidirectionalStream() {
}
QuicStream* QuicSession::GetOrCreateStream(const QuicStreamId stream_id) {
- StreamHandler handler =
- GetOrCreateStreamImpl(stream_id, /*may_buffer=*/false);
- DCHECK(!handler.is_pending);
- return handler.stream;
-}
-
-QuicSession::StreamHandler QuicSession::GetOrCreateStreamImpl(
- QuicStreamId stream_id,
- bool may_buffer) {
+ if (eliminate_static_stream_map_ &&
+ QuicUtils::IsCryptoStreamId(connection_->transport_version(),
+ stream_id)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map_3, 13, 17);
+ return GetMutableCryptoStream();
+ }
StaticStreamMap::iterator it = static_stream_map_.find(stream_id);
if (it != static_stream_map_.end()) {
- return StreamHandler(it->second);
+ return it->second;
}
- return GetOrCreateDynamicStreamImpl(stream_id, may_buffer);
+ return GetOrCreateDynamicStream(stream_id);
}
void QuicSession::StreamDraining(QuicStreamId stream_id) {
@@ -1114,47 +1315,40 @@ bool QuicSession::ShouldYield(QuicStreamId stream_id) {
return write_blocked_streams()->ShouldYield(stream_id);
}
-QuicStream* QuicSession::GetOrCreateDynamicStream(
- const QuicStreamId stream_id) {
- StreamHandler handler =
- GetOrCreateDynamicStreamImpl(stream_id, /*may_buffer=*/false);
- DCHECK(!handler.is_pending);
- return handler.stream;
+PendingStream* QuicSession::GetOrCreatePendingStream(QuicStreamId stream_id) {
+ auto it = pending_stream_map_.find(stream_id);
+ if (it != pending_stream_map_.end()) {
+ return it->second.get();
+ }
+
+ if (IsClosedStream(stream_id) ||
+ !MaybeIncreaseLargestPeerStreamId(stream_id)) {
+ return nullptr;
+ }
+
+ auto pending = QuicMakeUnique<PendingStream>(stream_id, this);
+ PendingStream* unowned_pending = pending.get();
+ pending_stream_map_[stream_id] = std::move(pending);
+ return unowned_pending;
}
-QuicSession::StreamHandler QuicSession::GetOrCreateDynamicStreamImpl(
- QuicStreamId stream_id,
- bool may_buffer) {
+QuicStream* QuicSession::GetOrCreateDynamicStream(
+ const QuicStreamId stream_id) {
DCHECK(!QuicContainsKey(static_stream_map_, stream_id))
<< "Attempt to call GetOrCreateDynamicStream for a static stream";
DynamicStreamMap::iterator it = dynamic_stream_map_.find(stream_id);
if (it != dynamic_stream_map_.end()) {
- return StreamHandler(it->second.get());
+ return it->second.get();
}
if (IsClosedStream(stream_id)) {
- return StreamHandler();
+ return nullptr;
}
if (!IsIncomingStream(stream_id)) {
HandleFrameOnNonexistentOutgoingStream(stream_id);
- return StreamHandler();
- }
-
- auto pending_it = pending_stream_map_.find(stream_id);
- if (pending_it != pending_stream_map_.end()) {
- DCHECK_EQ(QUIC_VERSION_99, connection_->transport_version());
- if (may_buffer) {
- return StreamHandler(pending_it->second.get());
- }
- // The stream limit accounting has already been taken care of
- // when the PendingStream was created, so there is no need to
- // do so here. Now we can create the actual stream from the
- // PendingStream.
- StreamHandler handler(CreateIncomingStream(std::move(*pending_it->second)));
- pending_stream_map_.erase(pending_it);
- return handler;
+ return nullptr;
}
// TODO(fkastenholz): If we are creating a new stream and we have
@@ -1163,7 +1357,7 @@ QuicSession::StreamHandler QuicSession::GetOrCreateDynamicStreamImpl(
// B) reject stream creation ("return nullptr")
if (!MaybeIncreaseLargestPeerStreamId(stream_id)) {
- return StreamHandler();
+ return nullptr;
}
if (connection_->transport_version() != QUIC_VERSION_99) {
@@ -1173,23 +1367,11 @@ QuicSession::StreamHandler QuicSession::GetOrCreateDynamicStreamImpl(
GetNumOpenIncomingStreams())) {
// Refuse to open the stream.
SendRstStream(stream_id, QUIC_REFUSED_STREAM, 0);
- return StreamHandler();
+ return nullptr;
}
}
- if (connection_->transport_version() == QUIC_VERSION_99 && may_buffer &&
- ShouldBufferIncomingStream(stream_id)) {
- ++num_dynamic_incoming_streams_;
- // Since STREAM frames may arrive out of order, delay creating the
- // stream object until the first byte arrives. Buffer the frames and
- // handle flow control accounting in the PendingStream.
- auto pending = QuicMakeUnique<PendingStream>(stream_id, this);
- StreamHandler handler(pending.get());
- pending_stream_map_[stream_id] = std::move(pending);
- return handler;
- }
-
- return StreamHandler(CreateIncomingStream(stream_id));
+ return CreateIncomingStream(stream_id);
}
void QuicSession::set_largest_peer_created_stream_id(
@@ -1223,13 +1405,26 @@ bool QuicSession::IsOpenStream(QuicStreamId id) {
id);
if (QuicContainsKey(static_stream_map_, id) ||
QuicContainsKey(dynamic_stream_map_, id) ||
- QuicContainsKey(pending_stream_map_, id)) {
+ QuicContainsKey(pending_stream_map_, id) ||
+ QuicUtils::IsCryptoStreamId(connection_->transport_version(), id)) {
// Stream is active
return true;
}
return false;
}
+bool QuicSession::IsStaticStream(QuicStreamId id) const {
+ if (eliminate_static_stream_map()) {
+ auto it = dynamic_stream_map_.find(id);
+ if (it == dynamic_stream_map_.end()) {
+ return false;
+ }
+ return it->second->is_static();
+ }
+
+ return QuicContainsKey(static_streams(), id);
+}
+
size_t QuicSession::GetNumOpenIncomingStreams() const {
return num_dynamic_incoming_streams_ - num_draining_incoming_streams_ +
num_locally_closed_incoming_streams_highest_offset_;
@@ -1245,7 +1440,8 @@ size_t QuicSession::GetNumOpenOutgoingStreams() const {
}
size_t QuicSession::GetNumActiveStreams() const {
- return dynamic_stream_map_.size() - draining_streams_.size();
+ return dynamic_stream_map_.size() - draining_streams_.size() -
+ num_incoming_static_streams_ - num_outgoing_static_streams_;
}
size_t QuicSession::GetNumDrainingStreams() const {
@@ -1280,9 +1476,11 @@ void QuicSession::SendPing() {
size_t QuicSession::GetNumDynamicOutgoingStreams() const {
DCHECK_GE(static_cast<size_t>(dynamic_stream_map_.size() +
pending_stream_map_.size()),
- num_dynamic_incoming_streams_);
+ num_dynamic_incoming_streams_ + num_outgoing_static_streams_ +
+ num_incoming_static_streams_);
return dynamic_stream_map_.size() + pending_stream_map_.size() -
- num_dynamic_incoming_streams_;
+ num_dynamic_incoming_streams_ - num_outgoing_static_streams_ -
+ num_incoming_static_streams_;
}
size_t QuicSession::GetNumDrainingOutgoingStreams() const {
@@ -1312,6 +1510,12 @@ bool QuicSession::IsStreamFlowControlBlocked() {
return true;
}
}
+ if (eliminate_static_stream_map_ &&
+ !QuicVersionUsesCryptoFrames(connection_->transport_version()) &&
+ GetMutableCryptoStream()->flow_controller()->IsBlocked()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map_3, 14, 17);
+ return true;
+ }
return false;
}
@@ -1367,6 +1571,13 @@ QuicStream* QuicSession::GetStream(QuicStreamId id) const {
if (zombie_stream != zombie_streams_.end()) {
return zombie_stream->second.get();
}
+
+ if (eliminate_static_stream_map_ &&
+ QuicUtils::IsCryptoStreamId(connection_->transport_version(), id)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map_3, 15, 17);
+ return const_cast<QuicCryptoStream*>(GetCryptoStream());
+ }
+
return nullptr;
}
@@ -1603,7 +1814,8 @@ void QuicSession::NeuterUnencryptedData() {
if (connection_->session_decides_what_to_write()) {
QuicCryptoStream* crypto_stream = GetMutableCryptoStream();
crypto_stream->NeuterUnencryptedStreamData();
- if (!crypto_stream->HasPendingRetransmission()) {
+ if (!crypto_stream->HasPendingRetransmission() &&
+ !QuicVersionUsesCryptoFrames(connection_->transport_version())) {
streams_with_pending_retransmission_.erase(
QuicUtils::GetCryptoStreamId(connection_->transport_version()));
}
@@ -1672,13 +1884,12 @@ QuicStreamId QuicSession::next_outgoing_unidirectional_stream_id() const {
return stream_id_manager_.next_outgoing_stream_id();
}
-bool QuicSession::OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) {
- return v99_streamid_manager_.OnMaxStreamIdFrame(frame);
+bool QuicSession::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
+ return v99_streamid_manager_.OnMaxStreamsFrame(frame);
}
-bool QuicSession::OnStreamIdBlockedFrame(
- const QuicStreamIdBlockedFrame& frame) {
- return v99_streamid_manager_.OnStreamIdBlockedFrame(frame);
+bool QuicSession::OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) {
+ return v99_streamid_manager_.OnStreamsBlockedFrame(frame);
}
size_t QuicSession::max_open_incoming_bidirectional_streams() const {
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 a9fb9923624..513ed9bf60f 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
@@ -52,7 +52,7 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
virtual ~Visitor() {}
// Called when the connection is closed after the streams have been closed.
- virtual void OnConnectionClosed(QuicConnectionId connection_id,
+ virtual void OnConnectionClosed(QuicConnectionId server_connection_id,
QuicErrorCode error,
const std::string& error_details,
ConnectionCloseSource source) = 0;
@@ -115,6 +115,7 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address) override;
void OnCanWrite() override;
+ bool SendProbingData() override;
void OnCongestionWindowChange(QuicTime /*now*/) override {}
void OnConnectionMigration(AddressChangeType type) override {}
// Adds a connection level WINDOW_UPDATE frame.
@@ -125,8 +126,8 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
void OnPathDegrading() override;
bool AllowSelfAddressChange() const override;
void OnForwardProgressConfirmed() override;
- bool OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) override;
- bool OnStreamIdBlockedFrame(const QuicStreamIdBlockedFrame& frame) override;
+ bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override;
+ bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
bool OnStopSendingFrame(const QuicStopSendingFrame& frame) override;
// QuicStreamFrameDataProducer
@@ -211,11 +212,11 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
// Sends a WINDOW_UPDATE frame.
virtual void SendWindowUpdate(QuicStreamId id, QuicStreamOffset byte_offset);
- // Send a MAX_STREAM_ID frame.
- void SendMaxStreamId(QuicStreamId max_allowed_incoming_id);
+ // Send a MAX_STREAMS frame.
+ void SendMaxStreams(QuicStreamCount stream_count, bool unidirectional);
- // Send a STREAM_ID_BLOCKED frame.
- void SendStreamIdBlocked(QuicStreamId max_allowed_outgoing_id);
+ // Send a STREAMS_BLOCKED frame.
+ void SendStreamsBlocked(QuicStreamCount stream_count, bool unidirectional);
// Create and transmit a STOP_SENDING frame
virtual void SendStopSending(uint16_t code, QuicStreamId stream_id);
@@ -300,6 +301,16 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
// reserved headers and crypto streams.
size_t GetNumOpenOutgoingStreams() const;
+ // Returns the number of open peer initiated static streams.
+ size_t num_incoming_static_streams() const {
+ return num_incoming_static_streams_;
+ }
+
+ // Returns the number of open self initiated static streams.
+ size_t num_outgoing_static_streams() const {
+ return num_outgoing_static_streams_;
+ }
+
// Add the stream to the session's write-blocked list because it is blocked by
// connection-level flow control but not by its own stream-level flow control.
// The stream will be given a chance to write when a connection-level
@@ -408,6 +419,10 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
static void RecordConnectionCloseAtServer(QuicErrorCode error,
ConnectionCloseSource source);
+ inline QuicTransportVersion transport_version() const {
+ return connection_->transport_version();
+ }
+
protected:
using StaticStreamMap = QuicSmallMap<QuicStreamId, QuicStream*, 2>;
@@ -472,15 +487,18 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
virtual void OnFinalByteOffsetReceived(QuicStreamId id,
QuicStreamOffset final_byte_offset);
- // Returns true if incoming streams should be buffered until the first
- // byte of the stream arrives.
- virtual bool ShouldBufferIncomingStream(QuicStreamId id) const {
- return false;
- }
+ // Returns true if incoming unidirectional streams should be buffered until
+ // the first byte of the stream arrives.
+ // If a subclass returns true here, it should make sure to implement
+ // ProcessPendingStream().
+ virtual bool UsesPendingStreams() const { return false; }
// Register (|id|, |stream|) with the static stream map. Override previous
// registrations with the same id.
void RegisterStaticStream(QuicStreamId id, QuicStream* stream);
+ // TODO(renjietang): Replace the original Register method with the new one
+ // once flag is deprecated.
+ void RegisterStaticStreamNew(std::unique_ptr<QuicStream> stream);
const StaticStreamMap& static_streams() const { return static_stream_map_; }
DynamicStreamMap& dynamic_streams() { return dynamic_stream_map_; }
@@ -507,6 +525,9 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
// Returns true if the stream is still active.
bool IsOpenStream(QuicStreamId id);
+ // Returns true if the stream is a static stream.
+ bool IsStaticStream(QuicStreamId id) const;
+
// Close connection when receive a frame for a locally-created nonexistant
// stream.
// Prerequisite: IsClosedStream(stream_id) == false
@@ -536,30 +557,14 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
return stream_id_manager_;
}
- // A StreamHandler represents an object which can receive a STREAM or
- // or RST_STREAM frame.
- struct StreamHandler {
- StreamHandler() : is_pending(false), stream(nullptr) {}
-
- // Creates a StreamHandler wrapping a QuicStream.
- explicit StreamHandler(QuicStream* stream)
- : is_pending(false), stream(stream) {}
-
- // Creates a StreamHandler wrapping a PendingStream.
- explicit StreamHandler(PendingStream* pending)
- : is_pending(true), pending(pending) {
- DCHECK(pending != nullptr);
- }
-
- // True if this handler contains a non-null PendingStream, false otherwise.
- bool is_pending;
- union {
- QuicStream* stream;
- PendingStream* pending;
- };
- };
+ // Processes the stream type information of |pending| depending on
+ // different kinds of sessions' own rules. Returns true if the pending stream
+ // is converted into a normal stream.
+ virtual bool ProcessPendingStream(PendingStream* pending) { return false; }
- StreamHandler GetOrCreateStreamImpl(QuicStreamId stream_id, bool may_buffer);
+ bool eliminate_static_stream_map() const {
+ return eliminate_static_stream_map_;
+ }
private:
friend class test::QuicSessionPeer;
@@ -591,8 +596,7 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
// closed.
QuicStream* GetStream(QuicStreamId id) const;
- StreamHandler GetOrCreateDynamicStreamImpl(QuicStreamId stream_id,
- bool may_buffer);
+ PendingStream* GetOrCreatePendingStream(QuicStreamId stream_id);
// Let streams and control frame managers retransmit lost data, returns true
// if all lost data is retransmitted. Returns false otherwise.
@@ -601,6 +605,14 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
// Closes the pending stream |stream_id| before it has been created.
void ClosePendingStream(QuicStreamId stream_id);
+ // Creates or gets pending stream, feeds it with |frame|, and processes the
+ // pending stream.
+ void PendingStreamOnStreamFrame(const QuicStreamFrame& frame);
+
+ // Creates or gets pending strea, feed it with |frame|, and closes the pending
+ // stream.
+ void PendingStreamOnRstStream(const QuicRstStreamFrame& frame);
+
// 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>
@@ -653,6 +665,14 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
// A counter for peer initiated streams which are in the draining_streams_.
size_t num_draining_incoming_streams_;
+ // A counter for self initiated static streams which are in
+ // dynamic_stream_map_.
+ size_t num_outgoing_static_streams_;
+
+ // A counter for peer initiated static streams which are in
+ // dynamic_stream_map_.
+ size_t num_incoming_static_streams_;
+
// A counter for peer initiated streams which are in the
// locally_closed_streams_highest_offset_.
size_t num_locally_closed_incoming_streams_highest_offset_;
@@ -695,6 +715,9 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
// Supported version list used by the crypto handshake only. Please note, this
// list may be a superset of the connection framer's supported versions.
ParsedQuicVersionVector supported_versions_;
+
+ // Latched value of quic_eliminate_static_stream_map.
+ const bool eliminate_static_stream_map_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc
index a517d4703da..e2996db731c 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
@@ -9,7 +9,6 @@
#include <string>
#include <utility>
-#include "testing/gmock/include/gmock/gmock.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
@@ -70,7 +69,8 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
kInitialStreamFlowControlWindowForTest);
session()->config()->SetInitialSessionFlowControlWindowToSend(
kInitialSessionFlowControlWindowForTest);
- session()->config()->ToHandshakeMessage(&msg);
+ session()->config()->ToHandshakeMessage(
+ &msg, session()->connection()->transport_version());
const QuicErrorCode error =
session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
EXPECT_EQ(QUIC_NO_ERROR, error);
@@ -94,7 +94,7 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
}
MOCK_METHOD0(OnCanWrite, void());
- bool HasPendingCryptoRetransmission() override { return false; }
+ bool HasPendingCryptoRetransmission() const override { return false; }
MOCK_CONST_METHOD0(HasPendingRetransmission, bool());
@@ -109,10 +109,16 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
class TestStream : public QuicStream {
public:
TestStream(QuicStreamId id, QuicSession* session, StreamType type)
- : QuicStream(id, session, /*is_static=*/false, type) {}
+ : TestStream(id, session, /*is_static=*/false, type) {}
+
+ TestStream(QuicStreamId id,
+ QuicSession* session,
+ bool is_static,
+ StreamType type)
+ : QuicStream(id, session, is_static, type) {}
TestStream(PendingStream pending, StreamType type)
- : QuicStream(std::move(pending), type) {}
+ : QuicStream(std::move(pending), type, /*is_static=*/false) {}
using QuicStream::CloseReadSide;
using QuicStream::CloseWriteSide;
@@ -139,7 +145,7 @@ class TestSession : public QuicSession {
CurrentSupportedVersions()),
crypto_stream_(this),
writev_consumes_all_data_(false),
- should_buffer_incoming_streams_(false),
+ uses_pending_streams_(false),
num_incoming_streams_created_(0) {
Initialize();
this->connection()->SetEncrypter(
@@ -210,6 +216,19 @@ class TestSession : public QuicSession {
return stream;
}
+ // QuicSession doesn't do anything in this method. So it's overridden here to
+ // test that the session handles pending streams correctly in terms of
+ // receiving stream frames.
+ bool ProcessPendingStream(PendingStream* pending) override {
+ struct iovec iov;
+ if (pending->sequencer()->GetReadableRegion(&iov)) {
+ // Create TestStream once the first byte is received.
+ CreateIncomingStream(std::move(*pending));
+ return true;
+ }
+ return false;
+ }
+
bool IsClosedStream(QuicStreamId id) {
return QuicSession::IsClosedStream(id);
}
@@ -249,8 +268,8 @@ class TestSession : public QuicSession {
QuicConsumedData SendStreamData(QuicStream* stream) {
struct iovec iov;
- if (stream->id() !=
- QuicUtils::GetCryptoStreamId(connection()->transport_version()) &&
+ if (!QuicUtils::IsCryptoStreamId(connection()->transport_version(),
+ stream->id()) &&
this->connection()->encryption_level() != ENCRYPTION_FORWARD_SECURE) {
this->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
}
@@ -280,12 +299,10 @@ class TestSession : public QuicSession {
return WritevData(stream, stream->id(), bytes, 0, FIN);
}
- bool ShouldBufferIncomingStream(QuicStreamId id) const override {
- return should_buffer_incoming_streams_;
- }
+ bool UsesPendingStreams() const override { return uses_pending_streams_; }
- void set_should_buffer_incoming_streams(bool should_buffer_incoming_streams) {
- should_buffer_incoming_streams_ = should_buffer_incoming_streams;
+ void set_uses_pending_streams(bool uses_pending_streams) {
+ uses_pending_streams_ = uses_pending_streams;
}
int num_incoming_streams_created() const {
@@ -300,7 +317,7 @@ class TestSession : public QuicSession {
StrictMock<TestCryptoStream> crypto_stream_;
bool writev_consumes_all_data_;
- bool should_buffer_incoming_streams_;
+ bool uses_pending_streams_;
QuicFrame save_frame_;
int num_incoming_streams_created_;
};
@@ -393,6 +410,24 @@ class QuicSessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
QuicUtils::StreamIdDelta(connection_->transport_version()) * n;
}
+ QuicStreamId StreamCountToId(QuicStreamCount stream_count,
+ Perspective perspective,
+ bool bidirectional) {
+ // Calculate and build up stream ID rather than use
+ // GetFirst... because tests that rely on this method
+ // needs to do the stream count where #1 is 0/1/2/3, and not
+ // take into account that stream 0 is special.
+ QuicStreamId id =
+ ((stream_count - 1) * QuicUtils::StreamIdDelta(QUIC_VERSION_99));
+ if (!bidirectional) {
+ id |= 0x2;
+ }
+ if (perspective == Perspective::IS_SERVER) {
+ id |= 0x1;
+ }
+ return id;
+ }
+
MockQuicConnectionHelper helper_;
MockAlarmFactory alarm_factory_;
NiceMock<MockQuicSessionVisitor> session_visitor_;
@@ -681,31 +716,89 @@ TEST_P(QuicSessionTestServer, TooManyAvailableUnidirectionalStreams) {
TEST_P(QuicSessionTestServer, ManyAvailableBidirectionalStreams) {
// When max_open_streams_ is 200, should be able to create 200 streams
// out-of-order, that is, creating the one with the largest stream ID first.
- QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
+ if (transport_version() == QUIC_VERSION_99) {
+ QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_, 200);
+ // Smaller limit on unidirectional streams to help detect crossed wires.
+ QuicSessionPeer::SetMaxOpenIncomingUnidirectionalStreams(&session_, 50);
+ } else {
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
+ }
+ // Create a stream at the start of the range.
QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
- // Create one stream.
EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id));
- EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
// Create the largest stream ID of a threatened total of 200 streams.
// GetNth... starts at 0, so for 200 streams, get the 199th.
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(
GetNthClientInitiatedBidirectionalId(199)));
+
+ if (transport_version() == QUIC_VERSION_99) {
+ // If IETF QUIC, check to make sure that creating bidirectional
+ // streams does not mess up the unidirectional streams.
+ stream_id = GetNthClientInitiatedUnidirectionalId(0);
+ EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id));
+ // Now try to get the last possible unidirectional stream.
+ EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(
+ GetNthClientInitiatedUnidirectionalId(49)));
+ // and this should fail because it exceeds the unidirectional limit
+ // (but not the bi-)
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_INVALID_STREAM_ID,
+ "Stream id 798 would exceed stream count limit 50",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET
+
+ ))
+ .Times(1);
+ EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(
+ GetNthClientInitiatedUnidirectionalId(199)));
+ }
}
TEST_P(QuicSessionTestServer, ManyAvailableUnidirectionalStreams) {
// When max_open_streams_ is 200, should be able to create 200 streams
// out-of-order, that is, creating the one with the largest stream ID first.
- QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
- QuicStreamId stream_id = GetNthClientInitiatedUnidirectionalId(0);
+ if (transport_version() == QUIC_VERSION_99) {
+ QuicSessionPeer::SetMaxOpenIncomingUnidirectionalStreams(&session_, 200);
+ // Smaller limit on unidirectional streams to help detect crossed wires.
+ QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_, 50);
+ } else {
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, 200);
+ }
// Create one stream.
+ QuicStreamId stream_id = GetNthClientInitiatedUnidirectionalId(0);
EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id));
- EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
// Create the largest stream ID of a threatened total of 200 streams.
// GetNth... starts at 0, so for 200 streams, get the 199th.
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(
GetNthClientInitiatedUnidirectionalId(199)));
+ if (transport_version() == QUIC_VERSION_99) {
+ // If IETF QUIC, check to make sure that creating unidirectional
+ // streams does not mess up the bidirectional streams.
+ stream_id = GetNthClientInitiatedBidirectionalId(0);
+ EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id));
+ // Now try to get the last possible bidirectional stream.
+ EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(
+ GetNthClientInitiatedBidirectionalId(49)));
+ // and this should fail because it exceeds the bnidirectional limit
+ // (but not the uni-)
+ std::string error_detail;
+ if (QuicVersionUsesCryptoFrames(transport_version())) {
+ error_detail = "Stream id 796 would exceed stream count limit 50";
+ } else {
+ error_detail = "Stream id 800 would exceed stream count limit 50";
+ }
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_INVALID_STREAM_ID, error_detail,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET))
+ .Times(1);
+ EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(
+ GetNthClientInitiatedBidirectionalId(199)));
+ }
}
TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) {
@@ -935,6 +1028,11 @@ TEST_P(QuicSessionTestServer, OnCanWriteWriterBlocks) {
}
TEST_P(QuicSessionTestServer, BufferedHandshake) {
+ // This test is testing behavior of crypto stream flow control, but when
+ // CRYPTO frames are used, there is no flow control for the crypto handshake.
+ if (QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ return;
+ }
session_.set_writev_consumes_all_data(true);
EXPECT_FALSE(session_.HasPendingHandshake()); // Default value.
@@ -1021,8 +1119,10 @@ TEST_P(QuicSessionTestServer, OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
// Mark the crypto and headers streams as write blocked, we expect them to be
// allowed to write later.
- session_.MarkConnectionLevelWriteBlocked(
- QuicUtils::GetCryptoStreamId(connection_->transport_version()));
+ if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ session_.MarkConnectionLevelWriteBlocked(
+ QuicUtils::GetCryptoStreamId(connection_->transport_version()));
+ }
// Create a data stream, and although it is write blocked we never expect it
// to be allowed to write as we are connection level flow control blocked.
@@ -1032,8 +1132,10 @@ TEST_P(QuicSessionTestServer, OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
// The crypto and headers streams should be called even though we are
// connection flow control blocked.
- TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
- EXPECT_CALL(*crypto_stream, OnCanWrite());
+ if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
+ EXPECT_CALL(*crypto_stream, OnCanWrite());
+ }
// After the crypto and header streams perform a write, the connection will be
// blocked by the flow control, hence it should become application-limited.
@@ -1164,10 +1266,19 @@ TEST_P(QuicSessionTestServer, IncreasedTimeoutAfterCryptoHandshake) {
}
TEST_P(QuicSessionTestServer, OnStreamFrameFinStaticStreamId) {
+ QuicStreamId headers_stream_id =
+ QuicUtils::GetHeadersStreamId(connection_->transport_version());
+ std::unique_ptr<TestStream> fake_headers_stream = QuicMakeUnique<TestStream>(
+ headers_stream_id, &session_, /*is_static*/ true, BIDIRECTIONAL);
+ if (GetQuicReloadableFlag(quic_eliminate_static_stream_map_3)) {
+ QuicSessionPeer::RegisterStaticStreamNew(&session_,
+ std::move(fake_headers_stream));
+ } else {
+ QuicSessionPeer::RegisterStaticStream(&session_, headers_stream_id,
+ fake_headers_stream.get());
+ }
// Send two bytes of payload.
- QuicStreamFrame data1(
- QuicUtils::GetCryptoStreamId(connection_->transport_version()), true, 0,
- QuicStringPiece("HT"));
+ QuicStreamFrame data1(headers_stream_id, true, 0, QuicStringPiece("HT"));
EXPECT_CALL(*connection_,
CloseConnection(
QUIC_INVALID_STREAM_ID, "Attempt to close a static stream",
@@ -1176,11 +1287,20 @@ TEST_P(QuicSessionTestServer, OnStreamFrameFinStaticStreamId) {
}
TEST_P(QuicSessionTestServer, OnRstStreamStaticStreamId) {
+ QuicStreamId headers_stream_id =
+ QuicUtils::GetHeadersStreamId(connection_->transport_version());
+ std::unique_ptr<TestStream> fake_headers_stream = QuicMakeUnique<TestStream>(
+ headers_stream_id, &session_, /*is_static*/ true, BIDIRECTIONAL);
+ if (GetQuicReloadableFlag(quic_eliminate_static_stream_map_3)) {
+ QuicSessionPeer::RegisterStaticStreamNew(&session_,
+ std::move(fake_headers_stream));
+ } else {
+ QuicSessionPeer::RegisterStaticStream(&session_, headers_stream_id,
+ fake_headers_stream.get());
+ }
// Send two bytes of payload.
- QuicRstStreamFrame rst1(
- kInvalidControlFrameId,
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- QUIC_ERROR_PROCESSING_STREAM, 0);
+ QuicRstStreamFrame rst1(kInvalidControlFrameId, headers_stream_id,
+ QUIC_ERROR_PROCESSING_STREAM, 0);
EXPECT_CALL(*connection_,
CloseConnection(
QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream",
@@ -1269,7 +1389,7 @@ TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedCryptoStream) {
QuicStreamOffset offset = crypto_stream->stream_bytes_written();
QuicConfig config;
CryptoHandshakeMessage crypto_message;
- config.ToHandshakeMessage(&crypto_message);
+ config.ToHandshakeMessage(&crypto_message, transport_version());
crypto_stream->SendHandshakeMessage(crypto_message);
char buf[1000];
QuicDataWriter writer(1000, buf, NETWORK_BYTE_ORDER);
@@ -1431,8 +1551,12 @@ TEST_P(QuicSessionTestServer, InvalidStreamFlowControlWindowInHandshake) {
QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(session_.config(),
kInvalidWindow);
- EXPECT_CALL(*connection_,
- CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
+ if (!connection_->version().AllowsLowFlowControlLimits()) {
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
+ } else {
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
+ }
session_.OnConfigNegotiated();
}
@@ -1442,9 +1566,12 @@ TEST_P(QuicSessionTestServer, InvalidSessionFlowControlWindowInHandshake) {
const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(session_.config(),
kInvalidWindow);
-
- EXPECT_CALL(*connection_,
- CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
+ if (!connection_->version().AllowsLowFlowControlLimits()) {
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
+ } else {
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
+ }
session_.OnConfigNegotiated();
}
@@ -1486,7 +1613,12 @@ TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) {
// with a FIN or RST then we send an RST to refuse streams. For V99 the
// connection is closed.
const QuicStreamId kMaxStreams = 5;
- QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
+ if (transport_version() == QUIC_VERSION_99) {
+ QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
+ kMaxStreams);
+ } else {
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
+ }
const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);
const QuicStreamId kFinalStreamId =
GetNthClientInitiatedBidirectionalId(kMaxStreams);
@@ -1514,8 +1646,10 @@ TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) {
}
if (transport_version() == QUIC_VERSION_99) {
- EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID,
- "Stream id 24 above 20", _));
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_INVALID_STREAM_ID,
+ "Stream id 20 would exceed stream count limit 5", _));
} else {
EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
EXPECT_CALL(*connection_,
@@ -1540,7 +1674,7 @@ TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpenedOutgoing) {
}
TEST_P(QuicSessionTestServer, NoPendingStreams) {
- session_.set_should_buffer_incoming_streams(false);
+ session_.set_uses_pending_streams(false);
QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
transport_version(), Perspective::IS_CLIENT);
@@ -1557,7 +1691,7 @@ TEST_P(QuicSessionTestServer, PendingStreams) {
if (connection_->transport_version() != QUIC_VERSION_99) {
return;
}
- session_.set_should_buffer_incoming_streams(true);
+ session_.set_uses_pending_streams(true);
QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
transport_version(), Perspective::IS_CLIENT);
@@ -1574,7 +1708,7 @@ TEST_P(QuicSessionTestServer, RstPendingStreams) {
if (connection_->transport_version() != QUIC_VERSION_99) {
return;
}
- session_.set_should_buffer_incoming_streams(true);
+ session_.set_uses_pending_streams(true);
QuicStreamId stream_id = QuicUtils::GetFirstUnidirectionalStreamId(
transport_version(), Perspective::IS_CLIENT);
@@ -1601,7 +1735,7 @@ TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpened) {
// it) does not count against the open quota (because it is closed from the
// protocol point of view).
if (transport_version() == QUIC_VERSION_99) {
- // On v99, we will expect to see a MAX_STREAM_ID go out when there are not
+ // On v99, we will expect to see a MAX_STREAMS go out when there are not
// enough streams to create the next one.
EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
} else {
@@ -1609,7 +1743,12 @@ TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpened) {
}
EXPECT_CALL(*connection_, OnStreamReset(_, QUIC_REFUSED_STREAM)).Times(0);
const QuicStreamId kMaxStreams = 5;
- QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
+ if (transport_version() == QUIC_VERSION_99) {
+ QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
+ kMaxStreams);
+ } else {
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
+ }
// Create kMaxStreams + 1 data streams, and mark them draining.
const QuicStreamId kFirstStreamId = GetNthClientInitiatedBidirectionalId(0);
@@ -1806,9 +1945,12 @@ TEST_P(QuicSessionTestServer, OnStreamFrameLost) {
TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
- QuicStreamFrame frame1(
- QuicUtils::GetCryptoStreamId(connection_->transport_version()), false, 0,
- 1300);
+ QuicStreamFrame frame1;
+ if (!QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ frame1 = QuicStreamFrame(
+ QuicUtils::GetCryptoStreamId(connection_->transport_version()), false,
+ 0, 1300);
+ }
QuicStreamFrame frame2(stream2->id(), false, 0, 9);
QuicStreamFrame frame3(stream4->id(), false, 0, 9);
@@ -2179,19 +2321,24 @@ TEST_P(QuicSessionTestServer, NewStreamIdBelowLimit) {
// Applicable only to V99
return;
}
- QuicStreamId bidirectional_stream_id =
+ QuicStreamId bidirectional_stream_id = StreamCountToId(
QuicSessionPeer::v99_streamid_manager(&session_)
- ->advertised_max_allowed_incoming_bidirectional_stream_id() -
- kV99StreamIdIncrement;
+ ->advertised_max_allowed_incoming_bidirectional_streams() -
+ 1,
+ Perspective::IS_CLIENT,
+ /*bidirectional=*/true);
+
QuicStreamFrame bidirectional_stream_frame(bidirectional_stream_id, false, 0,
"Random String");
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
session_.OnStreamFrame(bidirectional_stream_frame);
- QuicStreamId unidirectional_stream_id =
+ QuicStreamId unidirectional_stream_id = StreamCountToId(
QuicSessionPeer::v99_streamid_manager(&session_)
- ->advertised_max_allowed_incoming_unidirectional_stream_id() -
- kV99StreamIdIncrement;
+ ->advertised_max_allowed_incoming_unidirectional_streams() -
+ 1,
+ Perspective::IS_CLIENT,
+ /*bidirectional=*/false);
QuicStreamFrame unidirectional_stream_frame(unidirectional_stream_id, false,
0, "Random String");
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
@@ -2204,17 +2351,19 @@ TEST_P(QuicSessionTestServer, NewStreamIdAtLimit) {
// Applicable only to V99
return;
}
- QuicStreamId bidirectional_stream_id =
+ QuicStreamId bidirectional_stream_id = StreamCountToId(
QuicSessionPeer::v99_streamid_manager(&session_)
- ->advertised_max_allowed_incoming_bidirectional_stream_id();
+ ->advertised_max_allowed_incoming_bidirectional_streams(),
+ Perspective::IS_CLIENT, /*bidirectional=*/true);
QuicStreamFrame bidirectional_stream_frame(bidirectional_stream_id, false, 0,
"Random String");
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
session_.OnStreamFrame(bidirectional_stream_frame);
- QuicStreamId unidirectional_stream_id =
+ QuicStreamId unidirectional_stream_id = StreamCountToId(
QuicSessionPeer::v99_streamid_manager(&session_)
- ->advertised_max_allowed_incoming_unidirectional_stream_id();
+ ->advertised_max_allowed_incoming_unidirectional_streams(),
+ Perspective::IS_CLIENT, /*bidirectional=*/false);
QuicStreamFrame unidirectional_stream_frame(unidirectional_stream_id, false,
0, "Random String");
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
@@ -2227,24 +2376,30 @@ TEST_P(QuicSessionTestServer, NewStreamIdAboveLimit) {
// Applicable only to V99
return;
}
- QuicStreamId bidirectional_stream_id =
+ QuicStreamId bidirectional_stream_id = StreamCountToId(
QuicSessionPeer::v99_streamid_manager(&session_)
- ->advertised_max_allowed_incoming_bidirectional_stream_id() +
- kV99StreamIdIncrement;
+ ->advertised_max_allowed_incoming_bidirectional_streams() +
+ 1,
+ Perspective::IS_CLIENT, /*bidirectional=*/true);
QuicStreamFrame bidirectional_stream_frame(bidirectional_stream_id, false, 0,
"Random String");
- EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID,
- "Stream id 404 above 400", _));
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_INVALID_STREAM_ID,
+ "Stream id 400 would exceed stream count limit 100", _));
session_.OnStreamFrame(bidirectional_stream_frame);
- QuicStreamId unidirectional_stream_id =
+ QuicStreamId unidirectional_stream_id = StreamCountToId(
QuicSessionPeer::v99_streamid_manager(&session_)
- ->advertised_max_allowed_incoming_unidirectional_stream_id() +
- kV99StreamIdIncrement;
+ ->advertised_max_allowed_incoming_unidirectional_streams() +
+ 1,
+ Perspective::IS_CLIENT, /*bidirectional=*/false);
QuicStreamFrame unidirectional_stream_frame(unidirectional_stream_id, false,
0, "Random String");
- EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID,
- "Stream id 402 above 398", _));
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_INVALID_STREAM_ID,
+ "Stream id 402 would exceed stream count limit 100", _));
session_.OnStreamFrame(unidirectional_stream_frame);
}
@@ -2272,9 +2427,19 @@ TEST_P(QuicSessionTestServer, OnStopSendingInputStaticStreams) {
// Applicable only to V99
return;
}
+ QuicStreamId stream_id = 0;
+ std::unique_ptr<TestStream> fake_static_stream = QuicMakeUnique<TestStream>(
+ stream_id, &session_, /*is_static*/ true, BIDIRECTIONAL);
+ if (GetQuicReloadableFlag(quic_eliminate_static_stream_map_3)) {
+ QuicSessionPeer::RegisterStaticStreamNew(&session_,
+ std::move(fake_static_stream));
+ } else {
+ QuicSessionPeer::RegisterStaticStream(&session_, stream_id,
+ fake_static_stream.get());
+ }
// Check that a stream id in the static stream map is ignored.
// Note that the notion of a static stream is Google-specific.
- QuicStopSendingFrame frame(1, 0, 123);
+ QuicStopSendingFrame frame(1, stream_id, 123);
EXPECT_CALL(*connection_,
CloseConnection(QUIC_INVALID_STREAM_ID,
"Received STOP_SENDING for a static stream", _));
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 4fba898377a..94cffd4030c 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
@@ -33,7 +33,7 @@ size_t GetReceivedFlowControlWindow(QuicSession* session) {
return session->config()->ReceivedInitialStreamFlowControlWindowBytes();
}
- return kMinimumFlowControlSendWindow;
+ return kDefaultFlowControlSendWindow;
}
} // namespace
@@ -58,8 +58,8 @@ PendingStream::PendingStream(QuicStreamId id, QuicSession* session)
sequencer_(this) {}
void PendingStream::OnDataAvailable() {
- QUIC_BUG << "OnDataAvailable should not be called.";
- CloseConnectionWithDetails(QUIC_INTERNAL_ERROR, "Unexpected data available");
+ // It will be called when pending stream receives its first byte. But this
+ // call should simply be ignored so that data remains in sequencer.
}
void PendingStream::OnFinRead() {
@@ -68,8 +68,9 @@ void PendingStream::OnFinRead() {
}
void PendingStream::AddBytesConsumed(QuicByteCount bytes) {
- QUIC_BUG << "AddBytesConsumed should not be called.";
- CloseConnectionWithDetails(QUIC_INTERNAL_ERROR, "Unexpected bytes consumed");
+ // It will be called when the metadata of the stream is consumed.
+ flow_controller_.AddBytesConsumed(bytes);
+ connection_flow_controller_->AddBytesConsumed(bytes);
}
void PendingStream::Reset(QuicRstStreamErrorCode error) {
@@ -92,7 +93,6 @@ const QuicSocketAddress& PendingStream::PeerAddressOfLatestPacket() const {
void PendingStream::OnStreamFrame(const QuicStreamFrame& frame) {
DCHECK_EQ(frame.stream_id, id_);
- DCHECK_NE(0u, frame.offset);
bool is_stream_too_long =
(frame.offset > kMaxStreamLength) ||
@@ -169,11 +169,15 @@ bool PendingStream::MaybeIncreaseHighestReceivedOffset(
return true;
}
-QuicStream::QuicStream(PendingStream pending, StreamType type)
+void PendingStream::MarkConsumed(size_t num_bytes) {
+ sequencer_.MarkConsumed(num_bytes);
+}
+
+QuicStream::QuicStream(PendingStream pending, StreamType type, bool is_static)
: QuicStream(pending.id_,
pending.session_,
std::move(pending.sequencer_),
- /*is_static=*/false,
+ is_static,
type,
pending.stream_bytes_read_,
pending.fin_received_,
@@ -182,6 +186,30 @@ QuicStream::QuicStream(PendingStream pending, StreamType type)
sequencer_.set_stream(this);
}
+namespace {
+
+QuicOptional<QuicFlowController> FlowController(QuicStreamId id,
+ QuicSession* session,
+ StreamType type) {
+ if (type == CRYPTO) {
+ // The only QuicStream with a StreamType of CRYPTO is QuicCryptoStream, when
+ // it is using crypto frames instead of stream frames. The QuicCryptoStream
+ // doesn't have any flow control in that case, so we don't create a
+ // QuicFlowController for it.
+ return QuicOptional<QuicFlowController>();
+ }
+ return QuicFlowController(
+ session, id,
+ /*is_connection_flow_controller*/ false,
+ GetReceivedFlowControlWindow(session),
+ GetInitialStreamFlowControlWindowToSend(session),
+ kStreamReceiveWindowLimit,
+ session->flow_controller()->auto_tune_receive_window(),
+ session->flow_controller());
+}
+
+} // namespace
+
QuicStream::QuicStream(QuicStreamId id,
QuicSession* session,
bool is_static,
@@ -193,15 +221,7 @@ QuicStream::QuicStream(QuicStreamId id,
type,
0,
false,
- QuicFlowController(
- session,
- id,
- /*is_connection_flow_controller*/ false,
- GetReceivedFlowControlWindow(session),
- GetInitialStreamFlowControlWindowToSend(session),
- kStreamReceiveWindowLimit,
- session->flow_controller()->auto_tune_receive_window(),
- session->flow_controller()),
+ FlowController(id, session, type),
session->flow_controller()) {}
QuicStream::QuicStream(QuicStreamId id,
@@ -211,7 +231,7 @@ QuicStream::QuicStream(QuicStreamId id,
StreamType type,
uint64_t stream_bytes_read,
bool fin_received,
- QuicFlowController flow_controller,
+ QuicOptional<QuicFlowController> flow_controller,
QuicFlowController* connection_flow_controller)
: sequencer_(std::move(sequencer)),
id_(id),
@@ -240,7 +260,8 @@ QuicStream::QuicStream(QuicStreamId id,
buffered_data_threshold_(GetQuicFlag(FLAGS_quic_buffered_data_threshold)),
is_static_(is_static),
deadline_(QuicTime::Zero()),
- type_(session->connection()->transport_version() == QUIC_VERSION_99
+ type_(session->connection()->transport_version() == QUIC_VERSION_99 &&
+ type != CRYPTO
? QuicUtils::GetStreamType(id_,
perspective_,
session->IsIncomingStream(id_))
@@ -253,7 +274,9 @@ QuicStream::QuicStream(QuicStreamId id,
CloseWriteSide();
}
SetFromConfig();
- session_->RegisterStreamPriority(id, is_static_, priority_);
+ if (type_ != CRYPTO) {
+ session_->RegisterStreamPriority(id, is_static_, priority_);
+ }
}
QuicStream::~QuicStream() {
@@ -264,7 +287,7 @@ QuicStream::~QuicStream() {
<< send_buffer_.stream_bytes_outstanding()
<< ", fin_outstanding: " << fin_outstanding_;
}
- if (session_ != nullptr) {
+ if (session_ != nullptr && type_ != CRYPTO) {
session_->UnregisterStreamPriority(id(), is_static_);
}
}
@@ -324,7 +347,7 @@ void QuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
MaybeIncreaseHighestReceivedOffset(frame.offset + frame_payload_size)) {
// As the highest received offset has changed, check to see if this is a
// violation of flow control.
- if (flow_controller_.FlowControlViolation() ||
+ if (flow_controller_->FlowControlViolation() ||
connection_flow_controller_->FlowControlViolation()) {
CloseConnectionWithDetails(
QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
@@ -353,7 +376,7 @@ void QuicStream::OnStreamReset(const QuicRstStreamFrame& frame) {
return;
}
MaybeIncreaseHighestReceivedOffset(frame.byte_offset);
- if (flow_controller_.FlowControlViolation() ||
+ if (flow_controller_->FlowControlViolation() ||
connection_flow_controller_->FlowControlViolation()) {
CloseConnectionWithDetails(
QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
@@ -494,7 +517,7 @@ void QuicStream::OnCanWrite() {
}
void QuicStream::MaybeSendBlocked() {
- if (flow_controller_.ShouldSendBlocked()) {
+ if (flow_controller_->ShouldSendBlocked()) {
session_->SendBlocked(id_);
}
if (!stream_contributes_to_connection_flow_control_) {
@@ -508,7 +531,7 @@ void QuicStream::MaybeSendBlocked() {
// the stream will be given a chance to write when a connection-level
// WINDOW_UPDATE arrives.
if (connection_flow_controller_->IsBlocked() &&
- !flow_controller_.IsBlocked()) {
+ !flow_controller_->IsBlocked()) {
session_->MarkConnectionLevelWriteBlocked(id());
}
}
@@ -708,7 +731,7 @@ void QuicStream::OnClose() {
rst_sent_ = true;
}
- if (flow_controller_.FlowControlViolation() ||
+ if (flow_controller_->FlowControlViolation() ||
connection_flow_controller_->FlowControlViolation()) {
return;
}
@@ -717,13 +740,13 @@ void QuicStream::OnClose() {
// the same connection level flow control state, mark all unreceived or
// buffered bytes as consumed.
QuicByteCount bytes_to_consume =
- flow_controller_.highest_received_byte_offset() -
- flow_controller_.bytes_consumed();
+ flow_controller_->highest_received_byte_offset() -
+ flow_controller_->bytes_consumed();
AddBytesConsumed(bytes_to_consume);
}
void QuicStream::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
- if (flow_controller_.UpdateSendWindowOffset(frame.byte_offset)) {
+ if (flow_controller_->UpdateSendWindowOffset(frame.byte_offset)) {
// Let session unblock this stream.
session_->MarkConnectionLevelWriteBlocked(id_);
}
@@ -732,8 +755,8 @@ void QuicStream::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
bool QuicStream::MaybeIncreaseHighestReceivedOffset(
QuicStreamOffset new_offset) {
uint64_t increment =
- new_offset - flow_controller_.highest_received_byte_offset();
- if (!flow_controller_.UpdateHighestReceivedOffset(new_offset)) {
+ new_offset - flow_controller_->highest_received_byte_offset();
+ if (!flow_controller_->UpdateHighestReceivedOffset(new_offset)) {
return false;
}
@@ -749,16 +772,22 @@ bool QuicStream::MaybeIncreaseHighestReceivedOffset(
}
void QuicStream::AddBytesSent(QuicByteCount bytes) {
- flow_controller_.AddBytesSent(bytes);
+ flow_controller_->AddBytesSent(bytes);
if (stream_contributes_to_connection_flow_control_) {
connection_flow_controller_->AddBytesSent(bytes);
}
}
void QuicStream::AddBytesConsumed(QuicByteCount bytes) {
+ if (type_ == CRYPTO) {
+ // A stream with type CRYPTO has no flow control, so there's nothing this
+ // function needs to do. This function still gets called by the
+ // QuicStreamSequencers used by QuicCryptoStream.
+ return;
+ }
// Only adjust stream level flow controller if still reading.
if (!read_side_closed_) {
- flow_controller_.AddBytesConsumed(bytes);
+ flow_controller_->AddBytesConsumed(bytes);
}
if (stream_contributes_to_connection_flow_control_) {
@@ -767,7 +796,7 @@ void QuicStream::AddBytesConsumed(QuicByteCount bytes) {
}
void QuicStream::UpdateSendWindowOffset(QuicStreamOffset new_window) {
- if (flow_controller_.UpdateSendWindowOffset(new_window)) {
+ if (flow_controller_->UpdateSendWindowOffset(new_window)) {
// Let session unblock this stream.
session_->MarkConnectionLevelWriteBlocked(id_);
}
@@ -920,7 +949,7 @@ void QuicStream::WriteBufferedData() {
bool fin = fin_buffered_;
// How much data flow control permits to be written.
- QuicByteCount send_window = flow_controller_.SendWindowSize();
+ QuicByteCount send_window = flow_controller_->SendWindowSize();
if (stream_contributes_to_connection_flow_control_) {
send_window =
std::min(send_window, connection_flow_controller_->SendWindowSize());
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 40bed1c19c9..80ee4e4a24a 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
@@ -30,6 +30,7 @@
#include "net/third_party/quiche/src/quic/core/session_notifier_interface.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_optional.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
@@ -73,6 +74,10 @@ class QUIC_EXPORT_PRIVATE PendingStream
// Returns the number of bytes read on this stream.
uint64_t stream_bytes_read() { return stream_bytes_read_; }
+ const QuicStreamSequencer* sequencer() const { return &sequencer_; }
+
+ void MarkConsumed(size_t num_bytes);
+
private:
friend class QuicStream;
@@ -121,7 +126,7 @@ class QUIC_EXPORT_PRIVATE QuicStream
QuicSession* session,
bool is_static,
StreamType type);
- QuicStream(PendingStream pending, StreamType type);
+ QuicStream(PendingStream pending, StreamType type, bool is_static);
QuicStream(const QuicStream&) = delete;
QuicStream& operator=(const QuicStream&) = delete;
@@ -222,7 +227,7 @@ class QUIC_EXPORT_PRIVATE QuicStream
int num_frames_received() const;
int num_duplicate_frames_received() const;
- QuicFlowController* flow_controller() { return &flow_controller_; }
+ QuicFlowController* flow_controller() { return &*flow_controller_; }
// Called when endpoint receives a frame which could increase the highest
// offset.
@@ -343,6 +348,9 @@ class QUIC_EXPORT_PRIVATE QuicStream
// Does not send a FIN. May cause the stream to be closed.
virtual void CloseWriteSide();
+ // Returns true if the stream is static.
+ 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
@@ -428,7 +436,7 @@ class QUIC_EXPORT_PRIVATE QuicStream
StreamType type,
uint64_t stream_bytes_read,
bool fin_received,
- QuicFlowController flow_controller,
+ QuicOptional<QuicFlowController> flow_controller,
QuicFlowController* connection_flow_controller);
// Subclasses and consumers should use reading_stopped.
@@ -499,7 +507,7 @@ class QUIC_EXPORT_PRIVATE QuicStream
// server or a client.
Perspective perspective_;
- QuicFlowController flow_controller_;
+ QuicOptional<QuicFlowController> flow_controller_;
// The connection level flow controller. Not owned.
QuicFlowController* connection_flow_controller_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc
index fb6e14b8957..2921268b5a2 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc
@@ -22,312 +22,341 @@ namespace quic {
QuicStreamIdManager::QuicStreamIdManager(
QuicSession* session,
- QuicStreamId next_outgoing_stream_id,
- QuicStreamId largest_peer_created_stream_id,
- QuicStreamId first_incoming_dynamic_stream_id,
- size_t max_allowed_outgoing_streams,
- size_t max_allowed_incoming_streams)
+ bool unidirectional,
+ QuicStreamCount max_allowed_outgoing_streams,
+ QuicStreamCount max_allowed_incoming_streams)
: session_(session),
- next_outgoing_stream_id_(next_outgoing_stream_id),
- largest_peer_created_stream_id_(largest_peer_created_stream_id),
- max_allowed_outgoing_stream_id_(0),
- actual_max_allowed_incoming_stream_id_(0),
- advertised_max_allowed_incoming_stream_id_(0),
- max_stream_id_window_(max_allowed_incoming_streams /
- kMaxStreamIdWindowDivisor),
- max_allowed_incoming_streams_(max_allowed_incoming_streams),
- first_incoming_dynamic_stream_id_(first_incoming_dynamic_stream_id),
- first_outgoing_dynamic_stream_id_(next_outgoing_stream_id) {
- available_incoming_streams_ = max_allowed_incoming_streams_;
- SetMaxOpenOutgoingStreams(max_allowed_outgoing_streams);
- SetMaxOpenIncomingStreams(max_allowed_incoming_streams);
+ unidirectional_(unidirectional),
+ outgoing_max_streams_(max_allowed_outgoing_streams),
+ next_outgoing_stream_id_(GetFirstOutgoingStreamId()),
+ outgoing_stream_count_(0),
+ outgoing_static_stream_count_(0),
+ using_default_max_streams_(true),
+ incoming_actual_max_streams_(max_allowed_incoming_streams),
+ // Advertised max starts at actual because it's communicated in the
+ // handshake.
+ incoming_advertised_max_streams_(max_allowed_incoming_streams),
+ incoming_initial_max_open_streams_(max_allowed_incoming_streams),
+ incoming_static_stream_count_(0),
+ incoming_stream_count_(0),
+ largest_peer_created_stream_id_(
+ QuicUtils::GetInvalidStreamId(transport_version())),
+ max_streams_window_(0) {
+ CalculateIncomingMaxStreamsWindow();
}
QuicStreamIdManager::~QuicStreamIdManager() {
- QUIC_LOG_IF(WARNING,
- session_->num_locally_closed_incoming_streams_highest_offset() >
- max_allowed_incoming_streams_)
- << "Surprisingly high number of locally closed peer initiated streams"
- "still waiting for final byte offset: "
- << session_->num_locally_closed_incoming_streams_highest_offset();
- QUIC_LOG_IF(WARNING,
- session_->GetNumLocallyClosedOutgoingStreamsHighestOffset() >
- max_allowed_outgoing_streams_)
- << "Surprisingly high number of locally closed self initiated streams"
- "still waiting for final byte offset: "
- << session_->GetNumLocallyClosedOutgoingStreamsHighestOffset();
}
-bool QuicStreamIdManager::OnMaxStreamIdFrame(
- const QuicMaxStreamIdFrame& frame) {
- DCHECK_EQ(QuicUtils::IsBidirectionalStreamId(frame.max_stream_id),
- QuicUtils::IsBidirectionalStreamId(next_outgoing_stream_id_));
- // Need to determine whether the stream id matches our client/server
- // perspective or not. If not, it's an error. If so, update appropriate
- // maxima.
- QUIC_CODE_COUNT_N(max_stream_id_received, 2, 2);
- // TODO(fkastenholz): this test needs to be broader to handle uni- and bi-
- // directional stream ids when that functionality is supported.
- if (IsIncomingStream(frame.max_stream_id)) {
- // TODO(fkastenholz): This, and following, closeConnection may
- // need modification when proper support for IETF CONNECTION
- // CLOSE is done.
- QUIC_CODE_COUNT(max_stream_id_bad_direction);
- session_->connection()->CloseConnection(
- QUIC_MAX_STREAM_ID_ERROR,
- "Received max stream ID with wrong initiator bit setting",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+bool QuicStreamIdManager::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
+ // Ensure that the frame has the correct directionality.
+ DCHECK_EQ(frame.unidirectional, unidirectional_);
+ QUIC_CODE_COUNT_N(quic_max_streams_received, 2, 2);
+ const QuicStreamCount current_outgoing_max_streams = outgoing_max_streams_;
+
+ // Set the limit to be exactly the stream count in the frame.
+ if (!ConfigureMaxOpenOutgoingStreams(frame.stream_count)) {
return false;
}
-
- // If a MAX_STREAM_ID advertises a stream ID that is smaller than previously
- // advertised, it is to be ignored.
- if (frame.max_stream_id < max_allowed_outgoing_stream_id_) {
- QUIC_CODE_COUNT(max_stream_id_ignored);
- return true;
+ // If we were at the previous limit and this MAX_STREAMS frame
+ // increased the limit, inform the application that new streams are
+ // available.
+ if (outgoing_stream_count_ == current_outgoing_max_streams &&
+ current_outgoing_max_streams < outgoing_max_streams_) {
+ session_->OnCanCreateNewOutgoingStream();
}
- max_allowed_outgoing_stream_id_ = frame.max_stream_id;
-
- // Outgoing stream limit has increased, tell the applications
- session_->OnCanCreateNewOutgoingStream();
-
return true;
}
-bool QuicStreamIdManager::OnStreamIdBlockedFrame(
- const QuicStreamIdBlockedFrame& frame) {
- DCHECK_EQ(QuicUtils::IsBidirectionalStreamId(frame.stream_id),
- QuicUtils::IsBidirectionalStreamId(next_outgoing_stream_id_));
- QUIC_CODE_COUNT_N(stream_id_blocked_received, 2, 2);
- QuicStreamId id = frame.stream_id;
- if (!IsIncomingStream(frame.stream_id)) {
- // Client/server mismatch, close the connection
- // TODO(fkastenholz): revise when proper IETF Connection Close support is
- // done.
- QUIC_CODE_COUNT(stream_id_blocked_bad_direction);
- session_->connection()->CloseConnection(
- QUIC_STREAM_ID_BLOCKED_ERROR,
- "Invalid stream ID directionality specified",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- return false;
- }
+// The peer sends a streams blocked frame when it can not open any more
+// streams because it has runs into the limit.
+bool QuicStreamIdManager::OnStreamsBlockedFrame(
+ const QuicStreamsBlockedFrame& frame) {
+ // Ensure that the frame has the correct directionality.
+ DCHECK_EQ(frame.unidirectional, unidirectional_);
+ QUIC_CODE_COUNT_N(quic_streams_blocked_received, 2, 2);
- if (id > advertised_max_allowed_incoming_stream_id_) {
+ if (frame.stream_count > incoming_advertised_max_streams_) {
// Peer thinks it can send more streams that we've told it.
// This is a protocol error.
// TODO(fkastenholz): revise when proper IETF Connection Close support is
// done.
- QUIC_CODE_COUNT(stream_id_blocked_id_too_big);
+ QUIC_CODE_COUNT(quic_streams_blocked_too_big);
session_->connection()->CloseConnection(
- QUIC_STREAM_ID_BLOCKED_ERROR, "Invalid stream ID specified",
+ QUIC_STREAMS_BLOCKED_ERROR, "Invalid stream count specified",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
}
- if (id < actual_max_allowed_incoming_stream_id_) {
- // Peer thinks it's blocked on an ID that is less than our current
- // max. Inform the peer of the correct stream ID.
- SendMaxStreamIdFrame();
+ if (frame.stream_count < incoming_actual_max_streams_) {
+ // Peer thinks it's blocked on a stream count that is less than our current
+ // max. Inform the peer of the correct stream count. Sending a MAX_STREAMS
+ // frame in this case is not controlled by the window.
+ SendMaxStreamsFrame();
+ }
+ QUIC_CODE_COUNT(quic_streams_blocked_id_correct);
+ return true;
+}
+
+// Used when configuration has been done and we have an initial
+// maximum stream count from the peer.
+bool QuicStreamIdManager::ConfigureMaxOpenOutgoingStreams(
+ size_t max_open_streams) {
+ if (using_default_max_streams_) {
+ // This is the first MAX_STREAMS/transport negotiation we've received. Treat
+ // this a bit differently than later ones. The difference is that
+ // outgoing_max_streams_ is currently an estimate. The MAX_STREAMS frame or
+ // transport negotiation is authoritative and can reduce
+ // outgoing_max_streams_ -- so long as outgoing_max_streams_ is not set to
+ // be less than the number of existing outgoing streams. If that happens,
+ // close the connection.
+ if (max_open_streams < outgoing_stream_count_) {
+ session_->connection()->CloseConnection(
+ QUIC_MAX_STREAMS_ERROR,
+ "Stream limit less than existing stream count",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ }
+ using_default_max_streams_ = false;
+ } else if (max_open_streams <= outgoing_max_streams_) {
+ // Is not the 1st MAX_STREAMS or negotiation.
+ // Only update the stream count if it would increase the limit.
+ // If it decreases the limit, or doesn't change it, then do not update.
+ // Note that this handles the case of receiving a count of 0 in the frame
return true;
}
- // The peer's notion of the maximum ID is correct,
- // there is nothing to do.
- QUIC_CODE_COUNT(stream_id_blocked_id_correct);
+
+ // This implementation only supports 32 bit Stream IDs, so limit max streams
+ // if it would exceed the max 32 bits can express.
+ outgoing_max_streams_ = std::min<size_t>(
+ max_open_streams,
+ QuicUtils::GetMaxStreamCount(unidirectional_, session_->perspective()));
return true;
}
-// TODO(fkastenholz): Many changes will be needed here:
-// -- Use IETF QUIC server/client-initiation sense
-// -- Support both BIDI and UNI streams.
-// -- can not change the max number of streams after config negotiation has
-// been done.
-void QuicStreamIdManager::SetMaxOpenOutgoingStreams(size_t max_streams) {
- max_allowed_outgoing_streams_ = max_streams;
- max_allowed_outgoing_stream_id_ =
- next_outgoing_stream_id_ + (max_streams - 1) * kV99StreamIdIncrement;
+void QuicStreamIdManager::SetMaxOpenOutgoingStreams(size_t max_open_streams) {
+ QUIC_BUG_IF(!using_default_max_streams_);
+ // TODO(fkastenholz): when static streams are removed from I-Quic, this
+ // should be revised to invoke ConfigureMaxOpen...
+ AdjustMaxOpenOutgoingStreams(max_open_streams);
}
-// TODO(fkastenholz): Many changes will be needed here:
-// -- can not change the max number of streams after config negotiation has
-// been done.
-// -- Currently uses the Google Client/server-initiation sense, needs to
-// be IETF.
-// -- Support both BIDI and UNI streams.
-// -- Convert calculation of the maximum ID from Google-QUIC semantics to IETF
-// QUIC semantics.
-void QuicStreamIdManager::SetMaxOpenIncomingStreams(size_t max_streams) {
- max_allowed_incoming_streams_ = max_streams;
- // The peer should always believe that it has the negotiated
- // number of stream ids available for use.
- available_incoming_streams_ = max_allowed_incoming_streams_;
-
- // the window is a fraction of the peer's notion of its stream-id space.
- max_stream_id_window_ =
- available_incoming_streams_ / kMaxStreamIdWindowDivisor;
- if (max_stream_id_window_ == 0) {
- max_stream_id_window_ = 1;
+// Adjust the outgoing stream limit - max_open_streams is the limit, not
+// including static streams. If the new stream limit wraps, will peg
+// the limit at the implementation max.
+// TODO(fkastenholz): AdjustMax is cognizant of the number of static streams and
+// sets the maximum to be max_streams + number_of_statics. This should be
+// removed from IETF QUIC when static streams are gone.
+void QuicStreamIdManager::AdjustMaxOpenOutgoingStreams(
+ size_t max_open_streams) {
+ if ((outgoing_static_stream_count_ + max_open_streams) < max_open_streams) {
+ // New limit causes us to wrap, set limit to be the implementation maximum.
+ ConfigureMaxOpenOutgoingStreams(
+ QuicUtils::GetMaxStreamCount(unidirectional_, perspective()));
+ return;
}
+ // Does not wrap, set limit to what is requested.
+ ConfigureMaxOpenOutgoingStreams(outgoing_static_stream_count_ +
+ max_open_streams);
+}
- actual_max_allowed_incoming_stream_id_ =
- first_incoming_dynamic_stream_id_ +
- (max_allowed_incoming_streams_ - 1) * kV99StreamIdIncrement;
- // To start, we can assume advertised and actual are the same.
- advertised_max_allowed_incoming_stream_id_ =
- actual_max_allowed_incoming_stream_id_;
+void QuicStreamIdManager::SetMaxOpenIncomingStreams(size_t max_open_streams) {
+ QuicStreamCount implementation_max =
+ QuicUtils::GetMaxStreamCount(unidirectional_, perspective());
+ QuicStreamCount new_max =
+ std::min(implementation_max,
+ static_cast<QuicStreamCount>(max_open_streams +
+ incoming_static_stream_count_));
+ if (new_max < max_open_streams) {
+ // wrapped around ...
+ new_max = implementation_max;
+ }
+ if (new_max < incoming_stream_count_) {
+ session_->connection()->CloseConnection(
+ QUIC_MAX_STREAMS_ERROR, "Stream limit less than existing stream count",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
+ incoming_actual_max_streams_ = new_max;
+ incoming_advertised_max_streams_ = new_max;
+ incoming_initial_max_open_streams_ =
+ std::min(max_open_streams, static_cast<size_t>(implementation_max));
+ CalculateIncomingMaxStreamsWindow();
}
-void QuicStreamIdManager::MaybeSendMaxStreamIdFrame() {
- if (available_incoming_streams_ > max_stream_id_window_) {
+void QuicStreamIdManager::MaybeSendMaxStreamsFrame() {
+ if ((incoming_advertised_max_streams_ - incoming_stream_count_) >
+ max_streams_window_) {
// window too large, no advertisement
return;
}
- // Calculate the number of streams that the peer will believe
- // it has. The "/kV99StreamIdIncrement" converts from stream-id-
- // values to number-of-stream-ids.
- available_incoming_streams_ += (actual_max_allowed_incoming_stream_id_ -
- advertised_max_allowed_incoming_stream_id_) /
- kV99StreamIdIncrement;
- SendMaxStreamIdFrame();
+ SendMaxStreamsFrame();
}
-void QuicStreamIdManager::SendMaxStreamIdFrame() {
- advertised_max_allowed_incoming_stream_id_ =
- actual_max_allowed_incoming_stream_id_;
- // And Advertise it.
- session_->SendMaxStreamId(advertised_max_allowed_incoming_stream_id_);
+void QuicStreamIdManager::SendMaxStreamsFrame() {
+ incoming_advertised_max_streams_ = incoming_actual_max_streams_;
+ session_->SendMaxStreams(incoming_advertised_max_streams_, unidirectional_);
}
void QuicStreamIdManager::OnStreamClosed(QuicStreamId stream_id) {
- DCHECK_EQ(QuicUtils::IsBidirectionalStreamId(stream_id),
- QuicUtils::IsBidirectionalStreamId(next_outgoing_stream_id_));
+ DCHECK_NE(QuicUtils::IsBidirectionalStreamId(stream_id), unidirectional_);
if (!IsIncomingStream(stream_id)) {
- // Nothing to do for outbound streams with respect to the
- // stream ID space management.
+ // Nothing to do for outgoing streams.
return;
}
- // If the stream is inbound, we can increase the stream ID limit and maybe
- // advertise the new limit to the peer.
- if (actual_max_allowed_incoming_stream_id_ >=
- (kMaxQuicStreamId - kV99StreamIdIncrement)) {
+ // If the stream is inbound, we can increase the actual stream limit and maybe
+ // advertise the new limit to the peer. Have to check to make sure that we do
+ // not exceed the maximum.
+ if (incoming_actual_max_streams_ ==
+ QuicUtils::GetMaxStreamCount(unidirectional_, perspective())) {
// Reached the maximum stream id value that the implementation
// supports. Nothing can be done here.
return;
}
- actual_max_allowed_incoming_stream_id_ += kV99StreamIdIncrement;
- MaybeSendMaxStreamIdFrame();
+ // One stream closed ... another can be opened.
+ incoming_actual_max_streams_++;
+ MaybeSendMaxStreamsFrame();
}
QuicStreamId QuicStreamIdManager::GetNextOutgoingStreamId() {
- QUIC_BUG_IF(next_outgoing_stream_id_ > max_allowed_outgoing_stream_id_)
- << "Attempt allocate a new outgoing stream ID would exceed the limit";
+ // TODO(fkastenholz): Should we close the connection?
+ QUIC_BUG_IF(outgoing_stream_count_ >= outgoing_max_streams_)
+ << "Attempt to allocate a new outgoing stream that would exceed the "
+ "limit";
QuicStreamId id = next_outgoing_stream_id_;
- next_outgoing_stream_id_ += kV99StreamIdIncrement;
+ next_outgoing_stream_id_ += QuicUtils::StreamIdDelta(transport_version());
+ outgoing_stream_count_++;
return id;
}
bool QuicStreamIdManager::CanOpenNextOutgoingStream() {
- DCHECK_EQ(QUIC_VERSION_99, session_->connection()->transport_version());
- if (next_outgoing_stream_id_ > max_allowed_outgoing_stream_id_) {
- // Next stream ID would exceed the limit, need to inform the peer.
- session_->SendStreamIdBlocked(max_allowed_outgoing_stream_id_);
- QUIC_CODE_COUNT(reached_outgoing_stream_id_limit);
- return false;
+ DCHECK_EQ(QUIC_VERSION_99, transport_version());
+ if (outgoing_stream_count_ < outgoing_max_streams_) {
+ return true;
}
- return true;
+ // Next stream ID would exceed the limit, need to inform the peer.
+ session_->SendStreamsBlocked(outgoing_max_streams_, unidirectional_);
+ QUIC_CODE_COUNT(quic_reached_outgoing_stream_id_limit);
+ return false;
}
-void QuicStreamIdManager::RegisterStaticStream(QuicStreamId stream_id) {
- DCHECK_EQ(QuicUtils::IsBidirectionalStreamId(stream_id),
- QuicUtils::IsBidirectionalStreamId(next_outgoing_stream_id_));
- QuicStreamId first_dynamic_stream_id = stream_id + kV99StreamIdIncrement;
-
- if (IsIncomingStream(first_dynamic_stream_id)) {
+bool QuicStreamIdManager::RegisterStaticStream(QuicStreamId stream_id) {
+ DCHECK_NE(QuicUtils::IsBidirectionalStreamId(stream_id), unidirectional_);
+ if (IsIncomingStream(stream_id)) {
// This code is predicated on static stream ids being allocated densely, in
// order, and starting with the first stream allowed. QUIC_BUG if this is
// not so.
- QUIC_BUG_IF(stream_id > first_incoming_dynamic_stream_id_)
- << "Error in incoming static stream allocation, expected to allocate "
- << first_incoming_dynamic_stream_id_ << " got " << stream_id;
-
// This is a stream id for a stream that is started by the peer, deal with
// the incoming stream ids. Increase the floor and adjust everything
// accordingly.
- if (stream_id == first_incoming_dynamic_stream_id_) {
- actual_max_allowed_incoming_stream_id_ += kV99StreamIdIncrement;
- first_incoming_dynamic_stream_id_ = first_dynamic_stream_id;
+
+ QUIC_BUG_IF(incoming_actual_max_streams_ >
+ QuicUtils::GetMaxStreamCount(unidirectional_, perspective()));
+
+ // If we have reached the limit on stream creation, do not create
+ // the static stream; return false.
+ if (incoming_stream_count_ >=
+ QuicUtils::GetMaxStreamCount(unidirectional_, perspective())) {
+ return false;
}
- return;
+
+ if (incoming_actual_max_streams_ <
+ QuicUtils::GetMaxStreamCount(unidirectional_, perspective())) {
+ incoming_actual_max_streams_++;
+ }
+ if (incoming_advertised_max_streams_ <
+ QuicUtils::GetMaxStreamCount(unidirectional_, perspective())) {
+ incoming_advertised_max_streams_++;
+ }
+ incoming_stream_count_++;
+ incoming_static_stream_count_++;
+ return true;
}
- // This code is predicated on static stream ids being allocated densely, in
- // order, and starting with the first stream allowed. QUIC_BUG if this is
- // not so.
- QUIC_BUG_IF(stream_id > first_outgoing_dynamic_stream_id_)
- << "Error in outgoing static stream allocation, expected to allocate "
- << first_outgoing_dynamic_stream_id_ << " got " << stream_id;
- // This is a stream id for a stream that is started by this node; deal with
- // the outgoing stream ids. Increase the floor and adjust everything
- // accordingly.
- if (stream_id == first_outgoing_dynamic_stream_id_) {
- max_allowed_outgoing_stream_id_ += kV99StreamIdIncrement;
- first_outgoing_dynamic_stream_id_ = first_dynamic_stream_id;
+ QUIC_BUG_IF(!using_default_max_streams_)
+ << "Attempted to allocate static stream (id " << stream_id
+ << ") after receiving a MAX_STREAMS frame";
+
+ // If we have reached the limit on stream creation, do not create
+ // the static stream; return false.
+ if (outgoing_max_streams_ >=
+ QuicUtils::GetMaxStreamCount(unidirectional_, perspective())) {
+ return false;
}
+
+ // Increase the outgoing_max_streams_ limit to reflect the semantic that
+ // outgoing_max_streams_ was inialized to a "maximum request/response" count
+ // and only becomes a maximum stream count when we receive the first
+ // MAX_STREAMS.
+ outgoing_max_streams_++;
+ outgoing_static_stream_count_++;
+ return true;
}
+// Stream_id is the id of a new incoming stream. Check if it can be
+// created (doesn't violate limits, etc).
bool QuicStreamIdManager::MaybeIncreaseLargestPeerStreamId(
const QuicStreamId stream_id) {
- DCHECK_EQ(QuicUtils::IsBidirectionalStreamId(stream_id),
- QuicUtils::IsBidirectionalStreamId(next_outgoing_stream_id_));
+ DCHECK_NE(QuicUtils::IsBidirectionalStreamId(stream_id), unidirectional_);
+
available_streams_.erase(stream_id);
if (largest_peer_created_stream_id_ !=
- QuicUtils::GetInvalidStreamId(
- session_->connection()->transport_version()) &&
+ QuicUtils::GetInvalidStreamId(transport_version()) &&
stream_id <= largest_peer_created_stream_id_) {
return true;
}
- if (stream_id > actual_max_allowed_incoming_stream_id_) {
- // Desired stream ID is larger than the limit, do not increase.
+ QuicStreamCount stream_count_increment;
+ if (largest_peer_created_stream_id_ !=
+ QuicUtils::GetInvalidStreamId(transport_version())) {
+ stream_count_increment = (stream_id - largest_peer_created_stream_id_) /
+ QuicUtils::StreamIdDelta(transport_version());
+ } else {
+ // Largest_peer_created_stream_id is the invalid ID,
+ // which means that the peer has not created any stream IDs.
+ // The "+1" is because the first stream ID has not yet
+ // been used. For example, if the FirstIncoming ID is 1
+ // and stream_id is 1, then we want the increment to be 1.
+ stream_count_increment = ((stream_id - GetFirstIncomingStreamId()) /
+ QuicUtils::StreamIdDelta(transport_version())) +
+ 1;
+ }
+
+ // If already at, or over, the limit, close the connection/etc.
+ if (((incoming_stream_count_ + stream_count_increment) >
+ incoming_advertised_max_streams_) ||
+ ((incoming_stream_count_ + stream_count_increment) <
+ incoming_stream_count_)) {
+ // This stream would exceed the limit. do not increase.
QUIC_DLOG(INFO) << ENDPOINT
<< "Failed to create a new incoming stream with id:"
- << stream_id << ". Maximum allowed stream id is "
- << actual_max_allowed_incoming_stream_id_ << ".";
+ << stream_id << ", reaching MAX_STREAMS limit: "
+ << incoming_advertised_max_streams_ << ".";
session_->connection()->CloseConnection(
QUIC_INVALID_STREAM_ID,
- QuicStrCat("Stream id ", stream_id, " above ",
- actual_max_allowed_incoming_stream_id_),
+ QuicStrCat("Stream id ", stream_id, " would exceed stream count limit ",
+ incoming_advertised_max_streams_),
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
}
- available_incoming_streams_--;
-
- QuicStreamId id = largest_peer_created_stream_id_ + kV99StreamIdIncrement;
- if (largest_peer_created_stream_id_ ==
- QuicUtils::GetInvalidStreamId(
- session_->connection()->transport_version())) {
- // Adjust id based on perspective and whether stream_id is bidirectional or
- // unidirectional.
- if (QuicUtils::IsBidirectionalStreamId(stream_id)) {
- // This should only happen on client side because server bidirectional
- // stream ID manager's largest_peer_created_stream_id_ is initialized to
- // the crypto stream ID.
- DCHECK_EQ(Perspective::IS_CLIENT, session_->perspective());
- id = 1;
- } else {
- id = session_->perspective() == Perspective::IS_SERVER ? 2 : 3;
- }
+ QuicStreamId id = GetFirstIncomingStreamId();
+ if (largest_peer_created_stream_id_ !=
+ QuicUtils::GetInvalidStreamId(transport_version())) {
+ id = largest_peer_created_stream_id_ +
+ QuicUtils::StreamIdDelta(transport_version());
}
- for (; id < stream_id; id += kV99StreamIdIncrement) {
+
+ for (; id < stream_id; id += QuicUtils::StreamIdDelta(transport_version())) {
available_streams_.insert(id);
}
+ incoming_stream_count_ += stream_count_increment;
largest_peer_created_stream_id_ = stream_id;
return true;
}
bool QuicStreamIdManager::IsAvailableStream(QuicStreamId id) const {
- DCHECK_EQ(QuicUtils::IsBidirectionalStreamId(id),
- QuicUtils::IsBidirectionalStreamId(next_outgoing_stream_id_));
+ DCHECK_NE(QuicUtils::IsBidirectionalStreamId(id), unidirectional_);
if (!IsIncomingStream(id)) {
// Stream IDs under next_ougoing_stream_id_ are either open or previously
// open but now closed.
@@ -335,17 +364,57 @@ bool QuicStreamIdManager::IsAvailableStream(QuicStreamId id) const {
}
// For peer created streams, we also need to consider available streams.
return largest_peer_created_stream_id_ ==
- QuicUtils::GetInvalidStreamId(
- session_->connection()->transport_version()) ||
+ QuicUtils::GetInvalidStreamId(transport_version()) ||
id > largest_peer_created_stream_id_ ||
QuicContainsKey(available_streams_, id);
}
bool QuicStreamIdManager::IsIncomingStream(QuicStreamId id) const {
- DCHECK_EQ(QuicUtils::IsBidirectionalStreamId(id),
- QuicUtils::IsBidirectionalStreamId(next_outgoing_stream_id_));
- return id % kV99StreamIdIncrement !=
- next_outgoing_stream_id_ % kV99StreamIdIncrement;
+ DCHECK_NE(QuicUtils::IsBidirectionalStreamId(id), unidirectional_);
+ // The 0x1 bit in the stream id indicates whether the stream id is
+ // server- or client- initiated. Next_OUTGOING_stream_id_ has that bit
+ // set based on whether this node is a server or client. Thus, if the stream
+ // id in question has the 0x1 bit set opposite of next_OUTGOING_stream_id_,
+ // then that stream id is incoming -- it is for streams initiated by the peer.
+ return (id & 0x1) != (next_outgoing_stream_id_ & 0x1);
+}
+
+QuicStreamId QuicStreamIdManager::GetFirstOutgoingStreamId() const {
+ return (unidirectional_) ? QuicUtils::GetFirstUnidirectionalStreamId(
+ transport_version(), perspective())
+ : QuicUtils::GetFirstBidirectionalStreamId(
+ transport_version(), perspective());
+}
+
+QuicStreamId QuicStreamIdManager::GetFirstIncomingStreamId() const {
+ return (unidirectional_) ? QuicUtils::GetFirstUnidirectionalStreamId(
+ transport_version(), peer_perspective())
+ : QuicUtils::GetFirstBidirectionalStreamId(
+ transport_version(), peer_perspective());
+}
+
+Perspective QuicStreamIdManager::perspective() const {
+ return session_->perspective();
+}
+
+Perspective QuicStreamIdManager::peer_perspective() const {
+ return (perspective() == Perspective::IS_SERVER) ? Perspective::IS_CLIENT
+ : Perspective::IS_SERVER;
+}
+
+QuicTransportVersion QuicStreamIdManager::transport_version() const {
+ return session_->connection()->transport_version();
+}
+
+size_t QuicStreamIdManager::available_incoming_streams() {
+ return incoming_advertised_max_streams_ - incoming_stream_count_;
+}
+
+void QuicStreamIdManager::CalculateIncomingMaxStreamsWindow() {
+ max_streams_window_ = incoming_actual_max_streams_ / kMaxStreamsWindowDivisor;
+ if (max_streams_window_ == 0) {
+ max_streams_window_ = 1;
+ }
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.h b/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.h
index 6fd75fb4168..42c7d1a260d 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
@@ -6,6 +6,7 @@
#include "net/third_party/quiche/src/quic/core/frames/quic_frame.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_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
@@ -23,21 +24,17 @@ class QuicSession;
const QuicStreamId kV99StreamIdIncrement = 4;
// This constant controls the size of the window when deciding whether
-// to generate a MAX STREAM ID frame or not. See the discussion of the
+// to generate a MAX_STREAMS frame or not. See the discussion of the
// window, below, for more details.
-const int kMaxStreamIdWindowDivisor = 2;
+const int kMaxStreamsWindowDivisor = 2;
// This class manages the stream ids for Version 99/IETF QUIC.
-// TODO(fkastenholz): Expand to support bi- and uni-directional stream ids
-// TODO(fkastenholz): Roll in pre-version-99 management
class QUIC_EXPORT_PRIVATE QuicStreamIdManager {
public:
QuicStreamIdManager(QuicSession* session,
- QuicStreamId next_outgoing_stream_id,
- QuicStreamId largest_peer_created_stream_id,
- QuicStreamId first_incoming_dynamic_stream_id,
- size_t max_allowed_outgoing_streams,
- size_t max_allowed_incoming_streams);
+ bool unidirectional,
+ QuicStreamCount max_allowed_outgoing_streams,
+ QuicStreamCount max_allowed_incoming_streams);
~QuicStreamIdManager();
@@ -45,68 +42,85 @@ class QUIC_EXPORT_PRIVATE QuicStreamIdManager {
// of the stream ID manager.
std::string DebugString() const {
return QuicStrCat(
- " { max_allowed_outgoing_stream_id: ", max_allowed_outgoing_stream_id_,
- ", actual_max_allowed_incoming_stream_id_: ",
- actual_max_allowed_incoming_stream_id_,
- ", advertised_max_allowed_incoming_stream_id_: ",
- advertised_max_allowed_incoming_stream_id_,
- ", max_stream_id_window_: ", max_stream_id_window_,
- ", max_allowed_outgoing_streams_: ", max_allowed_outgoing_streams_,
- ", max_allowed_incoming_streams_: ", max_allowed_incoming_streams_,
- ", available_incoming_streams_: ", available_incoming_streams_,
- ", first_incoming_dynamic_stream_id_: ",
- first_incoming_dynamic_stream_id_,
- ", first_outgoing_dynamic_stream_id_: ",
- first_outgoing_dynamic_stream_id_, " }");
+ " { unidirectional_: ", unidirectional_,
+ ", perspective: ", perspective(),
+ ", outgoing_max_streams_: ", outgoing_max_streams_,
+ ", next_outgoing_stream_id_: ", next_outgoing_stream_id_,
+ ", outgoing_stream_count_: ", outgoing_stream_count_,
+ ", outgoing_static_stream_count_: ", outgoing_static_stream_count_,
+ ", using_default_max_streams_: ", using_default_max_streams_,
+ ", incoming_actual_max_streams_: ", incoming_actual_max_streams_,
+ ", incoming_advertised_max_streams_: ",
+ incoming_advertised_max_streams_,
+ ", incoming_static_stream_count_: ", incoming_static_stream_count_,
+ ", incoming_stream_count_: ", incoming_stream_count_,
+ ", available_streams_.size(): ", available_streams_.size(),
+ ", largest_peer_created_stream_id_: ", largest_peer_created_stream_id_,
+ ", max_streams_window_: ", max_streams_window_, " }");
}
- // Processes the MAX STREAM ID frame, invoked from
- // QuicSession::OnMaxStreamIdFrame. It has the same semantics as the
+ // Processes the MAX_STREAMS frame, invoked from
+ // QuicSession::OnMaxStreamsFrame. It has the same semantics as the
// QuicFramerVisitorInterface, returning true if the framer should continue
// processing the packet, false if not.
- bool OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame);
+ bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame);
- // Processes the STREAM ID BLOCKED frame, invoked from
- // QuicSession::OnStreamIdBlockedFrame. It has the same semantics as the
+ // Processes the STREAMS_BLOCKED frame, invoked from
+ // QuicSession::OnStreamsBlockedFrame. It has the same semantics as the
// QuicFramerVisitorInterface, returning true if the framer should continue
// processing the packet, false if not.
- bool OnStreamIdBlockedFrame(const QuicStreamIdBlockedFrame& frame);
+ bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame);
- // Indicates whether the next outgoing stream ID can be allocated or not. The
- // test is whether it will exceed the maximum-stream-id or not.
+ // Indicates whether the next outgoing stream ID can be allocated or not.
bool CanOpenNextOutgoingStream();
- // Generate and send a MAX_STREAM_ID frame.
- void SendMaxStreamIdFrame();
+ // Generate and send a MAX_STREAMS frame.
+ void SendMaxStreamsFrame();
- // Invoked to deal with releasing a stream ID.
+ // Invoked to deal with releasing a stream. Does nothing if the stream is
+ // outgoing. If the stream is incoming, the number of streams that the peer
+ // can open will be updated and a MAX_STREAMS frame, informing the peer of
+ // the additional streams, may be sent.
void OnStreamClosed(QuicStreamId stream_id);
- // Returns the next outgoing stream id. If it fails (due to running into the
- // max_allowed_outgoing_stream_id limit) then it returns an invalid stream id.
+ // Returns the next outgoing stream id. Applications must call
+ // CanOpenNextOutgoingStream() first. A QUIC_BUG is logged if this method
+ // allocates a stream ID past the peer specified limit.
QuicStreamId GetNextOutgoingStreamId();
- // Initialize the maximum allowed incoming stream id and number of streams.
- void SetMaxOpenIncomingStreams(size_t max_streams);
-
- // Initialize the maximum allowed outgoing stream id, number of streams, and
- // MAX_STREAM_ID advertisement window.
- void SetMaxOpenOutgoingStreams(size_t max_streams);
+ // Set the outgoing stream limits to be |max_open_streams| plus the number
+ // of static streams that have been opened. For outgoing and incoming,
+ // respectively.
+ // SetMaxOpenOutgoingStreams will QUIC_BUG if it is called after
+ // a MAX_STREAMS frame has been received.
+ // TODO(fkastenholz): When static streams disappear, these should be removed.
+ void SetMaxOpenOutgoingStreams(size_t max_open_streams);
+ void SetMaxOpenIncomingStreams(size_t max_open_streams);
+
+ // Adjust the outgoing stream limit - max_open_streams is the limit, not
+ // including static streams. Does not QUIC_BUG if it is called _after_
+ // receiving a MAX_STREAMS.
+ void AdjustMaxOpenOutgoingStreams(size_t max_open_streams);
+
+ // Sets the maximum number of outgoing streams to max_open_streams.
+ // Used when configuration has been done and we have an initial
+ // maximum stream count from the peer. Note that if the stream count is such
+ // that it would result in stream ID values that are greater than the
+ // implementation limit, it pegs the count at the implementation limit.
+ bool ConfigureMaxOpenOutgoingStreams(size_t max_open_streams);
// Register a new stream as a static stream. This is used so that the
- // advertised maximum stream ID can be calculated based on the start of the
+ // advertised MAX STREAMS can be calculated based on the start of the
// dynamic stream space. This method will take any stream ID, one that either
// this node or the peer will initiate.
- void RegisterStaticStream(QuicStreamId stream_id);
-
- // Check that an incoming stream id is valid -- is below the maximum allowed
- // stream ID. Note that this method uses the actual maximum, not the most
- // recently advertised maximum this helps preserve the Google-QUIC semantic
- // that we actually care about the number of open streams, not the maximum
- // stream ID. Returns true if the stream ID is valid. If the stream ID fails
- // the test, will close the connection (per the protocol specification) and
- // return false. This method also maintains state with regard to the number of
- // streams that the peer can open (used for generating MAX_STREAM_ID frames).
+ // Returns false if this fails because the new static stream would cause the
+ // stream limit to be exceeded.
+ bool RegisterStaticStream(QuicStreamId stream_id);
+
+ // Checks if the incoming stream ID exceeds the MAX_STREAMS limit. If the
+ // limit is exceeded, closes the connection and returns false. Uses the
+ // actual maximium, not the most recently advertised value, in order to
+ // enforce the Google-QUIC number of open streams behavior.
// This method should be called exactly once for each incoming stream
// creation.
bool MaybeIncreaseLargestPeerStreamId(const QuicStreamId stream_id);
@@ -117,122 +131,145 @@ class QUIC_EXPORT_PRIVATE QuicStreamIdManager {
// Return true if given stream is peer initiated.
bool IsIncomingStream(QuicStreamId id) const;
- size_t max_allowed_outgoing_streams() const {
- return max_allowed_outgoing_streams_;
- }
- size_t max_allowed_incoming_streams() const {
- return max_allowed_incoming_streams_;
- }
- QuicStreamId max_allowed_outgoing_stream_id() const {
- return max_allowed_outgoing_stream_id_;
+ size_t outgoing_static_stream_count() const {
+ return outgoing_static_stream_count_;
}
- QuicStreamId advertised_max_allowed_incoming_stream_id() const {
- return advertised_max_allowed_incoming_stream_id_;
- }
- QuicStreamId actual_max_allowed_incoming_stream_id() const {
- return actual_max_allowed_incoming_stream_id_;
+
+ size_t incoming_initial_max_open_streams() const {
+ return incoming_initial_max_open_streams_;
}
- QuicStreamId max_stream_id_window() const { return max_stream_id_window_; }
+
+ QuicStreamCount max_streams_window() const { return max_streams_window_; }
QuicStreamId next_outgoing_stream_id() const {
return next_outgoing_stream_id_;
}
- QuicStreamId first_incoming_dynamic_stream_id() {
- return first_incoming_dynamic_stream_id_;
- }
- QuicStreamId first_outgoing_dynamic_stream_id() {
- return first_outgoing_dynamic_stream_id_;
- }
- size_t available_incoming_streams() { return available_incoming_streams_; }
-
- void set_max_allowed_incoming_streams(size_t stream_count) {
- max_allowed_incoming_streams_ = stream_count;
- }
+ // Number of streams that the peer believes that it can still create.
+ size_t available_incoming_streams();
void set_largest_peer_created_stream_id(
QuicStreamId largest_peer_created_stream_id) {
largest_peer_created_stream_id_ = largest_peer_created_stream_id;
}
+ // 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.
+ // The advertised incoming amount should never be more than the actual
+ // incoming one.
+ QuicStreamCount outgoing_max_streams() const { return outgoing_max_streams_; }
+ QuicStreamCount incoming_actual_max_streams() const {
+ return incoming_actual_max_streams_;
+ }
+ QuicStreamCount incoming_advertised_max_streams() const {
+ return incoming_advertised_max_streams_;
+ }
+ // Number of streams that have been opened (including those that have been
+ // opened and then closed. Must never exceed outgoing_max_streams
+ QuicStreamCount outgoing_stream_count() { return outgoing_stream_count_; }
+
+ // Perspective (CLIENT/SERVER) of this node and the peer, respectively.
+ Perspective perspective() const;
+ Perspective peer_perspective() const;
+
+ QuicTransportVersion transport_version() const;
+
private:
friend class test::QuicSessionPeer;
friend class test::QuicStreamIdManagerPeer;
- // Check whether the MAX_STREAM_ID window has opened up enough and, if so,
- // generate and send a MAX_STREAM_ID frame.
- void MaybeSendMaxStreamIdFrame();
+ // Check whether the MAX_STREAMS window has opened up enough and, if so,
+ // generate and send a MAX_STREAMS frame.
+ void MaybeSendMaxStreamsFrame();
+
+ // Get what should be the first incoming/outgoing stream ID that
+ // this stream id manager will manage, taking into account directionality and
+ // client/server perspective.
+ QuicStreamId GetFirstOutgoingStreamId() const;
+ QuicStreamId GetFirstIncomingStreamId() const;
+
+ void CalculateIncomingMaxStreamsWindow();
// Back reference to the session containing this Stream ID Manager.
// needed to access various session methods, such as perspective()
QuicSession* session_;
+ // Whether this stream id manager is for unidrectional (true) or bidirectional
+ // (false) streams.
+ bool unidirectional_;
+
+ // This is the number of streams that this node can initiate.
+ // This limit applies to both static and dynamic streams - the total
+ // of the two can not exceed this count.
+ // This limit is:
+ // - Initiated to a value specified in the constructor
+ // - May be updated when the config is received.
+ // - Is updated whenever a MAX STREAMS frame is received.
+ QuicStreamCount outgoing_max_streams_;
+
// The ID to use for the next outgoing stream.
QuicStreamId next_outgoing_stream_id_;
+ // The number of outgoing streams that have ever been opened, including those
+ // that have been closed. This number must never be larger than
+ // outgoing_max_streams_.
+ QuicStreamCount outgoing_stream_count_;
+
+ // Number of outgoing static streams created.
+ // TODO(fkastenholz): Remove when static streams no longer supported for IETF
+ // QUIC.
+ QuicStreamCount outgoing_static_stream_count_;
+
+ // Set to true while the default (from the constructor) outgoing stream limit
+ // is in use. It is set to false when either a MAX STREAMS frame is received
+ // or the transport negotiation completes and sets the stream limit (this is
+ // equivalent to a MAX_STREAMS frame).
+ // Necessary because outgoing_max_streams_ is a "best guess"
+ // until we receive an authoritative value from the peer.
+ // outgoing_max_streams_ is initialized in the constructor
+ // to some hard-coded value, which may or may not be consistent
+ // with what the peer wants. Furthermore, as we create outgoing
+ // static streams, the cap raises as static streams get inserted
+ // "beneath" the dynamic streams because, prior to receiving
+ // a MAX_STREAMS, the values setting the limit are interpreted
+ // as "number of request/responses" that can be created. Once
+ // a MAX_STREAMS is received, it becomes a hard limit.
+ bool using_default_max_streams_;
+
+ // FOR INCOMING STREAMS
+
+ // The maximum number of streams that can be opened by the peer.
+ QuicStreamCount incoming_actual_max_streams_;
+ QuicStreamCount incoming_advertised_max_streams_;
+
+ // Initial maximum on the number of open streams allowed.
+ QuicStreamCount incoming_initial_max_open_streams_;
+
+ // Number of outgoing static streams created.
+ // TODO(fkastenholz): Remove when static streams no longer supported for IETF
+ // QUIC.
+ QuicStreamCount incoming_static_stream_count_;
+
+ // This is the number of streams that have been created -- some are still
+ // open, the others have been closed. It is the number that is compared
+ // against MAX_STREAMS when deciding whether to accept a new stream or not.
+ QuicStreamCount incoming_stream_count_;
+
// Set of stream ids that are less than the largest stream id that has been
// received, but are nonetheless available to be created.
QuicUnorderedSet<QuicStreamId> available_streams_;
QuicStreamId largest_peer_created_stream_id_;
- // The maximum stream ID value that we can use. This is initialized based on,
- // first, the default number of open streams we can do, updated per the number
- // of streams we receive in the transport parameters, and then finally is
- // modified whenever a MAX_STREAM_ID frame is received from the peer.
- QuicStreamId max_allowed_outgoing_stream_id_;
-
- // Unlike for streams this node initiates, for incoming streams, there are two
- // maxima; the actual maximum which is the limit the peer must obey and the
- // maximum that was most recently advertised to the peer in a MAX_STREAM_ID
- // frame.
- //
- // The advertised maximum is never larger than the actual maximum. The actual
- // maximum increases whenever an incoming stream is closed. The advertised
- // maximum increases (to the actual maximum) whenever a MAX_STREAM_ID is sent.
- //
- // The peer is granted some leeway, incoming streams are accepted as long as
- // their stream id is not greater than the actual maximum. The protocol
- // specifies that the advertised maximum is the limit. This implmentation uses
- // the actual maximum in order to support Google-QUIC semantics, where it's
- // the number of open streams, not their ID number, that is the real limit.
- QuicStreamId actual_max_allowed_incoming_stream_id_;
- QuicStreamId advertised_max_allowed_incoming_stream_id_;
-
- // max_stream_id_window_ is set to max_allowed_outgoing_streams_ / 2
- // (half of the number of streams that are allowed). The local node
- // does not send a MAX_STREAM_ID frame to the peer until the local node
- // believes that the peer can open fewer than |max_stream_id_window_|
- // streams. When that is so, the local node sends a MAX_STREAM_ID every time
- // an inbound stream is closed.
- QuicStreamId max_stream_id_window_;
-
- // Maximum number of outgoing and incoming streams that are allowed to be
- // concurrently opened. Initialized as part of configuration.
- size_t max_allowed_outgoing_streams_;
- size_t max_allowed_incoming_streams_;
-
- // Keep track of the first dynamic stream id (which is the largest static
- // stream id plus one id). For Google QUIC, static streams are not counted
- // against the stream count limit. When the number of static streams
- // increases, the maximum stream id has to increase by a corresponding amount.
- // These are used as floors from which the relevant maximum is
- // calculated. Keeping the "first dynamic" rather than the "last static" has
- // some implementation advantages.
- QuicStreamId first_incoming_dynamic_stream_id_;
- QuicStreamId first_outgoing_dynamic_stream_id_;
-
- // Number of streams that that this node believes that the
- // peer can open. It is initialized to the same value as
- // max_allowed_incoming_streams_. It is decremented every
- // time a new incoming stream is detected. A MAX_STREAM_ID
- // is sent whenver a stream closes and this counter is less
- // than the window. When that happens, it is incremented by
- // the number of streams we make available (the actual max
- // stream ID - the most recently advertised one)
- size_t available_incoming_streams_;
+ // When incoming streams close the local node sends MAX_STREAMS frames. It
+ // does so only when the peer can open fewer than |max_stream_id_window_|
+ // streams. That is, when |incoming_actual_max_streams_| -
+ // |incoming_advertised_max_streams_| is less than the window.
+ // max_streams_window_ is set to 1/2 of the initial number of incoming streams
+ // that are allowed (as set in the constructor).
+ QuicStreamId max_streams_window_;
};
-
} // namespace quic
#endif // QUICHE_QUIC_CORE_QUIC_STREAM_ID_MANAGER_H_
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 3d0c06c2eb1..79c484525d3 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
@@ -118,10 +118,10 @@ class QuicStreamIdManagerTestBase : public QuicTestWithParam<bool> {
connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
session_ = QuicMakeUnique<TestQuicSession>(connection_);
stream_id_manager_ =
- GetParam() ? QuicSessionPeer::v99_bidirectional_stream_id_manager(
- session_.get())
- : QuicSessionPeer::v99_unidirectional_stream_id_manager(
- session_.get());
+ IsBidi() ? QuicSessionPeer::v99_bidirectional_stream_id_manager(
+ session_.get())
+ : QuicSessionPeer::v99_unidirectional_stream_id_manager(
+ session_.get());
}
QuicTransportVersion transport_version() const {
@@ -154,6 +154,27 @@ class QuicStreamIdManagerTestBase : public QuicTestWithParam<bool> {
kV99StreamIdIncrement * n;
}
+ QuicStreamId StreamCountToId(QuicStreamCount stream_count,
+ Perspective perspective) {
+ // Calculate and build up stream ID rather than use
+ // GetFirst... because the tests that rely on this method
+ // needs to do the stream count where #1 is 0/1/2/3, and not
+ // take into account that stream 0 is special.
+ QuicStreamId id =
+ ((stream_count - 1) * QuicUtils::StreamIdDelta(QUIC_VERSION_99));
+ if (IsUnidi()) {
+ id |= 0x2;
+ }
+ if (perspective == Perspective::IS_SERVER) {
+ id |= 0x1;
+ }
+ return id;
+ }
+
+ // GetParam returns true if the test is for bidirectional streams
+ bool IsUnidi() { return GetParam() ? false : true; }
+ bool IsBidi() { return GetParam(); }
+
MockQuicConnectionHelper helper_;
MockAlarmFactory alarm_factory_;
StrictMock<MockQuicConnection>* connection_;
@@ -178,128 +199,154 @@ INSTANTIATE_TEST_SUITE_P(Tests, QuicStreamIdManagerTestClient, testing::Bool());
TEST_P(QuicStreamIdManagerTestClient, StreamIdManagerClientInitialization) {
// These fields are inited via the QuicSession constructor to default
// values defined as a constant.
+ // If bidi, Crypto stream default created at start up, it is one
+ // more stream to account for since initialization is "number of
+ // request/responses" & crypto is added in to that, not streams.
+ size_t extra_stream_count = 0;
+ if (GetParam() && !QuicVersionUsesCryptoFrames(transport_version())) {
+ extra_stream_count = 1;
+ }
+ EXPECT_EQ(kDefaultMaxStreamsPerConnection + extra_stream_count,
+ stream_id_manager_->outgoing_max_streams());
+ // Test is predicated on having 1 static stream going if bidi, 0 if not...)
+ EXPECT_EQ(extra_stream_count,
+ stream_id_manager_->outgoing_static_stream_count());
+
+ EXPECT_EQ(kDefaultMaxStreamsPerConnection,
+ stream_id_manager_->incoming_actual_max_streams());
EXPECT_EQ(kDefaultMaxStreamsPerConnection,
- stream_id_manager_->max_allowed_incoming_streams());
+ stream_id_manager_->incoming_advertised_max_streams());
EXPECT_EQ(kDefaultMaxStreamsPerConnection,
- stream_id_manager_->max_allowed_outgoing_streams());
+ stream_id_manager_->incoming_initial_max_open_streams());
// The window for advertising updates to the MAX STREAM ID is half the number
// of streams allowed.
- EXPECT_EQ(kDefaultMaxStreamsPerConnection / kMaxStreamIdWindowDivisor,
- stream_id_manager_->max_stream_id_window());
-
- // This test runs as a client, so it initiates (that is to say, outgoing)
- // even-numbered stream IDs. Also, our implementation starts allocating
- // stream IDs at 0 (for clients) 1 (for servers) -- before taking statically
- // allocated streams into account. The -1 in the calculation is
- // because the value being tested is the maximum allowed stream ID, not the
- // first unallowed stream id.
- const QuicStreamId kExpectedMaxOutgoingStreamId =
- (GetParam() ? session_->next_outgoing_bidirectional_stream_id()
- : session_->next_outgoing_unidirectional_stream_id()) +
- ((kDefaultMaxStreamsPerConnection - 1) * kV99StreamIdIncrement);
- EXPECT_EQ(kExpectedMaxOutgoingStreamId,
- stream_id_manager_->max_allowed_outgoing_stream_id());
-
- // Same for IDs of incoming streams...
- const QuicStreamId kExpectedMaxIncomingStreamId =
- stream_id_manager_->first_incoming_dynamic_stream_id() +
- (kDefaultMaxStreamsPerConnection - 1) * kV99StreamIdIncrement;
- EXPECT_EQ(kExpectedMaxIncomingStreamId,
- stream_id_manager_->actual_max_allowed_incoming_stream_id());
- EXPECT_EQ(kExpectedMaxIncomingStreamId,
- stream_id_manager_->advertised_max_allowed_incoming_stream_id());
-}
-
-// This test checks that the initialization for the maximum allowed outgoing
-// stream id is correct.
-TEST_P(QuicStreamIdManagerTestClient, CheckMaxAllowedOutgoing) {
- const size_t kNumOutgoingStreams = 124;
- stream_id_manager_->SetMaxOpenOutgoingStreams(kNumOutgoingStreams);
- EXPECT_EQ(kNumOutgoingStreams,
- stream_id_manager_->max_allowed_outgoing_streams());
-
- // Check that the maximum available stream is properly set.
- size_t expected_max_outgoing_id =
- (GetParam() ? session_->next_outgoing_bidirectional_stream_id()
- : session_->next_outgoing_unidirectional_stream_id()) +
- ((kNumOutgoingStreams - 1) * kV99StreamIdIncrement);
- EXPECT_EQ(expected_max_outgoing_id,
- stream_id_manager_->max_allowed_outgoing_stream_id());
-}
-
-// This test checks that the initialization for the maximum allowed incoming
-// stream id is correct.
-TEST_P(QuicStreamIdManagerTestClient, CheckMaxAllowedIncoming) {
- const size_t kStreamCount = 245;
- stream_id_manager_->SetMaxOpenIncomingStreams(kStreamCount);
- EXPECT_EQ(kStreamCount, stream_id_manager_->max_allowed_incoming_streams());
- // Check that the window is 1/2 (integer math) of the stream count.
- EXPECT_EQ(kStreamCount / 2, stream_id_manager_->max_stream_id_window());
-
- // Actual- and advertised- maxima start out equal.
- EXPECT_EQ(stream_id_manager_->actual_max_allowed_incoming_stream_id(),
- stream_id_manager_->advertised_max_allowed_incoming_stream_id());
-
- // Check that the maximum stream ID is properly calculated.
- EXPECT_EQ(stream_id_manager_->first_incoming_dynamic_stream_id() +
- ((kStreamCount - 1) * kV99StreamIdIncrement),
- stream_id_manager_->actual_max_allowed_incoming_stream_id());
+ EXPECT_EQ(kDefaultMaxStreamsPerConnection / kMaxStreamsWindowDivisor,
+ stream_id_manager_->max_streams_window());
}
// This test checks that the stream advertisement window is set to 1
// if the number of stream ids is 1. This is a special case in the code.
-TEST_P(QuicStreamIdManagerTestClient, CheckMaxStreamIdWindow1) {
+TEST_P(QuicStreamIdManagerTestClient, CheckMaxStreamsWindow1) {
stream_id_manager_->SetMaxOpenIncomingStreams(1);
- EXPECT_EQ(1u, stream_id_manager_->max_allowed_incoming_streams());
+ EXPECT_EQ(1u, stream_id_manager_->incoming_initial_max_open_streams());
+ EXPECT_EQ(1u, stream_id_manager_->incoming_actual_max_streams());
// If streamid_count/2==0 (integer math) force it to 1.
- EXPECT_EQ(1u, stream_id_manager_->max_stream_id_window());
+ EXPECT_EQ(1u, stream_id_manager_->max_streams_window());
+}
+
+// Test that stream counts that would exceed the implementation maximum are
+// safely handled.
+// First, check that setting up to and including the implementation maximum
+// is OK.
+TEST_P(QuicStreamIdManagerTestClient, CheckMaxStreamsBadValuesToMaxOkOutgoing) {
+ QuicStreamCount implementation_max =
+ QuicUtils::GetMaxStreamCount(!GetParam(), /* GetParam==true for bidi */
+ Perspective::IS_CLIENT);
+ stream_id_manager_->AdjustMaxOpenOutgoingStreams(implementation_max - 1u);
+ // If bidi, Crypto stream default created at start up, it is one
+ // more stream to account for since initialization is "number of
+ // request/responses" & crypto is added in to that, not streams.
+ size_t extra_stream_count = 0;
+ if (GetParam() && !QuicVersionUsesCryptoFrames(transport_version())) {
+ extra_stream_count = 1;
+ }
+ EXPECT_EQ(implementation_max - 1u + extra_stream_count,
+ stream_id_manager_->outgoing_max_streams());
+
+ stream_id_manager_->AdjustMaxOpenOutgoingStreams(implementation_max);
+ EXPECT_EQ(implementation_max, stream_id_manager_->outgoing_max_streams());
+}
+
+// Now check that setting to a value larger than the maximum fails.
+TEST_P(QuicStreamIdManagerTestClient,
+ CheckMaxStreamsBadValuesOverMaxFailsOutgoing) {
+ QuicStreamCount implementation_max =
+ QuicUtils::GetMaxStreamCount(!GetParam(), /* GetParam==true for bidi */
+ Perspective::IS_CLIENT);
+ // Ensure that the limit is less than the implementation maximum.
+ EXPECT_LT(stream_id_manager_->outgoing_max_streams(), implementation_max);
+
+ // Try to go over.
+ stream_id_manager_->AdjustMaxOpenOutgoingStreams(implementation_max + 1);
+ // Should be pegged at the max.
+ EXPECT_EQ(implementation_max, stream_id_manager_->outgoing_max_streams());
}
-// Check the case of the stream ID in a STREAM_ID_BLOCKED frame is less than the
-// stream ID most recently advertised in a MAX_STREAM_ID frame. This should
-// cause a MAX_STREAM_ID frame with the most recently advertised stream id to be
-// sent.
-TEST_P(QuicStreamIdManagerTestClient, ProcessStreamIdBlockedOk) {
+// Now do the same for the incoming streams
+TEST_P(QuicStreamIdManagerTestClient, CheckMaxStreamsBadValuesIncoming) {
+ QuicStreamCount implementation_max =
+ QuicUtils::GetMaxStreamCount(!GetParam(), /* GetParam==true for bidi */
+ Perspective::IS_CLIENT);
+ stream_id_manager_->SetMaxOpenIncomingStreams(implementation_max - 1u);
+ EXPECT_EQ(implementation_max - 1u,
+ stream_id_manager_->incoming_initial_max_open_streams());
+ EXPECT_EQ(implementation_max - 1u,
+ stream_id_manager_->incoming_actual_max_streams());
+ EXPECT_EQ((implementation_max - 1u) / 2u,
+ stream_id_manager_->max_streams_window());
+
+ stream_id_manager_->SetMaxOpenIncomingStreams(implementation_max);
+ EXPECT_EQ(implementation_max,
+ stream_id_manager_->incoming_initial_max_open_streams());
+ EXPECT_EQ(implementation_max,
+ stream_id_manager_->incoming_actual_max_streams());
+ EXPECT_EQ(implementation_max / 2, stream_id_manager_->max_streams_window());
+
+ // Reset to 1 so that we can detect the change.
+ stream_id_manager_->SetMaxOpenIncomingStreams(1u);
+ EXPECT_EQ(1u, stream_id_manager_->incoming_initial_max_open_streams());
+ EXPECT_EQ(1u, stream_id_manager_->incoming_actual_max_streams());
+ EXPECT_EQ(1u, stream_id_manager_->max_streams_window());
+ // Now try to exceed the max, without wrapping.
+ stream_id_manager_->SetMaxOpenIncomingStreams(implementation_max + 1);
+ EXPECT_EQ(implementation_max,
+ stream_id_manager_->incoming_initial_max_open_streams());
+ EXPECT_EQ(implementation_max,
+ stream_id_manager_->incoming_actual_max_streams());
+ EXPECT_EQ(implementation_max / 2u, stream_id_manager_->max_streams_window());
+}
+
+// Check the case of the stream count in a STREAMS_BLOCKED frame is less than
+// the count most recently advertised in a MAX_STREAMS frame. This should cause
+// a MAX_STREAMS frame with the most recently advertised count to be sent.
+TEST_P(QuicStreamIdManagerTestClient, ProcessStreamsBlockedOk) {
EXPECT_CALL(*connection_, SendControlFrame(_))
.WillRepeatedly(Invoke(session_.get(), &TestQuicSession::SaveFrame));
- QuicStreamId stream_id =
- stream_id_manager_->advertised_max_allowed_incoming_stream_id() -
- kV99StreamIdIncrement;
- QuicStreamIdBlockedFrame frame(0, stream_id);
- session_->OnStreamIdBlockedFrame(frame);
+ QuicStreamCount stream_count =
+ stream_id_manager_->incoming_initial_max_open_streams() - 1;
+ QuicStreamsBlockedFrame frame(0, stream_count, /*unidirectional=*/false);
+ session_->OnStreamsBlockedFrame(frame);
- // We should see a MAX_STREAM_ID frame.
- EXPECT_EQ(MAX_STREAM_ID_FRAME, session_->save_frame().type);
+ // We should see a MAX_STREAMS frame.
+ EXPECT_EQ(MAX_STREAMS_FRAME, session_->save_frame().type);
// and it should advertise the current max-allowed value.
- EXPECT_EQ(stream_id_manager_->actual_max_allowed_incoming_stream_id(),
- session_->save_frame().max_stream_id_frame.max_stream_id);
+ EXPECT_EQ(stream_id_manager_->incoming_initial_max_open_streams(),
+ session_->save_frame().max_streams_frame.stream_count);
}
-// Check the case of the stream ID in a STREAM_ID_BLOCKED frame is equal to
-// stream ID most recently advertised in a MAX_STREAM_ID frame. No
-// MAX_STREAM_ID should be generated.
-TEST_P(QuicStreamIdManagerTestClient, ProcessStreamIdBlockedNoOp) {
+// Check the case of the stream count in a STREAMS_BLOCKED frame is equal to the
+// count most recently advertised in a MAX_STREAMS frame. No MAX_STREAMS
+// should be generated.
+TEST_P(QuicStreamIdManagerTestClient, ProcessStreamsBlockedNoOp) {
EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
- QuicStreamId stream_id =
- stream_id_manager_->advertised_max_allowed_incoming_stream_id();
- QuicStreamIdBlockedFrame frame(0, stream_id);
- session_->OnStreamIdBlockedFrame(frame);
+ QuicStreamCount stream_count =
+ stream_id_manager_->incoming_initial_max_open_streams();
+ QuicStreamsBlockedFrame frame(0, stream_count, /*unidirectional=*/false);
+ session_->OnStreamsBlockedFrame(frame);
}
-// Check the case of the stream ID in a STREAM_ID_BLOCKED frame is greater than
-// the stream ID most recently advertised in a MAX_STREAM_ID frame. Expect a
+// Check the case of the stream count in a STREAMS_BLOCKED frame is greater than
+// the count most recently advertised in a MAX_STREAMS frame. Expect a
// connection close with an error.
-TEST_P(QuicStreamIdManagerTestClient, ProcessStreamIdBlockedTooBig) {
- EXPECT_CALL(*connection_,
- CloseConnection(QUIC_STREAM_ID_BLOCKED_ERROR, _, _));
+TEST_P(QuicStreamIdManagerTestClient, ProcessStreamsBlockedTooBig) {
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_STREAMS_BLOCKED_ERROR, _, _));
EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
- QuicStreamId stream_id =
- stream_id_manager_->advertised_max_allowed_incoming_stream_id() +
- kV99StreamIdIncrement;
- QuicStreamIdBlockedFrame frame(0, stream_id);
- session_->OnStreamIdBlockedFrame(frame);
+ QuicStreamCount stream_count =
+ stream_id_manager_->incoming_initial_max_open_streams() + 1;
+ QuicStreamsBlockedFrame frame(0, stream_count, /*unidirectional=*/false);
+ session_->OnStreamsBlockedFrame(frame);
}
// Same basic tests as above, but calls
@@ -310,8 +357,8 @@ TEST_P(QuicStreamIdManagerTestClient, ProcessStreamIdBlockedTooBig) {
// First test make sure that streams with ids below the limit are accepted.
TEST_P(QuicStreamIdManagerTestClient, IsIncomingStreamIdValidBelowLimit) {
QuicStreamId stream_id =
- stream_id_manager_->actual_max_allowed_incoming_stream_id() -
- kV99StreamIdIncrement;
+ StreamCountToId(stream_id_manager_->incoming_actual_max_streams() - 1,
+ Perspective::IS_CLIENT);
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
EXPECT_TRUE(stream_id_manager_->MaybeIncreaseLargestPeerStreamId(stream_id));
}
@@ -319,227 +366,223 @@ TEST_P(QuicStreamIdManagerTestClient, IsIncomingStreamIdValidBelowLimit) {
// Accept a stream with an ID that equals the limit.
TEST_P(QuicStreamIdManagerTestClient, IsIncomingStreamIdValidAtLimit) {
QuicStreamId stream_id =
- stream_id_manager_->actual_max_allowed_incoming_stream_id();
+ StreamCountToId(stream_id_manager_->incoming_actual_max_streams(),
+ Perspective::IS_CLIENT);
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
EXPECT_TRUE(stream_id_manager_->MaybeIncreaseLargestPeerStreamId(stream_id));
}
// Close the connection if the id exceeds the limit.
TEST_P(QuicStreamIdManagerTestClient, IsIncomingStreamIdInValidAboveLimit) {
- QuicStreamId stream_id =
- stream_id_manager_->actual_max_allowed_incoming_stream_id() +
- kV99StreamIdIncrement;
+ QuicStreamId stream_id = StreamCountToId(
+ stream_id_manager_->incoming_actual_max_streams() + 1,
+ Perspective::IS_SERVER); // This node is a client, incoming
+ // stream ids must be server-originated.
std::string error_details =
- GetParam() ? "Stream id 401 above 397" : "Stream id 403 above 399";
+ GetParam() ? "Stream id 401 would exceed stream count limit 100"
+ : "Stream id 403 would exceed stream count limit 100";
EXPECT_CALL(*connection_,
CloseConnection(QUIC_INVALID_STREAM_ID, error_details, _));
EXPECT_FALSE(stream_id_manager_->MaybeIncreaseLargestPeerStreamId(stream_id));
}
-// Test that a client will reject a MAX_STREAM_ID that specifies a
-// server-initiated stream ID.
-TEST_P(QuicStreamIdManagerTestClient, RejectServerMaxStreamId) {
- QuicStreamId id = stream_id_manager_->max_allowed_outgoing_stream_id();
-
- // Ensure that the ID that will be in the MAX_STREAM_ID is larger than the
- // current MAX.
- id += (kV99StreamIdIncrement * 2);
-
- // Make it an odd (server-initiated) ID.
- id |= 0x1;
- EXPECT_FALSE(QuicUtils::IsClientInitiatedStreamId(QUIC_VERSION_99, id));
-
- // Make the frame and process it; should result in the connection being
- // closed.
- QuicMaxStreamIdFrame frame(0, id);
- EXPECT_CALL(*connection_, CloseConnection(QUIC_MAX_STREAM_ID_ERROR, _, _));
- session_->OnMaxStreamIdFrame(frame);
-}
-
-// Test that a client will reject a STREAM_ID_BLOCKED that specifies a
-// client-initiated stream ID. STREAM_ID_BLOCKED from a server should specify an
-// odd (server-initiated_ ID). Generate one with an odd ID and check that the
-// connection is closed.
-TEST_P(QuicStreamIdManagerTestClient, RejectServerStreamIdBlocked) {
- QuicStreamId id = stream_id_manager_->max_allowed_outgoing_stream_id();
-
- // Ensure that the ID that will be in the MAX_STREAM_ID is larger than the
- // current MAX.
- id += (kV99StreamIdIncrement * 2);
- // Make sure it's odd, like a client-initiated ID.
- id &= ~0x01;
- EXPECT_TRUE(QuicUtils::IsClientInitiatedStreamId(QUIC_VERSION_99, id));
-
- // Generate and process the frame; connection should be closed.
- QuicStreamIdBlockedFrame frame(0, id);
- EXPECT_CALL(*connection_,
- CloseConnection(QUIC_STREAM_ID_BLOCKED_ERROR, _, _));
- session_->OnStreamIdBlockedFrame(frame);
-}
-
-// Test functionality for reception of a MAX STREAM ID frame. This code is
+// Test functionality for reception of a MAX_STREAMS frame. This code is
// client/server-agnostic.
-TEST_P(QuicStreamIdManagerTestClient, StreamIdManagerClientOnMaxStreamIdFrame) {
- // Get the current maximum allowed outgoing stream ID.
- QuicStreamId initial_stream_id =
- stream_id_manager_->max_allowed_outgoing_stream_id();
- QuicMaxStreamIdFrame frame;
-
- // If the stream ID in the frame is < the current maximum then
- // the frame should be ignored.
- frame.max_stream_id = initial_stream_id - kV99StreamIdIncrement;
- EXPECT_TRUE(stream_id_manager_->OnMaxStreamIdFrame(frame));
- EXPECT_EQ(initial_stream_id,
- stream_id_manager_->max_allowed_outgoing_stream_id());
-
- // A stream ID greater than the current limit should increase the limit.
- frame.max_stream_id = initial_stream_id + kV99StreamIdIncrement;
- EXPECT_TRUE(stream_id_manager_->OnMaxStreamIdFrame(frame));
- EXPECT_EQ(initial_stream_id + kV99StreamIdIncrement,
- stream_id_manager_->max_allowed_outgoing_stream_id());
+TEST_P(QuicStreamIdManagerTestClient, StreamIdManagerClientOnMaxStreamsFrame) {
+ // Get the current maximum allowed outgoing stream count.
+ QuicStreamCount initial_stream_count =
+ // need to know the number of request/response streams.
+ // This is the total number of outgoing streams (which includes both
+ // req/resp and statics) minus just the statics...
+ stream_id_manager_->outgoing_max_streams() -
+ stream_id_manager_->outgoing_static_stream_count();
+
+ QuicMaxStreamsFrame frame;
+
+ // Even though the stream count in the frame is < the initial maximum,
+ // it is should be ignored since the initial max was set via
+ // the constructor (an educated guess) and the MAX STREAMS frame
+ // is authoritative.
+ frame.stream_count = initial_stream_count - 1;
+
+ frame.unidirectional = IsUnidi();
+ EXPECT_TRUE(stream_id_manager_->OnMaxStreamsFrame(frame));
+ EXPECT_EQ(initial_stream_count - 1u,
+ stream_id_manager_->outgoing_max_streams());
+
+ QuicStreamCount save_outgoing_max_streams =
+ stream_id_manager_->outgoing_max_streams();
+ // Now that there has been one MAX STREAMS frame, we should not
+ // accept a MAX_STREAMS that reduces the limit...
+ frame.stream_count = initial_stream_count - 2;
+ frame.unidirectional = IsUnidi();
+ EXPECT_TRUE(stream_id_manager_->OnMaxStreamsFrame(frame));
+ // should not change from previous setting.
+ EXPECT_EQ(save_outgoing_max_streams,
+ stream_id_manager_->outgoing_max_streams());
+
+ // A stream count greater than the current limit should increase the limit.
+ frame.stream_count = initial_stream_count + 1;
+ EXPECT_TRUE(stream_id_manager_->OnMaxStreamsFrame(frame));
+
+ EXPECT_EQ(initial_stream_count + 1u,
+ stream_id_manager_->outgoing_max_streams());
}
-// Test functionality for reception of a STREAM ID BLOCKED frame.
+// Test functionality for reception of a STREAMS_BLOCKED frame.
// This code is client/server-agnostic.
-TEST_P(QuicStreamIdManagerTestClient, StreamIdManagerOnStreamIdBlockedFrame) {
- // Get the current maximum allowed incoming stream ID.
- QuicStreamId advertised_stream_id =
- stream_id_manager_->advertised_max_allowed_incoming_stream_id();
- QuicStreamIdBlockedFrame frame;
+TEST_P(QuicStreamIdManagerTestClient, StreamIdManagerOnStreamsBlockedFrame) {
+ // Get the current maximum allowed incoming stream count.
+ QuicStreamCount advertised_stream_count =
+ stream_id_manager_->incoming_advertised_max_streams();
+ QuicStreamsBlockedFrame frame;
+
+ frame.unidirectional = IsUnidi();
- // If the peer is saying it's blocked on the stream ID that
+ // If the peer is saying it's blocked on the stream count that
// we've advertised, it's a noop since the peer has the correct information.
- frame.stream_id = advertised_stream_id;
- EXPECT_TRUE(stream_id_manager_->OnStreamIdBlockedFrame(frame));
+ frame.stream_count = advertised_stream_count;
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
+ EXPECT_TRUE(stream_id_manager_->OnStreamsBlockedFrame(frame));
- // If the peer is saying it's blocked on a stream ID that is larger
+ // If the peer is saying it's blocked on a stream count that is larger
// than what we've advertised, the connection should get closed.
- frame.stream_id = advertised_stream_id + kV99StreamIdIncrement;
- EXPECT_CALL(*connection_,
- CloseConnection(QUIC_STREAM_ID_BLOCKED_ERROR, _, _));
- EXPECT_FALSE(stream_id_manager_->OnStreamIdBlockedFrame(frame));
+ frame.stream_count = advertised_stream_count + 1;
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_STREAMS_BLOCKED_ERROR, _, _));
+ EXPECT_FALSE(stream_id_manager_->OnStreamsBlockedFrame(frame));
- // If the peer is saying it's blocked on a stream ID that is less than
- // what we've advertised, we send a MAX STREAM ID frame and update
+ // If the peer is saying it's blocked on a count that is less than
+ // our actual count, we send a MAX_STREAMS frame and update
// the advertised value.
// First, need to bump up the actual max so there is room for the MAX
- // STREAM_ID frame to send a larger ID.
- QuicStreamId actual_stream_id =
- stream_id_manager_->actual_max_allowed_incoming_stream_id();
+ // STREAMS frame to send a larger ID.
+ QuicStreamCount actual_stream_count =
+ stream_id_manager_->incoming_actual_max_streams();
+
+ // Closing a stream will result in the ability to initiate one more
+ // stream
stream_id_manager_->OnStreamClosed(
- stream_id_manager_->first_incoming_dynamic_stream_id());
- EXPECT_EQ(actual_stream_id + kV99StreamIdIncrement,
- stream_id_manager_->actual_max_allowed_incoming_stream_id());
- EXPECT_GT(stream_id_manager_->actual_max_allowed_incoming_stream_id(),
- stream_id_manager_->advertised_max_allowed_incoming_stream_id());
-
- // Now simulate receiving a STTREAM_ID_BLOCKED frame...
- // Changing the actual maximum, above, forces a MAX STREAM ID frame to be
- // sent, so the logic for that (SendMaxStreamIdFrame(), etc) is tested.
- frame.stream_id = advertised_stream_id;
+ QuicStreamIdManagerPeer::GetFirstIncomingStreamId(stream_id_manager_));
+ EXPECT_EQ(actual_stream_count + 1u,
+ stream_id_manager_->incoming_actual_max_streams());
+ EXPECT_EQ(stream_id_manager_->incoming_actual_max_streams(),
+ stream_id_manager_->incoming_advertised_max_streams() + 1u);
+
+ // Now simulate receiving a STREAMS_BLOCKED frame...
+ // Changing the actual maximum, above, forces a MAX_STREAMS frame to be
+ // sent, so the logic for that (SendMaxStreamsFrame(), etc) is tested.
+
+ // The STREAMS_BLOCKED frame contains the previous advertised count,
+ // not the one that the peer would have received as a result of the
+ // MAX_STREAMS sent earler.
+ frame.stream_count = advertised_stream_count;
+
EXPECT_CALL(*connection_, SendControlFrame(_))
.Times(1)
.WillRepeatedly(Invoke(session_.get(), &TestQuicSession::SaveFrame));
- EXPECT_TRUE(stream_id_manager_->OnStreamIdBlockedFrame(frame));
- EXPECT_EQ(stream_id_manager_->actual_max_allowed_incoming_stream_id(),
- stream_id_manager_->advertised_max_allowed_incoming_stream_id());
- EXPECT_EQ(MAX_STREAM_ID_FRAME, session_->save_frame().type);
- EXPECT_EQ(stream_id_manager_->advertised_max_allowed_incoming_stream_id(),
- session_->save_frame().max_stream_id_frame.max_stream_id);
-
- // Ensure a client initiated stream ID is rejected.
- frame.stream_id = GetParam() ? GetNthClientInitiatedBidirectionalId(1)
- : GetNthClientInitiatedUnidirectionalId(1);
- EXPECT_CALL(*connection_,
- CloseConnection(QUIC_STREAM_ID_BLOCKED_ERROR, _, _));
- EXPECT_FALSE(stream_id_manager_->OnStreamIdBlockedFrame(frame));
+
+ EXPECT_TRUE(stream_id_manager_->OnStreamsBlockedFrame(frame));
+ // Check that the saved frame is correct.
+ EXPECT_EQ(stream_id_manager_->incoming_actual_max_streams(),
+ stream_id_manager_->incoming_advertised_max_streams());
+ EXPECT_EQ(MAX_STREAMS_FRAME, session_->save_frame().type);
+ EXPECT_EQ(stream_id_manager_->incoming_advertised_max_streams(),
+ session_->save_frame().max_streams_frame.stream_count);
+ // Make sure that this is the only MAX_STREAMS
+ EXPECT_EQ(1u, GetControlFrameId(session_->save_frame()));
}
// Test GetNextOutgoingStream. This is client/server agnostic.
-TEST_P(QuicStreamIdManagerTestClient, StreamIdManagerGetNextOutgoingFrame) {
+TEST_P(QuicStreamIdManagerTestClient, StreamIdManagerGetNextOutgoingStream) {
// Number of streams we can open and the first one we should get when
// opening...
int number_of_streams = kDefaultMaxStreamsPerConnection;
QuicStreamId stream_id =
- GetParam() ? session_->next_outgoing_bidirectional_stream_id()
- : session_->next_outgoing_unidirectional_stream_id();
-
+ IsUnidi() ? session_->next_outgoing_unidirectional_stream_id()
+ : session_->next_outgoing_bidirectional_stream_id();
+
+ // If bidi, Crypto stream default created at start up, it is one
+ // more stream to account for since initialization is "number of
+ // request/responses" & crypto is added in to that, not streams.
+ size_t extra_stream_count = 0;
+ if (IsBidi() && !QuicVersionUsesCryptoFrames(transport_version())) {
+ extra_stream_count = 1;
+ }
+ EXPECT_EQ(number_of_streams + extra_stream_count,
+ stream_id_manager_->outgoing_max_streams());
while (number_of_streams) {
EXPECT_TRUE(stream_id_manager_->CanOpenNextOutgoingStream());
EXPECT_EQ(stream_id, stream_id_manager_->GetNextOutgoingStreamId());
stream_id += kV99StreamIdIncrement;
number_of_streams--;
}
- EXPECT_EQ(stream_id - kV99StreamIdIncrement,
- stream_id_manager_->max_allowed_outgoing_stream_id());
// If we try to check that the next outgoing stream id is available it should
- // A) fail and B) generate a STREAM_ID_BLOCKED frame.
+ // A) fail and B) generate a STREAMS_BLOCKED frame.
EXPECT_CALL(*connection_, SendControlFrame(_))
.Times(1)
.WillRepeatedly(Invoke(session_.get(), &TestQuicSession::SaveFrame));
EXPECT_FALSE(stream_id_manager_->CanOpenNextOutgoingStream());
- EXPECT_EQ(STREAM_ID_BLOCKED_FRAME, session_->save_frame().type);
- EXPECT_EQ(stream_id_manager_->max_allowed_outgoing_stream_id(),
- session_->save_frame().max_stream_id_frame.max_stream_id);
+ EXPECT_EQ(STREAMS_BLOCKED_FRAME, session_->save_frame().type);
+ // If bidi, Crypto stream default created at start up, it is one
+ // more stream to account for since initialization is "number of
+ // request/responses" & crypto is added in to that, not streams.
+ EXPECT_EQ(kDefaultMaxStreamsPerConnection + extra_stream_count,
+ session_->save_frame().max_streams_frame.stream_count);
// If we try to get the next id (above the limit), it should cause a quic-bug.
EXPECT_QUIC_BUG(
stream_id_manager_->GetNextOutgoingStreamId(),
- "Attempt allocate a new outgoing stream ID would exceed the limit");
+ "Attempt to allocate a new outgoing stream that would exceed the limit");
}
// Ensure that MaybeIncreaseLargestPeerStreamId works properly. This is
// server/client agnostic.
TEST_P(QuicStreamIdManagerTestClient,
StreamIdManagerServerMaybeIncreaseLargestPeerStreamId) {
- EXPECT_TRUE(stream_id_manager_->MaybeIncreaseLargestPeerStreamId(
- stream_id_manager_->actual_max_allowed_incoming_stream_id()));
+ QuicStreamId max_stream_id =
+ StreamCountToId(stream_id_manager_->incoming_actual_max_streams(),
+ Perspective::IS_SERVER);
+ EXPECT_TRUE(
+ stream_id_manager_->MaybeIncreaseLargestPeerStreamId(max_stream_id));
+
QuicStreamId server_initiated_stream_id =
- GetParam() ? GetNthServerInitiatedBidirectionalId(0)
- : GetNthServerInitiatedUnidirectionalId(0);
+ StreamCountToId(1u, // get 1st id
+ Perspective::IS_SERVER);
EXPECT_TRUE(stream_id_manager_->MaybeIncreaseLargestPeerStreamId(
server_initiated_stream_id));
// A bad stream ID results in a closed connection.
EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
EXPECT_FALSE(stream_id_manager_->MaybeIncreaseLargestPeerStreamId(
- stream_id_manager_->actual_max_allowed_incoming_stream_id() +
- kV99StreamIdIncrement));
+ max_stream_id + kV99StreamIdIncrement));
}
-// Test the MAX STREAM ID Window functionality.
-// Free up Stream ID space. Do not expect to see a MAX_STREAM_ID
-// until |window| stream ids are available.
-TEST_P(QuicStreamIdManagerTestClient, StreamIdManagerServerMaxStreamId) {
- // Test that a MAX_STREAM_ID frame is generated when the peer has less than
- // |max_stream_id_window_| streams left that it can initiate.
+// Test the MAX STREAMS Window functionality.
+TEST_P(QuicStreamIdManagerTestClient, StreamIdManagerServerMaxStreams) {
+ // Test that a MAX_STREAMS frame is generated when the peer has less than
+ // |max_streams_window_| streams left that it can initiate.
- // First, open, and then close, max_stream_id_window_ streams. This will
- // max_stream_id_window_ streams available for the peer -- no MAX_STREAM_ID
+ // First, open, and then close, max_streams_window_ streams. This will
+ // max_streams_window_ streams available for the peer -- no MAX_STREAMS
// should be sent. The -1 is because the check in
- // QuicStreamIdManager::MaybeSendMaxStreamIdFrame sends a MAX_STREAM_ID if the
- // number of available streams at the peer is <= |max_stream_id_window_|
- int stream_count = stream_id_manager_->max_stream_id_window() - 1;
-
- QuicStreamId advertised_max =
- stream_id_manager_->advertised_max_allowed_incoming_stream_id();
- QuicStreamId expected_actual_max_id =
- stream_id_manager_->actual_max_allowed_incoming_stream_id();
+ // QuicStreamIdManager::MaybeSendMaxStreamsFrame sends a MAX_STREAMS if the
+ // number of available streams at the peer is <= |max_streams_window_|
+ int stream_count = stream_id_manager_->max_streams_window() - 1;
// Should not get a control-frame transmission since the peer should have
// "plenty" of stream IDs to use.
EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
- // This test runs as a client, so the first stream to release is 2, a
- // server-initiated stream.
- QuicStreamId stream_id = GetParam()
- ? GetNthServerInitiatedBidirectionalId(0)
- : GetNthServerInitiatedUnidirectionalId(0);
+
+ // Get the first incoming stream ID to try and allocate.
+ QuicStreamId stream_id = IsBidi() ? GetNthServerInitiatedBidirectionalId(0)
+ : GetNthServerInitiatedUnidirectionalId(0);
size_t old_available_incoming_streams =
stream_id_manager_->available_incoming_streams();
-
while (stream_count) {
EXPECT_TRUE(
stream_id_manager_->MaybeIncreaseLargestPeerStreamId(stream_id));
+ // This node should think that the peer believes it has one fewer
+ // stream it can create.
old_available_incoming_streams--;
EXPECT_EQ(old_available_incoming_streams,
stream_id_manager_->available_incoming_streams());
@@ -548,27 +591,31 @@ TEST_P(QuicStreamIdManagerTestClient, StreamIdManagerServerMaxStreamId) {
stream_id += kV99StreamIdIncrement;
}
- // Now close them, still should get no MAX_STREAM_ID
- stream_count = stream_id_manager_->max_stream_id_window();
- stream_id = GetParam() ? GetNthServerInitiatedBidirectionalId(0)
- : GetNthServerInitiatedUnidirectionalId(0);
+ // Now close them, still should get no MAX_STREAMS
+ stream_count = stream_id_manager_->max_streams_window();
+ stream_id = IsBidi() ? GetNthServerInitiatedBidirectionalId(0)
+ : GetNthServerInitiatedUnidirectionalId(0);
+ QuicStreamCount expected_actual_max =
+ stream_id_manager_->incoming_actual_max_streams();
+ QuicStreamCount expected_advertised_max_streams =
+ stream_id_manager_->incoming_advertised_max_streams();
while (stream_count) {
stream_id_manager_->OnStreamClosed(stream_id);
stream_count--;
stream_id += kV99StreamIdIncrement;
- expected_actual_max_id += kV99StreamIdIncrement;
- EXPECT_EQ(expected_actual_max_id,
- stream_id_manager_->actual_max_allowed_incoming_stream_id());
+ expected_actual_max++;
+ EXPECT_EQ(expected_actual_max,
+ stream_id_manager_->incoming_actual_max_streams());
// Advertised maximum should remain the same.
- EXPECT_EQ(advertised_max,
- stream_id_manager_->advertised_max_allowed_incoming_stream_id());
+ EXPECT_EQ(expected_advertised_max_streams,
+ stream_id_manager_->incoming_advertised_max_streams());
}
// This should not change.
EXPECT_EQ(old_available_incoming_streams,
stream_id_manager_->available_incoming_streams());
- // Now whenever we close a stream we should get a MAX_STREAM_ID frame.
+ // Now whenever we close a stream we should get a MAX_STREAMS frame.
// Above code closed all the open streams, so we have to open/close
EXPECT_CALL(*connection_, SendControlFrame(_))
.Times(1)
@@ -577,37 +624,74 @@ TEST_P(QuicStreamIdManagerTestClient, StreamIdManagerServerMaxStreamId) {
stream_id_manager_->OnStreamClosed(stream_id);
stream_id += kV99StreamIdIncrement;
- // Check that the MAX STREAM ID was sent and has the correct values.
- EXPECT_EQ(MAX_STREAM_ID_FRAME, session_->save_frame().type);
- EXPECT_EQ(stream_id_manager_->advertised_max_allowed_incoming_stream_id(),
- session_->save_frame().max_stream_id_frame.max_stream_id);
+ // Check that the MAX STREAMS was sent and has the correct values.
+ EXPECT_EQ(MAX_STREAMS_FRAME, session_->save_frame().type);
+ EXPECT_EQ(stream_id_manager_->incoming_advertised_max_streams(),
+ session_->save_frame().max_streams_frame.stream_count);
}
-// Test that registering static stream IDs causes the stream ID limit to rise
+// Test that registering static stream IDs causes the stream limit to rise
// accordingly. This is server/client agnostic.
TEST_P(QuicStreamIdManagerTestClient, TestStaticStreamAdjustment) {
QuicStreamId first_dynamic =
- stream_id_manager_->first_incoming_dynamic_stream_id();
- QuicStreamId expected_max_incoming =
- stream_id_manager_->actual_max_allowed_incoming_stream_id();
+ QuicStreamIdManagerPeer::GetFirstIncomingStreamId(stream_id_manager_);
+ QuicStreamCount actual_max =
+ stream_id_manager_->incoming_actual_max_streams();
// First test will register the first dynamic stream id as being for a static
- // stream. This takes one stream ID out of the low-end of the dynamic range
- // so therefore the high end should go up by 1 ID.
- expected_max_incoming += kV99StreamIdIncrement;
+ // stream.
stream_id_manager_->RegisterStaticStream(first_dynamic);
- EXPECT_EQ(expected_max_incoming,
- stream_id_manager_->actual_max_allowed_incoming_stream_id());
-
- // Now be extreme, increase static by 100 stream ids. A discontinuous
- // jump is not allowed; make sure.
- first_dynamic += kV99StreamIdIncrement * 100;
- expected_max_incoming += kV99StreamIdIncrement * 100;
- std::string bug_detail =
- GetParam() ? "allocate 5 got 401" : "allocate 7 got 403";
- EXPECT_QUIC_BUG(
- stream_id_manager_->RegisterStaticStream(first_dynamic),
- "Error in incoming static stream allocation, expected to " + bug_detail);
+ // Should go up by 1 stream/stream id.
+ EXPECT_EQ(actual_max + 1u, stream_id_manager_->incoming_actual_max_streams());
+}
+
+// Check that the OnMaxStreamFrame logic properly handles all the
+// cases of offered max streams and outgoing_static_stream_count_,
+// checking for the wrap conditions. Tests in client perspective, necessary
+// because internally, some calculations depend on the client/server
+// perspective.
+TEST_P(QuicStreamIdManagerTestClient, TestMaxStreamsWrapChecks) {
+ QuicStreamCount max_stream_count =
+ QuicUtils::GetMaxStreamCount(IsUnidi(), Perspective::IS_CLIENT);
+ QuicMaxStreamsFrame frame;
+ frame.unidirectional = IsUnidi();
+
+ // Check the case where the offered stream count is less than the
+ // maximum
+ frame.stream_count = max_stream_count - 10;
+ EXPECT_TRUE(stream_id_manager_->OnMaxStreamsFrame(frame));
+ EXPECT_EQ(max_stream_count - 10u, stream_id_manager_->outgoing_max_streams());
+
+ // Now check if the offered count is larger than the max.
+ // The count should be pegged at the max.
+ frame.stream_count = max_stream_count + 10;
+ EXPECT_TRUE(stream_id_manager_->OnMaxStreamsFrame(frame));
+ EXPECT_EQ(max_stream_count, stream_id_manager_->outgoing_max_streams());
+}
+
+// Check that edge conditions of the stream count in a STREAMS_BLOCKED frame
+// are. properly handled.
+TEST_P(QuicStreamIdManagerTestClient, StreamsBlockedEdgeConditions) {
+ QuicStreamsBlockedFrame frame;
+ frame.unidirectional = IsUnidi();
+
+ // Check that receipt of a STREAMS BLOCKED with stream-count = 0 does nothing
+ // when max_allowed_incoming_streams is 0.
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
+ stream_id_manager_->SetMaxOpenIncomingStreams(0);
+ frame.stream_count = 0;
+ stream_id_manager_->OnStreamsBlockedFrame(frame);
+
+ // Check that receipt of a STREAMS BLOCKED with stream-count = 0 invokes a
+ // MAX STREAMS, count = 123, when the MaxOpen... is set to 123.
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(1)
+ .WillOnce(Invoke(session_.get(), &TestQuicSession::SaveFrame));
+ stream_id_manager_->SetMaxOpenIncomingStreams(123);
+ frame.stream_count = 0;
+ stream_id_manager_->OnStreamsBlockedFrame(frame);
+ EXPECT_EQ(MAX_STREAMS_FRAME, session_->save_frame().type);
+ EXPECT_EQ(123u, session_->save_frame().max_streams_frame.stream_count);
}
// Following tests all are server-specific. They depend, in some way, on
@@ -626,42 +710,13 @@ INSTANTIATE_TEST_SUITE_P(Tests, QuicStreamIdManagerTestServer, testing::Bool());
TEST_P(QuicStreamIdManagerTestServer, CheckMaxAllowedOutgoing) {
const size_t kIncomingStreamCount = 123;
stream_id_manager_->SetMaxOpenOutgoingStreams(kIncomingStreamCount);
- EXPECT_EQ(kIncomingStreamCount,
- stream_id_manager_->max_allowed_outgoing_streams());
-
- // Check that the max outgoing stream id is properly calculated
- EXPECT_EQ(stream_id_manager_->GetNextOutgoingStreamId() +
- ((kIncomingStreamCount - 1) * kV99StreamIdIncrement),
- stream_id_manager_->max_allowed_outgoing_stream_id());
+ EXPECT_EQ(kIncomingStreamCount, stream_id_manager_->outgoing_max_streams());
}
-// This test checks that the initialization for the maximum allowed incoming
-// stream id is correct.
-TEST_P(QuicStreamIdManagerTestServer, CheckMaxAllowedIncoming) {
- const size_t kIncomingStreamCount = 245;
- stream_id_manager_->SetMaxOpenIncomingStreams(kIncomingStreamCount);
- EXPECT_EQ(kIncomingStreamCount,
- stream_id_manager_->max_allowed_incoming_streams());
-
- // Check that the window is 1/2 (integer math) of the stream count.
- EXPECT_EQ((kIncomingStreamCount / 2),
- stream_id_manager_->max_stream_id_window());
-
- // Actual- and advertised- maxima start out equal.
- EXPECT_EQ(stream_id_manager_->actual_max_allowed_incoming_stream_id(),
- stream_id_manager_->advertised_max_allowed_incoming_stream_id());
-
- // First stream ID the client should use should be 3, this means that the max
- // stream id is 491 -- ((number of stream ids-1) * 2) + first available id.
- EXPECT_EQ(stream_id_manager_->first_incoming_dynamic_stream_id() +
- ((kIncomingStreamCount - 1) * kV99StreamIdIncrement),
- stream_id_manager_->actual_max_allowed_incoming_stream_id());
-}
-
-// Test that a MAX_STREAM_ID frame is generated when half the stream ids become
+// Test that a MAX_STREAMS frame is generated when half the stream ids become
// available. This has a useful side effect of testing that when streams are
// closed, the number of available stream ids increases.
-TEST_P(QuicStreamIdManagerTestServer, MaxStreamIdSlidingWindow) {
+TEST_P(QuicStreamIdManagerTestServer, MaxStreamsSlidingWindow) {
// Ignore OnStreamReset calls.
EXPECT_CALL(*connection_, OnStreamReset(_, _)).WillRepeatedly(Return());
// Capture control frames for analysis.
@@ -669,16 +724,17 @@ TEST_P(QuicStreamIdManagerTestServer, MaxStreamIdSlidingWindow) {
.WillRepeatedly(Invoke(session_.get(), &TestQuicSession::SaveFrame));
// Simulate config being negotiated, causing the limits all to be initialized.
session_->OnConfigNegotiated();
- QuicStreamId first_advert =
- stream_id_manager_->advertised_max_allowed_incoming_stream_id();
+ QuicStreamCount first_advert =
+ stream_id_manager_->incoming_advertised_max_streams();
- // Open/close enough streams to shrink the window without causing a MAX STREAM
- // ID to be generated. The window will open (and a MAX STREAM ID generated)
- // when max_stream_id_window() stream IDs have been made available. The loop
+ // Open/close enough streams to shrink the window without causing a MAX
+ // STREAMS to be generated. The window will open (and a MAX STREAMS generated)
+ // when max_streams_window() stream IDs have been made available. The loop
// will make that many stream IDs available, so the last CloseStream should
- // cause a MAX STREAM ID frame to be generated.
- int i = static_cast<int>(stream_id_manager_->max_stream_id_window());
- QuicStreamId id = stream_id_manager_->first_incoming_dynamic_stream_id();
+ // cause a MAX STREAMS frame to be generated.
+ int i = static_cast<int>(stream_id_manager_->max_streams_window());
+ QuicStreamId id =
+ QuicStreamIdManagerPeer::GetFirstIncomingStreamId(stream_id_manager_);
while (i) {
QuicStream* stream = session_->GetOrCreateStream(id);
EXPECT_NE(nullptr, stream);
@@ -687,10 +743,10 @@ TEST_P(QuicStreamIdManagerTestServer, MaxStreamIdSlidingWindow) {
// to the stream being added to the locally_closed_streams_highest_offset_
// map, and therefore not counting as truly being closed. The test requires
// that the stream truly close, so that new streams become available,
- // causing the MAX_STREAM_ID to be sent.
+ // causing the MAX_STREAMS to be sent.
stream->set_fin_received(true);
EXPECT_EQ(id, stream->id());
- if (GetParam()) {
+ if (IsBidi()) {
// Only send reset for incoming bidirectional streams.
EXPECT_CALL(*session_, SendRstStream(_, _, _));
}
@@ -698,147 +754,123 @@ TEST_P(QuicStreamIdManagerTestServer, MaxStreamIdSlidingWindow) {
i--;
id += kV99StreamIdIncrement;
}
- EXPECT_EQ(MAX_STREAM_ID_FRAME, session_->save_frame().type);
- QuicStreamId second_advert =
- session_->save_frame().max_stream_id_frame.max_stream_id;
- EXPECT_EQ(first_advert + (stream_id_manager_->max_stream_id_window() *
- kV99StreamIdIncrement),
+ EXPECT_EQ(MAX_STREAMS_FRAME, session_->save_frame().type);
+ QuicStreamCount second_advert =
+ session_->save_frame().max_streams_frame.stream_count;
+ EXPECT_EQ(first_advert + stream_id_manager_->max_streams_window(),
second_advert);
}
// Tast that an attempt to create an outgoing stream does not exceed the limit
-// and that it generates an appropriate STREAM_ID_BLOCKED frame.
+// and that it generates an appropriate STREAMS_BLOCKED frame.
TEST_P(QuicStreamIdManagerTestServer, NewStreamDoesNotExceedLimit) {
- size_t stream_count = stream_id_manager_->max_allowed_outgoing_streams();
+ size_t stream_count = stream_id_manager_->outgoing_max_streams();
EXPECT_NE(0u, stream_count);
TestQuicStream* stream;
while (stream_count) {
- stream = GetParam() ? session_->CreateOutgoingBidirectionalStream()
- : session_->CreateOutgoingUnidirectionalStream();
+ stream = IsBidi() ? session_->CreateOutgoingBidirectionalStream()
+ : session_->CreateOutgoingUnidirectionalStream();
EXPECT_NE(stream, nullptr);
stream_count--;
}
- // Quis Custodiet Ipsos Custodes.
- EXPECT_EQ(stream->id(), stream_id_manager_->max_allowed_outgoing_stream_id());
- // Create another, it should fail. Should also send a STREAM_ID_BLOCKED
+
+ EXPECT_EQ(stream_id_manager_->outgoing_stream_count(),
+ stream_id_manager_->outgoing_max_streams());
+ // Create another, it should fail. Should also send a STREAMS_BLOCKED
// control frame.
EXPECT_CALL(*connection_, SendControlFrame(_));
- stream = GetParam() ? session_->CreateOutgoingBidirectionalStream()
- : session_->CreateOutgoingUnidirectionalStream();
+ stream = IsBidi() ? session_->CreateOutgoingBidirectionalStream()
+ : session_->CreateOutgoingUnidirectionalStream();
EXPECT_EQ(nullptr, stream);
}
-// Test that a server will reject a MAX_STREAM_ID that specifies a
-// client-initiated stream ID.
-TEST_P(QuicStreamIdManagerTestServer, RejectClientMaxStreamId) {
- QuicStreamId id = stream_id_manager_->max_allowed_outgoing_stream_id();
-
- // Ensure that the ID that will be in the MAX_STREAM_ID is larger than the
- // current MAX.
- id += (kV99StreamIdIncrement * 2);
-
- // Turn it into a client-initiated ID (even).
- id &= ~0x1;
- EXPECT_TRUE(QuicUtils::IsClientInitiatedStreamId(QUIC_VERSION_99, id));
-
- // Generate a MAX_STREAM_ID frame and process it; the connection should close.
- QuicMaxStreamIdFrame frame(0, id);
- EXPECT_CALL(*connection_, CloseConnection(QUIC_MAX_STREAM_ID_ERROR, _, _));
- session_->OnMaxStreamIdFrame(frame);
-}
-
-// Test that a server will reject a STREAM_ID_BLOCKED that specifies a
-// server-initiated stream ID. STREAM_ID_BLOCKED from a client should specify an
-// even (client-initiated_ ID) generate one with an odd ID and check that the
-// connection is closed.
-TEST_P(QuicStreamIdManagerTestServer, RejectClientStreamIdBlocked) {
- QuicStreamId id = stream_id_manager_->max_allowed_outgoing_stream_id();
-
- // Ensure that the ID that will be in the MAX_STREAM_ID is larger than the
- // current MAX.
- id += (kV99StreamIdIncrement * 2);
-
- // Make the ID odd, so it looks like the client is trying to specify a
- // server-initiated ID.
- id |= 0x1;
- EXPECT_FALSE(QuicUtils::IsClientInitiatedStreamId(QUIC_VERSION_99, id));
-
- // Generate a STREAM_ID_BLOCKED frame and process it; the connection should
- // close.
- QuicStreamIdBlockedFrame frame(0, id);
- EXPECT_CALL(*connection_,
- CloseConnection(QUIC_STREAM_ID_BLOCKED_ERROR, _, _));
- session_->OnStreamIdBlockedFrame(frame);
-}
-
// Check that the parameters used by the stream ID manager are properly
// initialized
TEST_P(QuicStreamIdManagerTestServer, StreamIdManagerServerInitialization) {
// These fields are inited via the QuicSession constructor to default
// values defined as a constant.
EXPECT_EQ(kDefaultMaxStreamsPerConnection,
- stream_id_manager_->max_allowed_incoming_streams());
+ stream_id_manager_->incoming_initial_max_open_streams());
+ // If bidi, Crypto stream default created at start up, it is one
+ // more stream to account for since initialization is "number of
+ // request/responses" & crypto is added in to that, not streams.
+ // Since this is the server, the stream is incoming.
+ size_t extra_stream_count = 0;
+ if (IsBidi() && !QuicVersionUsesCryptoFrames(transport_version())) {
+ extra_stream_count = 1;
+ }
+ EXPECT_EQ(kDefaultMaxStreamsPerConnection + extra_stream_count,
+ stream_id_manager_->incoming_actual_max_streams());
EXPECT_EQ(kDefaultMaxStreamsPerConnection,
- stream_id_manager_->max_allowed_outgoing_streams());
+ stream_id_manager_->outgoing_max_streams());
// The window for advertising updates to the MAX STREAM ID is half the number
// of stream allowed.
- EXPECT_EQ(kDefaultMaxStreamsPerConnection / kMaxStreamIdWindowDivisor,
- stream_id_manager_->max_stream_id_window());
-
- // This test runs as a server, so it initiates (that is to say, outgoing)
- // even-numbered stream IDs. The -1 in the calculation is because the value
- // being tested is the maximum allowed stream ID, not the first unallowed
- // stream id.
- const QuicStreamId kExpectedMaxOutgoingStreamId =
- (GetParam() ? session_->next_outgoing_bidirectional_stream_id()
- : session_->next_outgoing_unidirectional_stream_id()) +
- ((kDefaultMaxStreamsPerConnection - 1) * kV99StreamIdIncrement);
- EXPECT_EQ(kExpectedMaxOutgoingStreamId,
- stream_id_manager_->max_allowed_outgoing_stream_id());
-
- // Same for IDs of incoming streams... But they are client initiated, so are
- // even.
- const QuicStreamId kExpectedMaxIncomingStreamId =
- GetParam() ? GetNthClientInitiatedBidirectionalId(
- kDefaultMaxStreamsPerConnection - 1)
- : GetNthClientInitiatedUnidirectionalId(
- kDefaultMaxStreamsPerConnection - 1);
- EXPECT_EQ(kExpectedMaxIncomingStreamId,
- stream_id_manager_->actual_max_allowed_incoming_stream_id());
- EXPECT_EQ(kExpectedMaxIncomingStreamId,
- stream_id_manager_->advertised_max_allowed_incoming_stream_id());
+ EXPECT_EQ(kDefaultMaxStreamsPerConnection / kMaxStreamsWindowDivisor,
+ stream_id_manager_->max_streams_window());
}
TEST_P(QuicStreamIdManagerTestServer, AvailableStreams) {
stream_id_manager_->MaybeIncreaseLargestPeerStreamId(
- GetParam() ? GetNthClientInitiatedBidirectionalId(3)
- : GetNthClientInitiatedUnidirectionalId(3));
+ IsBidi() ? GetNthClientInitiatedBidirectionalId(3)
+ : GetNthClientInitiatedUnidirectionalId(3));
EXPECT_TRUE(stream_id_manager_->IsAvailableStream(
- GetParam() ? GetNthClientInitiatedBidirectionalId(1)
- : GetNthClientInitiatedUnidirectionalId(1)));
+ IsBidi() ? GetNthClientInitiatedBidirectionalId(1)
+ : GetNthClientInitiatedUnidirectionalId(1)));
EXPECT_TRUE(stream_id_manager_->IsAvailableStream(
- GetParam() ? GetNthClientInitiatedBidirectionalId(2)
- : GetNthClientInitiatedUnidirectionalId(2)));
+ IsBidi() ? GetNthClientInitiatedBidirectionalId(2)
+ : GetNthClientInitiatedUnidirectionalId(2)));
}
// Tests that if MaybeIncreaseLargestPeerStreamId is given an extremely
// large stream ID (larger than the limit) it is rejected.
// This is a regression for Chromium bugs 909987 and 910040
TEST_P(QuicStreamIdManagerTestServer, ExtremeMaybeIncreaseLargestPeerStreamId) {
- QuicStreamId too_big_stream_id =
- stream_id_manager_->actual_max_allowed_incoming_stream_id() +
- kV99StreamIdIncrement * 20;
+ QuicStreamId too_big_stream_id = StreamCountToId(
+ stream_id_manager_->incoming_actual_max_streams() + 20,
+ Perspective::IS_CLIENT); // This node is a server, incoming stream
+ // ids must be client-originated.
+ std::string error_details;
+ if (IsBidi()) {
+ if (QuicVersionUsesCryptoFrames(transport_version())) {
+ error_details = "Stream id 476 would exceed stream count limit 100";
+ } else {
+ error_details = "Stream id 480 would exceed stream count limit 101";
+ }
+ } else {
+ error_details = "Stream id 478 would exceed stream count limit 100";
+ }
- std::string error_details =
- GetParam() ? "Stream id 480 above 400" : "Stream id 478 above 398";
EXPECT_CALL(*connection_,
CloseConnection(QUIC_INVALID_STREAM_ID, error_details, _));
-
EXPECT_FALSE(
stream_id_manager_->MaybeIncreaseLargestPeerStreamId(too_big_stream_id));
}
+// Check that the OnMaxStreamFrame logic properly handles all the
+// cases of offered max streams and outgoing_static_stream_count_,
+// checking for the wrap conditions. Tests in server perspective, necessary
+// because internally, some calculations depend on the client/server
+// perspective.
+TEST_P(QuicStreamIdManagerTestServer, TestMaxStreamsWrapChecks) {
+ QuicStreamCount max_stream_count =
+ QuicUtils::GetMaxStreamCount(IsUnidi(), Perspective::IS_SERVER);
+ QuicMaxStreamsFrame frame;
+ frame.unidirectional = IsUnidi();
+
+ // Check the case where the offered stream count is less than the
+ // implementation maximum,
+ frame.stream_count = max_stream_count - 10;
+ EXPECT_TRUE(stream_id_manager_->OnMaxStreamsFrame(frame));
+ EXPECT_EQ(max_stream_count - 10u, stream_id_manager_->outgoing_max_streams());
+
+ // Check the case where the offered stream count is greater than the
+ // implementation maximum. The count should peg at the maximum.
+ frame.stream_count = max_stream_count + 10;
+ EXPECT_TRUE(stream_id_manager_->OnMaxStreamsFrame(frame));
+ EXPECT_EQ(max_stream_count, stream_id_manager_->outgoing_max_streams());
+}
+
} // namespace
} // namespace test
} // namespace quic
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 57e2bd1802a..3a5efb50e7f 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
@@ -48,7 +48,7 @@ class QuicStreamSendBufferTest : public QuicTest {
QuicStreamSendBufferPeer::CurrentWriteSlice(&send_buffer_));
// Save all data.
- SetQuicFlag(&FLAGS_quic_send_buffer_max_data_slice_size, 1024);
+ SetQuicFlag(FLAGS_quic_send_buffer_max_data_slice_size, 1024);
send_buffer_.SaveStreamData(iov, 2, 0, 2048);
send_buffer_.SaveMemSlice(std::move(slice1));
EXPECT_TRUE(slice1.empty());
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.cc
index d42ee20de5d..7f0f2cbf22d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.cc
@@ -34,9 +34,7 @@ QuicStreamSequencerBuffer::QuicStreamSequencerBuffer(size_t max_capacity_bytes)
blocks_count_(CalculateBlockCount(max_capacity_bytes)),
total_bytes_read_(0),
blocks_(nullptr),
- total_bytes_prefetched_(0),
- faster_interval_add_in_sequence_buffer_(
- GetQuicReloadableFlag(quic_faster_interval_add_in_sequence_buffer)) {
+ total_bytes_prefetched_(0) {
Clear();
}
@@ -90,35 +88,15 @@ QuicErrorCode QuicStreamSequencerBuffer::OnStreamData(
bytes_received_.IsDisjoint(QuicInterval<QuicStreamOffset>(
starting_offset, starting_offset + size))) {
// Optimization for the typical case, when all data is newly received.
- if (faster_interval_add_in_sequence_buffer_) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_faster_interval_add_in_sequence_buffer);
- bytes_received_.AddOptimizedForAppend(starting_offset,
- starting_offset + size);
- if (bytes_received_.Size() >= kMaxNumDataIntervalsAllowed) {
- // This frame is going to create more intervals than allowed. Stop
- // processing.
- *error_details = "Too many data intervals received for this stream.";
- return QUIC_TOO_MANY_STREAM_DATA_INTERVALS;
- }
- } else {
- if (!bytes_received_.Empty() &&
- starting_offset == bytes_received_.rbegin()->max()) {
- // Extend the right edge of last interval.
- // TODO(fayang): Encapsulate this into a future version of
- // QuicIntervalSet if this is more efficient than Add.
- const_cast<QuicInterval<QuicStreamOffset>*>(
- &(*bytes_received_.rbegin()))
- ->SetMax(starting_offset + size);
- } else {
- bytes_received_.Add(starting_offset, starting_offset + size);
- if (bytes_received_.Size() >= kMaxNumDataIntervalsAllowed) {
- // This frame is going to create more intervals than allowed. Stop
- // processing.
- *error_details = "Too many data intervals received for this stream.";
- return QUIC_TOO_MANY_STREAM_DATA_INTERVALS;
- }
- }
+ bytes_received_.AddOptimizedForAppend(starting_offset,
+ starting_offset + size);
+ if (bytes_received_.Size() >= kMaxNumDataIntervalsAllowed) {
+ // This frame is going to create more intervals than allowed. Stop
+ // processing.
+ *error_details = "Too many data intervals received for this stream.";
+ return QUIC_TOO_MANY_STREAM_DATA_INTERVALS;
}
+
size_t bytes_copy = 0;
if (!CopyStreamData(starting_offset, data, &bytes_copy, error_details)) {
return QUIC_STREAM_SEQUENCER_INVALID_STATE;
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 6f4717d8ca6..08a1ab4a640 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
@@ -239,9 +239,6 @@ class QUIC_EXPORT_PRIVATE QuicStreamSequencerBuffer {
// Total number of bytes that have been prefetched.
QuicStreamOffset total_bytes_prefetched_;
-
- // Latched value of --quic_faster_interval_add_in_sequence_buffer.
- const bool faster_interval_add_in_sequence_buffer_;
};
} // namespace quic
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 aa30b5107ef..335aa2dd3d8 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
@@ -11,7 +11,6 @@
#include <string>
#include <utility>
-#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
@@ -36,10 +35,10 @@ char GetCharFromIOVecs(size_t offset, iovec iov[], size_t count) {
}
start_offset += iov[i].iov_len;
}
- LOG(ERROR) << "Could not locate char at offset " << offset << " in " << count
- << " iovecs";
+ QUIC_LOG(ERROR) << "Could not locate char at offset " << offset << " in "
+ << count << " iovecs";
for (size_t i = 0; i < count; ++i) {
- LOG(ERROR) << " iov[" << i << "].iov_len = " << iov[i].iov_len;
+ QUIC_LOG(ERROR) << " iov[" << i << "].iov_len = " << iov[i].iov_len;
}
return '\0';
}
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 d1b442ed888..9b32012e319 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
@@ -49,8 +49,8 @@ class TestStream : public QuicStream {
TestStream(QuicStreamId id, QuicSession* session, StreamType type)
: QuicStream(id, session, /*is_static=*/false, type) {}
- TestStream(PendingStream pending, StreamType type)
- : QuicStream(std::move(pending), type) {}
+ TestStream(PendingStream pending, StreamType type, bool is_static)
+ : QuicStream(std::move(pending), type, is_static) {}
void OnDataAvailable() override {}
@@ -171,6 +171,18 @@ INSTANTIATE_TEST_SUITE_P(QuicParameterizedStreamTests,
QuicParameterizedStreamTest,
::testing::ValuesIn(AllSupportedVersions()));
+TEST_P(QuicStreamTest, PendingStreamStaticness) {
+ Initialize();
+
+ PendingStream pending(kTestStreamId + 2, session_.get());
+ TestStream stream(std::move(pending), StreamType::BIDIRECTIONAL, false);
+ EXPECT_FALSE(stream.is_static());
+
+ PendingStream pending2(kTestStreamId + 3, session_.get());
+ TestStream stream2(std::move(pending2), StreamType::BIDIRECTIONAL, true);
+ EXPECT_TRUE(stream2.is_static());
+}
+
TEST_P(QuicStreamTest, PendingStreamTooMuchData) {
Initialize();
@@ -228,7 +240,7 @@ TEST_P(QuicStreamTest, FromPendingStream) {
QuicStreamFrame frame2(kTestStreamId + 2, true, 3, QuicStringPiece("."));
pending.OnStreamFrame(frame2);
- TestStream stream(std::move(pending), StreamType::READ_UNIDIRECTIONAL);
+ TestStream stream(std::move(pending), StreamType::READ_UNIDIRECTIONAL, false);
EXPECT_EQ(3, stream.num_frames_received());
EXPECT_EQ(3u, stream.stream_bytes_read());
EXPECT_EQ(1, stream.num_duplicate_frames_received());
@@ -247,8 +259,8 @@ TEST_P(QuicStreamTest, FromPendingStreamThenData) {
QuicStreamFrame frame(kTestStreamId + 2, false, 2, QuicStringPiece("."));
pending.OnStreamFrame(frame);
- auto stream =
- new TestStream(std::move(pending), StreamType::READ_UNIDIRECTIONAL);
+ auto stream = new TestStream(std::move(pending),
+ StreamType::READ_UNIDIRECTIONAL, false);
session_->ActivateStream(QuicWrapUnique(stream));
QuicStreamFrame frame2(kTestStreamId + 2, true, 3, QuicStringPiece("."));
@@ -956,7 +968,7 @@ TEST_P(QuicStreamTest, ConnectionClosed) {
}
TEST_P(QuicStreamTest, CanWriteNewDataAfterData) {
- SetQuicFlag(&FLAGS_quic_buffered_data_threshold, 100);
+ SetQuicFlag(FLAGS_quic_buffered_data_threshold, 100);
Initialize();
EXPECT_TRUE(stream_->CanWriteNewDataAfterData(99));
EXPECT_FALSE(stream_->CanWriteNewDataAfterData(100));
@@ -964,7 +976,7 @@ TEST_P(QuicStreamTest, CanWriteNewDataAfterData) {
TEST_P(QuicStreamTest, WriteBufferedData) {
// Set buffered data low water mark to be 100.
- SetQuicFlag(&FLAGS_quic_buffered_data_threshold, 100);
+ SetQuicFlag(FLAGS_quic_buffered_data_threshold, 100);
// Do not stream level flow control block this stream.
set_initial_flow_control_window_bytes(500000);
@@ -1006,7 +1018,8 @@ TEST_P(QuicStreamTest, WriteBufferedData) {
// Buffered data size < threshold, ask upper layer for more data.
EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
stream_->OnCanWrite();
- EXPECT_EQ(GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1,
+ EXPECT_EQ(static_cast<uint64_t>(
+ GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1),
stream_->BufferedDataBytes());
EXPECT_TRUE(stream_->CanWriteNewData());
@@ -1055,7 +1068,8 @@ TEST_P(QuicStreamTest, WriteBufferedData) {
EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
stream_->OnCanWrite();
- EXPECT_EQ(GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1,
+ EXPECT_EQ(static_cast<uint64_t>(
+ GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1),
stream_->BufferedDataBytes());
EXPECT_TRUE(stream_->CanWriteNewData());
@@ -1096,7 +1110,7 @@ TEST_P(QuicStreamTest, WritevDataReachStreamLimit) {
TEST_P(QuicStreamTest, WriteMemSlices) {
// Set buffered data low water mark to be 100.
- SetQuicFlag(&FLAGS_quic_buffered_data_threshold, 100);
+ SetQuicFlag(FLAGS_quic_buffered_data_threshold, 100);
// Do not flow control block this stream.
set_initial_flow_control_window_bytes(500000);
@@ -1139,7 +1153,8 @@ TEST_P(QuicStreamTest, WriteMemSlices) {
}));
EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
stream_->OnCanWrite();
- EXPECT_EQ(GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1,
+ EXPECT_EQ(static_cast<uint64_t>(
+ GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1),
stream_->BufferedDataBytes());
// Try to write slices2 again.
EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(0);
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_time.cc b/chromium/net/third_party/quiche/src/quic/core/quic_time.cc
index 25cd56092e3..ffc59dadf9b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_time.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_time.cc
@@ -13,7 +13,7 @@
namespace quic {
-std::string QuicTime::Delta::ToDebugValue() const {
+std::string QuicTime::Delta::ToDebuggingValue() const {
const int64_t one_ms = 1000;
const int64_t one_s = 1000 * one_ms;
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 cd33649be5c..9a5ae7dd5b2 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
@@ -75,7 +75,7 @@ class QUIC_EXPORT_PRIVATE QuicTime {
return time_offset_ == kQuicInfiniteTimeUs;
}
- std::string ToDebugValue() const;
+ std::string ToDebuggingValue() const;
private:
friend inline bool operator==(QuicTime::Delta lhs, QuicTime::Delta rhs);
@@ -275,7 +275,7 @@ inline QuicTime::Delta operator-(QuicTime lhs, QuicTime rhs) {
// Override stream output operator for gtest.
inline std::ostream& operator<<(std::ostream& output,
const QuicTime::Delta delta) {
- output << delta.ToDebugValue();
+ output << delta.ToDebuggingValue();
return output;
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_time_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_time_test.cc
index 97205325a95..2e2838a4b51 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_time_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_time_test.cc
@@ -82,18 +82,18 @@ TEST_F(QuicTimeDeltaTest, NotEqual) {
QuicTime::Delta::FromSeconds(0));
}
-TEST_F(QuicTimeDeltaTest, DebugValue) {
+TEST_F(QuicTimeDeltaTest, DebuggingValue) {
const QuicTime::Delta one_us = QuicTime::Delta::FromMicroseconds(1);
const QuicTime::Delta one_ms = QuicTime::Delta::FromMilliseconds(1);
const QuicTime::Delta one_s = QuicTime::Delta::FromSeconds(1);
- EXPECT_EQ("3s", (3 * one_s).ToDebugValue());
- EXPECT_EQ("3ms", (3 * one_ms).ToDebugValue());
- EXPECT_EQ("3us", (3 * one_us).ToDebugValue());
+ EXPECT_EQ("3s", (3 * one_s).ToDebuggingValue());
+ EXPECT_EQ("3ms", (3 * one_ms).ToDebuggingValue());
+ EXPECT_EQ("3us", (3 * one_us).ToDebuggingValue());
- EXPECT_EQ("3001us", (3 * one_ms + one_us).ToDebugValue());
- EXPECT_EQ("3001ms", (3 * one_s + one_ms).ToDebugValue());
- EXPECT_EQ("3000001us", (3 * one_s + one_us).ToDebugValue());
+ EXPECT_EQ("3001us", (3 * one_ms + one_us).ToDebuggingValue());
+ EXPECT_EQ("3001ms", (3 * one_s + one_ms).ToDebuggingValue());
+ EXPECT_EQ("3000001us", (3 * one_s + one_us).ToDebuggingValue());
}
class QuicTimeTest : public QuicTest {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.cc
index 6fba2ebe5e0..f1f6dcf2678 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.cc
@@ -22,6 +22,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
namespace quic {
@@ -161,18 +162,15 @@ void QuicTimeWaitListManager::ProcessPacket(
if (connection_data->encryption_level == ENCRYPTION_INITIAL) {
QUIC_CODE_COUNT(
quic_encryption_none_termination_packets_for_short_header);
- if (GetQuicReloadableFlag(quic_always_reset_short_header_packets)) {
- QUIC_RELOADABLE_FLAG_COUNT(
- quic_always_reset_short_header_packets);
- // Send stateless reset in response to short header packets,
- // because ENCRYPTION_INITIAL termination packets will not be
- // processed by clients.
- SendPublicReset(self_address, peer_address, connection_id,
- connection_data->ietf_quic,
- std::move(packet_context));
- return;
- }
- } else if (connection_data->encryption_level == ENCRYPTION_ZERO_RTT) {
+ // Send stateless reset in response to short header packets,
+ // because ENCRYPTION_INITIAL termination packets will not be
+ // processed by clients.
+ SendPublicReset(self_address, peer_address, connection_id,
+ connection_data->ietf_quic,
+ std::move(packet_context));
+ return;
+ }
+ if (connection_data->encryption_level == ENCRYPTION_ZERO_RTT) {
QUIC_CODE_COUNT(quic_zero_rtt_termination_packets_for_short_header);
}
break;
@@ -203,16 +201,24 @@ void QuicTimeWaitListManager::ProcessPacket(
}
void QuicTimeWaitListManager::SendVersionNegotiationPacket(
- QuicConnectionId connection_id,
+ QuicConnectionId server_connection_id,
+ QuicConnectionId client_connection_id,
bool ietf_quic,
const ParsedQuicVersionVector& supported_versions,
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
std::unique_ptr<QuicPerPacketContext> packet_context) {
- SendOrQueuePacket(QuicMakeUnique<QueuedPacket>(
- self_address, peer_address,
- QuicFramer::BuildVersionNegotiationPacket(
- connection_id, ietf_quic, supported_versions)),
+ std::unique_ptr<QuicEncryptedPacket> version_packet =
+ QuicFramer::BuildVersionNegotiationPacket(server_connection_id,
+ client_connection_id, ietf_quic,
+ supported_versions);
+ QUIC_DVLOG(2) << "Dispatcher sending version negotiation packet: {"
+ << ParsedQuicVersionVectorToString(supported_versions) << "}, "
+ << (ietf_quic ? "" : "!") << "ietf_quic:" << std::endl
+ << QuicTextUtils::HexDump(QuicStringPiece(
+ version_packet->data(), version_packet->length()));
+ SendOrQueuePacket(QuicMakeUnique<QueuedPacket>(self_address, peer_address,
+ std::move(version_packet)),
packet_context.get());
}
@@ -229,10 +235,17 @@ void QuicTimeWaitListManager::SendPublicReset(
bool ietf_quic,
std::unique_ptr<QuicPerPacketContext> packet_context) {
if (ietf_quic) {
- SendOrQueuePacket(QuicMakeUnique<QueuedPacket>(
- self_address, peer_address,
- BuildIetfStatelessResetPacket(connection_id)),
- packet_context.get());
+ std::unique_ptr<QuicEncryptedPacket> ietf_reset_packet =
+ BuildIetfStatelessResetPacket(connection_id);
+ QUIC_DVLOG(2) << "Dispatcher sending IETF reset packet for "
+ << connection_id << std::endl
+ << QuicTextUtils::HexDump(
+ QuicStringPiece(ietf_reset_packet->data(),
+ ietf_reset_packet->length()));
+ SendOrQueuePacket(
+ QuicMakeUnique<QueuedPacket>(self_address, peer_address,
+ std::move(ietf_reset_packet)),
+ packet_context.get());
return;
}
QuicPublicResetPacket packet;
@@ -243,8 +256,13 @@ void QuicTimeWaitListManager::SendPublicReset(
packet.client_address = peer_address;
GetEndpointId(&packet.endpoint_id);
// Takes ownership of the packet.
+ std::unique_ptr<QuicEncryptedPacket> reset_packet = BuildPublicReset(packet);
+ QUIC_DVLOG(2) << "Dispatcher sending reset packet for " << connection_id
+ << std::endl
+ << QuicTextUtils::HexDump(QuicStringPiece(
+ reset_packet->data(), reset_packet->length()));
SendOrQueuePacket(QuicMakeUnique<QueuedPacket>(self_address, peer_address,
- BuildPublicReset(packet)),
+ std::move(reset_packet)),
packet_context.get());
}
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 dee5d11de43..ba0c76336aa 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
@@ -118,10 +118,12 @@ class QuicTimeWaitListManager : public QuicBlockedWriterInterface {
// The number of connections on the time-wait list.
size_t num_connections() const { return connection_id_map_.size(); }
- // Sends a version negotiation packet for |connection_id| announcing support
- // for |supported_versions| to |peer_address| from |self_address|.
+ // Sends a version negotiation packet for |server_connection_id| and
+ // |client_connection_id| announcing support for |supported_versions| to
+ // |peer_address| from |self_address|.
virtual void SendVersionNegotiationPacket(
- QuicConnectionId connection_id,
+ QuicConnectionId server_connection_id,
+ QuicConnectionId client_connection_id,
bool ietf_quic,
const ParsedQuicVersionVector& supported_versions,
const QuicSocketAddress& self_address,
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager_test.cc
index aa0c911ee9b..4624a236503 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager_test.cc
@@ -251,15 +251,50 @@ TEST_F(QuicTimeWaitListManagerTest, CheckStatelessConnectionIdInTimeWait) {
TEST_F(QuicTimeWaitListManagerTest, SendVersionNegotiationPacket) {
std::unique_ptr<QuicEncryptedPacket> packet(
- QuicFramer::BuildVersionNegotiationPacket(connection_id_, false,
+ QuicFramer::BuildVersionNegotiationPacket(connection_id_,
+ EmptyQuicConnectionId(), false,
AllSupportedVersions()));
EXPECT_CALL(writer_, WritePacket(_, packet->length(), self_address_.host(),
peer_address_, _))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
time_wait_list_manager_.SendVersionNegotiationPacket(
- connection_id_, false, AllSupportedVersions(), self_address_,
- peer_address_, QuicMakeUnique<QuicPerPacketContext>());
+ connection_id_, EmptyQuicConnectionId(), false, AllSupportedVersions(),
+ self_address_, peer_address_, QuicMakeUnique<QuicPerPacketContext>());
+ EXPECT_EQ(0u, time_wait_list_manager_.num_connections());
+}
+
+TEST_F(QuicTimeWaitListManagerTest, SendIetfVersionNegotiationPacket) {
+ std::unique_ptr<QuicEncryptedPacket> packet(
+ QuicFramer::BuildVersionNegotiationPacket(connection_id_,
+ EmptyQuicConnectionId(), true,
+ AllSupportedVersions()));
+ EXPECT_CALL(writer_, WritePacket(_, packet->length(), self_address_.host(),
+ peer_address_, _))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
+
+ time_wait_list_manager_.SendVersionNegotiationPacket(
+ connection_id_, EmptyQuicConnectionId(), true, AllSupportedVersions(),
+ self_address_, peer_address_, QuicMakeUnique<QuicPerPacketContext>());
+ EXPECT_EQ(0u, time_wait_list_manager_.num_connections());
+}
+
+TEST_F(QuicTimeWaitListManagerTest,
+ SendIetfVersionNegotiationPacketWithClientConnectionId) {
+ // Client connection IDs cannot be used unless this flag is true.
+ SetQuicRestartFlag(quic_do_not_override_connection_id, true);
+
+ std::unique_ptr<QuicEncryptedPacket> packet(
+ QuicFramer::BuildVersionNegotiationPacket(connection_id_,
+ TestConnectionId(0x33), true,
+ AllSupportedVersions()));
+ EXPECT_CALL(writer_, WritePacket(_, packet->length(), self_address_.host(),
+ peer_address_, _))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
+
+ time_wait_list_manager_.SendVersionNegotiationPacket(
+ connection_id_, TestConnectionId(0x33), true, AllSupportedVersions(),
+ self_address_, peer_address_, QuicMakeUnique<QuicPerPacketContext>());
EXPECT_EQ(0u, time_wait_list_manager_.num_connections());
}
@@ -560,18 +595,11 @@ TEST_F(QuicTimeWaitListManagerTest,
QuicTimeWaitListManager::SEND_TERMINATION_PACKETS, ENCRYPTION_INITIAL,
&termination_packets);
- if (GetQuicReloadableFlag(quic_always_reset_short_header_packets)) {
- // Termination packet is not encrypted, instead, send stateless reset.
- EXPECT_CALL(writer_,
- WritePacket(_, _, self_address_.host(), peer_address_, _))
- .With(Args<0, 1>(PublicResetPacketEq(connection_id_)))
- .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
- } else {
- // An unprocessable connection close is sent to peer.
- EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength,
- self_address_.host(), peer_address_, _))
- .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
- }
+ // Termination packet is not encrypted, instead, send stateless reset.
+ EXPECT_CALL(writer_,
+ WritePacket(_, _, self_address_.host(), peer_address_, _))
+ .With(Args<0, 1>(PublicResetPacketEq(connection_id_)))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
// Processes IETF short header packet.
time_wait_list_manager_.ProcessPacket(
self_address_, peer_address_, connection_id_,
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 5fdab2d6f37..8b1b62a6278 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
@@ -78,8 +78,8 @@ void QuicTraceVisitor::OnPacketSent(const SerializedPacket& serialized_packet,
// New IETF frames, not used in current gQUIC version.
case NEW_CONNECTION_ID_FRAME:
case RETIRE_CONNECTION_ID_FRAME:
- case MAX_STREAM_ID_FRAME:
- case STREAM_ID_BLOCKED_FRAME:
+ case MAX_STREAMS_FRAME:
+ case STREAMS_BLOCKED_FRAME:
case PATH_RESPONSE_FRAME:
case PATH_CHALLENGE_FRAME:
case STOP_SENDING_FRAME:
@@ -208,8 +208,8 @@ void QuicTraceVisitor::PopulateFrameInfo(const QuicFrame& frame,
// New IETF frames, not used in current gQUIC version.
case NEW_CONNECTION_ID_FRAME:
case RETIRE_CONNECTION_ID_FRAME:
- case MAX_STREAM_ID_FRAME:
- case STREAM_ID_BLOCKED_FRAME:
+ case MAX_STREAMS_FRAME:
+ case STREAMS_BLOCKED_FRAME:
case PATH_RESPONSE_FRAME:
case PATH_CHALLENGE_FRAME:
case STOP_SENDING_FRAME:
@@ -278,7 +278,9 @@ void QuicTraceVisitor::OnApplicationLimited() {
}
void QuicTraceVisitor::OnAdjustNetworkParameters(QuicBandwidth bandwidth,
- QuicTime::Delta rtt) {
+ QuicTime::Delta rtt,
+ QuicByteCount old_cwnd,
+ QuicByteCount new_cwnd) {
quic_trace::Event* event = trace_.add_events();
event->set_time_us(
ConvertTimestampToRecordedFormat(connection_->clock()->ApproximateNow()));
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 a70b150d653..8021865f852 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
@@ -42,7 +42,9 @@ class QuicTraceVisitor : public QuicConnectionDebugVisitor {
void OnApplicationLimited() override;
void OnAdjustNetworkParameters(QuicBandwidth bandwidth,
- QuicTime::Delta rtt) override;
+ QuicTime::Delta rtt,
+ QuicByteCount old_cwnd,
+ QuicByteCount new_cwnd) override;
// Returns a mutable pointer to the trace. The trace is owned by the
// visitor, but can be moved using Swap() method after the connection is
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor_test.cc
index 1a581534a9c..5e771336d9c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_trace_visitor_test.cc
@@ -4,8 +4,6 @@
#include "net/third_party/quiche/src/quic/core/quic_trace_visitor.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/quic/core/quic_constants.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"
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 c9e21d6190f..102b60ecf63 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
@@ -31,6 +31,12 @@ std::ostream& operator<<(std::ostream& os, const AckedPacket& acked_packet) {
return os;
}
+std::ostream& operator<<(std::ostream& os, const LostPacket& lost_packet) {
+ os << "{ packet_number: " << lost_packet.packet_number
+ << ", bytes_lost: " << lost_packet.bytes_lost << "} ";
+ return os;
+}
+
std::string HistogramEnumString(WriteStatus enum_value) {
switch (enum_value) {
case WRITE_STATUS_OK:
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 6f4cbe615c2..66a90c16562 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
@@ -27,6 +27,10 @@ typedef uint32_t QuicMessageId;
// TODO(fkastenholz): Should update this to 64 bits for V99.
typedef uint32_t QuicStreamId;
+// Count of stream IDs. Used in MAX_STREAMS and STREAMS_BLOCKED
+// frames.
+typedef uint32_t QuicStreamCount;
+
typedef uint64_t QuicByteCount;
typedef uint64_t QuicPacketCount;
typedef uint64_t QuicPublicResetNonceProof;
@@ -169,8 +173,7 @@ enum class ConnectionCloseSource { FROM_PEER, FROM_SELF };
// Should a connection be closed silently or not.
enum class ConnectionCloseBehavior {
SILENT_CLOSE,
- SEND_CONNECTION_CLOSE_PACKET,
- SEND_CONNECTION_CLOSE_PACKET_WITH_NO_ACK
+ SEND_CONNECTION_CLOSE_PACKET
};
enum QuicFrameType : uint8_t {
@@ -198,8 +201,8 @@ enum QuicFrameType : uint8_t {
// QUIC has been negotiated. Values are not important, they are not
// the values that are in the packets (see QuicIetfFrameType, below).
NEW_CONNECTION_ID_FRAME,
- MAX_STREAM_ID_FRAME,
- STREAM_ID_BLOCKED_FRAME,
+ MAX_STREAMS_FRAME,
+ STREAMS_BLOCKED_FRAME,
PATH_RESPONSE_FRAME,
PATH_CHALLENGE_FRAME,
STOP_SENDING_FRAME,
@@ -296,6 +299,7 @@ enum QuicPacketNumberLength : uint8_t {
PACKET_2BYTE_PACKET_NUMBER = 2,
PACKET_3BYTE_PACKET_NUMBER = 3, // Used in version > QUIC_VERSION_44.
PACKET_4BYTE_PACKET_NUMBER = 4,
+ IETF_MAX_PACKET_NUMBER_LENGTH = 4,
// TODO(rch): Remove this when we remove QUIC_VERSION_39.
PACKET_6BYTE_PACKET_NUMBER = 6,
PACKET_8BYTE_PACKET_NUMBER = 8
@@ -386,6 +390,10 @@ enum EncryptionLevel : int8_t {
NUM_ENCRYPTION_LEVELS,
};
+inline bool EncryptionLevelIsValid(EncryptionLevel level) {
+ return ENCRYPTION_INITIAL <= level && level < NUM_ENCRYPTION_LEVELS;
+}
+
enum AddressChangeType : uint8_t {
// IP address and port remain unchanged.
NO_CHANGE,
@@ -476,6 +484,10 @@ struct LostPacket {
LostPacket(QuicPacketNumber packet_number, QuicPacketLength bytes_lost)
: packet_number(packet_number), bytes_lost(bytes_lost) {}
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const LostPacket& lost_packet);
+
QuicPacketNumber packet_number;
// Number of bytes sent in the packet that was lost.
QuicPacketLength bytes_lost;
@@ -572,6 +584,9 @@ enum StreamType {
// Unidirectional streams carry data in one direction only.
WRITE_UNIDIRECTIONAL,
READ_UNIDIRECTIONAL,
+ // Not actually a stream type. Used only by QuicCryptoStream when it uses
+ // CRYPTO frames and isn't actually a QuicStream.
+ CRYPTO,
};
// A packet number space is the context in which a packet can be processed and
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 413a2446642..a7fe40f6730 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,6 +15,7 @@
#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"
@@ -382,14 +383,23 @@ QuicStreamId QuicUtils::GetInvalidStreamId(QuicTransportVersion version) {
// static
QuicStreamId QuicUtils::GetCryptoStreamId(QuicTransportVersion version) {
- // TODO(nharper): Change this to return GetInvalidStreamId for version 47 or
- // greater. Currently, too many things break with that change.
- return version == QUIC_VERSION_99 ? 0 : 1;
+ QUIC_BUG_IF(QuicVersionUsesCryptoFrames(version))
+ << "CRYPTO data aren't in stream frames; they have no stream ID.";
+ return QuicVersionUsesCryptoFrames(version) ? GetInvalidStreamId(version) : 1;
+}
+
+// static
+bool QuicUtils::IsCryptoStreamId(QuicTransportVersion version,
+ QuicStreamId stream_id) {
+ if (QuicVersionUsesCryptoFrames(version)) {
+ return false;
+ }
+ return stream_id == GetCryptoStreamId(version);
}
// static
QuicStreamId QuicUtils::GetHeadersStreamId(QuicTransportVersion version) {
- return version == QUIC_VERSION_99 ? 4 : 3;
+ return GetFirstBidirectionalStreamId(version, Perspective::IS_CLIENT);
}
// static
@@ -451,18 +461,26 @@ QuicStreamId QuicUtils::StreamIdDelta(QuicTransportVersion version) {
QuicStreamId QuicUtils::GetFirstBidirectionalStreamId(
QuicTransportVersion version,
Perspective perspective) {
- if (perspective == Perspective::IS_CLIENT) {
- return version == QUIC_VERSION_99 ? 4 : 3;
+ if (version == QUIC_VERSION_99) {
+ return perspective == Perspective::IS_CLIENT ? 0 : 1;
+ } else if (QuicVersionUsesCryptoFrames(version)) {
+ return perspective == Perspective::IS_CLIENT ? 1 : 2;
}
- return version == QUIC_VERSION_99 ? 1 : 2;
+ return perspective == Perspective::IS_CLIENT ? 3 : 2;
}
// static
QuicStreamId QuicUtils::GetFirstUnidirectionalStreamId(
QuicTransportVersion version,
Perspective perspective) {
+ if (version == QUIC_VERSION_99) {
+ return perspective == Perspective::IS_CLIENT ? 2 : 3;
+ } else if (QuicVersionUsesCryptoFrames(version)) {
+ return perspective == Perspective::IS_CLIENT ? 1 : 2;
+ }
+ return perspective == Perspective::IS_CLIENT ? 3 : 2;
if (perspective == Perspective::IS_CLIENT) {
- return version == QUIC_VERSION_99 ? 2 : 3;
+ return version == QUIC_VERSION_99 ? 2 : 1;
}
return version == QUIC_VERSION_99 ? 3 : 2;
}
@@ -505,7 +523,16 @@ QuicConnectionId QuicUtils::CreateRandomConnectionId(
// static
bool QuicUtils::VariableLengthConnectionIdAllowedForVersion(
QuicTransportVersion version) {
- return version >= QUIC_VERSION_47;
+ if (!GetQuicRestartFlag(
+ quic_allow_variable_length_connection_id_for_negotiation)) {
+ return version >= QUIC_VERSION_47;
+ }
+ QUIC_RESTART_FLAG_COUNT(
+ quic_allow_variable_length_connection_id_for_negotiation);
+ // 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;
}
// static
@@ -543,6 +570,24 @@ QuicUint128 QuicUtils::GenerateStatelessResetToken(
QuicEndian::NetToHost64(data_bytes[0]));
}
+// Returns the maximum value that a stream count may have, taking into account
+// the fact that bidirectional, client initiated, streams have one fewer stream
+// available than the others. This is because the old crypto streams, with ID ==
+// 0 are not included in the count.
+// The version is not included in the call, nor does the method take the version
+// into account, because this is called only from code used for IETF QUIC.
+// TODO(fkastenholz): Remove this method and replace calls to it with direct
+// references to kMaxQuicStreamIdCount when streamid 0 becomes a normal stream
+// id.
+// static
+QuicStreamCount QuicUtils::GetMaxStreamCount(bool unidirectional,
+ Perspective perspective) {
+ if (!unidirectional && perspective == Perspective::IS_CLIENT) {
+ return kMaxQuicStreamCount >> 2;
+ }
+ return (kMaxQuicStreamCount >> 2) + 1;
+}
+
// static
PacketNumberSpace QuicUtils::GetPacketNumberSpace(
EncryptionLevel encryption_level) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_utils.h b/chromium/net/third_party/quiche/src/quic/core/quic_utils.h
index cacbc60219a..bac025e79a0 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_utils.h
@@ -116,6 +116,11 @@ class QUIC_EXPORT_PRIVATE QuicUtils {
// Returns crypto stream ID of |version|.
static QuicStreamId GetCryptoStreamId(QuicTransportVersion version);
+ // Returns whether |id| is the stream ID for the crypto stream. If |version|
+ // is a version where crypto data doesn't go over stream frames, this function
+ // will always return false.
+ static bool IsCryptoStreamId(QuicTransportVersion version, QuicStreamId id);
+
// Returns headers stream ID of |version|.
static QuicStreamId GetHeadersStreamId(QuicTransportVersion version);
@@ -190,6 +195,12 @@ class QUIC_EXPORT_PRIVATE QuicUtils {
// Determines encryption level to send packets in |packet_number_space|.
static EncryptionLevel GetEncryptionLevel(
PacketNumberSpace packet_number_space);
+
+ // Get the maximum value for a V99/IETF QUIC stream count. If a count
+ // exceeds this value, it will result in a stream ID that exceeds the
+ // implementation limit on stream ID size.
+ static QuicStreamCount GetMaxStreamCount(bool unidirectional,
+ Perspective perspective);
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc
index 62b2e44dd7a..5874f92abb7 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
@@ -18,7 +18,6 @@ QuicVersionManager::QuicVersionManager(
enable_version_47_(GetQuicReloadableFlag(quic_enable_version_47)),
enable_version_46_(GetQuicReloadableFlag(quic_enable_version_46)),
enable_version_44_(GetQuicReloadableFlag(quic_enable_version_44)),
- enable_version_43_(GetQuicReloadableFlag(quic_enable_version_43)),
disable_version_39_(GetQuicReloadableFlag(quic_disable_version_39)),
allowed_supported_versions_(std::move(supported_versions)) {
RefilterSupportedVersions();
@@ -42,13 +41,11 @@ void QuicVersionManager::MaybeRefilterSupportedVersions() {
enable_version_47_ != GetQuicReloadableFlag(quic_enable_version_47) ||
enable_version_46_ != GetQuicReloadableFlag(quic_enable_version_46) ||
enable_version_44_ != GetQuicReloadableFlag(quic_enable_version_44) ||
- enable_version_43_ != GetQuicReloadableFlag(quic_enable_version_43) ||
disable_version_39_ != GetQuicReloadableFlag(quic_disable_version_39)) {
enable_version_99_ = GetQuicReloadableFlag(quic_enable_version_99);
enable_version_47_ = GetQuicReloadableFlag(quic_enable_version_47);
enable_version_46_ = GetQuicReloadableFlag(quic_enable_version_46);
enable_version_44_ = GetQuicReloadableFlag(quic_enable_version_44);
- enable_version_43_ = GetQuicReloadableFlag(quic_enable_version_43);
disable_version_39_ = GetQuicReloadableFlag(quic_disable_version_39);
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 4fedae35baa..db9f2c5880e 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
@@ -46,8 +46,6 @@ class QUIC_EXPORT_PRIVATE QuicVersionManager {
bool enable_version_46_;
// quic_enable_version_44 flag
bool enable_version_44_;
- // quic_enable_version_43 flag
- bool enable_version_43_;
// quic_disable_version_39 flag
bool disable_version_39_;
// The list of versions that may be supported.
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 7c7a08d655c..9a7b2a328be 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
@@ -22,20 +22,16 @@ TEST_F(QuicVersionManagerTest, QuicVersionManager) {
SetQuicReloadableFlag(quic_enable_version_47, false);
SetQuicReloadableFlag(quic_enable_version_46, false);
SetQuicReloadableFlag(quic_enable_version_44, false);
- SetQuicReloadableFlag(quic_enable_version_43, false);
SetQuicReloadableFlag(quic_disable_version_39, true);
QuicVersionManager manager(AllSupportedVersions());
EXPECT_EQ(FilterSupportedTransportVersions(AllSupportedTransportVersions()),
manager.GetSupportedTransportVersions());
- EXPECT_TRUE(manager.GetSupportedTransportVersions().empty());
-
- SetQuicReloadableFlag(quic_disable_version_39, false);
- EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_39}),
+ EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_43}),
manager.GetSupportedTransportVersions());
- SetQuicReloadableFlag(quic_enable_version_43, true);
+ SetQuicReloadableFlag(quic_disable_version_39, false);
EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_43, QUIC_VERSION_39}),
manager.GetSupportedTransportVersions());
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 a37f3a7b433..6873eddfe12 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
@@ -32,16 +32,35 @@ ParsedQuicVersion::ParsedQuicVersion(HandshakeProtocol handshake_protocol,
: handshake_protocol(handshake_protocol),
transport_version(transport_version) {
if (handshake_protocol == PROTOCOL_TLS1_3 &&
- !FLAGS_quic_supports_tls_handshake) {
+ !GetQuicFlag(FLAGS_quic_supports_tls_handshake)) {
QUIC_BUG << "TLS use attempted when not enabled";
}
}
bool ParsedQuicVersion::KnowsWhichDecrypterToUse() const {
- return transport_version == QUIC_VERSION_99 ||
+ return transport_version >= QUIC_VERSION_47 ||
handshake_protocol == PROTOCOL_TLS1_3;
}
+bool ParsedQuicVersion::AllowsLowFlowControlLimits() const {
+ return transport_version == QUIC_VERSION_99 &&
+ handshake_protocol == PROTOCOL_TLS1_3;
+}
+
+bool ParsedQuicVersion::HasHeaderProtection() const {
+ return transport_version == QUIC_VERSION_99;
+}
+
+bool ParsedQuicVersion::SupportsRetry() const {
+ return transport_version > QUIC_VERSION_46;
+}
+
+bool ParsedQuicVersion::SupportsClientConnectionIds() const {
+ // This will be enabled in v99 after the rest of the client connection ID
+ // code lands.
+ return false;
+}
+
std::ostream& operator<<(std::ostream& os, const ParsedQuicVersion& version) {
os << ParsedQuicVersionToString(version);
return os;
@@ -75,9 +94,12 @@ QuicVersionLabel CreateQuicVersionLabel(ParsedQuicVersion parsed_version) {
case QUIC_VERSION_99:
if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3 &&
GetQuicFlag(FLAGS_quic_ietf_draft_version) != 0) {
- return 0xff000000 + GetQuicFlag(FLAGS_quic_ietf_draft_version);
+ return MakeVersionLabel(0xff, 0x00, 0x00,
+ GetQuicFlag(FLAGS_quic_ietf_draft_version));
}
return MakeVersionLabel(proto, '0', '9', '9');
+ case QUIC_VERSION_RESERVED_FOR_NEGOTIATION:
+ return MakeVersionLabel(0xda, 0x5a, 0x3a, 0x3a);
default:
// This shold be an ERROR because we should never attempt to convert an
// invalid QuicTransportVersion to be written to the wire.
@@ -99,7 +121,7 @@ QuicVersionLabelVector CreateQuicVersionLabelVector(
ParsedQuicVersion ParseQuicVersionLabel(QuicVersionLabel version_label) {
std::vector<HandshakeProtocol> protocols = {PROTOCOL_QUIC_CRYPTO};
- if (FLAGS_quic_supports_tls_handshake) {
+ if (GetQuicFlag(FLAGS_quic_supports_tls_handshake)) {
protocols.push_back(PROTOCOL_TLS1_3);
}
for (QuicTransportVersion version : kSupportedTransportVersions) {
@@ -129,7 +151,7 @@ ParsedQuicVersion ParseQuicVersionString(std::string version_string) {
}
std::vector<HandshakeProtocol> protocols = {PROTOCOL_QUIC_CRYPTO};
- if (FLAGS_quic_supports_tls_handshake) {
+ if (GetQuicFlag(FLAGS_quic_supports_tls_handshake)) {
protocols.push_back(PROTOCOL_TLS1_3);
}
for (QuicTransportVersion version : kSupportedTransportVersions) {
@@ -142,7 +164,8 @@ ParsedQuicVersion ParseQuicVersionString(std::string version_string) {
}
}
// Still recognize T099 even if flag quic_ietf_draft_version has been changed.
- if (FLAGS_quic_supports_tls_handshake && version_string == "T099") {
+ if (GetQuicFlag(FLAGS_quic_supports_tls_handshake) &&
+ version_string == "T099") {
return ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99);
}
// Reading from the client so this should not be considered an ERROR.
@@ -162,7 +185,8 @@ QuicTransportVersionVector AllSupportedTransportVersions() {
ParsedQuicVersionVector AllSupportedVersions() {
ParsedQuicVersionVector supported_versions;
for (HandshakeProtocol protocol : kSupportedHandshakeProtocols) {
- if (protocol == PROTOCOL_TLS1_3 && !FLAGS_quic_supports_tls_handshake) {
+ if (protocol == PROTOCOL_TLS1_3 &&
+ !GetQuicFlag(FLAGS_quic_supports_tls_handshake)) {
continue;
}
for (QuicTransportVersion version : kSupportedTransportVersions) {
@@ -212,30 +236,22 @@ ParsedQuicVersionVector FilterSupportedVersions(
if (GetQuicReloadableFlag(quic_enable_version_99) &&
GetQuicReloadableFlag(quic_enable_version_47) &&
GetQuicReloadableFlag(quic_enable_version_46) &&
- GetQuicReloadableFlag(quic_enable_version_44) &&
- GetQuicReloadableFlag(quic_enable_version_43)) {
+ GetQuicReloadableFlag(quic_enable_version_44)) {
filtered_versions.push_back(version);
}
} else if (version.transport_version == QUIC_VERSION_47) {
if (GetQuicReloadableFlag(quic_enable_version_47) &&
GetQuicReloadableFlag(quic_enable_version_46) &&
- GetQuicReloadableFlag(quic_enable_version_44) &&
- GetQuicReloadableFlag(quic_enable_version_43)) {
+ GetQuicReloadableFlag(quic_enable_version_44)) {
filtered_versions.push_back(version);
}
} else if (version.transport_version == QUIC_VERSION_46) {
if (GetQuicReloadableFlag(quic_enable_version_46) &&
- GetQuicReloadableFlag(quic_enable_version_44) &&
- GetQuicReloadableFlag(quic_enable_version_43)) {
+ GetQuicReloadableFlag(quic_enable_version_44)) {
filtered_versions.push_back(version);
}
} else if (version.transport_version == QUIC_VERSION_44) {
- if (GetQuicReloadableFlag(quic_enable_version_44) &&
- GetQuicReloadableFlag(quic_enable_version_43)) {
- filtered_versions.push_back(version);
- }
- } else if (version.transport_version == QUIC_VERSION_43) {
- if (GetQuicReloadableFlag(quic_enable_version_43)) {
+ if (GetQuicReloadableFlag(quic_enable_version_44)) {
filtered_versions.push_back(version);
}
} else if (version.transport_version == QUIC_VERSION_39) {
@@ -379,6 +395,11 @@ ParsedQuicVersion UnsupportedQuicVersion() {
return ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED);
}
+ParsedQuicVersion QuicVersionReservedForNegotiation() {
+ return ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
+ QUIC_VERSION_RESERVED_FOR_NEGOTIATION);
+}
+
std::string AlpnForVersion(ParsedQuicVersion parsed_version) {
if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3 &&
parsed_version.transport_version == QUIC_VERSION_99 &&
@@ -395,26 +416,37 @@ void QuicVersionInitializeSupportForIetfDraft(int32_t draft_version) {
return;
}
- SetQuicFlag(&FLAGS_quic_ietf_draft_version, draft_version);
+ SetQuicFlag(FLAGS_quic_ietf_draft_version, draft_version);
if (draft_version == 0) {
return;
}
// Enable necessary flags.
- SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
SetQuicReloadableFlag(quic_deprecate_ack_bundling_mode, true);
SetQuicReloadableFlag(quic_rpm_decides_when_to_send_acks, true);
SetQuicReloadableFlag(quic_use_uber_loss_algorithm, true);
SetQuicReloadableFlag(quic_use_uber_received_packet_manager, true);
SetQuicReloadableFlag(quic_validate_packet_number_post_decryption, true);
SetQuicReloadableFlag(quic_print_tag_hex, true);
+ SetQuicReloadableFlag(quic_send_version_negotiation_fixed_bit, true);
+ SetQuicReloadableFlag(quic_no_client_conn_ver_negotiation, true);
+ SetQuicReloadableFlag(quic_eliminate_static_stream_map_3, true);
+ SetQuicReloadableFlag(quic_tolerate_reneging, true);
+ SetQuicReloadableFlag(quic_simplify_stop_waiting, true);
+ SetQuicRestartFlag(quic_no_server_conn_ver_negotiation2, true);
+ SetQuicRestartFlag(quic_server_drop_version_negotiation, true);
SetQuicRestartFlag(quic_enable_accept_random_ipn, true);
+ SetQuicRestartFlag(quic_allow_variable_length_connection_id_for_negotiation,
+ true);
+ SetQuicRestartFlag(quic_do_not_override_connection_id, true);
+ SetQuicRestartFlag(quic_no_framer_object_in_dispatcher, true);
}
void QuicEnableVersion(ParsedQuicVersion parsed_version) {
if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3) {
- SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
}
static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
"Supported versions out of sync");
@@ -430,9 +462,6 @@ void QuicEnableVersion(ParsedQuicVersion parsed_version) {
if (parsed_version.transport_version >= QUIC_VERSION_44) {
SetQuicReloadableFlag(quic_enable_version_44, true);
}
- if (parsed_version.transport_version >= QUIC_VERSION_43) {
- SetQuicReloadableFlag(quic_enable_version_43, 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 160adeb7f59..0a368dfc0bb 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
@@ -106,6 +106,11 @@ enum QuicTransportVersion {
QUIC_VERSION_47 = 47, // Allow variable-length QUIC connection IDs.
QUIC_VERSION_99 = 99, // Dumping ground for IETF QUIC changes which are not
// yet ready for production.
+ // QUIC_VERSION_RESERVED_FOR_NEGOTIATION is sent over the wire as da5a3a3a
+ // which is part of a range reserved by the IETF for version negotiation
+ // testing. It is intentionally meant to never be supported by servers to
+ // trigger version negotiation when proposed by clients.
+ QUIC_VERSION_RESERVED_FOR_NEGOTIATION = 999,
};
// The crypto handshake protocols that can be used with QUIC.
@@ -147,10 +152,25 @@ struct QUIC_EXPORT_PRIVATE ParsedQuicVersion {
}
bool KnowsWhichDecrypterToUse() const;
+
+ // Indicates that this QUIC version does not have an enforced minimum value
+ // for flow control values negotiated during the handshake.
+ bool AllowsLowFlowControlLimits() const;
+
+ // Returns whether header protection is used in this version of QUIC.
+ bool HasHeaderProtection() const;
+
+ // Returns whether this version supports IETF RETRY packets.
+ bool SupportsRetry() const;
+
+ // Returns whether this version supports client connection ID.
+ bool SupportsClientConnectionIds() const;
};
QUIC_EXPORT_PRIVATE ParsedQuicVersion UnsupportedQuicVersion();
+QUIC_EXPORT_PRIVATE ParsedQuicVersion QuicVersionReservedForNegotiation();
+
QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
const ParsedQuicVersion& version);
@@ -323,13 +343,23 @@ QUIC_EXPORT_PRIVATE inline bool VersionHasDataFrameHeader(
return transport_version == QUIC_VERSION_99;
}
-// Returns true if QuicSpdySession instantiates a QPACK encoder and decoder.
+// If true:
+// * QuicSpdySession instantiates a QPACK encoder and decoder;
+// * HEADERS frames (containing headers or trailers) are sent on
+// request/response streams, compressed with QPACK;
+// * trailers must not contain :final-offset key.
+// If false:
+// * HEADERS frames (containing headers or trailers) are sent on the headers
+// stream, compressed with HPACK;
+// * trailers must contain :final-offset key.
+//
// TODO(123528590): Implement the following features and gate them on this
-// function as well, optionally renaming this function as appropriate.
-// Send HEADERS on the request/response stream instead of the headers stream.
-// Send PUSH_PROMISE on the request/response stream instead of headers stream.
-// Send PRIORITY on the request/response stream instead of the headers stream.
-// Do not instantiate the headers stream object.
+// function as well, optionally renaming this function as appropriate:
+// * send PUSH_PROMISE frames on the request/response stream instead of the
+// headers stream;
+// * send PRIORITY frames on the request/response stream instead of the headers
+// stream;
+// * do not instantiate the headers stream object.
QUIC_EXPORT_PRIVATE inline bool VersionUsesQpack(
QuicTransportVersion transport_version) {
const bool uses_qpack = (transport_version == QUIC_VERSION_99);
@@ -355,8 +385,8 @@ QUIC_EXPORT_PRIVATE inline bool QuicVersionUsesCryptoFrames(
return transport_version == QUIC_VERSION_99;
}
-// Returns whether |transport_version| has HTTP/3 Control stream.
-QUIC_EXPORT_PRIVATE inline bool VersionHasControlStreams(
+// Returns whether |transport_version| has HTTP/3 stream type.
+QUIC_EXPORT_PRIVATE inline bool VersionHasStreamType(
QuicTransportVersion transport_version) {
return transport_version == QUIC_VERSION_99;
}
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 b04db0caff1..c19e621fd0a 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
@@ -116,11 +116,11 @@ TEST_F(QuicVersionsTest, QuicVersionLabelToHandshakeProtocol) {
}
// Test a TLS version:
- FLAGS_quic_supports_tls_handshake = true;
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
QuicTag tls_tag = MakeQuicTag('3', '4', '0', 'T');
EXPECT_EQ(PROTOCOL_TLS1_3, QuicVersionLabelToHandshakeProtocol(tls_tag));
- FLAGS_quic_supports_tls_handshake = false;
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, false);
if (QUIC_DLOG_INFO_IS_ON()) {
EXPECT_QUIC_LOG_CALL_CONTAINS(log, INFO,
"Unsupported QuicVersionLabel version: T043")
@@ -142,7 +142,7 @@ TEST_F(QuicVersionsTest, ParseQuicVersionLabel) {
ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '4', '7')));
// Test a TLS version:
- FLAGS_quic_supports_tls_handshake = true;
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_39),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '9')));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_43),
@@ -154,7 +154,7 @@ TEST_F(QuicVersionsTest, ParseQuicVersionLabel) {
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '7')));
- FLAGS_quic_supports_tls_handshake = false;
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, false);
EXPECT_EQ(UnsupportedQuicVersion(),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '5')));
EXPECT_EQ(UnsupportedQuicVersion(),
@@ -188,7 +188,7 @@ TEST_F(QuicVersionsTest, ParseQuicVersionString) {
EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("Q047 "));
// Test a TLS version:
- FLAGS_quic_supports_tls_handshake = true;
+ SetQuicFlag(FLAGS_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),
@@ -200,7 +200,7 @@ TEST_F(QuicVersionsTest, ParseQuicVersionString) {
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47),
ParseQuicVersionString("T047"));
- FLAGS_quic_supports_tls_handshake = false;
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, false);
EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("T035"));
EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("T039"));
EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("T043"));
@@ -228,7 +228,7 @@ TEST_F(QuicVersionsTest, CreateQuicVersionLabel) {
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47)));
// Test a TLS version:
- FLAGS_quic_supports_tls_handshake = true;
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
EXPECT_EQ(MakeVersionLabel('T', '0', '3', '9'),
CreateQuicVersionLabel(
ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_39)));
@@ -245,7 +245,7 @@ TEST_F(QuicVersionsTest, CreateQuicVersionLabel) {
CreateQuicVersionLabel(
ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47)));
- FLAGS_quic_supports_tls_handshake = false;
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, false);
EXPECT_EQ(UnsupportedQuicVersion(),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '5')));
EXPECT_EQ(UnsupportedQuicVersion(),
@@ -323,7 +323,7 @@ TEST_F(QuicVersionsTest, ParsedQuicVersionToString) {
// Make sure that all supported versions are present in
// ParsedQuicVersionToString.
- FLAGS_quic_supports_tls_handshake = true;
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
for (QuicTransportVersion transport_version : kSupportedTransportVersions) {
for (HandshakeProtocol protocol : kSupportedHandshakeProtocols) {
EXPECT_NE("0", ParsedQuicVersionToString(
@@ -342,7 +342,6 @@ TEST_F(QuicVersionsTest, AllSupportedTransportVersions) {
TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsAllVersions) {
QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
SetQuicReloadableFlag(quic_disable_version_39, false);
- SetQuicReloadableFlag(quic_enable_version_43, true);
SetQuicReloadableFlag(quic_enable_version_44, true);
SetQuicReloadableFlag(quic_enable_version_46, true);
SetQuicReloadableFlag(quic_enable_version_47, true);
@@ -367,7 +366,6 @@ TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsAllVersions) {
TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo99) {
QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
SetQuicReloadableFlag(quic_disable_version_39, false);
- SetQuicReloadableFlag(quic_enable_version_43, true);
SetQuicReloadableFlag(quic_enable_version_44, true);
SetQuicReloadableFlag(quic_enable_version_46, true);
SetQuicReloadableFlag(quic_enable_version_47, true);
@@ -392,7 +390,6 @@ TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo99) {
TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo47) {
QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
SetQuicReloadableFlag(quic_disable_version_39, false);
- SetQuicReloadableFlag(quic_enable_version_43, true);
SetQuicReloadableFlag(quic_enable_version_44, true);
SetQuicReloadableFlag(quic_enable_version_46, true);
SetQuicReloadableFlag(quic_enable_version_47, false);
@@ -416,7 +413,6 @@ TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo47) {
TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo46) {
QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
SetQuicReloadableFlag(quic_disable_version_39, false);
- SetQuicReloadableFlag(quic_enable_version_43, true);
SetQuicReloadableFlag(quic_enable_version_44, true);
SetQuicReloadableFlag(quic_enable_version_46, false);
SetQuicReloadableFlag(quic_enable_version_47, false);
@@ -440,7 +436,6 @@ TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo46) {
TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo44) {
QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
SetQuicReloadableFlag(quic_disable_version_39, false);
- SetQuicReloadableFlag(quic_enable_version_43, true);
SetQuicReloadableFlag(quic_enable_version_44, false);
SetQuicReloadableFlag(quic_enable_version_46, false);
SetQuicReloadableFlag(quic_enable_version_47, false);
@@ -461,33 +456,9 @@ TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo44) {
ASSERT_EQ(expected_parsed_versions, FilterSupportedVersions(parsed_versions));
}
-TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo43) {
- QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
- SetQuicReloadableFlag(quic_disable_version_39, false);
- SetQuicReloadableFlag(quic_enable_version_43, false);
- SetQuicReloadableFlag(quic_enable_version_44, false);
- SetQuicReloadableFlag(quic_enable_version_46, false);
- SetQuicReloadableFlag(quic_enable_version_47, 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_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();
SetQuicReloadableFlag(quic_disable_version_39, true);
- SetQuicReloadableFlag(quic_enable_version_43, true);
SetQuicReloadableFlag(quic_enable_version_44, false);
SetQuicReloadableFlag(quic_enable_version_46, false);
SetQuicReloadableFlag(quic_enable_version_47, false);
@@ -557,14 +528,14 @@ TEST_F(QuicVersionsTest, CheckVersionNumbersForTypos) {
}
TEST_F(QuicVersionsTest, AlpnForVersion) {
- FLAGS_quic_supports_tls_handshake = true;
+ SetQuicFlag(FLAGS_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_t099 =
ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99);
- FLAGS_quic_supports_tls_handshake = false;
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, false);
EXPECT_EQ("h3-google-Q047", AlpnForVersion(parsed_version_q047));
EXPECT_EQ("h3-google-T047", AlpnForVersion(parsed_version_t047));
@@ -572,10 +543,10 @@ TEST_F(QuicVersionsTest, AlpnForVersion) {
}
TEST_F(QuicVersionsTest, InitializeSupportForIetfDraft) {
- FLAGS_quic_supports_tls_handshake = true;
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
ParsedQuicVersion parsed_version_t099 =
ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99);
- FLAGS_quic_supports_tls_handshake = false;
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, false);
EXPECT_EQ(MakeVersionLabel('T', '0', '9', '9'),
CreateQuicVersionLabel(parsed_version_t099));
EXPECT_EQ("h3-google-T099", AlpnForVersion(parsed_version_t099));
@@ -584,10 +555,10 @@ TEST_F(QuicVersionsTest, InitializeSupportForIetfDraft) {
EXPECT_EQ(MakeVersionLabel('T', '0', '9', '9'),
CreateQuicVersionLabel(parsed_version_t099));
EXPECT_EQ("h3-google-T099", AlpnForVersion(parsed_version_t099));
- EXPECT_FALSE(FLAGS_quic_supports_tls_handshake);
+ EXPECT_FALSE(GetQuicFlag(FLAGS_quic_supports_tls_handshake));
QuicVersionInitializeSupportForIetfDraft(18);
- EXPECT_TRUE(FLAGS_quic_supports_tls_handshake);
+ EXPECT_TRUE(GetQuicFlag(FLAGS_quic_supports_tls_handshake));
EXPECT_EQ(MakeVersionLabel(0xff, 0, 0, 18),
CreateQuicVersionLabel(parsed_version_t099));
EXPECT_EQ("h3-18", AlpnForVersion(parsed_version_t099));
@@ -599,37 +570,47 @@ TEST_F(QuicVersionsTest, InitializeSupportForIetfDraft) {
}
TEST_F(QuicVersionsTest, QuicEnableVersion) {
- FLAGS_quic_supports_tls_handshake = true;
+ SetQuicFlag(FLAGS_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_t099 =
ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99);
- FLAGS_quic_supports_tls_handshake = false;
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, false);
SetQuicReloadableFlag(quic_disable_version_39, false);
- SetQuicReloadableFlag(quic_enable_version_43, true);
SetQuicReloadableFlag(quic_enable_version_44, true);
SetQuicReloadableFlag(quic_enable_version_46, true);
SetQuicReloadableFlag(quic_enable_version_47, false);
SetQuicReloadableFlag(quic_enable_version_99, false);
QuicEnableVersion(parsed_version_q047);
- EXPECT_FALSE(FLAGS_quic_supports_tls_handshake);
+ EXPECT_FALSE(GetQuicFlag(FLAGS_quic_supports_tls_handshake));
EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_47));
EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
QuicEnableVersion(parsed_version_t047);
- EXPECT_TRUE(FLAGS_quic_supports_tls_handshake);
+ EXPECT_TRUE(GetQuicFlag(FLAGS_quic_supports_tls_handshake));
EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_47));
EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
QuicEnableVersion(parsed_version_t099);
- EXPECT_TRUE(FLAGS_quic_supports_tls_handshake);
+ EXPECT_TRUE(GetQuicFlag(FLAGS_quic_supports_tls_handshake));
EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_47));
EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_99));
}
+TEST_F(QuicVersionsTest, ReservedForNegotiation) {
+ EXPECT_EQ(QUIC_VERSION_RESERVED_FOR_NEGOTIATION,
+ QuicVersionReservedForNegotiation().transport_version);
+ // QUIC_VERSION_RESERVED_FOR_NEGOTIATION MUST NOT be added to
+ // kSupportedTransportVersions.
+ for (size_t i = 0; i < QUIC_ARRAYSIZE(kSupportedTransportVersions); ++i) {
+ EXPECT_NE(QUIC_VERSION_RESERVED_FOR_NEGOTIATION,
+ kSupportedTransportVersions[i]);
+ }
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.cc b/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.cc
index e3929557caf..d7fe3c0e554 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.cc
@@ -9,7 +9,11 @@
namespace quic {
-QuicWriteBlockedList::QuicWriteBlockedList() : last_priority_popped_(0) {
+QuicWriteBlockedList::QuicWriteBlockedList(QuicTransportVersion version)
+ : priority_write_scheduler_(QuicVersionUsesCryptoFrames(version)
+ ? std::numeric_limits<QuicStreamId>::max()
+ : 0),
+ last_priority_popped_(0) {
memset(batch_write_stream_id_, 0, sizeof(batch_write_stream_id_));
memset(bytes_left_for_batch_write_, 0, sizeof(bytes_left_for_batch_write_));
}
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 83c2e2069be..eca7c1a29ab 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
@@ -24,7 +24,7 @@ class QUIC_EXPORT_PRIVATE QuicWriteBlockedList {
typedef spdy::PriorityWriteScheduler<QuicStreamId> QuicPriorityWriteScheduler;
public:
- explicit QuicWriteBlockedList();
+ explicit QuicWriteBlockedList(QuicTransportVersion version);
QuicWriteBlockedList(const QuicWriteBlockedList&) = delete;
QuicWriteBlockedList& operator=(const QuicWriteBlockedList&) = delete;
~QuicWriteBlockedList();
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list_test.cc
index a9319e333e6..30bb08ef010 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list_test.cc
@@ -14,218 +14,214 @@ namespace quic {
namespace test {
namespace {
-class QuicWriteBlockedListTest : public QuicTest {};
+class QuicWriteBlockedListTest : public QuicTest {
+ public:
+ QuicWriteBlockedListTest()
+ : write_blocked_list_(AllSupportedVersions()[0].transport_version) {}
-TEST_F(QuicWriteBlockedListTest, PriorityOrder) {
- QuicWriteBlockedList write_blocked_list;
+ protected:
+ QuicWriteBlockedList write_blocked_list_;
+};
+TEST_F(QuicWriteBlockedListTest, PriorityOrder) {
// Mark streams blocked in roughly reverse priority order, and
// verify that streams are sorted.
- write_blocked_list.RegisterStream(40, false, kV3LowestPriority);
- write_blocked_list.RegisterStream(23, false, kV3HighestPriority);
- write_blocked_list.RegisterStream(17, false, kV3HighestPriority);
- write_blocked_list.RegisterStream(1, true, kV3HighestPriority);
- write_blocked_list.RegisterStream(3, true, kV3HighestPriority);
-
- write_blocked_list.AddStream(40);
- EXPECT_TRUE(write_blocked_list.IsStreamBlocked(40));
- write_blocked_list.AddStream(23);
- EXPECT_TRUE(write_blocked_list.IsStreamBlocked(23));
- write_blocked_list.AddStream(17);
- EXPECT_TRUE(write_blocked_list.IsStreamBlocked(17));
- write_blocked_list.AddStream(3);
- EXPECT_TRUE(write_blocked_list.IsStreamBlocked(3));
- write_blocked_list.AddStream(1);
- EXPECT_TRUE(write_blocked_list.IsStreamBlocked(1));
-
- EXPECT_EQ(5u, write_blocked_list.NumBlockedStreams());
- EXPECT_TRUE(write_blocked_list.HasWriteBlockedSpecialStream());
- EXPECT_EQ(2u, write_blocked_list.NumBlockedSpecialStreams());
- EXPECT_TRUE(write_blocked_list.HasWriteBlockedDataStreams());
+ write_blocked_list_.RegisterStream(40, false, kV3LowestPriority);
+ write_blocked_list_.RegisterStream(23, false, kV3HighestPriority);
+ write_blocked_list_.RegisterStream(17, false, kV3HighestPriority);
+ write_blocked_list_.RegisterStream(1, true, kV3HighestPriority);
+ write_blocked_list_.RegisterStream(3, true, kV3HighestPriority);
+
+ write_blocked_list_.AddStream(40);
+ EXPECT_TRUE(write_blocked_list_.IsStreamBlocked(40));
+ write_blocked_list_.AddStream(23);
+ EXPECT_TRUE(write_blocked_list_.IsStreamBlocked(23));
+ write_blocked_list_.AddStream(17);
+ EXPECT_TRUE(write_blocked_list_.IsStreamBlocked(17));
+ write_blocked_list_.AddStream(3);
+ EXPECT_TRUE(write_blocked_list_.IsStreamBlocked(3));
+ write_blocked_list_.AddStream(1);
+ EXPECT_TRUE(write_blocked_list_.IsStreamBlocked(1));
+
+ EXPECT_EQ(5u, write_blocked_list_.NumBlockedStreams());
+ EXPECT_TRUE(write_blocked_list_.HasWriteBlockedSpecialStream());
+ EXPECT_EQ(2u, write_blocked_list_.NumBlockedSpecialStreams());
+ EXPECT_TRUE(write_blocked_list_.HasWriteBlockedDataStreams());
// The Crypto stream is highest priority.
- EXPECT_EQ(1u, write_blocked_list.PopFront());
- EXPECT_EQ(1u, write_blocked_list.NumBlockedSpecialStreams());
- EXPECT_FALSE(write_blocked_list.IsStreamBlocked(1));
+ EXPECT_EQ(1u, write_blocked_list_.PopFront());
+ EXPECT_EQ(1u, write_blocked_list_.NumBlockedSpecialStreams());
+ EXPECT_FALSE(write_blocked_list_.IsStreamBlocked(1));
// Followed by the Headers stream.
- EXPECT_EQ(3u, write_blocked_list.PopFront());
- EXPECT_EQ(0u, write_blocked_list.NumBlockedSpecialStreams());
- EXPECT_FALSE(write_blocked_list.IsStreamBlocked(3));
+ EXPECT_EQ(3u, write_blocked_list_.PopFront());
+ EXPECT_EQ(0u, write_blocked_list_.NumBlockedSpecialStreams());
+ EXPECT_FALSE(write_blocked_list_.IsStreamBlocked(3));
// Streams with same priority are popped in the order they were inserted.
- EXPECT_EQ(23u, write_blocked_list.PopFront());
- EXPECT_FALSE(write_blocked_list.IsStreamBlocked(23));
- EXPECT_EQ(17u, write_blocked_list.PopFront());
- EXPECT_FALSE(write_blocked_list.IsStreamBlocked(17));
+ EXPECT_EQ(23u, write_blocked_list_.PopFront());
+ EXPECT_FALSE(write_blocked_list_.IsStreamBlocked(23));
+ EXPECT_EQ(17u, write_blocked_list_.PopFront());
+ EXPECT_FALSE(write_blocked_list_.IsStreamBlocked(17));
// Low priority stream appears last.
- EXPECT_EQ(40u, write_blocked_list.PopFront());
- EXPECT_FALSE(write_blocked_list.IsStreamBlocked(40));
+ EXPECT_EQ(40u, write_blocked_list_.PopFront());
+ EXPECT_FALSE(write_blocked_list_.IsStreamBlocked(40));
- EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams());
- EXPECT_FALSE(write_blocked_list.HasWriteBlockedSpecialStream());
- EXPECT_FALSE(write_blocked_list.HasWriteBlockedDataStreams());
+ EXPECT_EQ(0u, write_blocked_list_.NumBlockedStreams());
+ EXPECT_FALSE(write_blocked_list_.HasWriteBlockedSpecialStream());
+ EXPECT_FALSE(write_blocked_list_.HasWriteBlockedDataStreams());
}
TEST_F(QuicWriteBlockedListTest, CryptoStream) {
- QuicWriteBlockedList write_blocked_list;
- write_blocked_list.RegisterStream(1, true, kV3HighestPriority);
- write_blocked_list.AddStream(1);
-
- EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams());
- EXPECT_TRUE(write_blocked_list.HasWriteBlockedSpecialStream());
- EXPECT_EQ(1u, write_blocked_list.PopFront());
- EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams());
- EXPECT_FALSE(write_blocked_list.HasWriteBlockedSpecialStream());
+ write_blocked_list_.RegisterStream(1, true, kV3HighestPriority);
+ write_blocked_list_.AddStream(1);
+
+ EXPECT_EQ(1u, write_blocked_list_.NumBlockedStreams());
+ EXPECT_TRUE(write_blocked_list_.HasWriteBlockedSpecialStream());
+ EXPECT_EQ(1u, write_blocked_list_.PopFront());
+ EXPECT_EQ(0u, write_blocked_list_.NumBlockedStreams());
+ EXPECT_FALSE(write_blocked_list_.HasWriteBlockedSpecialStream());
}
TEST_F(QuicWriteBlockedListTest, HeadersStream) {
- QuicWriteBlockedList write_blocked_list;
- write_blocked_list.RegisterStream(3, true, kV3HighestPriority);
- write_blocked_list.AddStream(3);
-
- EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams());
- EXPECT_TRUE(write_blocked_list.HasWriteBlockedSpecialStream());
- EXPECT_EQ(3u, write_blocked_list.PopFront());
- EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams());
- EXPECT_FALSE(write_blocked_list.HasWriteBlockedSpecialStream());
+ write_blocked_list_.RegisterStream(3, true, kV3HighestPriority);
+ write_blocked_list_.AddStream(3);
+
+ EXPECT_EQ(1u, write_blocked_list_.NumBlockedStreams());
+ EXPECT_TRUE(write_blocked_list_.HasWriteBlockedSpecialStream());
+ EXPECT_EQ(3u, write_blocked_list_.PopFront());
+ EXPECT_EQ(0u, write_blocked_list_.NumBlockedStreams());
+ EXPECT_FALSE(write_blocked_list_.HasWriteBlockedSpecialStream());
}
TEST_F(QuicWriteBlockedListTest, VerifyHeadersStream) {
- QuicWriteBlockedList write_blocked_list;
- write_blocked_list.RegisterStream(5, false, kV3HighestPriority);
- write_blocked_list.RegisterStream(3, true, kV3HighestPriority);
- write_blocked_list.AddStream(5);
- write_blocked_list.AddStream(3);
-
- EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams());
- EXPECT_TRUE(write_blocked_list.HasWriteBlockedSpecialStream());
- EXPECT_TRUE(write_blocked_list.HasWriteBlockedDataStreams());
+ write_blocked_list_.RegisterStream(5, false, kV3HighestPriority);
+ write_blocked_list_.RegisterStream(3, true, kV3HighestPriority);
+ write_blocked_list_.AddStream(5);
+ write_blocked_list_.AddStream(3);
+
+ EXPECT_EQ(2u, write_blocked_list_.NumBlockedStreams());
+ EXPECT_TRUE(write_blocked_list_.HasWriteBlockedSpecialStream());
+ EXPECT_TRUE(write_blocked_list_.HasWriteBlockedDataStreams());
// In newer QUIC versions, there is a headers stream which is
// higher priority than data streams.
- EXPECT_EQ(3u, write_blocked_list.PopFront());
- EXPECT_EQ(5u, write_blocked_list.PopFront());
- EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams());
- EXPECT_FALSE(write_blocked_list.HasWriteBlockedSpecialStream());
- EXPECT_FALSE(write_blocked_list.HasWriteBlockedDataStreams());
+ EXPECT_EQ(3u, write_blocked_list_.PopFront());
+ EXPECT_EQ(5u, write_blocked_list_.PopFront());
+ EXPECT_EQ(0u, write_blocked_list_.NumBlockedStreams());
+ EXPECT_FALSE(write_blocked_list_.HasWriteBlockedSpecialStream());
+ EXPECT_FALSE(write_blocked_list_.HasWriteBlockedDataStreams());
}
TEST_F(QuicWriteBlockedListTest, NoDuplicateEntries) {
// Test that QuicWriteBlockedList doesn't allow duplicate entries.
- QuicWriteBlockedList write_blocked_list;
-
// Try to add a stream to the write blocked list multiple times at the same
// priority.
const QuicStreamId kBlockedId = 3 + 2;
- write_blocked_list.RegisterStream(kBlockedId, false, kV3HighestPriority);
- write_blocked_list.AddStream(kBlockedId);
- write_blocked_list.AddStream(kBlockedId);
- write_blocked_list.AddStream(kBlockedId);
+ write_blocked_list_.RegisterStream(kBlockedId, false, kV3HighestPriority);
+ write_blocked_list_.AddStream(kBlockedId);
+ write_blocked_list_.AddStream(kBlockedId);
+ write_blocked_list_.AddStream(kBlockedId);
// This should only result in one blocked stream being added.
- EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams());
- EXPECT_TRUE(write_blocked_list.HasWriteBlockedDataStreams());
+ EXPECT_EQ(1u, write_blocked_list_.NumBlockedStreams());
+ EXPECT_TRUE(write_blocked_list_.HasWriteBlockedDataStreams());
// There should only be one stream to pop off the front.
- EXPECT_EQ(kBlockedId, write_blocked_list.PopFront());
- EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams());
- EXPECT_FALSE(write_blocked_list.HasWriteBlockedDataStreams());
+ EXPECT_EQ(kBlockedId, write_blocked_list_.PopFront());
+ EXPECT_EQ(0u, write_blocked_list_.NumBlockedStreams());
+ EXPECT_FALSE(write_blocked_list_.HasWriteBlockedDataStreams());
}
TEST_F(QuicWriteBlockedListTest, BatchingWrites) {
- QuicWriteBlockedList write_blocked_list;
-
const QuicStreamId id1 = 3 + 2;
const QuicStreamId id2 = id1 + 2;
const QuicStreamId id3 = id2 + 2;
- write_blocked_list.RegisterStream(id1, false, kV3LowestPriority);
- write_blocked_list.RegisterStream(id2, false, kV3LowestPriority);
- write_blocked_list.RegisterStream(id3, false, kV3HighestPriority);
+ write_blocked_list_.RegisterStream(id1, false, kV3LowestPriority);
+ write_blocked_list_.RegisterStream(id2, false, kV3LowestPriority);
+ write_blocked_list_.RegisterStream(id3, false, kV3HighestPriority);
- write_blocked_list.AddStream(id1);
- write_blocked_list.AddStream(id2);
- EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams());
+ write_blocked_list_.AddStream(id1);
+ write_blocked_list_.AddStream(id2);
+ EXPECT_EQ(2u, write_blocked_list_.NumBlockedStreams());
// The first stream we push back should stay at the front until 16k is
// written.
- EXPECT_EQ(id1, write_blocked_list.PopFront());
- write_blocked_list.UpdateBytesForStream(id1, 15999);
- write_blocked_list.AddStream(id1);
- EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams());
- EXPECT_EQ(id1, write_blocked_list.PopFront());
+ EXPECT_EQ(id1, write_blocked_list_.PopFront());
+ write_blocked_list_.UpdateBytesForStream(id1, 15999);
+ write_blocked_list_.AddStream(id1);
+ EXPECT_EQ(2u, write_blocked_list_.NumBlockedStreams());
+ EXPECT_EQ(id1, write_blocked_list_.PopFront());
// Once 16k is written the first stream will yield to the next.
- write_blocked_list.UpdateBytesForStream(id1, 1);
- write_blocked_list.AddStream(id1);
- EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams());
- EXPECT_EQ(id2, write_blocked_list.PopFront());
+ write_blocked_list_.UpdateBytesForStream(id1, 1);
+ write_blocked_list_.AddStream(id1);
+ EXPECT_EQ(2u, write_blocked_list_.NumBlockedStreams());
+ EXPECT_EQ(id2, write_blocked_list_.PopFront());
// Set the new stream to have written all but one byte.
- write_blocked_list.UpdateBytesForStream(id2, 15999);
- write_blocked_list.AddStream(id2);
- EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams());
+ write_blocked_list_.UpdateBytesForStream(id2, 15999);
+ write_blocked_list_.AddStream(id2);
+ EXPECT_EQ(2u, write_blocked_list_.NumBlockedStreams());
// Ensure higher priority streams are popped first.
- write_blocked_list.AddStream(id3);
- EXPECT_EQ(id3, write_blocked_list.PopFront());
+ write_blocked_list_.AddStream(id3);
+ EXPECT_EQ(id3, write_blocked_list_.PopFront());
// Higher priority streams will always be popped first, even if using their
// byte quota
- write_blocked_list.UpdateBytesForStream(id3, 20000);
- write_blocked_list.AddStream(id3);
- EXPECT_EQ(id3, write_blocked_list.PopFront());
+ write_blocked_list_.UpdateBytesForStream(id3, 20000);
+ write_blocked_list_.AddStream(id3);
+ EXPECT_EQ(id3, write_blocked_list_.PopFront());
// Once the higher priority stream is out of the way, id2 will resume its 16k
// write, with only 1 byte remaining of its guaranteed write allocation.
- EXPECT_EQ(id2, write_blocked_list.PopFront());
- write_blocked_list.UpdateBytesForStream(id2, 1);
- write_blocked_list.AddStream(id2);
- EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams());
- EXPECT_EQ(id1, write_blocked_list.PopFront());
+ EXPECT_EQ(id2, write_blocked_list_.PopFront());
+ write_blocked_list_.UpdateBytesForStream(id2, 1);
+ write_blocked_list_.AddStream(id2);
+ EXPECT_EQ(2u, write_blocked_list_.NumBlockedStreams());
+ EXPECT_EQ(id1, write_blocked_list_.PopFront());
}
TEST_F(QuicWriteBlockedListTest, Ceding) {
- QuicWriteBlockedList write_blocked_list;
-
- write_blocked_list.RegisterStream(15, false, kV3HighestPriority);
- write_blocked_list.RegisterStream(16, false, kV3HighestPriority);
- write_blocked_list.RegisterStream(5, false, 5);
- write_blocked_list.RegisterStream(4, false, 5);
- write_blocked_list.RegisterStream(7, false, 7);
- write_blocked_list.RegisterStream(1, true, kV3HighestPriority);
- write_blocked_list.RegisterStream(3, true, kV3HighestPriority);
+ write_blocked_list_.RegisterStream(15, false, kV3HighestPriority);
+ write_blocked_list_.RegisterStream(16, false, kV3HighestPriority);
+ write_blocked_list_.RegisterStream(5, false, 5);
+ write_blocked_list_.RegisterStream(4, false, 5);
+ write_blocked_list_.RegisterStream(7, false, 7);
+ write_blocked_list_.RegisterStream(1, true, kV3HighestPriority);
+ write_blocked_list_.RegisterStream(3, true, kV3HighestPriority);
// When nothing is on the list, nothing yields.
- EXPECT_FALSE(write_blocked_list.ShouldYield(5));
+ EXPECT_FALSE(write_blocked_list_.ShouldYield(5));
- write_blocked_list.AddStream(5);
+ write_blocked_list_.AddStream(5);
// 5 should not yield to itself.
- EXPECT_FALSE(write_blocked_list.ShouldYield(5));
+ EXPECT_FALSE(write_blocked_list_.ShouldYield(5));
// 4 and 7 are equal or lower priority and should yield to 5.
- EXPECT_TRUE(write_blocked_list.ShouldYield(4));
- EXPECT_TRUE(write_blocked_list.ShouldYield(7));
+ EXPECT_TRUE(write_blocked_list_.ShouldYield(4));
+ EXPECT_TRUE(write_blocked_list_.ShouldYield(7));
// 15, headers and crypto should preempt 5.
- EXPECT_FALSE(write_blocked_list.ShouldYield(15));
- EXPECT_FALSE(write_blocked_list.ShouldYield(3));
- EXPECT_FALSE(write_blocked_list.ShouldYield(1));
+ EXPECT_FALSE(write_blocked_list_.ShouldYield(15));
+ EXPECT_FALSE(write_blocked_list_.ShouldYield(3));
+ EXPECT_FALSE(write_blocked_list_.ShouldYield(1));
// Block a high priority stream.
- write_blocked_list.AddStream(15);
+ write_blocked_list_.AddStream(15);
// 16 should yield (same priority) but headers and crypto will still not.
- EXPECT_TRUE(write_blocked_list.ShouldYield(16));
- EXPECT_FALSE(write_blocked_list.ShouldYield(3));
- EXPECT_FALSE(write_blocked_list.ShouldYield(1));
+ EXPECT_TRUE(write_blocked_list_.ShouldYield(16));
+ EXPECT_FALSE(write_blocked_list_.ShouldYield(3));
+ EXPECT_FALSE(write_blocked_list_.ShouldYield(1));
// Block the headers stream. All streams but crypto and headers should yield.
- write_blocked_list.AddStream(3);
- EXPECT_TRUE(write_blocked_list.ShouldYield(16));
- EXPECT_TRUE(write_blocked_list.ShouldYield(15));
- EXPECT_FALSE(write_blocked_list.ShouldYield(3));
- EXPECT_FALSE(write_blocked_list.ShouldYield(1));
+ write_blocked_list_.AddStream(3);
+ EXPECT_TRUE(write_blocked_list_.ShouldYield(16));
+ EXPECT_TRUE(write_blocked_list_.ShouldYield(15));
+ EXPECT_FALSE(write_blocked_list_.ShouldYield(3));
+ EXPECT_FALSE(write_blocked_list_.ShouldYield(1));
// Block the crypto stream. All streams but crypto should yield.
- write_blocked_list.AddStream(1);
- EXPECT_TRUE(write_blocked_list.ShouldYield(16));
- EXPECT_TRUE(write_blocked_list.ShouldYield(15));
- EXPECT_TRUE(write_blocked_list.ShouldYield(3));
- EXPECT_FALSE(write_blocked_list.ShouldYield(1));
+ write_blocked_list_.AddStream(1);
+ EXPECT_TRUE(write_blocked_list_.ShouldYield(16));
+ EXPECT_TRUE(write_blocked_list_.ShouldYield(15));
+ EXPECT_TRUE(write_blocked_list_.ShouldYield(3));
+ EXPECT_FALSE(write_blocked_list_.ShouldYield(1));
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/core/stateless_rejector.cc b/chromium/net/third_party/quiche/src/quic/core/stateless_rejector.cc
deleted file mode 100644
index e2ef51cb845..00000000000
--- a/chromium/net/third_party/quiche/src/quic/core/stateless_rejector.cc
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/third_party/quiche/src/quic/core/stateless_rejector.h"
-
-#include <string>
-
-#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-
-namespace quic {
-
-class StatelessRejector::ValidateCallback
- : public ValidateClientHelloResultCallback {
- public:
- explicit ValidateCallback(
- std::unique_ptr<StatelessRejector> rejector,
- std::unique_ptr<StatelessRejector::ProcessDoneCallback> cb)
- : rejector_(std::move(rejector)), cb_(std::move(cb)) {}
-
- ~ValidateCallback() override = default;
-
- void Run(QuicReferenceCountedPointer<Result> result,
- std::unique_ptr<ProofSource::Details> /* proof_source_details */)
- override {
- StatelessRejector* rejector_ptr = rejector_.get();
- rejector_ptr->ProcessClientHello(std::move(result), std::move(rejector_),
- std::move(cb_));
- }
-
- private:
- std::unique_ptr<StatelessRejector> rejector_;
- std::unique_ptr<StatelessRejector::ProcessDoneCallback> cb_;
-};
-
-StatelessRejector::StatelessRejector(
- ParsedQuicVersion version,
- const ParsedQuicVersionVector& versions,
- const QuicCryptoServerConfig* crypto_config,
- QuicCompressedCertsCache* compressed_certs_cache,
- const QuicClock* clock,
- QuicRandom* random,
- QuicByteCount chlo_packet_size,
- const QuicSocketAddress& client_address,
- const QuicSocketAddress& server_address)
- : state_(UNKNOWN),
- error_(QUIC_INTERNAL_ERROR),
- version_(version),
- versions_(versions),
- connection_id_(EmptyQuicConnectionId()),
- chlo_packet_size_(chlo_packet_size),
- client_address_(client_address),
- server_address_(server_address),
- clock_(clock),
- random_(random),
- crypto_config_(crypto_config),
- compressed_certs_cache_(compressed_certs_cache),
- signed_config_(new QuicSignedServerConfig),
- params_(new QuicCryptoNegotiatedParameters) {}
-
-StatelessRejector::~StatelessRejector() = default;
-
-void StatelessRejector::OnChlo(QuicTransportVersion version,
- QuicConnectionId connection_id,
- QuicConnectionId server_designated_connection_id,
- const CryptoHandshakeMessage& message) {
- DCHECK_EQ(kCHLO, message.tag());
- DCHECK_NE(connection_id, server_designated_connection_id);
- DCHECK_EQ(state_, UNKNOWN);
-
- if (!GetQuicReloadableFlag(enable_quic_stateless_reject_support) ||
- !GetQuicReloadableFlag(quic_use_cheap_stateless_rejects) ||
- !QuicCryptoServerStream::DoesPeerSupportStatelessRejects(message)) {
- state_ = UNSUPPORTED;
- return;
- }
-
- connection_id_ = connection_id;
- server_designated_connection_id_ = server_designated_connection_id;
- chlo_ = message; // Note: copies the message
-}
-
-void StatelessRejector::Process(std::unique_ptr<StatelessRejector> rejector,
- std::unique_ptr<ProcessDoneCallback> done_cb) {
- QUIC_BUG_IF(rejector->state() != UNKNOWN) << "StatelessRejector::Process "
- "called for a rejector which "
- "has already made a decision";
- StatelessRejector* rejector_ptr = rejector.get();
- rejector_ptr->crypto_config_->ValidateClientHello(
- rejector_ptr->chlo_, rejector_ptr->client_address_.host(),
- rejector_ptr->server_address_, rejector_ptr->version_.transport_version,
- rejector_ptr->clock_, rejector_ptr->signed_config_,
- std::unique_ptr<ValidateCallback>(
- new ValidateCallback(std::move(rejector), std::move(done_cb))));
-}
-
-class StatelessRejector::ProcessClientHelloCallback
- : public ProcessClientHelloResultCallback {
- public:
- ProcessClientHelloCallback(
- std::unique_ptr<StatelessRejector> rejector,
- std::unique_ptr<StatelessRejector::ProcessDoneCallback> done_cb)
- : rejector_(std::move(rejector)), done_cb_(std::move(done_cb)) {}
-
- void Run(QuicErrorCode error,
- const std::string& error_details,
- std::unique_ptr<CryptoHandshakeMessage> message,
- std::unique_ptr<DiversificationNonce> diversification_nonce,
- std::unique_ptr<ProofSource::Details> /* proof_source_details */)
- override {
- StatelessRejector* rejector_ptr = rejector_.get();
- rejector_ptr->ProcessClientHelloDone(
- error, error_details, std::move(message), std::move(rejector_),
- std::move(done_cb_));
- }
-
- private:
- std::unique_ptr<StatelessRejector> rejector_;
- std::unique_ptr<StatelessRejector::ProcessDoneCallback> done_cb_;
-};
-
-void StatelessRejector::ProcessClientHello(
- QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
- result,
- std::unique_ptr<StatelessRejector> rejector,
- std::unique_ptr<StatelessRejector::ProcessDoneCallback> done_cb) {
- std::unique_ptr<ProcessClientHelloCallback> cb(
- new ProcessClientHelloCallback(std::move(rejector), std::move(done_cb)));
- crypto_config_->ProcessClientHello(
- result,
- /*reject_only=*/true, connection_id_, server_address_, client_address_,
- version_, versions_,
- /*use_stateless_rejects=*/true, server_designated_connection_id_, clock_,
- random_, compressed_certs_cache_, params_, signed_config_,
- QuicCryptoStream::CryptoMessageFramingOverhead(version_.transport_version,
- connection_id_),
- chlo_packet_size_, std::move(cb));
-}
-
-void StatelessRejector::ProcessClientHelloDone(
- QuicErrorCode error,
- const std::string& error_details,
- std::unique_ptr<CryptoHandshakeMessage> message,
- std::unique_ptr<StatelessRejector> rejector,
- std::unique_ptr<StatelessRejector::ProcessDoneCallback> done_cb) {
- reply_ = std::move(message);
-
- if (error != QUIC_NO_ERROR) {
- error_ = error;
- error_details_ = error_details;
- state_ = FAILED;
- } else if (reply_->tag() == kSREJ) {
- state_ = REJECTED;
- } else {
- state_ = ACCEPTED;
- }
- done_cb->Run(std::move(rejector));
-}
-
-} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/stateless_rejector.h b/chromium/net/third_party/quiche/src/quic/core/stateless_rejector.h
deleted file mode 100644
index 18dbdcb45c0..00000000000
--- a/chromium/net/third_party/quiche/src/quic/core/stateless_rejector.h
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_QUIC_CORE_STATELESS_REJECTOR_H_
-#define QUICHE_QUIC_CORE_STATELESS_REJECTOR_H_
-
-#include <string>
-
-#include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
-#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
-#include "net/third_party/quiche/src/quic/core/quic_packets.h"
-
-namespace quic {
-
-// The StatelessRejector receives CHLO messages and generates an SREJ
-// message in response, if the CHLO can be statelessly rejected.
-class StatelessRejector {
- public:
- enum State {
- UNKNOWN, // State has not yet been determined
- UNSUPPORTED, // Stateless rejects are not supported
- FAILED, // There was an error processing the CHLO.
- ACCEPTED, // The CHLO was accepted
- REJECTED, // The CHLO was rejected.
- };
-
- StatelessRejector(ParsedQuicVersion version,
- const ParsedQuicVersionVector& versions,
- const QuicCryptoServerConfig* crypto_config,
- QuicCompressedCertsCache* compressed_certs_cache,
- const QuicClock* clock,
- QuicRandom* random,
- QuicByteCount chlo_packet_size,
- const QuicSocketAddress& client_address,
- const QuicSocketAddress& server_address);
- StatelessRejector(const StatelessRejector&) = delete;
- StatelessRejector& operator=(const StatelessRejector&) = delete;
-
- ~StatelessRejector();
-
- // Called when |chlo| is received for |connection_id|.
- void OnChlo(QuicTransportVersion version,
- QuicConnectionId connection_id,
- QuicConnectionId server_designated_connection_id,
- const CryptoHandshakeMessage& chlo);
-
- class ProcessDoneCallback {
- public:
- virtual ~ProcessDoneCallback() = default;
- virtual void Run(std::unique_ptr<StatelessRejector> rejector) = 0;
- };
-
- // Perform processing to determine whether the CHLO received in OnChlo should
- // be statelessly rejected, and invoke the callback once a decision has been
- // made.
- static void Process(std::unique_ptr<StatelessRejector> rejector,
- std::unique_ptr<ProcessDoneCallback> done_cb);
-
- // Return the version of the CHLO.
- ParsedQuicVersion version() const { return version_; }
-
- // Returns the state of the rejector after OnChlo() has been called.
- State state() const { return state_; }
-
- // Returns the error code when state() returns FAILED.
- QuicErrorCode error() const { return error_; }
-
- // Returns the error details when state() returns FAILED.
- std::string error_details() const { return error_details_; }
-
- // Returns the connection ID.
- QuicConnectionId connection_id() const { return connection_id_; }
-
- // Returns the SREJ message when state() returns REJECTED.
- const CryptoHandshakeMessage& reply() const { return *reply_; }
-
- private:
- // Helper class which is passed in to
- // QuicCryptoServerConfig::ValidateClientHello.
- class ValidateCallback;
- friend class ValidateCallback;
-
- class ProcessClientHelloCallback;
- friend class ProcessClientHelloCallback;
-
- void ProcessClientHello(
- QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
- result,
- std::unique_ptr<StatelessRejector> rejector,
- std::unique_ptr<StatelessRejector::ProcessDoneCallback> done_cb);
-
- void ProcessClientHelloDone(
- QuicErrorCode error,
- const std::string& error_details,
- std::unique_ptr<CryptoHandshakeMessage> message,
- std::unique_ptr<StatelessRejector> rejector,
- std::unique_ptr<StatelessRejector::ProcessDoneCallback> done_cb);
-
- State state_;
- QuicErrorCode error_;
- std::string error_details_;
- ParsedQuicVersion version_;
- ParsedQuicVersionVector versions_;
- QuicConnectionId connection_id_;
- QuicConnectionId server_designated_connection_id_;
- QuicByteCount chlo_packet_size_;
- QuicSocketAddress client_address_;
- QuicSocketAddress server_address_;
- const QuicClock* clock_;
- QuicRandom* random_;
- const QuicCryptoServerConfig* crypto_config_;
- QuicCompressedCertsCache* compressed_certs_cache_;
- CryptoHandshakeMessage chlo_;
- std::unique_ptr<CryptoHandshakeMessage> reply_;
- CryptoFramer crypto_framer_;
- QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
- QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
-};
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_CORE_STATELESS_REJECTOR_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/stateless_rejector_test.cc b/chromium/net/third_party/quiche/src/quic/core/stateless_rejector_test.cc
deleted file mode 100644
index f8757e10b11..00000000000
--- a/chromium/net/third_party/quiche/src/quic/core/stateless_rejector_test.cc
+++ /dev/null
@@ -1,292 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/third_party/quiche/src/quic/core/stateless_rejector.h"
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
-#include "net/third_party/quiche/src/quic/core/crypto/proof_source.h"
-#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
-#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.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"
-
-namespace quic {
-namespace test {
-namespace {
-
-QuicConnectionId TestServerDesignatedConnectionId() {
- return TestConnectionId(24);
-}
-
-// All four combinations of the two flags involved.
-enum FlagsMode { ENABLED, STATELESS_DISABLED, CHEAP_DISABLED, BOTH_DISABLED };
-
-const char* FlagsModeToString(FlagsMode mode) {
- switch (mode) {
- case ENABLED:
- return "ENABLED";
- case STATELESS_DISABLED:
- return "STATELESS_DISABLED";
- case CHEAP_DISABLED:
- return "CHEAP_DISABLED";
- case BOTH_DISABLED:
- return "BOTH_DISABLED";
- default:
- QUIC_DLOG(FATAL) << "Unexpected FlagsMode";
- return nullptr;
- }
-}
-
-// Test various combinations of QUIC version and flag state.
-struct TestParams {
- ParsedQuicVersion version = UnsupportedQuicVersion();
- FlagsMode flags;
-};
-
-std::string TestParamToString(
- const testing::TestParamInfo<TestParams>& params) {
- return QuicStrCat("v", ParsedQuicVersionToString(params.param.version), "_",
- FlagsModeToString(params.param.flags));
-}
-
-std::vector<TestParams> GetTestParams() {
- std::vector<TestParams> params;
- for (FlagsMode flags :
- {ENABLED, STATELESS_DISABLED, CHEAP_DISABLED, BOTH_DISABLED}) {
- for (ParsedQuicVersion version : AllSupportedVersions()) {
- TestParams param;
- param.version = version;
- param.flags = flags;
- params.push_back(param);
- }
- }
- return params;
-}
-
-class StatelessRejectorTest : public QuicTestWithParam<TestParams> {
- public:
- StatelessRejectorTest()
- : proof_source_(crypto_test_utils::ProofSourceForTesting()),
- config_(QuicCryptoServerConfig::TESTING,
- QuicRandom::GetInstance(),
- crypto_test_utils::ProofSourceForTesting(),
- KeyExchangeSource::Default(),
- TlsServerHandshaker::CreateSslCtx()),
- config_peer_(&config_),
- compressed_certs_cache_(
- QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
- rejector_(QuicMakeUnique<StatelessRejector>(
- GetParam().version,
- AllSupportedVersions(),
- &config_,
- &compressed_certs_cache_,
- &clock_,
- QuicRandom::GetInstance(),
- kDefaultMaxPacketSize,
- QuicSocketAddress(QuicIpAddress::Loopback4(), 12345),
- QuicSocketAddress(QuicIpAddress::Loopback4(), 443))) {
- SetQuicReloadableFlag(
- enable_quic_stateless_reject_support,
- GetParam().flags == ENABLED || GetParam().flags == CHEAP_DISABLED);
- SetQuicReloadableFlag(
- quic_use_cheap_stateless_rejects,
- GetParam().flags == ENABLED || GetParam().flags == STATELESS_DISABLED);
-
- // Add a new primary config.
- std::unique_ptr<CryptoHandshakeMessage> msg(config_.AddDefaultConfig(
- QuicRandom::GetInstance(), &clock_, config_options_));
-
- // Save the server config.
- scid_hex_ =
- "#" + QuicTextUtils::HexEncode(config_peer_.GetPrimaryConfig()->id);
-
- // Encode the QUIC version.
- ver_hex_ = ParsedQuicVersionToString(GetParam().version);
-
- // Generate a public value.
- char public_value[32];
- memset(public_value, 42, sizeof(public_value));
- pubs_hex_ =
- "#" + QuicTextUtils::HexEncode(public_value, sizeof(public_value));
-
- // Generate a client nonce.
- std::string nonce;
- CryptoUtils::GenerateNonce(
- clock_.WallNow(), QuicRandom::GetInstance(),
- QuicStringPiece(
- reinterpret_cast<char*>(config_peer_.GetPrimaryConfig()->orbit),
- kOrbitSize),
- &nonce);
- nonc_hex_ = "#" + QuicTextUtils::HexEncode(nonce);
-
- // Generate a source address token.
- SourceAddressTokens previous_tokens;
- QuicIpAddress ip = QuicIpAddress::Loopback4();
- MockRandom rand;
- std::string stk = config_peer_.NewSourceAddressToken(
- config_peer_.GetPrimaryConfig()->id, previous_tokens, ip, &rand,
- clock_.WallNow(), nullptr);
- stk_hex_ = "#" + QuicTextUtils::HexEncode(stk);
- }
-
- protected:
- class ProcessDoneCallback : public StatelessRejector::ProcessDoneCallback {
- public:
- explicit ProcessDoneCallback(StatelessRejectorTest* test) : test_(test) {}
- void Run(std::unique_ptr<StatelessRejector> rejector) override {
- test_->rejector_ = std::move(rejector);
- }
-
- private:
- StatelessRejectorTest* test_;
- };
-
- std::unique_ptr<ProofSource> proof_source_;
- MockClock clock_;
- QuicCryptoServerConfig config_;
- QuicCryptoServerConfigPeer config_peer_;
- QuicCompressedCertsCache compressed_certs_cache_;
- QuicCryptoServerConfig::ConfigOptions config_options_;
- std::unique_ptr<StatelessRejector> rejector_;
-
- // Values used in CHLO messages
- std::string scid_hex_;
- std::string nonc_hex_;
- std::string pubs_hex_;
- std::string ver_hex_;
- std::string stk_hex_;
-};
-
-INSTANTIATE_TEST_SUITE_P(Flags,
- StatelessRejectorTest,
- ::testing::ValuesIn(GetTestParams()),
- TestParamToString);
-
-TEST_P(StatelessRejectorTest, InvalidChlo) {
- // clang-format off
- const CryptoHandshakeMessage client_hello = crypto_test_utils::CreateCHLO(
- {{"PDMD", "X509"},
- {"COPT", "SREJ"}});
- // clang-format on
- rejector_->OnChlo(GetParam().version.transport_version, TestConnectionId(),
- TestServerDesignatedConnectionId(), client_hello);
-
- if (GetParam().flags != ENABLED) {
- EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_->state());
- return;
- }
-
- // The StatelessRejector is undecided - proceed with async processing
- ASSERT_EQ(StatelessRejector::UNKNOWN, rejector_->state());
- StatelessRejector::Process(std::move(rejector_),
- QuicMakeUnique<ProcessDoneCallback>(this));
-
- EXPECT_EQ(StatelessRejector::FAILED, rejector_->state());
- EXPECT_EQ(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, rejector_->error());
-}
-
-TEST_P(StatelessRejectorTest, ValidChloWithoutSrejSupport) {
- // clang-format off
- const CryptoHandshakeMessage client_hello = crypto_test_utils::CreateCHLO(
- {{"PDMD", "X509"},
- {"AEAD", "AESG"},
- {"KEXS", "C255"},
- {"PUBS", pubs_hex_},
- {"NONC", nonc_hex_},
- {"VER\0", ver_hex_}},
- kClientHelloMinimumSize);
- // clang-format on
-
- rejector_->OnChlo(GetParam().version.transport_version, TestConnectionId(),
- TestServerDesignatedConnectionId(), client_hello);
- EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_->state());
-}
-
-TEST_P(StatelessRejectorTest, RejectChlo) {
- // clang-format off
- const CryptoHandshakeMessage client_hello = crypto_test_utils::CreateCHLO(
- {{"PDMD", "X509"},
- {"AEAD", "AESG"},
- {"KEXS", "C255"},
- {"COPT", "SREJ"},
- {"SCID", scid_hex_},
- {"PUBS", pubs_hex_},
- {"NONC", nonc_hex_},
- {"#004b5453", stk_hex_},
- {"VER\0", ver_hex_}},
- kClientHelloMinimumSize);
- // clang-format on
-
- rejector_->OnChlo(GetParam().version.transport_version, TestConnectionId(),
- TestServerDesignatedConnectionId(), client_hello);
- if (GetParam().flags != ENABLED) {
- EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_->state());
- return;
- }
-
- // The StatelessRejector is undecided - proceed with async processing
- ASSERT_EQ(StatelessRejector::UNKNOWN, rejector_->state());
- StatelessRejector::Process(std::move(rejector_),
- QuicMakeUnique<ProcessDoneCallback>(this));
-
- ASSERT_EQ(StatelessRejector::REJECTED, rejector_->state());
- const CryptoHandshakeMessage& reply = rejector_->reply();
- EXPECT_EQ(kSREJ, reply.tag());
- QuicTagVector reject_reasons;
- EXPECT_EQ(QUIC_NO_ERROR, reply.GetTaglist(kRREJ, &reject_reasons));
- EXPECT_EQ(1u, reject_reasons.size());
- EXPECT_EQ(INVALID_EXPECTED_LEAF_CERTIFICATE,
- static_cast<HandshakeFailureReason>(reject_reasons[0]));
-}
-
-TEST_P(StatelessRejectorTest, AcceptChlo) {
- const uint64_t xlct = crypto_test_utils::LeafCertHashForTesting();
- const std::string xlct_hex =
- "#" + QuicTextUtils::HexEncode(reinterpret_cast<const char*>(&xlct),
- sizeof(xlct));
- // clang-format off
- const CryptoHandshakeMessage client_hello = crypto_test_utils::CreateCHLO(
- {{"PDMD", "X509"},
- {"AEAD", "AESG"},
- {"KEXS", "C255"},
- {"COPT", "SREJ"},
- {"SCID", scid_hex_},
- {"PUBS", pubs_hex_},
- {"NONC", nonc_hex_},
- {"#004b5453", stk_hex_},
- {"VER\0", ver_hex_},
- {"XLCT", xlct_hex}},
- kClientHelloMinimumSize);
- // clang-format on
-
- rejector_->OnChlo(GetParam().version.transport_version, TestConnectionId(),
- TestServerDesignatedConnectionId(), client_hello);
- if (GetParam().flags != ENABLED) {
- EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_->state());
- return;
- }
-
- // The StatelessRejector is undecided - proceed with async processing
- ASSERT_EQ(StatelessRejector::UNKNOWN, rejector_->state());
- StatelessRejector::Process(std::move(rejector_),
- QuicMakeUnique<ProcessDoneCallback>(this));
-
- EXPECT_EQ(StatelessRejector::ACCEPTED, rejector_->state());
-}
-
-} // namespace
-} // namespace test
-} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc b/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc
index 932d537b16d..db1f6b480d6 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
@@ -152,6 +152,15 @@ bool TlsClientHandshaker::ProcessTransportParameters(
return false;
}
+ // When interoperating with non-Google implementations that do not send
+ // the version extension, set it to what we expect.
+ if (params.version == 0) {
+ params.version = CreateQuicVersionLabel(session()->connection()->version());
+ }
+ if (params.supported_versions.empty()) {
+ params.supported_versions.push_back(params.version);
+ }
+
if (params.version !=
CreateQuicVersionLabel(session()->connection()->version())) {
*error_details = "Version mismatch detected";
@@ -181,16 +190,6 @@ int TlsClientHandshaker::num_scup_messages_received() const {
return 0;
}
-bool TlsClientHandshaker::WasChannelIDSent() const {
- // Channel ID is not used with TLS in QUIC.
- return false;
-}
-
-bool TlsClientHandshaker::WasChannelIDSourceCallbackRun() const {
- // Channel ID is not used with TLS in QUIC.
- return false;
-}
-
std::string TlsClientHandshaker::chlo_hash() const {
return "";
}
@@ -331,12 +330,22 @@ enum ssl_verify_result_t TlsClientHandshaker::VerifyCert(uint8_t* out_alert) {
std::string(reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert)),
CRYPTO_BUFFER_len(cert)));
}
+ const uint8_t* ocsp_response_raw;
+ size_t ocsp_response_len;
+ SSL_get0_ocsp_response(ssl(), &ocsp_response_raw, &ocsp_response_len);
+ std::string ocsp_response(reinterpret_cast<const char*>(ocsp_response_raw),
+ ocsp_response_len);
+ const uint8_t* sct_list_raw;
+ size_t sct_list_len;
+ SSL_get0_signed_cert_timestamp_list(ssl(), &sct_list_raw, &sct_list_len);
+ std::string sct_list(reinterpret_cast<const char*>(sct_list_raw),
+ sct_list_len);
ProofVerifierCallbackImpl* proof_verify_callback =
new ProofVerifierCallbackImpl(this);
QuicAsyncStatus verify_result = proof_verifier_->VerifyCertChain(
- server_id_.host(), certs, verify_context_.get(),
+ server_id_.host(), certs, ocsp_response, sct_list, verify_context_.get(),
&cert_verify_error_details_, &verify_details_,
std::unique_ptr<ProofVerifierCallback>(proof_verify_callback));
switch (verify_result) {
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 c2243b3efb5..3647e10f084 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
@@ -42,8 +42,6 @@ class QUIC_EXPORT_PRIVATE TlsClientHandshaker
bool CryptoConnect() override;
int num_sent_client_hellos() const override;
int num_scup_messages_received() const override;
- bool WasChannelIDSent() const override;
- bool WasChannelIDSourceCallbackRun() const override;
std::string chlo_hash() const override;
// From QuicCryptoClientStream::HandshakerDelegate and TlsHandshaker
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 3a45f36379f..51602b42daa 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
@@ -105,8 +105,9 @@ EncryptionLevel TlsHandshaker::QuicEncryptionLevel(
case ssl_encryption_initial:
return ENCRYPTION_INITIAL;
case ssl_encryption_early_data:
- case ssl_encryption_handshake:
return ENCRYPTION_ZERO_RTT;
+ case ssl_encryption_handshake:
+ return ENCRYPTION_HANDSHAKE;
case ssl_encryption_application:
return ENCRYPTION_FORWARD_SECURE;
}
@@ -119,8 +120,9 @@ enum ssl_encryption_level_t TlsHandshaker::BoringEncryptionLevel(
case ENCRYPTION_INITIAL:
return ssl_encryption_initial;
case ENCRYPTION_HANDSHAKE:
- case ENCRYPTION_ZERO_RTT:
return ssl_encryption_handshake;
+ case ENCRYPTION_ZERO_RTT:
+ return ssl_encryption_early_data;
case ENCRYPTION_FORWARD_SECURE:
return ssl_encryption_application;
default:
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 a7b2aa8b410..e710d7b166b 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
@@ -47,17 +47,20 @@ class FakeProofVerifier : public ProofVerifier {
QuicAsyncStatus VerifyCertChain(
const std::string& hostname,
const std::vector<std::string>& certs,
+ const std::string& ocsp_response,
+ const std::string& cert_sct,
const ProofVerifyContext* context,
std::string* error_details,
std::unique_ptr<ProofVerifyDetails>* details,
std::unique_ptr<ProofVerifierCallback> callback) override {
if (!active_) {
- return verifier_->VerifyCertChain(hostname, certs, context, error_details,
+ return verifier_->VerifyCertChain(hostname, certs, ocsp_response,
+ cert_sct, context, error_details,
details, std::move(callback));
}
pending_ops_.push_back(QuicMakeUnique<VerifyChainPendingOp>(
- hostname, certs, context, error_details, details, std::move(callback),
- verifier_.get()));
+ hostname, certs, ocsp_response, cert_sct, context, error_details,
+ details, std::move(callback), verifier_.get()));
return QUIC_PENDING;
}
@@ -92,6 +95,8 @@ class FakeProofVerifier : public ProofVerifier {
public:
VerifyChainPendingOp(const std::string& hostname,
const std::vector<std::string>& certs,
+ const std::string& ocsp_response,
+ const std::string& cert_sct,
const ProofVerifyContext* context,
std::string* error_details,
std::unique_ptr<ProofVerifyDetails>* details,
@@ -99,6 +104,8 @@ class FakeProofVerifier : public ProofVerifier {
ProofVerifier* delegate)
: hostname_(hostname),
certs_(certs),
+ ocsp_response_(ocsp_response),
+ cert_sct_(cert_sct),
context_(context),
error_details_(error_details),
details_(details),
@@ -111,7 +118,8 @@ class FakeProofVerifier : public ProofVerifier {
// runs the original callback after asserting that the verification ran
// synchronously.
QuicAsyncStatus status = delegate_->VerifyCertChain(
- hostname_, certs_, context_, error_details_, details_,
+ hostname_, certs_, ocsp_response_, cert_sct_, context_,
+ error_details_, details_,
QuicMakeUnique<FailingProofVerifierCallback>());
ASSERT_NE(status, QUIC_PENDING);
callback_->Run(status == QUIC_SUCCESS, *error_details_, details_);
@@ -120,6 +128,8 @@ class FakeProofVerifier : public ProofVerifier {
private:
std::string hostname_;
std::vector<std::string> certs_;
+ std::string ocsp_response_;
+ std::string cert_sct_;
const ProofVerifyContext* context_;
std::string* error_details_;
std::unique_ptr<ProofVerifyDetails>* details_;
@@ -265,7 +275,7 @@ void ExchangeHandshakeMessages(TestQuicCryptoStream* client,
ParsedQuicVersionVector AllTlsSupportedVersions() {
SetQuicReloadableFlag(quic_enable_version_99, true);
- SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
ParsedQuicVersionVector supported_versions;
for (QuicTransportVersion version : kSupportedTransportVersions) {
if (!QuicVersionUsesCryptoFrames(version)) {
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 ec254b53550..ca56e4dd3d2 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
@@ -211,6 +211,14 @@ bool TlsServerHandshaker::ProcessTransportParameters(
*error_details = "Unable to parse Transport Parameters";
return false;
}
+
+ // When interoperating with non-Google implementations that do not send
+ // the version extension, set it to what we expect.
+ if (client_params.version == 0) {
+ client_params.version =
+ CreateQuicVersionLabel(session()->connection()->version());
+ }
+
if (CryptoUtils::ValidateClientHelloVersion(
client_params.version, session()->connection()->version(),
session()->supported_versions(), error_details) != QUIC_NO_ERROR ||
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 51ea994fe95..75f7c6ac71a 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
@@ -8,47 +8,22 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
namespace quic {
-namespace {
-
-Perspective Reverse(Perspective perspective) {
- return perspective == Perspective::IS_SERVER ? Perspective::IS_CLIENT
- : Perspective::IS_SERVER;
-}
-
-} // namespace
UberQuicStreamIdManager::UberQuicStreamIdManager(
QuicSession* session,
- size_t max_open_outgoing_streams,
- size_t max_open_incoming_streams)
- : bidirectional_stream_id_manager_(
- session,
- QuicUtils::GetFirstBidirectionalStreamId(
- session->connection()->transport_version(),
- session->perspective()),
- session->perspective() == Perspective::IS_SERVER
- ? QuicUtils::GetCryptoStreamId(
- session->connection()->transport_version())
- : QuicUtils::GetInvalidStreamId(
- session->connection()->transport_version()),
- QuicUtils::GetFirstBidirectionalStreamId(
- session->connection()->transport_version(),
- Reverse(session->perspective())),
- max_open_outgoing_streams,
- max_open_incoming_streams),
+ QuicStreamCount max_open_outgoing_bidirectional_streams,
+ QuicStreamCount max_open_outgoing_unidirectional_streams,
+ QuicStreamCount max_open_incoming_bidirectional_streams,
+ QuicStreamCount max_open_incoming_unidirectional_streams)
+ : bidirectional_stream_id_manager_(session,
+ /*unidirectional=*/false,
+ max_open_outgoing_bidirectional_streams,
+ max_open_incoming_bidirectional_streams),
unidirectional_stream_id_manager_(
session,
- QuicUtils::GetFirstUnidirectionalStreamId(
- session->connection()->transport_version(),
- session->perspective()),
- QuicUtils::GetInvalidStreamId(
- session->connection()->transport_version()),
- QuicUtils::GetFirstUnidirectionalStreamId(
- session->connection()->transport_version(),
- Reverse(session->perspective())),
- max_open_outgoing_streams,
- max_open_incoming_streams) {}
-
+ /*unidirectional=*/true,
+ max_open_outgoing_unidirectional_streams,
+ max_open_incoming_unidirectional_streams) {}
void UberQuicStreamIdManager::RegisterStaticStream(QuicStreamId id) {
if (QuicUtils::IsBidirectionalStreamId(id)) {
bidirectional_stream_id_manager_.RegisterStaticStream(id);
@@ -57,14 +32,43 @@ void UberQuicStreamIdManager::RegisterStaticStream(QuicStreamId id) {
unidirectional_stream_id_manager_.RegisterStaticStream(id);
}
-void UberQuicStreamIdManager::SetMaxOpenOutgoingStreams(size_t max_streams) {
- bidirectional_stream_id_manager_.SetMaxOpenOutgoingStreams(max_streams);
- unidirectional_stream_id_manager_.SetMaxOpenOutgoingStreams(max_streams);
+void UberQuicStreamIdManager::AdjustMaxOpenOutgoingUnidirectionalStreams(
+ size_t max_streams) {
+ unidirectional_stream_id_manager_.AdjustMaxOpenOutgoingStreams(max_streams);
+}
+void UberQuicStreamIdManager::AdjustMaxOpenOutgoingBidirectionalStreams(
+ size_t max_streams) {
+ bidirectional_stream_id_manager_.AdjustMaxOpenOutgoingStreams(max_streams);
}
-void UberQuicStreamIdManager::SetMaxOpenIncomingStreams(size_t max_streams) {
- bidirectional_stream_id_manager_.SetMaxOpenIncomingStreams(max_streams);
- unidirectional_stream_id_manager_.SetMaxOpenIncomingStreams(max_streams);
+void UberQuicStreamIdManager::ConfigureMaxOpenOutgoingBidirectionalStreams(
+ size_t max_streams) {
+ bidirectional_stream_id_manager_.ConfigureMaxOpenOutgoingStreams(max_streams);
+}
+void UberQuicStreamIdManager::ConfigureMaxOpenOutgoingUnidirectionalStreams(
+ size_t max_streams) {
+ unidirectional_stream_id_manager_.ConfigureMaxOpenOutgoingStreams(
+ max_streams);
+}
+
+// TODO(fkastenholz): SetMax is cognizant of the number of static streams and
+// sets the maximum to be max_streams + number_of_statics. This should
+// eventually be removed from IETF QUIC.
+void UberQuicStreamIdManager::SetMaxOpenOutgoingBidirectionalStreams(
+ size_t max_open_streams) {
+ bidirectional_stream_id_manager_.SetMaxOpenOutgoingStreams(max_open_streams);
+}
+void UberQuicStreamIdManager::SetMaxOpenOutgoingUnidirectionalStreams(
+ size_t max_open_streams) {
+ unidirectional_stream_id_manager_.SetMaxOpenOutgoingStreams(max_open_streams);
+}
+void UberQuicStreamIdManager::SetMaxOpenIncomingBidirectionalStreams(
+ size_t max_open_streams) {
+ bidirectional_stream_id_manager_.SetMaxOpenIncomingStreams(max_open_streams);
+}
+void UberQuicStreamIdManager::SetMaxOpenIncomingUnidirectionalStreams(
+ size_t max_open_streams) {
+ unidirectional_stream_id_manager_.SetMaxOpenIncomingStreams(max_open_streams);
}
bool UberQuicStreamIdManager::CanOpenNextOutgoingBidirectionalStream() {
@@ -100,20 +104,20 @@ void UberQuicStreamIdManager::OnStreamClosed(QuicStreamId id) {
unidirectional_stream_id_manager_.OnStreamClosed(id);
}
-bool UberQuicStreamIdManager::OnMaxStreamIdFrame(
- const QuicMaxStreamIdFrame& frame) {
- if (QuicUtils::IsBidirectionalStreamId(frame.max_stream_id)) {
- return bidirectional_stream_id_manager_.OnMaxStreamIdFrame(frame);
+bool UberQuicStreamIdManager::OnMaxStreamsFrame(
+ const QuicMaxStreamsFrame& frame) {
+ if (frame.unidirectional) {
+ return unidirectional_stream_id_manager_.OnMaxStreamsFrame(frame);
}
- return unidirectional_stream_id_manager_.OnMaxStreamIdFrame(frame);
+ return bidirectional_stream_id_manager_.OnMaxStreamsFrame(frame);
}
-bool UberQuicStreamIdManager::OnStreamIdBlockedFrame(
- const QuicStreamIdBlockedFrame& frame) {
- if (QuicUtils::IsBidirectionalStreamId(frame.stream_id)) {
- return bidirectional_stream_id_manager_.OnStreamIdBlockedFrame(frame);
+bool UberQuicStreamIdManager::OnStreamsBlockedFrame(
+ const QuicStreamsBlockedFrame& frame) {
+ if (frame.unidirectional) {
+ return unidirectional_stream_id_manager_.OnStreamsBlockedFrame(frame);
}
- return unidirectional_stream_id_manager_.OnStreamIdBlockedFrame(frame);
+ return bidirectional_stream_id_manager_.OnStreamsBlockedFrame(frame);
}
bool UberQuicStreamIdManager::IsIncomingStream(QuicStreamId id) const {
@@ -132,12 +136,12 @@ bool UberQuicStreamIdManager::IsAvailableStream(QuicStreamId id) const {
size_t UberQuicStreamIdManager::GetMaxAllowdIncomingBidirectionalStreams()
const {
- return bidirectional_stream_id_manager_.max_allowed_incoming_streams();
+ return bidirectional_stream_id_manager_.incoming_initial_max_open_streams();
}
size_t UberQuicStreamIdManager::GetMaxAllowdIncomingUnidirectionalStreams()
const {
- return unidirectional_stream_id_manager_.max_allowed_incoming_streams();
+ return unidirectional_stream_id_manager_.incoming_initial_max_open_streams();
}
void UberQuicStreamIdManager::SetLargestPeerCreatedStreamId(
@@ -161,50 +165,37 @@ QuicStreamId UberQuicStreamIdManager::next_outgoing_unidirectional_stream_id()
return unidirectional_stream_id_manager_.next_outgoing_stream_id();
}
-QuicStreamId
-UberQuicStreamIdManager::max_allowed_outgoing_bidirectional_stream_id() const {
- return bidirectional_stream_id_manager_.max_allowed_outgoing_stream_id();
-}
-
-QuicStreamId
-UberQuicStreamIdManager::max_allowed_outgoing_unidirectional_stream_id() const {
- return unidirectional_stream_id_manager_.max_allowed_outgoing_stream_id();
-}
-
size_t UberQuicStreamIdManager::max_allowed_outgoing_bidirectional_streams()
const {
- return bidirectional_stream_id_manager_.max_allowed_outgoing_streams();
+ return bidirectional_stream_id_manager_.outgoing_max_streams();
}
size_t UberQuicStreamIdManager::max_allowed_outgoing_unidirectional_streams()
const {
- return unidirectional_stream_id_manager_.max_allowed_outgoing_streams();
+ return unidirectional_stream_id_manager_.outgoing_max_streams();
}
-QuicStreamId
-UberQuicStreamIdManager::actual_max_allowed_incoming_bidirectional_stream_id()
+QuicStreamCount
+UberQuicStreamIdManager::actual_max_allowed_incoming_bidirectional_streams()
const {
- return bidirectional_stream_id_manager_
- .actual_max_allowed_incoming_stream_id();
+ return bidirectional_stream_id_manager_.incoming_actual_max_streams();
}
-QuicStreamId
-UberQuicStreamIdManager::actual_max_allowed_incoming_unidirectional_stream_id()
+QuicStreamCount
+UberQuicStreamIdManager::actual_max_allowed_incoming_unidirectional_streams()
const {
- return unidirectional_stream_id_manager_
- .actual_max_allowed_incoming_stream_id();
+ return unidirectional_stream_id_manager_.incoming_actual_max_streams();
}
-QuicStreamId UberQuicStreamIdManager::
- advertised_max_allowed_incoming_bidirectional_stream_id() const {
- return bidirectional_stream_id_manager_
- .advertised_max_allowed_incoming_stream_id();
+QuicStreamCount
+UberQuicStreamIdManager::advertised_max_allowed_incoming_bidirectional_streams()
+ const {
+ return bidirectional_stream_id_manager_.incoming_advertised_max_streams();
}
-QuicStreamId UberQuicStreamIdManager::
- advertised_max_allowed_incoming_unidirectional_stream_id() const {
- return unidirectional_stream_id_manager_
- .advertised_max_allowed_incoming_stream_id();
+QuicStreamCount UberQuicStreamIdManager::
+ advertised_max_allowed_incoming_unidirectional_streams() const {
+ return unidirectional_stream_id_manager_.incoming_advertised_max_streams();
}
} // namespace quic
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 bf5a5882ba4..288f0c0a092 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
@@ -11,6 +11,7 @@ namespace quic {
namespace test {
class QuicSessionPeer;
+class UberQuicStreamIdManagerPeer;
} // namespace test
class QuicSession;
@@ -19,19 +20,39 @@ class QuicSession;
// unidirectional stream IDs, respectively.
class QUIC_EXPORT_PRIVATE UberQuicStreamIdManager {
public:
- UberQuicStreamIdManager(QuicSession* session,
- size_t max_open_outgoing_streams,
- size_t max_open_incoming_streams);
+ UberQuicStreamIdManager(
+ QuicSession* session,
+ QuicStreamCount max_open_outgoing_bidirectional_streams,
+ QuicStreamCount max_open_outgoing_unidirectional_streams,
+ QuicStreamCount max_open_incoming_bidirectional_streams,
+ QuicStreamCount max_open_incoming_unidirectional_streams);
// Called when a stream with |stream_id| is registered as a static stream.
void RegisterStaticStream(QuicStreamId id);
- // Initialize the maximum allowed outgoing stream id, number of streams, and
- // MAX_STREAM_ID advertisement window.
- void SetMaxOpenOutgoingStreams(size_t max_streams);
-
- // Initialize the maximum allowed incoming stream id and number of streams.
- void SetMaxOpenIncomingStreams(size_t max_streams);
+ // Sets the maximum outgoing stream count as a result of doing the transport
+ // configuration negotiation. Forces the limit to max_streams, regardless of
+ // static streams.
+ void ConfigureMaxOpenOutgoingBidirectionalStreams(size_t max_streams);
+ void ConfigureMaxOpenOutgoingUnidirectionalStreams(size_t max_streams);
+
+ // Sets the limits to max_open_streams + number of static streams
+ // in existence. SetMaxOpenOutgoingStreams will QUIC_BUG if it is called
+ // after getting the first MAX_STREAMS frame or the transport configuration
+ // was done.
+ // TODO(fkastenholz): SetMax is cognizant of the number of static streams and
+ // sets the maximum to be max_streams + number_of_statics. This should
+ // eventually be removed from IETF QUIC.
+ void SetMaxOpenOutgoingBidirectionalStreams(size_t max_open_streams);
+ void SetMaxOpenOutgoingUnidirectionalStreams(size_t max_open_streams);
+ void SetMaxOpenIncomingBidirectionalStreams(size_t max_open_streams);
+ void SetMaxOpenIncomingUnidirectionalStreams(size_t max_open_streams);
+
+ // Sets the outgoing stream count to the number of static streams + max
+ // outgoing streams. Unlike SetMaxOpenOutgoingStreams, this method will
+ // not QUIC_BUG if called after getting the first MAX_STREAMS frame.
+ void AdjustMaxOpenOutgoingBidirectionalStreams(size_t max_streams);
+ void AdjustMaxOpenOutgoingUnidirectionalStreams(size_t max_streams);
// Returns true if next outgoing bidirectional stream ID can be allocated.
bool CanOpenNextOutgoingBidirectionalStream();
@@ -45,17 +66,17 @@ class QUIC_EXPORT_PRIVATE UberQuicStreamIdManager {
// Returns the next outgoing unidirectional stream id.
QuicStreamId GetNextOutgoingUnidirectionalStreamId();
- // Returns true if allow to open the incoming |id|.
+ // Returns true if the incoming |id| is within the limit.
bool MaybeIncreaseLargestPeerStreamId(QuicStreamId id);
// Called when |id| is released.
void OnStreamClosed(QuicStreamId id);
- // Called when a MAX_STREAM_ID frame is received.
- bool OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame);
+ // Called when a MAX_STREAMS frame is received.
+ bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame);
- // Called when a STREAM_ID_BLOCKED frame is received.
- bool OnStreamIdBlockedFrame(const QuicStreamIdBlockedFrame& frame);
+ // Called when a STREAMS_BLOCKED frame is received.
+ bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame);
// Return true if |id| is peer initiated.
bool IsIncomingStream(QuicStreamId id) const;
@@ -73,20 +94,19 @@ class QUIC_EXPORT_PRIVATE UberQuicStreamIdManager {
QuicStreamId next_outgoing_bidirectional_stream_id() const;
QuicStreamId next_outgoing_unidirectional_stream_id() const;
- QuicStreamId max_allowed_outgoing_bidirectional_stream_id() const;
- QuicStreamId max_allowed_outgoing_unidirectional_stream_id() const;
-
size_t max_allowed_outgoing_bidirectional_streams() const;
size_t max_allowed_outgoing_unidirectional_streams() const;
- QuicStreamId actual_max_allowed_incoming_bidirectional_stream_id() const;
- QuicStreamId actual_max_allowed_incoming_unidirectional_stream_id() const;
+ QuicStreamCount actual_max_allowed_incoming_bidirectional_streams() const;
+ QuicStreamCount actual_max_allowed_incoming_unidirectional_streams() const;
- QuicStreamId advertised_max_allowed_incoming_bidirectional_stream_id() const;
- QuicStreamId advertised_max_allowed_incoming_unidirectional_stream_id() const;
+ QuicStreamCount advertised_max_allowed_incoming_bidirectional_streams() const;
+ QuicStreamCount advertised_max_allowed_incoming_unidirectional_streams()
+ const;
private:
friend class test::QuicSessionPeer;
+ friend class test::UberQuicStreamIdManagerPeer;
// Manages stream IDs of bidirectional streams.
QuicStreamIdManager bidirectional_stream_id_manager_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager_test.cc
index 929d0a1cc8f..8b1bacea54f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager_test.cc
@@ -7,6 +7,7 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
using testing::_;
@@ -59,6 +60,38 @@ class UberQuicStreamIdManagerTest : public QuicTestWithParam<Perspective> {
kV99StreamIdIncrement * n;
}
+ // TODO(fkastenholz): Existing tests can use these helper functions.
+ QuicStreamId GetNthPeerInitiatedBidirectionalStreamId(int n) {
+ return ((GetParam() == Perspective::IS_SERVER)
+ ? GetNthClientInitiatedBidirectionalId(n)
+ : GetNthServerInitiatedBidirectionalId(n));
+ }
+ QuicStreamId GetNthPeerInitiatedUnidirectionalStreamId(int n) {
+ return ((GetParam() == Perspective::IS_SERVER)
+ ? GetNthClientInitiatedUnidirectionalId(n)
+ : GetNthServerInitiatedUnidirectionalId(n));
+ }
+ QuicStreamId GetNthSelfInitiatedBidirectionalStreamId(int n) {
+ return ((GetParam() == Perspective::IS_CLIENT)
+ ? GetNthClientInitiatedBidirectionalId(n)
+ : GetNthServerInitiatedBidirectionalId(n));
+ }
+ QuicStreamId GetNthSelfInitiatedUnidirectionalStreamId(int n) {
+ return ((GetParam() == Perspective::IS_CLIENT)
+ ? GetNthClientInitiatedUnidirectionalId(n)
+ : GetNthServerInitiatedUnidirectionalId(n));
+ }
+
+ QuicStreamId StreamCountToId(QuicStreamCount stream_count,
+ Perspective perspective,
+ bool bidirectional) {
+ return ((bidirectional) ? QuicUtils::GetFirstBidirectionalStreamId(
+ QUIC_VERSION_99, perspective)
+ : QuicUtils::GetFirstUnidirectionalStreamId(
+ QUIC_VERSION_99, perspective)) +
+ ((stream_count - 1) * QuicUtils::StreamIdDelta(QUIC_VERSION_99));
+ }
+
MockQuicConnectionHelper helper_;
MockAlarmFactory alarm_factory_;
MockQuicConnection* connection_;
@@ -96,66 +129,86 @@ TEST_P(UberQuicStreamIdManagerTest, RegisterStaticStream) {
? GetNthClientInitiatedUnidirectionalId(0)
: GetNthServerInitiatedUnidirectionalId(0);
- QuicStreamId actual_max_allowed_incoming_bidirectional_stream_id =
- manager_->actual_max_allowed_incoming_bidirectional_stream_id();
- QuicStreamId actual_max_allowed_incoming_unidirectional_stream_id =
- manager_->actual_max_allowed_incoming_unidirectional_stream_id();
+ QuicStreamCount actual_max_allowed_incoming_bidirectional_streams =
+ manager_->actual_max_allowed_incoming_bidirectional_streams();
+ QuicStreamCount actual_max_allowed_incoming_unidirectional_streams =
+ manager_->actual_max_allowed_incoming_unidirectional_streams();
manager_->RegisterStaticStream(first_incoming_bidirectional_stream_id);
- // Verify actual_max_allowed_incoming_bidirectional_stream_id increases.
- EXPECT_EQ(actual_max_allowed_incoming_bidirectional_stream_id +
- kV99StreamIdIncrement,
- manager_->actual_max_allowed_incoming_bidirectional_stream_id());
- // Verify actual_max_allowed_incoming_unidirectional_stream_id does not
+ // Verify actual_max_allowed_incoming_bidirectional_streams increases.
+ EXPECT_EQ(actual_max_allowed_incoming_bidirectional_streams + 1u,
+ manager_->actual_max_allowed_incoming_bidirectional_streams());
+ // Verify actual_max_allowed_incoming_unidirectional_streams does not
// change.
- EXPECT_EQ(actual_max_allowed_incoming_unidirectional_stream_id,
- manager_->actual_max_allowed_incoming_unidirectional_stream_id());
+ EXPECT_EQ(actual_max_allowed_incoming_unidirectional_streams,
+ manager_->actual_max_allowed_incoming_unidirectional_streams());
manager_->RegisterStaticStream(first_incoming_unidirectional_stream_id);
- EXPECT_EQ(actual_max_allowed_incoming_bidirectional_stream_id +
- kV99StreamIdIncrement,
- manager_->actual_max_allowed_incoming_bidirectional_stream_id());
- EXPECT_EQ(actual_max_allowed_incoming_unidirectional_stream_id +
- kV99StreamIdIncrement,
- manager_->actual_max_allowed_incoming_unidirectional_stream_id());
+ EXPECT_EQ(actual_max_allowed_incoming_bidirectional_streams + 1u,
+ manager_->actual_max_allowed_incoming_bidirectional_streams());
+ EXPECT_EQ(actual_max_allowed_incoming_unidirectional_streams + 1u,
+ manager_->actual_max_allowed_incoming_unidirectional_streams());
}
TEST_P(UberQuicStreamIdManagerTest, SetMaxOpenOutgoingStreams) {
const size_t kNumMaxOutgoingStream = 123;
- manager_->SetMaxOpenOutgoingStreams(kNumMaxOutgoingStream);
+ // Set the uni- and bi- directional limits to different values to ensure
+ // that they are managed separately.
+ manager_->SetMaxOpenOutgoingBidirectionalStreams(kNumMaxOutgoingStream);
+ manager_->SetMaxOpenOutgoingUnidirectionalStreams(kNumMaxOutgoingStream + 1);
EXPECT_EQ(kNumMaxOutgoingStream,
manager_->max_allowed_outgoing_bidirectional_streams());
- EXPECT_EQ(kNumMaxOutgoingStream,
+ EXPECT_EQ(kNumMaxOutgoingStream + 1,
manager_->max_allowed_outgoing_unidirectional_streams());
+ // Check that, for each directionality, we can open the correct number of
+ // streams.
+ int i = kNumMaxOutgoingStream;
+ while (i) {
+ EXPECT_TRUE(manager_->CanOpenNextOutgoingBidirectionalStream());
+ manager_->GetNextOutgoingBidirectionalStreamId();
+ EXPECT_TRUE(manager_->CanOpenNextOutgoingUnidirectionalStream());
+ manager_->GetNextOutgoingUnidirectionalStreamId();
+ i--;
+ }
+ // One more unidirectional
+ EXPECT_TRUE(manager_->CanOpenNextOutgoingUnidirectionalStream());
+ manager_->GetNextOutgoingUnidirectionalStreamId();
+
+ // Both should be exhausted...
+ EXPECT_FALSE(manager_->CanOpenNextOutgoingUnidirectionalStream());
+ EXPECT_FALSE(manager_->CanOpenNextOutgoingBidirectionalStream());
}
TEST_P(UberQuicStreamIdManagerTest, SetMaxOpenIncomingStreams) {
const size_t kNumMaxIncomingStreams = 456;
- manager_->SetMaxOpenIncomingStreams(kNumMaxIncomingStreams);
- EXPECT_EQ(kNumMaxIncomingStreams,
+ manager_->SetMaxOpenIncomingUnidirectionalStreams(kNumMaxIncomingStreams);
+ // Do +1 for bidirectional to ensure that uni- and bi- get properly set.
+ manager_->SetMaxOpenIncomingBidirectionalStreams(kNumMaxIncomingStreams + 1);
+ EXPECT_EQ(kNumMaxIncomingStreams + 1,
manager_->GetMaxAllowdIncomingBidirectionalStreams());
EXPECT_EQ(kNumMaxIncomingStreams,
manager_->GetMaxAllowdIncomingUnidirectionalStreams());
- EXPECT_EQ(
- manager_->actual_max_allowed_incoming_bidirectional_stream_id(),
- manager_->advertised_max_allowed_incoming_bidirectional_stream_id());
- EXPECT_EQ(
- manager_->actual_max_allowed_incoming_unidirectional_stream_id(),
- manager_->advertised_max_allowed_incoming_unidirectional_stream_id());
+ EXPECT_EQ(manager_->actual_max_allowed_incoming_bidirectional_streams(),
+ manager_->advertised_max_allowed_incoming_bidirectional_streams());
+ EXPECT_EQ(manager_->actual_max_allowed_incoming_unidirectional_streams(),
+ manager_->advertised_max_allowed_incoming_unidirectional_streams());
+ // Make sure that we can create kNumMaxIncomingStreams incoming unidirectional
+ // streams and kNumMaxIncomingStreams+1 incoming bidirectional streams.
+ size_t i;
+ for (i = 0; i < kNumMaxIncomingStreams; i++) {
+ EXPECT_TRUE(manager_->MaybeIncreaseLargestPeerStreamId(
+ GetNthPeerInitiatedUnidirectionalStreamId(i)));
+ EXPECT_TRUE(manager_->MaybeIncreaseLargestPeerStreamId(
+ GetNthPeerInitiatedBidirectionalStreamId(i)));
+ }
+ // Should be able to open the next bidirectional stream
+ EXPECT_TRUE(manager_->MaybeIncreaseLargestPeerStreamId(
+ GetNthPeerInitiatedBidirectionalStreamId(i)));
- QuicStreamId first_incoming_bidirectional_stream_id =
- GetParam() == Perspective::IS_SERVER
- ? GetNthClientInitiatedBidirectionalId(0)
- : GetNthServerInitiatedBidirectionalId(0);
- QuicStreamId first_incoming_unidirectional_stream_id =
- GetParam() == Perspective::IS_SERVER
- ? GetNthClientInitiatedUnidirectionalId(0)
- : GetNthServerInitiatedUnidirectionalId(0);
- EXPECT_EQ(first_incoming_bidirectional_stream_id +
- (kNumMaxIncomingStreams - 1) * kV99StreamIdIncrement,
- manager_->actual_max_allowed_incoming_bidirectional_stream_id());
- EXPECT_EQ(first_incoming_unidirectional_stream_id +
- (kNumMaxIncomingStreams - 1) * kV99StreamIdIncrement,
- manager_->actual_max_allowed_incoming_unidirectional_stream_id());
+ // We should have exhausted the counts, the next streams should fail
+ EXPECT_FALSE(manager_->MaybeIncreaseLargestPeerStreamId(
+ GetNthPeerInitiatedUnidirectionalStreamId(i)));
+ EXPECT_FALSE(manager_->MaybeIncreaseLargestPeerStreamId(
+ GetNthPeerInitiatedBidirectionalStreamId(i + 1)));
}
TEST_P(UberQuicStreamIdManagerTest, GetNextOutgoingStreamId) {
@@ -214,86 +267,116 @@ TEST_P(UberQuicStreamIdManagerTest, AvailableStreams) {
TEST_P(UberQuicStreamIdManagerTest, MaybeIncreaseLargestPeerStreamId) {
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
- EXPECT_TRUE(manager_->MaybeIncreaseLargestPeerStreamId(
- manager_->actual_max_allowed_incoming_bidirectional_stream_id()));
- EXPECT_TRUE(manager_->MaybeIncreaseLargestPeerStreamId(
- manager_->actual_max_allowed_incoming_unidirectional_stream_id()));
+ EXPECT_TRUE(manager_->MaybeIncreaseLargestPeerStreamId(StreamCountToId(
+ manager_->actual_max_allowed_incoming_bidirectional_streams(),
+ /* Perspective=*/GetParam() == Perspective::IS_SERVER
+ ? Perspective::IS_CLIENT
+ : Perspective::IS_SERVER,
+ /* bidirectional=*/true)));
+ EXPECT_TRUE(manager_->MaybeIncreaseLargestPeerStreamId(StreamCountToId(
+ manager_->actual_max_allowed_incoming_bidirectional_streams(),
+ /* Perspective=*/GetParam() == Perspective::IS_SERVER
+ ? Perspective::IS_CLIENT
+ : Perspective::IS_SERVER,
+ /* bidirectional=*/false)));
+
+ std::string error_details =
+ GetParam() == Perspective::IS_SERVER
+ ? "Stream id 400 would exceed stream count limit 100"
+ : "Stream id 401 would exceed stream count limit 100";
- std::string error_details = GetParam() == Perspective::IS_SERVER
- ? "Stream id 404 above 400"
- : "Stream id 401 above 397";
EXPECT_CALL(*connection_,
CloseConnection(QUIC_INVALID_STREAM_ID, error_details, _));
- EXPECT_FALSE(manager_->MaybeIncreaseLargestPeerStreamId(
- manager_->actual_max_allowed_incoming_bidirectional_stream_id() +
- kV99StreamIdIncrement));
+ EXPECT_FALSE(manager_->MaybeIncreaseLargestPeerStreamId(StreamCountToId(
+ manager_->actual_max_allowed_incoming_bidirectional_streams() + 1,
+ /* Perspective=*/GetParam() == Perspective::IS_SERVER
+ ? Perspective::IS_CLIENT
+ : Perspective::IS_SERVER,
+ /* bidirectional=*/true)));
error_details = GetParam() == Perspective::IS_SERVER
- ? "Stream id 402 above 398"
- : "Stream id 403 above 399";
+ ? "Stream id 402 would exceed stream count limit 100"
+ : "Stream id 403 would exceed stream count limit 100";
EXPECT_CALL(*connection_,
CloseConnection(QUIC_INVALID_STREAM_ID, error_details, _));
- EXPECT_FALSE(manager_->MaybeIncreaseLargestPeerStreamId(
- manager_->actual_max_allowed_incoming_unidirectional_stream_id() +
- kV99StreamIdIncrement));
+ EXPECT_FALSE(manager_->MaybeIncreaseLargestPeerStreamId(StreamCountToId(
+ manager_->actual_max_allowed_incoming_bidirectional_streams() + 1,
+ /* Perspective=*/GetParam() == Perspective::IS_SERVER
+ ? Perspective::IS_CLIENT
+ : Perspective::IS_SERVER,
+ /* bidirectional=*/false)));
}
-TEST_P(UberQuicStreamIdManagerTest, OnMaxStreamIdFrame) {
- QuicStreamId max_allowed_outgoing_bidirectional_stream_id =
- manager_->max_allowed_outgoing_bidirectional_stream_id();
- QuicStreamId max_allowed_outgoing_unidirectional_stream_id =
- manager_->max_allowed_outgoing_unidirectional_stream_id();
-
- QuicMaxStreamIdFrame frame(kInvalidControlFrameId,
- max_allowed_outgoing_bidirectional_stream_id);
- EXPECT_TRUE(manager_->OnMaxStreamIdFrame(frame));
- EXPECT_EQ(max_allowed_outgoing_bidirectional_stream_id,
- manager_->max_allowed_outgoing_bidirectional_stream_id());
- frame.max_stream_id = max_allowed_outgoing_unidirectional_stream_id;
- EXPECT_TRUE(manager_->OnMaxStreamIdFrame(frame));
- EXPECT_EQ(max_allowed_outgoing_unidirectional_stream_id,
- manager_->max_allowed_outgoing_unidirectional_stream_id());
-
- frame.max_stream_id =
- max_allowed_outgoing_bidirectional_stream_id + kV99StreamIdIncrement;
- EXPECT_TRUE(manager_->OnMaxStreamIdFrame(frame));
- EXPECT_EQ(
- max_allowed_outgoing_bidirectional_stream_id + kV99StreamIdIncrement,
- manager_->max_allowed_outgoing_bidirectional_stream_id());
- EXPECT_EQ(max_allowed_outgoing_unidirectional_stream_id,
- manager_->max_allowed_outgoing_unidirectional_stream_id());
-
- frame.max_stream_id =
- max_allowed_outgoing_unidirectional_stream_id + kV99StreamIdIncrement;
- EXPECT_TRUE(manager_->OnMaxStreamIdFrame(frame));
- EXPECT_EQ(
- max_allowed_outgoing_bidirectional_stream_id + kV99StreamIdIncrement,
- manager_->max_allowed_outgoing_bidirectional_stream_id());
- EXPECT_EQ(
- max_allowed_outgoing_unidirectional_stream_id + kV99StreamIdIncrement,
- manager_->max_allowed_outgoing_unidirectional_stream_id());
+TEST_P(UberQuicStreamIdManagerTest, OnMaxStreamsFrame) {
+ QuicStreamCount max_allowed_outgoing_bidirectional_stream_count =
+ manager_->max_allowed_outgoing_bidirectional_streams();
+
+ QuicStreamCount max_allowed_outgoing_unidirectional_stream_count =
+ manager_->max_allowed_outgoing_unidirectional_streams();
+
+ // Inject a MAX_STREAMS frame that does not increase the limit and then
+ // check that there are no changes. First try the bidirectional manager.
+ QuicMaxStreamsFrame frame(kInvalidControlFrameId,
+ max_allowed_outgoing_bidirectional_stream_count,
+ /*unidirectional=*/false);
+ EXPECT_TRUE(manager_->OnMaxStreamsFrame(frame));
+ EXPECT_EQ(max_allowed_outgoing_bidirectional_stream_count,
+ manager_->max_allowed_outgoing_bidirectional_streams());
+
+ // Now try the unidirectioanl manager
+ frame.stream_count = max_allowed_outgoing_unidirectional_stream_count;
+ frame.unidirectional = true;
+ EXPECT_TRUE(manager_->OnMaxStreamsFrame(frame));
+ EXPECT_EQ(max_allowed_outgoing_unidirectional_stream_count,
+ manager_->max_allowed_outgoing_unidirectional_streams());
+
+ // Now try to increase the bidirectional stream count.
+ frame.stream_count = max_allowed_outgoing_bidirectional_stream_count + 1;
+ frame.unidirectional = false;
+ EXPECT_TRUE(manager_->OnMaxStreamsFrame(frame));
+ EXPECT_EQ(max_allowed_outgoing_bidirectional_stream_count + 1,
+ manager_->max_allowed_outgoing_bidirectional_streams());
+ // Make sure that the unidirectional state does not change.
+ EXPECT_EQ(max_allowed_outgoing_unidirectional_stream_count,
+ manager_->max_allowed_outgoing_unidirectional_streams());
+
+ // Now check that a MAX_STREAMS for the unidirectional manager increases
+ // just the unidirectiomal manager's state.
+ frame.stream_count = max_allowed_outgoing_unidirectional_stream_count + 1;
+ frame.unidirectional = true;
+ EXPECT_TRUE(manager_->OnMaxStreamsFrame(frame));
+ EXPECT_EQ(max_allowed_outgoing_bidirectional_stream_count + 1,
+ manager_->max_allowed_outgoing_bidirectional_streams());
+ EXPECT_EQ(max_allowed_outgoing_unidirectional_stream_count + 1,
+ manager_->max_allowed_outgoing_unidirectional_streams());
}
-TEST_P(UberQuicStreamIdManagerTest, OnStreamIdBlockedFrame) {
+TEST_P(UberQuicStreamIdManagerTest, OnStreamsBlockedFrame) {
+ // Set up to capture calls to SendControlFrame - when a STREAMS_BLOCKED
+ // frame is received, it will result in a a new MAX_STREAMS frame being
+ // sent (if new streams can be made available).
EXPECT_CALL(*connection_, SendControlFrame(_))
.WillRepeatedly(
Invoke(this, &UberQuicStreamIdManagerTest::SaveControlFrame));
- QuicStreamId stream_id =
- manager_->advertised_max_allowed_incoming_bidirectional_stream_id() -
- kV99StreamIdIncrement;
- QuicStreamIdBlockedFrame frame(kInvalidControlFrameId, stream_id);
- session_->OnStreamIdBlockedFrame(frame);
- EXPECT_EQ(MAX_STREAM_ID_FRAME, frame_.type);
- EXPECT_EQ(manager_->actual_max_allowed_incoming_bidirectional_stream_id(),
- frame_.max_stream_id_frame.max_stream_id);
-
- frame.stream_id =
- manager_->advertised_max_allowed_incoming_unidirectional_stream_id() -
- kV99StreamIdIncrement;
- session_->OnStreamIdBlockedFrame(frame);
- EXPECT_EQ(MAX_STREAM_ID_FRAME, frame_.type);
- EXPECT_EQ(manager_->actual_max_allowed_incoming_unidirectional_stream_id(),
- frame_.max_stream_id_frame.max_stream_id);
+ QuicStreamCount stream_count =
+ manager_->advertised_max_allowed_incoming_bidirectional_streams() - 1;
+
+ QuicStreamsBlockedFrame frame(kInvalidControlFrameId, stream_count,
+ /*unidirectional=*/false);
+ session_->OnStreamsBlockedFrame(frame);
+ EXPECT_EQ(MAX_STREAMS_FRAME, frame_.type);
+ EXPECT_EQ(manager_->actual_max_allowed_incoming_bidirectional_streams(),
+ frame_.max_streams_frame.stream_count);
+
+ stream_count =
+ manager_->advertised_max_allowed_incoming_unidirectional_streams() - 1;
+ frame.stream_count = stream_count;
+ frame.unidirectional = true;
+
+ session_->OnStreamsBlockedFrame(frame);
+ EXPECT_EQ(MAX_STREAMS_FRAME, frame_.type);
+ EXPECT_EQ(manager_->actual_max_allowed_incoming_unidirectional_streams(),
+ frame_.max_streams_frame.stream_count);
}
TEST_P(UberQuicStreamIdManagerTest, IsIncomingStream) {
@@ -318,6 +401,44 @@ TEST_P(UberQuicStreamIdManagerTest, IsIncomingStream) {
}
}
+TEST_P(UberQuicStreamIdManagerTest, SetMaxOpenOutgoingStreamsPlusFrame) {
+ const size_t kNumMaxOutgoingStream = 123;
+ // Set the uni- and bi- directional limits to different values to ensure
+ // that they are managed separately.
+ manager_->SetMaxOpenOutgoingBidirectionalStreams(kNumMaxOutgoingStream);
+ manager_->SetMaxOpenOutgoingUnidirectionalStreams(kNumMaxOutgoingStream + 1);
+ EXPECT_EQ(kNumMaxOutgoingStream,
+ manager_->max_allowed_outgoing_bidirectional_streams());
+ EXPECT_EQ(kNumMaxOutgoingStream + 1,
+ manager_->max_allowed_outgoing_unidirectional_streams());
+ // Check that, for each directionality, we can open the correct number of
+ // streams.
+ int i = kNumMaxOutgoingStream;
+ while (i) {
+ EXPECT_TRUE(manager_->CanOpenNextOutgoingBidirectionalStream());
+ manager_->GetNextOutgoingBidirectionalStreamId();
+ EXPECT_TRUE(manager_->CanOpenNextOutgoingUnidirectionalStream());
+ manager_->GetNextOutgoingUnidirectionalStreamId();
+ i--;
+ }
+ // One more unidirectional
+ EXPECT_TRUE(manager_->CanOpenNextOutgoingUnidirectionalStream());
+ manager_->GetNextOutgoingUnidirectionalStreamId();
+
+ // Both should be exhausted...
+ EXPECT_FALSE(manager_->CanOpenNextOutgoingUnidirectionalStream());
+ EXPECT_FALSE(manager_->CanOpenNextOutgoingBidirectionalStream());
+
+ // Now cons a MAX STREAMS frame for unidirectional streams to raise
+ // the limit.
+ QuicMaxStreamsFrame frame(1, kNumMaxOutgoingStream + 10,
+ /*unidirectional=*/true);
+ manager_->OnMaxStreamsFrame(frame);
+ // We now should be able to get another uni- stream, but not a bi.
+ EXPECT_TRUE(manager_->CanOpenNextOutgoingUnidirectionalStream());
+ EXPECT_FALSE(manager_->CanOpenNextOutgoingBidirectionalStream());
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.cc b/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.cc
index e8876369c8b..a3c79d34428 100644
--- a/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.cc
@@ -195,6 +195,12 @@ const QuicAckFrame& UberReceivedPacketManager::ack_frame() const {
return received_packet_managers_[0].ack_frame();
}
+const QuicAckFrame& UberReceivedPacketManager::GetAckFrame(
+ PacketNumberSpace packet_number_space) const {
+ DCHECK(supports_multiple_packet_number_spaces_);
+ return received_packet_managers_[packet_number_space].ack_frame();
+}
+
void UberReceivedPacketManager::set_max_ack_ranges(size_t max_ack_ranges) {
for (auto& received_packet_manager : received_packet_managers_) {
received_packet_manager.set_max_ack_ranges(max_ack_ranges);
diff --git a/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.h b/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.h
index 5c813e21f6d..21c2c0c7240 100644
--- a/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/uber_received_packet_manager.h
@@ -85,6 +85,7 @@ class QUIC_EXPORT_PRIVATE UberReceivedPacketManager {
// For logging purposes.
const QuicAckFrame& ack_frame() const;
+ const QuicAckFrame& GetAckFrame(PacketNumberSpace packet_number_space) const;
void set_max_ack_ranges(size_t max_ack_ranges);
diff --git a/chromium/net/third_party/quiche/src/quic/platform/README.md b/chromium/net/third_party/quiche/src/quic/platform/README.md
new file mode 100644
index 00000000000..6538de108cf
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/platform/README.md
@@ -0,0 +1,12 @@
+# QUIC platform
+
+This platform/ directory exists in order to allow QUIC code to be built on
+numerous platforms. It contains two subdirectories:
+
+- api/ contains platform independent class definitions for fundamental data
+ structures (e.g., IPAddress, SocketAddress, etc.).
+- impl/ contains platform specific implementations of these data structures.
+ The content of files in impl/ will vary depending on the platform.
+
+Code in the parent quic/ directory should not depend on any platform specific
+code, other than that found in impl/.
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/README.md b/chromium/net/third_party/quiche/src/quic/platform/api/README.md
new file mode 100644
index 00000000000..d3de2e14073
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/README.md
@@ -0,0 +1,67 @@
+# QUIC platform API
+
+This directory contains the infrastructure blocks needed to support QUIC in
+certain platform. These APIs act as interaction layers between QUIC core and
+either the upper layer application (i.e. Chrome, Envoy) or the platform's own
+infrastructure (i.e. logging, test framework and system IO). QUIC core needs the
+implementations of these APIs to build and function appropriately. There is
+unidirectional dependency from QUIC core to most of the APIs here, such as
+QUIC_LOG and QuicMutex, but a few APIs also depend back on QUIC core's basic
+QUIC data types, such as QuicClock and QuicSleep.
+
+- APIs used by QUIC core:
+
+ Most APIs are used by QUIC core to interact with platform infrastructure
+ (i.e. QUIC_LOG) or to wrap around platform dependent data types (i.e.
+ QuicIntervalSet), the dependency is:
+
+ ```dot
+ digraph {
+ application -> quic_core -> quic_platform_api -> quic_platform_impl -> platform_infrastructure
+ application -> platform_infrastructure
+ }
+ ```
+
+- APIs used by applications:
+
+ Some APIs are used by applications to interact with QUIC core (i.e.
+ QuicMemSlice). For such APIs, their dependency model is:
+
+ ```dot
+ digraph {
+ application -> quic_platform_impl -> platform_infrastructure
+ application -> quic_core -> quic_platform_api
+ quic_platform_impl -> quic_platform_api
+ application -> platform_infrastructure
+ }
+ ```
+
+ An example for such dependency is QuicClock.
+
+ Or
+
+ ```dot
+ digraph {
+ application -> quic_platform_impl -> platform_infrastructure
+ application -> quic_core -> quic_platform_api -> quic_platform_impl
+ quic_platform_impl -> quic_platform_api
+ application -> platform_infrastructure
+ }
+ ```
+
+ An example for such dependency is QuicMemSlice.
+
+# Documentation of each API and its usage.
+
+QuicMemSlice
+: QuicMemSlice is used to wrap application data and pass to QUIC stream's
+ write interface. It refers to a memory block of data which should be around
+ till QuicMemSlice::Reset() is called. It's upto each platform, to implement
+ it as reference counted or not.
+
+QuicClock
+: QuicClock is used by QUIC core to get current time. Its instance is created
+ by applications and passed into QuicDispatcher and
+ QuicConnectionHelperInterface.
+
+TODO(b/131224336) add document for other APIs
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_clock.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_clock.h
index afd82dc5906..80000177780 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_clock.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_clock.h
@@ -8,6 +8,11 @@
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+/* API_DESCRIPTION
+ QuicClock is used by QUIC core to get current time. Its instance is created by
+ applications and passed into QuicDispatcher and QuicConnectionHelperInterface.
+ API-DESCRIPTION */
+
namespace quic {
// Interface for retrieving the current time.
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_flags.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_flags.h
index 302036fd3d8..bf6fc3c306a 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_flags.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_flags.h
@@ -8,6 +8,7 @@
#include <string>
#include <vector>
+#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/quic/platform/impl/quic_flags_impl.h"
// Define a command-line flag that can be automatically set via
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address.cc
index 2b86cadc3fa..3b48c475f67 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address.cc
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address.cc
@@ -85,7 +85,15 @@ bool QuicIpAddress::IsIPv6() const {
bool QuicIpAddress::InSameSubnet(const QuicIpAddress& other,
int subnet_length) {
- return impl_.InSameSubnet(other.impl(), subnet_length);
+ return impl_.InSameSubnet(other.impl_, subnet_length);
+}
+
+in_addr QuicIpAddress::GetIPv4() const {
+ return impl_.GetIPv4();
+}
+
+in6_addr QuicIpAddress::GetIPv6() const {
+ return impl_.GetIPv6();
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address.h
index f6013af4d4b..6d507b4d843 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address.h
@@ -73,7 +73,8 @@ class QUIC_EXPORT_PRIVATE QuicIpAddress {
bool IsIPv6() const;
bool InSameSubnet(const QuicIpAddress& other, int subnet_length);
- const QuicIpAddressImpl& impl() const { return impl_; }
+ in_addr GetIPv4() const;
+ in6_addr GetIPv6() const;
private:
QuicIpAddressImpl impl_;
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address_test.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address_test.cc
new file mode 100644
index 00000000000..69424272146
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_ip_address_test.cc
@@ -0,0 +1,63 @@
+// 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/platform/api/quic_ip_address.h"
+
+#include <cstdint>
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+
+namespace quic {
+namespace test {
+namespace {
+
+TEST(QuicIpAddressTest, IPv4) {
+ QuicIpAddress ip_address;
+ EXPECT_FALSE(ip_address.IsInitialized());
+
+ EXPECT_TRUE(ip_address.FromString("127.0.52.223"));
+ EXPECT_TRUE(ip_address.IsInitialized());
+
+ EXPECT_EQ(IpAddressFamily::IP_V4, ip_address.address_family());
+ EXPECT_TRUE(ip_address.IsIPv4());
+ EXPECT_FALSE(ip_address.IsIPv6());
+
+ EXPECT_EQ("127.0.52.223", ip_address.ToString());
+ const in_addr v4_address = ip_address.GetIPv4();
+ const uint8_t* const v4_address_ptr =
+ reinterpret_cast<const uint8_t*>(&v4_address);
+ EXPECT_EQ(127u, *(v4_address_ptr + 0));
+ EXPECT_EQ(0u, *(v4_address_ptr + 1));
+ EXPECT_EQ(52u, *(v4_address_ptr + 2));
+ EXPECT_EQ(223u, *(v4_address_ptr + 3));
+}
+
+TEST(QuicIpAddressTest, IPv6) {
+ QuicIpAddress ip_address;
+ EXPECT_FALSE(ip_address.IsInitialized());
+
+ EXPECT_TRUE(ip_address.FromString("fe80::1ff:fe23:4567"));
+ EXPECT_TRUE(ip_address.IsInitialized());
+
+ EXPECT_EQ(IpAddressFamily::IP_V6, ip_address.address_family());
+ EXPECT_FALSE(ip_address.IsIPv4());
+ EXPECT_TRUE(ip_address.IsIPv6());
+
+ EXPECT_EQ("fe80::1ff:fe23:4567", ip_address.ToString());
+ const in6_addr v6_address = ip_address.GetIPv6();
+ const uint16_t* const v6_address_ptr =
+ reinterpret_cast<const uint16_t*>(&v6_address);
+ EXPECT_EQ(0x80feu, *(v6_address_ptr + 0));
+ EXPECT_EQ(0x0000u, *(v6_address_ptr + 1));
+ EXPECT_EQ(0x0000u, *(v6_address_ptr + 2));
+ EXPECT_EQ(0x0000u, *(v6_address_ptr + 3));
+ EXPECT_EQ(0x0000u, *(v6_address_ptr + 4));
+ EXPECT_EQ(0xff01u, *(v6_address_ptr + 5));
+ EXPECT_EQ(0x23feu, *(v6_address_ptr + 6));
+ EXPECT_EQ(0x6745u, *(v6_address_ptr + 7));
+}
+
+} // namespace
+} // namespace test
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h
index a4318ad8bcc..a40d6384df9 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h
@@ -8,6 +8,13 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/quic/platform/impl/quic_mem_slice_impl.h"
+/* API_DESCRIPTION
+ QuicMemSlice is used to wrap application data and pass to QUIC stream's write
+ interface. It refers to a memory block of data which should be around till
+ QuicMemSlice::Reset() is called. It's upto each platform, to implement it as
+ reference counted or not.
+ API-DESCRIPTION */
+
namespace quic {
// QuicMemSlice is an internally reference counted data buffer used as the
@@ -53,6 +60,8 @@ class QUIC_EXPORT_PRIVATE QuicMemSlice {
bool empty() const { return impl_.empty(); }
+ QuicMemSliceImpl* impl() { return &impl_; }
+
private:
QuicMemSliceImpl impl_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h
index 4fdf059434b..62cec4871c9 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h
@@ -22,6 +22,9 @@ class QUIC_EXPORT_PRIVATE QuicMemSliceSpan {
public:
explicit QuicMemSliceSpan(QuicMemSliceSpanImpl impl) : impl_(impl) {}
+ // Constructs a span with a single QuicMemSlice.
+ explicit QuicMemSliceSpan(QuicMemSlice* slice) : impl_(slice->impl()) {}
+
QuicMemSliceSpan(const QuicMemSliceSpan& other) = default;
QuicMemSliceSpan& operator=(const QuicMemSliceSpan& other) = default;
QuicMemSliceSpan(QuicMemSliceSpan&& other) = default;
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_optional.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_optional.h
new file mode 100644
index 00000000000..921c3a874a3
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_optional.h
@@ -0,0 +1,17 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_OPTIONAL_H_
+#define QUICHE_QUIC_PLATFORM_API_QUIC_OPTIONAL_H_
+
+#include "net/quic/platform/impl/quic_optional_impl.h"
+
+namespace quic {
+
+template <typename T>
+using QuicOptional = QuicOptionalImpl<T>;
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_PLATFORM_API_QUIC_OPTIONAL_H_
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.cc
index dacd6ac3505..e0bb35c4f7d 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.cc
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.cc
@@ -9,7 +9,7 @@
namespace quic {
QuicSocketAddress::QuicSocketAddress(QuicIpAddress address, uint16_t port)
- : impl_(address.impl(), port) {}
+ : impl_(address, port) {}
QuicSocketAddress::QuicSocketAddress(const struct sockaddr_storage& saddr)
: impl_(saddr) {}
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.h
index 57689a77828..85e61d5a235 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_socket_address.h
@@ -39,7 +39,6 @@ class QUIC_EXPORT_PRIVATE QuicSocketAddress {
QuicIpAddress host() const;
uint16_t port() const;
sockaddr_storage generic_address() const;
- const QuicSocketAddressImpl& impl() const { return impl_; }
private:
QuicSocketAddressImpl impl_;
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_string_utils_test.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_string_utils_test.cc
index e2f13005846..39f675f8bd3 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_string_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_string_utils_test.cc
@@ -6,9 +6,9 @@
#include <cstdint>
-#include "testing/gtest/include/gtest/gtest.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"
namespace quic {
namespace test {
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 f4d255ab0b8..2f3286541a9 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
@@ -5,6 +5,7 @@
#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_TEST_H_
#define QUICHE_QUIC_PLATFORM_API_QUIC_TEST_H_
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/quic/platform/impl/quic_test_impl.h"
using QuicFlagSaver = QuicFlagSaverImpl;
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_connection_helper.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_connection_helper.cc
index 6c6ee97c29f..da74858d69b 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_connection_helper.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_connection_helper.cc
@@ -6,15 +6,16 @@
namespace quic {
-QuartcConnectionHelper::QuartcConnectionHelper(const QuicClock* clock)
- : clock_(clock) {}
+QuartcConnectionHelper::QuartcConnectionHelper(const QuicClock* clock,
+ QuicRandom* random)
+ : clock_(clock), random_(random) {}
const QuicClock* QuartcConnectionHelper::GetClock() const {
return clock_;
}
QuicRandom* QuartcConnectionHelper::GetRandomGenerator() {
- return QuicRandom::GetInstance();
+ return random_;
}
QuicBufferAllocator* QuartcConnectionHelper::GetStreamSendBufferAllocator() {
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h b/chromium/net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h
index 2b1d62f9a53..184dacc1aaf 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h
@@ -16,7 +16,7 @@ namespace quic {
// Simple implementation of QuicConnectionHelperInterface for Quartc.
class QuartcConnectionHelper : public QuicConnectionHelperInterface {
public:
- explicit QuartcConnectionHelper(const QuicClock* clock);
+ QuartcConnectionHelper(const QuicClock* clock, QuicRandom* random);
// QuicConnectionHelperInterface overrides.
const QuicClock* GetClock() const override;
@@ -25,6 +25,7 @@ class QuartcConnectionHelper : public QuicConnectionHelperInterface {
private:
const QuicClock* clock_;
+ QuicRandom* random_;
SimpleBufferAllocator buffer_allocator_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.cc
index 93023e72d3f..4653000138b 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.cc
@@ -60,6 +60,8 @@ QuicAsyncStatus InsecureProofVerifier::VerifyProof(
QuicAsyncStatus InsecureProofVerifier::VerifyCertChain(
const std::string& hostname,
const std::vector<std::string>& certs,
+ const std::string& ocsp_response,
+ const std::string& cert_sct,
const ProofVerifyContext* context,
std::string* error_details,
std::unique_ptr<ProofVerifyDetails>* details,
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h b/chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h
index 2dba7ac7d06..1436aeb41f0 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h
@@ -88,6 +88,8 @@ class InsecureProofVerifier : public ProofVerifier {
QuicAsyncStatus VerifyCertChain(
const std::string& hostname,
const std::vector<std::string>& certs,
+ const std::string& ocsp_response,
+ const std::string& cert_sct,
const ProofVerifyContext* context,
std::string* error_details,
std::unique_ptr<ProofVerifyDetails>* details,
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.cc
index fd4f289f3a6..e6e9c2b0a89 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.cc
@@ -37,9 +37,9 @@ QuartcDispatcher::QuartcDispatcher(
delegate_(delegate),
packet_writer_(packet_writer.get()) {
// Allow incoming packets to set our expected connection ID length.
- SetShouldUpdateExpectedConnectionIdLength(true);
+ SetShouldUpdateExpectedServerConnectionIdLength(true);
// Allow incoming packets with connection ID lengths shorter than allowed.
- SetAllowShortInitialConnectionIds(true);
+ SetAllowShortInitialServerConnectionIds(true);
// QuicDispatcher takes ownership of the writer.
QuicDispatcher::InitializeWithWriter(packet_writer.release());
// NB: This must happen *after* InitializeWithWriter. It can call us back
@@ -58,7 +58,7 @@ QuartcSession* QuartcDispatcher::CreateQuicSession(
QuicStringPiece alpn,
const ParsedQuicVersion& version) {
// Make our expected connection ID non-mutable since we have a connection.
- SetShouldUpdateExpectedConnectionIdLength(false);
+ SetShouldUpdateExpectedServerConnectionIdLength(false);
std::unique_ptr<QuicConnection> connection = CreateQuicConnection(
connection_id, client_address, helper(), alarm_factory(), writer(),
Perspective::IS_SERVER, ParsedQuicVersionVector{version});
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.h b/chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.h
index 26b52ac4f0c..239b6ef0c22 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.h
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_dispatcher.h
@@ -41,7 +41,7 @@ class QuartcDispatcher : public QuicDispatcher,
Delegate* delegate);
~QuartcDispatcher() override;
- QuartcSession* CreateQuicSession(QuicConnectionId connection_id,
+ QuartcSession* CreateQuicSession(QuicConnectionId server_connection_id,
const QuicSocketAddress& client_address,
QuicStringPiece alpn,
const ParsedQuicVersion& version) override;
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.cc
index 459ceba0618..7676c591062 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.cc
@@ -47,6 +47,7 @@ QuicArenaScopedPtr<QuicAlarm> QuartcAlarmFactoryWrapper::CreateAlarm(
QuartcClientEndpoint::QuartcClientEndpoint(
QuicAlarmFactory* alarm_factory,
const QuicClock* clock,
+ QuicRandom* random,
QuartcEndpoint::Delegate* delegate,
const QuartcSessionConfig& config,
QuicStringPiece serialized_server_config,
@@ -60,25 +61,82 @@ QuartcClientEndpoint::QuartcClientEndpoint(
AllSupportedVersions())),
create_session_alarm_(QuicWrapUnique(
alarm_factory_->CreateAlarm(new CreateSessionDelegate(this)))),
- connection_helper_(QuicMakeUnique<QuartcConnectionHelper>(clock)),
+ connection_helper_(
+ QuicMakeUnique<QuartcConnectionHelper>(clock_, random)),
config_(config) {}
void QuartcClientEndpoint::Connect(QuartcPacketTransport* packet_transport) {
packet_transport_ = packet_transport;
+ // For the first attempt to connect, use any version that the client supports.
+ current_versions_ = version_manager_->GetSupportedVersions();
create_session_alarm_->Set(clock_->Now());
}
void QuartcClientEndpoint::OnCreateSessionAlarm() {
session_ = CreateQuartcClientSession(
config_, clock_, alarm_factory_, connection_helper_.get(),
- version_manager_->GetSupportedVersions(), serialized_server_config_,
- packet_transport_);
+ current_versions_, serialized_server_config_, packet_transport_);
+ session_->SetDelegate(this);
delegate_->OnSessionCreated(session_.get());
}
+void QuartcClientEndpoint::OnCryptoHandshakeComplete() {
+ delegate_->OnCryptoHandshakeComplete();
+}
+
+void QuartcClientEndpoint::OnConnectionWritable() {
+ delegate_->OnConnectionWritable();
+}
+
+void QuartcClientEndpoint::OnIncomingStream(QuartcStream* stream) {
+ delegate_->OnIncomingStream(stream);
+}
+
+void QuartcClientEndpoint::OnCongestionControlChange(
+ QuicBandwidth bandwidth_estimate,
+ QuicBandwidth pacing_rate,
+ QuicTime::Delta latest_rtt) {
+ delegate_->OnCongestionControlChange(bandwidth_estimate, pacing_rate,
+ latest_rtt);
+}
+
+void QuartcClientEndpoint::OnConnectionClosed(QuicErrorCode error_code,
+ const std::string& error_details,
+ ConnectionCloseSource source) {
+ // First, see if we can restart the session with a mutually-supported version.
+ if (error_code == QUIC_INVALID_VERSION && session_ &&
+ session_->connection() &&
+ !session_->connection()->server_supported_versions().empty()) {
+ for (const auto& client_version :
+ version_manager_->GetSupportedVersions()) {
+ if (QuicContainsValue(session_->connection()->server_supported_versions(),
+ client_version)) {
+ // Found a mutually-supported version. Reconnect using that version.
+ current_versions_.clear();
+ current_versions_.push_back(client_version);
+ create_session_alarm_->Set(clock_->Now());
+ return;
+ }
+ }
+ }
+
+ // Permanent version negotiation errors are forwarded to the |delegate_|,
+ // along with all other errors.
+ delegate_->OnConnectionClosed(error_code, error_details, source);
+}
+
+void QuartcClientEndpoint::OnMessageReceived(QuicStringPiece message) {
+ delegate_->OnMessageReceived(message);
+}
+
+void QuartcClientEndpoint::OnMessageSent(int64_t datagram_id) {
+ delegate_->OnMessageSent(datagram_id);
+}
+
QuartcServerEndpoint::QuartcServerEndpoint(
QuicAlarmFactory* alarm_factory,
const QuicClock* clock,
+ QuicRandom* random,
QuartcEndpoint::Delegate* delegate,
const QuartcSessionConfig& config,
std::unique_ptr<QuicVersionManager> version_manager)
@@ -88,7 +146,8 @@ QuartcServerEndpoint::QuartcServerEndpoint(
version_manager_(version_manager ? std::move(version_manager)
: QuicMakeUnique<QuicVersionManager>(
AllSupportedVersions())),
- pre_connection_helper_(QuicMakeUnique<QuartcConnectionHelper>(clock)),
+ pre_connection_helper_(
+ QuicMakeUnique<QuartcConnectionHelper>(clock, random)),
crypto_config_(
CreateCryptoServerConfig(pre_connection_helper_->GetRandomGenerator(),
clock,
@@ -111,6 +170,7 @@ void QuartcServerEndpoint::Connect(QuartcPacketTransport* packet_transport) {
}
void QuartcServerEndpoint::OnSessionCreated(QuartcSession* session) {
+ session->SetDelegate(delegate_);
delegate_->OnSessionCreated(session);
}
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.h b/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.h
index 97f30609ec0..6c7644c9519 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.h
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_endpoint.h
@@ -10,6 +10,7 @@
#include "net/third_party/quiche/src/quic/core/quic_alarm_factory.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_dispatcher.h"
@@ -29,22 +30,23 @@ class QuartcEndpointImpl {
// Endpoint (client or server) in a peer-to-peer Quartc connection.
class QuartcEndpoint {
public:
- class Delegate {
+ class Delegate : public QuartcSession::Delegate {
public:
virtual ~Delegate() = default;
// Called when an endpoint creates a new session, before any packets are
// processed or sent. The callee should perform any additional
- // configuration required, such as setting a session delegate, before
+ // configuration required, such as setting up congestion control, before
// returning. |session| is owned by the endpoint, but remains safe to use
- // until another call to |OnSessionCreated| occurs, at which point previous
- // session is destroyed.
+ // until another call to |OnSessionCreated| or |OnConnectionClosed| occurs,
+ // at which point previous session may be destroyed.
+ //
+ // Callees must not change the |session|'s delegate. The Endpoint itself
+ // manages the delegate and will forward calls.
+ //
+ // New calls to |OnSessionCreated| will only occur prior to
+ // |OnConnectionWritable|, during initial connection negotiation.
virtual void OnSessionCreated(QuartcSession* session) = 0;
-
- // Called if the endpoint fails to establish a session after a call to
- // Connect. (The most likely cause is a network idle timeout.)
- virtual void OnConnectError(QuicErrorCode error,
- const std::string& error_details) = 0;
};
virtual ~QuartcEndpoint() = default;
@@ -58,20 +60,35 @@ class QuartcEndpoint {
// Implementation of QuartcEndpoint which immediately (but asynchronously)
// creates a session by scheduling a QuicAlarm. Only suitable for use with the
// client perspective.
-class QuartcClientEndpoint : public QuartcEndpoint {
+class QuartcClientEndpoint : public QuartcEndpoint,
+ public QuartcSession::Delegate {
public:
// |alarm_factory|, |clock|, and |delegate| are owned by the caller and must
// outlive the endpoint.
QuartcClientEndpoint(
QuicAlarmFactory* alarm_factory,
const QuicClock* clock,
- Delegate* delegate,
+ QuicRandom* random,
+ QuartcEndpoint::Delegate* delegate,
const QuartcSessionConfig& config,
QuicStringPiece serialized_server_config,
std::unique_ptr<QuicVersionManager> version_manager = nullptr);
void Connect(QuartcPacketTransport* packet_transport) override;
+ // QuartcSession::Delegate overrides.
+ void OnCryptoHandshakeComplete() override;
+ void OnConnectionWritable() override;
+ void OnIncomingStream(QuartcStream* stream) override;
+ void OnCongestionControlChange(QuicBandwidth bandwidth_estimate,
+ QuicBandwidth pacing_rate,
+ QuicTime::Delta latest_rtt) override;
+ void OnConnectionClosed(QuicErrorCode error_code,
+ const std::string& error_details,
+ ConnectionCloseSource source) override;
+ void OnMessageReceived(QuicStringPiece message) override;
+ void OnMessageSent(int64_t datagram_id) override;
+
private:
friend class CreateSessionDelegate;
class CreateSessionDelegate : public QuicAlarm::Delegate {
@@ -103,6 +120,18 @@ class QuartcClientEndpoint : public QuartcEndpoint {
// Version manager. May be injected to control version negotiation in tests.
std::unique_ptr<QuicVersionManager> version_manager_;
+ // Versions to be used when the next session is created. The session will
+ // choose one of these versions for its connection attempt.
+ //
+ // If the connection does not succeed, the client session MAY try again using
+ // another version from this list, or it MAY simply fail with a
+ // QUIC_INVALID_VERSION error. The latter occurs when it is not possible to
+ // upgrade a connection in-place (for example, if the way stream ids are
+ // allocated changes between versions). This failure mode is handled by
+ // narrowing |current_versions_| to one of that is mutually-supported and
+ // reconnecting (with a new session).
+ ParsedQuicVersionVector current_versions_;
+
// Alarm for creating sessions asynchronously. The alarm is set when
// Connect() is called. When it fires, the endpoint creates a session and
// calls the delegate.
@@ -130,6 +159,7 @@ class QuartcServerEndpoint : public QuartcEndpoint,
QuartcServerEndpoint(
QuicAlarmFactory* alarm_factory,
const QuicClock* clock,
+ QuicRandom* random,
QuartcEndpoint::Delegate* delegate,
const QuartcSessionConfig& config,
std::unique_ptr<QuicVersionManager> version_manager = nullptr);
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 3d7d85e8ed8..5f8c25d6416 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
@@ -30,20 +30,20 @@ class QuartcEndpointTest : public QuicTest {
&server_transport_,
QuicBandwidth::FromKBitsPerSecond(10000),
QuicTime::Delta::FromMilliseconds(1)),
- server_session_delegate_(&server_stream_delegate_,
- simulator_.GetClock()),
- server_endpoint_delegate_(&server_session_delegate_),
- server_endpoint_(
- QuicMakeUnique<QuartcServerEndpoint>(simulator_.GetAlarmFactory(),
- simulator_.GetClock(),
- &server_endpoint_delegate_,
- QuartcSessionConfig())),
- client_session_delegate_(&client_stream_delegate_,
- simulator_.GetClock()),
- client_endpoint_delegate_(&client_session_delegate_),
+ server_endpoint_delegate_(&server_stream_delegate_,
+ simulator_.GetClock()),
+ server_endpoint_(QuicMakeUnique<QuartcServerEndpoint>(
+ simulator_.GetAlarmFactory(),
+ simulator_.GetClock(),
+ simulator_.GetRandomGenerator(),
+ &server_endpoint_delegate_,
+ QuartcSessionConfig())),
+ client_endpoint_delegate_(&client_stream_delegate_,
+ simulator_.GetClock()),
client_endpoint_(QuicMakeUnique<QuartcClientEndpoint>(
simulator_.GetAlarmFactory(),
simulator_.GetClock(),
+ simulator_.GetRandomGenerator(),
&client_endpoint_delegate_,
QuartcSessionConfig(),
/*serialized_server_config=*/"")) {}
@@ -55,13 +55,11 @@ class QuartcEndpointTest : public QuicTest {
simulator::SymmetricLink client_server_link_;
FakeQuartcStreamDelegate server_stream_delegate_;
- FakeQuartcSessionDelegate server_session_delegate_;
FakeQuartcEndpointDelegate server_endpoint_delegate_;
std::unique_ptr<QuartcServerEndpoint> server_endpoint_;
FakeQuartcStreamDelegate client_stream_delegate_;
- FakeQuartcSessionDelegate client_session_delegate_;
FakeQuartcEndpointDelegate client_endpoint_delegate_;
std::unique_ptr<QuartcClientEndpoint> client_endpoint_;
@@ -86,7 +84,6 @@ TEST_F(QuartcEndpointTest,
// matter, but they must be enabled so that the version manager doesn't filter
// them out.
SetQuicReloadableFlag(quic_enable_version_46, true);
- SetQuicReloadableFlag(quic_enable_version_43, true);
// Reset the client endpoint to prefer version 46 but also be capable of
// speaking version 43.
@@ -95,7 +92,8 @@ TEST_F(QuartcEndpointTest,
client_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43});
client_endpoint_ = QuicMakeUnique<QuartcClientEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
- &client_endpoint_delegate_, QuartcSessionConfig(),
+ simulator_.GetRandomGenerator(), &client_endpoint_delegate_,
+ QuartcSessionConfig(),
/*serialized_server_config=*/"",
QuicMakeUnique<QuicVersionManager>(client_versions));
@@ -104,7 +102,8 @@ TEST_F(QuartcEndpointTest,
server_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43});
server_endpoint_ = QuicMakeUnique<QuartcServerEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
- &server_endpoint_delegate_, QuartcSessionConfig(),
+ simulator_.GetRandomGenerator(), &server_endpoint_delegate_,
+ QuartcSessionConfig(),
QuicMakeUnique<QuicVersionManager>(server_versions));
// The endpoints should be able to establish a connection using version 46.
@@ -131,14 +130,14 @@ TEST_F(QuartcEndpointTest,
// matter, but they must be enabled so that the version manager doesn't filter
// them out.
SetQuicReloadableFlag(quic_enable_version_46, true);
- SetQuicReloadableFlag(quic_enable_version_43, true);
// Reset the client endpoint to only speak version 43.
ParsedQuicVersionVector client_versions;
client_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43});
client_endpoint_ = QuicMakeUnique<QuartcClientEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
- &client_endpoint_delegate_, QuartcSessionConfig(),
+ simulator_.GetRandomGenerator(), &client_endpoint_delegate_,
+ QuartcSessionConfig(),
/*serialized_server_config=*/"",
QuicMakeUnique<QuicVersionManager>(client_versions));
@@ -149,7 +148,8 @@ TEST_F(QuartcEndpointTest,
server_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43});
server_endpoint_ = QuicMakeUnique<QuartcServerEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
- &server_endpoint_delegate_, QuartcSessionConfig(),
+ simulator_.GetRandomGenerator(), &server_endpoint_delegate_,
+ QuartcSessionConfig(),
QuicMakeUnique<QuicVersionManager>(server_versions));
// The endpoints should be able to establish a connection using version 46.
@@ -176,14 +176,14 @@ TEST_F(QuartcEndpointTest,
// matter, but they must be enabled so that the version manager doesn't filter
// them out.
SetQuicReloadableFlag(quic_enable_version_46, true);
- SetQuicReloadableFlag(quic_enable_version_43, true);
// Reset the client endpoint to only speak version 43.
ParsedQuicVersionVector client_versions;
client_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43});
client_endpoint_ = QuicMakeUnique<QuartcClientEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
- &client_endpoint_delegate_, QuartcSessionConfig(),
+ simulator_.GetRandomGenerator(), &client_endpoint_delegate_,
+ QuartcSessionConfig(),
/*serialized_server_config=*/"",
QuicMakeUnique<QuicVersionManager>(client_versions));
@@ -192,7 +192,8 @@ TEST_F(QuartcEndpointTest,
server_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46});
server_endpoint_ = QuicMakeUnique<QuartcServerEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
- &server_endpoint_delegate_, QuartcSessionConfig(),
+ simulator_.GetRandomGenerator(), &server_endpoint_delegate_,
+ QuartcSessionConfig(),
QuicMakeUnique<QuicVersionManager>(server_versions));
// The endpoints should be unable to establish a connection.
@@ -210,5 +211,57 @@ TEST_F(QuartcEndpointTest,
EXPECT_EQ(client_endpoint_delegate_.session()->error(), QUIC_INVALID_VERSION);
}
+// Tests that the client endpoint can create a new session in order to continue
+// version negotiation.
+TEST_F(QuartcEndpointTest,
+ QUIC_TEST_DISABLED_IN_CHROME(CreatesNewSessionWhenRequired)) {
+ // Setting this flag to true requires the client to create a new session when
+ // version negotiation fails.
+ SetQuicReloadableFlag(quic_no_client_conn_ver_negotiation, true);
+
+ // Note: for this test, we need support for two versions. Which two shouldn't
+ // matter, but they must be enabled so that the version manager doesn't filter
+ // them out.
+ SetQuicReloadableFlag(quic_enable_version_46, true);
+
+ // Reset the client endpoint to prefer version 46 but also be capable of
+ // speaking version 43.
+ ParsedQuicVersionVector client_versions;
+ client_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46});
+ client_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43});
+ client_endpoint_ = QuicMakeUnique<QuartcClientEndpoint>(
+ simulator_.GetAlarmFactory(), simulator_.GetClock(),
+ simulator_.GetRandomGenerator(), &client_endpoint_delegate_,
+ QuartcSessionConfig(),
+ /*serialized_server_config=*/"",
+ QuicMakeUnique<QuicVersionManager>(client_versions));
+
+ // Reset the server endpoint to only speak version 43.
+ ParsedQuicVersionVector server_versions;
+ server_versions.push_back({PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43});
+ server_endpoint_ = QuicMakeUnique<QuartcServerEndpoint>(
+ simulator_.GetAlarmFactory(), simulator_.GetClock(),
+ simulator_.GetRandomGenerator(), &server_endpoint_delegate_,
+ QuartcSessionConfig(),
+ QuicMakeUnique<QuicVersionManager>(server_versions));
+
+ // The endpoints should be able to establish a connection using version 46.
+ server_endpoint_->Connect(&server_transport_);
+ client_endpoint_->Connect(&client_transport_);
+
+ ASSERT_TRUE(simulator_.RunUntil([this] {
+ return client_endpoint_delegate_.session() != nullptr &&
+ client_endpoint_delegate_.session()->IsEncryptionEstablished() &&
+ server_endpoint_delegate_.session() != nullptr &&
+ server_endpoint_delegate_.session()->IsEncryptionEstablished();
+ }));
+ EXPECT_EQ(client_endpoint_delegate_.session()->connection()->version(),
+ server_versions[0]);
+ EXPECT_EQ(server_endpoint_delegate_.session()->connection()->version(),
+ server_versions[0]);
+
+ EXPECT_EQ(2, client_endpoint_delegate_.num_sessions_created());
+}
+
} // namespace
} // namespace quic
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 436212fd7a1..06871a2fe97 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
@@ -68,19 +68,9 @@ void ConfigureGlobalQuicSettings() {
// Ensure that we don't drop data because QUIC streams refuse to buffer it.
// TODO(b/120099046): Replace this with correct handling of WriteMemSlices().
- SetQuicFlag(&FLAGS_quic_buffered_data_threshold,
+ SetQuicFlag(FLAGS_quic_buffered_data_threshold,
std::numeric_limits<int>::max());
- // TODO(b/117157454): Perform version negotiation for Quartc outside of
- // QuicSession/QuicConnection. Currently default of
- // quic_restart_flag_quic_no_server_conn_ver_negotiation2 is false,
- // but we fail blueprint test that sets all QUIC flags to true.
- //
- // Forcing flag to false to pass blueprint tests, but eventually we'll have
- // to implement negotiation outside of QuicConnection.
- SetQuicRestartFlag(quic_no_server_conn_ver_negotiation2, false);
- SetQuicReloadableFlag(quic_no_client_conn_ver_negotiation, false);
-
// Enable and request QUIC to include receive timestamps in ACK frames.
SetQuicReloadableFlag(quic_send_timestamps, true);
@@ -133,7 +123,6 @@ QuicConfig CreateQuicConfig(const QuartcSessionConfig& quartc_session_config) {
copt.push_back(kBBR9); // Ignore app-limited if enough data is in flight.
copt.push_back(kBBQ1); // 2.773 pacing gain in STARTUP.
copt.push_back(kBBQ2); // 2.0 CWND gain in STARTUP.
- copt.push_back(kBBQ4); // 0.75 pacing gain in DRAIN.
copt.push_back(k1RTT); // Exit STARTUP after 1 RTT with no gains.
copt.push_back(kIW10); // 10-packet (14600 byte) initial cwnd.
@@ -191,7 +180,7 @@ QuicConfig CreateQuicConfig(const QuartcSessionConfig& quartc_session_config) {
// incomplete streams, but targets 1 second for recovery. Increasing the
// number of open streams gives sufficient headroom to recover before QUIC
// refuses new streams.
- quic_config.SetMaxIncomingDynamicStreamsToSend(1000);
+ quic_config.SetMaxIncomingBidirectionalStreamsToSend(1000);
return quic_config;
}
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_fakes.h b/chromium/net/third_party/quiche/src/quic/quartc/quartc_fakes.h
index 17e3874051c..13b65b1b532 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_fakes.h
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_fakes.h
@@ -18,38 +18,19 @@ namespace quic {
class FakeQuartcEndpointDelegate : public QuartcEndpoint::Delegate {
public:
- explicit FakeQuartcEndpointDelegate(QuartcSession::Delegate* session_delegate)
- : session_delegate_(session_delegate) {}
+ explicit FakeQuartcEndpointDelegate(QuartcStream::Delegate* stream_delegate,
+ const QuicClock* clock)
+ : stream_delegate_(stream_delegate), clock_(clock) {}
void OnSessionCreated(QuartcSession* session) override {
- CHECK_EQ(session_, nullptr);
CHECK_NE(session, nullptr);
session_ = session;
- session_->SetDelegate(session_delegate_);
session_->StartCryptoHandshake();
+ ++num_sessions_created_;
}
- void OnConnectError(QuicErrorCode error,
- const std::string& error_details) override {
- LOG(FATAL) << "Unexpected error during QuartcEndpoint::Connect(); error="
- << error << ", error_details=" << error_details;
- }
-
- QuartcSession* session() { return session_; }
-
- private:
- QuartcSession::Delegate* session_delegate_;
- QuartcSession* session_ = nullptr;
-};
-
-class FakeQuartcSessionDelegate : public QuartcSession::Delegate {
- public:
- explicit FakeQuartcSessionDelegate(QuartcStream::Delegate* stream_delegate,
- const QuicClock* clock)
- : stream_delegate_(stream_delegate), clock_(clock) {}
-
void OnConnectionWritable() override {
- LOG(INFO) << "Connection writable!";
+ QUIC_LOG(INFO) << "Connection writable!";
if (!writable_time_.IsInitialized()) {
writable_time_ = clock_->Now();
}
@@ -57,7 +38,7 @@ class FakeQuartcSessionDelegate : public QuartcSession::Delegate {
// Called when peers have established forward-secure encryption
void OnCryptoHandshakeComplete() override {
- LOG(INFO) << "Crypto handshake complete!";
+ QUIC_LOG(INFO) << "Crypto handshake complete!";
crypto_handshake_time_ = clock_->Now();
}
@@ -78,24 +59,44 @@ class FakeQuartcSessionDelegate : public QuartcSession::Delegate {
incoming_messages_.emplace_back(message);
}
+ void OnMessageSent(int64_t datagram_id) override {
+ sent_datagram_ids_.push_back(datagram_id);
+ }
+
void OnCongestionControlChange(QuicBandwidth bandwidth_estimate,
QuicBandwidth pacing_rate,
QuicTime::Delta latest_rtt) override {}
- QuartcStream* last_incoming_stream() { return last_incoming_stream_; }
+ QuartcSession* session() { return session_; }
+
+ int num_sessions_created() const { return num_sessions_created_; }
+
+ QuartcStream* last_incoming_stream() const { return last_incoming_stream_; }
// Returns all received messages.
- const std::vector<std::string>& incoming_messages() {
+ const std::vector<std::string>& incoming_messages() const {
return incoming_messages_;
}
- bool connected() { return connected_; }
+ // Returns all sent datagram ids in the order sent.
+ const std::vector<int64_t>& sent_datagram_ids() const {
+ return sent_datagram_ids_;
+ }
+
+ bool connected() const { return connected_; }
QuicTime writable_time() const { return writable_time_; }
QuicTime crypto_handshake_time() const { return crypto_handshake_time_; }
private:
+ // Current session.
+ QuartcSession* session_ = nullptr;
+
+ // Number of new sessions created by the endpoint.
+ int num_sessions_created_ = 0;
+
QuartcStream* last_incoming_stream_;
std::vector<std::string> incoming_messages_;
+ std::vector<int64_t> sent_datagram_ids_;
bool connected_ = true;
QuartcStream::Delegate* stream_delegate_;
QuicTime writable_time_ = QuicTime::Zero();
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_interval_counter_test.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_interval_counter_test.cc
index 9bc9af5e55b..028aaf2dab6 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_interval_counter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_interval_counter_test.cc
@@ -4,8 +4,6 @@
#include "net/third_party/quiche/src/quic/quartc/quartc_interval_counter.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/quic/core/quic_interval.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
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 80031dd0f2c..96156896af6 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
@@ -41,14 +41,16 @@ QuartcStream* QuartcSession::CreateOutgoingBidirectionalStream() {
GetNextOutgoingBidirectionalStreamId(), QuicStream::kDefaultPriority));
}
-bool QuartcSession::SendOrQueueMessage(std::string message) {
+bool QuartcSession::SendOrQueueMessage(QuicMemSliceSpan message,
+ int64_t datagram_id) {
if (!CanSendMessage()) {
QUIC_LOG(ERROR) << "Quic session does not support SendMessage";
return false;
}
- if (message.size() > GetCurrentLargestMessagePayload()) {
- QUIC_LOG(ERROR) << "Message is too big, message_size=" << message.size()
+ if (message.total_length() > GetCurrentLargestMessagePayload()) {
+ QUIC_LOG(ERROR) << "Message is too big, message_size="
+ << message.total_length()
<< ", GetCurrentLargestMessagePayload="
<< GetCurrentLargestMessagePayload();
return false;
@@ -56,7 +58,9 @@ bool QuartcSession::SendOrQueueMessage(std::string message) {
// There may be other messages in send queue, so we have to add message
// to the queue and call queue processing helper.
- send_message_queue_.emplace_back(std::move(message));
+ message.ConsumeAll([this, datagram_id](QuicMemSlice slice) {
+ send_message_queue_.emplace_back(std::move(slice), datagram_id);
+ });
ProcessSendMessageQueue();
@@ -64,21 +68,22 @@ bool QuartcSession::SendOrQueueMessage(std::string message) {
}
void QuartcSession::ProcessSendMessageQueue() {
+ QuicConnection::ScopedPacketFlusher flusher(
+ connection(), QuicConnection::AckBundling::NO_ACK);
while (!send_message_queue_.empty()) {
- struct iovec iov = {const_cast<char*>(send_message_queue_.front().data()),
- send_message_queue_.front().length()};
- QuicMemSliceStorage storage(
- &iov, 1, connection()->helper()->GetStreamSendBufferAllocator(),
- send_message_queue_.front().length());
- MessageResult result = SendMessage(storage.ToSpan());
-
- const size_t message_size = send_message_queue_.front().size();
+ QueuedMessage& it = send_message_queue_.front();
+ const size_t message_size = it.message.length();
+ MessageResult result = SendMessage(QuicMemSliceSpan(&it.message));
// Handle errors.
switch (result.status) {
case MESSAGE_STATUS_SUCCESS:
QUIC_VLOG(1) << "Quartc message sent, message_id=" << result.message_id
<< ", message_size=" << message_size;
+
+ // Notify that datagram was sent.
+ session_delegate_->OnMessageSent(it.datagram_id);
+
break;
// If connection is congestion controlled or not writable yet, stop
@@ -120,6 +125,20 @@ void QuartcSession::OnCanWrite() {
QuicSession::OnCanWrite();
}
+bool QuartcSession::SendProbingData() {
+ if (QuicSession::SendProbingData()) {
+ return true;
+ }
+
+ // Set transmission type to PROBING_RETRANSMISSION such that the packets will
+ // be padded to full.
+ SetTransmissionType(PROBING_RETRANSMISSION);
+ // TODO(mellem): this sent PING will be retransmitted if it is lost which is
+ // not ideal. Consider to send stream data as probing data instead.
+ SendPing();
+ return true;
+}
+
void QuartcSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
QuicSession::OnCryptoHandshakeEvent(event);
switch (event) {
@@ -192,12 +211,12 @@ void QuartcSession::OnConnectionClosed(QuicErrorCode error,
void QuartcSession::CloseConnection(const std::string& details) {
connection_->CloseConnection(
QuicErrorCode::QUIC_CONNECTION_CANCELLED, details,
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET_WITH_NO_ACK);
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
void QuartcSession::SetDelegate(Delegate* session_delegate) {
if (session_delegate_) {
- LOG(WARNING) << "The delegate for the session has already been set.";
+ QUIC_LOG(WARNING) << "The delegate for the session has already been set.";
}
session_delegate_ = session_delegate;
DCHECK(session_delegate_);
@@ -337,7 +356,7 @@ void QuartcClientSession::StartCryptoHandshake() {
std::vector<std::string>{kDummyCertName}, /*cert_sct=*/"",
/*chlo_hash=*/"", /*signature=*/"anything");
} else {
- LOG(DFATAL) << "Unable to set server config, error=" << error;
+ QUIC_LOG(DFATAL) << "Unable to set server config, error=" << error;
}
}
@@ -389,8 +408,7 @@ QuicCryptoStream* QuartcServerSession::GetMutableCryptoStream() {
void QuartcServerSession::StartCryptoHandshake() {
crypto_stream_ = QuicMakeUnique<QuicCryptoServerStream>(
- server_crypto_config_, compressed_certs_cache_,
- /*use_stateless_rejects_if_peer_supported=*/false, this, stream_helper_);
+ server_crypto_config_, compressed_certs_cache_, this, stream_helper_);
Initialize();
}
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_session.h b/chromium/net/third_party/quiche/src/quic/quartc/quartc_session.h
index 29e63066efe..840f69d084b 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
@@ -48,7 +48,18 @@ class QuartcSession : public QuicSession,
// support SendMessage API. Other unexpected errors during send will not be
// returned, because messages can be sent later if connection is congestion
// controlled.
- bool SendOrQueueMessage(std::string message);
+ //
+ // |datagram_id| is used to notify when message was sent in
+ // Delegate::OnMessageSent.
+ //
+ // TODO(sukhanov): We can not use QUIC message ID for notifications, because
+ // QUIC does not take ownership of messages and if connection is congestion
+ // controlled, message is not sent and does not get message id until it is
+ // sent successfully. It also creates problem of flow control between
+ // messages and streams if they are used together. We discussed it with QUIC
+ // team and there are multiple solutions, but for now we have to use our
+ // own datagram identification.
+ bool SendOrQueueMessage(QuicMemSliceSpan message, int64_t datagram_id);
// Returns largest message payload acceptable in SendQuartcMessage.
QuicPacketLength GetCurrentLargestMessagePayload() const {
@@ -67,6 +78,7 @@ class QuartcSession : public QuicSession,
bool ShouldKeepConnectionAlive() const override;
void OnCanWrite() override;
+ bool SendProbingData() override;
void OnConnectionClosed(QuicErrorCode error,
const std::string& error_details,
@@ -128,6 +140,22 @@ class QuartcSession : public QuicSession,
// Called when message (sent as SendMessage) is received.
virtual void OnMessageReceived(QuicStringPiece message) = 0;
+ // Called when message is sent to QUIC.
+ //
+ // Takes into account delay due to congestion control, but does not take
+ // into account any additional socket delays.
+ //
+ // Passed |datagram_id| is the same used in SendOrQueueMessage.
+ //
+ // TODO(sukhanov): We can take into account socket delay, but it's not clear
+ // if it's worth doing if we eventually plan to move congestion control to
+ // QUIC in QRTP model. If we need to do it, mellem@ thinks it's fairly
+ // strtaightforward: QUIC does not know about socket delay, but ICE does. We
+ // can tell ICE the QUIC packet number for each packet sent, and it will
+ // echo it back to us when the packet actually goes out. We just need to
+ // plumb that signal up to RTP's congestion control.
+ virtual void OnMessageSent(int64_t datagram_id) = 0;
+
// TODO(zhihuang): Add proof verification.
};
@@ -170,6 +198,14 @@ class QuartcSession : public QuicSession,
std::unique_ptr<QuartcStream> stream,
spdy::SpdyPriority priority);
+ // Holds message until it's sent.
+ struct QueuedMessage {
+ QueuedMessage(QuicMemSlice the_message, int64_t the_datagram_id)
+ : message(std::move(the_message)), datagram_id(the_datagram_id) {}
+ QuicMemSlice message;
+ int64_t datagram_id;
+ };
+
void ProcessSendMessageQueue();
// Take ownership of the QuicConnection. Note: if |connection_| changes,
@@ -189,7 +225,7 @@ class QuartcSession : public QuicSession,
// Queue of pending messages sent by SendQuartcMessage that were not sent
// yet or blocked by congestion control. Messages are queued in the order
// of sent by SendOrQueueMessage().
- QuicDeque<std::string> send_message_queue_;
+ QuicDeque<QueuedMessage> send_message_queue_;
};
class QuartcClientSession : public QuartcSession,
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 31abd57231e..87174dcc4a6 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
@@ -4,8 +4,6 @@
#include "net/third_party/quiche/src/quic/quartc/quartc_session.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
@@ -36,6 +34,11 @@ constexpr QuicTime::Delta kPropagationDelayAndABit =
static QuicByteCount kDefaultMaxPacketSize = 1200;
+test::QuicTestMemSliceVector CreateMemSliceVector(QuicStringPiece data) {
+ return test::QuicTestMemSliceVector(
+ {std::pair<char*, size_t>(const_cast<char*>(data.data()), data.size())});
+}
+
class QuartcSessionTest : public QuicTest {
public:
~QuartcSessionTest() override {}
@@ -58,28 +61,26 @@ class QuartcSessionTest : public QuicTest {
QuicBandwidth::FromKBitsPerSecond(10 * 1000), kPropagationDelay);
client_stream_delegate_ = QuicMakeUnique<FakeQuartcStreamDelegate>();
- client_session_delegate_ = QuicMakeUnique<FakeQuartcSessionDelegate>(
+ client_session_delegate_ = QuicMakeUnique<FakeQuartcEndpointDelegate>(
client_stream_delegate_.get(), simulator_.GetClock());
- client_endpoint_delegate_ = QuicMakeUnique<FakeQuartcEndpointDelegate>(
- client_session_delegate_.get());
server_stream_delegate_ = QuicMakeUnique<FakeQuartcStreamDelegate>();
- server_session_delegate_ = QuicMakeUnique<FakeQuartcSessionDelegate>(
+ server_session_delegate_ = QuicMakeUnique<FakeQuartcEndpointDelegate>(
server_stream_delegate_.get(), simulator_.GetClock());
- server_endpoint_delegate_ = QuicMakeUnique<FakeQuartcEndpointDelegate>(
- server_session_delegate_.get());
// No 0-rtt setup, because server config is empty.
// CannotCreateDataStreamBeforeHandshake depends on 1-rtt setup.
if (create_client_endpoint) {
client_endpoint_ = QuicMakeUnique<QuartcClientEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
- client_endpoint_delegate_.get(), quic::QuartcSessionConfig(),
+ simulator_.GetRandomGenerator(), client_session_delegate_.get(),
+ quic::QuartcSessionConfig(),
/*serialized_server_config=*/"");
}
server_endpoint_ = QuicMakeUnique<QuartcServerEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
- server_endpoint_delegate_.get(), quic::QuartcSessionConfig());
+ simulator_.GetRandomGenerator(), server_session_delegate_.get(),
+ quic::QuartcSessionConfig());
}
// Note that input session config will apply to both server and client.
@@ -94,12 +95,12 @@ class QuartcSessionTest : public QuicTest {
client_endpoint_->Connect(client_transport_.get());
CHECK(simulator_.RunUntil([this] {
- return client_endpoint_delegate_->session() != nullptr &&
- server_endpoint_delegate_->session() != nullptr;
+ return client_session_delegate_->session() != nullptr &&
+ server_session_delegate_->session() != nullptr;
}));
- client_peer_ = client_endpoint_delegate_->session();
- server_peer_ = server_endpoint_delegate_->session();
+ client_peer_ = client_session_delegate_->session();
+ server_peer_ = server_session_delegate_->session();
}
// Runs all tasks scheduled in the next 200 ms.
@@ -130,9 +131,7 @@ class QuartcSessionTest : public QuicTest {
outgoing_stream->SetDelegate(server_stream_delegate_.get());
// Send a test message from peer 1 to peer 2.
- char kTestMessage[] = "Hello";
- test::QuicTestMemSliceVector data(
- {std::make_pair(kTestMessage, strlen(kTestMessage))});
+ test::QuicTestMemSliceVector data = CreateMemSliceVector("Hello");
outgoing_stream->WriteMemSlices(data.span(), /*fin=*/false);
RunTasks();
@@ -144,17 +143,15 @@ class QuartcSessionTest : public QuicTest {
EXPECT_EQ(incoming->id(), stream_id);
EXPECT_TRUE(client_peer_->ShouldKeepConnectionAlive());
- EXPECT_EQ(client_stream_delegate_->data()[stream_id], kTestMessage);
+ EXPECT_EQ(client_stream_delegate_->data()[stream_id], "Hello");
// Send a test message from peer 2 to peer 1.
- char kTestResponse[] = "Response";
- test::QuicTestMemSliceVector response(
- {std::make_pair(kTestResponse, strlen(kTestResponse))});
+ test::QuicTestMemSliceVector response = CreateMemSliceVector("Response");
incoming->WriteMemSlices(response.span(), /*fin=*/false);
RunTasks();
// Wait for peer 1 to receive messages.
ASSERT_TRUE(server_stream_delegate_->has_data());
- EXPECT_EQ(server_stream_delegate_->data()[stream_id], kTestResponse);
+ EXPECT_EQ(server_stream_delegate_->data()[stream_id], "Response");
}
// Test sending/receiving of messages for two directions.
@@ -162,8 +159,14 @@ class QuartcSessionTest : public QuicTest {
ASSERT_TRUE(server_peer_->CanSendMessage());
ASSERT_TRUE(client_peer_->CanSendMessage());
+ int64_t server_datagram_id = 111;
+ int64_t client_datagram_id = 222;
+
// Send message from peer 1 to peer 2.
- ASSERT_TRUE(server_peer_->SendOrQueueMessage("Message from server"));
+ test::QuicTestMemSliceVector message =
+ CreateMemSliceVector("Message from server");
+ ASSERT_TRUE(
+ server_peer_->SendOrQueueMessage(message.span(), server_datagram_id));
// First message in each direction should not be queued.
EXPECT_EQ(server_peer_->send_message_queue_size(), 0u);
@@ -174,8 +177,13 @@ class QuartcSessionTest : public QuicTest {
EXPECT_THAT(client_session_delegate_->incoming_messages(),
testing::ElementsAre("Message from server"));
+ EXPECT_THAT(server_session_delegate_->sent_datagram_ids(),
+ testing::ElementsAre(server_datagram_id));
+
// Send message from peer 2 to peer 1.
- ASSERT_TRUE(client_peer_->SendOrQueueMessage("Message from client"));
+ message = CreateMemSliceVector("Message from client");
+ ASSERT_TRUE(
+ client_peer_->SendOrQueueMessage(message.span(), client_datagram_id));
// First message in each direction should not be queued.
EXPECT_EQ(client_peer_->send_message_queue_size(), 0u);
@@ -185,6 +193,9 @@ class QuartcSessionTest : public QuicTest {
EXPECT_THAT(server_session_delegate_->incoming_messages(),
testing::ElementsAre("Message from client"));
+
+ EXPECT_THAT(client_session_delegate_->sent_datagram_ids(),
+ testing::ElementsAre(client_datagram_id));
}
// Test for sending multiple messages that also result in queueing.
@@ -199,26 +210,38 @@ class QuartcSessionTest : public QuicTest {
QuartcSession* const peer_sending =
direction_from_server ? server_peer_ : client_peer_;
- FakeQuartcSessionDelegate* const delegate_receiving =
+ FakeQuartcEndpointDelegate* const delegate_receiving =
direction_from_server ? client_session_delegate_.get()
: server_session_delegate_.get();
+ FakeQuartcEndpointDelegate* const delegate_sending =
+ direction_from_server ? server_session_delegate_.get()
+ : client_session_delegate_.get();
+
// There should be no messages in the queue before we start sending.
EXPECT_EQ(peer_sending->send_message_queue_size(), 0u);
// Send messages from peer 1 to peer 2 until required number of messages
// are queued in unsent message queue.
std::vector<std::string> sent_messages;
+ std::vector<int64_t> sent_datagram_ids;
+ int64_t current_datagram_id = 0;
while (peer_sending->send_message_queue_size() < queue_size) {
sent_messages.push_back(
QuicStrCat("Sending message, index=", sent_messages.size()));
- ASSERT_TRUE(peer_sending->SendOrQueueMessage(sent_messages.back()));
+ ASSERT_TRUE(peer_sending->SendOrQueueMessage(
+ CreateMemSliceVector(sent_messages.back()).span(),
+ current_datagram_id));
+
+ sent_datagram_ids.push_back(current_datagram_id);
+ ++current_datagram_id;
}
// Wait for peer 2 to receive all messages.
RunTasks();
EXPECT_EQ(delegate_receiving->incoming_messages(), sent_messages);
+ EXPECT_EQ(delegate_sending->sent_datagram_ids(), sent_datagram_ids);
}
// Test sending long messages:
@@ -231,12 +254,17 @@ class QuartcSessionTest : public QuicTest {
// Send message of maximum allowed length.
std::string message_max_long =
std::string(server_peer_->GetCurrentLargestMessagePayload(), 'A');
- ASSERT_TRUE(server_peer_->SendOrQueueMessage(message_max_long));
+ test::QuicTestMemSliceVector message =
+ CreateMemSliceVector(message_max_long);
+ ASSERT_TRUE(
+ server_peer_->SendOrQueueMessage(message.span(), /*datagram_id=*/0));
// Send long message which should fail.
std::string message_too_long =
std::string(server_peer_->GetCurrentLargestMessagePayload() + 1, 'B');
- ASSERT_FALSE(server_peer_->SendOrQueueMessage(message_too_long));
+ message = CreateMemSliceVector(message_too_long);
+ ASSERT_FALSE(
+ server_peer_->SendOrQueueMessage(message.span(), /*datagram_id=*/0));
// Wait for peer 2 to receive message.
RunTasks();
@@ -267,11 +295,9 @@ class QuartcSessionTest : public QuicTest {
std::unique_ptr<simulator::SymmetricLink> client_server_link_;
std::unique_ptr<FakeQuartcStreamDelegate> client_stream_delegate_;
- std::unique_ptr<FakeQuartcSessionDelegate> client_session_delegate_;
- std::unique_ptr<FakeQuartcEndpointDelegate> client_endpoint_delegate_;
+ std::unique_ptr<FakeQuartcEndpointDelegate> client_session_delegate_;
std::unique_ptr<FakeQuartcStreamDelegate> server_stream_delegate_;
- std::unique_ptr<FakeQuartcSessionDelegate> server_session_delegate_;
- std::unique_ptr<FakeQuartcEndpointDelegate> server_endpoint_delegate_;
+ std::unique_ptr<FakeQuartcEndpointDelegate> server_session_delegate_;
std::unique_ptr<QuartcClientEndpoint> client_endpoint_;
std::unique_ptr<QuartcServerEndpoint> server_endpoint_;
@@ -375,9 +401,7 @@ TEST_F(QuartcSessionTest, WriterGivesPacketNumberToTransport) {
QuartcStream* stream = client_peer_->CreateOutgoingBidirectionalStream();
stream->SetDelegate(client_stream_delegate_.get());
- char kClientMessage[] = "Hello";
- test::QuicTestMemSliceVector stream_data(
- {std::make_pair(kClientMessage, strlen(kClientMessage))});
+ test::QuicTestMemSliceVector stream_data = CreateMemSliceVector("Hello");
stream->WriteMemSlices(stream_data.span(), /*fin=*/false);
RunTasks();
@@ -412,15 +436,13 @@ TEST_F(QuartcSessionTest, StreamRetransmissionEnabled) {
client_filter_->set_packets_to_drop(1);
- char kClientMessage[] = "Hello";
- test::QuicTestMemSliceVector stream_data(
- {std::make_pair(kClientMessage, strlen(kClientMessage))});
+ test::QuicTestMemSliceVector stream_data = CreateMemSliceVector("Hello");
stream->WriteMemSlices(stream_data.span(), /*fin=*/false);
RunTasks();
// Stream data should make it despite packet loss.
ASSERT_TRUE(server_stream_delegate_->has_data());
- EXPECT_EQ(server_stream_delegate_->data()[stream_id], kClientMessage);
+ EXPECT_EQ(server_stream_delegate_->data()[stream_id], "Hello");
}
TEST_F(QuartcSessionTest, StreamRetransmissionDisabled) {
@@ -450,9 +472,7 @@ TEST_F(QuartcSessionTest, StreamRetransmissionDisabled) {
client_filter_->set_packets_to_drop(1);
- char kMessage[] = "Hello";
- test::QuicTestMemSliceVector stream_data(
- {std::make_pair(kMessage, strlen(kMessage))});
+ test::QuicTestMemSliceVector stream_data = CreateMemSliceVector("Hello");
stream->WriteMemSlices(stream_data.span(), /*fin=*/false);
simulator_.RunFor(QuicTime::Delta::FromMilliseconds(1));
@@ -460,9 +480,8 @@ TEST_F(QuartcSessionTest, StreamRetransmissionDisabled) {
QuartcStream* stream_1 = client_peer_->CreateOutgoingBidirectionalStream();
stream_1->SetDelegate(client_stream_delegate_.get());
- char kMessage1[] = "Second message";
- test::QuicTestMemSliceVector stream_data_1(
- {std::make_pair(kMessage1, strlen(kMessage1))});
+ test::QuicTestMemSliceVector stream_data_1 =
+ CreateMemSliceVector("Second message");
stream_1->WriteMemSlices(stream_data_1.span(), /*fin=*/false);
RunTasks();
@@ -512,7 +531,8 @@ TEST_F(QuartcSessionTest, PreSharedKeyHandshakeIs0RTT) {
client_endpoint_ = QuicMakeUnique<QuartcClientEndpoint>(
simulator_.GetAlarmFactory(), simulator_.GetClock(),
- client_endpoint_delegate_.get(), QuartcSessionConfig(),
+ simulator_.GetRandomGenerator(), client_session_delegate_.get(),
+ QuartcSessionConfig(),
// This is the key line here. It passes through the server config
// from the server to the client.
server_endpoint_->server_crypto_config());
@@ -523,8 +543,8 @@ TEST_F(QuartcSessionTest, PreSharedKeyHandshakeIs0RTT) {
// client session should be created, but server won't be created yet.
simulator_.RunFor(QuicTime::Delta::FromMilliseconds(1));
- client_peer_ = client_endpoint_delegate_->session();
- server_peer_ = server_endpoint_delegate_->session();
+ client_peer_ = client_session_delegate_->session();
+ server_peer_ = server_session_delegate_->session();
ASSERT_NE(client_peer_, nullptr);
ASSERT_EQ(server_peer_, nullptr);
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream.cc b/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream.cc
index 49ade235765..5fc10749951 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/quartc_stream.cc
@@ -25,7 +25,7 @@ QuartcStream::QuartcStream(QuicStreamId id, QuicSession* session)
}
QuartcStream::QuartcStream(PendingStream pending)
- : QuicStream(std::move(pending), BIDIRECTIONAL) {
+ : QuicStream(std::move(pending), BIDIRECTIONAL, /*is_static=*/false) {
sequencer()->set_level_triggered(true);
}
@@ -161,8 +161,8 @@ void QuartcStream::FinishWriting() {
void QuartcStream::SetDelegate(Delegate* delegate) {
if (delegate_) {
- LOG(WARNING) << "The delegate for Stream " << id()
- << " has already been set.";
+ QUIC_LOG(WARNING) << "The delegate for Stream " << id()
+ << " has already been set.";
}
delegate_ = delegate;
DCHECK(delegate_);
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 3b5458c7870..d7599e8d9d1 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
@@ -9,8 +9,6 @@
#include <type_traits>
#include <utility>
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h"
#include "net/third_party/quiche/src/quic/core/quic_alarm_factory.h"
diff --git a/chromium/net/third_party/quiche/src/quic/quartc/simulated_packet_transport_test.cc b/chromium/net/third_party/quiche/src/quic/quartc/simulated_packet_transport_test.cc
index cae966f4a3e..24a4f4fc49f 100644
--- a/chromium/net/third_party/quiche/src/quic/quartc/simulated_packet_transport_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/quartc/simulated_packet_transport_test.cc
@@ -4,8 +4,6 @@
#include "net/third_party/quiche/src/quic/quartc/simulated_packet_transport.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_packet_writer.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
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 63154b9b54c..11cfefc8c5d 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
@@ -43,126 +43,6 @@
namespace quic {
namespace test {
-TestChannelIDKey::TestChannelIDKey(EVP_PKEY* ecdsa_key)
- : ecdsa_key_(ecdsa_key) {}
-TestChannelIDKey::~TestChannelIDKey() {}
-
-bool TestChannelIDKey::Sign(QuicStringPiece signed_data,
- std::string* out_signature) const {
- bssl::ScopedEVP_MD_CTX md_ctx;
- if (EVP_DigestSignInit(md_ctx.get(), nullptr, EVP_sha256(), nullptr,
- ecdsa_key_.get()) != 1) {
- return false;
- }
-
- EVP_DigestUpdate(md_ctx.get(), ChannelIDVerifier::kContextStr,
- strlen(ChannelIDVerifier::kContextStr) + 1);
- EVP_DigestUpdate(md_ctx.get(), ChannelIDVerifier::kClientToServerStr,
- strlen(ChannelIDVerifier::kClientToServerStr) + 1);
- EVP_DigestUpdate(md_ctx.get(), signed_data.data(), signed_data.size());
-
- size_t sig_len;
- if (!EVP_DigestSignFinal(md_ctx.get(), nullptr, &sig_len)) {
- return false;
- }
-
- std::unique_ptr<uint8_t[]> der_sig(new uint8_t[sig_len]);
- if (!EVP_DigestSignFinal(md_ctx.get(), der_sig.get(), &sig_len)) {
- return false;
- }
-
- uint8_t* derp = der_sig.get();
- bssl::UniquePtr<ECDSA_SIG> sig(
- d2i_ECDSA_SIG(nullptr, const_cast<const uint8_t**>(&derp), sig_len));
- if (sig.get() == nullptr) {
- return false;
- }
-
- // The signature consists of a pair of 32-byte numbers.
- static const size_t kSignatureLength = 32 * 2;
- std::unique_ptr<uint8_t[]> signature(new uint8_t[kSignatureLength]);
- if (!BN_bn2bin_padded(&signature[0], 32, sig->r) ||
- !BN_bn2bin_padded(&signature[32], 32, sig->s)) {
- return false;
- }
-
- *out_signature =
- std::string(reinterpret_cast<char*>(signature.get()), kSignatureLength);
-
- return true;
-}
-
-std::string TestChannelIDKey::SerializeKey() const {
- // i2d_PublicKey will produce an ANSI X9.62 public key which, for a P-256
- // key, is 0x04 (meaning uncompressed) followed by the x and y field
- // elements as 32-byte, big-endian numbers.
- static const int kExpectedKeyLength = 65;
-
- int len = i2d_PublicKey(ecdsa_key_.get(), nullptr);
- if (len != kExpectedKeyLength) {
- return "";
- }
-
- uint8_t buf[kExpectedKeyLength];
- uint8_t* derp = buf;
- i2d_PublicKey(ecdsa_key_.get(), &derp);
-
- return std::string(reinterpret_cast<char*>(buf + 1), kExpectedKeyLength - 1);
-}
-
-TestChannelIDSource::~TestChannelIDSource() {}
-
-QuicAsyncStatus TestChannelIDSource::GetChannelIDKey(
- const std::string& hostname,
- std::unique_ptr<ChannelIDKey>* channel_id_key,
- ChannelIDSourceCallback* /*callback*/) {
- *channel_id_key = QuicMakeUnique<TestChannelIDKey>(HostnameToKey(hostname));
- return QUIC_SUCCESS;
-}
-
-// static
-EVP_PKEY* TestChannelIDSource::HostnameToKey(const std::string& hostname) {
- // In order to generate a deterministic key for a given hostname the
- // hostname is hashed with SHA-256 and the resulting digest is treated as a
- // big-endian number. The most-significant bit is cleared to ensure that
- // the resulting value is less than the order of the group and then it's
- // taken as a private key. Given the private key, the public key is
- // calculated with a group multiplication.
- SHA256_CTX sha256;
- SHA256_Init(&sha256);
- SHA256_Update(&sha256, hostname.data(), hostname.size());
-
- unsigned char digest[SHA256_DIGEST_LENGTH];
- SHA256_Final(digest, &sha256);
-
- // Ensure that the digest is less than the order of the P-256 group by
- // clearing the most-significant bit.
- digest[0] &= 0x7f;
-
- bssl::UniquePtr<BIGNUM> k(BN_new());
- CHECK(BN_bin2bn(digest, sizeof(digest), k.get()) != nullptr);
-
- bssl::UniquePtr<EC_GROUP> p256(
- EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
- CHECK(p256);
-
- bssl::UniquePtr<EC_KEY> ecdsa_key(EC_KEY_new());
- CHECK(ecdsa_key && EC_KEY_set_group(ecdsa_key.get(), p256.get()));
-
- bssl::UniquePtr<EC_POINT> point(EC_POINT_new(p256.get()));
- CHECK(EC_POINT_mul(p256.get(), point.get(), k.get(), nullptr, nullptr,
- nullptr));
-
- EC_KEY_set_private_key(ecdsa_key.get(), k.get());
- EC_KEY_set_public_key(ecdsa_key.get(), point.get());
-
- bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
- // EVP_PKEY_set1_EC_KEY takes a reference so no |release| here.
- EVP_PKEY_set1_EC_KEY(pkey.get(), ecdsa_key.get());
-
- return pkey.release();
-}
-
namespace crypto_test_utils {
namespace {
@@ -207,63 +87,15 @@ bool HexChar(char c, uint8_t* value) {
return false;
}
-// A ChannelIDSource that works in asynchronous mode unless the |callback|
-// argument to GetChannelIDKey is nullptr.
-class AsyncTestChannelIDSource : public ChannelIDSource, public CallbackSource {
- public:
- // |sync_source| is a synchronous ChannelIDSource.
- explicit AsyncTestChannelIDSource(
- std::unique_ptr<ChannelIDSource> sync_source)
- : sync_source_(std::move(sync_source)) {}
- ~AsyncTestChannelIDSource() override {}
-
- // ChannelIDSource implementation.
- QuicAsyncStatus GetChannelIDKey(const std::string& hostname,
- std::unique_ptr<ChannelIDKey>* channel_id_key,
- ChannelIDSourceCallback* callback) override {
- // Synchronous mode.
- if (!callback) {
- return sync_source_->GetChannelIDKey(hostname, channel_id_key, nullptr);
- }
-
- // Asynchronous mode.
- QuicAsyncStatus status =
- sync_source_->GetChannelIDKey(hostname, &channel_id_key_, nullptr);
- if (status != QUIC_SUCCESS) {
- return QUIC_FAILURE;
- }
- callback_.reset(callback);
- return QUIC_PENDING;
- }
-
- // CallbackSource implementation.
- void RunPendingCallbacks() override {
- if (callback_) {
- callback_->Run(&channel_id_key_);
- callback_.reset();
- }
- }
-
- private:
- std::unique_ptr<ChannelIDSource> sync_source_;
- std::unique_ptr<ChannelIDSourceCallback> callback_;
- std::unique_ptr<ChannelIDKey> channel_id_key_;
-};
-
} // anonymous namespace
-FakeServerOptions::FakeServerOptions() {}
-
-FakeServerOptions::~FakeServerOptions() {}
-
-FakeClientOptions::FakeClientOptions()
- : channel_id_enabled(false), channel_id_source_async(false) {}
+FakeClientOptions::FakeClientOptions() {}
FakeClientOptions::~FakeClientOptions() {}
namespace {
// This class is used by GenerateFullCHLO() to extract SCID and STK from
-// REJ/SREJ and to construct a full CHLO with these fields and given inchoate
+// REJ and to construct a full CHLO with these fields and given inchoate
// CHLO.
class FullChloGenerator {
public:
@@ -340,11 +172,10 @@ class FullChloGenerator {
}
void ProcessClientHelloDone(std::unique_ptr<CryptoHandshakeMessage> rej) {
- // Verify output is a REJ or SREJ.
- EXPECT_THAT(rej->tag(),
- testing::AnyOf(testing::Eq(kSREJ), testing::Eq(kREJ)));
+ // Verify output is a REJ.
+ EXPECT_THAT(rej->tag(), testing::Eq(kREJ));
- VLOG(1) << "Extract valid STK and SCID from\n" << rej->DebugString();
+ QUIC_VLOG(1) << "Extract valid STK and SCID from\n" << rej->DebugString();
QuicStringPiece srct;
ASSERT_TRUE(rej->GetStringPiece(kSourceAddressTokenTag, &srct));
@@ -383,8 +214,7 @@ int HandshakeWithFakeServer(QuicConfig* server_quic_config,
MockQuicConnectionHelper* helper,
MockAlarmFactory* alarm_factory,
PacketSavingConnection* client_conn,
- QuicCryptoClientStream* client,
- const FakeServerOptions& options) {
+ QuicCryptoClientStream* client) {
PacketSavingConnection* server_conn = new PacketSavingConnection(
helper, alarm_factory, Perspective::IS_SERVER,
ParsedVersionOfIndex(client_conn->supported_versions(), 0));
@@ -395,9 +225,8 @@ int HandshakeWithFakeServer(QuicConfig* server_quic_config,
TlsServerHandshaker::CreateSslCtx());
QuicCompressedCertsCache compressed_certs_cache(
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize);
- SetupCryptoServerConfigForTest(server_conn->clock(),
- server_conn->random_generator(),
- &crypto_config, options);
+ SetupCryptoServerConfigForTest(
+ server_conn->clock(), server_conn->random_generator(), &crypto_config);
TestQuicSpdyServerSession server_session(
server_conn, *server_quic_config, client_conn->supported_versions(),
@@ -446,19 +275,6 @@ int HandshakeWithFakeClient(MockQuicConnectionHelper* helper,
QuicCryptoClientConfig crypto_config(ProofVerifierForTesting(),
TlsClientHandshaker::CreateSslCtx());
- AsyncTestChannelIDSource* async_channel_id_source = nullptr;
- if (options.channel_id_enabled) {
- std::unique_ptr<ChannelIDSource> source = ChannelIDSourceForTesting();
- if (options.channel_id_source_async) {
- auto temp = QuicMakeUnique<AsyncTestChannelIDSource>(std::move(source));
- async_channel_id_source = temp.get();
- source = std::move(temp);
- }
- crypto_config.SetChannelIDSource(std::move(source));
- }
- if (!options.token_binding_params.empty()) {
- crypto_config.tb_key_params = options.token_binding_params;
- }
TestQuicSpdyClientSession client_session(client_conn, DefaultQuicConfig(),
supported_versions, server_id,
&crypto_config);
@@ -471,25 +287,12 @@ int HandshakeWithFakeClient(MockQuicConnectionHelper* helper,
client_session.GetMutableCryptoStream()->CryptoConnect();
CHECK_EQ(1u, client_conn->encrypted_packets_.size());
- CommunicateHandshakeMessagesAndRunCallbacks(
- client_conn, client_session.GetMutableCryptoStream(), server_conn, server,
- async_channel_id_source);
+ CommunicateHandshakeMessages(client_conn,
+ client_session.GetMutableCryptoStream(),
+ server_conn, server);
if (server->handshake_confirmed() && server->encryption_established()) {
CompareClientAndServerKeys(client_session.GetMutableCryptoStream(), server);
-
- if (options.channel_id_enabled) {
- std::unique_ptr<ChannelIDKey> channel_id_key;
- QuicAsyncStatus status =
- crypto_config.channel_id_source()->GetChannelIDKey(
- server_id.host(), &channel_id_key, nullptr);
- EXPECT_EQ(QUIC_SUCCESS, status);
- EXPECT_EQ(channel_id_key->SerializeKey(),
- server->crypto_negotiated_params().channel_id);
- EXPECT_EQ(
- options.channel_id_source_async,
- client_session.GetCryptoStream()->WasChannelIDSourceCallbackRun());
- }
}
return client_session.GetCryptoStream()->num_sent_client_hellos();
@@ -497,11 +300,9 @@ int HandshakeWithFakeClient(MockQuicConnectionHelper* helper,
void SetupCryptoServerConfigForTest(const QuicClock* clock,
QuicRandom* rand,
- QuicCryptoServerConfig* crypto_config,
- const FakeServerOptions& fake_options) {
+ QuicCryptoServerConfig* crypto_config) {
QuicCryptoServerConfig::ConfigOptions options;
options.channel_id_enabled = true;
- options.token_binding_params = fake_options.token_binding_params;
std::unique_ptr<CryptoHandshakeMessage> scfg =
crypto_config->AddDefaultConfig(rand, clock, options);
}
@@ -530,16 +331,6 @@ void CommunicateHandshakeMessages(PacketSavingConnection* client_conn,
QuicCryptoStream* client,
PacketSavingConnection* server_conn,
QuicCryptoStream* server) {
- CommunicateHandshakeMessagesAndRunCallbacks(client_conn, client, server_conn,
- server, nullptr);
-}
-
-void CommunicateHandshakeMessagesAndRunCallbacks(
- PacketSavingConnection* client_conn,
- QuicCryptoStream* client,
- PacketSavingConnection* server_conn,
- QuicCryptoStream* server,
- CallbackSource* callback_source) {
size_t client_i = 0, server_i = 0;
while (!client->handshake_confirmed() || !server->handshake_confirmed()) {
ASSERT_GT(client_conn->encrypted_packets_.size(), client_i);
@@ -548,9 +339,6 @@ void CommunicateHandshakeMessagesAndRunCallbacks(
<< " packets client->server";
MovePackets(client_conn, &client_i, server, server_conn,
Perspective::IS_SERVER);
- if (callback_source) {
- callback_source->RunPendingCallbacks();
- }
if (client->handshake_confirmed() && server->handshake_confirmed()) {
break;
@@ -561,9 +349,6 @@ void CommunicateHandshakeMessagesAndRunCallbacks(
<< " packets server->client";
MovePackets(server_conn, &server_i, client, client_conn,
Perspective::IS_CLIENT);
- if (callback_source) {
- callback_source->RunPendingCallbacks();
- }
}
}
@@ -695,12 +480,8 @@ CommonCertSets* MockCommonCertSets(QuicStringPiece cert,
return new class MockCommonCertSets(cert, hash, index);
}
-void FillInDummyReject(CryptoHandshakeMessage* rej, bool reject_is_stateless) {
- if (reject_is_stateless) {
- rej->set_tag(kSREJ);
- } else {
- rej->set_tag(kREJ);
- }
+void FillInDummyReject(CryptoHandshakeMessage* rej) {
+ rej->set_tag(kREJ);
// Minimum SCFG that passes config validation checks.
// clang-format off
@@ -898,10 +679,6 @@ CryptoHandshakeMessage CreateCHLO(
return *parsed;
}
-std::unique_ptr<ChannelIDSource> ChannelIDSourceForTesting() {
- return QuicMakeUnique<TestChannelIDSource>();
-}
-
void MovePackets(PacketSavingConnection* source_conn,
size_t* inout_packet_index,
QuicCryptoStream* dest_stream,
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 5bb4b4e42a3..421c0f3dd2d 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
@@ -20,7 +20,6 @@
namespace quic {
-class ChannelIDSource;
class CommonCertSets;
class ProofSource;
class ProofVerifier;
@@ -38,37 +37,6 @@ namespace test {
class PacketSavingConnection;
-class TestChannelIDKey : public ChannelIDKey {
- public:
- explicit TestChannelIDKey(EVP_PKEY* ecdsa_key);
- ~TestChannelIDKey() override;
-
- // ChannelIDKey implementation.
-
- bool Sign(QuicStringPiece signed_data,
- std::string* out_signature) const override;
-
- std::string SerializeKey() const override;
-
- private:
- bssl::UniquePtr<EVP_PKEY> ecdsa_key_;
-};
-
-class TestChannelIDSource : public ChannelIDSource {
- public:
- ~TestChannelIDSource() override;
-
- // ChannelIDSource implementation.
-
- QuicAsyncStatus GetChannelIDKey(
- const std::string& hostname,
- std::unique_ptr<ChannelIDKey>* channel_id_key,
- ChannelIDSourceCallback* /*callback*/) override;
-
- private:
- static EVP_PKEY* HostnameToKey(const std::string& hostname);
-};
-
namespace crypto_test_utils {
// An interface for a source of callbacks. This is used for invoking
@@ -85,33 +53,12 @@ class CallbackSource {
virtual void RunPendingCallbacks() = 0;
};
-// FakeServerOptions bundles together a number of options for configuring the
-// server in HandshakeWithFakeServer.
-struct FakeServerOptions {
- FakeServerOptions();
- ~FakeServerOptions();
-
- // The Token Binding params that the server supports and will negotiate.
- QuicTagVector token_binding_params;
-};
-
// FakeClientOptions bundles together a number of options for configuring
// HandshakeWithFakeClient.
struct FakeClientOptions {
FakeClientOptions();
~FakeClientOptions();
- // If channel_id_enabled is true then the client will attempt to send a
- // ChannelID.
- bool channel_id_enabled;
-
- // If channel_id_source_async is true then the client will use an async
- // ChannelIDSource for testing. Ignored if channel_id_enabled is false.
- bool channel_id_source_async;
-
- // The Token Binding params that the client supports and will negotiate.
- QuicTagVector token_binding_params;
-
// If only_tls_versions is set, then the client will only use TLS for the
// crypto handshake.
bool only_tls_versions = false;
@@ -122,8 +69,7 @@ int HandshakeWithFakeServer(QuicConfig* server_quic_config,
MockQuicConnectionHelper* helper,
MockAlarmFactory* alarm_factory,
PacketSavingConnection* client_conn,
- QuicCryptoClientStream* client,
- const FakeServerOptions& options);
+ QuicCryptoClientStream* client);
// returns: the number of client hellos that the client sent.
int HandshakeWithFakeClient(MockQuicConnectionHelper* helper,
@@ -137,8 +83,7 @@ int HandshakeWithFakeClient(MockQuicConnectionHelper* helper,
// with sensible defaults for testing.
void SetupCryptoServerConfigForTest(const QuicClock* clock,
QuicRandom* rand,
- QuicCryptoServerConfig* crypto_config,
- const FakeServerOptions& options);
+ QuicCryptoServerConfig* crypto_config);
// Sends the handshake message |message| to stream |stream| with the perspective
// that the message is coming from |perspective|.
@@ -153,18 +98,6 @@ void CommunicateHandshakeMessages(PacketSavingConnection* client_conn,
PacketSavingConnection* server_conn,
QuicCryptoStream* server);
-// CommunicateHandshakeMessagesAndRunCallbacks moves messages from |client|
-// to |server| and back until |client|'s handshake has completed. If
-// |callback_source| is not nullptr,
-// CommunicateHandshakeMessagesAndRunCallbacks also runs callbacks from
-// |callback_source| between processing messages.
-void CommunicateHandshakeMessagesAndRunCallbacks(
- PacketSavingConnection* client_conn,
- QuicCryptoStream* client,
- PacketSavingConnection* server_conn,
- QuicCryptoStream* server,
- CallbackSource* callback_source);
-
// AdvanceHandshake attempts to moves messages from |client| to |server| and
// |server| to |client|. Returns the number of messages moved.
std::pair<size_t, size_t> AdvanceHandshake(PacketSavingConnection* client_conn,
@@ -199,7 +132,7 @@ CommonCertSets* MockCommonCertSets(QuicStringPiece cert,
// Creates a minimal dummy reject message that will pass the client-config
// validation tests. This will include a server config, but no certs, proof
// source address token, or server nonce.
-void FillInDummyReject(CryptoHandshakeMessage* rej, bool reject_is_stateless);
+void FillInDummyReject(CryptoHandshakeMessage* rej);
// ParseTag returns a QuicTag from parsing |tagstr|. |tagstr| may either be
// in the format "EXMP" (i.e. ASCII format), or "#11223344" (an explicit hex
@@ -222,12 +155,6 @@ CryptoHandshakeMessage CreateCHLO(
std::vector<std::pair<std::string, std::string>> tags_and_values,
int minimum_size_bytes);
-// ChannelIDSourceForTesting returns a ChannelIDSource that generates keys
-// deterministically based on the hostname given in the GetChannelIDKey call.
-// This ChannelIDSource works in synchronous mode, i.e., its GetChannelIDKey
-// method never returns QUIC_PENDING.
-std::unique_ptr<ChannelIDSource> ChannelIDSourceForTesting();
-
// MovePackets parses crypto handshake messages from packet number
// |*inout_packet_index| through to the last packet (or until a packet fails
// to decrypt) and has |dest_stream| process them. |*inout_packet_index| is
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_client_promised_info.h b/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_client_promised_info.h
index 2fbdfc38948..1cb9019033c 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_client_promised_info.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_client_promised_info.h
@@ -7,9 +7,9 @@
#include <string>
-#include "testing/gmock/include/gmock/gmock.h"
#include "net/third_party/quiche/src/quic/core/http/quic_client_promised_info.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
namespace quic {
namespace test {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_dispatcher.h b/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_dispatcher.h
index 0eaddc5fb35..3134e1fea7b 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_dispatcher.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_dispatcher.h
@@ -5,10 +5,10 @@
#ifndef QUICHE_QUIC_TEST_TOOLS_MOCK_QUIC_DISPATCHER_H_
#define QUICHE_QUIC_TEST_TOOLS_MOCK_QUIC_DISPATCHER_H_
-#include "testing/gmock/include/gmock/gmock.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
#include "net/third_party/quiche/src/quic/core/quic_config.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h"
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h b/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h
index d429cd42c0b..11dc24a724c 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h
@@ -5,9 +5,9 @@
#ifndef QUICHE_QUIC_TEST_TOOLS_MOCK_QUIC_SESSION_VISITOR_H_
#define QUICHE_QUIC_TEST_TOOLS_MOCK_QUIC_SESSION_VISITOR_H_
-#include "testing/gmock/include/gmock/gmock.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
namespace quic {
namespace test {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_spdy_client_stream.h b/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_spdy_client_stream.h
index e41df5284b7..02fe74ecb70 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_spdy_client_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_spdy_client_stream.h
@@ -5,10 +5,10 @@
#ifndef QUICHE_QUIC_TEST_TOOLS_MOCK_QUIC_SPDY_CLIENT_STREAM_H_
#define QUICHE_QUIC_TEST_TOOLS_MOCK_QUIC_SPDY_CLIENT_STREAM_H_
-#include "testing/gmock/include/gmock/gmock.h"
#include "net/third_party/quiche/src/quic/core/http/quic_header_list.h"
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
namespace quic {
namespace test {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_time_wait_list_manager.h b/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_time_wait_list_manager.h
index 742fef2ae89..8a394424a73 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_time_wait_list_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/mock_quic_time_wait_list_manager.h
@@ -5,8 +5,8 @@
#ifndef QUICHE_QUIC_TEST_TOOLS_MOCK_QUIC_TIME_WAIT_LIST_MANAGER_H_
#define QUICHE_QUIC_TEST_TOOLS_MOCK_QUIC_TIME_WAIT_LIST_MANAGER_H_
-#include "testing/gmock/include/gmock/gmock.h"
#include "net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
namespace quic {
namespace test {
@@ -45,8 +45,9 @@ class MockTimeWaitListManager : public QuicTimeWaitListManager {
PacketHeaderFormat header_format,
std::unique_ptr<QuicPerPacketContext> packet_context));
- MOCK_METHOD6(SendVersionNegotiationPacket,
- void(QuicConnectionId connection_id,
+ MOCK_METHOD7(SendVersionNegotiationPacket,
+ void(QuicConnectionId server_connection_id,
+ QuicConnectionId client_connection_id,
bool ietf_quic,
const ParsedQuicVersionVector& supported_versions,
const QuicSocketAddress& server_address,
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/packet_reordering_writer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/packet_reordering_writer.cc
index 5fa5659e596..7bbec0d3533 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/packet_reordering_writer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/packet_reordering_writer.cc
@@ -18,12 +18,12 @@ WriteResult PacketReorderingWriter::WritePacket(
const QuicSocketAddress& peer_address,
PerPacketOptions* options) {
if (!delay_next_) {
- VLOG(2) << "Writing a non-delayed packet";
+ QUIC_VLOG(2) << "Writing a non-delayed packet";
WriteResult wr = QuicPacketWriterWrapper::WritePacket(
buffer, buf_len, self_address, peer_address, options);
--num_packets_to_wait_;
if (num_packets_to_wait_ == 0) {
- VLOG(2) << "Writing a delayed packet";
+ QUIC_VLOG(2) << "Writing a delayed packet";
// It's time to write the delayed packet.
QuicPacketWriterWrapper::WritePacket(
delayed_data_.data(), delayed_data_.length(), delayed_self_address_,
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.cc
index f5a5b315b3f..f9ce04f1765 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.cc
@@ -45,10 +45,16 @@ void QuicConfigPeer::SetReceivedDisableConnectionMigration(QuicConfig* config) {
}
// static
-void QuicConfigPeer::SetReceivedMaxIncomingDynamicStreams(
+void QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams(
QuicConfig* config,
uint32_t max_streams) {
- config->max_incoming_dynamic_streams_.SetReceivedValue(max_streams);
+ config->max_incoming_bidirectional_streams_.SetReceivedValue(max_streams);
+}
+// static
+void QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
+ QuicConfig* config,
+ uint32_t max_streams) {
+ config->max_incoming_unidirectional_streams_.SetReceivedValue(max_streams);
}
// static
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.h
index 8869d270875..7faee7e6e11 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_config_peer.h
@@ -33,8 +33,10 @@ class QuicConfigPeer {
static void SetReceivedDisableConnectionMigration(QuicConfig* config);
- static void SetReceivedMaxIncomingDynamicStreams(QuicConfig* config,
- uint32_t max_streams);
+ static void SetReceivedMaxIncomingBidirectionalStreams(QuicConfig* config,
+ uint32_t max_streams);
+ static void SetReceivedMaxIncomingUnidirectionalStreams(QuicConfig* config,
+ uint32_t max_streams);
static void SetConnectionOptionsToSend(QuicConfig* config,
const QuicTagVector& options);
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.cc
index 13b315000ea..6eedd601bf3 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.cc
@@ -22,10 +22,10 @@ uint64_t QuicFramerPeer::CalculatePacketNumberFromWire(
}
// static
-void QuicFramerPeer::SetLastSerializedConnectionId(
+void QuicFramerPeer::SetLastSerializedServerConnectionId(
QuicFramer* framer,
- QuicConnectionId connection_id) {
- framer->last_serialized_connection_id_ = connection_id;
+ QuicConnectionId server_connection_id) {
+ framer->last_serialized_server_connection_id_ = server_connection_id;
}
// static
@@ -199,7 +199,7 @@ bool QuicFramerPeer::ProcessMaxStreamDataFrame(QuicFramer* framer,
// static
bool QuicFramerPeer::AppendMaxStreamsFrame(QuicFramer* framer,
- const QuicMaxStreamIdFrame& frame,
+ const QuicMaxStreamsFrame& frame,
QuicDataWriter* writer) {
return framer->AppendMaxStreamsFrame(frame, writer);
}
@@ -207,7 +207,7 @@ bool QuicFramerPeer::AppendMaxStreamsFrame(QuicFramer* framer,
// static
bool QuicFramerPeer::ProcessMaxStreamsFrame(QuicFramer* framer,
QuicDataReader* reader,
- QuicMaxStreamIdFrame* frame,
+ QuicMaxStreamsFrame* frame,
uint64_t frame_type) {
return framer->ProcessMaxStreamsFrame(reader, frame, frame_type);
}
@@ -243,7 +243,7 @@ bool QuicFramerPeer::ProcessStreamBlockedFrame(QuicFramer* framer,
// static
bool QuicFramerPeer::AppendStreamsBlockedFrame(
QuicFramer* framer,
- const QuicStreamIdBlockedFrame& frame,
+ const QuicStreamsBlockedFrame& frame,
QuicDataWriter* writer) {
return framer->AppendStreamsBlockedFrame(frame, writer);
}
@@ -251,7 +251,7 @@ bool QuicFramerPeer::AppendStreamsBlockedFrame(
// static
bool QuicFramerPeer::ProcessStreamsBlockedFrame(QuicFramer* framer,
QuicDataReader* reader,
- QuicStreamIdBlockedFrame* frame,
+ QuicStreamsBlockedFrame* frame,
uint64_t frame_type) {
return framer->ProcessStreamsBlockedFrame(reader, frame, frame_type);
}
@@ -337,11 +337,11 @@ void QuicFramerPeer::SetFirstSendingPacketNumber(QuicFramer* framer,
}
// static
-void QuicFramerPeer::SetExpectedConnectionIDLength(
+void QuicFramerPeer::SetExpectedServerConnectionIDLength(
QuicFramer* framer,
- uint8_t expected_connection_id_length) {
- *const_cast<uint8_t*>(&framer->expected_connection_id_length_) =
- expected_connection_id_length;
+ uint8_t expected_server_connection_id_length) {
+ *const_cast<uint8_t*>(&framer->expected_server_connection_id_length_) =
+ expected_server_connection_id_length;
}
// static
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 7b23189af24..0b17c1958d0 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
@@ -22,8 +22,9 @@ class QuicFramerPeer {
QuicPacketNumberLength packet_number_length,
QuicPacketNumber last_packet_number,
uint64_t packet_number);
- static void SetLastSerializedConnectionId(QuicFramer* framer,
- QuicConnectionId connection_id);
+ static void SetLastSerializedServerConnectionId(
+ QuicFramer* framer,
+ QuicConnectionId server_connection_id);
static void SetLargestPacketNumber(QuicFramer* framer,
QuicPacketNumber packet_number);
static void SetPerspective(QuicFramer* framer, Perspective perspective);
@@ -111,11 +112,11 @@ class QuicFramerPeer {
QuicDataReader* reader,
QuicWindowUpdateFrame* frame);
static bool AppendMaxStreamsFrame(QuicFramer* framer,
- const QuicMaxStreamIdFrame& frame,
+ const QuicMaxStreamsFrame& frame,
QuicDataWriter* writer);
static bool ProcessMaxStreamsFrame(QuicFramer* framer,
QuicDataReader* reader,
- QuicMaxStreamIdFrame* frame,
+ QuicMaxStreamsFrame* frame,
uint64_t frame_type);
static bool AppendIetfBlockedFrame(QuicFramer* framer,
const QuicBlockedFrame& frame,
@@ -132,11 +133,11 @@ class QuicFramerPeer {
QuicBlockedFrame* frame);
static bool AppendStreamsBlockedFrame(QuicFramer* framer,
- const QuicStreamIdBlockedFrame& frame,
+ const QuicStreamsBlockedFrame& frame,
QuicDataWriter* writer);
static bool ProcessStreamsBlockedFrame(QuicFramer* framer,
QuicDataReader* reader,
- QuicStreamIdBlockedFrame* frame,
+ QuicStreamsBlockedFrame* frame,
uint64_t frame_type);
static bool AppendNewConnectionIdFrame(QuicFramer* framer,
@@ -159,9 +160,9 @@ class QuicFramerPeer {
QuicPacketNumberLength packet_number_length);
static void SetFirstSendingPacketNumber(QuicFramer* framer,
uint64_t packet_number);
- static void SetExpectedConnectionIDLength(
+ static void SetExpectedServerConnectionIDLength(
QuicFramer* framer,
- uint8_t expected_connection_id_length);
+ uint8_t expected_server_connection_id_length);
static QuicPacketNumber GetLargestDecryptedPacketNumber(
QuicFramer* framer,
PacketNumberSpace packet_number_space);
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 3057e5e189c..c48c090ffbd 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
@@ -79,12 +79,6 @@ RttStats* QuicSentPacketManagerPeer::GetRttStats(
}
// static
-bool QuicSentPacketManagerPeer::HasPendingPackets(
- const QuicSentPacketManager* sent_packet_manager) {
- return sent_packet_manager->unacked_packets_.HasInFlightPackets();
-}
-
-// static
bool QuicSentPacketManagerPeer::IsRetransmission(
QuicSentPacketManager* sent_packet_manager,
uint64_t packet_number) {
@@ -142,12 +136,6 @@ QuicTime::Delta QuicSentPacketManagerPeer::GetTailLossProbeDelay(
}
// static
-bool QuicSentPacketManagerPeer::HasUnackedCryptoPackets(
- const QuicSentPacketManager* sent_packet_manager) {
- return sent_packet_manager->unacked_packets_.HasPendingCryptoPackets();
-}
-
-// static
size_t QuicSentPacketManagerPeer::GetNumRetransmittablePackets(
const QuicSentPacketManager* sent_packet_manager) {
size_t num_unacked_packets = 0;
@@ -161,12 +149,6 @@ size_t QuicSentPacketManagerPeer::GetNumRetransmittablePackets(
}
// static
-QuicByteCount QuicSentPacketManagerPeer::GetBytesInFlight(
- const QuicSentPacketManager* sent_packet_manager) {
- return sent_packet_manager->unacked_packets_.bytes_in_flight();
-}
-
-// static
void QuicSentPacketManagerPeer::SetConsecutiveRtoCount(
QuicSentPacketManager* sent_packet_manager,
size_t count) {
@@ -200,14 +182,6 @@ void QuicSentPacketManagerPeer::SetUsingPacing(
}
// static
-bool QuicSentPacketManagerPeer::IsUnacked(
- QuicSentPacketManager* sent_packet_manager,
- uint64_t packet_number) {
- return sent_packet_manager->unacked_packets_.IsUnacked(
- QuicPacketNumber(packet_number));
-}
-
-// static
bool QuicSentPacketManagerPeer::HasRetransmittableFrames(
QuicSentPacketManager* sent_packet_manager,
uint64_t packet_number) {
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 23244e5d2b9..6dcce0cf4a4 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
@@ -46,9 +46,6 @@ class QuicSentPacketManagerPeer {
static RttStats* GetRttStats(QuicSentPacketManager* sent_packet_manager);
- static bool HasPendingPackets(
- const QuicSentPacketManager* sent_packet_manager);
-
// Returns true if |packet_number| is a retransmission of a packet.
static bool IsRetransmission(QuicSentPacketManager* sent_packet_manager,
uint64_t packet_number);
@@ -68,15 +65,9 @@ class QuicSentPacketManagerPeer {
static QuicTime::Delta GetTailLossProbeDelay(
const QuicSentPacketManager* sent_packet_manager);
- static bool HasUnackedCryptoPackets(
- const QuicSentPacketManager* sent_packet_manager);
-
static size_t GetNumRetransmittablePackets(
const QuicSentPacketManager* sent_packet_manager);
- static QuicByteCount GetBytesInFlight(
- const QuicSentPacketManager* sent_packet_manager);
-
static void SetConsecutiveRtoCount(QuicSentPacketManager* sent_packet_manager,
size_t count);
@@ -91,9 +82,6 @@ class QuicSentPacketManagerPeer {
static bool UsingPacing(const QuicSentPacketManager* sent_packet_manager);
- static bool IsUnacked(QuicSentPacketManager* sent_packet_manager,
- uint64_t packet_number);
-
static bool HasRetransmittableFrames(
QuicSentPacketManager* sent_packet_manager,
uint64_t packet_number);
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_server_session_base_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_server_session_base_peer.h
index 30c9b22836d..d2a21a6c9eb 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_server_session_base_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_server_session_base_peer.h
@@ -21,9 +21,11 @@ class QuicServerSessionBasePeer {
static void SetCryptoStream(QuicServerSessionBase* s,
QuicCryptoServerStream* crypto_stream) {
s->crypto_stream_.reset(crypto_stream);
- s->RegisterStaticStream(
- QuicUtils::GetCryptoStreamId(s->connection()->transport_version()),
- crypto_stream);
+ if (!QuicVersionUsesCryptoFrames(s->connection()->transport_version())) {
+ s->RegisterStaticStream(
+ QuicUtils::GetCryptoStreamId(s->connection()->transport_version()),
+ crypto_stream);
+ }
}
static bool IsBandwidthResumptionEnabled(QuicServerSessionBase* s) {
return s->bandwidth_resumption_enabled_;
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 37e5013cf92..9eee4944773 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
@@ -6,6 +6,7 @@
#include "net/third_party/quiche/src/quic/core/quic_session.h"
#include "net/third_party/quiche/src/quic/core/quic_stream.h"
+#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
namespace quic {
@@ -38,23 +39,73 @@ void QuicSessionPeer::SetNextOutgoingBidirectionalStreamId(QuicSession* session,
void QuicSessionPeer::SetMaxOpenIncomingStreams(QuicSession* session,
uint32_t max_streams) {
if (session->connection()->transport_version() == QUIC_VERSION_99) {
- session->v99_streamid_manager_.SetMaxOpenIncomingStreams(max_streams);
+ QUIC_BUG << "SetmaxOpenIncomingStreams deprecated for IETF QUIC/V99";
+ session->v99_streamid_manager_.SetMaxOpenIncomingUnidirectionalStreams(
+ max_streams);
+ session->v99_streamid_manager_.SetMaxOpenIncomingBidirectionalStreams(
+ max_streams);
return;
}
session->stream_id_manager_.set_max_open_incoming_streams(max_streams);
}
// static
+void QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(
+ QuicSession* session,
+ uint32_t max_streams) {
+ DCHECK_EQ(QUIC_VERSION_99, session->connection()->transport_version())
+ << "SetmaxOpenIncomingBidirectionalStreams not supported for Google "
+ "QUIC/not-V99";
+ session->v99_streamid_manager_.SetMaxOpenIncomingBidirectionalStreams(
+ max_streams);
+}
+// static
+void QuicSessionPeer::SetMaxOpenIncomingUnidirectionalStreams(
+ QuicSession* session,
+ uint32_t max_streams) {
+ DCHECK_EQ(QUIC_VERSION_99, session->connection()->transport_version())
+ << "SetmaxOpenIncomingUnidirectionalStreams not supported for Google "
+ "QUIC/not-V99";
+ session->v99_streamid_manager_.SetMaxOpenIncomingUnidirectionalStreams(
+ max_streams);
+}
+
+// static
void QuicSessionPeer::SetMaxOpenOutgoingStreams(QuicSession* session,
uint32_t max_streams) {
if (session->connection()->transport_version() == QUIC_VERSION_99) {
- session->v99_streamid_manager_.SetMaxOpenOutgoingStreams(max_streams);
+ QUIC_BUG << "SetmaxOpenOutgoingStreams deprecated for IETF QUIC/V99";
+ session->v99_streamid_manager_.SetMaxOpenOutgoingUnidirectionalStreams(
+ max_streams);
+ session->v99_streamid_manager_.SetMaxOpenOutgoingBidirectionalStreams(
+ max_streams);
return;
}
session->stream_id_manager_.set_max_open_outgoing_streams(max_streams);
}
// static
+void QuicSessionPeer::SetMaxOpenOutgoingBidirectionalStreams(
+ QuicSession* session,
+ uint32_t max_streams) {
+ DCHECK_EQ(QUIC_VERSION_99, session->connection()->transport_version())
+ << "SetmaxOpenOutgoingBidirectionalStreams not supported for Google "
+ "QUIC/not-V99";
+ session->v99_streamid_manager_.SetMaxOpenOutgoingBidirectionalStreams(
+ max_streams);
+}
+// static
+void QuicSessionPeer::SetMaxOpenOutgoingUnidirectionalStreams(
+ QuicSession* session,
+ uint32_t max_streams) {
+ DCHECK_EQ(QUIC_VERSION_99, session->connection()->transport_version())
+ << "SetmaxOpenOutgoingUnidirectionalStreams not supported for Google "
+ "QUIC/not-V99";
+ session->v99_streamid_manager_.SetMaxOpenOutgoingUnidirectionalStreams(
+ max_streams);
+}
+
+// static
QuicCryptoStream* QuicSessionPeer::GetMutableCryptoStream(
QuicSession* session) {
return session->GetMutableCryptoStream();
@@ -115,22 +166,33 @@ void QuicSessionPeer::ActivateStream(QuicSession* session,
}
// static
+void QuicSessionPeer::RegisterStaticStream(QuicSession* session,
+ QuicStreamId id,
+ QuicStream* stream) {
+ return session->RegisterStaticStream(id, stream);
+}
+
+// static
+void QuicSessionPeer::RegisterStaticStreamNew(
+ QuicSession* session,
+ std::unique_ptr<QuicStream> stream) {
+ return session->RegisterStaticStreamNew(std::move(stream));
+}
+
+// static
bool QuicSessionPeer::IsStreamClosed(QuicSession* session, QuicStreamId id) {
- DCHECK_NE(0u, id);
return session->IsClosedStream(id);
}
// static
bool QuicSessionPeer::IsStreamCreated(QuicSession* session, QuicStreamId id) {
- DCHECK_NE(0u, id);
return QuicContainsKey(session->dynamic_streams(), id);
}
// static
bool QuicSessionPeer::IsStreamAvailable(QuicSession* session, QuicStreamId id) {
- DCHECK_NE(0u, id);
if (session->connection()->transport_version() == QUIC_VERSION_99) {
- if (id % kV99StreamIdIncrement < 2) {
+ if (id % QuicUtils::StreamIdDelta(QUIC_VERSION_99) < 2) {
return QuicContainsKey(
session->v99_streamid_manager_.bidirectional_stream_id_manager_
.available_streams_,
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 30e358f4bc6..3828981ed94 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
@@ -32,10 +32,24 @@ class QuicSessionPeer {
QuicSession* session);
static void SetNextOutgoingBidirectionalStreamId(QuicSession* session,
QuicStreamId id);
+ // Following is only for Google-QUIC, will QUIC_BUG if called for IETF
+ // QUIC.
static void SetMaxOpenIncomingStreams(QuicSession* session,
uint32_t max_streams);
+ // Following two are only for IETF-QUIC, will QUIC_BUG if called for Google
+ // QUIC.
+ static void SetMaxOpenIncomingBidirectionalStreams(QuicSession* session,
+ uint32_t max_streams);
+ static void SetMaxOpenIncomingUnidirectionalStreams(QuicSession* session,
+ uint32_t max_streams);
+
static void SetMaxOpenOutgoingStreams(QuicSession* session,
uint32_t max_streams);
+ static void SetMaxOpenOutgoingBidirectionalStreams(QuicSession* session,
+ uint32_t max_streams);
+ static void SetMaxOpenOutgoingUnidirectionalStreams(QuicSession* session,
+ uint32_t max_streams);
+
static QuicCryptoStream* GetMutableCryptoStream(QuicSession* session);
static QuicWriteBlockedList* GetWriteBlockedStreams(QuicSession* session);
static QuicStream* GetOrCreateDynamicStream(QuicSession* session,
@@ -50,6 +64,11 @@ class QuicSessionPeer {
QuicSession* session);
static void ActivateStream(QuicSession* session,
std::unique_ptr<QuicStream> stream);
+ static void RegisterStaticStream(QuicSession* session,
+ QuicStreamId stream_id,
+ QuicStream* stream);
+ static void RegisterStaticStreamNew(QuicSession* session,
+ std::unique_ptr<QuicStream> stream);
// Discern the state of a stream. Exactly one of these should be true at a
// time for any stream id > 0 (other than the special streams 1 and 3).
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc
index dcba12c5fee..956cd88034f 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc
@@ -13,7 +13,7 @@ namespace test {
// static
QuicHeadersStream* QuicSpdySessionPeer::GetHeadersStream(
QuicSpdySession* session) {
- return session->headers_stream_.get();
+ return session->headers_stream();
}
// static
@@ -25,6 +25,20 @@ void QuicSpdySessionPeer::SetHeadersStream(QuicSpdySession* session,
}
}
+void QuicSpdySessionPeer::SetUnownedHeadersStream(
+ QuicSpdySession* session,
+ QuicHeadersStream* headers_stream) {
+ for (auto& it : session->dynamic_streams()) {
+ if (it.first == QuicUtils::GetHeadersStreamId(
+ session->connection()->transport_version())) {
+ it.second.reset(headers_stream);
+ session->unowned_headers_stream_ =
+ static_cast<QuicHeadersStream*>(it.second.get());
+ break;
+ }
+ }
+}
+
// static
const spdy::SpdyFramer& QuicSpdySessionPeer::GetSpdyFramer(
QuicSpdySession* session) {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h
index 83e8b0caf11..47b55e1c7c0 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h
@@ -24,6 +24,8 @@ class QuicSpdySessionPeer {
static QuicHeadersStream* GetHeadersStream(QuicSpdySession* session);
static void SetHeadersStream(QuicSpdySession* session,
QuicHeadersStream* headers_stream);
+ static void SetUnownedHeadersStream(QuicSpdySession* session,
+ QuicHeadersStream* headers_stream);
static const spdy::SpdyFramer& GetSpdyFramer(QuicSpdySession* session);
static void SetHpackEncoderDebugVisitor(
QuicSpdySession* session,
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.cc
index 705ee270b55..3ce5f1f2a39 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.cc
@@ -4,33 +4,26 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.h"
#include "net/third_party/quiche/src/quic/core/quic_stream_id_manager.h"
+#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
namespace quic {
namespace test {
// static
-void QuicStreamIdManagerPeer::IncrementMaximumAllowedOutgoingStreamId(
+void QuicStreamIdManagerPeer::set_incoming_actual_max_streams(
QuicStreamIdManager* stream_id_manager,
- int increment) {
- stream_id_manager->max_allowed_outgoing_stream_id_ +=
- (increment * kV99StreamIdIncrement);
+ QuicStreamCount count) {
+ stream_id_manager->incoming_actual_max_streams_ = count;
}
// static
-void QuicStreamIdManagerPeer::IncrementMaximumAllowedIncomingStreamId(
- QuicStreamIdManager* stream_id_manager,
- int increment) {
- stream_id_manager->actual_max_allowed_incoming_stream_id_ +=
- (increment * kV99StreamIdIncrement);
- stream_id_manager->advertised_max_allowed_incoming_stream_id_ +=
- (increment * kV99StreamIdIncrement);
+QuicStreamId QuicStreamIdManagerPeer::GetFirstIncomingStreamId(
+ QuicStreamIdManager* stream_id_manager) {
+ return stream_id_manager->GetFirstIncomingStreamId();
}
-// static
-void QuicStreamIdManagerPeer::SetMaxOpenIncomingStreams(
- QuicStreamIdManager* stream_id_manager,
- size_t max_streams) {
- stream_id_manager->SetMaxOpenIncomingStreams(max_streams);
-}
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.h
index 2ec07b1e7fd..cc78aee5820 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.h
@@ -6,23 +6,25 @@
#include <stddef.h>
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+
namespace quic {
class QuicStreamIdManager;
+class UberQuicStreamIdManager;
namespace test {
class QuicStreamIdManagerPeer {
public:
QuicStreamIdManagerPeer() = delete;
- static void IncrementMaximumAllowedOutgoingStreamId(
- QuicStreamIdManager* stream_id_manager,
- int increment);
- static void IncrementMaximumAllowedIncomingStreamId(
+
+ static void set_incoming_actual_max_streams(
QuicStreamIdManager* stream_id_manager,
- int increment);
- static void SetMaxOpenIncomingStreams(QuicStreamIdManager* stream_id_manager,
- size_t max_streams);
+ QuicStreamCount count);
+
+ static QuicStreamId GetFirstIncomingStreamId(
+ QuicStreamIdManager* stream_id_manager);
};
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.cc
index fb76f7a10f3..d4608ed8686 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
@@ -92,6 +92,8 @@ class RecordingProofVerifier : public ProofVerifier {
QuicAsyncStatus VerifyCertChain(
const std::string& hostname,
const std::vector<std::string>& certs,
+ const std::string& ocsp_response,
+ const std::string& cert_sct,
const ProofVerifyContext* context,
std::string* error_details,
std::unique_ptr<ProofVerifyDetails>* details,
@@ -207,8 +209,8 @@ MockableQuicClient::MockableQuicClient(
this),
QuicWrapUnique(
new RecordingProofVerifier(std::move(proof_verifier)))),
- override_connection_id_(EmptyQuicConnectionId()),
- connection_id_overridden_(false) {}
+ override_server_connection_id_(EmptyQuicConnectionId()),
+ server_connection_id_overridden_(false) {}
MockableQuicClient::~MockableQuicClient() {
if (connected()) {
@@ -229,13 +231,15 @@ MockableQuicClient::mockable_network_helper() const {
}
QuicConnectionId MockableQuicClient::GenerateNewConnectionId() {
- return connection_id_overridden_ ? override_connection_id_
- : QuicClient::GenerateNewConnectionId();
+ return server_connection_id_overridden_
+ ? override_server_connection_id_
+ : QuicClient::GenerateNewConnectionId();
}
-void MockableQuicClient::UseConnectionId(QuicConnectionId connection_id) {
- connection_id_overridden_ = true;
- override_connection_id_ = connection_id;
+void MockableQuicClient::UseConnectionId(
+ QuicConnectionId server_connection_id) {
+ server_connection_id_overridden_ = true;
+ override_server_connection_id_ = server_connection_id;
}
void MockableQuicClient::UseWriter(QuicPacketWriterWrapper* writer) {
@@ -396,16 +400,6 @@ ssize_t QuicTestClient::GetOrCreateStreamAndSendRequest(
stream->WriteOrBufferBody(std::string(body), fin);
ret = body.length();
}
- if (GetQuicReloadableFlag(enable_quic_stateless_reject_support)) {
- std::unique_ptr<spdy::SpdyHeaderBlock> new_headers;
- if (headers) {
- new_headers = QuicMakeUnique<spdy::SpdyHeaderBlock>(headers->Clone());
- }
- std::unique_ptr<QuicSpdyClientBase::QuicDataToResend> data_to_resend(
- new TestClientDataToResend(std::move(new_headers), body, fin, this,
- ack_listener));
- client()->MaybeAddQuicDataToResend(std::move(data_to_resend));
- }
return ret;
}
@@ -629,8 +623,8 @@ bool QuicTestClient::WaitUntil(int timeout_ms, std::function<bool()> trigger) {
epoll_server()->set_timeout_in_us(old_timeout_us);
}
if (trigger && !trigger()) {
- VLOG(1) << "Client WaitUntil returning with trigger returning false."
- << QuicStackTrace();
+ QUIC_VLOG(1) << "Client WaitUntil returning with trigger returning false."
+ << QuicStackTrace();
return false;
}
return true;
@@ -651,9 +645,7 @@ bool QuicTestClient::response_headers_complete() const {
const spdy::SpdyHeaderBlock* QuicTestClient::response_headers() const {
for (std::pair<QuicStreamId, QuicSpdyClientStream*> stream : open_streams_) {
- size_t bytes_read =
- stream.second->stream_bytes_read() + stream.second->header_bytes_read();
- if (bytes_read > 0) {
+ if (stream.second->headers_decompressed()) {
response_headers_ = stream.second->response_headers().Clone();
break;
}
@@ -759,9 +751,9 @@ void QuicTestClient::UseWriter(QuicPacketWriterWrapper* writer) {
client_->UseWriter(writer);
}
-void QuicTestClient::UseConnectionId(QuicConnectionId connection_id) {
+void QuicTestClient::UseConnectionId(QuicConnectionId server_connection_id) {
DCHECK(!connected());
- client_->UseConnectionId(connection_id);
+ client_->UseConnectionId(server_connection_id);
}
bool QuicTestClient::MigrateSocket(const QuicIpAddress& new_host) {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.h
index 02a0ed6cf8f..a4ee0d5cb80 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.h
@@ -9,7 +9,6 @@
#include <memory>
#include <string>
-#include "testing/gmock/include/gmock/gmock.h"
#include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters.pb.h"
#include "net/third_party/quiche/src/quic/core/quic_framer.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_creator.h"
@@ -18,6 +17,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/tools/quic_client.h"
namespace quic {
@@ -55,7 +55,7 @@ class MockableQuicClient : public QuicClient {
~MockableQuicClient() override;
QuicConnectionId GenerateNewConnectionId() override;
- void UseConnectionId(QuicConnectionId connection_id);
+ void UseConnectionId(QuicConnectionId server_connection_id);
void UseWriter(QuicPacketWriterWrapper* writer);
void set_peer_address(const QuicSocketAddress& address);
@@ -69,9 +69,9 @@ class MockableQuicClient : public QuicClient {
const MockableQuicClientEpollNetworkHelper* mockable_network_helper() const;
private:
- // ConnectionId to use, if connection_id_overridden_
- QuicConnectionId override_connection_id_;
- bool connection_id_overridden_;
+ // Server connection ID to use, if server_connection_id_overridden_
+ QuicConnectionId override_server_connection_id_;
+ bool server_connection_id_overridden_;
CachedNetworkParameters cached_network_paramaters_;
};
@@ -185,8 +185,8 @@ class QuicTestClient : public QuicSpdyStream::Visitor,
void WaitForResponseForMs(int timeout_ms) {
WaitUntil(timeout_ms, [this]() { return !closed_stream_states_.empty(); });
if (response_complete()) {
- VLOG(1) << "Client received response:"
- << response_headers()->DebugString() << response_body();
+ QUIC_VLOG(1) << "Client received response:"
+ << response_headers()->DebugString() << response_body();
}
}
@@ -219,9 +219,9 @@ class QuicTestClient : public QuicSpdyStream::Visitor,
// Configures client_ to take ownership of and use the writer.
// Must be called before initial connect.
void UseWriter(QuicPacketWriterWrapper* writer);
- // If the given ConnectionId is nonzero, configures client_ to use a specific
- // ConnectionId instead of a random one.
- void UseConnectionId(QuicConnectionId connection_id);
+ // Configures client_ to use a specific server connection ID instead of a
+ // random one.
+ void UseConnectionId(QuicConnectionId server_connection_id);
// Returns nullptr if the maximum number of streams have already been created.
QuicSpdyClientStream* GetOrCreateStream();
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 bda2148731c..68c500e67b7 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
@@ -77,7 +77,7 @@ class QuicTestDispatcher : public QuicSimpleDispatcher {
std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
QuicSimpleServerBackend* quic_simple_server_backend,
- uint8_t expected_connection_id_length)
+ uint8_t expected_server_connection_id_length)
: QuicSimpleDispatcher(config,
crypto_config,
version_manager,
@@ -85,7 +85,7 @@ class QuicTestDispatcher : public QuicSimpleDispatcher {
std::move(session_helper),
std::move(alarm_factory),
quic_simple_server_backend,
- expected_connection_id_length),
+ expected_server_connection_id_length),
session_factory_(nullptr),
stream_factory_(nullptr),
crypto_stream_factory_(nullptr) {}
@@ -170,13 +170,13 @@ QuicTestServer::QuicTestServer(
const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
QuicSimpleServerBackend* quic_simple_server_backend,
- uint8_t expected_connection_id_length)
+ uint8_t expected_server_connection_id_length)
: QuicServer(std::move(proof_source),
config,
QuicCryptoServerConfig::ConfigOptions(),
supported_versions,
quic_simple_server_backend,
- expected_connection_id_length) {}
+ expected_server_connection_id_length) {}
QuicDispatcher* QuicTestServer::CreateQuicDispatcher() {
return new QuicTestDispatcher(
@@ -186,7 +186,7 @@ QuicDispatcher* QuicTestServer::CreateQuicDispatcher() {
std::unique_ptr<QuicCryptoServerStream::Helper>(
new QuicSimpleCryptoServerStreamHelper(QuicRandom::GetInstance())),
QuicMakeUnique<QuicEpollAlarmFactory>(epoll_server()), server_backend(),
- expected_connection_id_length());
+ expected_server_connection_id_length());
}
void QuicTestServer::SetSessionFactory(SessionFactory* factory) {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.h
index 52fb7c531d5..3661b7a1c8e 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_server.h
@@ -69,7 +69,7 @@ class QuicTestServer : public QuicServer {
const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
QuicSimpleServerBackend* quic_simple_server_backend,
- uint8_t expected_connection_id_length);
+ uint8_t expected_server_connection_id_length);
// Create a custom dispatcher which creates custom sessions.
QuicDispatcher* CreateQuicDispatcher() override;
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 870a7b82e66..e1f036d3bcd 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
@@ -5,8 +5,10 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include <algorithm>
+#include <cstdint>
#include <memory>
+#include "third_party/boringssl/src/include/openssl/chacha.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
@@ -152,20 +154,42 @@ std::string Sha1Hash(QuicStringPiece data) {
}
uint64_t SimpleRandom::RandUint64() {
- std::string hash =
- Sha1Hash(QuicStringPiece(reinterpret_cast<char*>(&seed_), sizeof(seed_)));
- DCHECK_EQ(static_cast<size_t>(SHA_DIGEST_LENGTH), hash.length());
- memcpy(&seed_, hash.data(), sizeof(seed_));
- return seed_;
+ uint64_t result;
+ RandBytes(&result, sizeof(result));
+ return result;
}
void SimpleRandom::RandBytes(void* data, size_t len) {
- uint8_t* real_data = static_cast<uint8_t*>(data);
- for (size_t offset = 0; offset < len; offset++) {
- real_data[offset] = RandUint64() & 0xff;
+ uint8_t* data_bytes = reinterpret_cast<uint8_t*>(data);
+ while (len > 0) {
+ const size_t buffer_left = sizeof(buffer_) - buffer_offset_;
+ const size_t to_copy = std::min(buffer_left, len);
+ memcpy(data_bytes, buffer_ + buffer_offset_, to_copy);
+ data_bytes += to_copy;
+ buffer_offset_ += to_copy;
+ len -= to_copy;
+
+ if (buffer_offset_ == sizeof(buffer_)) {
+ FillBuffer();
+ }
}
}
+void SimpleRandom::FillBuffer() {
+ uint8_t nonce[12];
+ memcpy(nonce, buffer_, sizeof(nonce));
+ CRYPTO_chacha_20(buffer_, buffer_, sizeof(buffer_), key_, nonce, 0);
+ buffer_offset_ = 0;
+}
+
+void SimpleRandom::set_seed(uint64_t seed) {
+ static_assert(sizeof(key_) == SHA256_DIGEST_LENGTH, "Key has to be 256 bits");
+ SHA256(reinterpret_cast<const uint8_t*>(&seed), sizeof(seed), key_);
+
+ memset(buffer_, 0, sizeof(buffer_));
+ FillBuffer();
+}
+
MockFramerVisitor::MockFramerVisitor() {
// By default, we want to accept packets.
ON_CALL(*this, OnProtocolVersionMismatch(_, _))
@@ -202,9 +226,8 @@ MockFramerVisitor::MockFramerVisitor() {
ON_CALL(*this, OnPathResponseFrame(_)).WillByDefault(testing::Return(true));
ON_CALL(*this, OnGoAwayFrame(_)).WillByDefault(testing::Return(true));
- ON_CALL(*this, OnMaxStreamIdFrame(_)).WillByDefault(testing::Return(true));
- ON_CALL(*this, OnStreamIdBlockedFrame(_))
- .WillByDefault(testing::Return(true));
+ ON_CALL(*this, OnMaxStreamsFrame(_)).WillByDefault(testing::Return(true));
+ ON_CALL(*this, OnStreamsBlockedFrame(_)).WillByDefault(testing::Return(true));
}
MockFramerVisitor::~MockFramerVisitor() {}
@@ -310,12 +333,12 @@ bool NoOpFramerVisitor::OnGoAwayFrame(const QuicGoAwayFrame& frame) {
return true;
}
-bool NoOpFramerVisitor::OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) {
+bool NoOpFramerVisitor::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
return true;
}
-bool NoOpFramerVisitor::OnStreamIdBlockedFrame(
- const QuicStreamIdBlockedFrame& frame) {
+bool NoOpFramerVisitor::OnStreamsBlockedFrame(
+ const QuicStreamsBlockedFrame& frame) {
return true;
}
@@ -615,10 +638,8 @@ QuicCryptoServerStreamBase*
TestQuicSpdyServerSession::CreateQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache) {
- return new QuicCryptoServerStream(
- crypto_config, compressed_certs_cache,
- GetQuicReloadableFlag(enable_quic_stateless_reject_support), this,
- &helper_);
+ return new QuicCryptoServerStream(crypto_config, compressed_certs_cache, this,
+ &helper_);
}
void TestQuicSpdyServerSession::OnCryptoHandshakeEvent(
@@ -862,15 +883,41 @@ QuicEncryptedPacket* ConstructEncryptedPacket(
QuicFrames frames;
QuicFramer framer(*versions, QuicTime::Zero(), perspective,
kQuicDefaultConnectionIdLength);
- if (!QuicVersionUsesCryptoFrames((*versions)[0].transport_version)) {
- QuicFrame frame(QuicStreamFrame(
- QuicUtils::GetCryptoStreamId((*versions)[0].transport_version), false,
- 0, QuicStringPiece(data)));
+ ParsedQuicVersion version = (*versions)[0];
+ EncryptionLevel level =
+ header.version_flag ? ENCRYPTION_INITIAL : ENCRYPTION_FORWARD_SECURE;
+ if (version.handshake_protocol == PROTOCOL_TLS1_3 &&
+ level == ENCRYPTION_INITIAL) {
+ CrypterPair crypters;
+ CryptoUtils::CreateTlsInitialCrypters(Perspective::IS_CLIENT,
+ version.transport_version,
+ destination_connection_id, &crypters);
+ framer.SetEncrypter(ENCRYPTION_INITIAL, std::move(crypters.encrypter));
+ if (version.KnowsWhichDecrypterToUse()) {
+ framer.InstallDecrypter(ENCRYPTION_INITIAL,
+ std::move(crypters.decrypter));
+ } else {
+ framer.SetDecrypter(ENCRYPTION_INITIAL, std::move(crypters.decrypter));
+ }
+ }
+ if (!QuicVersionUsesCryptoFrames(version.transport_version)) {
+ QuicFrame frame(
+ QuicStreamFrame(QuicUtils::GetCryptoStreamId(version.transport_version),
+ false, 0, QuicStringPiece(data)));
frames.push_back(frame);
} else {
- QuicFrame frame(new QuicCryptoFrame(ENCRYPTION_INITIAL, 0, data));
+ QuicFrame frame(new QuicCryptoFrame(level, 0, data));
frames.push_back(frame);
}
+ // We need a minimum number of bytes of encrypted payload. This will
+ // guarantee that we have at least that much. (It ignores the overhead of the
+ // stream/crypto framing, so it overpads slightly.)
+ size_t min_plaintext_size =
+ QuicPacketCreator::MinPlaintextPacketSize(version);
+ if (data.length() < min_plaintext_size) {
+ size_t padding_length = min_plaintext_size - data.length();
+ frames.push_back(QuicFrame(QuicPaddingFrame(padding_length)));
+ }
std::unique_ptr<QuicPacket> packet(
BuildUnsizedDataPacket(&framer, header, frames));
@@ -923,9 +970,26 @@ 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,
kQuicDefaultConnectionIdLength);
+ if (version.handshake_protocol == PROTOCOL_TLS1_3 && version_flag) {
+ CrypterPair crypters;
+ CryptoUtils::CreateTlsInitialCrypters(Perspective::IS_CLIENT,
+ version.transport_version,
+ destination_connection_id, &crypters);
+ framer.SetEncrypter(ENCRYPTION_INITIAL, std::move(crypters.encrypter));
+ framer.SetDecrypter(ENCRYPTION_INITIAL, std::move(crypters.decrypter));
+ }
+ // We need a minimum of 7 bytes of encrypted payload. This will guarantee that
+ // we have at least that much. (It ignores the overhead of the stream/crypto
+ // framing, so it overpads slightly.)
+ if (data.length() < 7) {
+ size_t padding_length = 7 - data.length();
+ frames.push_back(QuicFrame(QuicPaddingFrame(padding_length)));
+ }
std::unique_ptr<QuicPacket> packet(
BuildUnsizedDataPacket(&framer, header, frames));
@@ -985,7 +1049,7 @@ QuicConfig DefaultQuicConfig() {
kInitialStreamFlowControlWindowForTest);
config.SetInitialSessionFlowControlWindowToSend(
kInitialSessionFlowControlWindowForTest);
- QuicConfigPeer::SetReceivedMaxIncomingDynamicStreams(
+ QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams(
&config, kDefaultMaxStreamsPerConnection);
// Default enable NSTP.
// This is unnecessary for versions > 44
@@ -998,14 +1062,6 @@ QuicConfig DefaultQuicConfig() {
return config;
}
-QuicConfig DefaultQuicConfigStatelessRejects() {
- QuicConfig config = DefaultQuicConfig();
- QuicTagVector copt;
- copt.push_back(kSREJ);
- config.SetConnectionOptionsToSend(copt);
- return config;
-}
-
QuicTransportVersionVector SupportedTransportVersions(
QuicTransportVersion version) {
QuicTransportVersionVector versions;
@@ -1028,10 +1084,6 @@ MockReceivedPacketManager::MockReceivedPacketManager(QuicConnectionStats* stats)
MockReceivedPacketManager::~MockReceivedPacketManager() {}
-MockConnectionCloseDelegate::MockConnectionCloseDelegate() {}
-
-MockConnectionCloseDelegate::~MockConnectionCloseDelegate() {}
-
MockPacketCreatorDelegate::MockPacketCreatorDelegate() {}
MockPacketCreatorDelegate::~MockPacketCreatorDelegate() {}
@@ -1040,7 +1092,6 @@ MockSessionNotifier::~MockSessionNotifier() {}
void CreateClientSessionForTest(
QuicServerId server_id,
- bool supports_stateless_rejects,
QuicTime::Delta connection_start_time,
const ParsedQuicVersionVector& supported_versions,
MockQuicConnectionHelper* helper,
@@ -1055,9 +1106,7 @@ void CreateClientSessionForTest(
<< "Connections must start at non-zero times, otherwise the "
<< "strike-register will be unhappy.";
- QuicConfig config = supports_stateless_rejects
- ? DefaultQuicConfigStatelessRejects()
- : DefaultQuicConfig();
+ QuicConfig config = DefaultQuicConfig();
*client_connection = new PacketSavingConnection(
helper, alarm_factory, Perspective::IS_CLIENT, supported_versions);
*client_session = new TestQuicSpdyClientSession(*client_connection, config,
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 c888fef9b72..4f6a30a17c0 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
@@ -13,13 +13,11 @@
#include <utility>
#include <vector>
-#include "testing/gmock/include/gmock/gmock.h"
#include "net/third_party/quiche/src/quic/core/congestion_control/loss_detection_interface.h"
#include "net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h"
#include "net/third_party/quiche/src/quic/core/http/quic_client_push_promise_index.h"
#include "net/third_party/quiche/src/quic/core/http/quic_server_session_base.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
-#include "net/third_party/quiche/src/quic/core/quic_connection_close_delegate_interface.h"
#include "net/third_party/quiche/src/quic/core/quic_framer.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_writer.h"
#include "net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h"
@@ -27,6 +25,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_storage.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_quic_session_visitor.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
@@ -161,9 +160,6 @@ void CompareCharArraysWithHexError(const std::string& description,
// Returns QuicConfig set to default values.
QuicConfig DefaultQuicConfig();
-// Returns a QuicConfig set to default values that supports stateless rejects.
-QuicConfig DefaultQuicConfigStatelessRejects();
-
// Returns a version vector consisting of |version|.
QuicTransportVersionVector SupportedTransportVersions(
QuicTransportVersion version);
@@ -213,12 +209,10 @@ std::unique_ptr<QuicPacket> BuildUnsizedDataPacket(
std::string Sha1Hash(QuicStringPiece data);
// Simple random number generator used to compute random numbers suitable
-// for pseudo-randomly dropping packets in tests. It works by computing
-// the sha1 hash of the current seed, and using the first 64 bits as
-// the next random number, and the next seed.
+// for pseudo-randomly dropping packets in tests.
class SimpleRandom : public QuicRandom {
public:
- SimpleRandom() : seed_(0) {}
+ SimpleRandom() { set_seed(0); }
SimpleRandom(const SimpleRandom&) = delete;
SimpleRandom& operator=(const SimpleRandom&) = delete;
~SimpleRandom() override {}
@@ -228,10 +222,14 @@ class SimpleRandom : public QuicRandom {
void RandBytes(void* data, size_t len) override;
- void set_seed(uint64_t seed) { seed_ = seed; }
+ void set_seed(uint64_t seed);
private:
- uint64_t seed_;
+ uint8_t buffer_[4096];
+ size_t buffer_offset_;
+ uint8_t key_[32];
+
+ void FillBuffer();
};
class MockFramerVisitor : public QuicFramerVisitorInterface {
@@ -249,6 +247,10 @@ class MockFramerVisitor : public QuicFramerVisitorInterface {
MOCK_METHOD1(OnPublicResetPacket, void(const QuicPublicResetPacket& header));
MOCK_METHOD1(OnVersionNegotiationPacket,
void(const QuicVersionNegotiationPacket& packet));
+ MOCK_METHOD3(OnRetryPacket,
+ void(QuicConnectionId original_connection_id,
+ QuicConnectionId new_connection_id,
+ QuicStringPiece retry_token));
// The constructor sets this up to return true by default.
MOCK_METHOD1(OnUnauthenticatedHeader, bool(const QuicPacketHeader& header));
// The constructor sets this up to return true by default.
@@ -278,9 +280,9 @@ class MockFramerVisitor : public QuicFramerVisitorInterface {
MOCK_METHOD1(OnPathChallengeFrame, bool(const QuicPathChallengeFrame& frame));
MOCK_METHOD1(OnPathResponseFrame, bool(const QuicPathResponseFrame& frame));
MOCK_METHOD1(OnGoAwayFrame, bool(const QuicGoAwayFrame& frame));
- MOCK_METHOD1(OnMaxStreamIdFrame, bool(const QuicMaxStreamIdFrame& frame));
- MOCK_METHOD1(OnStreamIdBlockedFrame,
- bool(const QuicStreamIdBlockedFrame& frame));
+ MOCK_METHOD1(OnMaxStreamsFrame, bool(const QuicMaxStreamsFrame& frame));
+ MOCK_METHOD1(OnStreamsBlockedFrame,
+ bool(const QuicStreamsBlockedFrame& frame));
MOCK_METHOD1(OnWindowUpdateFrame, bool(const QuicWindowUpdateFrame& frame));
MOCK_METHOD1(OnBlockedFrame, bool(const QuicBlockedFrame& frame));
MOCK_METHOD1(OnMessageFrame, bool(const QuicMessageFrame& frame));
@@ -301,6 +303,9 @@ class NoOpFramerVisitor : public QuicFramerVisitorInterface {
void OnPublicResetPacket(const QuicPublicResetPacket& packet) override {}
void OnVersionNegotiationPacket(
const QuicVersionNegotiationPacket& packet) override {}
+ void OnRetryPacket(QuicConnectionId original_connection_id,
+ QuicConnectionId new_connection_id,
+ QuicStringPiece retry_token) override {}
bool OnProtocolVersionMismatch(ParsedQuicVersion version,
PacketHeaderFormat form) override;
bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
@@ -329,8 +334,8 @@ class NoOpFramerVisitor : public QuicFramerVisitorInterface {
bool OnPathChallengeFrame(const QuicPathChallengeFrame& frame) override;
bool OnPathResponseFrame(const QuicPathResponseFrame& frame) override;
bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override;
- bool OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) override;
- bool OnStreamIdBlockedFrame(const QuicStreamIdBlockedFrame& frame) override;
+ bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override;
+ bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
bool OnBlockedFrame(const QuicBlockedFrame& frame) override;
bool OnMessageFrame(const QuicMessageFrame& frame) override;
@@ -361,6 +366,7 @@ class MockQuicConnectionVisitor : public QuicConnectionVisitorInterface {
ConnectionCloseSource source));
MOCK_METHOD0(OnWriteBlocked, void());
MOCK_METHOD0(OnCanWrite, void());
+ MOCK_METHOD0(SendProbingData, bool());
MOCK_METHOD1(OnCongestionWindowChange, void(QuicTime now));
MOCK_METHOD1(OnConnectionMigration, void(AddressChangeType type));
MOCK_METHOD0(OnPathDegrading, void());
@@ -377,9 +383,9 @@ class MockQuicConnectionVisitor : public QuicConnectionVisitorInterface {
MOCK_METHOD0(SendPing, void());
MOCK_CONST_METHOD0(AllowSelfAddressChange, bool());
MOCK_METHOD0(OnForwardProgressConfirmed, void());
- MOCK_METHOD1(OnMaxStreamIdFrame, bool(const QuicMaxStreamIdFrame& frame));
- MOCK_METHOD1(OnStreamIdBlockedFrame,
- bool(const QuicStreamIdBlockedFrame& frame));
+ MOCK_METHOD1(OnMaxStreamsFrame, bool(const QuicMaxStreamsFrame& frame));
+ MOCK_METHOD1(OnStreamsBlockedFrame,
+ bool(const QuicStreamsBlockedFrame& frame));
MOCK_METHOD1(OnStopSendingFrame, bool(const QuicStopSendingFrame& frame));
};
@@ -474,10 +480,8 @@ class MockQuicConnection : public QuicConnection {
void(QuicErrorCode error,
const std::string& details,
ConnectionCloseBehavior connection_close_behavior));
- MOCK_METHOD3(SendConnectionClosePacket,
- void(QuicErrorCode error,
- const std::string& details,
- AckBundling ack_mode));
+ MOCK_METHOD2(SendConnectionClosePacket,
+ void(QuicErrorCode error, const std::string& details));
MOCK_METHOD3(SendRstStream,
void(QuicStreamId id,
QuicRstStreamErrorCode error,
@@ -910,7 +914,8 @@ class MockSendAlgorithm : public SendAlgorithmInterface {
MOCK_CONST_METHOD0(ShouldSendProbingPacket, bool());
MOCK_CONST_METHOD0(GetSlowStartThreshold, QuicByteCount());
MOCK_CONST_METHOD0(GetCongestionControlType, CongestionControlType());
- MOCK_METHOD2(AdjustNetworkParameters, void(QuicBandwidth, QuicTime::Delta));
+ MOCK_METHOD3(AdjustNetworkParameters,
+ void(QuicBandwidth, QuicTime::Delta, bool));
MOCK_METHOD1(OnApplicationLimited, void(QuicByteCount));
};
@@ -1011,6 +1016,9 @@ class MockQuicConnectionDebugVisitor : public QuicConnectionDebugVisitor {
MOCK_METHOD1(OnVersionNegotiationPacket,
void(const QuicVersionNegotiationPacket&));
+
+ MOCK_METHOD3(OnRetryPacket,
+ void(QuicConnectionId, QuicConnectionId, QuicStringPiece));
};
class MockReceivedPacketManager : public QuicReceivedPacketManager {
@@ -1028,18 +1036,6 @@ class MockReceivedPacketManager : public QuicReceivedPacketManager {
MOCK_CONST_METHOD0(ack_frame_updated, bool(void));
};
-class MockConnectionCloseDelegate
- : public QuicConnectionCloseDelegateInterface {
- public:
- MockConnectionCloseDelegate();
- ~MockConnectionCloseDelegate() override;
-
- MOCK_METHOD3(OnUnrecoverableError,
- void(QuicErrorCode,
- const std::string&,
- ConnectionCloseSource source));
-};
-
class MockPacketCreatorDelegate : public QuicPacketCreator::DelegateInterface {
public:
MockPacketCreatorDelegate();
@@ -1050,10 +1046,7 @@ class MockPacketCreatorDelegate : public QuicPacketCreator::DelegateInterface {
MOCK_METHOD0(GetPacketBuffer, char*());
MOCK_METHOD1(OnSerializedPacket, void(SerializedPacket* packet));
- MOCK_METHOD3(OnUnrecoverableError,
- void(QuicErrorCode,
- const std::string&,
- ConnectionCloseSource source));
+ MOCK_METHOD2(OnUnrecoverableError, void(QuicErrorCode, const std::string&));
};
class MockSessionNotifier : public SessionNotifierInterface {
@@ -1073,7 +1066,6 @@ class MockSessionNotifier : public SessionNotifierInterface {
// Creates a client session for testing.
//
// server_id: The server id associated with this stream.
-// supports_stateless_rejects: Does this client support stateless rejects.
// connection_start_time: The time to set for the connection clock.
// Needed for strike-register nonce verification. The client
// connection_start_time should be synchronized witht the server
@@ -1088,7 +1080,6 @@ class MockSessionNotifier : public SessionNotifierInterface {
// session. The new object will be owned by the caller.
void CreateClientSessionForTest(
QuicServerId server_id,
- bool supports_stateless_rejects,
QuicTime::Delta connection_start_time,
const ParsedQuicVersionVector& supported_versions,
MockQuicConnectionHelper* helper,
@@ -1125,7 +1116,8 @@ void CreateServerSessionForTest(
// Verifies that the relative error of |actual| with respect to |expected| is
// no more than |margin|.
-
+// Please use EXPECT_APPROX_EQ, a wrapper around this function, for better error
+// report.
template <typename T>
void ExpectApproxEq(T expected, T actual, float relative_margin) {
// If |relative_margin| > 1 and T is an unsigned type, the comparison will
@@ -1135,10 +1127,16 @@ void ExpectApproxEq(T expected, T actual, float relative_margin) {
T absolute_margin = expected * relative_margin;
- EXPECT_GE(expected + absolute_margin, actual);
- EXPECT_LE(expected - absolute_margin, actual);
+ EXPECT_GE(expected + absolute_margin, actual) << "actual value too big";
+ EXPECT_LE(expected - absolute_margin, actual) << "actual value too small";
}
+#define EXPECT_APPROX_EQ(expected, actual, relative_margin) \
+ do { \
+ SCOPED_TRACE(testing::Message() << "relative_margin:" << relative_margin); \
+ quic::test::ExpectApproxEq(expected, actual, relative_margin); \
+ } while (0)
+
template <typename T>
QuicHeaderList AsHeaderList(const T& container) {
QuicHeaderList l;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils_test.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils_test.cc
index 79d2af8c908..31e48041758 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils_test.cc
@@ -4,7 +4,6 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
-#include "testing/gtest/include/gtest/gtest-spi.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
namespace quic {
@@ -23,29 +22,29 @@ TEST_F(QuicTestUtilsTest, ConnectionId) {
}
TEST_F(QuicTestUtilsTest, BasicApproxEq) {
- ExpectApproxEq(10, 10, 1e-6f);
- ExpectApproxEq(1000, 1001, 0.01f);
- EXPECT_NONFATAL_FAILURE(ExpectApproxEq(1000, 1100, 0.01f), "");
+ EXPECT_APPROX_EQ(10, 10, 1e-6f);
+ EXPECT_APPROX_EQ(1000, 1001, 0.01f);
+ EXPECT_NONFATAL_FAILURE(EXPECT_APPROX_EQ(1000, 1100, 0.01f), "");
- ExpectApproxEq(64, 31, 0.55f);
- EXPECT_NONFATAL_FAILURE(ExpectApproxEq(31, 64, 0.55f), "");
+ EXPECT_APPROX_EQ(64, 31, 0.55f);
+ EXPECT_NONFATAL_FAILURE(EXPECT_APPROX_EQ(31, 64, 0.55f), "");
}
TEST_F(QuicTestUtilsTest, QuicTimeDelta) {
- ExpectApproxEq(QuicTime::Delta::FromMicroseconds(1000),
- QuicTime::Delta::FromMicroseconds(1003), 0.01f);
+ EXPECT_APPROX_EQ(QuicTime::Delta::FromMicroseconds(1000),
+ QuicTime::Delta::FromMicroseconds(1003), 0.01f);
EXPECT_NONFATAL_FAILURE(
- ExpectApproxEq(QuicTime::Delta::FromMicroseconds(1000),
- QuicTime::Delta::FromMicroseconds(1200), 0.01f),
+ EXPECT_APPROX_EQ(QuicTime::Delta::FromMicroseconds(1000),
+ QuicTime::Delta::FromMicroseconds(1200), 0.01f),
"");
}
TEST_F(QuicTestUtilsTest, QuicBandwidth) {
- ExpectApproxEq(QuicBandwidth::FromBytesPerSecond(1000),
- QuicBandwidth::FromBitsPerSecond(8005), 0.01f);
+ EXPECT_APPROX_EQ(QuicBandwidth::FromBytesPerSecond(1000),
+ QuicBandwidth::FromBitsPerSecond(8005), 0.01f);
EXPECT_NONFATAL_FAILURE(
- ExpectApproxEq(QuicBandwidth::FromBytesPerSecond(1000),
- QuicBandwidth::FromBitsPerSecond(9005), 0.01f),
+ EXPECT_APPROX_EQ(QuicBandwidth::FromBytesPerSecond(1000),
+ QuicBandwidth::FromBitsPerSecond(9005), 0.01f),
"");
}
@@ -53,8 +52,27 @@ TEST_F(QuicTestUtilsTest, QuicBandwidth) {
TEST_F(QuicTestUtilsTest, SimpleRandomStability) {
SimpleRandom rng;
rng.set_seed(UINT64_C(0x1234567800010001));
- EXPECT_EQ(UINT64_C(14865409841904857791), rng.RandUint64());
- EXPECT_EQ(UINT64_C(12139094019410129741), rng.RandUint64());
+ EXPECT_EQ(UINT64_C(12589383305231984671), rng.RandUint64());
+ EXPECT_EQ(UINT64_C(17775425089941798664), rng.RandUint64());
+}
+
+// Ensure that the output of SimpleRandom does not depend on the size of the
+// read calls.
+TEST_F(QuicTestUtilsTest, SimpleRandomChunks) {
+ SimpleRandom rng;
+ std::string reference(16 * 1024, '\0');
+ rng.RandBytes(&reference[0], reference.size());
+
+ for (size_t chunk_size : {3, 4, 7, 4096}) {
+ rng.set_seed(0);
+ size_t chunks = reference.size() / chunk_size;
+ std::string buffer(chunks * chunk_size, '\0');
+ for (size_t i = 0; i < chunks; i++) {
+ rng.RandBytes(&buffer[i * chunk_size], chunk_size);
+ }
+ EXPECT_EQ(reference.substr(0, buffer.size()), buffer)
+ << "Failed for chunk_size = " << chunk_size;
+ }
}
} // namespace test
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 6a90a79a074..06a6718439b 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
@@ -39,6 +39,10 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
QuicMakeUnique<QuicVersionNegotiationPacket>((packet));
}
+ void OnRetryPacket(QuicConnectionId original_connection_id,
+ QuicConnectionId new_connection_id,
+ QuicStringPiece retry_token) override {}
+
bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override {
return true;
}
@@ -160,13 +164,13 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
goaway_frames_.push_back(frame);
return true;
}
- bool OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) override {
- max_stream_id_frames_.push_back(frame);
+ bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override {
+ max_streams_frames_.push_back(frame);
return true;
}
- bool OnStreamIdBlockedFrame(const QuicStreamIdBlockedFrame& frame) override {
- stream_id_blocked_frames_.push_back(frame);
+ bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override {
+ streams_blocked_frames_.push_back(frame);
return true;
}
@@ -206,12 +210,11 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
const std::vector<QuicGoAwayFrame>& goaway_frames() const {
return goaway_frames_;
}
- const std::vector<QuicMaxStreamIdFrame>& max_stream_id_frames() const {
- return max_stream_id_frames_;
+ const std::vector<QuicMaxStreamsFrame>& max_streams_frames() const {
+ return max_streams_frames_;
}
- const std::vector<QuicStreamIdBlockedFrame>& stream_id_blocked_frames()
- const {
- return stream_id_blocked_frames_;
+ const std::vector<QuicStreamsBlockedFrame>& streams_blocked_frames() const {
+ return streams_blocked_frames_;
}
const std::vector<QuicRstStreamFrame>& rst_stream_frames() const {
return rst_stream_frames_;
@@ -261,8 +264,8 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
std::vector<std::unique_ptr<QuicCryptoFrame>> crypto_frames_;
std::vector<QuicRstStreamFrame> rst_stream_frames_;
std::vector<QuicGoAwayFrame> goaway_frames_;
- std::vector<QuicStreamIdBlockedFrame> stream_id_blocked_frames_;
- std::vector<QuicMaxStreamIdFrame> max_stream_id_frames_;
+ std::vector<QuicStreamsBlockedFrame> streams_blocked_frames_;
+ std::vector<QuicMaxStreamsFrame> max_streams_frames_;
std::vector<QuicConnectionCloseFrame> connection_close_frames_;
std::vector<QuicStopSendingFrame> stop_sending_frames_;
std::vector<QuicPathChallengeFrame> path_challenge_frames_;
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 643821ab545..e72e0e1b811 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
@@ -5,6 +5,7 @@
#include "net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
@@ -71,7 +72,7 @@ void SimpleSessionNotifier::OnStreamDataConsumed(QuicStreamId id,
QuicByteCount data_length,
bool fin) {
StreamState& state = stream_map_.find(id)->second;
- if (id == QuicUtils::GetCryptoStreamId(connection_->transport_version()) &&
+ if (QuicUtils::IsCryptoStreamId(connection_->transport_version(), id) &&
data_length > 0) {
crypto_bytes_transferred_[connection_->encryption_level()].Add(
offset, offset + data_length);
@@ -126,8 +127,11 @@ void SimpleSessionNotifier::WriteOrBufferPing() {
}
void SimpleSessionNotifier::NeuterUnencryptedData() {
+ // TODO(nharper): Handle CRYPTO frame case.
+ if (QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ return;
+ }
for (const auto& interval : crypto_bytes_transferred_[ENCRYPTION_INITIAL]) {
- // TODO(nharper): Handle CRYPTO frame case.
QuicStreamFrame stream_frame(
QuicUtils::GetCryptoStreamId(connection_->transport_version()), false,
interval.min(), interval.max() - interval.min());
@@ -145,7 +149,6 @@ void SimpleSessionNotifier::OnCanWrite() {
return;
}
// Write new data.
- // TODO(nharper): Write CRYPTO frames.
for (const auto& pair : stream_map_) {
const auto& state = pair.second;
if (!StreamHasBufferedData(pair.first)) {
@@ -319,8 +322,8 @@ void SimpleSessionNotifier::RetransmitFrames(const QuicFrames& frames,
EncryptionLevel retransmission_encryption_level =
connection_->encryption_level();
EncryptionLevel current_encryption_level = connection_->encryption_level();
- if (frame.stream_frame.stream_id ==
- QuicUtils::GetCryptoStreamId(connection_->transport_version())) {
+ if (QuicUtils::IsCryptoStreamId(connection_->transport_version(),
+ frame.stream_frame.stream_id)) {
for (size_t i = 0; i < NUM_ENCRYPTION_LEVELS; ++i) {
if (retransmission.Intersects(crypto_bytes_transferred_[i])) {
retransmission_encryption_level = static_cast<EncryptionLevel>(i);
@@ -338,8 +341,8 @@ void SimpleSessionNotifier::RetransmitFrames(const QuicFrames& frames,
const bool can_bundle_fin =
retransmit_fin &&
(retransmission_offset + retransmission_length == state.bytes_sent);
- if (frame.stream_frame.stream_id ==
- QuicUtils::GetCryptoStreamId(connection_->transport_version())) {
+ if (QuicUtils::IsCryptoStreamId(connection_->transport_version(),
+ frame.stream_frame.stream_id)) {
// Set appropriate encryption level for crypto stream.
connection_->SetDefaultEncryptionLevel(retransmission_encryption_level);
}
@@ -355,8 +358,8 @@ void SimpleSessionNotifier::RetransmitFrames(const QuicFrames& frames,
if (can_bundle_fin) {
retransmit_fin = !consumed.fin_consumed;
}
- if (frame.stream_frame.stream_id ==
- QuicUtils::GetCryptoStreamId(connection_->transport_version())) {
+ if (QuicUtils::IsCryptoStreamId(connection_->transport_version(),
+ frame.stream_frame.stream_id)) {
// Restore encryption level.
connection_->SetDefaultEncryptionLevel(current_encryption_level);
}
@@ -496,7 +499,36 @@ bool SimpleSessionNotifier::RetransmitLostControlFrames() {
}
bool SimpleSessionNotifier::RetransmitLostCryptoData() {
- // TODO(nharper): Handle CRYPTO frame case.
+ if (QuicVersionUsesCryptoFrames(connection_->transport_version())) {
+ for (EncryptionLevel level :
+ {ENCRYPTION_INITIAL, ENCRYPTION_HANDSHAKE, ENCRYPTION_ZERO_RTT,
+ ENCRYPTION_FORWARD_SECURE}) {
+ auto& state = crypto_state_[level];
+ while (!state.pending_retransmissions.Empty()) {
+ connection_->SetTransmissionType(HANDSHAKE_RETRANSMISSION);
+ EncryptionLevel current_encryption_level =
+ connection_->encryption_level();
+ connection_->SetDefaultEncryptionLevel(level);
+ QuicIntervalSet<QuicStreamOffset> retransmission(
+ state.pending_retransmissions.begin()->min(),
+ state.pending_retransmissions.begin()->max());
+ retransmission.Intersection(crypto_bytes_transferred_[level]);
+ QuicStreamOffset retransmission_offset = retransmission.begin()->min();
+ QuicByteCount retransmission_length =
+ retransmission.begin()->max() - retransmission.begin()->min();
+ size_t bytes_consumed = connection_->SendCryptoData(
+ level, retransmission_length, retransmission_offset);
+ // Restore encryption level.
+ connection_->SetDefaultEncryptionLevel(current_encryption_level);
+ state.pending_retransmissions.Difference(
+ retransmission_offset, retransmission_offset + bytes_consumed);
+ if (bytes_consumed < retransmission_length) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
if (!QuicContainsKey(stream_map_, QuicUtils::GetCryptoStreamId(
connection_->transport_version()))) {
return true;
@@ -551,7 +583,7 @@ bool SimpleSessionNotifier::RetransmitLostStreamData() {
connection_->SendStreamData(pair.first, 0, state.bytes_sent, FIN);
state.fin_lost = !consumed.fin_consumed;
if (state.fin_lost) {
- DLOG(INFO) << "Connection is write blocked";
+ QUIC_DLOG(INFO) << "Connection is write blocked";
return false;
}
} else {
@@ -573,7 +605,7 @@ bool SimpleSessionNotifier::RetransmitLostStreamData() {
}
if (length > consumed.bytes_consumed ||
(can_bundle_fin && !consumed.fin_consumed)) {
- DVLOG(1) << "Connection is write blocked";
+ QUIC_DVLOG(1) << "Connection is write blocked";
break;
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h b/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h
index 17616b7693f..e7d4fdc9b50 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h
@@ -5,9 +5,9 @@
#ifndef QUICHE_QUIC_TEST_TOOLS_SIMPLE_SESSION_NOTIFIER_H_
#define QUICHE_QUIC_TEST_TOOLS_SIMPLE_SESSION_NOTIFIER_H_
-#include "testing/gmock/include/gmock/gmock.h"
#include "net/third_party/quiche/src/quic/core/quic_interval_set.h"
#include "net/third_party/quiche/src/quic/core/session_notifier_interface.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
namespace quic {
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 53712fd5395..d2aad9f087e 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
@@ -4,10 +4,12 @@
#include "net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h"
+#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/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/simple_data_producer.h"
using testing::_;
using testing::InSequence;
@@ -126,6 +128,9 @@ TEST_F(SimpleSessionNotifierTest, WriteOrBufferPing) {
}
TEST_F(SimpleSessionNotifierTest, NeuterUnencryptedData) {
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ return;
+ }
InSequence s;
// Send crypto data [0, 1024) in ENCRYPTION_INITIAL.
connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
@@ -159,6 +164,9 @@ TEST_F(SimpleSessionNotifierTest, NeuterUnencryptedData) {
}
TEST_F(SimpleSessionNotifierTest, OnCanWrite) {
+ if (QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ return;
+ }
InSequence s;
// Send crypto data [0, 1024) in ENCRYPTION_INITIAL.
connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
@@ -221,6 +229,72 @@ TEST_F(SimpleSessionNotifierTest, OnCanWrite) {
EXPECT_FALSE(notifier_.WillingToWrite());
}
+TEST_F(SimpleSessionNotifierTest, OnCanWriteCryptoFrames) {
+ if (!QuicVersionUsesCryptoFrames(connection_.transport_version())) {
+ return;
+ }
+ SimpleDataProducer producer;
+ connection_.SetDataProducer(&producer);
+ InSequence s;
+ // Send crypto data [0, 1024) in ENCRYPTION_INITIAL.
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
+ EXPECT_CALL(connection_, SendCryptoData(ENCRYPTION_INITIAL, 1024, 0))
+ .WillOnce(Invoke(&connection_,
+ &MockQuicConnection::QuicConnection_SendCryptoData));
+ EXPECT_CALL(connection_, CloseConnection(QUIC_PACKET_WRITE_ERROR, _, _));
+ producer.SaveCryptoData(ENCRYPTION_INITIAL, 0, std::string(1024, 'a'));
+ producer.SaveCryptoData(ENCRYPTION_INITIAL, 500, std::string(524, 'a'));
+ notifier_.WriteCryptoData(ENCRYPTION_INITIAL, 1024, 0);
+ // Send crypto data [1024, 2048) in ENCRYPTION_ZERO_RTT.
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ connection_.SetEncrypter(ENCRYPTION_ZERO_RTT, QuicMakeUnique<NullEncrypter>(
+ Perspective::IS_CLIENT));
+ EXPECT_CALL(connection_, SendCryptoData(ENCRYPTION_ZERO_RTT, 1024, 0))
+ .WillOnce(Invoke(&connection_,
+ &MockQuicConnection::QuicConnection_SendCryptoData));
+ producer.SaveCryptoData(ENCRYPTION_ZERO_RTT, 0, std::string(1024, 'a'));
+ notifier_.WriteCryptoData(ENCRYPTION_ZERO_RTT, 1024, 0);
+ // Send stream 3 [0, 1024) and connection is blocked.
+ EXPECT_CALL(connection_, SendStreamData(3, 1024, 0, FIN))
+ .WillOnce(Return(QuicConsumedData(512, false)));
+ notifier_.WriteOrBufferData(3, 1024, FIN);
+ // Send stream 5 [0, 1024).
+ EXPECT_CALL(connection_, SendStreamData(5, _, _, _)).Times(0);
+ notifier_.WriteOrBufferData(5, 1024, NO_FIN);
+ // Reset stream 5 with error.
+ EXPECT_CALL(connection_, SendControlFrame(_)).Times(0);
+ notifier_.WriteOrBufferRstStream(5, QUIC_ERROR_PROCESSING_STREAM, 1024);
+
+ // Lost crypto data [500, 1500) and stream 3 [0, 512).
+ QuicCryptoFrame crypto_frame1(ENCRYPTION_INITIAL, 500, 524);
+ QuicCryptoFrame crypto_frame2(ENCRYPTION_ZERO_RTT, 0, 476);
+ QuicStreamFrame stream3_frame(3, false, 0, 512);
+ notifier_.OnFrameLost(QuicFrame(&crypto_frame1));
+ notifier_.OnFrameLost(QuicFrame(&crypto_frame2));
+ notifier_.OnFrameLost(QuicFrame(stream3_frame));
+
+ // Connection becomes writable.
+ // Lost crypto data gets retransmitted as [500, 1024) and [1024, 1500), as
+ // they are in different encryption levels.
+ EXPECT_CALL(connection_, SendCryptoData(ENCRYPTION_INITIAL, 524, 500))
+ .WillOnce(Invoke(&connection_,
+ &MockQuicConnection::QuicConnection_SendCryptoData));
+ EXPECT_CALL(connection_, SendCryptoData(ENCRYPTION_ZERO_RTT, 476, 0))
+ .WillOnce(Invoke(&connection_,
+ &MockQuicConnection::QuicConnection_SendCryptoData));
+ // Lost stream 3 data gets retransmitted.
+ EXPECT_CALL(connection_, SendStreamData(3, 512, 0, NO_FIN))
+ .WillOnce(Return(QuicConsumedData(512, false)));
+ // Buffered control frames get sent.
+ EXPECT_CALL(connection_, SendControlFrame(_))
+ .WillOnce(Invoke(this, &SimpleSessionNotifierTest::ControlFrameConsumed));
+ // Buffered stream 3 data [512, 1024) gets sent.
+ EXPECT_CALL(connection_, SendStreamData(3, 512, 512, FIN))
+ .WillOnce(Return(QuicConsumedData(512, true)));
+ notifier_.OnCanWrite();
+ EXPECT_FALSE(notifier_.WillingToWrite());
+}
+
TEST_F(SimpleSessionNotifierTest, RetransmitFrames) {
InSequence s;
// Send stream 3 data [0, 10) and fin.
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/README.md b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/README.md
new file mode 100644
index 00000000000..8582962adee
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/README.md
@@ -0,0 +1,99 @@
+# QUIC network simulator
+
+This directory contains a discrete event network simulator which QUIC code uses
+for testing congestion control and other transmission control code that requires
+a network simulation for tests on QuicConnection level of abstraction.
+
+## Actors
+
+The core of the simulator is the Simulator class, which maintains a virtual
+clock and an event queue. Any object in a simulation that needs to schedule
+events has to subclass Actor. Subclassing Actor involves:
+
+1. Calling the `Actor::Actor(Simulator*, std::string)` constructor to establish
+ the name of the object and the simulator it is associated with.
+2. Calling `Schedule(QuicTime)` to schedule the time at which `Act()` method is
+ called. `Schedule` will only cause the object to be rescheduled if the time
+ for which it is currently scheduled is later than the new time.
+3. Implementing `Act()` method with the relevant logic. The actor will be
+ removed from the event queue right before `Act()` is called.
+
+Here is a simple example of an object that outputs simulation time into the log
+every 100 ms.
+
+```c++
+class LogClock : public Actor {
+ public:
+ LogClock(Simulator* simulator, std::string name) : Actor(simulator, name) {
+ Schedule(clock_->Now());
+ }
+ ~LogClock() override {}
+
+ void Act() override {
+ QUIC_LOG(INFO) << "The current time is "
+ << clock_->Now().ToDebuggingValue();
+ Schedule(clock_->Now() + QuicTime::Delta::FromMilliseconds(100));
+ }
+};
+```
+
+A QuicAlarm object can be used to schedule events in the simulation using
+`Simulator::GetAlarmFactory()`.
+
+## Ports
+
+The simulated network transfers packets, which are modelled as an instance of
+struct `Packet`. A packet consists of source and destination address (which are
+just plain strings), a transmission timestamp and the UDP-layer payload.
+
+The simulation uses the push model: any object that wishes to transfer a packet
+to another component in the simulation has to explicitly do it itself. Any
+object that can accept a packet is called a *port*. There are two types of
+ports: unconstrained ports, which can always accept packets, and constrained
+ports, which signal when they can accept a new packet.
+
+An endpoint is an object that is connected to the network and can both receive
+and send packets. In our model, the endpoint always receives packets as an
+unconstrained port (*RX port*), and always writes packets to a constrained port
+(*TX port*).
+
+## Links
+
+The `SymmetricLink` class models a symmetric duplex links with finite bandwidth
+and propagation delay. It consists of a pair of identical `OneWayLink`s, which
+accept packets as a constrained port (where constrain comes from the finiteness
+of bandwidth) and outputs them into an unconstrained port. Two endpoints
+connected via a `SymmetricLink` look like this:
+
+```none
+ Endpoint A Endpoint B
++-----------+ SymmetricLink +-----------+
+| | +------------------------------+ | |
+| +---------+ | +------------------------+ | +---------+ |
+| | RX port <-----| OneWayLink *<-----| TX port | |
+| +---------+ | +------------------------+ | +---------+ |
+| | | | | |
+| +---------+ | +------------------------+ | +---------+ |
+| | TX port |----->* OneWayLink |-----> RX port | |
+| +---------+ | +------------------------+ | +---------+ |
+| | +------------------------------+ | |
++-----------+ +-----------+
+
+ ( -->* denotes constrained port)
+```
+
+In most common scenario, one of the endpoints is going to be a QUIC endpoint,
+and another is going to be a switch port.
+
+## Other objects
+
+Besides `SymmetricLink`, the simulator provides the following objects:
+
+* `Queue` allows to convert a constrained port into an unconstrained one by
+ buffering packets upon arrival. The queue has a finite size, and once the
+ queue is full, the packets are silently dropped.
+* `Switch` simulates a multi-port learning switch with a fixed queue for each
+ output port.
+* `QuicEndpoint` allows QuicConnection to be run over the simulated network.
+* `QuicEndpointMultiplexer` allows multiple connections to share the same
+ network endpoint.
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.cc
index a016b89f937..110933e1379 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.cc
@@ -39,9 +39,14 @@ void OneWayLink::AcceptPacket(std::unique_ptr<Packet> packet) {
QuicTime::Delta transfer_time = bandwidth_.TransferTime(packet->size);
next_write_at_ = clock_->Now() + transfer_time;
- packets_in_transit_.emplace(
+ packets_in_transit_.emplace_back(
std::move(packet),
- next_write_at_ + propagation_delay_ + GetRandomDelay(transfer_time));
+ // Ensure that packets are delivered in order.
+ std::max(
+ next_write_at_ + propagation_delay_ + GetRandomDelay(transfer_time),
+ packets_in_transit_.empty()
+ ? QuicTime::Zero()
+ : packets_in_transit_.back().dequeue_time));
ScheduleNextPacketDeparture();
}
@@ -59,7 +64,7 @@ void OneWayLink::Act() {
DCHECK(packets_in_transit_.front().dequeue_time >= clock_->Now());
sink_->AcceptPacket(std::move(packets_in_transit_.front().packet));
- packets_in_transit_.pop();
+ packets_in_transit_.pop_front();
ScheduleNextPacketDeparture();
}
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.h b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.h
index 103afa0998c..531eff67cf4 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/link.h
@@ -34,6 +34,13 @@ class OneWayLink : public Actor, public ConstrainedPortInterface {
inline QuicBandwidth bandwidth() const { return bandwidth_; }
+ protected:
+ // Get the value of a random delay imposed on each packet. By default, this
+ // is a short random delay in order to avoid artifical synchronization
+ // artifacts during the simulation. Subclasses may override this behavior
+ // (for example, to provide a random component of delay).
+ virtual QuicTime::Delta GetRandomDelay(QuicTime::Delta transfer_time);
+
private:
struct QueuedPacket {
std::unique_ptr<Packet> packet;
@@ -48,12 +55,8 @@ class OneWayLink : public Actor, public ConstrainedPortInterface {
// packets on the link.
void ScheduleNextPacketDeparture();
- // Get the value of a random delay imposed on each packet in order to avoid
- // artifical synchronization artifacts during the simulation.
- QuicTime::Delta GetRandomDelay(QuicTime::Delta transfer_time);
-
UnconstrainedPortInterface* sink_;
- QuicQueue<QueuedPacket> packets_in_transit_;
+ QuicDeque<QueuedPacket> packets_in_transit_;
const QuicBandwidth bandwidth_;
const QuicTime::Delta propagation_delay_;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.cc
index 9e5c3fab604..043eae99e21 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
@@ -113,7 +113,7 @@ QuicEndpoint::QuicEndpoint(Simulator* simulator,
CryptoHandshakeMessage peer_hello;
peer_hello.SetValue(kICSL,
static_cast<uint32_t>(kMaximumIdleTimeoutSecs - 1));
- peer_hello.SetValue(kMIDS,
+ peer_hello.SetValue(kMIBS,
static_cast<uint32_t>(kDefaultMaxStreamsPerConnection));
QuicConfig config;
QuicErrorCode error_code = config.ProcessPeerHello(
@@ -238,6 +238,15 @@ void QuicEndpoint::OnCanWrite() {
}
WriteStreamData();
}
+
+bool QuicEndpoint::SendProbingData() {
+ if (connection()->sent_packet_manager().MaybeRetransmitOldestPacket(
+ PROBING_RETRANSMISSION)) {
+ return true;
+ }
+ return false;
+}
+
bool QuicEndpoint::WillingAndAbleToWrite() const {
if (notifier_ != nullptr) {
return notifier_->WillingToWrite();
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 955ac8fcb64..8bbdbd7c5e2 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
@@ -82,6 +82,7 @@ class QuicEndpoint : public Endpoint,
void OnStreamFrame(const QuicStreamFrame& frame) override;
void OnCryptoFrame(const QuicCryptoFrame& frame) override;
void OnCanWrite() override;
+ bool SendProbingData() override;
bool WillingAndAbleToWrite() const override;
bool HasPendingHandshake() const override;
bool ShouldKeepConnectionAlive() const override;
@@ -107,10 +108,10 @@ class QuicEndpoint : public Endpoint,
void SendPing() override {}
bool AllowSelfAddressChange() const override;
void OnForwardProgressConfirmed() override {}
- bool OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) override {
+ bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override {
return true;
}
- bool OnStreamIdBlockedFrame(const QuicStreamIdBlockedFrame& frame) override {
+ bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override {
return true;
}
bool OnStopSendingFrame(const QuicStopSendingFrame& frame) override {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator_test.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator_test.cc
index 33ad564324e..1e7a8ce53a0 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/simulator_test.cc
@@ -224,7 +224,7 @@ TEST_F(SimulatorTest, DirectLinkSaturation) {
const QuicTime end_time = simulator.GetClock()->Now();
const QuicBandwidth observed_bandwidth = QuicBandwidth::FromBytesAndTimeDelta(
saturator_a.bytes_transmitted(), end_time - start_time);
- test::ExpectApproxEq(link.bandwidth(), observed_bandwidth, 0.01f);
+ EXPECT_APPROX_EQ(link.bandwidth(), observed_bandwidth, 0.01f);
}
// Accepts packets and stores them internally.
@@ -683,15 +683,15 @@ TEST_F(SimulatorTest, TrafficPolicer) {
// Ensure we've transmitted the amount of data we expected.
for (auto* saturator : {&saturator1, &saturator2}) {
- test::ExpectApproxEq(bandwidth * simulation_time,
- saturator->bytes_transmitted(), 0.01f);
+ EXPECT_APPROX_EQ(bandwidth * simulation_time,
+ saturator->bytes_transmitted(), 0.01f);
}
// Check that only one direction is throttled.
- test::ExpectApproxEq(saturator1.bytes_transmitted() / 4,
- saturator2.counter()->bytes(), 0.1f);
- test::ExpectApproxEq(saturator2.bytes_transmitted(),
- saturator1.counter()->bytes(), 0.1f);
+ EXPECT_APPROX_EQ(saturator1.bytes_transmitted() / 4,
+ saturator2.counter()->bytes(), 0.1f);
+ EXPECT_APPROX_EQ(saturator2.bytes_transmitted(),
+ saturator1.counter()->bytes(), 0.1f);
}
// Ensure that a larger burst is allowed when the policed saturator exits
@@ -740,14 +740,14 @@ TEST_F(SimulatorTest, TrafficPolicerBurst) {
simulator.RunFor(2 * base_propagation_delay);
// Expect the burst to pass without losses.
- test::ExpectApproxEq(saturator1.bytes_transmitted(),
- saturator2.counter()->bytes(), 0.1f);
+ EXPECT_APPROX_EQ(saturator1.bytes_transmitted(),
+ saturator2.counter()->bytes(), 0.1f);
// Expect subsequent traffic to be policed.
saturator1.Resume();
simulator.RunFor(QuicTime::Delta::FromSeconds(10));
- test::ExpectApproxEq(saturator1.bytes_transmitted() / 4,
- saturator2.counter()->bytes(), 0.1f);
+ EXPECT_APPROX_EQ(saturator1.bytes_transmitted() / 4,
+ saturator2.counter()->bytes(), 0.1f);
}
// Test that the packet aggregation support in queues work.
diff --git a/chromium/net/third_party/quiche/src/quic/tools/fake_proof_verifier.h b/chromium/net/third_party/quiche/src/quic/tools/fake_proof_verifier.h
new file mode 100644
index 00000000000..ffeb6e95e72
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/tools/fake_proof_verifier.h
@@ -0,0 +1,49 @@
+// 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_TOOLS_FAKE_PROOF_VERIFIER_H_
+#define QUICHE_QUIC_TOOLS_FAKE_PROOF_VERIFIER_H_
+
+#include "net/third_party/quiche/src/quic/core/crypto/proof_verifier.h"
+
+namespace quic {
+
+// ProofVerifier implementation which always returns success.
+class FakeProofVerifier : public ProofVerifier {
+ public:
+ ~FakeProofVerifier() override {}
+ QuicAsyncStatus VerifyProof(
+ const std::string& /*hostname*/,
+ const uint16_t /*port*/,
+ const std::string& /*server_config*/,
+ QuicTransportVersion /*quic_version*/,
+ QuicStringPiece /*chlo_hash*/,
+ const std::vector<std::string>& /*certs*/,
+ const std::string& /*cert_sct*/,
+ const std::string& /*signature*/,
+ const ProofVerifyContext* /*context*/,
+ std::string* /*error_details*/,
+ std::unique_ptr<ProofVerifyDetails>* /*details*/,
+ std::unique_ptr<ProofVerifierCallback> /*callback*/) override {
+ return QUIC_SUCCESS;
+ }
+ QuicAsyncStatus VerifyCertChain(
+ const std::string& /*hostname*/,
+ const std::vector<std::string>& /*certs*/,
+ const std::string& /*ocsp_response*/,
+ const std::string& /*cert_sct*/,
+ const ProofVerifyContext* /*context*/,
+ std::string* /*error_details*/,
+ std::unique_ptr<ProofVerifyDetails>* /*details*/,
+ std::unique_ptr<ProofVerifierCallback> /*callback*/) override {
+ return QUIC_SUCCESS;
+ }
+ std::unique_ptr<ProofVerifyContext> CreateDefaultContext() override {
+ return nullptr;
+ }
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_TOOLS_FAKE_PROOF_VERIFIER_H_
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 b736c71aef4..e7fe6b4830e 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
@@ -85,7 +85,7 @@ std::unique_ptr<QuicSession> QuicClient::CreateQuicClientSession(
QuicConnection* connection) {
return QuicMakeUnique<QuicSimpleClientSession>(
*config(), supported_versions, connection, server_id(), crypto_config(),
- push_promise_index(), drop_response_body_);
+ push_promise_index(), drop_response_body());
}
QuicClientEpollNetworkHelper* QuicClient::epoll_network_helper() {
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 b84c597969a..0e708ec2835 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
@@ -67,13 +67,8 @@ class QuicClient : public QuicSpdyClientBase {
QuicClientEpollNetworkHelper* epoll_network_helper();
const QuicClientEpollNetworkHelper* epoll_network_helper() const;
- void set_drop_response_body(bool drop_response_body) {
- drop_response_body_ = drop_response_body;
- }
-
private:
friend class test::QuicClientPeer;
- bool drop_response_body_ = false;
};
} // namespace quic
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 db0503c5f9b..b746ba5f6dc 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
@@ -54,11 +54,11 @@ bool QuicClientBase::Initialize() {
const uint32_t kSessionMaxRecvWindowSize = 15 * 1024 * 1024; // 15 MB
const uint32_t kStreamMaxRecvWindowSize = 6 * 1024 * 1024; // 6 MB
if (config()->GetInitialStreamFlowControlWindowToSend() ==
- kMinimumFlowControlSendWindow) {
+ kDefaultFlowControlSendWindow) {
config()->SetInitialStreamFlowControlWindowToSend(kStreamMaxRecvWindowSize);
}
if (config()->GetInitialSessionFlowControlWindowToSend() ==
- kMinimumFlowControlSendWindow) {
+ kDefaultFlowControlSendWindow) {
config()->SetInitialSessionFlowControlWindowToSend(
kSessionMaxRecvWindowSize);
}
@@ -81,11 +81,6 @@ bool QuicClientBase::Connect() {
while (EncryptionBeingEstablished()) {
WaitForEvents();
}
- if (GetQuicReloadableFlag(enable_quic_stateless_reject_support) &&
- connected()) {
- // Resend any previously queued data.
- ResendSavedData();
- }
ParsedQuicVersion version = UnsupportedQuicVersion();
if (session() != nullptr &&
session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT &&
@@ -181,16 +176,13 @@ bool QuicClientBase::WaitForEvents() {
DCHECK(session() != nullptr);
ParsedQuicVersion version = UnsupportedQuicVersion();
if (!connected() &&
- (session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT ||
- CanReconnectWithDifferentVersion(&version))) {
- if (session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
- DCHECK(GetQuicReloadableFlag(enable_quic_stateless_reject_support));
- QUIC_DLOG(INFO) << "Detected stateless reject while waiting for events. "
- << "Attempting to reconnect.";
- } else {
- QUIC_DLOG(INFO) << "Can reconnect with version: " << version
- << ", attempting to reconnect.";
- }
+
+ CanReconnectWithDifferentVersion(&version)) {
+ DCHECK_NE(session()->error(), QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT);
+
+ QUIC_DLOG(INFO) << "Can reconnect with version: " << version
+ << ", attempting to reconnect.";
+
Connect();
}
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 6ad326eb4dc..0cc4d71ff78 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
@@ -102,7 +102,7 @@ class QuicClientBase {
// Wait for events until the handshake is confirmed.
// Returns true if the crypto handshake succeeds, false otherwise.
- bool WaitForCryptoHandshakeConfirmed() QUIC_MUST_USE_RESULT;
+ QUIC_MUST_USE_RESULT bool WaitForCryptoHandshakeConfirmed();
// Wait up to 50ms, and handle any events which occur.
// Returns true if there are any outstanding requests.
@@ -131,13 +131,6 @@ class QuicClientBase {
crypto_config_.set_user_agent_id(user_agent_id);
}
- // SetChannelIDSource sets a ChannelIDSource that will be called, when the
- // server supports channel IDs, to obtain a channel ID for signing a message
- // proving possession of the channel ID.
- void SetChannelIDSource(std::unique_ptr<ChannelIDSource> source) {
- crypto_config_.SetChannelIDSource(std::move(source));
- }
-
const ParsedQuicVersionVector& supported_versions() const {
return supported_versions_;
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_client_bin.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_client_bin.cc
index ee8262f751f..06760ce4a70 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_client_bin.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_client_bin.cc
@@ -34,175 +34,19 @@
//
// Try to connect to a host which does not speak QUIC:
// quic_client www.example.com
-
-#include <netdb.h>
-#include <sys/socket.h>
-#include <sys/types.h>
+//
+// This tool is available as a built binary at:
+// /google/data/ro/teams/quic/tools/quic_client
+// After submitting changes to this file, you will need to follow the
+// instructions at go/quic_client_binary_update
#include <iostream>
#include <memory>
#include <string>
-#include <vector>
-#include "net/third_party/quiche/src/quic/core/quic_packets.h"
-#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
-#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/core/quic_versions.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_default_proof_providers.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_system_event_loop.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
-#include "net/third_party/quiche/src/quic/tools/quic_client.h"
-#include "net/third_party/quiche/src/quic/tools/quic_url.h"
-
-namespace {
-
-using quic::QuicSocketAddress;
-using quic::QuicStringPiece;
-using quic::QuicTextUtils;
-using quic::QuicUrl;
-
-class FakeProofVerifier : public quic::ProofVerifier {
- public:
- ~FakeProofVerifier() override {}
- quic::QuicAsyncStatus VerifyProof(
- const std::string& /*hostname*/,
- const uint16_t /*port*/,
- const std::string& /*server_config*/,
- quic::QuicTransportVersion /*quic_version*/,
- quic::QuicStringPiece /*chlo_hash*/,
- const std::vector<std::string>& /*certs*/,
- const std::string& /*cert_sct*/,
- const std::string& /*signature*/,
- const quic::ProofVerifyContext* /*context*/,
- std::string* /*error_details*/,
- std::unique_ptr<quic::ProofVerifyDetails>* /*details*/,
- std::unique_ptr<quic::ProofVerifierCallback> /*callback*/) override {
- return quic::QUIC_SUCCESS;
- }
- quic::QuicAsyncStatus VerifyCertChain(
- const std::string& /*hostname*/,
- const std::vector<std::string>& /*certs*/,
- const quic::ProofVerifyContext* /*context*/,
- std::string* /*error_details*/,
- std::unique_ptr<quic::ProofVerifyDetails>* /*details*/,
- std::unique_ptr<quic::ProofVerifierCallback> /*callback*/) override {
- return quic::QUIC_SUCCESS;
- }
- std::unique_ptr<quic::ProofVerifyContext> CreateDefaultContext() override {
- return nullptr;
- }
-};
-
-QuicSocketAddress LookupAddress(std::string host, std::string port) {
- addrinfo hint;
- memset(&hint, 0, sizeof(hint));
- hint.ai_protocol = IPPROTO_UDP;
-
- addrinfo* info_list = nullptr;
- int result = getaddrinfo(host.c_str(), port.c_str(), &hint, &info_list);
- if (result != 0) {
- QUIC_LOG(ERROR) << "Failed to look up " << host << ": "
- << gai_strerror(result);
- return QuicSocketAddress();
- }
-
- CHECK(info_list != nullptr);
- std::unique_ptr<addrinfo, void (*)(addrinfo*)> info_list_owned(info_list,
- freeaddrinfo);
- return QuicSocketAddress(*info_list->ai_addr);
-}
-
-} // namespace
-
-DEFINE_QUIC_COMMAND_LINE_FLAG(
- std::string,
- host,
- "",
- "The IP or hostname to connect to. If not provided, the host "
- "will be derived from the provided URL.");
-
-DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t, port, 0, "The port to connect to.");
-
-DEFINE_QUIC_COMMAND_LINE_FLAG(std::string,
- body,
- "",
- "If set, send a POST with this body.");
-
-DEFINE_QUIC_COMMAND_LINE_FLAG(
- std::string,
- body_hex,
- "",
- "If set, contents are converted from hex to ascii, before "
- "sending as body of a POST. e.g. --body_hex=\"68656c6c6f\"");
-
-DEFINE_QUIC_COMMAND_LINE_FLAG(
- std::string,
- headers,
- "",
- "A semicolon separated list of key:value pairs to "
- "add to request headers.");
-
-DEFINE_QUIC_COMMAND_LINE_FLAG(bool,
- quiet,
- false,
- "Set to true for a quieter output experience.");
-
-DEFINE_QUIC_COMMAND_LINE_FLAG(
- std::string,
- quic_version,
- "",
- "QUIC version to speak, e.g. 21. If not set, then all available "
- "versions are offered in the handshake. Also supports wire versions "
- "such as Q043 or T099.");
-
-DEFINE_QUIC_COMMAND_LINE_FLAG(
- int32_t,
- quic_ietf_draft,
- 0,
- "QUIC IETF draft number to use over the wire, e.g. 18. "
- "By default this sets quic_version to T099. "
- "This also enables required internal QUIC flags.");
-
-DEFINE_QUIC_COMMAND_LINE_FLAG(
- bool,
- version_mismatch_ok,
- false,
- "If true, a version mismatch in the handshake is not considered a "
- "failure. Useful for probing a server to determine if it speaks "
- "any version of QUIC.");
-
-DEFINE_QUIC_COMMAND_LINE_FLAG(
- bool,
- redirect_is_success,
- true,
- "If true, an HTTP response code of 3xx is considered to be a "
- "successful response, otherwise a failure.");
-
-DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t,
- initial_mtu,
- 0,
- "Initial MTU of the connection.");
-
-DEFINE_QUIC_COMMAND_LINE_FLAG(
- int32_t,
- num_requests,
- 1,
- "How many sequential requests to make on a single connection.");
-
-DEFINE_QUIC_COMMAND_LINE_FLAG(bool,
- disable_certificate_verification,
- false,
- "If true, don't verify the server certificate.");
-
-DEFINE_QUIC_COMMAND_LINE_FLAG(
- bool,
- drop_response_body,
- false,
- "If true, drop response body immediately after it is received.");
+#include "net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.h"
+#include "net/third_party/quiche/src/quic/tools/quic_toy_client.h"
int main(int argc, char* argv[]) {
QuicSystemEventLoop event_loop("quic_client");
@@ -216,188 +60,7 @@ int main(int argc, char* argv[]) {
exit(0);
}
- QuicUrl url(urls[0], "https");
- std::string host = GetQuicFlag(FLAGS_host);
- if (host.empty()) {
- host = url.host();
- }
- int port = GetQuicFlag(FLAGS_port);
- if (port == 0) {
- port = url.port();
- }
-
- // Determine IP address to connect to from supplied hostname.
- QuicSocketAddress addr = LookupAddress(host, quic::QuicStrCat(port));
- if (!addr.IsInitialized()) {
- return 1;
- }
- std::cerr << "Resolved " << url.ToString() << " to " << addr.ToString()
- << std::endl;
-
- // Build the client, and try to connect.
- quic::QuicEpollServer epoll_server;
- quic::QuicServerId server_id(url.host(), port, false);
- quic::ParsedQuicVersionVector versions = quic::CurrentSupportedVersions();
-
- std::string quic_version_string = GetQuicFlag(FLAGS_quic_version);
- const int32_t quic_ietf_draft = GetQuicFlag(FLAGS_quic_ietf_draft);
- if (quic_ietf_draft > 0) {
- quic::QuicVersionInitializeSupportForIetfDraft(quic_ietf_draft);
- if (quic_version_string.length() == 0) {
- quic_version_string = "T099";
- }
- }
- if (quic_version_string.length() > 0) {
- if (quic_version_string[0] == 'T') {
- // ParseQuicVersionString checks quic_supports_tls_handshake.
- SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
- }
- quic::ParsedQuicVersion parsed_quic_version =
- quic::ParseQuicVersionString(quic_version_string);
- if (parsed_quic_version.transport_version ==
- quic::QUIC_VERSION_UNSUPPORTED) {
- return 1;
- }
- versions.clear();
- versions.push_back(parsed_quic_version);
- quic::QuicEnableVersion(parsed_quic_version);
- }
-
- const int32_t num_requests(GetQuicFlag(FLAGS_num_requests));
- std::unique_ptr<quic::ProofVerifier> proof_verifier;
- if (GetQuicFlag(FLAGS_disable_certificate_verification)) {
- proof_verifier = quic::QuicMakeUnique<FakeProofVerifier>();
- } else {
- proof_verifier = quic::CreateDefaultProofVerifier();
- }
- quic::QuicClient client(addr, server_id, versions, &epoll_server,
- std::move(proof_verifier));
- int32_t initial_mtu = GetQuicFlag(FLAGS_initial_mtu);
- client.set_initial_max_packet_length(
- initial_mtu != 0 ? initial_mtu : quic::kDefaultMaxPacketSize);
- client.set_drop_response_body(GetQuicFlag(FLAGS_drop_response_body));
- if (!client.Initialize()) {
- std::cerr << "Failed to initialize client." << std::endl;
- return 1;
- }
- if (!client.Connect()) {
- quic::QuicErrorCode error = client.session()->error();
- if (error == quic::QUIC_INVALID_VERSION) {
- std::cerr << "Server talks QUIC, but none of the versions supported by "
- << "this client: " << ParsedQuicVersionVectorToString(versions)
- << std::endl;
- // 0: No error.
- // 20: Failed to connect due to QUIC_INVALID_VERSION.
- return GetQuicFlag(FLAGS_version_mismatch_ok) ? 0 : 20;
- }
- std::cerr << "Failed to connect to " << addr.ToString()
- << ". Error: " << quic::QuicErrorCodeToString(error) << std::endl;
- return 1;
- }
- std::cerr << "Connected to " << addr.ToString() << std::endl;
-
- // Construct the string body from flags, if provided.
- std::string body = GetQuicFlag(FLAGS_body);
- if (!GetQuicFlag(FLAGS_body_hex).empty()) {
- DCHECK(GetQuicFlag(FLAGS_body).empty())
- << "Only set one of --body and --body_hex.";
- body = QuicTextUtils::HexDecode(GetQuicFlag(FLAGS_body_hex));
- }
-
- // Construct a GET or POST request for supplied URL.
- spdy::SpdyHeaderBlock header_block;
- header_block[":method"] = body.empty() ? "GET" : "POST";
- header_block[":scheme"] = url.scheme();
- header_block[":authority"] = url.HostPort();
- header_block[":path"] = url.PathParamsQuery();
-
- // Append any additional headers supplied on the command line.
- for (QuicStringPiece sp :
- QuicTextUtils::Split(GetQuicFlag(FLAGS_headers), ';')) {
- QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&sp);
- if (sp.empty()) {
- continue;
- }
- std::vector<QuicStringPiece> kv = QuicTextUtils::Split(sp, ':');
- QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[0]);
- QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[1]);
- header_block[kv[0]] = kv[1];
- }
-
- // Make sure to store the response, for later output.
- client.set_store_response(true);
-
- for (int i = 0; i < num_requests; ++i) {
- // Send the request.
- client.SendRequestAndWaitForResponse(header_block, body, /*fin=*/true);
-
- // Print request and response details.
- if (!GetQuicFlag(FLAGS_quiet)) {
- std::cout << "Request:" << std::endl;
- std::cout << "headers:" << header_block.DebugString();
- if (!GetQuicFlag(FLAGS_body_hex).empty()) {
- // Print the user provided hex, rather than binary body.
- std::cout << "body:\n"
- << QuicTextUtils::HexDump(
- QuicTextUtils::HexDecode(GetQuicFlag(FLAGS_body_hex)))
- << std::endl;
- } else {
- std::cout << "body: " << body << std::endl;
- }
- std::cout << std::endl;
-
- if (!client.preliminary_response_headers().empty()) {
- std::cout << "Preliminary response headers: "
- << client.preliminary_response_headers() << std::endl;
- std::cout << std::endl;
- }
-
- std::cout << "Response:" << std::endl;
- std::cout << "headers: " << client.latest_response_headers() << std::endl;
- std::string response_body = client.latest_response_body();
- if (!GetQuicFlag(FLAGS_body_hex).empty()) {
- // Assume response is binary data.
- std::cout << "body:\n"
- << QuicTextUtils::HexDump(response_body) << std::endl;
- } else {
- std::cout << "body: " << response_body << std::endl;
- }
- std::cout << "trailers: " << client.latest_response_trailers()
- << std::endl;
- }
-
- if (!client.connected()) {
- std::cerr << "Request caused connection failure. Error: "
- << quic::QuicErrorCodeToString(client.session()->error())
- << std::endl;
- return 1;
- }
-
- size_t response_code = client.latest_response_code();
- if (response_code >= 200 && response_code < 300) {
- std::cerr << "Request succeeded (" << response_code << ")." << std::endl;
- } else if (response_code >= 300 && response_code < 400) {
- if (GetQuicFlag(FLAGS_redirect_is_success)) {
- std::cerr << "Request succeeded (redirect " << response_code << ")."
- << std::endl;
- } else {
- std::cerr << "Request failed (redirect " << response_code << ")."
- << std::endl;
- return 1;
- }
- } else {
- std::cerr << "Request failed (" << response_code << ")." << std::endl;
- return 1;
- }
-
- // Change the ephemeral port if there are more requests to do.
- if (i + 1 < num_requests) {
- if (!client.ChangeEphemeralPort()) {
- std::cerr << "Failed to change ephemeral port." << std::endl;
- return 1;
- }
- }
- }
-
- return 0;
+ quic::QuicEpollClientFactory factory;
+ quic::QuicToyClient client(&factory);
+ return client.SendRequestsAndPrintResponses(urls);
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.cc
index e545ee2c62c..117521111f5 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.cc
@@ -133,7 +133,7 @@ void QuicClientEpollNetworkHelper::OnEvent(int fd, QuicEpollEvent* event) {
DCHECK_EQ(fd, GetLatestFD());
if (event->in_events & EPOLLIN) {
- DVLOG(1) << "Read packets on EPOLLIN";
+ QUIC_DVLOG(1) << "Read packets on EPOLLIN";
int times_to_read = max_reads_per_epoll_loop_;
bool more_to_read = true;
QuicPacketCount packets_dropped = 0;
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.cc
new file mode 100644
index 00000000000..3b6b2eed714
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.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_epoll_client_factory.h"
+
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
+#include "net/third_party/quiche/src/quic/tools/quic_client.h"
+
+namespace quic {
+
+namespace {
+
+QuicSocketAddress LookupAddress(std::string host, std::string port) {
+ addrinfo hint;
+ memset(&hint, 0, sizeof(hint));
+ hint.ai_protocol = IPPROTO_UDP;
+
+ addrinfo* info_list = nullptr;
+ int result = getaddrinfo(host.c_str(), port.c_str(), &hint, &info_list);
+ if (result != 0) {
+ QUIC_LOG(ERROR) << "Failed to look up " << host << ": "
+ << gai_strerror(result);
+ return QuicSocketAddress();
+ }
+
+ CHECK(info_list != nullptr);
+ std::unique_ptr<addrinfo, void (*)(addrinfo*)> info_list_owned(info_list,
+ freeaddrinfo);
+ return QuicSocketAddress(*info_list->ai_addr);
+}
+
+} // namespace
+
+std::unique_ptr<QuicSpdyClientBase> QuicEpollClientFactory::CreateClient(
+ std::string host,
+ uint16_t port,
+ ParsedQuicVersionVector versions,
+ std::unique_ptr<ProofVerifier> verifier) {
+ QuicSocketAddress addr = LookupAddress(host, QuicStrCat(port));
+ if (!addr.IsInitialized()) {
+ QUIC_LOG(ERROR) << "Unable to resolve address: " << host;
+ return nullptr;
+ }
+ QuicServerId server_id(host, port, false);
+ return QuicMakeUnique<QuicClient>(addr, server_id, versions, &epoll_server_,
+ std::move(verifier));
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.h b/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.h
new file mode 100644
index 00000000000..a083643ec3e
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_client_factory.h
@@ -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.
+
+#ifndef QUICHE_QUIC_TOOLS_EPOLL_CLIENT_FACTORY_H_
+#define QUICHE_QUIC_TOOLS_EPOLL_CLIENT_FACTORY_H_
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h"
+#include "net/third_party/quiche/src/quic/tools/quic_toy_client.h"
+
+namespace quic {
+
+// Factory creating QuicClient instances.
+class QuicEpollClientFactory : public QuicToyClient::ClientFactory {
+ public:
+ std::unique_ptr<QuicSpdyClientBase> CreateClient(
+ std::string host,
+ uint16_t port,
+ ParsedQuicVersionVector versions,
+ std::unique_ptr<ProofVerifier> verifier) override;
+
+ private:
+ QuicEpollServer epoll_server_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_TOOLS_EPOLL_CLIENT_FACTORY_H_
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_server_factory.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_server_factory.cc
new file mode 100644
index 00000000000..f0c206a5d3f
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_server_factory.cc
@@ -0,0 +1,18 @@
+// 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_epoll_server_factory.h"
+
+#include "net/third_party/quiche/src/quic/tools/quic_server.h"
+
+namespace quic {
+
+std::unique_ptr<quic::QuicSpdyServerBase> QuicEpollServerFactory::CreateServer(
+ quic::QuicSimpleServerBackend* backend,
+ std::unique_ptr<quic::ProofSource> proof_source) {
+ return quic::QuicMakeUnique<quic::QuicServer>(std::move(proof_source),
+ backend);
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_server_factory.h b/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_server_factory.h
new file mode 100644
index 00000000000..391f3cd8d12
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_epoll_server_factory.h
@@ -0,0 +1,26 @@
+// 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_EPOLL_SERVER_FACTORY_H_
+#define QUICHE_QUIC_TOOLS_EPOLL_SERVER_FACTORY_H_
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h"
+#include "net/third_party/quiche/src/quic/tools/quic_toy_server.h"
+
+namespace quic {
+
+// Factory creating QuicServer instances.
+class QuicEpollServerFactory : public QuicToyServer::ServerFactory {
+ public:
+ std::unique_ptr<QuicSpdyServerBase> CreateServer(
+ QuicSimpleServerBackend* backend,
+ std::unique_ptr<ProofSource> proof_source) override;
+
+ private:
+ QuicEpollServer epoll_server_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_TOOLS_EPOLL_SERVER_FACTORY_H_
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 76a52c3bf87..96faacb6914 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
@@ -137,8 +137,8 @@ const QuicBackendResponse* QuicMemoryCacheBackend::GetResponse(
auto it = responses_.find(GetKey(host, path));
if (it == responses_.end()) {
- DVLOG(1) << "Get response for resource failed: host " << host << " path "
- << path;
+ QUIC_DVLOG(1) << "Get response for resource failed: host " << host
+ << " path " << path;
if (default_response_) {
return default_response_.get();
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc
index c8cfc11ec8f..80ffd4eeb9a 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_packet_printer_bin.cc
@@ -63,6 +63,11 @@ class QuicPacketPrinter : public QuicFramerVisitorInterface {
const QuicVersionNegotiationPacket& packet) override {
std::cerr << "OnVersionNegotiationPacket\n";
}
+ void OnRetryPacket(QuicConnectionId original_connection_id,
+ QuicConnectionId new_connection_id,
+ QuicStringPiece retry_token) override {
+ std::cerr << "OnRetryPacket\n";
+ }
bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override {
std::cerr << "OnUnauthenticatedPublicHeader\n";
return true;
@@ -168,12 +173,12 @@ class QuicPacketPrinter : public QuicFramerVisitorInterface {
std::cerr << "OnGoAwayFrame: " << frame;
return true;
}
- bool OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) override {
- std::cerr << "OnMaxStreamIdFrame: " << frame;
+ bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override {
+ std::cerr << "OnMaxStreamsFrame: " << frame;
return true;
}
- bool OnStreamIdBlockedFrame(const QuicStreamIdBlockedFrame& frame) override {
- std::cerr << "OnStreamIdBlockedFrame: " << frame;
+ bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override {
+ std::cerr << "OnStreamsBlockedFrame: " << frame;
return true;
}
bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override {
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 d67bc3078d0..3696b7cd06b 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
@@ -64,7 +64,7 @@ QuicServer::QuicServer(
const QuicCryptoServerConfig::ConfigOptions& crypto_config_options,
const ParsedQuicVersionVector& supported_versions,
QuicSimpleServerBackend* quic_simple_server_backend,
- uint8_t expected_connection_id_length)
+ uint8_t expected_server_connection_id_length)
: port_(0),
fd_(-1),
packets_dropped_(0),
@@ -80,7 +80,9 @@ QuicServer::QuicServer(
version_manager_(supported_versions),
packet_reader_(new QuicPacketReader()),
quic_simple_server_backend_(quic_simple_server_backend),
- expected_connection_id_length_(expected_connection_id_length) {
+ expected_server_connection_id_length_(
+ expected_server_connection_id_length) {
+ DCHECK(quic_simple_server_backend_);
Initialize();
}
@@ -90,12 +92,12 @@ void QuicServer::Initialize() {
const uint32_t kInitialSessionFlowControlWindow = 1 * 1024 * 1024; // 1 MB
const uint32_t kInitialStreamFlowControlWindow = 64 * 1024; // 64 KB
if (config_.GetInitialStreamFlowControlWindowToSend() ==
- kMinimumFlowControlSendWindow) {
+ kDefaultFlowControlSendWindow) {
config_.SetInitialStreamFlowControlWindowToSend(
kInitialStreamFlowControlWindow);
}
if (config_.GetInitialSessionFlowControlWindowToSend() ==
- kMinimumFlowControlSendWindow) {
+ kDefaultFlowControlSendWindow) {
config_.SetInitialSessionFlowControlWindowToSend(
kInitialSessionFlowControlWindow);
}
@@ -158,7 +160,13 @@ QuicDispatcher* QuicServer::CreateQuicDispatcher() {
new QuicSimpleCryptoServerStreamHelper(QuicRandom::GetInstance())),
std::unique_ptr<QuicEpollAlarmFactory>(
new QuicEpollAlarmFactory(&epoll_server_)),
- quic_simple_server_backend_, expected_connection_id_length_);
+ quic_simple_server_backend_, expected_server_connection_id_length_);
+}
+
+void QuicServer::HandleEventsForever() {
+ while (true) {
+ WaitForEvents();
+ }
}
void QuicServer::WaitForEvents() {
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_server.h b/chromium/net/third_party/quiche/src/quic/tools/quic_server.h
index 4d7e08199a9..1f9c225a2d3 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_server.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_server.h
@@ -22,6 +22,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h"
+#include "net/third_party/quiche/src/quic/tools/quic_spdy_server_base.h"
namespace quic {
@@ -32,7 +33,8 @@ class QuicServerPeer;
class QuicDispatcher;
class QuicPacketReader;
-class QuicServer : public QuicEpollCallbackInterface {
+class QuicServer : public QuicSpdyServerBase,
+ public QuicEpollCallbackInterface {
public:
QuicServer(std::unique_ptr<ProofSource> proof_source,
QuicSimpleServerBackend* quic_simple_server_backend);
@@ -41,7 +43,7 @@ class QuicServer : public QuicEpollCallbackInterface {
const QuicCryptoServerConfig::ConfigOptions& server_config_options,
const ParsedQuicVersionVector& supported_versions,
QuicSimpleServerBackend* quic_simple_server_backend,
- uint8_t expected_connection_id_length);
+ uint8_t expected_server_connection_id_length);
QuicServer(const QuicServer&) = delete;
QuicServer& operator=(const QuicServer&) = delete;
@@ -50,7 +52,9 @@ class QuicServer : public QuicEpollCallbackInterface {
std::string Name() const override { return "QuicServer"; }
// Start listening on the specified address.
- bool CreateUDPSocketAndListen(const QuicSocketAddress& address);
+ bool CreateUDPSocketAndListen(const QuicSocketAddress& address) override;
+ // Handles all events. Does not return.
+ void HandleEventsForever() override;
// Wait up to 50ms, and handle any events which occur.
void WaitForEvents();
@@ -99,8 +103,8 @@ class QuicServer : public QuicEpollCallbackInterface {
void set_silent_close(bool value) { silent_close_ = value; }
- uint8_t expected_connection_id_length() {
- return expected_connection_id_length_;
+ uint8_t expected_server_connection_id_length() {
+ return expected_server_connection_id_length_;
}
private:
@@ -151,7 +155,7 @@ class QuicServer : public QuicEpollCallbackInterface {
QuicSimpleServerBackend* quic_simple_server_backend_; // unowned.
// Connection ID length expected to be read on incoming IETF short headers.
- uint8_t expected_connection_id_length_;
+ uint8_t expected_server_connection_id_length_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_server_bin.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_server_bin.cc
index 128c873dfda..541f6f9e13e 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_server_bin.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_server_bin.cc
@@ -8,31 +8,9 @@
#include <vector>
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_default_proof_providers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h"
-#include "net/third_party/quiche/src/quic/tools/quic_server.h"
-
-DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t,
- port,
- 6121,
- "The port the quic server will listen on.");
-
-DEFINE_QUIC_COMMAND_LINE_FLAG(
- std::string,
- quic_response_cache_dir,
- "",
- "Specifies the directory used during QuicHttpResponseCache "
- "construction to seed the cache. Cache directory can be "
- "generated using `wget -p --save-headers <url>`");
-
-DEFINE_QUIC_COMMAND_LINE_FLAG(
- int32_t,
- quic_ietf_draft,
- 0,
- "QUIC IETF draft number to use over the wire, e.g. 18. "
- "This also enables required internal QUIC flags.");
+#include "net/third_party/quiche/src/quic/tools/quic_epoll_server_factory.h"
+#include "net/third_party/quiche/src/quic/tools/quic_toy_server.h"
int main(int argc, char* argv[]) {
const char* usage = "Usage: quic_server [options]";
@@ -43,28 +21,8 @@ int main(int argc, char* argv[]) {
exit(0);
}
- const int32_t quic_ietf_draft = GetQuicFlag(FLAGS_quic_ietf_draft);
- if (quic_ietf_draft > 0) {
- quic::QuicVersionInitializeSupportForIetfDraft(quic_ietf_draft);
- quic::QuicEnableVersion(
- quic::ParsedQuicVersion(quic::PROTOCOL_TLS1_3, quic::QUIC_VERSION_99));
- }
-
- quic::QuicMemoryCacheBackend memory_cache_backend;
- if (!GetQuicFlag(FLAGS_quic_response_cache_dir).empty()) {
- memory_cache_backend.InitializeBackend(
- GetQuicFlag(FLAGS_quic_response_cache_dir));
- }
-
- quic::QuicServer server(quic::CreateDefaultProofSource(),
- &memory_cache_backend);
-
- if (!server.CreateUDPSocketAndListen(quic::QuicSocketAddress(
- quic::QuicIpAddress::Any6(), GetQuicFlag(FLAGS_port)))) {
- return 1;
- }
-
- while (true) {
- server.WaitForEvents();
- }
+ quic::QuicToyServer::MemoryCacheBackendFactory backend_factory;
+ quic::QuicEpollServerFactory server_factory;
+ quic::QuicToyServer server(&backend_factory, &server_factory);
+ return server.Start();
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.cc
index 4706b606843..0f4d4476848 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.cc
@@ -16,14 +16,14 @@ QuicSimpleDispatcher::QuicSimpleDispatcher(
std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
QuicSimpleServerBackend* quic_simple_server_backend,
- uint8_t expected_connection_id_length)
+ uint8_t expected_server_connection_id_length)
: QuicDispatcher(config,
crypto_config,
version_manager,
std::move(helper),
std::move(session_helper),
std::move(alarm_factory),
- expected_connection_id_length),
+ expected_server_connection_id_length),
quic_simple_server_backend_(quic_simple_server_backend) {}
QuicSimpleDispatcher::~QuicSimpleDispatcher() = default;
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h
index 46d976c7b5b..8a6cf85e6c5 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h
@@ -21,7 +21,7 @@ class QuicSimpleDispatcher : public QuicDispatcher {
std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
QuicSimpleServerBackend* quic_simple_server_backend,
- uint8_t expected_connection_id_length);
+ uint8_t expected_server_connection_id_length);
~QuicSimpleDispatcher() override;
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.cc
index a722d373dd7..2b4cae71fc3 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_session.cc
@@ -33,7 +33,9 @@ QuicSimpleServerSession::QuicSimpleServerSession(
compressed_certs_cache),
highest_promised_stream_id_(
QuicUtils::GetInvalidStreamId(connection->transport_version())),
- quic_simple_server_backend_(quic_simple_server_backend) {}
+ quic_simple_server_backend_(quic_simple_server_backend) {
+ DCHECK(quic_simple_server_backend_);
+}
QuicSimpleServerSession::~QuicSimpleServerSession() {
delete connection();
@@ -43,10 +45,8 @@ QuicCryptoServerStreamBase*
QuicSimpleServerSession::CreateQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache) {
- return new QuicCryptoServerStream(
- crypto_config, compressed_certs_cache,
- GetQuicReloadableFlag(enable_quic_stateless_reject_support), this,
- stream_helper());
+ return new QuicCryptoServerStream(crypto_config, compressed_certs_cache, this,
+ stream_helper());
}
void QuicSimpleServerSession::OnStreamFrame(const QuicStreamFrame& frame) {
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 7203f128caa..58c98dd39f8 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
@@ -46,7 +46,12 @@ using testing::StrictMock;
namespace quic {
namespace test {
namespace {
+
typedef QuicSimpleServerSession::PromisedStreamInfo PromisedStreamInfo;
+
+const QuicByteCount kHeadersFrameHeaderLength = 2;
+const QuicByteCount kHeadersFramePayloadLength = 9;
+
} // namespace
class QuicSimpleServerSessionPeer {
@@ -54,9 +59,11 @@ class QuicSimpleServerSessionPeer {
static void SetCryptoStream(QuicSimpleServerSession* s,
QuicCryptoServerStream* crypto_stream) {
s->crypto_stream_.reset(crypto_stream);
- s->RegisterStaticStream(
- QuicUtils::GetCryptoStreamId(s->connection()->transport_version()),
- crypto_stream);
+ if (!QuicVersionUsesCryptoFrames(s->connection()->transport_version())) {
+ s->RegisterStaticStream(
+ QuicUtils::GetCryptoStreamId(s->connection()->transport_version()),
+ crypto_stream);
+ }
}
static QuicSpdyStream* CreateIncomingStream(QuicSimpleServerSession* s,
@@ -84,8 +91,6 @@ class MockQuicCryptoServerStream : public QuicCryptoServerStream {
: QuicCryptoServerStream(
crypto_config,
compressed_certs_cache,
- GetQuicReloadableFlag(
- enable_quic_stateless_reject_support), // NOLINT
session,
helper) {}
MockQuicCryptoServerStream(const MockQuicCryptoServerStream&) = delete;
@@ -178,13 +183,13 @@ class QuicSimpleServerSessionTest
return true;
}
- // The function ensures that A) the max stream id frames get properly deleted
+ // The function ensures that A) the MAX_STREAMS frames get properly deleted
// (since the test uses a 'did we leak memory' check ... if we just lose the
// frame, the test fails) and B) returns true (instead of the default, false)
// which ensures that the rest of the system thinks that the frame actually
// was transmitted.
- bool ClearMaxStreamIdControlFrame(const QuicFrame& frame) {
- if (frame.type == MAX_STREAM_ID_FRAME) {
+ bool ClearMaxStreamsControlFrame(const QuicFrame& frame) {
+ if (frame.type == MAX_STREAMS_FRAME) {
DeleteFrame(&const_cast<QuicFrame&>(frame));
return true;
}
@@ -200,9 +205,13 @@ class QuicSimpleServerSessionTest
TlsServerHandshaker::CreateSslCtx()),
compressed_certs_cache_(
QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {
- config_.SetMaxIncomingDynamicStreamsToSend(kMaxStreamsForTest);
- QuicConfigPeer::SetReceivedMaxIncomingDynamicStreams(&config_,
- kMaxStreamsForTest);
+ config_.SetMaxIncomingBidirectionalStreamsToSend(kMaxStreamsForTest);
+ QuicConfigPeer::SetReceivedMaxIncomingBidirectionalStreams(
+ &config_, kMaxStreamsForTest);
+ config_.SetMaxIncomingUnidirectionalStreamsToSend(kMaxStreamsForTest);
+ QuicConfigPeer::SetReceivedMaxIncomingUnidirectionalStreams(
+ &config_, kMaxStreamsForTest);
+
config_.SetInitialStreamFlowControlWindowToSend(
kInitialStreamFlowControlWindowForTest);
config_.SetInitialSessionFlowControlWindowToSend(
@@ -227,8 +236,7 @@ class QuicSimpleServerSessionTest
if (IsVersion99()) {
EXPECT_CALL(*connection_, SendControlFrame(_))
.WillRepeatedly(Invoke(
- this,
- &QuicSimpleServerSessionTest::ClearMaxStreamIdControlFrame));
+ this, &QuicSimpleServerSessionTest::ClearMaxStreamsControlFrame));
}
session_->OnConfigNegotiated();
}
@@ -566,7 +574,7 @@ class QuicSimpleServerSessionServerPushTest
if (IsVersion99()) {
EXPECT_CALL(*connection_, SendControlFrame(_))
.WillRepeatedly(Invoke(this, &QuicSimpleServerSessionServerPushTest::
- ClearMaxStreamIdControlFrame));
+ ClearMaxStreamsControlFrame));
}
session_->OnConfigNegotiated();
@@ -640,6 +648,22 @@ class QuicSimpleServerSessionServerPushTest
// Since flow control window is smaller than response body, not the
// whole body will be sent.
QuicStreamOffset offset = 0;
+ if (VersionHasStreamType(connection_->transport_version())) {
+ EXPECT_CALL(*connection_,
+ SendStreamData(stream_id, 1, offset, NO_FIN));
+ offset++;
+ }
+
+ if (VersionUsesQpack(connection_->transport_version())) {
+ EXPECT_CALL(*connection_,
+ SendStreamData(stream_id, kHeadersFrameHeaderLength,
+ offset, NO_FIN));
+ offset += kHeadersFrameHeaderLength;
+ EXPECT_CALL(*connection_,
+ SendStreamData(stream_id, kHeadersFramePayloadLength,
+ offset, NO_FIN));
+ offset += kHeadersFramePayloadLength;
+ }
if (VersionHasDataFrameHeader(connection_->transport_version())) {
EXPECT_CALL(*connection_,
SendStreamData(stream_id, data_frame_header_length,
@@ -658,11 +682,13 @@ class QuicSimpleServerSessionServerPushTest
return data_frame_header_length;
}
- void ConsumeHeadersStreamData() {
- QuicStreamId headers_stream_id =
- QuicUtils::GetHeadersStreamId(connection_->transport_version());
- EXPECT_CALL(*connection_, SendStreamData(headers_stream_id, _, _, _))
- .Times(AtLeast(1));
+ void MaybeConsumeHeadersStreamData() {
+ if (!VersionUsesQpack(connection_->transport_version())) {
+ QuicStreamId headers_stream_id =
+ QuicUtils::GetHeadersStreamId(connection_->transport_version());
+ EXPECT_CALL(*connection_, SendStreamData(headers_stream_id, _, _, _))
+ .Times(AtLeast(1));
+ }
}
};
@@ -674,7 +700,7 @@ INSTANTIATE_TEST_SUITE_P(Tests,
// PUSH_PROMISE's will be sent out and only kMaxStreamsForTest streams will be
// opened and send push response.
TEST_P(QuicSimpleServerSessionServerPushTest, TestPromisePushResources) {
- ConsumeHeadersStreamData();
+ MaybeConsumeHeadersStreamData();
size_t num_resources = kMaxStreamsForTest + 5;
PromisePushResources(num_resources);
EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams());
@@ -684,7 +710,7 @@ TEST_P(QuicSimpleServerSessionServerPushTest, TestPromisePushResources) {
// draining, a queued promised stream will become open and send push response.
TEST_P(QuicSimpleServerSessionServerPushTest,
HandlePromisedPushRequestsAfterStreamDraining) {
- ConsumeHeadersStreamData();
+ MaybeConsumeHeadersStreamData();
size_t num_resources = kMaxStreamsForTest + 1;
QuicByteCount data_frame_header_length = PromisePushResources(num_resources);
QuicStreamId next_out_going_stream_id =
@@ -693,6 +719,21 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
// After an open stream is marked draining, a new stream is expected to be
// created and a response sent on the stream.
QuicStreamOffset offset = 0;
+ if (VersionHasStreamType(connection_->transport_version())) {
+ EXPECT_CALL(*connection_,
+ SendStreamData(next_out_going_stream_id, 1, offset, NO_FIN));
+ offset++;
+ }
+ if (VersionUsesQpack(connection_->transport_version())) {
+ EXPECT_CALL(*connection_,
+ SendStreamData(next_out_going_stream_id,
+ kHeadersFrameHeaderLength, offset, NO_FIN));
+ offset += kHeadersFrameHeaderLength;
+ EXPECT_CALL(*connection_,
+ SendStreamData(next_out_going_stream_id,
+ kHeadersFramePayloadLength, offset, NO_FIN));
+ offset += kHeadersFramePayloadLength;
+ }
if (VersionHasDataFrameHeader(connection_->transport_version())) {
EXPECT_CALL(*connection_,
SendStreamData(next_out_going_stream_id,
@@ -708,12 +749,13 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
if (IsVersion99()) {
// The PromisePushedResources call, above, will have used all available
// stream ids. For version 99, stream ids are not made available until
- // a MAX_STREAM_ID frame is received. This emulates the reception of one.
+ // a MAX_STREAMS frame is received. This emulates the reception of one.
// For pre-v-99, the node monitors its own stream usage and makes streams
// available as it closes/etc them.
- session_->OnMaxStreamIdFrame(
- QuicMaxStreamIdFrame(0, GetNthServerInitiatedUnidirectionalId(10)));
+ session_->OnMaxStreamsFrame(
+ QuicMaxStreamsFrame(0, num_resources, /*unidirectional=*/true));
}
+
session_->StreamDraining(GetNthServerInitiatedUnidirectionalId(0));
// Number of open outgoing streams should still be the same, because a new
// stream is opened. And the queue should be empty.
@@ -724,14 +766,14 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
// prevent a promised resource to be send out.
TEST_P(QuicSimpleServerSessionServerPushTest,
ResetPromisedStreamToCancelServerPush) {
- ConsumeHeadersStreamData();
+ MaybeConsumeHeadersStreamData();
// Having two extra resources to be send later. One of them will be reset, so
// when opened stream become close, only one will become open.
size_t num_resources = kMaxStreamsForTest + 2;
if (IsVersion99()) {
- // V99 will send out a stream-id-blocked frame when the we desired to exceed
- // the limit. This will clear the frames so that they do not block the later
+ // V99 will send out a STREAMS_BLOCKED frame when it tries to exceed the
+ // limit. This will clear the frames so that they do not block the later
// rst-stream frame.
EXPECT_CALL(*connection_, SendControlFrame(_))
.WillOnce(Invoke(
@@ -759,6 +801,21 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
GetNthServerInitiatedUnidirectionalId(kMaxStreamsForTest);
InSequence s;
QuicStreamOffset offset = 0;
+ if (VersionHasStreamType(connection_->transport_version())) {
+ EXPECT_CALL(*connection_,
+ SendStreamData(stream_not_reset, 1, offset, NO_FIN));
+ offset++;
+ }
+ if (VersionUsesQpack(connection_->transport_version())) {
+ EXPECT_CALL(*connection_,
+ SendStreamData(stream_not_reset, kHeadersFrameHeaderLength,
+ offset, NO_FIN));
+ offset += kHeadersFrameHeaderLength;
+ EXPECT_CALL(*connection_,
+ SendStreamData(stream_not_reset, kHeadersFramePayloadLength,
+ offset, NO_FIN));
+ offset += kHeadersFramePayloadLength;
+ }
if (VersionHasDataFrameHeader(connection_->transport_version())) {
EXPECT_CALL(*connection_,
SendStreamData(stream_not_reset, data_frame_header_length,
@@ -773,11 +830,11 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
if (IsVersion99()) {
// The PromisePushedResources call, above, will have used all available
// stream ids. For version 99, stream ids are not made available until
- // a MAX_STREAM_ID frame is received. This emulates the reception of one.
+ // a MAX_STREAMS frame is received. This emulates the reception of one.
// For pre-v-99, the node monitors its own stream usage and makes streams
// available as it closes/etc them.
- session_->OnMaxStreamIdFrame(
- QuicMaxStreamIdFrame(0, GetNthServerInitiatedUnidirectionalId(11)));
+ session_->OnMaxStreamsFrame(
+ QuicMaxStreamsFrame(0, num_resources, /*unidirectional=*/true));
}
session_->StreamDraining(GetNthServerInitiatedUnidirectionalId(0));
session_->StreamDraining(GetNthServerInitiatedUnidirectionalId(1));
@@ -787,7 +844,7 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
// the queue to be send out.
TEST_P(QuicSimpleServerSessionServerPushTest,
CloseStreamToHandleMorePromisedStream) {
- ConsumeHeadersStreamData();
+ MaybeConsumeHeadersStreamData();
size_t num_resources = kMaxStreamsForTest + 1;
if (IsVersion99()) {
// V99 will send out a stream-id-blocked frame when the we desired to exceed
@@ -812,6 +869,21 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
OnStreamReset(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT));
}
QuicStreamOffset offset = 0;
+ if (VersionHasStreamType(connection_->transport_version())) {
+ EXPECT_CALL(*connection_,
+ SendStreamData(stream_to_open, 1, offset, NO_FIN));
+ offset++;
+ }
+ if (VersionUsesQpack(connection_->transport_version())) {
+ EXPECT_CALL(*connection_,
+ SendStreamData(stream_to_open, kHeadersFrameHeaderLength,
+ offset, NO_FIN));
+ offset += kHeadersFrameHeaderLength;
+ EXPECT_CALL(*connection_,
+ SendStreamData(stream_to_open, kHeadersFramePayloadLength,
+ offset, NO_FIN));
+ offset += kHeadersFramePayloadLength;
+ }
if (VersionHasDataFrameHeader(connection_->transport_version())) {
EXPECT_CALL(*connection_,
SendStreamData(stream_to_open, data_frame_header_length, offset,
@@ -828,11 +900,11 @@ TEST_P(QuicSimpleServerSessionServerPushTest,
if (IsVersion99()) {
// The PromisePushedResources call, above, will have used all available
// stream ids. For version 99, stream ids are not made available until
- // a MAX_STREAM_ID frame is received. This emulates the reception of one.
+ // a MAX_STREAMS frame is received. This emulates the reception of one.
// For pre-v-99, the node monitors its own stream usage and makes streams
// available as it closes/etc them.
- session_->OnMaxStreamIdFrame(
- QuicMaxStreamIdFrame(0, GetNthServerInitiatedUnidirectionalId(10)));
+ session_->OnMaxStreamsFrame(
+ QuicMaxStreamsFrame(0, num_resources, /*unidirectional=*/true));
}
visitor_->OnRstStream(rst);
// Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.cc
index 4e25552d03c..55d93dcd54d 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.cc
@@ -29,7 +29,9 @@ QuicSimpleServerStream::QuicSimpleServerStream(
QuicSimpleServerBackend* quic_simple_server_backend)
: QuicSpdyServerStreamBase(id, session, type),
content_length_(-1),
- quic_simple_server_backend_(quic_simple_server_backend) {}
+ quic_simple_server_backend_(quic_simple_server_backend) {
+ DCHECK(quic_simple_server_backend_);
+}
QuicSimpleServerStream::QuicSimpleServerStream(
PendingStream pending,
@@ -38,7 +40,9 @@ QuicSimpleServerStream::QuicSimpleServerStream(
QuicSimpleServerBackend* quic_simple_server_backend)
: QuicSpdyServerStreamBase(std::move(pending), session, type),
content_length_(-1),
- quic_simple_server_backend_(quic_simple_server_backend) {}
+ quic_simple_server_backend_(quic_simple_server_backend) {
+ DCHECK(quic_simple_server_backend_);
+}
QuicSimpleServerStream::~QuicSimpleServerStream() {
quic_simple_server_backend_->CloseBackendResponseStream(this);
@@ -141,6 +145,12 @@ void QuicSimpleServerStream::SendResponse() {
return;
}
+ if (quic_simple_server_backend_ == nullptr) {
+ QUIC_DVLOG(1) << "Backend is missing.";
+ SendErrorResponse();
+ return;
+ }
+
// Fetch the response from the backend interface and wait for callback once
// response is ready
quic_simple_server_backend_->FetchResponseFromBackend(request_headers_, body_,
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 7572a75da84..8aaaf6b73db 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
@@ -100,8 +100,15 @@ class MockQuicSimpleServerSession : public QuicSimpleServerSession {
crypto_config,
compressed_certs_cache,
quic_simple_server_backend) {
- QuicSessionPeer::SetMaxOpenIncomingStreams(this, kMaxStreamsForTest);
- QuicSessionPeer::SetMaxOpenOutgoingStreams(this, kMaxStreamsForTest);
+ if (connection->transport_version() == QUIC_VERSION_99) {
+ QuicSessionPeer::SetMaxOpenIncomingUnidirectionalStreams(
+ this, kMaxStreamsForTest);
+ QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(
+ this, kMaxStreamsForTest);
+ } else {
+ QuicSessionPeer::SetMaxOpenIncomingStreams(this, kMaxStreamsForTest);
+ QuicSessionPeer::SetMaxOpenOutgoingStreams(this, kMaxStreamsForTest);
+ }
ON_CALL(*this, WritevData(_, _, _, _, _))
.WillByDefault(Invoke(MockQuicSession::ConsumeData));
}
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 3d7ef028e8a..e9e08fd548b 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
@@ -76,9 +76,11 @@ void QuicSpdyClientBase::OnClose(QuicSpdyStream* stream) {
// Store response headers and body.
if (store_response_) {
auto status = response_headers.find(":status");
- if (status == response_headers.end() ||
- !QuicTextUtils::StringToInt(status->second, &latest_response_code_)) {
- QUIC_LOG(ERROR) << "Invalid response headers";
+ if (status == response_headers.end()) {
+ QUIC_LOG(ERROR) << "Missing :status response header";
+ } else if (!QuicTextUtils::StringToInt(status->second,
+ &latest_response_code_)) {
+ QUIC_LOG(ERROR) << "Invalid :status response header: " << status->second;
}
latest_response_headers_ = response_headers.DebugString();
preliminary_response_headers_ =
@@ -118,8 +120,6 @@ void QuicSpdyClientBase::SendRequest(const SpdyHeaderBlock& headers,
return;
}
stream->SendRequest(headers.Clone(), body, fin);
- // Record this in case we need to resend.
- MaybeAddDataToResend(headers, body, fin);
}
void QuicSpdyClientBase::SendRequestAndWaitForResponse(
@@ -167,29 +167,6 @@ int QuicSpdyClientBase::GetNumReceivedServerConfigUpdatesFromSession() {
return client_session()->GetNumReceivedServerConfigUpdates();
}
-void QuicSpdyClientBase::MaybeAddDataToResend(const SpdyHeaderBlock& headers,
- QuicStringPiece body,
- bool fin) {
- if (!GetQuicReloadableFlag(enable_quic_stateless_reject_support)) {
- return;
- }
-
- if (client_session()->IsCryptoHandshakeConfirmed()) {
- // The handshake is confirmed. No need to continue saving requests to
- // resend.
- data_to_resend_on_connect_.clear();
- return;
- }
-
- // The handshake is not confirmed. Push the data onto the queue of data to
- // resend if statelessly rejected.
- std::unique_ptr<SpdyHeaderBlock> new_headers(
- new SpdyHeaderBlock(headers.Clone()));
- std::unique_ptr<QuicDataToResend> data_to_resend(
- new ClientQuicDataToResend(std::move(new_headers), body, fin, this));
- MaybeAddQuicDataToResend(std::move(data_to_resend));
-}
-
void QuicSpdyClientBase::MaybeAddQuicDataToResend(
std::unique_ptr<QuicDataToResend> data_to_resend) {
data_to_resend_on_connect_.push_back(std::move(data_to_resend));
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 03a981e1b1c..7481bfaa7f8 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
@@ -135,6 +135,11 @@ class QuicSpdyClientBase : public QuicClientBase,
response_listener_ = std::move(listener);
}
+ void set_drop_response_body(bool drop_response_body) {
+ drop_response_body_ = drop_response_body;
+ }
+ bool drop_response_body() const { return drop_response_body_; }
+
protected:
int GetNumSentClientHellosFromSession() override;
int GetNumReceivedServerConfigUpdatesFromSession() override;
@@ -144,13 +149,6 @@ class QuicSpdyClientBase : public QuicClientBase,
const quic::ParsedQuicVersionVector& supported_versions,
QuicConnection* connection) override;
- // If the crypto handshake has not yet been confirmed, adds the data to the
- // queue of data to resend if the client receives a stateless reject.
- // Otherwise, deletes the data.
- void MaybeAddDataToResend(const spdy::SpdyHeaderBlock& headers,
- QuicStringPiece body,
- bool fin);
-
void ClearDataToResend() override;
void ResendSavedData() override;
@@ -209,6 +207,8 @@ class QuicSpdyClientBase : public QuicClientBase,
std::vector<std::unique_ptr<QuicDataToResend>> data_to_resend_on_connect_;
std::unique_ptr<ClientQuicDataToResend> push_promise_data_to_resend_;
+
+ bool drop_response_body_ = false;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_server_base.h b/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_server_base.h
new file mode 100644
index 00000000000..1130cfcba4e
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_server_base.h
@@ -0,0 +1,30 @@
+// 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.
+
+// A toy server, which connects to a specified port and sends QUIC
+// requests to that endpoint.
+
+#ifndef QUICHE_QUIC_TOOLS_QUIC_SPDY_SERVER_BASE_H_
+#define QUICHE_QUIC_TOOLS_QUIC_SPDY_SERVER_BASE_H_
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
+
+namespace quic {
+
+// Base class for service instances to be used with QuicToyServer.
+class QuicSpdyServerBase {
+ public:
+ virtual ~QuicSpdyServerBase() = default;
+
+ // Creates a UDP socket and listens on |address|. Returns true on success
+ // and false otherwise.
+ virtual bool CreateUDPSocketAndListen(const QuicSocketAddress& address) = 0;
+
+ // Handles incoming requests. Does not return.
+ virtual void HandleEventsForever() = 0;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_TOOLS_QUIC_SPDY_SERVER_BASE_H_
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_tcp_like_trace_converter.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_tcp_like_trace_converter.cc
index 63bbc5d549c..3301ef5d014 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_tcp_like_trace_converter.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_tcp_like_trace_converter.cc
@@ -95,8 +95,7 @@ QuicInterval<uint64_t> QuicTcpLikeTraceConverter::OnControlFrameSent(
QuicInterval<uint64_t> connection_offset = QuicInterval<uint64_t>(
connection_offset_, connection_offset_ + control_frame_length);
connection_offset_ += control_frame_length;
- control_frames_info_[control_frame_id] = QuicInterval<uint64_t>(
- connection_offset_, connection_offset_ + control_frame_length);
+ control_frames_info_[control_frame_id] = connection_offset;
largest_observed_control_frame_id_ = control_frame_id;
return connection_offset;
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_tcp_like_trace_converter_test.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_tcp_like_trace_converter_test.cc
index 44f7351036b..a6ce81a8dcd 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_tcp_like_trace_converter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_tcp_like_trace_converter_test.cc
@@ -70,7 +70,7 @@ TEST(QuicTcpLikeTraceConverterTest, BasicTest) {
EXPECT_EQ(expected2, converter.OnControlFrameSent(1, 100));
// Ignore passed in length for retransmitted frame.
- expected2 = {450, 600};
+ expected2 = {300, 450};
EXPECT_EQ(expected2, converter.OnControlFrameSent(2, 200));
expected2 = {1602, 1702};
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
new file mode 100644
index 00000000000..f6e2e155e86
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc
@@ -0,0 +1,357 @@
+// 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.
+
+// A binary wrapper for QuicClient.
+// Connects to a host using QUIC, sends a request to the provided URL, and
+// displays the response.
+//
+// Some usage examples:
+//
+// Standard request/response:
+// quic_client www.google.com
+// quic_client www.google.com --quiet
+// quic_client www.google.com --port=443
+//
+// Use a specific version:
+// quic_client www.google.com --quic_version=23
+//
+// Send a POST instead of a GET:
+// quic_client www.google.com --body="this is a POST body"
+//
+// Append additional headers to the request:
+// quic_client www.google.com --headers="Header-A: 1234; Header-B: 5678"
+//
+// Connect to a host different to the URL being requested:
+// quic_client mail.google.com --host=www.google.com
+//
+// Connect to a specific IP:
+// IP=`dig www.google.com +short | head -1`
+// quic_client www.google.com --host=${IP}
+//
+// Send repeated requests and change ephemeral port between requests
+// quic_client www.google.com --num_requests=10
+//
+// Try to connect to a host which does not speak QUIC:
+// quic_client www.example.com
+//
+// This tool is available as a built binary at:
+// /google/data/ro/teams/quic/tools/quic_client
+// After submitting changes to this file, you will need to follow the
+// instructions at go/quic_client_binary_update
+
+#include "net/third_party/quiche/src/quic/tools/quic_toy_client.h"
+
+#include <iostream>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "net/third_party/quiche/src/quic/core/quic_packets.h"
+#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
+#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_default_proof_providers.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_system_event_loop.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+#include "net/third_party/quiche/src/quic/tools/fake_proof_verifier.h"
+#include "net/third_party/quiche/src/quic/tools/quic_url.h"
+
+namespace {
+
+using quic::QuicSocketAddress;
+using quic::QuicStringPiece;
+using quic::QuicTextUtils;
+using quic::QuicUrl;
+
+} // namespace
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ std::string,
+ host,
+ "",
+ "The IP or hostname to connect to. If not provided, the host "
+ "will be derived from the provided URL.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t, port, 0, "The port to connect to.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(std::string,
+ body,
+ "",
+ "If set, send a POST with this body.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ std::string,
+ body_hex,
+ "",
+ "If set, contents are converted from hex to ascii, before "
+ "sending as body of a POST. e.g. --body_hex=\"68656c6c6f\"");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ std::string,
+ headers,
+ "",
+ "A semicolon separated list of key:value pairs to "
+ "add to request headers.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(bool,
+ quiet,
+ false,
+ "Set to true for a quieter output experience.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ std::string,
+ quic_version,
+ "",
+ "QUIC version to speak, e.g. 21. If not set, then all available "
+ "versions are offered in the handshake. Also supports wire versions "
+ "such as Q043 or T099.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ int32_t,
+ quic_ietf_draft,
+ 0,
+ "QUIC IETF draft number to use over the wire, e.g. 18. "
+ "By default this sets quic_version to T099. "
+ "This also enables required internal QUIC flags.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ bool,
+ version_mismatch_ok,
+ false,
+ "If true, a version mismatch in the handshake is not considered a "
+ "failure. Useful for probing a server to determine if it speaks "
+ "any version of QUIC.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ bool,
+ force_version_negotiation,
+ false,
+ "If true, start by proposing a version that is reserved for version "
+ "negotiation.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ bool,
+ redirect_is_success,
+ true,
+ "If true, an HTTP response code of 3xx is considered to be a "
+ "successful response, otherwise a failure.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t,
+ initial_mtu,
+ 0,
+ "Initial MTU of the connection.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ int32_t,
+ num_requests,
+ 1,
+ "How many sequential requests to make on a single connection.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(bool,
+ disable_certificate_verification,
+ false,
+ "If true, don't verify the server certificate.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ bool,
+ drop_response_body,
+ false,
+ "If true, drop response body immediately after it is received.");
+
+namespace quic {
+
+QuicToyClient::QuicToyClient(ClientFactory* client_factory)
+ : client_factory_(client_factory) {}
+
+int QuicToyClient::SendRequestsAndPrintResponses(
+ std::vector<std::string> urls) {
+ QuicUrl url(urls[0], "https");
+ std::string host = GetQuicFlag(FLAGS_host);
+ if (host.empty()) {
+ host = url.host();
+ }
+ int port = GetQuicFlag(FLAGS_port);
+ if (port == 0) {
+ port = url.port();
+ }
+
+ quic::ParsedQuicVersionVector versions = quic::CurrentSupportedVersions();
+
+ std::string quic_version_string = GetQuicFlag(FLAGS_quic_version);
+ const int32_t quic_ietf_draft = GetQuicFlag(FLAGS_quic_ietf_draft);
+ if (quic_ietf_draft > 0) {
+ quic::QuicVersionInitializeSupportForIetfDraft(quic_ietf_draft);
+ if (quic_version_string.length() == 0) {
+ quic_version_string = "T099";
+ }
+ }
+ if (quic_version_string.length() > 0) {
+ if (quic_version_string[0] == 'T') {
+ // ParseQuicVersionString checks quic_supports_tls_handshake.
+ SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
+ }
+ quic::ParsedQuicVersion parsed_quic_version =
+ quic::ParseQuicVersionString(quic_version_string);
+ if (parsed_quic_version.transport_version ==
+ quic::QUIC_VERSION_UNSUPPORTED) {
+ return 1;
+ }
+ versions.clear();
+ versions.push_back(parsed_quic_version);
+ quic::QuicEnableVersion(parsed_quic_version);
+ }
+
+ if (GetQuicFlag(FLAGS_force_version_negotiation)) {
+ versions.insert(versions.begin(),
+ quic::QuicVersionReservedForNegotiation());
+ }
+
+ const int32_t num_requests(GetQuicFlag(FLAGS_num_requests));
+ std::unique_ptr<quic::ProofVerifier> proof_verifier;
+ if (GetQuicFlag(FLAGS_disable_certificate_verification)) {
+ proof_verifier = quic::QuicMakeUnique<FakeProofVerifier>();
+ } else {
+ proof_verifier = quic::CreateDefaultProofVerifier();
+ }
+
+ // Build the client, and try to connect.
+ std::unique_ptr<QuicSpdyClientBase> client = client_factory_->CreateClient(
+ host, port, versions, std::move(proof_verifier));
+
+ int32_t initial_mtu = GetQuicFlag(FLAGS_initial_mtu);
+ client->set_initial_max_packet_length(
+ initial_mtu != 0 ? initial_mtu : quic::kDefaultMaxPacketSize);
+ client->set_drop_response_body(GetQuicFlag(FLAGS_drop_response_body));
+ if (!client->Initialize()) {
+ std::cerr << "Failed to initialize client." << std::endl;
+ return 1;
+ }
+ if (!client->Connect()) {
+ quic::QuicErrorCode error = client->session()->error();
+ if (error == quic::QUIC_INVALID_VERSION) {
+ std::cerr << "Server talks QUIC, but none of the versions supported by "
+ << "this client: " << ParsedQuicVersionVectorToString(versions)
+ << std::endl;
+ // 0: No error.
+ // 20: Failed to connect due to QUIC_INVALID_VERSION.
+ return GetQuicFlag(FLAGS_version_mismatch_ok) ? 0 : 20;
+ }
+ std::cerr << "Failed to connect to " << host << ":" << port
+ << ". Error: " << quic::QuicErrorCodeToString(error) << std::endl;
+ return 1;
+ }
+ std::cerr << "Connected to " << host << ":" << port << std::endl;
+
+ // Construct the string body from flags, if provided.
+ std::string body = GetQuicFlag(FLAGS_body);
+ if (!GetQuicFlag(FLAGS_body_hex).empty()) {
+ DCHECK(GetQuicFlag(FLAGS_body).empty())
+ << "Only set one of --body and --body_hex.";
+ body = QuicTextUtils::HexDecode(GetQuicFlag(FLAGS_body_hex));
+ }
+
+ // Construct a GET or POST request for supplied URL.
+ spdy::SpdyHeaderBlock header_block;
+ header_block[":method"] = body.empty() ? "GET" : "POST";
+ header_block[":scheme"] = url.scheme();
+ header_block[":authority"] = url.HostPort();
+ header_block[":path"] = url.PathParamsQuery();
+
+ // Append any additional headers supplied on the command line.
+ const std::string headers = GetQuicFlag(FLAGS_headers);
+ for (QuicStringPiece sp : QuicTextUtils::Split(headers, ';')) {
+ QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&sp);
+ if (sp.empty()) {
+ continue;
+ }
+ std::vector<QuicStringPiece> kv = QuicTextUtils::Split(sp, ':');
+ QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[0]);
+ QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[1]);
+ header_block[kv[0]] = kv[1];
+ }
+
+ // Make sure to store the response, for later output.
+ client->set_store_response(true);
+
+ for (int i = 0; i < num_requests; ++i) {
+ // Send the request.
+ client->SendRequestAndWaitForResponse(header_block, body, /*fin=*/true);
+
+ // Print request and response details.
+ if (!GetQuicFlag(FLAGS_quiet)) {
+ std::cout << "Request:" << std::endl;
+ std::cout << "headers:" << header_block.DebugString();
+ if (!GetQuicFlag(FLAGS_body_hex).empty()) {
+ // Print the user provided hex, rather than binary body.
+ std::cout << "body:\n"
+ << QuicTextUtils::HexDump(
+ QuicTextUtils::HexDecode(GetQuicFlag(FLAGS_body_hex)))
+ << std::endl;
+ } else {
+ std::cout << "body: " << body << std::endl;
+ }
+ std::cout << std::endl;
+
+ if (!client->preliminary_response_headers().empty()) {
+ std::cout << "Preliminary response headers: "
+ << client->preliminary_response_headers() << std::endl;
+ std::cout << std::endl;
+ }
+
+ std::cout << "Response:" << std::endl;
+ std::cout << "headers: " << client->latest_response_headers()
+ << std::endl;
+ std::string response_body = client->latest_response_body();
+ if (!GetQuicFlag(FLAGS_body_hex).empty()) {
+ // Assume response is binary data.
+ std::cout << "body:\n"
+ << QuicTextUtils::HexDump(response_body) << std::endl;
+ } else {
+ std::cout << "body: " << response_body << std::endl;
+ }
+ std::cout << "trailers: " << client->latest_response_trailers()
+ << std::endl;
+ }
+
+ if (!client->connected()) {
+ std::cerr << "Request caused connection failure. Error: "
+ << quic::QuicErrorCodeToString(client->session()->error())
+ << std::endl;
+ return 1;
+ }
+
+ size_t response_code = client->latest_response_code();
+ if (response_code >= 200 && response_code < 300) {
+ std::cout << "Request succeeded (" << response_code << ")." << std::endl;
+ } else if (response_code >= 300 && response_code < 400) {
+ if (GetQuicFlag(FLAGS_redirect_is_success)) {
+ std::cout << "Request succeeded (redirect " << response_code << ")."
+ << std::endl;
+ } else {
+ std::cout << "Request failed (redirect " << response_code << ")."
+ << std::endl;
+ return 1;
+ }
+ } else {
+ std::cout << "Request failed (" << response_code << ")." << std::endl;
+ return 1;
+ }
+
+ // Change the ephemeral port if there are more requests to do.
+ if (i + 1 < num_requests) {
+ if (!client->ChangeEphemeralPort()) {
+ std::cerr << "Failed to change ephemeral port." << std::endl;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.h b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.h
new file mode 100644
index 00000000000..e832ac76697
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.h
@@ -0,0 +1,45 @@
+// 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.
+
+// A toy client, which connects to a specified port and sends QUIC
+// requests to that endpoint.
+
+#ifndef QUICHE_QUIC_TOOLS_QUIC_TOY_CLIENT_H_
+#define QUICHE_QUIC_TOOLS_QUIC_TOY_CLIENT_H_
+
+#include "net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h"
+
+namespace quic {
+
+class QuicToyClient {
+ public:
+ class ClientFactory {
+ public:
+ virtual ~ClientFactory() = default;
+
+ // Creates a new client configured to connect to |host:port| supporting
+ // |versions|, and using |verifier| to verify proofs.
+ virtual std::unique_ptr<QuicSpdyClientBase> CreateClient(
+ std::string host,
+ uint16_t port,
+ ParsedQuicVersionVector versions,
+ std::unique_ptr<ProofVerifier> verifier) = 0;
+ };
+
+ // Constructs a new toy client that will use |client_factory| to create the
+ // actual QuicSpdyClientBase instance.
+ QuicToyClient(ClientFactory* client_factory);
+
+ // Connects to the QUIC server based on the various flags defined in the
+ // .cc file, sends requests and prints the responses. Returns 0 on success
+ // and non-zero otherwise.
+ int SendRequestsAndPrintResponses(std::vector<std::string> urls);
+
+ private:
+ ClientFactory* client_factory_; // Unowned.
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_TOOLS_QUIC_TOY_CLIENT_H_
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
new file mode 100644
index 00000000000..633b465960e
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.cc
@@ -0,0 +1,73 @@
+// 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/tools/quic_toy_server.h"
+
+#include <vector>
+
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_default_proof_providers.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_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/tools/quic_memory_cache_backend.h"
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t,
+ port,
+ 6121,
+ "The port the quic server will listen on.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ std::string,
+ quic_response_cache_dir,
+ "",
+ "Specifies the directory used during QuicHttpResponseCache "
+ "construction to seed the cache. Cache directory can be "
+ "generated using `wget -p --save-headers <url>`");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+ int32_t,
+ quic_ietf_draft,
+ 0,
+ "QUIC IETF draft number to use over the wire, e.g. 18. "
+ "This also enables required internal QUIC flags.");
+
+namespace quic {
+
+std::unique_ptr<quic::QuicSimpleServerBackend>
+QuicToyServer::MemoryCacheBackendFactory::CreateBackend() {
+ auto memory_cache_backend = QuicMakeUnique<QuicMemoryCacheBackend>();
+ if (!GetQuicFlag(FLAGS_quic_response_cache_dir).empty()) {
+ memory_cache_backend->InitializeBackend(
+ GetQuicFlag(FLAGS_quic_response_cache_dir));
+ }
+ return memory_cache_backend;
+}
+
+QuicToyServer::QuicToyServer(BackendFactory* backend_factory,
+ ServerFactory* server_factory)
+ : backend_factory_(backend_factory), server_factory_(server_factory) {}
+
+int QuicToyServer::Start() {
+ const int32_t quic_ietf_draft = GetQuicFlag(FLAGS_quic_ietf_draft);
+ if (quic_ietf_draft > 0) {
+ quic::QuicVersionInitializeSupportForIetfDraft(quic_ietf_draft);
+ quic::QuicEnableVersion(
+ quic::ParsedQuicVersion(quic::PROTOCOL_TLS1_3, quic::QUIC_VERSION_99));
+ }
+ auto proof_source = quic::CreateDefaultProofSource();
+ auto backend = backend_factory_->CreateBackend();
+ auto server =
+ server_factory_->CreateServer(backend.get(), std::move(proof_source));
+
+ if (!server->CreateUDPSocketAndListen(quic::QuicSocketAddress(
+ quic::QuicIpAddress::Any6(), GetQuicFlag(FLAGS_port)))) {
+ return 1;
+ }
+
+ server->HandleEventsForever();
+ return 0;
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.h b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.h
new file mode 100644
index 00000000000..6c5c486c493
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_server.h
@@ -0,0 +1,62 @@
+// 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_TOOLS_QUIC_TOY_SERVER_H_
+#define QUICHE_QUIC_TOOLS_QUIC_TOY_SERVER_H_
+
+#include "net/third_party/quiche/src/quic/core/crypto/proof_source.h"
+#include "net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h"
+#include "net/third_party/quiche/src/quic/tools/quic_spdy_server_base.h"
+
+namespace quic {
+
+// A binary wrapper for QuicServer. It listens forever on --port
+// (default 6121) until it's killed or ctrl-cd to death.
+class QuicToyServer {
+ public:
+ // A factory for creating QuicSpdyServerBase instances.
+ class ServerFactory {
+ public:
+ virtual ~ServerFactory() = default;
+
+ // Creates a QuicSpdyServerBase instance using |backend| for generating
+ // responses, and |proof_source| for certificates.
+ virtual std::unique_ptr<QuicSpdyServerBase> CreateServer(
+ QuicSimpleServerBackend* backend,
+ std::unique_ptr<ProofSource> proof_source) = 0;
+ };
+
+ // A facotry for creating QuicSimpleServerBackend instances.
+ class BackendFactory {
+ public:
+ virtual ~BackendFactory() = default;
+
+ // Creates a new backend.
+ virtual std::unique_ptr<QuicSimpleServerBackend> CreateBackend() = 0;
+ };
+
+ // A factory for creating QuicMemoryCacheBackend instances, configured
+ // to load files from disk, if necessary.
+ class MemoryCacheBackendFactory : public BackendFactory {
+ public:
+ std::unique_ptr<quic::QuicSimpleServerBackend> CreateBackend() override;
+ };
+
+ // Constructs a new toy server that will use |server_factory| to create the
+ // actual QuicSpdyServerBase instance.
+ QuicToyServer(BackendFactory* backend_factory, ServerFactory* server_factory);
+
+ // Connects to the QUIC server based on the various flags defined in the
+ // .cc file, listends for requests and sends the responses. Returns 1 on
+ // failure and does not return otherwise.
+ int Start();
+
+ private:
+ BackendFactory* backend_factory_; // Unowned.
+ ServerFactory* server_factory_; // Unowned.
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_TOOLS_QUIC_TOY_SERVER_H_
diff --git a/chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler.h b/chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler.h
index b02d4634715..067153ba8bc 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler.h
@@ -45,7 +45,9 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
using typename WriteScheduler<StreamIdType>::StreamPrecedenceType;
// Creates scheduler with no streams.
- PriorityWriteScheduler() = default;
+ PriorityWriteScheduler() : PriorityWriteScheduler(kHttp2RootStreamId) {}
+ explicit PriorityWriteScheduler(StreamIdType root_stream_id)
+ : root_stream_id_(root_stream_id) {}
void RegisterStream(StreamIdType stream_id,
const StreamPrecedenceType& precedence) override {
@@ -55,12 +57,12 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
// parent_id not used here, but may as well validate it. However,
// parent_id may legitimately not be registered yet--see b/15676312.
StreamIdType parent_id = precedence.parent_id();
- SPDY_DVLOG_IF(
- 1, parent_id != kHttp2RootStreamId && !StreamRegistered(parent_id))
+ SPDY_DVLOG_IF(1,
+ parent_id != root_stream_id_ && !StreamRegistered(parent_id))
<< "Parent stream " << parent_id << " not registered";
- if (stream_id == kHttp2RootStreamId) {
- SPDY_BUG << "Stream " << kHttp2RootStreamId << " already registered";
+ if (stream_id == root_stream_id_) {
+ SPDY_BUG << "Stream " << root_stream_id_ << " already registered";
return;
}
StreamInfo stream_info = {precedence.spdy3_priority(), stream_id, false};
@@ -106,8 +108,8 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
// parent_id not used here, but may as well validate it. However,
// parent_id may legitimately not be registered yet--see b/15676312.
StreamIdType parent_id = precedence.parent_id();
- SPDY_DVLOG_IF(
- 1, parent_id != kHttp2RootStreamId && !StreamRegistered(parent_id))
+ SPDY_DVLOG_IF(1,
+ parent_id != root_stream_id_ && !StreamRegistered(parent_id))
<< "Parent stream " << parent_id << " not registered";
auto it = stream_infos_.find(stream_id);
@@ -315,6 +317,7 @@ class PriorityWriteScheduler : public WriteScheduler<StreamIdType> {
PriorityInfo priority_infos_[kV3LowestPriority + 1];
// StreamInfos for all registered streams.
StreamInfoMap stream_infos_;
+ StreamIdType root_stream_id_;
};
} // namespace spdy
diff --git a/chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler_test.cc b/chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler_test.cc
index a285cb2e4bd..08a4ff69281 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler_test.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/priority_write_scheduler_test.cc
@@ -7,6 +7,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
#include "net/third_party/quiche/src/spdy/core/spdy_test_utils.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_test_helpers.h"
namespace spdy {
namespace test {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.h b/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.h
index ac172af0942..f5795790e5e 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.h
@@ -180,7 +180,7 @@ class SPDY_EXPORT_PRIVATE SpdyHeaderBlock {
const SpdyStringPiece value);
// Allows either lookup or mutation of the value associated with a key.
- ValueProxy operator[](const SpdyStringPiece key) SPDY_MUST_USE_RESULT;
+ SPDY_MUST_USE_RESULT ValueProxy operator[](const SpdyStringPiece key);
// This object provides automatic conversions that allow SpdyHeaderBlock to be
// nearly a drop-in replacement for SpdyLinkedHashMap<SpdyString, SpdyString>.
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test.cc
index 09a56cbe4f4..fc595a23f06 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test.cc
@@ -11,6 +11,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/spdy/core/spdy_bitmasks.h"
#include "net/third_party/quiche/src/spdy/core/spdy_test_utils.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_test_helpers.h"
namespace spdy {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test_utils.h b/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test_utils.h
index ce2c9d538e7..bb8bea31268 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test_utils.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol_test_utils.h
@@ -21,6 +21,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "net/third_party/quiche/src/http2/platform/api/http2_test_helpers.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
#include "net/third_party/quiche/src/spdy/core/spdy_test_utils.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_logging.h"
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_simple_arena.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_simple_arena.cc
index 08cdc62db0c..f7d48b47017 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_simple_arena.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_simple_arena.cc
@@ -4,6 +4,8 @@
#include "net/third_party/quiche/src/spdy/core/spdy_simple_arena.h"
+#include <algorithm>
+
#include "net/third_party/quiche/src/spdy/platform/api/spdy_logging.h"
namespace spdy {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_test_utils.h b/chromium/net/third_party/quiche/src/spdy/core/spdy_test_utils.h
index bf62eeba930..03a6caf896d 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_test_utils.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_test_utils.h
@@ -8,14 +8,12 @@
#include <cstddef>
#include <cstdint>
-#include "net/third_party/quiche/src/http2/platform/api/http2_test_helpers.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
#include "net/third_party/quiche/src/spdy/core/spdy_headers_handler_interface.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h"
-#include "net/third_party/quiche/src/spdy/platform/api/spdy_test_helpers.h"
namespace spdy {