summaryrefslogtreecommitdiff
path: root/chromium/net/quic
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-05-15 10:20:33 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-05-15 10:28:57 +0000
commitd17ea114e5ef69ad5d5d7413280a13e6428098aa (patch)
tree2c01a75df69f30d27b1432467cfe7c1467a498da /chromium/net/quic
parent8c5c43c7b138c9b4b0bf56d946e61d3bbc111bec (diff)
downloadqtwebengine-chromium-d17ea114e5ef69ad5d5d7413280a13e6428098aa.tar.gz
BASELINE: Update Chromium to 67.0.3396.47
Change-Id: Idcb1341782e417561a2473eeecc82642dafda5b7 Reviewed-by: Michal Klocek <michal.klocek@qt.io>
Diffstat (limited to 'chromium/net/quic')
-rw-r--r--chromium/net/quic/chromium/bidirectional_stream_quic_impl.cc9
-rw-r--r--chromium/net/quic/chromium/bidirectional_stream_quic_impl.h3
-rw-r--r--chromium/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc105
-rw-r--r--chromium/net/quic/chromium/crypto/proof_verifier_chromium_test.cc31
-rw-r--r--chromium/net/quic/chromium/quic_chromium_client_session.cc172
-rw-r--r--chromium/net/quic/chromium/quic_chromium_client_session.h40
-rw-r--r--chromium/net/quic/chromium/quic_chromium_client_session_test.cc77
-rw-r--r--chromium/net/quic/chromium/quic_chromium_client_stream.cc7
-rw-r--r--chromium/net/quic/chromium/quic_chromium_client_stream_test.cc10
-rw-r--r--chromium/net/quic/chromium/quic_chromium_packet_writer.cc53
-rw-r--r--chromium/net/quic/chromium/quic_connection_logger.cc4
-rw-r--r--chromium/net/quic/chromium/quic_connection_logger.h2
-rw-r--r--chromium/net/quic/chromium/quic_connectivity_probing_manager_test.cc4
-rw-r--r--chromium/net/quic/chromium/quic_end_to_end_unittest.cc2
-rw-r--r--chromium/net/quic/chromium/quic_http_stream.cc4
-rw-r--r--chromium/net/quic/chromium/quic_http_stream_test.cc213
-rw-r--r--chromium/net/quic/chromium/quic_http_utils.cc1
-rw-r--r--chromium/net/quic/chromium/quic_http_utils.h1
-rw-r--r--chromium/net/quic/chromium/quic_network_transaction_unittest.cc149
-rw-r--r--chromium/net/quic/chromium/quic_proxy_client_socket_unittest.cc11
-rw-r--r--chromium/net/quic/chromium/quic_stream_factory.cc4
-rw-r--r--chromium/net/quic/chromium/quic_stream_factory.h20
-rw-r--r--chromium/net/quic/chromium/quic_stream_factory_test.cc16
-rw-r--r--chromium/net/quic/chromium/quic_test_packet_maker.cc90
-rw-r--r--chromium/net/quic/chromium/quic_test_packet_maker.h25
-rw-r--r--chromium/net/quic/core/congestion_control/bandwidth_sampler.h4
-rw-r--r--chromium/net/quic/core/congestion_control/bbr_sender.cc13
-rw-r--r--chromium/net/quic/core/congestion_control/bbr_sender.h2
-rw-r--r--chromium/net/quic/core/congestion_control/bbr_sender_test.cc6
-rw-r--r--chromium/net/quic/core/congestion_control/rtt_stats.cc8
-rw-r--r--chromium/net/quic/core/congestion_control/rtt_stats_test.cc28
-rw-r--r--chromium/net/quic/core/congestion_control/send_algorithm_interface.h4
-rw-r--r--chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc54
-rw-r--r--chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.h3
-rw-r--r--chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc7
-rw-r--r--chromium/net/quic/core/crypto/cert_compressor.cc6
-rw-r--r--chromium/net/quic/core/crypto/common_cert_set.cc5
-rw-r--r--chromium/net/quic/core/crypto/crypto_framer.cc24
-rw-r--r--chromium/net/quic/core/crypto/crypto_framer.h7
-rw-r--r--chromium/net/quic/core/crypto/crypto_handshake_message.cc7
-rw-r--r--chromium/net/quic/core/crypto/crypto_handshake_message.h4
-rw-r--r--chromium/net/quic/core/crypto/crypto_server_test.cc8
-rw-r--r--chromium/net/quic/core/crypto/crypto_utils.cc101
-rw-r--r--chromium/net/quic/core/crypto/crypto_utils.h44
-rw-r--r--chromium/net/quic/core/crypto/crypto_utils_test.cc14
-rw-r--r--chromium/net/quic/core/crypto/null_decrypter.cc18
-rw-r--r--chromium/net/quic/core/crypto/null_decrypter.h11
-rw-r--r--chromium/net/quic/core/crypto/null_encrypter.cc2
-rw-r--r--chromium/net/quic/core/crypto/quic_crypto_client_config.cc17
-rw-r--r--chromium/net/quic/core/crypto/quic_crypto_server_config.cc19
-rw-r--r--chromium/net/quic/core/crypto/quic_crypto_server_config_test.cc3
-rw-r--r--chromium/net/quic/core/crypto/quic_decrypter.cc27
-rw-r--r--chromium/net/quic/core/crypto/quic_decrypter.h3
-rw-r--r--chromium/net/quic/core/crypto/quic_encrypter.cc19
-rw-r--r--chromium/net/quic/core/crypto/quic_encrypter.h5
-rw-r--r--chromium/net/quic/core/crypto/quic_random.cc5
-rw-r--r--chromium/net/quic/core/frames/quic_connection_close_frame.cc4
-rw-r--r--chromium/net/quic/core/frames/quic_connection_close_frame.h1
-rw-r--r--chromium/net/quic/core/frames/quic_frame.h6
-rw-r--r--chromium/net/quic/core/frames/quic_ietf_blocked_frame.cc21
-rw-r--r--chromium/net/quic/core/frames/quic_ietf_blocked_frame.h32
-rw-r--r--chromium/net/quic/core/frames/quic_ietf_max_stream_id_frame.cc23
-rw-r--r--chromium/net/quic/core/frames/quic_ietf_max_stream_id_frame.h32
-rw-r--r--chromium/net/quic/core/frames/quic_ietf_stream_id_blocked_frame.cc23
-rw-r--r--chromium/net/quic/core/frames/quic_ietf_stream_id_blocked_frame.h33
-rw-r--r--chromium/net/quic/core/frames/quic_path_challenge_frame.cc35
-rw-r--r--chromium/net/quic/core/frames/quic_path_challenge_frame.h37
-rw-r--r--chromium/net/quic/core/frames/quic_path_response_frame.cc34
-rw-r--r--chromium/net/quic/core/frames/quic_path_response_frame.h37
-rw-r--r--chromium/net/quic/core/frames/quic_stop_sending_frame.cc27
-rw-r--r--chromium/net/quic/core/frames/quic_stop_sending_frame.h31
-rw-r--r--chromium/net/quic/core/frames/quic_window_update_frame.h4
-rw-r--r--chromium/net/quic/core/quic_buffered_packet_store.cc5
-rw-r--r--chromium/net/quic/core/quic_buffered_packet_store.h3
-rw-r--r--chromium/net/quic/core/quic_buffered_packet_store_test.cc84
-rw-r--r--chromium/net/quic/core/quic_client_promised_info_test.cc87
-rw-r--r--chromium/net/quic/core/quic_config.cc15
-rw-r--r--chromium/net/quic/core/quic_config.h22
-rw-r--r--chromium/net/quic/core/quic_config_test.cc4
-rw-r--r--chromium/net/quic/core/quic_connection.cc752
-rw-r--r--chromium/net/quic/core/quic_connection.h227
-rw-r--r--chromium/net/quic/core/quic_connection_test.cc1036
-rw-r--r--chromium/net/quic/core/quic_constants.h12
-rw-r--r--chromium/net/quic/core/quic_control_frame_manager.cc9
-rw-r--r--chromium/net/quic/core/quic_control_frame_manager_test.cc1
-rw-r--r--chromium/net/quic/core/quic_crypto_client_handshaker.cc12
-rw-r--r--chromium/net/quic/core/quic_crypto_client_stream_test.cc1
-rw-r--r--chromium/net/quic/core/quic_crypto_server_handshaker.cc8
-rw-r--r--chromium/net/quic/core/quic_crypto_server_stream.cc3
-rw-r--r--chromium/net/quic/core/quic_crypto_stream.cc2
-rw-r--r--chromium/net/quic/core/quic_crypto_stream_test.cc80
-rw-r--r--chromium/net/quic/core/quic_data_reader.cc14
-rw-r--r--chromium/net/quic/core/quic_data_reader.h9
-rw-r--r--chromium/net/quic/core/quic_data_writer.h1
-rw-r--r--chromium/net/quic/core/quic_data_writer_test.cc43
-rw-r--r--chromium/net/quic/core/quic_error_codes.h35
-rw-r--r--chromium/net/quic/core/quic_flags_list.h146
-rw-r--r--chromium/net/quic/core/quic_flow_controller.cc12
-rw-r--r--chromium/net/quic/core/quic_flow_controller_test.cc62
-rw-r--r--chromium/net/quic/core/quic_framer.cc448
-rw-r--r--chromium/net/quic/core/quic_framer.h141
-rw-r--r--chromium/net/quic/core/quic_framer_test.cc720
-rw-r--r--chromium/net/quic/core/quic_headers_stream.cc3
-rw-r--r--chromium/net/quic/core/quic_headers_stream_test.cc6
-rw-r--r--chromium/net/quic/core/quic_ietf_framer_test.cc727
-rw-r--r--chromium/net/quic/core/quic_packet_creator.cc44
-rw-r--r--chromium/net/quic/core/quic_packet_creator.h26
-rw-r--r--chromium/net/quic/core/quic_packet_creator_test.cc35
-rw-r--r--chromium/net/quic/core/quic_packet_generator.cc11
-rw-r--r--chromium/net/quic/core/quic_packet_generator.h4
-rw-r--r--chromium/net/quic/core/quic_packet_generator_test.cc32
-rw-r--r--chromium/net/quic/core/quic_packets.cc15
-rw-r--r--chromium/net/quic/core/quic_packets.h12
-rw-r--r--chromium/net/quic/core/quic_sent_packet_manager.cc224
-rw-r--r--chromium/net/quic/core/quic_sent_packet_manager.h80
-rw-r--r--chromium/net/quic/core/quic_sent_packet_manager_test.cc485
-rw-r--r--chromium/net/quic/core/quic_server_session_base_test.cc55
-rw-r--r--chromium/net/quic/core/quic_session.cc173
-rw-r--r--chromium/net/quic/core/quic_session.h43
-rw-r--r--chromium/net/quic/core/quic_session_test.cc1427
-rw-r--r--chromium/net/quic/core/quic_spdy_session.cc59
-rw-r--r--chromium/net/quic/core/quic_spdy_session.h9
-rw-r--r--chromium/net/quic/core/quic_spdy_session_test.cc395
-rw-r--r--chromium/net/quic/core/quic_spdy_stream.cc29
-rw-r--r--chromium/net/quic/core/quic_spdy_stream.h14
-rw-r--r--chromium/net/quic/core/quic_spdy_stream_test.cc30
-rw-r--r--chromium/net/quic/core/quic_stream.cc86
-rw-r--r--chromium/net/quic/core/quic_stream.h27
-rw-r--r--chromium/net/quic/core/quic_stream_send_buffer.cc152
-rw-r--r--chromium/net/quic/core/quic_stream_send_buffer.h23
-rw-r--r--chromium/net/quic/core/quic_stream_send_buffer_test.cc45
-rw-r--r--chromium/net/quic/core/quic_stream_sequencer_buffer.cc35
-rw-r--r--chromium/net/quic/core/quic_stream_sequencer_test.cc3
-rw-r--r--chromium/net/quic/core/quic_stream_test.cc60
-rw-r--r--chromium/net/quic/core/quic_types.h19
-rw-r--r--chromium/net/quic/core/quic_unacked_packet_map.cc6
-rw-r--r--chromium/net/quic/core/quic_unacked_packet_map.h6
-rw-r--r--chromium/net/quic/core/quic_utils.cc59
-rw-r--r--chromium/net/quic/core/quic_utils.h19
-rw-r--r--chromium/net/quic/core/quic_utils_test.cc10
-rw-r--r--chromium/net/quic/core/quic_versions.cc13
-rw-r--r--chromium/net/quic/core/quic_versions.h6
-rw-r--r--chromium/net/quic/core/quic_write_blocked_list.cc7
-rw-r--r--chromium/net/quic/core/quic_write_blocked_list.h180
-rw-r--r--chromium/net/quic/core/quic_write_blocked_list_test.cc95
-rw-r--r--chromium/net/quic/core/tls_client_handshaker.cc30
-rw-r--r--chromium/net/quic/core/tls_handshaker.cc45
-rw-r--r--chromium/net/quic/core/tls_handshaker.h6
-rw-r--r--chromium/net/quic/core/tls_handshaker_test.cc64
-rw-r--r--chromium/net/quic/core/tls_server_handshaker.cc30
-rw-r--r--chromium/net/quic/http/decoder/quic_http_frame_decoder_adapter.cc9
-rw-r--r--chromium/net/quic/http/quic_http_structures.h1
-rw-r--r--chromium/net/quic/http/tools/quic_http_random_util.cc16
-rw-r--r--chromium/net/quic/http/tools/quic_http_random_util.h9
-rw-r--r--chromium/net/quic/platform/api/quic_logging.h2
-rw-r--r--chromium/net/quic/platform/api/quic_mem_slice.h4
-rw-r--r--chromium/net/quic/platform/api/quic_singleton.h48
-rw-r--r--chromium/net/quic/platform/api/quic_singleton_test.cc32
-rw-r--r--chromium/net/quic/platform/api/quic_test.h2
-rw-r--r--chromium/net/quic/platform/api/quic_uint128.h19
-rw-r--r--chromium/net/quic/platform/impl/quic_logging_impl.h2
-rw-r--r--chromium/net/quic/platform/impl/quic_mem_slice_impl.cc5
-rw-r--r--chromium/net/quic/platform/impl/quic_mem_slice_impl.h4
-rw-r--r--chromium/net/quic/platform/impl/quic_singleton_impl.h20
-rw-r--r--chromium/net/quic/platform/impl/quic_test_impl.cc14
-rw-r--r--chromium/net/quic/platform/impl/quic_test_impl.h37
-rw-r--r--chromium/net/quic/platform/impl/quic_uint128_impl.h19
-rw-r--r--chromium/net/quic/quartc/quartc_factory.cc21
-rw-r--r--chromium/net/quic/quartc/quartc_factory_interface.h6
-rw-r--r--chromium/net/quic/quartc/quartc_session.cc28
-rw-r--r--chromium/net/quic/quartc/quartc_session.h2
-rw-r--r--chromium/net/quic/quartc/quartc_session_interface.h4
-rw-r--r--chromium/net/quic/quartc/quartc_session_test.cc16
-rw-r--r--chromium/net/quic/quartc/quartc_session_visitor_interface.h27
-rw-r--r--chromium/net/quic/quartc/quartc_stream.cc36
-rw-r--r--chromium/net/quic/quartc/quartc_stream.h16
-rw-r--r--chromium/net/quic/quartc/quartc_stream_interface.h18
-rw-r--r--chromium/net/quic/quartc/quartc_stream_test.cc89
-rw-r--r--chromium/net/quic/test_tools/crypto_test_utils.cc38
-rw-r--r--chromium/net/quic/test_tools/mock_crypto_client_stream.cc33
-rw-r--r--chromium/net/quic/test_tools/quic_config_peer.cc13
-rw-r--r--chromium/net/quic/test_tools/quic_config_peer.h6
-rw-r--r--chromium/net/quic/test_tools/quic_connection_peer.cc26
-rw-r--r--chromium/net/quic/test_tools/quic_connection_peer.h10
-rw-r--r--chromium/net/quic/test_tools/quic_framer_peer.cc199
-rw-r--r--chromium/net/quic/test_tools/quic_framer_peer.h95
-rw-r--r--chromium/net/quic/test_tools/quic_packet_creator_peer.cc4
-rw-r--r--chromium/net/quic/test_tools/quic_sent_packet_manager_peer.cc14
-rw-r--r--chromium/net/quic/test_tools/quic_sent_packet_manager_peer.h6
-rw-r--r--chromium/net/quic/test_tools/quic_stream_send_buffer_peer.cc11
-rw-r--r--chromium/net/quic/test_tools/quic_stream_send_buffer_peer.h2
-rw-r--r--chromium/net/quic/test_tools/quic_test_utils.cc33
-rw-r--r--chromium/net/quic/test_tools/quic_test_utils.h29
-rw-r--r--chromium/net/quic/test_tools/simple_quic_framer.cc11
-rw-r--r--chromium/net/quic/test_tools/simple_session_notifier.cc14
-rw-r--r--chromium/net/quic/test_tools/simple_session_notifier.h3
-rw-r--r--chromium/net/quic/test_tools/simple_session_notifier_test.cc7
-rw-r--r--chromium/net/quic/test_tools/simulator/quic_endpoint.cc4
-rw-r--r--chromium/net/quic/test_tools/simulator/quic_endpoint.h1
-rw-r--r--chromium/net/quic/test_tools/simulator/quic_endpoint_test.cc2
200 files changed, 8630 insertions, 3306 deletions
diff --git a/chromium/net/quic/chromium/bidirectional_stream_quic_impl.cc b/chromium/net/quic/chromium/bidirectional_stream_quic_impl.cc
index e809c3e1634..b2c48aec8a8 100644
--- a/chromium/net/quic/chromium/bidirectional_stream_quic_impl.cc
+++ b/chromium/net/quic/chromium/bidirectional_stream_quic_impl.cc
@@ -12,6 +12,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/timer/timer.h"
#include "net/http/bidirectional_stream_request_info.h"
+#include "net/http/http_util.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/platform/api/quic_string_piece.h"
#include "net/socket/next_proto.h"
@@ -68,7 +69,8 @@ void BidirectionalStreamQuicImpl::Start(
const NetLogWithSource& net_log,
bool send_request_headers_automatically,
BidirectionalStreamImpl::Delegate* delegate,
- std::unique_ptr<base::Timer> /* timer */) {
+ std::unique_ptr<base::Timer> timer,
+ const NetworkTrafficAnnotationTag& traffic_annotation) {
ScopedBoolSaver saver(&may_invoke_callbacks_, false);
DCHECK(!stream_);
CHECK(delegate);
@@ -79,12 +81,11 @@ void BidirectionalStreamQuicImpl::Start(
delegate_ = delegate;
request_info_ = request_info;
- // TODO(https://crbug.com/656607): Add proper annotation here.
int rv = session_->RequestStream(
- request_info_->method == "POST",
+ !HttpUtil::IsMethodSafe(request_info_->method),
base::Bind(&BidirectionalStreamQuicImpl::OnStreamReady,
weak_factory_.GetWeakPtr()),
- NO_TRAFFIC_ANNOTATION_BUG_656607);
+ traffic_annotation);
if (rv == ERR_IO_PENDING)
return;
diff --git a/chromium/net/quic/chromium/bidirectional_stream_quic_impl.h b/chromium/net/quic/chromium/bidirectional_stream_quic_impl.h
index 8b63600bd90..00a70d2cccb 100644
--- a/chromium/net/quic/chromium/bidirectional_stream_quic_impl.h
+++ b/chromium/net/quic/chromium/bidirectional_stream_quic_impl.h
@@ -41,7 +41,8 @@ class NET_EXPORT_PRIVATE BidirectionalStreamQuicImpl
const NetLogWithSource& net_log,
bool send_request_headers_automatically,
BidirectionalStreamImpl::Delegate* delegate,
- std::unique_ptr<base::Timer> timer) override;
+ std::unique_ptr<base::Timer> timer,
+ const NetworkTrafficAnnotationTag& traffic_annotation) override;
void SendRequestHeaders() override;
int ReadData(IOBuffer* buffer, int buffer_len) override;
void SendvData(const std::vector<scoped_refptr<IOBuffer>>& buffers,
diff --git a/chromium/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc b/chromium/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
index 79794cdfafc..fac7558c616 100644
--- a/chromium/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
+++ b/chromium/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
@@ -28,6 +28,7 @@
#include "net/quic/chromium/quic_chromium_packet_writer.h"
#include "net/quic/chromium/quic_http_utils.h"
#include "net/quic/chromium/quic_server_info.h"
+#include "net/quic/chromium/quic_stream_factory.h"
#include "net/quic/chromium/quic_test_packet_maker.h"
#include "net/quic/chromium/test_task_runner.h"
#include "net/quic/core/crypto/crypto_protocol.h"
@@ -46,6 +47,7 @@
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/socket/socket_test_util.h"
#include "net/test/gtest_util.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -167,7 +169,7 @@ class TestDelegateBase : public BidirectionalStreamImpl::Delegate {
not_expect_callback_ = true;
stream_ = std::make_unique<BidirectionalStreamQuicImpl>(std::move(session));
stream_->Start(request_info, net_log, send_request_headers_automatically_,
- this, nullptr);
+ this, nullptr, TRAFFIC_ANNOTATION_FOR_TESTS);
not_expect_callback_ = false;
}
@@ -990,28 +992,16 @@ TEST_P(BidirectionalStreamQuicImplTest, CoalesceDataBuffersNotHeadersFrame) {
AddWrite(ConstructRequestHeadersPacketInner(
2, GetNthClientInitiatedStreamId(0), !kFin, DEFAULT_PRIORITY,
&spdy_request_headers_frame_length, &header_stream_offset));
- if (FLAGS_quic_reloadable_flag_quic_use_mem_slices) {
- AddWrite(ConstructDataPacket(3, kIncludeVersion, !kFin, 0,
- "here are some datadata keep coming",
- &client_maker_));
- } else {
AddWrite(ConstructClientMultipleDataFramesPacket(3, kIncludeVersion, !kFin,
0, {kBody1, kBody2}));
- }
// Ack server's data packet.
AddWrite(ConstructClientAckPacket(4, 3, 1, 1));
const char kBody3[] = "hello there";
const char kBody4[] = "another piece of small data";
const char kBody5[] = "really small";
QuicStreamOffset data_offset = strlen(kBody1) + strlen(kBody2);
- if (FLAGS_quic_reloadable_flag_quic_use_mem_slices) {
- AddWrite(ConstructDataPacket(
- 5, !kIncludeVersion, kFin, data_offset,
- "hello thereanother piece of small datareally small", &client_maker_));
- } else {
AddWrite(ConstructClientMultipleDataFramesPacket(
5, !kIncludeVersion, kFin, data_offset, {kBody3, kBody4, kBody5}));
- }
Initialize();
BidirectionalStreamRequestInfo request;
@@ -1207,27 +1197,18 @@ TEST_P(BidirectionalStreamQuicImplTest,
AddWrite(ConstructInitialSettingsPacket(1, &header_stream_offset));
const char kBody1[] = "here are some data";
const char kBody2[] = "data keep coming";
- const char kBody1And2[] = "here are some datadata keep coming";
std::vector<std::string> two_writes = {kBody1, kBody2};
- std::vector<std::string> one_write = {kBody1And2};
AddWrite(ConstructRequestHeadersAndMultipleDataFramesPacket(
2, !kFin, DEFAULT_PRIORITY, &header_stream_offset,
- &spdy_request_headers_frame_length,
- FLAGS_quic_reloadable_flag_quic_use_mem_slices ? one_write : two_writes));
+ &spdy_request_headers_frame_length, two_writes));
// Ack server's data packet.
AddWrite(ConstructClientAckPacket(3, 3, 1, 1));
const char kBody3[] = "hello there";
const char kBody4[] = "another piece of small data";
const char kBody5[] = "really small";
QuicStreamOffset data_offset = strlen(kBody1) + strlen(kBody2);
- if (FLAGS_quic_reloadable_flag_quic_use_mem_slices) {
- AddWrite(ConstructDataPacket(
- 4, !kIncludeVersion, kFin, data_offset,
- "hello thereanother piece of small datareally small", &client_maker_));
- } else {
AddWrite(ConstructClientMultipleDataFramesPacket(
4, !kIncludeVersion, kFin, data_offset, {kBody3, kBody4, kBody5}));
- }
Initialize();
BidirectionalStreamRequestInfo request;
@@ -1465,84 +1446,6 @@ TEST_P(BidirectionalStreamQuicImplTest, PostRequest) {
delegate->GetTotalReceivedBytes());
}
-TEST_P(BidirectionalStreamQuicImplTest, PutRequest) {
- SetRequest("PUT", "/", DEFAULT_PRIORITY);
- size_t spdy_request_headers_frame_length;
- AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY,
- &spdy_request_headers_frame_length));
- AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin, 0, kUploadData,
- &client_maker_));
- AddWrite(ConstructClientAckPacket(3, 3, 1, 1));
-
- Initialize();
-
- BidirectionalStreamRequestInfo request;
- request.method = "PUT";
- request.url = GURL("http://www.google.com/");
- request.end_stream_on_headers = false;
- request.priority = DEFAULT_PRIORITY;
-
- scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
- std::unique_ptr<TestDelegateBase> delegate(
- new TestDelegateBase(read_buffer.get(), kReadBufferSize));
- delegate->Start(&request, net_log().bound(),
- session()->CreateHandle(destination_));
- delegate->WaitUntilNextCallback(kOnStreamReady);
-
- // Send a DATA frame.
- scoped_refptr<StringIOBuffer> buf(new StringIOBuffer(kUploadData));
-
- delegate->SendData(buf, buf->size(), true);
- delegate->WaitUntilNextCallback(kOnDataSent);
-
- // Server acks the request.
- ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
-
- // Server sends the response headers.
- SpdyHeaderBlock response_headers = ConstructResponseHeaders("200");
- size_t spdy_response_headers_frame_length;
- QuicStreamOffset offset = 0;
- ProcessPacket(ConstructResponseHeadersPacket(
- 2, !kFin, std::move(response_headers),
- &spdy_response_headers_frame_length, &offset));
-
- delegate->WaitUntilNextCallback(kOnHeadersReceived);
- TestCompletionCallback cb;
- int rv = delegate->ReadData(cb.callback());
- EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
- EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
- const char kResponseBody[] = "Hello world!";
- // Server sends data.
- ProcessPacket(
- ConstructServerDataPacket(3, !kIncludeVersion, !kFin, 0, kResponseBody));
-
- EXPECT_EQ(static_cast<int>(strlen(kResponseBody)), cb.WaitForResult());
-
- size_t spdy_trailers_frame_length;
- SpdyHeaderBlock trailers;
- trailers["foo"] = "bar";
- trailers[kFinalOffsetHeaderKey] = base::IntToString(strlen(kResponseBody));
- // Server sends trailers.
- ProcessPacket(ConstructResponseTrailersPacket(
- 4, kFin, trailers.Clone(), &spdy_trailers_frame_length, &offset));
-
- delegate->WaitUntilNextCallback(kOnTrailersReceived);
- trailers.erase(kFinalOffsetHeaderKey);
- EXPECT_EQ(trailers, delegate->trailers());
- EXPECT_THAT(delegate->ReadData(cb.callback()), IsOk());
-
- EXPECT_EQ(1, delegate->on_data_read_count());
- EXPECT_EQ(1, delegate->on_data_sent_count());
- EXPECT_EQ(kProtoQUIC, delegate->GetProtocol());
- EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length +
- strlen(kUploadData)),
- delegate->GetTotalSentBytes());
- EXPECT_EQ(
- static_cast<int64_t>(spdy_response_headers_frame_length +
- strlen(kResponseBody) + spdy_trailers_frame_length),
- delegate->GetTotalReceivedBytes());
-}
-
TEST_P(BidirectionalStreamQuicImplTest, InterleaveReadDataAndSendData) {
SetRequest("POST", "/", DEFAULT_PRIORITY);
size_t spdy_request_headers_frame_length;
diff --git a/chromium/net/quic/chromium/crypto/proof_verifier_chromium_test.cc b/chromium/net/quic/chromium/crypto/proof_verifier_chromium_test.cc
index 696efbbad07..942b88a118c 100644
--- a/chromium/net/quic/chromium/crypto/proof_verifier_chromium_test.cc
+++ b/chromium/net/quic/chromium/crypto/proof_verifier_chromium_test.cc
@@ -62,8 +62,10 @@ class MockCTPolicyEnforcer : public CTPolicyEnforcer {
class MockRequireCTDelegate : public TransportSecurityState::RequireCTDelegate {
public:
- MOCK_METHOD1(IsCTRequiredForHost,
- CTRequirementLevel(const std::string& host));
+ MOCK_METHOD3(IsCTRequiredForHost,
+ CTRequirementLevel(const std::string& host,
+ const X509Certificate* chain,
+ const HashValueVector& hashes));
};
// Proof source callback which saves the signature into |signature|.
@@ -114,9 +116,8 @@ class ProofVerifierChromiumTest : public ::testing::Test {
.WillRepeatedly(
Return(ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS));
- scoped_refptr<const CTLogVerifier> log(
- CTLogVerifier::Create(ct::GetTestPublicKey(), kLogDescription,
- "https://test.example.com", "dns.example.com"));
+ scoped_refptr<const CTLogVerifier> log(CTLogVerifier::Create(
+ ct::GetTestPublicKey(), kLogDescription, "dns.example.com"));
ASSERT_TRUE(log);
log_verifiers_.push_back(log);
@@ -597,10 +598,10 @@ TEST_F(ProofVerifierChromiumTest, CTIsRequired) {
// Set up CT.
MockRequireCTDelegate require_ct_delegate;
transport_security_state_.SetRequireCTDelegate(&require_ct_delegate);
- EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_))
+ EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_, _, _))
.WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
CTRequirementLevel::NOT_REQUIRED));
- EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(kTestHostname))
+ EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(kTestHostname, _, _))
.WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
CTRequirementLevel::REQUIRED));
EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
@@ -649,10 +650,10 @@ TEST_F(ProofVerifierChromiumTest, CTIsRequiredHistogramNonCompliant) {
// Set up CT.
MockRequireCTDelegate require_ct_delegate;
transport_security_state_.SetRequireCTDelegate(&require_ct_delegate);
- EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_))
+ EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_, _, _))
.WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
CTRequirementLevel::NOT_REQUIRED));
- EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(kTestHostname))
+ EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(kTestHostname, _, _))
.WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
CTRequirementLevel::REQUIRED));
EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
@@ -696,10 +697,10 @@ TEST_F(ProofVerifierChromiumTest, CTIsRequiredHistogramCompliant) {
// Set up CT.
MockRequireCTDelegate require_ct_delegate;
transport_security_state_.SetRequireCTDelegate(&require_ct_delegate);
- EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_))
+ EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_, _, _))
.WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
CTRequirementLevel::NOT_REQUIRED));
- EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(kTestHostname))
+ EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(kTestHostname, _, _))
.WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
CTRequirementLevel::REQUIRED));
EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
@@ -805,10 +806,10 @@ TEST_F(ProofVerifierChromiumTest, PKPAndCTBothTested) {
// Set up CT.
MockRequireCTDelegate require_ct_delegate;
transport_security_state_.SetRequireCTDelegate(&require_ct_delegate);
- EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_))
+ EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_, _, _))
.WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
CTRequirementLevel::NOT_REQUIRED));
- EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(kTestHostname))
+ EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(kTestHostname, _, _))
.WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
CTRequirementLevel::REQUIRED));
EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
@@ -917,7 +918,7 @@ TEST_F(ProofVerifierChromiumTest, CTRequirementsFlagNotMet) {
// Set up CT.
MockRequireCTDelegate require_ct_delegate;
transport_security_state_.SetRequireCTDelegate(&require_ct_delegate);
- EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_))
+ EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_, _, _))
.WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
CTRequirementLevel::REQUIRED));
EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
@@ -959,7 +960,7 @@ TEST_F(ProofVerifierChromiumTest, CTRequirementsFlagMet) {
// Set up CT.
MockRequireCTDelegate require_ct_delegate;
transport_security_state_.SetRequireCTDelegate(&require_ct_delegate);
- EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_))
+ EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_, _, _))
.WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate::
CTRequirementLevel::REQUIRED));
EXPECT_CALL(ct_policy_enforcer_, CheckCompliance(_, _, _))
diff --git a/chromium/net/quic/chromium/quic_chromium_client_session.cc b/chromium/net/quic/chromium/quic_chromium_client_session.cc
index d366ad8a759..fcbaa1349a8 100644
--- a/chromium/net/quic/chromium/quic_chromium_client_session.cc
+++ b/chromium/net/quic/chromium/quic_chromium_client_session.cc
@@ -76,6 +76,12 @@ const int kDefaultRTTMilliSecs = 300;
// The maximum size of uncompressed QUIC headers that will be allowed.
const size_t kMaxUncompressedHeaderSize = 256 * 1024;
+// The maximum time allowed to have no retransmittable packets on the wire
+// (after sending the first retransmittable packet) if
+// |migrate_session_early_v2_| is true. PING frames will be sent as needed to
+// enforce this.
+const size_t kDefaultRetransmittableOnWireTimeoutMillisecs = 100;
+
// Histograms for tracking down the crashes from http://crbug.com/354669
// Note: these values must be kept in sync with the corresponding values in:
// tools/metrics/histograms/histograms.xml
@@ -130,26 +136,6 @@ std::unique_ptr<base::Value> NetLogQuicConnectionMigrationSuccessCallback(
return std::move(dict);
}
-void HistogramAndLogMigrationFailure(const NetLogWithSource& net_log,
- enum QuicConnectionMigrationStatus status,
- QuicConnectionId connection_id,
- std::string reason) {
- UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.ConnectionMigration", status,
- MIGRATION_STATUS_MAX);
- net_log.AddEvent(NetLogEventType::QUIC_CONNECTION_MIGRATION_FAILURE,
- base::Bind(&NetLogQuicConnectionMigrationFailureCallback,
- connection_id, reason));
-}
-
-void HistogramAndLogMigrationSuccess(const NetLogWithSource& net_log,
- QuicConnectionId connection_id) {
- UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.ConnectionMigration",
- MIGRATION_STATUS_SUCCESS, MIGRATION_STATUS_MAX);
- net_log.AddEvent(
- NetLogEventType::QUIC_CONNECTION_MIGRATION_SUCCESS,
- base::Bind(&NetLogQuicConnectionMigrationSuccessCallback, connection_id));
-}
-
// Histogram for recording the different reasons that a QUIC session is unable
// to complete the handshake.
enum HandshakeFailureReason {
@@ -180,6 +166,29 @@ void RecordHandshakeState(HandshakeState state) {
NUM_HANDSHAKE_STATES);
}
+std::string ConnectionMigrationCauseToString(ConnectionMigrationCause cause) {
+ switch (cause) {
+ case UNKNOWN:
+ return "Unknown";
+ case ON_NETWORK_CONNECTED:
+ return "OnNetworkConnected";
+ case ON_NETWORK_DISCONNECTED:
+ return "OnNetworkDisconnected";
+ case ON_WRITE_ERROR:
+ return "OnWriteError";
+ case ON_NETWORK_MADE_DEFAULT:
+ return "OnNetworkMadeDefault";
+ case ON_MIGRATE_BACK_TO_DEFAULT_NETWORK:
+ return "OnMigrateBackToDefaultNetwork";
+ case ON_PATH_DEGRADING:
+ return "OnPathDegrading";
+ default:
+ QUIC_NOTREACHED();
+ break;
+ }
+ return "InvalidCause";
+}
+
std::unique_ptr<base::Value> NetLogQuicClientSessionCallback(
const QuicServerId* server_id,
int cert_verify_flags,
@@ -207,6 +216,19 @@ std::unique_ptr<base::Value> NetLogQuicPushPromiseReceivedCallback(
return std::move(dict);
}
+// TODO(fayang): Remove this when necessary data is collected.
+void LogProbeResultToHistogram(ConnectionMigrationCause cause, bool success) {
+ UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ConnectionMigrationProbeSuccess",
+ success);
+ const std::string histogram_name =
+ "Net.QuicSession.ConnectionMigrationProbeSuccess." +
+ ConnectionMigrationCauseToString(cause);
+ STATIC_HISTOGRAM_POINTER_GROUP(
+ histogram_name, cause, MIGRATION_CAUSE_MAX, AddBoolean(success),
+ base::BooleanHistogram::FactoryGet(
+ histogram_name, base::HistogramBase::kUmaTargetedHistogramFlag));
+}
+
class HpackEncoderDebugVisitor : public QuicHpackDebugVisitor {
void OnUseEntry(QuicTime::Delta elapsed) override {
UMA_HISTOGRAM_TIMES(
@@ -721,6 +743,7 @@ QuicChromiumClientSession::QuicChromiumClientSession(
bytes_pushed_and_unclaimed_count_(0),
probing_manager_(this, task_runner_),
retry_migrate_back_count_(0),
+ current_connection_migration_cause_(UNKNOWN),
migration_pending_(false),
headers_include_h2_stream_dependency_(
headers_include_h2_stream_dependency &&
@@ -751,6 +774,11 @@ QuicChromiumClientSession::QuicChromiumClientSession(
}
connect_timing_.dns_start = dns_resolution_start_time;
connect_timing_.dns_end = dns_resolution_end_time;
+ if (migrate_session_early_v2_) {
+ connection->set_retransmittable_on_wire_timeout(
+ QuicTime::Delta::FromMilliseconds(
+ kDefaultRetransmittableOnWireTimeoutMillisecs));
+ }
}
QuicChromiumClientSession::~QuicChromiumClientSession() {
@@ -780,7 +808,7 @@ QuicChromiumClientSession::~QuicChromiumClientSession() {
if (connection()->connected()) {
// Ensure that the connection is closed by the time the session is
// destroyed.
- RecordInternalErrorLocation(QUIC_CHROMIUM_CLIENT_SESSION);
+ RecordInternalErrorLocation(QUIC_CHROMIUM_CLIENT_SESSION_DESTRUCTOR);
connection()->CloseConnection(QUIC_INTERNAL_ERROR, "session torn down",
ConnectionCloseBehavior::SILENT_CLOSE);
}
@@ -900,11 +928,12 @@ void QuicChromiumClientSession::OnHeadersHeadOfLineBlocking(
base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()));
}
-void QuicChromiumClientSession::UnregisterStreamPriority(QuicStreamId id) {
- if (headers_include_h2_stream_dependency_) {
+void QuicChromiumClientSession::UnregisterStreamPriority(QuicStreamId id,
+ bool is_static) {
+ if (headers_include_h2_stream_dependency_ && !is_static) {
priority_dependency_state_.OnStreamDestruction(id);
}
- QuicSpdySession::UnregisterStreamPriority(id);
+ QuicSpdySession::UnregisterStreamPriority(id, is_static);
}
void QuicChromiumClientSession::UpdateStreamPriority(
@@ -1563,7 +1592,7 @@ void QuicChromiumClientSession::OnConnectionClosed(
void QuicChromiumClientSession::OnSuccessfulVersionNegotiation(
const ParsedQuicVersion& version) {
- logger_->OnSuccessfulVersionNegotiation(version.transport_version);
+ logger_->OnSuccessfulVersionNegotiation(version);
QuicSpdySession::OnSuccessfulVersionNegotiation(version);
}
@@ -1619,6 +1648,8 @@ void QuicChromiumClientSession::MigrateSessionOnWriteError(int error_code) {
if (!migration_pending_)
return;
+ current_connection_migration_cause_ = ON_WRITE_ERROR;
+
MigrationResult result = MigrationResult::FAILURE;
if (stream_factory_ != nullptr) {
const NetLogWithSource migration_net_log = NetLogWithSource::Make(
@@ -1672,11 +1703,7 @@ void QuicChromiumClientSession::WriteToNewSocket() {
// Unblock the connection before sending a PING packet, since it
// may have been blocked before the migration started.
connection()->OnCanWrite();
- if (use_control_frame_manager()) {
- SendPing();
- } else {
- connection()->SendPing();
- }
+ SendPing();
return;
}
@@ -1700,9 +1727,8 @@ void QuicChromiumClientSession::OnMigrationTimeout(size_t num_sockets) {
// If number of sockets has changed, this migration task is stale.
if (num_sockets != sockets_.size())
return;
- UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.ConnectionMigration",
- MIGRATION_STATUS_NO_ALTERNATE_NETWORK,
- MIGRATION_STATUS_MAX);
+
+ LogConnectionMigrationResultToHistogram(MIGRATION_STATUS_TIMEOUT);
CloseSessionOnError(ERR_NETWORK_CHANGED,
QUIC_CONNECTION_MIGRATION_NO_NEW_NETWORK);
}
@@ -1721,6 +1747,8 @@ void QuicChromiumClientSession::OnProbeNetworkSucceeded(
NetLogEventType::QUIC_CONNECTION_CONNECTIVITY_PROBING_SUCCEEDED,
NetLog::Int64Callback("network", network));
+ LogProbeResultToHistogram(current_connection_migration_cause_, true);
+
// Set |this| to listen on socket write events on the packet writer
// that was used for probing.
writer->set_delegate(this);
@@ -1745,6 +1773,7 @@ void QuicChromiumClientSession::OnProbeNetworkSucceeded(
<< "successful probing network: " << network << ".";
current_migrations_to_non_default_network_on_path_degrading_++;
if (!migrate_back_to_default_timer_.IsRunning()) {
+ current_connection_migration_cause_ = ON_MIGRATE_BACK_TO_DEFAULT_NETWORK;
// Session gets off the |default_network|, stay on |network| for now but
// try to migrate back to default network after 1 second.
StartMigrateBackToDefaultNetworkTimer(
@@ -1758,6 +1787,8 @@ void QuicChromiumClientSession::OnProbeNetworkFailed(
net_log_.AddEvent(
NetLogEventType::QUIC_CONNECTION_CONNECTIVITY_PROBING_FAILED,
NetLog::Int64Callback("network", network));
+
+ LogProbeResultToHistogram(current_connection_migration_cause_, false);
// Probing failure for default network can be ignored.
DVLOG(1) << "Connectivity probing failed on NetworkHandle " << network;
DVLOG_IF(1, network == default_network_ &&
@@ -1782,6 +1813,7 @@ void QuicChromiumClientSession::OnNetworkConnected(
if (!migration_pending_)
return;
+ current_connection_migration_cause_ = ON_NETWORK_CONNECTED;
// |migration_pending_| is true, there was no working network previously.
// |network| is now the only possible candidate, migrate immediately.
if (migrate_session_on_network_change_v2_) {
@@ -1806,6 +1838,7 @@ void QuicChromiumClientSession::OnNetworkDisconnected(
if (!migrate_session_on_network_change_)
return;
+ current_connection_migration_cause_ = ON_NETWORK_DISCONNECTED;
MaybeMigrateOrCloseSession(
alternate_network, /*close_if_cannot_migrate*/ true, migration_net_log);
}
@@ -1829,6 +1862,7 @@ void QuicChromiumClientSession::OnNetworkDisconnectedV2(
return;
}
+ current_connection_migration_cause_ = ON_NETWORK_DISCONNECTED;
// Attempt to find alternative network.
NetworkChangeNotifier::NetworkHandle new_network =
stream_factory_->FindAlternateNetwork(disconnected_network);
@@ -1837,6 +1871,7 @@ void QuicChromiumClientSession::OnNetworkDisconnectedV2(
OnNoNewNetwork();
return;
}
+
// Current network is being disconnected, migrate immediately to the
// alternative network.
MigrateImmediately(new_network);
@@ -1855,6 +1890,7 @@ void QuicChromiumClientSession::OnNetworkMadeDefault(
DCHECK_NE(NetworkChangeNotifier::kInvalidNetworkHandle, new_network);
default_network_ = new_network;
+ current_connection_migration_cause_ = ON_NETWORK_MADE_DEFAULT;
if (!migrate_session_on_network_change_v2_) {
MaybeMigrateOrCloseSession(new_network, /*close_if_cannot_migrate*/ false,
@@ -1943,6 +1979,7 @@ void QuicChromiumClientSession::OnPathDegrading() {
NetworkChangeNotifier::NetworkHandle alternate_network =
stream_factory_->FindAlternateNetwork(
GetDefaultSocket()->GetBoundNetwork());
+ current_connection_migration_cause_ = ON_PATH_DEGRADING;
if (alternate_network != NetworkChangeNotifier::kInvalidNetworkHandle) {
if (GetDefaultSocket()->GetBoundNetwork() == default_network_ &&
current_migrations_to_non_default_network_on_path_degrading_ >=
@@ -1970,8 +2007,8 @@ void QuicChromiumClientSession::OnPathDegrading() {
migration_net_log);
} else {
HistogramAndLogMigrationFailure(
- migration_net_log, MIGRATION_STATUS_NOT_ENABLED, connection_id(),
- "Migration on path degrading not enabled");
+ migration_net_log, MIGRATION_STATUS_PATH_DEGRADING_NOT_ENABLED,
+ connection_id(), "Migration on path degrading not enabled");
}
migration_net_log.EndEvent(
NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED);
@@ -2027,6 +2064,10 @@ void QuicChromiumClientSession::StartReading() {
void QuicChromiumClientSession::CloseSessionOnError(int net_error,
QuicErrorCode quic_error) {
base::UmaHistogramSparse("Net.QuicSession.CloseSessionOnError", -net_error);
+ if (quic_error == QUIC_INTERNAL_ERROR) {
+ RecordInternalErrorLocation(
+ QUIC_CHROMIUM_CLIENT_SESSION_CLOSE_SESSION_ON_ERROR);
+ }
if (!callback_.is_null()) {
base::ResetAndReturn(&callback_).Run(net_error);
@@ -2189,6 +2230,9 @@ ProbingResult QuicChromiumClientSession::StartProbeNetwork(
void QuicChromiumClientSession::StartMigrateBackToDefaultNetworkTimer(
base::TimeDelta delay) {
+ if (current_connection_migration_cause_ != ON_NETWORK_MADE_DEFAULT)
+ current_connection_migration_cause_ = ON_MIGRATE_BACK_TO_DEFAULT_NETWORK;
+
CancelMigrateBackToDefaultNetworkTimer();
// Post a task to try migrate back to default network after |delay|.
migrate_back_to_default_timer_.Start(
@@ -2360,6 +2404,40 @@ void QuicChromiumClientSession::LogMetricsOnNetworkMadeDefault() {
}
}
+void QuicChromiumClientSession::LogConnectionMigrationResultToHistogram(
+ QuicConnectionMigrationStatus status) {
+ UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.ConnectionMigration", status,
+ MIGRATION_STATUS_MAX);
+
+ // Log the connection migraiton result to different histograms based on the
+ // cause of the connection migration.
+ std::string histogram_name =
+ "Net.QuicSession.ConnectionMigration." +
+ ConnectionMigrationCauseToString(current_connection_migration_cause_);
+ base::UmaHistogramEnumeration(histogram_name, status, MIGRATION_STATUS_MAX);
+ current_connection_migration_cause_ = UNKNOWN;
+}
+
+void QuicChromiumClientSession::HistogramAndLogMigrationFailure(
+ const NetLogWithSource& net_log,
+ QuicConnectionMigrationStatus status,
+ QuicConnectionId connection_id,
+ const std::string& reason) {
+ LogConnectionMigrationResultToHistogram(status);
+ net_log.AddEvent(NetLogEventType::QUIC_CONNECTION_MIGRATION_FAILURE,
+ base::Bind(&NetLogQuicConnectionMigrationFailureCallback,
+ connection_id, reason));
+}
+
+void QuicChromiumClientSession::HistogramAndLogMigrationSuccess(
+ const NetLogWithSource& net_log,
+ QuicConnectionId connection_id) {
+ LogConnectionMigrationResultToHistogram(MIGRATION_STATUS_SUCCESS);
+ net_log.AddEvent(
+ NetLogEventType::QUIC_CONNECTION_MIGRATION_SUCCESS,
+ base::Bind(&NetLogQuicConnectionMigrationSuccessCallback, connection_id));
+}
+
std::unique_ptr<base::Value> QuicChromiumClientSession::GetInfoAsValue(
const std::set<HostPortPair>& aliases) {
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
@@ -2403,13 +2481,31 @@ void QuicChromiumClientSession::OnReadError(
int result,
const DatagramClientSocket* socket) {
DCHECK(socket != nullptr);
+ base::UmaHistogramSparse("Net.QuicSession.ReadError.AnyNetwork", -result);
if (socket != GetDefaultSocket()) {
- // Ignore read errors from old sockets that are no longer active.
+ base::UmaHistogramSparse("Net.QuicSession.ReadError.OtherNetworks",
+ -result);
+ // Ignore read errors from sockets that are not affecting the current
+ // network, i.e., sockets that are no longer active and probing socket.
// TODO(jri): Maybe clean up old sockets on error.
return;
}
+
+ base::UmaHistogramSparse("Net.QuicSession.ReadError.CurrentNetwork", -result);
+ if (IsCryptoHandshakeConfirmed()) {
+ base::UmaHistogramSparse(
+ "Net.QuicSession.ReadError.CurrentNetwork.HandshakeConfirmed", -result);
+ }
+
+ if (migration_pending_) {
+ // Ignore read errors during pending migration. Connection will be closed if
+ // pending migration failed or timed out.
+ base::UmaHistogramSparse("Net.QuicSession.ReadError.PendingMigration",
+ -result);
+ return;
+ }
+
DVLOG(1) << "Closing session on read error: " << result;
- base::UmaHistogramSparse("Net.QuicSession.ReadError", -result);
connection()->CloseConnection(QUIC_PACKET_READ_ERROR, ErrorToString(result),
ConnectionCloseBehavior::SILENT_CLOSE);
}
@@ -2666,7 +2762,7 @@ bool QuicChromiumClientSession::HandlePromised(QuicStreamId id,
// push promise headers are received, send a PRIORITY frame for the
// promised stream ID. Send |kDefaultPriority| since that will be the
// initial SpdyPriority of the push promise stream when created.
- const SpdyPriority priority = kDefaultPriority;
+ const SpdyPriority priority = QuicStream::kDefaultPriority;
SpdyStreamId parent_stream_id = 0;
int weight = 0;
bool exclusive = false;
diff --git a/chromium/net/quic/chromium/quic_chromium_client_session.h b/chromium/net/quic/chromium/quic_chromium_client_session.h
index 21b4cb4bfc0..68ef0c92f0e 100644
--- a/chromium/net/quic/chromium/quic_chromium_client_session.h
+++ b/chromium/net/quic/chromium/quic_chromium_client_session.h
@@ -81,6 +81,35 @@ enum class ConnectionMigrationMode {
FULL_MIGRATION_V2
};
+// Cause of connection migration.
+enum ConnectionMigrationCause {
+ UNKNOWN,
+ ON_NETWORK_CONNECTED, // No probing.
+ ON_NETWORK_DISCONNECTED, // No probing.
+ ON_WRITE_ERROR, // No probing.
+ ON_NETWORK_MADE_DEFAULT, // With probing.
+ ON_MIGRATE_BACK_TO_DEFAULT_NETWORK, // With probing.
+ ON_PATH_DEGRADING, // With probing.
+ MIGRATION_CAUSE_MAX
+};
+
+// Result of connection migration.
+enum QuicConnectionMigrationStatus {
+ MIGRATION_STATUS_NO_MIGRATABLE_STREAMS,
+ MIGRATION_STATUS_ALREADY_MIGRATED,
+ MIGRATION_STATUS_INTERNAL_ERROR,
+ MIGRATION_STATUS_TOO_MANY_CHANGES,
+ MIGRATION_STATUS_SUCCESS,
+ MIGRATION_STATUS_NON_MIGRATABLE_STREAM,
+ MIGRATION_STATUS_NOT_ENABLED,
+ MIGRATION_STATUS_NO_ALTERNATE_NETWORK,
+ MIGRATION_STATUS_ON_PATH_DEGRADING_DISABLED,
+ MIGRATION_STATUS_DISABLED_BY_CONFIG,
+ MIGRATION_STATUS_PATH_DEGRADING_NOT_ENABLED,
+ MIGRATION_STATUS_TIMEOUT,
+ MIGRATION_STATUS_MAX
+};
+
// Result of a connectivity probing attempt.
enum class ProbingResult {
PENDING, // Probing started, pending result.
@@ -426,7 +455,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
QuicReferenceCountedPointer<QuicAckListenerInterface>
ack_listener) override;
void OnHeadersHeadOfLineBlocking(QuicTime::Delta delta) override;
- void UnregisterStreamPriority(QuicStreamId id) override;
+ void UnregisterStreamPriority(QuicStreamId id, bool is_static) override;
void UpdateStreamPriority(QuicStreamId id,
SpdyPriority new_priority) override;
@@ -687,6 +716,14 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
const NetLogWithSource& migration_net_log);
void LogMetricsOnNetworkDisconnected();
void LogMetricsOnNetworkMadeDefault();
+ void LogConnectionMigrationResultToHistogram(
+ QuicConnectionMigrationStatus status);
+ void HistogramAndLogMigrationFailure(const NetLogWithSource& net_log,
+ QuicConnectionMigrationStatus status,
+ QuicConnectionId connection_id,
+ const std::string& reason);
+ void HistogramAndLogMigrationSuccess(const NetLogWithSource& net_log,
+ QuicConnectionId connection_id);
// Notifies the factory that this session is going away and no more streams
// should be created from it. This needs to be called before closing any
@@ -763,6 +800,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
QuicConnectivityProbingManager probing_manager_;
int retry_migrate_back_count_;
base::OneShotTimer migrate_back_to_default_timer_;
+ ConnectionMigrationCause current_connection_migration_cause_;
// TODO(jri): Replace use of migration_pending_ sockets_.size().
// When a task is posted for MigrateSessionOnError, pass in
// sockets_.size(). Then in MigrateSessionOnError, check to see if
diff --git a/chromium/net/quic/chromium/quic_chromium_client_session_test.cc b/chromium/net/quic/chromium/quic_chromium_client_session_test.cc
index 88e20fb455a..36509ccb712 100644
--- a/chromium/net/quic/chromium/quic_chromium_client_session_test.cc
+++ b/chromium/net/quic/chromium/quic_chromium_client_session_test.cc
@@ -7,7 +7,6 @@
#include "base/base64.h"
#include "base/files/file_path.h"
#include "base/memory/ptr_util.h"
-#include "base/rand_util.h"
#include "base/run_loop.h"
#include "base/test/histogram_tester.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -36,14 +35,16 @@
#include "net/quic/core/quic_packet_writer.h"
#include "net/quic/core/tls_client_handshaker.h"
#include "net/quic/platform/api/quic_flags.h"
-#include "net/quic/platform/impl/quic_test_impl.h"
+#include "net/quic/platform/api/quic_test.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_client_promised_info_peer.h"
+#include "net/quic/test_tools/quic_connection_peer.h"
#include "net/quic/test_tools/quic_stream_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/quic/test_tools/simple_quic_framer.h"
#include "net/socket/datagram_client_socket.h"
#include "net/socket/socket_test_util.h"
+#include "net/spdy/chromium/spdy_test_util_common.h"
#include "net/spdy/core/spdy_test_utils.h"
#include "net/test/cert_test_util.h"
#include "net/test/gtest_util.h"
@@ -111,7 +112,8 @@ class QuicChromiumClientSessionTest
&clock_,
kServerHostname,
Perspective::IS_SERVER,
- false) {
+ false),
+ migrate_session_early_v2_(false) {
// Advance the time, because timers do not like uninitialized times.
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
}
@@ -129,7 +131,6 @@ class QuicChromiumClientSessionTest
socket_factory_.AddSocketDataProvider(socket_data_.get());
std::unique_ptr<DatagramClientSocket> socket =
socket_factory_.CreateDatagramClientSocket(DatagramSocket::DEFAULT_BIND,
- base::Bind(&base::RandInt),
&net_log_, NetLogSource());
socket->Connect(kIpEndPoint);
QuicChromiumPacketWriter* writer = new net::QuicChromiumPacketWriter(
@@ -144,10 +145,9 @@ class QuicChromiumClientSessionTest
/*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_,
&transport_security_state_,
base::WrapUnique(static_cast<QuicServerInfo*>(nullptr)), session_key_,
- /*require_confirmation=*/false, /*migrate_session_early*/ false,
- /*migrate_session_on_network_change*/ false,
- /*migrate_session_early_v2*/ false,
- /*migrate_session_on_network_change_v2*/ false,
+ /*require_confirmation=*/false, /*migrate_session_early=*/false,
+ /*migrate_session_on_network_change=*/false, migrate_session_early_v2_,
+ /*migrate_session_on_network_change_v2=*/false,
base::TimeDelta::FromSeconds(kMaxTimeOnNonDefaultNetworkSecs),
kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
kQuicYieldAfterPacketsRead,
@@ -219,6 +219,7 @@ class QuicChromiumClientSessionTest
QuicTestPacketMaker client_maker_;
QuicTestPacketMaker server_maker_;
ProofVerifyDetailsChromium verify_details_;
+ bool migrate_session_early_v2_;
};
INSTANTIATE_TEST_CASE_P(
@@ -1236,15 +1237,9 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocket) {
char data[] = "ABCD";
std::unique_ptr<QuicEncryptedPacket> client_ping;
std::unique_ptr<QuicEncryptedPacket> ack_and_data_out;
- if (session_->use_control_frame_manager()) {
client_ping = client_maker_.MakeAckAndPingPacket(2, false, 1, 1, 1);
ack_and_data_out = client_maker_.MakeDataPacket(3, 5, false, false, 0,
QuicStringPiece(data));
- } else {
- client_ping = client_maker_.MakePingPacket(2, /*include_version=*/false);
- ack_and_data_out = client_maker_.MakeAckAndDataPacket(
- 3, false, 5, 1, 1, 1, false, 0, QuicStringPiece(data));
- }
std::unique_ptr<QuicEncryptedPacket> server_ping(
server_maker_.MakePingPacket(1, /*include_version=*/false));
MockRead reads[] = {
@@ -1260,7 +1255,6 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocket) {
// Create connected socket.
std::unique_ptr<DatagramClientSocket> new_socket =
socket_factory_.CreateDatagramClientSocket(DatagramSocket::DEFAULT_BIND,
- base::Bind(&base::RandInt),
&net_log_, NetLogSource());
EXPECT_THAT(new_socket->Connect(kIpEndPoint), IsOk());
@@ -1319,7 +1313,6 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocketMaxReaders) {
// Create connected socket.
std::unique_ptr<DatagramClientSocket> new_socket =
socket_factory_.CreateDatagramClientSocket(DatagramSocket::DEFAULT_BIND,
- base::Bind(&base::RandInt),
&net_log_, NetLogSource());
EXPECT_THAT(new_socket->Connect(kIpEndPoint), IsOk());
@@ -1355,11 +1348,7 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocketReadError) {
std::unique_ptr<QuicEncryptedPacket> settings_packet(
client_maker_.MakeInitialSettingsPacket(1, nullptr));
std::unique_ptr<QuicEncryptedPacket> client_ping;
- if (FLAGS_quic_reloadable_flag_quic_use_control_frame_manager) {
client_ping = client_maker_.MakeAckAndPingPacket(2, false, 1, 1, 1);
- } else {
- client_ping = client_maker_.MakePingPacket(2, /*include_version=*/false);
- }
std::unique_ptr<QuicEncryptedPacket> server_ping(
server_maker_.MakePingPacket(1, /*include_version=*/false));
MockWrite old_writes[] = {
@@ -1386,7 +1375,6 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocketReadError) {
// Create connected socket.
std::unique_ptr<DatagramClientSocket> new_socket =
socket_factory_.CreateDatagramClientSocket(DatagramSocket::DEFAULT_BIND,
- base::Bind(&base::RandInt),
&net_log_, NetLogSource());
EXPECT_THAT(new_socket->Connect(kIpEndPoint), IsOk());
@@ -1425,6 +1413,53 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocketReadError) {
EXPECT_TRUE(new_socket_data.AllWriteDataConsumed());
}
+TEST_P(QuicChromiumClientSessionTest, RetransmittableOnWireTimeout) {
+ migrate_session_early_v2_ = true;
+
+ MockQuicData quic_data;
+ quic_data.AddWrite(client_maker_.MakeInitialSettingsPacket(1, nullptr));
+ quic_data.AddWrite(client_maker_.MakePingPacket(2, true));
+ quic_data.AddRead(server_maker_.MakeAckPacket(1, 2, 1, 1, false));
+
+ quic_data.AddWrite(client_maker_.MakePingPacket(3, false));
+ quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+ quic_data.AddRead(ASYNC, OK); // EOF
+ quic_data.AddSocketDataToFactory(&socket_factory_);
+
+ Initialize();
+ CompleteCryptoHandshake();
+
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100),
+ session_->connection()->retransmittable_on_wire_timeout());
+
+ // Open a stream since the connection only sends PINGs to keep a
+ // retransmittable packet on the wire if there's an open stream.
+ EXPECT_TRUE(QuicChromiumClientSessionPeer::CreateOutgoingDynamicStream(
+ session_.get()));
+
+ QuicAlarm* alarm =
+ QuicConnectionPeer::GetRetransmittableOnWireAlarm(session_->connection());
+ EXPECT_FALSE(alarm->IsSet());
+
+ // Send PING, which will be ACKed by the server. After the ACK, there will be
+ // no retransmittable packets on the wire, so the alarm should be set.
+ session_->SendPing();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(alarm->IsSet());
+ EXPECT_EQ(clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(100),
+ alarm->deadline());
+
+ // Advance clock and simulate the alarm firing. This should cause a PING to be
+ // sent.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
+ alarm_factory_.FireAlarm(alarm);
+ base::RunLoop().RunUntilIdle();
+
+ quic_data.Resume();
+ EXPECT_TRUE(quic_data.AllReadDataConsumed());
+ EXPECT_TRUE(quic_data.AllWriteDataConsumed());
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/chromium/quic_chromium_client_stream.cc b/chromium/net/quic/chromium/quic_chromium_client_stream.cc
index 4db1630d7dc..aa886ddd2e1 100644
--- a/chromium/net/quic/chromium/quic_chromium_client_stream.cc
+++ b/chromium/net/quic/chromium/quic_chromium_client_stream.cc
@@ -18,6 +18,7 @@
#include "net/quic/core/quic_spdy_session.h"
#include "net/quic/core/quic_write_blocked_list.h"
#include "net/quic/core/spdy_utils.h"
+#include "net/spdy/chromium/spdy_log_util.h"
namespace net {
namespace {
@@ -536,17 +537,11 @@ bool QuicChromiumClientStream::WritevStreamData(
// Must not be called when data is buffered.
DCHECK(!HasBufferedData());
// Writes the data, or buffers it.
- if (session_->can_use_slices()) {
- WriteMemSlices(QuicMemSliceSpan(QuicMemSliceSpanImpl(
- buffers.data(), lengths.data(), buffers.size())),
- fin);
- } else {
for (size_t i = 0; i < buffers.size(); ++i) {
bool is_fin = fin && (i == buffers.size() - 1);
QuicStringPiece string_data(buffers[i]->data(), lengths[i]);
WriteOrBufferData(string_data, is_fin, nullptr);
}
- }
return !HasBufferedData(); // Was all data written?
}
diff --git a/chromium/net/quic/chromium/quic_chromium_client_stream_test.cc b/chromium/net/quic/chromium/quic_chromium_client_stream_test.cc
index bd6ba937536..e37e55f6d8d 100644
--- a/chromium/net/quic/chromium/quic_chromium_client_stream_test.cc
+++ b/chromium/net/quic/chromium/quic_chromium_client_stream_test.cc
@@ -606,14 +606,9 @@ TEST_P(QuicChromiumClientStreamTest, WritevStreamData) {
new StringIOBuffer("Just a small payload"));
// All data written.
- if (session_.can_use_slices()) {
- EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
- .WillOnce(Return(QuicConsumedData(buf1->size() + buf2->size(), true)));
- } else {
EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
.WillOnce(Return(QuicConsumedData(buf1->size(), false)))
.WillOnce(Return(QuicConsumedData(buf2->size(), true)));
- }
TestCompletionCallback callback;
EXPECT_EQ(
OK, handle_->WritevStreamData({buf1, buf2}, {buf1->size(), buf2->size()},
@@ -626,16 +621,11 @@ TEST_P(QuicChromiumClientStreamTest, WritevStreamDataAsync) {
new StringIOBuffer("Just a small payload"));
// Only a part of the data is written.
- if (session_.can_use_slices()) {
- EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
- .WillOnce(Return(QuicConsumedData(buf1->size(), false)));
- } else {
EXPECT_CALL(session_, WritevData(stream_, stream_->id(), _, _, _))
// First piece of data is written.
.WillOnce(Return(QuicConsumedData(buf1->size(), false)))
// Second piece of data is queued.
.WillOnce(Return(QuicConsumedData(0, false)));
- }
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
handle_->WritevStreamData({buf1.get(), buf2.get()},
diff --git a/chromium/net/quic/chromium/quic_chromium_packet_writer.cc b/chromium/net/quic/chromium/quic_chromium_packet_writer.cc
index af3b7c0a20b..5786a7f0192 100644
--- a/chromium/net/quic/chromium/quic_chromium_packet_writer.cc
+++ b/chromium/net/quic/chromium/quic_chromium_packet_writer.cc
@@ -38,6 +38,32 @@ void RecordRetryCount(int count) {
count, kMaxRetries + 1);
}
+const net::NetworkTrafficAnnotationTag kTrafficAnnotation =
+ net::DefineNetworkTrafficAnnotation("quic_chromium_packet_writer", R"(
+ semantics {
+ sender: "QUIC Packet Writer"
+ description:
+ "A QUIC packet is written to the wire based on a request from "
+ "a QUIC stream."
+ trigger:
+ "A request from QUIC stream."
+ data: "Any data sent by the stream."
+ destination: OTHER
+ destination_other: "Any destination choosen by the stream."
+ }
+ policy {
+ cookies_allowed: NO
+ setting: "This feature cannot be disabled in settings."
+ policy_exception_justification:
+ "Essential for network access."
+ }
+ comments:
+ "All requests that are received by QUIC streams have network traffic "
+ "annotation, but the annotation is not passed to the writer function "
+ "due to technial overheads. Please see QuicChromiumClientSession and "
+ "QuicChromiumClientStream classes for references."
+ )");
+
} // namespace
QuicChromiumPacketWriter::ReusableIOBuffer::ReusableIOBuffer(size_t capacity)
@@ -108,34 +134,9 @@ WriteResult QuicChromiumPacketWriter::WritePacketToSocket(
WriteResult QuicChromiumPacketWriter::WritePacketToSocketImpl() {
base::TimeTicks now = base::TimeTicks::Now();
- net::NetworkTrafficAnnotationTag traffic_annotation =
- net::DefineNetworkTrafficAnnotation("quic_chromium_packet_writer", R"(
- semantics {
- sender: "QUIC Packet Writer"
- description:
- "A QUIC packet is written to the wire based on a request from "
- "a QUIC stream."
- trigger:
- "A request from QUIC stream."
- data: "Any data sent by the stream."
- destination: OTHER
- destination_other: "Any destination choosen by the stream."
- }
- policy {
- cookies_allowed: NO
- setting: "This feature cannot be disabled in settings."
- policy_exception_justification:
- "Essential for network access."
- }
- comments:
- "All requests that are received by QUIC streams have network traffic "
- "annotation, but the annotation is not passed to the writer function "
- "due to technial overheads. Please see QuicChromiumClientSession and "
- "QuicChromiumClientStream classes for references."
- )");
int rv = socket_->Write(packet_.get(), packet_->size(), write_callback_,
- traffic_annotation);
+ kTrafficAnnotation);
if (MaybeRetryAfterWriteError(rv))
return WriteResult(WRITE_STATUS_BLOCKED, ERR_IO_PENDING);
diff --git a/chromium/net/quic/chromium/quic_connection_logger.cc b/chromium/net/quic/chromium/quic_connection_logger.cc
index 048c4922a2e..d9e4ceefd38 100644
--- a/chromium/net/quic/chromium/quic_connection_logger.cc
+++ b/chromium/net/quic/chromium/quic_connection_logger.cc
@@ -711,10 +711,10 @@ void QuicConnectionLogger::OnConnectionClosed(QuicErrorCode error,
}
void QuicConnectionLogger::OnSuccessfulVersionNegotiation(
- const QuicTransportVersion& version) {
+ const ParsedQuicVersion& version) {
if (!net_log_is_capturing_)
return;
- string quic_version = QuicVersionToString(version);
+ string quic_version = QuicVersionToString(version.transport_version);
net_log_.AddEvent(NetLogEventType::QUIC_SESSION_VERSION_NEGOTIATED,
NetLog::StringCallback("version", &quic_version));
}
diff --git a/chromium/net/quic/chromium/quic_connection_logger.h b/chromium/net/quic/chromium/quic_connection_logger.h
index 07b6894e456..25638374c46 100644
--- a/chromium/net/quic/chromium/quic_connection_logger.h
+++ b/chromium/net/quic/chromium/quic_connection_logger.h
@@ -77,7 +77,7 @@ class NET_EXPORT_PRIVATE QuicConnectionLogger
const std::string& error_details,
ConnectionCloseSource source) override;
void OnSuccessfulVersionNegotiation(
- const QuicTransportVersion& version) override;
+ const ParsedQuicVersion& version) override;
void OnRttChanged(QuicTime::Delta rtt) const override;
void OnCryptoHandshakeMessageReceived(const CryptoHandshakeMessage& message);
diff --git a/chromium/net/quic/chromium/quic_connectivity_probing_manager_test.cc b/chromium/net/quic/chromium/quic_connectivity_probing_manager_test.cc
index 7b7b0c5c5cc..6d77dead83a 100644
--- a/chromium/net/quic/chromium/quic_connectivity_probing_manager_test.cc
+++ b/chromium/net/quic/chromium/quic_connectivity_probing_manager_test.cc
@@ -4,7 +4,6 @@
#include "net/quic/chromium/quic_connectivity_probing_manager.h"
-#include "base/rand_util.h"
#include "base/test/test_mock_time_task_runner.h"
#include "net/log/test_net_log.h"
#include "net/quic/test_tools/mock_clock.h"
@@ -84,8 +83,7 @@ class QuicConnectivityProbingManagerTest : public ::testing::Test {
socket_factory_.AddSocketDataProvider(socket_data_.get());
// Create a connected socket for probing.
socket_ = socket_factory_.CreateDatagramClientSocket(
- DatagramSocket::DEFAULT_BIND, base::Bind(&base::RandInt), &net_log_,
- NetLogSource());
+ DatagramSocket::DEFAULT_BIND, &net_log_, NetLogSource());
EXPECT_THAT(socket_->Connect(kIpEndPoint), IsOk());
IPEndPoint self_address;
socket_->GetLocalAddress(&self_address);
diff --git a/chromium/net/quic/chromium/quic_end_to_end_unittest.cc b/chromium/net/quic/chromium/quic_end_to_end_unittest.cc
index ae892bec698..ce0b3fbe1ee 100644
--- a/chromium/net/quic/chromium/quic_end_to_end_unittest.cc
+++ b/chromium/net/quic/chromium/quic_end_to_end_unittest.cc
@@ -28,7 +28,7 @@
#include "net/http/http_transaction_test_util.h"
#include "net/http/transport_security_state.h"
#include "net/log/net_log_with_source.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
#include "net/quic/platform/api/quic_string_piece.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
diff --git a/chromium/net/quic/chromium/quic_http_stream.cc b/chromium/net/quic/chromium/quic_http_stream.cc
index bd1f159af5b..307604da0e5 100644
--- a/chromium/net/quic/chromium/quic_http_stream.cc
+++ b/chromium/net/quic/chromium/quic_http_stream.cc
@@ -15,6 +15,7 @@
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
+#include "net/log/net_log.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_source.h"
#include "net/quic/chromium/quic_http_utils.h"
@@ -467,6 +468,9 @@ void QuicHttpStream::DoCallback(int rv) {
int QuicHttpStream::DoLoop(int rv) {
CHECK(!in_loop_);
base::AutoReset<bool> auto_reset_in_loop(&in_loop_, true);
+ std::unique_ptr<QuicConnection::ScopedPacketFlusher> packet_flusher =
+ quic_session()->CreatePacketBundler(
+ QuicConnection::AckBundling::SEND_ACK_IF_QUEUED);
do {
State state = next_state_;
next_state_ = STATE_NONE;
diff --git a/chromium/net/quic/chromium/quic_http_stream_test.cc b/chromium/net/quic/chromium/quic_http_stream_test.cc
index b0b026be692..4d68b369db3 100644
--- a/chromium/net/quic/chromium/quic_http_stream_test.cc
+++ b/chromium/net/quic/chromium/quic_http_stream_test.cc
@@ -34,6 +34,7 @@
#include "net/quic/chromium/quic_chromium_packet_writer.h"
#include "net/quic/chromium/quic_http_utils.h"
#include "net/quic/chromium/quic_server_info.h"
+#include "net/quic/chromium/quic_stream_factory.h"
#include "net/quic/chromium/quic_test_packet_maker.h"
#include "net/quic/chromium/test_task_runner.h"
#include "net/quic/core/congestion_control/send_algorithm_interface.h"
@@ -420,6 +421,45 @@ class QuicHttpStreamTest
spdy_headers_frame_length, offset);
}
+ std::unique_ptr<QuicReceivedPacket>
+ ConstructRequestHeadersAndDataFramesPacket(
+ QuicPacketNumber packet_number,
+ QuicStreamId stream_id,
+ bool should_include_version,
+ bool fin,
+ RequestPriority request_priority,
+ QuicStreamId parent_stream_id,
+ QuicStreamOffset* offset,
+ size_t* spdy_headers_frame_length,
+ const std::vector<std::string>& data_writes) {
+ SpdyPriority priority =
+ ConvertRequestPriorityToQuicPriority(request_priority);
+ return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
+ packet_number, stream_id, should_include_version, fin, priority,
+ std::move(request_headers_), parent_stream_id, offset,
+ spdy_headers_frame_length, data_writes);
+ }
+
+ std::unique_ptr<QuicReceivedPacket> ConstructRequestAndRstPacket(
+ QuicPacketNumber packet_number,
+ QuicStreamId stream_id,
+ bool should_include_version,
+ bool fin,
+ RequestPriority request_priority,
+ QuicStreamId parent_stream_id,
+ size_t* spdy_headers_frame_length,
+ QuicStreamOffset* header_stream_offset,
+ QuicRstStreamErrorCode error_code,
+ size_t bytes_written) {
+ SpdyPriority priority =
+ ConvertRequestPriorityToQuicPriority(request_priority);
+ return client_maker_.MakeRequestHeadersAndRstPacket(
+ packet_number, stream_id, should_include_version, fin, priority,
+ std::move(request_headers_), parent_stream_id,
+ spdy_headers_frame_length, header_stream_offset, error_code,
+ bytes_written);
+ }
+
std::unique_ptr<QuicReceivedPacket> ConstructRequestHeadersPacket(
QuicPacketNumber packet_number,
bool fin,
@@ -1141,12 +1181,13 @@ TEST_P(QuicHttpStreamTest, SendPostRequest) {
size_t spdy_request_headers_frame_length;
QuicStreamOffset header_stream_offset = 0;
AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
- AddWrite(InnerConstructRequestHeadersPacket(
- 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
- DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
- &header_stream_offset));
- AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, 0, kUploadData));
- AddWrite(ConstructClientAckPacket(4, 3, 1, 1));
+
+ AddWrite(ConstructRequestHeadersAndDataFramesPacket(
+ 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
+ DEFAULT_PRIORITY, 0, &header_stream_offset,
+ &spdy_request_headers_frame_length, {kUploadData}));
+
+ AddWrite(ConstructClientAckPacket(3, 3, 1, 1));
Initialize();
@@ -1212,12 +1253,11 @@ TEST_P(QuicHttpStreamTest, SendPostRequestAndReceiveSoloFin) {
size_t spdy_request_headers_frame_length;
QuicStreamOffset header_stream_offset = 0;
AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
- AddWrite(InnerConstructRequestHeadersPacket(
- 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
- DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
- &header_stream_offset));
- AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, 0, kUploadData));
- AddWrite(ConstructClientAckPacket(4, 3, 1, 1));
+ AddWrite(ConstructRequestHeadersAndDataFramesPacket(
+ 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, kFin,
+ DEFAULT_PRIORITY, 0, &header_stream_offset,
+ &spdy_request_headers_frame_length, {kUploadData}));
+ AddWrite(ConstructClientAckPacket(3, 3, 1, 1));
Initialize();
@@ -1286,15 +1326,13 @@ TEST_P(QuicHttpStreamTest, SendChunkedPostRequest) {
size_t spdy_request_headers_frame_length;
QuicStreamOffset header_stream_offset = 0;
AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
- AddWrite(InnerConstructRequestHeadersPacket(
+ AddWrite(ConstructRequestHeadersAndDataFramesPacket(
2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
- DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
- &header_stream_offset));
- AddWrite(
- ConstructClientDataPacket(3, kIncludeVersion, !kFin, 0, kUploadData));
- AddWrite(ConstructClientDataPacket(4, kIncludeVersion, kFin, chunk_size,
+ DEFAULT_PRIORITY, 0, &header_stream_offset,
+ &spdy_request_headers_frame_length, {kUploadData}));
+ AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, chunk_size,
kUploadData));
- AddWrite(ConstructClientAckPacket(5, 3, 1, 1));
+ AddWrite(ConstructClientAckPacket(4, 3, 1, 1));
Initialize();
upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
@@ -1361,14 +1399,12 @@ TEST_P(QuicHttpStreamTest, SendChunkedPostRequestWithFinalEmptyDataPacket) {
size_t spdy_request_headers_frame_length;
QuicStreamOffset header_stream_offset = 0;
AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
- AddWrite(InnerConstructRequestHeadersPacket(
+ AddWrite(ConstructRequestHeadersAndDataFramesPacket(
2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
- DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
- &header_stream_offset));
- AddWrite(
- ConstructClientDataPacket(3, kIncludeVersion, !kFin, 0, kUploadData));
- AddWrite(ConstructClientDataPacket(4, kIncludeVersion, kFin, chunk_size, ""));
- AddWrite(ConstructClientAckPacket(5, 3, 1, 1));
+ DEFAULT_PRIORITY, 0, &header_stream_offset,
+ &spdy_request_headers_frame_length, {kUploadData}));
+ AddWrite(ConstructClientDataPacket(3, kIncludeVersion, kFin, chunk_size, ""));
+ AddWrite(ConstructClientAckPacket(4, 3, 1, 1));
Initialize();
upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
@@ -1589,12 +1625,10 @@ TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
size_t spdy_request_headers_frame_length;
QuicStreamOffset header_stream_offset = 0;
AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
- AddWrite(InnerConstructRequestHeadersPacket(
+ AddWrite(ConstructRequestHeadersAndDataFramesPacket(
2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
- DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
- &header_stream_offset));
- AddWrite(
- ConstructClientDataPacket(3, kIncludeVersion, !kFin, 0, kUploadData));
+ DEFAULT_PRIORITY, 0, &header_stream_offset,
+ &spdy_request_headers_frame_length, {kUploadData}));
// Second data write will result in a synchronous failure which will close
// the session.
AddWrite(SYNCHRONOUS, ERR_FAILED);
@@ -1618,11 +1652,16 @@ TEST_P(QuicHttpStreamTest, SessionClosedDuringDoLoop) {
QuicHttpStream* stream = stream_.get();
DeleteStreamCallback delete_stream_callback(std::move(stream_));
// SendRequest() completes asynchronously after the final chunk is added.
+ // Error does not surface yet since packet write is triggered by a packet
+ // flusher that tries to bundle request body writes.
ASSERT_EQ(ERR_IO_PENDING,
stream->SendRequest(headers_, &response_, callback_.callback()));
chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
int rv = callback_.WaitForResult();
- EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR, rv);
+ EXPECT_EQ(OK, rv);
+ // Error will be surfaced once an attempt to read the response occurs.
+ ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
+ stream->ReadResponseHeaders(callback_.callback()));
}
TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
@@ -1633,6 +1672,8 @@ TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
Initialize();
upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
+ auto* chunked_upload_stream =
+ static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
request_.method = "POST";
request_.url = GURL("https://www.example.org/");
@@ -1643,9 +1684,49 @@ TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersComplete) {
ASSERT_EQ(OK,
stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
net_log_.bound(), callback_.callback()));
- ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
+ ASSERT_EQ(ERR_IO_PENDING,
stream_->SendRequest(headers_, &response_, callback_.callback()));
+ // Error will be surfaced once |upload_data_stream| triggers the next write.
+ size_t chunk_size = strlen(kUploadData);
+ chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
+ ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
+
+ EXPECT_LE(0, stream_->GetTotalSentBytes());
+ EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
+}
+
+TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendHeadersCompleteReadResponse) {
+ SetRequest("POST", "/", DEFAULT_PRIORITY);
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+ AddWrite(SYNCHRONOUS, ERR_FAILED);
+ Initialize();
+
+ upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
+ auto* chunked_upload_stream =
+ static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
+
+ request_.method = "POST";
+ request_.url = GURL("https://www.example.org/");
+ request_.upload_data_stream = upload_data_stream_.get();
+
+ size_t chunk_size = strlen(kUploadData);
+ chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
+
+ ASSERT_EQ(OK, request_.upload_data_stream->Init(
+ TestCompletionCallback().callback(), NetLogWithSource()));
+
+ ASSERT_EQ(OK,
+ stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
+ ASSERT_EQ(OK,
+ stream_->SendRequest(headers_, &response_, callback_.callback()));
+
+ // Error will be surfaced once an attempt to read the response occurs.
+ ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
+ stream_->ReadResponseHeaders(callback_.callback()));
+
EXPECT_LE(0, stream_->GetTotalSentBytes());
EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
}
@@ -1665,8 +1746,6 @@ TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
auto* chunked_upload_stream =
static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
- size_t chunk_size = strlen(kUploadData);
- chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
request_.method = "POST";
request_.url = GURL("https://www.example.org/");
@@ -1677,8 +1756,65 @@ TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBodyComplete) {
ASSERT_EQ(OK,
stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
net_log_.bound(), callback_.callback()));
+ ASSERT_EQ(ERR_IO_PENDING,
+ stream_->SendRequest(headers_, &response_, callback_.callback()));
+
+ size_t chunk_size = strlen(kUploadData);
+ chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
+ // Error does not surface yet since packet write is triggered by a packet
+ // flusher that tries to bundle request body writes.
+ ASSERT_EQ(OK, callback_.WaitForResult());
+ // Error will be surfaced once an attempt to read the response occurs.
ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
+ stream_->ReadResponseHeaders(callback_.callback()));
+
+ EXPECT_LE(0, stream_->GetTotalSentBytes());
+ EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
+}
+
+TEST_P(QuicHttpStreamTest, SessionClosedBeforeSendBundledBodyComplete) {
+ SetRequest("POST", "/", DEFAULT_PRIORITY);
+ size_t spdy_request_headers_frame_length;
+ QuicStreamOffset header_stream_offset = 0;
+ AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
+ AddWrite(ConstructRequestHeadersAndDataFramesPacket(
+ 2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
+ DEFAULT_PRIORITY, 0, &header_stream_offset,
+ &spdy_request_headers_frame_length, {kUploadData}));
+ AddWrite(SYNCHRONOUS, ERR_FAILED);
+ Initialize();
+
+ upload_data_stream_ = std::make_unique<ChunkedUploadDataStream>(0);
+ auto* chunked_upload_stream =
+ static_cast<ChunkedUploadDataStream*>(upload_data_stream_.get());
+
+ request_.method = "POST";
+ request_.url = GURL("https://www.example.org/");
+ request_.upload_data_stream = upload_data_stream_.get();
+
+ size_t chunk_size = strlen(kUploadData);
+ chunked_upload_stream->AppendData(kUploadData, chunk_size, false);
+
+ ASSERT_EQ(OK, request_.upload_data_stream->Init(
+ TestCompletionCallback().callback(), NetLogWithSource()));
+
+ ASSERT_EQ(OK,
+ stream_->InitializeStream(&request_, false, DEFAULT_PRIORITY,
+ net_log_.bound(), callback_.callback()));
+ ASSERT_EQ(ERR_IO_PENDING,
stream_->SendRequest(headers_, &response_, callback_.callback()));
+
+ chunked_upload_stream->AppendData(kUploadData, chunk_size, true);
+
+ // Error does not surface yet since packet write is triggered by a packet
+ // flusher that tries to bundle request body writes.
+ ASSERT_EQ(OK, callback_.WaitForResult());
+ // Error will be surfaced once an attempt to read the response occurs.
+ ASSERT_EQ(ERR_QUIC_PROTOCOL_ERROR,
+ stream_->ReadResponseHeaders(callback_.callback()));
+
+ EXPECT_LE(0, stream_->GetTotalSentBytes());
+ EXPECT_EQ(0, stream_->GetTotalReceivedBytes());
}
TEST_P(QuicHttpStreamTest, ServerPushGetRequest) {
@@ -2164,11 +2300,10 @@ TEST_P(QuicHttpStreamTest, DataReadErrorSynchronous) {
size_t spdy_request_headers_frame_length;
QuicStreamOffset header_stream_offset = 0;
AddWrite(ConstructInitialSettingsPacket(&header_stream_offset));
- AddWrite(InnerConstructRequestHeadersPacket(
+ AddWrite(ConstructRequestAndRstPacket(
2, GetNthClientInitiatedStreamId(0), kIncludeVersion, !kFin,
- DEFAULT_PRIORITY, &spdy_request_headers_frame_length,
- &header_stream_offset));
- AddWrite(ConstructClientRstStreamErrorPacket(3, kIncludeVersion));
+ DEFAULT_PRIORITY, 0, &spdy_request_headers_frame_length,
+ &header_stream_offset, QUIC_ERROR_PROCESSING_STREAM, 0));
Initialize();
diff --git a/chromium/net/quic/chromium/quic_http_utils.cc b/chromium/net/quic/chromium/quic_http_utils.cc
index 664ab42bd65..a0b52a27552 100644
--- a/chromium/net/quic/chromium/quic_http_utils.cc
+++ b/chromium/net/quic/chromium/quic_http_utils.cc
@@ -8,6 +8,7 @@
#include "base/metrics/histogram_macros.h"
#include "net/quic/platform/api/quic_endian.h"
+#include "net/spdy/chromium/spdy_log_util.h"
namespace net {
diff --git a/chromium/net/quic/chromium/quic_http_utils.h b/chromium/net/quic/chromium/quic_http_utils.h
index f2839b82724..1c2d4848bea 100644
--- a/chromium/net/quic/chromium/quic_http_utils.h
+++ b/chromium/net/quic/chromium/quic_http_utils.h
@@ -8,6 +8,7 @@
#include "base/values.h"
#include "net/base/net_export.h"
#include "net/base/request_priority.h"
+#include "net/log/net_log_capture_mode.h"
#include "net/quic/core/quic_packets.h"
#include "net/spdy/core/spdy_header_block.h"
#include "net/spdy/core/spdy_protocol.h"
diff --git a/chromium/net/quic/chromium/quic_network_transaction_unittest.cc b/chromium/net/quic/chromium/quic_network_transaction_unittest.cc
index ca11773b3b0..e270c0d8e8d 100644
--- a/chromium/net/quic/chromium/quic_network_transaction_unittest.cc
+++ b/chromium/net/quic/chromium/quic_network_transaction_unittest.cc
@@ -37,8 +37,8 @@
#include "net/log/test_net_log_entry.h"
#include "net/log/test_net_log_util.h"
#include "net/proxy_resolution/proxy_config_service_fixed.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
#include "net/proxy_resolution/proxy_resolver.h"
-#include "net/proxy_resolution/proxy_service.h"
#include "net/quic/chromium/crypto/proof_verifier_chromium.h"
#include "net/quic/chromium/mock_crypto_client_stream_factory.h"
#include "net/quic/chromium/mock_quic_data.h"
@@ -53,7 +53,7 @@
#include "net/quic/core/quic_framer.h"
#include "net/quic/platform/api/quic_str_cat.h"
#include "net/quic/platform/api/quic_string_piece.h"
-#include "net/quic/platform/impl/quic_test_impl.h"
+#include "net/quic/platform/api/quic_test.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/mock_random.h"
@@ -423,20 +423,19 @@ class QuicNetworkTransactionTest : public PlatformTest,
ConvertRequestPriorityToQuicPriority(request_priority), offset);
}
- std::unique_ptr<QuicEncryptedPacket> ConstructClientAckAndPriorityPacket(
+ std::unique_ptr<QuicEncryptedPacket>
+ ConstructClientAckAndPriorityFramesPacket(
QuicPacketNumber packet_number,
bool should_include_version,
QuicPacketNumber largest_received,
QuicPacketNumber smallest_received,
QuicPacketNumber least_unacked,
- QuicStreamId stream_id,
- QuicStreamId parent_stream_id,
- RequestPriority request_priority,
+ const std::vector<QuicTestPacketMaker::Http2StreamDependency>&
+ priority_frames,
QuicStreamOffset* offset) {
- return client_maker_.MakeAckAndPriorityPacket(
+ return client_maker_.MakeAckAndMultiplePriorityFramesPacket(
packet_number, should_include_version, largest_received,
- smallest_received, least_unacked, stream_id, parent_stream_id,
- ConvertRequestPriorityToQuicPriority(request_priority), offset);
+ smallest_received, least_unacked, priority_frames, offset);
}
// Uses default QuicTestPacketMaker.
@@ -568,6 +567,26 @@ class QuicNetworkTransactionTest : public PlatformTest,
std::move(headers), parent_stream_id, offset);
}
+ std::unique_ptr<QuicReceivedPacket>
+ ConstructClientRequestHeadersAndDataFramesPacket(
+ QuicPacketNumber packet_number,
+ QuicStreamId stream_id,
+ bool should_include_version,
+ bool fin,
+ RequestPriority request_priority,
+ SpdyHeaderBlock headers,
+ QuicStreamId parent_stream_id,
+ QuicStreamOffset* offset,
+ size_t* spdy_headers_frame_length,
+ const std::vector<std::string>& data_writes) {
+ SpdyPriority priority =
+ ConvertRequestPriorityToQuicPriority(request_priority);
+ return client_maker_.MakeRequestHeadersAndMultipleDataFramesPacket(
+ packet_number, stream_id, should_include_version, fin, priority,
+ std::move(headers), parent_stream_id, offset, spdy_headers_frame_length,
+ data_writes);
+ }
+
std::unique_ptr<QuicEncryptedPacket> ConstructClientMultipleDataFramesPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
@@ -837,7 +856,7 @@ class QuicNetworkTransactionTest : public PlatformTest,
session_context_.proxy_delegate = &test_proxy_delegate;
proxy_resolution_service_ =
ProxyResolutionService::CreateFixedFromPacResult(
- "HTTPS myproxy.org:443");
+ "HTTPS myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
CreateSession();
EXPECT_TRUE(test_proxy_delegate.alternative_proxy_server().is_valid());
@@ -928,6 +947,7 @@ INSTANTIATE_TEST_CASE_P(
::testing::Bool()));
TEST_P(QuicNetworkTransactionTest, WriteErrorHandshakeConfirmed) {
+ session_params_.retry_without_alt_svc_on_quic_errors = false;
base::HistogramTester histograms;
session_params_.origins_to_force_quic_on.insert(
HostPortPair::FromString("mail.example.org:443"));
@@ -959,6 +979,7 @@ TEST_P(QuicNetworkTransactionTest, WriteErrorHandshakeConfirmed) {
}
TEST_P(QuicNetworkTransactionTest, WriteErrorHandshakeConfirmedAsync) {
+ session_params_.retry_without_alt_svc_on_quic_errors = false;
base::HistogramTester histograms;
session_params_.origins_to_force_quic_on.insert(
HostPortPair::FromString("mail.example.org:443"));
@@ -1166,6 +1187,7 @@ TEST_P(QuicNetworkTransactionTest, LargeResponseHeaders) {
}
TEST_P(QuicNetworkTransactionTest, TooLargeResponseHeaders) {
+ session_params_.retry_without_alt_svc_on_quic_errors = false;
session_params_.origins_to_force_quic_on.insert(
HostPortPair::FromString("mail.example.org:443"));
@@ -1253,7 +1275,7 @@ TEST_P(QuicNetworkTransactionTest, ForceQuicForAll) {
TEST_P(QuicNetworkTransactionTest, QuicProxy) {
session_params_.enable_quic = true;
proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
- "QUIC mail.example.org:70");
+ "QUIC mail.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
MockQuicData mock_quic_data;
QuicStreamOffset header_stream_offset = 0;
@@ -1295,7 +1317,7 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyWithCert) {
session_params_.enable_quic = true;
proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
- "QUIC " + proxy_host + ":70");
+ "QUIC " + proxy_host + ":70", TRAFFIC_ANNOTATION_FOR_TESTS);
client_maker_.set_hostname(origin_host);
MockQuicData mock_quic_data;
@@ -2050,6 +2072,7 @@ TEST_P(QuicNetworkTransactionTest, GoAwayWithConnectionMigrationOnPortsOnly) {
// Verify that if a QUIC connection times out, the QuicHttpStream will
// return QUIC_PROTOCOL_ERROR.
TEST_P(QuicNetworkTransactionTest, TimeoutAfterHandshakeConfirmed) {
+ session_params_.retry_without_alt_svc_on_quic_errors = false;
session_params_.quic_idle_connection_timeout_seconds = 5;
// The request will initially go out over QUIC.
@@ -2143,6 +2166,7 @@ TEST_P(QuicNetworkTransactionTest, TimeoutAfterHandshakeConfirmed) {
// Verify that if a QUIC connection RTOs, the QuicHttpStream will
// return QUIC_PROTOCOL_ERROR.
TEST_P(QuicNetworkTransactionTest, TooManyRtosAfterHandshakeConfirmed) {
+ session_params_.retry_without_alt_svc_on_quic_errors = false;
session_params_.quic_connection_options.push_back(k5RTO);
// The request will initially go out over QUIC.
@@ -2345,6 +2369,7 @@ TEST_P(QuicNetworkTransactionTest,
// Verify that if a QUIC protocol error occurs after the handshake is confirmed
// the request fails with QUIC_PROTOCOL_ERROR.
TEST_P(QuicNetworkTransactionTest, ProtocolErrorAfterHandshakeConfirmed) {
+ session_params_.retry_without_alt_svc_on_quic_errors = false;
// The request will initially go out over QUIC.
MockQuicData quic_data;
QuicStreamOffset header_stream_offset = 0;
@@ -2527,7 +2552,6 @@ TEST_P(QuicNetworkTransactionTest, TimeoutAfterHandshakeConfirmedThenBroken) {
// connection times out, then QUIC will be marked as broken and the request
// retried over TCP.
TEST_P(QuicNetworkTransactionTest, TimeoutAfterHandshakeConfirmedThenBroken2) {
- session_params_.retry_without_alt_svc_on_quic_errors = true;
session_params_.quic_idle_connection_timeout_seconds = 5;
// The request will initially go out over QUIC.
@@ -2997,7 +3021,6 @@ TEST_P(QuicNetworkTransactionTest,
// retried over TCP and the QUIC will be marked as broken.
TEST_P(QuicNetworkTransactionTest,
ProtocolErrorAfterHandshakeConfirmedThenBroken) {
- session_params_.retry_without_alt_svc_on_quic_errors = true;
session_params_.quic_idle_connection_timeout_seconds = 5;
// The request will initially go out over QUIC.
@@ -3085,8 +3108,6 @@ TEST_P(QuicNetworkTransactionTest,
// request is reset from, then QUIC will be marked as broken and the request
// retried over TCP.
TEST_P(QuicNetworkTransactionTest, ResetAfterHandshakeConfirmedThenBroken) {
- session_params_.retry_without_alt_svc_on_quic_errors = true;
-
// The request will initially go out over QUIC.
MockQuicData quic_data;
QuicStreamOffset header_stream_offset = 0;
@@ -3247,7 +3268,6 @@ TEST_P(QuicNetworkTransactionTest, RemoteAltSvcWorkingWhileLocalAltSvcBroken) {
TEST_P(QuicNetworkTransactionTest,
ResetPooledAfterHandshakeConfirmedThenBroken) {
session_params_.quic_allow_remote_alt_svc = true;
- session_params_.retry_without_alt_svc_on_quic_errors = true;
GURL origin1 = request_.url;
GURL origin2("https://www.example.org/");
@@ -3374,10 +3394,10 @@ TEST_P(QuicNetworkTransactionTest,
SendRequestAndExpectHttpResponse("hello world");
}
-// When multiple alternative services are advertised,
-// HttpStreamFactoryImpl::RequestStreamInternal() should select the alternative
-// service which uses existing QUIC session if available. If no existing QUIC
-// session can be used, use the first alternative service from the list.
+// When multiple alternative services are advertised, HttpStreamFactoryImpl
+// should select the alternative service which uses existing QUIC session if
+// available. If no existing QUIC session can be used, use the first alternative
+// service from the list.
TEST_P(QuicNetworkTransactionTest, UseExistingAlternativeServiceForQuic) {
session_params_.quic_allow_remote_alt_svc = true;
MockRead http_reads[] = {
@@ -3492,7 +3512,7 @@ TEST_P(QuicNetworkTransactionTest, UseExistingQUICAlternativeProxy) {
TestProxyDelegate test_proxy_delegate;
proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
- "HTTPS mail.example.org:443");
+ "HTTPS mail.example.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
test_proxy_delegate.set_alternative_proxy_server(
ProxyServer::FromPacString("QUIC mail.example.org:443"));
@@ -3889,7 +3909,7 @@ TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceForQuicForHttps) {
TEST_P(QuicNetworkTransactionTest, QuicProxyWithRacing) {
base::HistogramTester histogram_tester;
proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
- "HTTPS mail.example.org:443");
+ "HTTPS mail.example.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
MockQuicData mock_quic_data;
QuicStreamOffset header_stream_offset = 0;
@@ -4054,8 +4074,8 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) {
}
TEST_P(QuicNetworkTransactionTest, ZeroRTTWithProxy) {
- proxy_resolution_service_ =
- ProxyResolutionService::CreateFixedFromPacResult("PROXY myproxy:70");
+ proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
+ "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
// Since we are using a proxy, the QUIC job will not succeed.
MockWrite http_writes[] = {
@@ -4144,6 +4164,7 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {
TEST_P(QuicNetworkTransactionTest,
LogGranularQuicErrorCodeOnQuicProtocolErrorLocal) {
+ session_params_.retry_without_alt_svc_on_quic_errors = false;
MockQuicData mock_quic_data;
QuicStreamOffset header_stream_offset = 0;
mock_quic_data.AddWrite(
@@ -4197,6 +4218,7 @@ TEST_P(QuicNetworkTransactionTest,
TEST_P(QuicNetworkTransactionTest,
LogGranularQuicErrorCodeOnQuicProtocolErrorRemote) {
+ session_params_.retry_without_alt_svc_on_quic_errors = false;
MockQuicData mock_quic_data;
QuicStreamOffset header_stream_offset = 0;
mock_quic_data.AddWrite(
@@ -4315,6 +4337,7 @@ TEST_P(QuicNetworkTransactionTest, RstSteamErrorHandling) {
}
TEST_P(QuicNetworkTransactionTest, RstSteamBeforeHeaders) {
+ session_params_.retry_without_alt_svc_on_quic_errors = false;
MockQuicData mock_quic_data;
QuicStreamOffset header_stream_offset = 0;
mock_quic_data.AddWrite(
@@ -4781,8 +4804,8 @@ TEST_P(QuicNetworkTransactionTest, ConnectionCloseDuringConnectProxy) {
EXPECT_TRUE(test_proxy_delegate.alternative_proxy_server().is_quic());
session_context_.proxy_delegate = &test_proxy_delegate;
- proxy_resolution_service_ =
- ProxyResolutionService::CreateFixedFromPacResult("HTTPS myproxy.org:443");
+ proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
+ "HTTPS myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
request_.url = GURL("http://mail.example.org/");
// In order for a new QUIC session to be established via alternate-protocol
@@ -4837,7 +4860,7 @@ TEST_P(QuicNetworkTransactionTest,
DISABLED_QuicUploadToAlternativeProxyServer) {
base::HistogramTester histogram_tester;
proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
- "HTTPS mail.example.org:443");
+ "HTTPS mail.example.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
TestProxyDelegate test_proxy_delegate;
@@ -4910,6 +4933,7 @@ TEST_P(QuicNetworkTransactionTest, QuicUpload) {
}
TEST_P(QuicNetworkTransactionTest, QuicUploadWriteError) {
+ session_params_.retry_without_alt_svc_on_quic_errors = false;
ScopedMockNetworkChangeNotifier network_change_notifier;
MockNetworkChangeNotifier* mock_ncn =
network_change_notifier.mock_network_change_notifier();
@@ -5015,6 +5039,7 @@ TEST_P(QuicNetworkTransactionTest, RetryAfterSynchronousNoBufferSpace) {
}
TEST_P(QuicNetworkTransactionTest, MaxRetriesAfterAsyncNoBufferSpace) {
+ session_params_.retry_without_alt_svc_on_quic_errors = false;
session_params_.origins_to_force_quic_on.insert(
HostPortPair::FromString("mail.example.org:443"));
@@ -5052,6 +5077,7 @@ TEST_P(QuicNetworkTransactionTest, MaxRetriesAfterAsyncNoBufferSpace) {
}
TEST_P(QuicNetworkTransactionTest, MaxRetriesAfterSynchronousNoBufferSpace) {
+ session_params_.retry_without_alt_svc_on_quic_errors = false;
session_params_.origins_to_force_quic_on.insert(
HostPortPair::FromString("mail.example.org:443"));
@@ -5089,6 +5115,7 @@ TEST_P(QuicNetworkTransactionTest, MaxRetriesAfterSynchronousNoBufferSpace) {
}
TEST_P(QuicNetworkTransactionTest, NoMigrationForMsgTooBig) {
+ session_params_.retry_without_alt_svc_on_quic_errors = false;
session_params_.origins_to_force_quic_on.insert(
HostPortPair::FromString("mail.example.org:443"));
const QuicString error_details =
@@ -5192,6 +5219,7 @@ TEST_P(QuicNetworkTransactionTest, QuicServerPush) {
// is closed before the pushed headers arrive, but after the connection
// is closed and before the callbacks are executed.
TEST_P(QuicNetworkTransactionTest, CancelServerPushAfterConnectionClose) {
+ session_params_.retry_without_alt_svc_on_quic_errors = false;
session_params_.origins_to_force_quic_on.insert(
HostPortPair::FromString("mail.example.org:443"));
@@ -5278,14 +5306,10 @@ TEST_P(QuicNetworkTransactionTest, QuicForceHolBlocking) {
QuicStreamOffset offset = 0;
mock_quic_data.AddWrite(ConstructInitialSettingsPacket(1, &offset));
- mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- 2, GetNthClientInitiatedStreamId(0), true, false,
- GetRequestHeaders("POST", "https", "/"), &offset));
- std::unique_ptr<QuicEncryptedPacket> packet;
- packet = ConstructClientDataPacket(3, GetNthClientInitiatedStreamId(0), true,
- true, 0, "1");
- mock_quic_data.AddWrite(std::move(packet));
+ mock_quic_data.AddWrite(ConstructClientRequestHeadersAndDataFramesPacket(
+ 2, GetNthClientInitiatedStreamId(0), true, true, DEFAULT_PRIORITY,
+ GetRequestHeaders("POST", "https", "/"), 0, &offset, nullptr, {"1"}));
mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
1, GetNthClientInitiatedStreamId(0), false, false,
@@ -5294,7 +5318,7 @@ TEST_P(QuicNetworkTransactionTest, QuicForceHolBlocking) {
mock_quic_data.AddRead(ConstructServerDataPacket(
2, GetNthClientInitiatedStreamId(0), false, true, 0, "hello!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(4, 2, 1, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0); // EOF
@@ -6068,13 +6092,11 @@ TEST_P(QuicNetworkTransactionTest, QuicServerPushMatchesRequestWithBody) {
client_packet_number++, GetNthServerInitiatedStreamId(0),
QUIC_STREAM_CANCELLED, 5, 5, 1));
const char kBody[] = "1";
- mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
- client_packet_number++, GetNthClientInitiatedStreamId(1), false, false,
- GetRequestHeaders("GET", "https", "/pushed.jpg"),
- GetNthServerInitiatedStreamId(0), &header_stream_offset));
- mock_quic_data.AddWrite(ConstructClientMultipleDataFramesPacket(
+ mock_quic_data.AddWrite(ConstructClientRequestHeadersAndDataFramesPacket(
client_packet_number++, GetNthClientInitiatedStreamId(1), false, true,
- {kBody}, 0));
+ DEFAULT_PRIORITY, GetRequestHeaders("GET", "https", "/pushed.jpg"),
+ GetNthServerInitiatedStreamId(0), &header_stream_offset, nullptr,
+ {kBody}));
// We see the same response as for the earlier pushed and cancelled
// stream.
@@ -6168,7 +6190,7 @@ TEST_P(QuicNetworkTransactionTest, QuicServerPushWithEmptyHostname) {
TEST_P(QuicNetworkTransactionTest, QuicProxyConnectHttpsServer) {
session_params_.enable_quic = true;
proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
- "QUIC proxy.example.org:70");
+ "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
MockQuicData mock_quic_data;
QuicStreamOffset header_stream_offset = 0;
@@ -6237,7 +6259,7 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyConnectHttpsServer) {
TEST_P(QuicNetworkTransactionTest, QuicProxyConnectSpdyServer) {
session_params_.enable_quic = true;
proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
- "QUIC proxy.example.org:70");
+ "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
MockQuicData mock_quic_data;
QuicStreamOffset header_stream_offset = 0;
@@ -6310,7 +6332,7 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyConnectSpdyServer) {
TEST_P(QuicNetworkTransactionTest, QuicProxyConnectReuseTransportSocket) {
session_params_.enable_quic = true;
proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
- "QUIC proxy.example.org:70");
+ "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
MockQuicData mock_quic_data;
QuicStreamOffset header_stream_offset = 0;
@@ -6425,7 +6447,7 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyConnectReuseTransportSocket) {
TEST_P(QuicNetworkTransactionTest, QuicProxyConnectReuseQuicSession) {
session_params_.enable_quic = true;
proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
- "QUIC proxy.example.org:70");
+ "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
MockQuicData mock_quic_data;
QuicStreamOffset client_header_stream_offset = 0;
@@ -6549,7 +6571,7 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyConnectReuseQuicSession) {
TEST_P(QuicNetworkTransactionTest, QuicProxyConnectFailure) {
session_params_.enable_quic = true;
proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
- "QUIC proxy.example.org:70");
+ "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
MockQuicData mock_quic_data;
QuicStreamOffset header_stream_offset = 0;
@@ -6591,7 +6613,7 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyConnectFailure) {
TEST_P(QuicNetworkTransactionTest, QuicProxyQuicConnectionError) {
session_params_.enable_quic = true;
proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
- "QUIC proxy.example.org:70");
+ "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
MockQuicData mock_quic_data;
QuicStreamOffset header_stream_offset = 0;
@@ -6626,7 +6648,7 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyQuicConnectionError) {
TEST_P(QuicNetworkTransactionTest, QuicProxyConnectBadCertificate) {
session_params_.enable_quic = true;
proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
- "QUIC proxy.example.org:70");
+ "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
MockQuicData mock_quic_data;
QuicStreamOffset client_header_stream_offset = 0;
@@ -6720,7 +6742,7 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyConnectBadCertificate) {
TEST_P(QuicNetworkTransactionTest, QuicProxyUserAgent) {
session_params_.enable_quic = true;
proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
- "QUIC proxy.example.org:70");
+ "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
MockQuicData mock_quic_data;
QuicStreamOffset header_stream_offset = 0;
@@ -6762,7 +6784,7 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyUserAgent) {
TEST_P(QuicNetworkTransactionTest, QuicProxyRequestPriority) {
session_params_.enable_quic = true;
proxy_resolution_service_ = ProxyResolutionService::CreateFixedFromPacResult(
- "QUIC proxy.example.org:70");
+ "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
const RequestPriority request_priority = MEDIUM;
@@ -6817,7 +6839,7 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyAuth) {
session_params_.enable_quic = true;
proxy_resolution_service_ =
ProxyResolutionService::CreateFixedFromPacResult(
- "QUIC proxy.example.org:70");
+ "QUIC proxy.example.org:70", TRAFFIC_ANNOTATION_FOR_TESTS);
MockQuicData mock_quic_data;
QuicStreamOffset client_header_stream_offset = 0;
@@ -7004,8 +7026,10 @@ TEST_P(QuicNetworkTransactionTest, QuicServerPushUpdatesPriority) {
4, client_stream_0, push_stream_0, false,
GetRequestHeaders("GET", "https", "/pushed_0.jpg"), &server_header_offset,
&server_maker_));
- mock_quic_data.AddWrite(ConstructClientAckAndPriorityPacket(
- 6, false, 4, 3, 1, push_stream_0, client_stream_2, DEFAULT_PRIORITY,
+ mock_quic_data.AddWrite(ConstructClientAckAndPriorityFramesPacket(
+ 6, false, 4, 3, 1,
+ {{push_stream_0, client_stream_2,
+ ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY)}},
&header_stream_offset));
mock_quic_data.AddRead(ConstructServerPushPromisePacket(
5, client_stream_0, push_stream_1, false,
@@ -7027,29 +7051,30 @@ TEST_P(QuicNetworkTransactionTest, QuicServerPushUpdatesPriority) {
// Request for "pushed_0.jpg" matches |push_stream_0|. |push_stream_0|'s
// priority updates to match the request's priority. Client sends PRIORITY
// frames to inform server of new HTTP/2 stream dependencies.
- mock_quic_data.AddWrite(ConstructClientAckAndPriorityPacket(
- 9, false, 7, 7, 1, push_stream_1, client_stream_2, DEFAULT_PRIORITY,
+ mock_quic_data.AddWrite(ConstructClientAckAndPriorityFramesPacket(
+ 9, false, 7, 7, 1,
+ {{push_stream_1, client_stream_2,
+ ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY)},
+ {push_stream_0, client_stream_0,
+ ConvertRequestPriorityToQuicPriority(HIGHEST)}},
&header_stream_offset));
- mock_quic_data.AddWrite(
- ConstructClientPriorityPacket(10, false, push_stream_0, client_stream_0,
- HIGHEST, &header_stream_offset));
// Server sends data for the three requests and the two push promises.
mock_quic_data.AddRead(ConstructServerDataPacket(8, client_stream_0, false,
true, 0, "hello 0!"));
mock_quic_data.AddSynchronousRead(ConstructServerDataPacket(
9, client_stream_1, false, true, 0, "hello 1!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(11, 9, 8, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(10, 9, 8, 1));
mock_quic_data.AddRead(ConstructServerDataPacket(10, client_stream_2, false,
true, 0, "hello 2!"));
mock_quic_data.AddSynchronousRead(ConstructServerDataPacket(
11, push_stream_0, false, true, 0, "and hello 0!"));
- mock_quic_data.AddWrite(ConstructClientAckPacket(12, 11, 10, 1));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(11, 11, 10, 1));
mock_quic_data.AddRead(ConstructServerDataPacket(12, push_stream_1, false,
true, 0, "and hello 1!"));
mock_quic_data.AddWrite(ConstructClientAckAndRstPacket(
- 13, push_stream_0, QUIC_RST_ACKNOWLEDGEMENT, 12, 12, 1));
+ 12, push_stream_0, QUIC_RST_ACKNOWLEDGEMENT, 12, 12, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
mock_quic_data.AddRead(ASYNC, 0); // EOF
diff --git a/chromium/net/quic/chromium/quic_proxy_client_socket_unittest.cc b/chromium/net/quic/chromium/quic_proxy_client_socket_unittest.cc
index b87795d17b7..cd205c97287 100644
--- a/chromium/net/quic/chromium/quic_proxy_client_socket_unittest.cc
+++ b/chromium/net/quic/chromium/quic_proxy_client_socket_unittest.cc
@@ -25,6 +25,7 @@
#include "net/quic/chromium/quic_chromium_packet_writer.h"
#include "net/quic/chromium/quic_http_utils.h"
#include "net/quic/chromium/quic_server_info.h"
+#include "net/quic/chromium/quic_stream_factory.h"
#include "net/quic/chromium/quic_test_packet_maker.h"
#include "net/quic/chromium/test_task_runner.h"
#include "net/quic/core/crypto/null_encrypter.h"
@@ -1362,13 +1363,8 @@ TEST_P(QuicProxyClientSocketTest, RstWithReadAndWritePending) {
mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
mock_quic_data_.AddAsyncWrite(
ConstructAckAndDataPacket(3, 1, 1, 1, 0, kMsg2, kLen2));
- if (FLAGS_quic_reloadable_flag_quic_use_control_frame_manager) {
mock_quic_data_.AddWrite(
ConstructAckAndRstPacket(4, QUIC_RST_ACKNOWLEDGEMENT, 2, 2, 1, kLen2));
- } else {
- mock_quic_data_.AddWrite(
- ConstructRstPacket(4, QUIC_RST_ACKNOWLEDGEMENT, kLen2));
- }
Initialize();
@@ -1485,13 +1481,8 @@ TEST_P(QuicProxyClientSocketTest, RstWithReadAndWritePendingDelete) {
mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
mock_quic_data_.AddAsyncWrite(
ConstructAckAndDataPacket(3, 1, 1, 1, 0, kMsg1, kLen1));
- if (FLAGS_quic_reloadable_flag_quic_use_control_frame_manager) {
mock_quic_data_.AddWrite(
ConstructAckAndRstPacket(4, QUIC_RST_ACKNOWLEDGEMENT, 2, 2, 1, kLen1));
- } else {
- mock_quic_data_.AddWrite(
- ConstructRstPacket(4, QUIC_RST_ACKNOWLEDGEMENT, kLen1));
- }
Initialize();
diff --git a/chromium/net/quic/chromium/quic_stream_factory.cc b/chromium/net/quic/chromium/quic_stream_factory.cc
index 6e816ad9edf..9448749cd60 100644
--- a/chromium/net/quic/chromium/quic_stream_factory.cc
+++ b/chromium/net/quic/chromium/quic_stream_factory.cc
@@ -14,7 +14,6 @@
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
-#include "base/rand_util.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -32,6 +31,7 @@
#include "net/cert/cert_verifier.h"
#include "net/cert/ct_verifier.h"
#include "net/dns/host_resolver.h"
+#include "net/log/net_log.h"
#include "net/log/net_log_capture_mode.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_source_type.h"
@@ -1346,7 +1346,7 @@ std::unique_ptr<DatagramClientSocket> QuicStreamFactory::CreateSocket(
NetLog* net_log,
const NetLogSource& source) {
auto socket = client_socket_factory_->CreateDatagramClientSocket(
- DatagramSocket::DEFAULT_BIND, RandIntCallback(), net_log, source);
+ DatagramSocket::DEFAULT_BIND, net_log, source);
if (enable_socket_recv_optimization_)
socket->EnableRecvOptimization();
return socket;
diff --git a/chromium/net/quic/chromium/quic_stream_factory.h b/chromium/net/quic/chromium/quic_stream_factory.h
index 92dab824bfc..041bd2e52e9 100644
--- a/chromium/net/quic/chromium/quic_stream_factory.h
+++ b/chromium/net/quic/chromium/quic_stream_factory.h
@@ -77,19 +77,13 @@ class QuicStreamFactoryPeer;
// When a connection is idle for 30 seconds it will be closed.
const int kIdleConnectionTimeoutSeconds = 30;
-enum QuicConnectionMigrationStatus {
- MIGRATION_STATUS_NO_MIGRATABLE_STREAMS,
- MIGRATION_STATUS_ALREADY_MIGRATED,
- MIGRATION_STATUS_INTERNAL_ERROR,
- MIGRATION_STATUS_TOO_MANY_CHANGES,
- MIGRATION_STATUS_SUCCESS,
- MIGRATION_STATUS_NON_MIGRATABLE_STREAM,
- MIGRATION_STATUS_NOT_ENABLED,
- MIGRATION_STATUS_NO_ALTERNATE_NETWORK,
- MIGRATION_STATUS_ON_PATH_DEGRADING_DISABLED,
- MIGRATION_STATUS_DISABLED_BY_CONFIG,
- MIGRATION_STATUS_MAX
-};
+// The default maximum time QUIC session could be on non-default network before
+// migrate back to default network.
+const int64_t kMaxTimeOnNonDefaultNetworkSecs = 128;
+
+// The default maximum number of migrations to non default network on path
+// degrading per network. Used in chromium only.
+const int64_t kMaxMigrationsToNonDefaultNetworkOnPathDegrading = 5;
enum QuicPlatformNotification {
NETWORK_CONNECTED,
diff --git a/chromium/net/quic/chromium/quic_stream_factory_test.cc b/chromium/net/quic/chromium/quic_stream_factory_test.cc
index 0122d1f6696..03c813265b5 100644
--- a/chromium/net/quic/chromium/quic_stream_factory_test.cc
+++ b/chromium/net/quic/chromium/quic_stream_factory_test.cc
@@ -40,7 +40,7 @@
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
#include "net/quic/core/quic_client_promised_info.h"
-#include "net/quic/platform/impl/quic_test_impl.h"
+#include "net/quic/platform/api/quic_test.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/mock_random.h"
#include "net/quic/test_tools/quic_config_peer.h"
@@ -49,6 +49,7 @@
#include "net/socket/next_proto.h"
#include "net/socket/socket_test_util.h"
#include "net/spdy/chromium/spdy_session_test_util.h"
+#include "net/spdy/chromium/spdy_test_util_common.h"
#include "net/spdy/core/spdy_test_utils.h"
#include "net/ssl/channel_id_service.h"
#include "net/ssl/default_channel_id_store.h"
@@ -189,7 +190,6 @@ class TestConnectionMigrationSocketFactory : public MockClientSocketFactory {
std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket(
DatagramSocket::BindType bind_type,
- const RandIntCallback& rand_int_cb,
NetLog* net_log,
const NetLogSource& source) override {
SocketDataProvider* data_provider = mock_data().GetNext();
@@ -2067,11 +2067,7 @@ void QuicStreamFactoryTestBase::OnNetworkMadeDefault(bool async_write_before) {
// Do an async write to leave writer blocked.
if (async_write_before) {
- if (session->use_control_frame_manager()) {
- session->SendPing();
- } else {
- session->connection()->SendPing();
- }
+ session->SendPing();
}
// Set up second socket data provider that is used after migration.
@@ -2206,11 +2202,7 @@ void QuicStreamFactoryTestBase::OnNetworkDisconnected(bool async_write_before) {
// Do an async write to leave writer blocked.
if (async_write_before) {
- if (session->use_control_frame_manager()) {
- session->SendPing();
- } else {
- session->connection()->SendPing();
- }
+ session->SendPing();
}
// Set up second socket data provider that is used after migration.
diff --git a/chromium/net/quic/chromium/quic_test_packet_maker.cc b/chromium/net/quic/chromium/quic_test_packet_maker.cc
index 9676a59007d..70d83bb4234 100644
--- a/chromium/net/quic/chromium/quic_test_packet_maker.cc
+++ b/chromium/net/quic/chromium/quic_test_packet_maker.cc
@@ -439,8 +439,9 @@ QuicTestPacketMaker::MakeRequestHeadersAndMultipleDataFramesPacket(
size_t* spdy_headers_frame_length,
const std::vector<std::string>& data_writes) {
InitializeHeader(packet_number, should_include_version);
- SpdySerializedFrame spdy_frame = MakeSpdyHeadersFrame(
- stream_id, fin, priority, std::move(headers), parent_stream_id);
+ SpdySerializedFrame spdy_frame =
+ MakeSpdyHeadersFrame(stream_id, fin && data_writes.empty(), priority,
+ std::move(headers), parent_stream_id);
if (spdy_headers_frame_length) {
*spdy_headers_frame_length = spdy_frame.size();
@@ -451,6 +452,7 @@ QuicTestPacketMaker::MakeRequestHeadersAndMultipleDataFramesPacket(
QuicStreamFrame frame(kHeadersStreamId, false, header_offset,
QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
frames.push_back(QuicFrame(&frame));
+ DVLOG(1) << "Adding frame: " << frames.back();
if (header_stream_offset != nullptr) {
*header_stream_offset += spdy_frame.size();
}
@@ -542,6 +544,45 @@ QuicTestPacketMaker::MakeRequestHeadersPacketAndSaveData(
}
}
+std::unique_ptr<QuicReceivedPacket>
+QuicTestPacketMaker::MakeRequestHeadersAndRstPacket(
+ QuicPacketNumber packet_number,
+ QuicStreamId stream_id,
+ bool should_include_version,
+ bool fin,
+ SpdyPriority priority,
+ SpdyHeaderBlock headers,
+ QuicStreamId parent_stream_id,
+ size_t* spdy_headers_frame_length,
+ QuicStreamOffset* header_stream_offset,
+ QuicRstStreamErrorCode error_code,
+ size_t bytes_written) {
+ SpdySerializedFrame spdy_frame = MakeSpdyHeadersFrame(
+ stream_id, fin, priority, std::move(headers), parent_stream_id);
+ if (spdy_headers_frame_length) {
+ *spdy_headers_frame_length = spdy_frame.size();
+ }
+ QuicStreamOffset header_offset = 0;
+ if (header_stream_offset != nullptr) {
+ header_offset = *header_stream_offset;
+ *header_stream_offset += spdy_frame.size();
+ }
+ QuicStreamFrame headers_frame(
+ kHeadersStreamId, false, header_offset,
+ QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
+
+ QuicRstStreamFrame rst_frame(1, stream_id, error_code, bytes_written);
+
+ QuicFrames frames;
+ frames.push_back(QuicFrame(&headers_frame));
+ DVLOG(1) << "Adding frame: " << frames.back();
+ frames.push_back(QuicFrame(&rst_frame));
+ DVLOG(1) << "Adding frame: " << frames.back();
+
+ InitializeHeader(packet_number, should_include_version);
+ return MakeMultipleFramesPacket(header_, frames);
+}
+
SpdySerializedFrame QuicTestPacketMaker::MakeSpdyHeadersFrame(
QuicStreamId stream_id,
bool fin,
@@ -830,15 +871,13 @@ std::unique_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakePriorityPacket(
}
std::unique_ptr<QuicReceivedPacket>
-QuicTestPacketMaker::MakeAckAndPriorityPacket(
+QuicTestPacketMaker::MakeAckAndMultiplePriorityFramesPacket(
QuicPacketNumber packet_number,
bool should_include_version,
QuicPacketNumber largest_received,
QuicPacketNumber smallest_received,
QuicPacketNumber least_unacked,
- QuicStreamId stream_id,
- QuicStreamId parent_stream_id,
- SpdyPriority spdy_priority,
+ const std::vector<Http2StreamDependency>& priority_frames,
QuicStreamOffset* offset) {
QuicAckFrame ack(MakeAckFrame(largest_received));
ack.ack_delay_time = QuicTime::Delta::Zero();
@@ -857,22 +896,33 @@ QuicTestPacketMaker::MakeAckAndPriorityPacket(
frames.push_back(QuicFrame(&stop_waiting));
DVLOG(1) << "Adding frame: " << frames[1];
- bool exclusive = client_headers_include_h2_stream_dependency_;
- SpdyPriorityIR priority_frame(stream_id, parent_stream_id,
- Spdy3PriorityToHttp2Weight(spdy_priority),
- exclusive);
- SpdySerializedFrame spdy_frame =
- spdy_request_framer_.SerializeFrame(priority_frame);
+ const bool exclusive = client_headers_include_h2_stream_dependency_;
QuicStreamOffset header_offset = 0;
- if (offset != nullptr) {
- header_offset = *offset;
- *offset += spdy_frame.size();
+ if (offset == nullptr) {
+ offset = &header_offset;
+ }
+ // Keep SpdySerializedFrames alive until MakeMultipleFramesPacket is done.
+ // Keep StreamFrames alive until MakeMultipleFramesPacket is done.
+ std::vector<std::unique_ptr<SpdySerializedFrame>> spdy_frames;
+ std::vector<std::unique_ptr<QuicStreamFrame>> stream_frames;
+ for (const Http2StreamDependency& info : priority_frames) {
+ SpdyPriorityIR priority_frame(
+ info.stream_id, info.parent_stream_id,
+ Spdy3PriorityToHttp2Weight(info.spdy_priority), exclusive);
+
+ spdy_frames.push_back(std::make_unique<SpdySerializedFrame>(
+ spdy_request_framer_.SerializeFrame(priority_frame)));
+
+ SpdySerializedFrame* spdy_frame = spdy_frames.back().get();
+ stream_frames.push_back(std::make_unique<QuicStreamFrame>(
+ kHeadersStreamId, false, *offset,
+ QuicStringPiece(spdy_frame->data(), spdy_frame->size())));
+ *offset += spdy_frame->size();
+
+ frames.push_back(QuicFrame(stream_frames.back().get()));
+ DVLOG(1) << "Adding frame: " << frames.back();
+ ;
}
- QuicStreamFrame priority(
- kHeadersStreamId, false, header_offset,
- QuicStringPiece(spdy_frame.data(), spdy_frame.size()));
- frames.push_back(QuicFrame(&priority));
- DVLOG(1) << "Adding frame: " << frames[2];
InitializeHeader(packet_number, should_include_version);
return MakeMultipleFramesPacket(header_, frames);
diff --git a/chromium/net/quic/chromium/quic_test_packet_maker.h b/chromium/net/quic/chromium/quic_test_packet_maker.h
index 925596dee09..c5a4a2b10b4 100644
--- a/chromium/net/quic/chromium/quic_test_packet_maker.h
+++ b/chromium/net/quic/chromium/quic_test_packet_maker.h
@@ -27,6 +27,12 @@ namespace test {
class QuicTestPacketMaker {
public:
+ struct Http2StreamDependency {
+ QuicStreamId stream_id;
+ QuicStreamId parent_stream_id;
+ SpdyPriority spdy_priority;
+ };
+
// |client_headers_include_h2_stream_dependency| affects the output of
// the MakeRequestHeaders...() methods. If its value is true, then request
// headers are constructed with the exclusive flag set to true and the parent
@@ -194,6 +200,19 @@ class QuicTestPacketMaker {
QuicStreamOffset* offset,
std::string* stream_data);
+ std::unique_ptr<QuicReceivedPacket> MakeRequestHeadersAndRstPacket(
+ QuicPacketNumber packet_number,
+ QuicStreamId stream_id,
+ bool should_include_version,
+ bool fin,
+ SpdyPriority priority,
+ SpdyHeaderBlock headers,
+ QuicStreamId parent_stream_id,
+ size_t* spdy_headers_frame_length,
+ QuicStreamOffset* header_stream_offset,
+ QuicRstStreamErrorCode error_code,
+ size_t bytes_written);
+
// Convenience method for calling MakeRequestHeadersPacket with nullptr for
// |spdy_headers_frame_length|.
std::unique_ptr<QuicReceivedPacket>
@@ -268,15 +287,13 @@ class QuicTestPacketMaker {
SpdyPriority priority,
QuicStreamOffset* offset);
- std::unique_ptr<QuicReceivedPacket> MakeAckAndPriorityPacket(
+ std::unique_ptr<QuicReceivedPacket> MakeAckAndMultiplePriorityFramesPacket(
QuicPacketNumber packet_number,
bool should_include_version,
QuicPacketNumber largest_received,
QuicPacketNumber smallest_received,
QuicPacketNumber least_unacked,
- QuicStreamId stream_id,
- QuicStreamId parent_stream_id,
- SpdyPriority spdy_priority,
+ const std::vector<Http2StreamDependency>& priority_frames,
QuicStreamOffset* offset);
SpdyHeaderBlock GetRequestHeaders(const std::string& method,
diff --git a/chromium/net/quic/core/congestion_control/bandwidth_sampler.h b/chromium/net/quic/core/congestion_control/bandwidth_sampler.h
index b42e8b91569..4255e614650 100644
--- a/chromium/net/quic/core/congestion_control/bandwidth_sampler.h
+++ b/chromium/net/quic/core/congestion_control/bandwidth_sampler.h
@@ -9,7 +9,6 @@
#include "net/quic/core/quic_bandwidth.h"
#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
-#include "net/quic/platform/api/quic_containers.h"
#include "net/quic/platform/api/quic_export.h"
namespace net {
@@ -250,9 +249,6 @@ class QUIC_EXPORT_PRIVATE BandwidthSampler : public BandwidthSamplerInterface {
is_app_limited(false) {}
};
- typedef QuicLinkedHashMap<QuicPacketNumber, ConnectionStateOnSentPacket>
- ConnectionStateMap;
-
// The total number of congestion controlled bytes sent during the connection.
QuicByteCount total_bytes_sent_;
diff --git a/chromium/net/quic/core/congestion_control/bbr_sender.cc b/chromium/net/quic/core/congestion_control/bbr_sender.cc
index 05266e3176f..ecbdbd78b2f 100644
--- a/chromium/net/quic/core/congestion_control/bbr_sender.cc
+++ b/chromium/net/quic/core/congestion_control/bbr_sender.cc
@@ -138,6 +138,14 @@ BbrSender::BbrSender(const RttStats* rtt_stats,
BbrSender::~BbrSender() {}
+void BbrSender::SetInitialCongestionWindowInPackets(
+ QuicPacketCount congestion_window) {
+ if (mode_ == STARTUP) {
+ initial_congestion_window_ = congestion_window * kDefaultTCPMSS;
+ congestion_window_ = congestion_window * kDefaultTCPMSS;
+ }
+}
+
bool BbrSender::InSlowStart() const {
return mode_ == STARTUP;
}
@@ -412,6 +420,11 @@ bool BbrSender::UpdateBandwidthAndMinRtt(
const AckedPacketVector& acked_packets) {
QuicTime::Delta sample_min_rtt = QuicTime::Delta::Infinite();
for (const auto& packet : acked_packets) {
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3) &&
+ packet.bytes_acked == 0) {
+ // Skip acked packets with 0 in flight bytes when updating bandwidth.
+ continue;
+ }
BandwidthSample bandwidth_sample =
sampler_->OnPacketAcknowledged(now, packet.packet_number);
last_sample_is_app_limited_ = bandwidth_sample.is_app_limited;
diff --git a/chromium/net/quic/core/congestion_control/bbr_sender.h b/chromium/net/quic/core/congestion_control/bbr_sender.h
index b351665bcd7..46993fc2891 100644
--- a/chromium/net/quic/core/congestion_control/bbr_sender.h
+++ b/chromium/net/quic/core/congestion_control/bbr_sender.h
@@ -109,6 +109,8 @@ class QUIC_EXPORT_PRIVATE BbrSender : public SendAlgorithmInterface {
void AdjustNetworkParameters(QuicBandwidth bandwidth,
QuicTime::Delta rtt) override;
void SetNumEmulatedConnections(int num_connections) override {}
+ void SetInitialCongestionWindowInPackets(
+ QuicPacketCount congestion_window) override;
void OnCongestionEvent(bool rtt_updated,
QuicByteCount prior_in_flight,
QuicTime event_time,
diff --git a/chromium/net/quic/core/congestion_control/bbr_sender_test.cc b/chromium/net/quic/core/congestion_control/bbr_sender_test.cc
index 3de677b22ca..38fee561d62 100644
--- a/chromium/net/quic/core/congestion_control/bbr_sender_test.cc
+++ b/chromium/net/quic/core/congestion_control/bbr_sender_test.cc
@@ -250,6 +250,12 @@ class BbrSenderTest : public QuicTest {
}
};
+TEST_F(BbrSenderTest, SetInitialCongestionWindow) {
+ EXPECT_NE(3u * kDefaultTCPMSS, sender_->GetCongestionWindow());
+ sender_->SetInitialCongestionWindowInPackets(3);
+ EXPECT_EQ(3u * kDefaultTCPMSS, sender_->GetCongestionWindow());
+}
+
// Test a simple long data transfer in the default setup.
TEST_F(BbrSenderTest, SimpleTransfer) {
// Adding TSO CWND causes packet loss before exiting startup.
diff --git a/chromium/net/quic/core/congestion_control/rtt_stats.cc b/chromium/net/quic/core/congestion_control/rtt_stats.cc
index 8bf8b6bc4a8..9e098d17f4b 100644
--- a/chromium/net/quic/core/congestion_control/rtt_stats.cc
+++ b/chromium/net/quic/core/congestion_control/rtt_stats.cc
@@ -70,12 +70,8 @@ void RttStats::UpdateRtt(QuicTime::Delta send_delta,
// an RTT sample at least as large as min_rtt. Otherwise, only use the
// send_delta.
if (rtt_sample > ack_delay) {
- if (GetQuicReloadableFlag(quic_min_rtt_ack_delay)) {
- if (rtt_sample - min_rtt_ >= ack_delay) {
- max_ack_delay_ = std::max(max_ack_delay_, ack_delay);
- rtt_sample = rtt_sample - ack_delay;
- }
- } else {
+ if (rtt_sample - min_rtt_ >= ack_delay) {
+ max_ack_delay_ = std::max(max_ack_delay_, ack_delay);
rtt_sample = rtt_sample - ack_delay;
}
}
diff --git a/chromium/net/quic/core/congestion_control/rtt_stats_test.cc b/chromium/net/quic/core/congestion_control/rtt_stats_test.cc
index 1e026bab5af..bc065e094cb 100644
--- a/chromium/net/quic/core/congestion_control/rtt_stats_test.cc
+++ b/chromium/net/quic/core/congestion_control/rtt_stats_test.cc
@@ -30,29 +30,6 @@ TEST_F(RttStatsTest, DefaultsBeforeUpdate) {
}
TEST_F(RttStatsTest, SmoothedRtt) {
- SetQuicReloadableFlag(quic_min_rtt_ack_delay, false);
- // Verify that ack_delay is corrected for in Smoothed RTT.
- rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(300),
- QuicTime::Delta::FromMilliseconds(100),
- QuicTime::Zero());
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.latest_rtt());
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.smoothed_rtt());
- // Verify that effective RTT of zero does not change Smoothed RTT.
- rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(200),
- QuicTime::Delta::FromMilliseconds(200),
- QuicTime::Zero());
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.latest_rtt());
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.smoothed_rtt());
- // Verify that large erroneous ack_delay does not change Smoothed RTT.
- rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(200),
- QuicTime::Delta::FromMilliseconds(300),
- QuicTime::Zero());
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.latest_rtt());
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.smoothed_rtt());
-}
-
-TEST_F(RttStatsTest, SmoothedRttMaxAckDelay) {
- SetQuicReloadableFlag(quic_min_rtt_ack_delay, true);
// Verify that ack_delay is ignored in the first measurement.
rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(300),
QuicTime::Delta::FromMilliseconds(100),
@@ -241,10 +218,7 @@ TEST_F(RttStatsTest, ResetAfterConnectionMigrations) {
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.latest_rtt());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.smoothed_rtt());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.min_rtt());
- if (GetQuicReloadableFlag(quic_min_rtt_ack_delay)) {
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100),
- rtt_stats_.max_ack_delay());
- }
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100), rtt_stats_.max_ack_delay());
// Reset rtt stats on connection migrations.
rtt_stats_.OnConnectionMigration();
diff --git a/chromium/net/quic/core/congestion_control/send_algorithm_interface.h b/chromium/net/quic/core/congestion_control/send_algorithm_interface.h
index 3b68b9e59fd..df25ba17523 100644
--- a/chromium/net/quic/core/congestion_control/send_algorithm_interface.h
+++ b/chromium/net/quic/core/congestion_control/send_algorithm_interface.h
@@ -49,6 +49,10 @@ class QUIC_EXPORT_PRIVATE SendAlgorithmInterface {
// particularly for congestion avoidance. Can be set any time.
virtual void SetNumEmulatedConnections(int num_connections) = 0;
+ // Sets the initial congestion window in number of packets. May be ignored
+ // if called after the initial congestion window is no longer relevant.
+ virtual void SetInitialCongestionWindowInPackets(QuicPacketCount packets) = 0;
+
// Indicates an update to the congestion state, caused either by an incoming
// ack or loss event timeout. |rtt_updated| indicates whether a new
// latest_rtt sample has been taken, |prior_in_flight| the bytes in flight
diff --git a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
index f3e77cfccbb..55cda43d009 100644
--- a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
+++ b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
@@ -62,30 +62,32 @@ TcpCubicSenderBytes::~TcpCubicSenderBytes() {}
void TcpCubicSenderBytes::SetFromConfig(const QuicConfig& config,
Perspective perspective) {
if (perspective == Perspective::IS_SERVER) {
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kIW03)) {
- // Initial window experiment.
- SetCongestionWindowInPackets(3);
- }
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kIW10)) {
- // Initial window experiment.
- SetCongestionWindowInPackets(10);
- }
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kIW20)) {
- // Initial window experiment.
- SetCongestionWindowInPackets(20);
- }
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kIW50)) {
- // Initial window experiment.
- SetCongestionWindowInPackets(50);
- }
- if (config.HasReceivedConnectionOptions() &&
- ContainsQuicTag(config.ReceivedConnectionOptions(), kMIN1)) {
- // Min CWND experiment.
- SetMinCongestionWindowInPackets(1);
+ if (!GetQuicReloadableFlag(quic_unified_iw_options)) {
+ if (config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kIW03)) {
+ // Initial window experiment.
+ SetInitialCongestionWindowInPackets(3);
+ }
+ if (config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kIW10)) {
+ // Initial window experiment.
+ SetInitialCongestionWindowInPackets(10);
+ }
+ if (config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kIW20)) {
+ // Initial window experiment.
+ SetInitialCongestionWindowInPackets(20);
+ }
+ if (config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kIW50)) {
+ // Initial window experiment.
+ SetInitialCongestionWindowInPackets(50);
+ }
+ if (config.HasReceivedConnectionOptions() &&
+ ContainsQuicTag(config.ReceivedConnectionOptions(), kMIN1)) {
+ // Min CWND experiment.
+ SetMinCongestionWindowInPackets(1);
+ }
}
if (config.HasReceivedConnectionOptions() &&
ContainsQuicTag(config.ReceivedConnectionOptions(), kMIN4)) {
@@ -272,7 +274,7 @@ void TcpCubicSenderBytes::SetCongestionWindowFromBandwidthAndRtt(
kMaxResumptionCongestionWindow * kDefaultTCPMSS));
}
-void TcpCubicSenderBytes::SetCongestionWindowInPackets(
+void TcpCubicSenderBytes::SetInitialCongestionWindowInPackets(
QuicPacketCount congestion_window) {
congestion_window_ = congestion_window * kDefaultTCPMSS;
}
@@ -321,7 +323,7 @@ void TcpCubicSenderBytes::OnPacketLost(QuicPacketNumber packet_number,
prr_.OnPacketLost(prior_in_flight);
}
- // TODO(jri): Separate out all of slow start into a separate class.
+ // TODO(b/77268641): Separate out all of slow start into a separate class.
if (slow_start_large_reduction_ && InSlowStart()) {
DCHECK_LT(kDefaultTCPMSS, congestion_window_);
if (congestion_window_ >= 2 * initial_tcp_congestion_window_) {
diff --git a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.h b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.h
index fde4fbf835f..70071aeba2e 100644
--- a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.h
+++ b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes.h
@@ -48,6 +48,8 @@ class QUIC_EXPORT_PRIVATE TcpCubicSenderBytes : public SendAlgorithmInterface {
void AdjustNetworkParameters(QuicBandwidth bandwidth,
QuicTime::Delta rtt) override;
void SetNumEmulatedConnections(int num_connections) override;
+ void SetInitialCongestionWindowInPackets(
+ QuicPacketCount congestion_window) override;
void OnConnectionMigration() override;
void OnCongestionEvent(bool rtt_updated,
QuicByteCount prior_in_flight,
@@ -88,7 +90,6 @@ class QUIC_EXPORT_PRIVATE TcpCubicSenderBytes : public SendAlgorithmInterface {
QuicTime event_time);
void SetCongestionWindowFromBandwidthAndRtt(QuicBandwidth bandwidth,
QuicTime::Delta rtt);
- void SetCongestionWindowInPackets(QuicPacketCount congestion_window);
void SetMinCongestionWindowInPackets(QuicPacketCount congestion_window);
void ExitSlowstart();
void OnPacketLost(QuicPacketNumber largest_loss,
diff --git a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
index 187a06036bb..d87be503cd6 100644
--- a/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
+++ b/chromium/net/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
@@ -544,6 +544,7 @@ TEST_F(TcpCubicSenderBytesTest, MultipleLossesInOneWindow) {
}
TEST_F(TcpCubicSenderBytesTest, ConfigureMaxInitialWindow) {
+ SetQuicReloadableFlag(quic_unified_iw_options, false);
QuicConfig config;
// Verify that kCOPT: kIW10 forces the congestion window to the default of 10.
@@ -554,6 +555,12 @@ TEST_F(TcpCubicSenderBytesTest, ConfigureMaxInitialWindow) {
EXPECT_EQ(10u * kDefaultTCPMSS, sender_->GetCongestionWindow());
}
+TEST_F(TcpCubicSenderBytesTest, SetInitialCongestionWindow) {
+ EXPECT_NE(3u * kDefaultTCPMSS, sender_->GetCongestionWindow());
+ sender_->SetInitialCongestionWindowInPackets(3);
+ EXPECT_EQ(3u * kDefaultTCPMSS, sender_->GetCongestionWindow());
+}
+
TEST_F(TcpCubicSenderBytesTest, 2ConnectionCongestionAvoidanceAtEndOfRecovery) {
sender_->SetNumEmulatedConnections(2);
// Ack 10 packets in 5 acks to raise the CWND to 20.
diff --git a/chromium/net/quic/core/crypto/cert_compressor.cc b/chromium/net/quic/core/crypto/cert_compressor.cc
index a8cefbcc9b4..a2670935e5e 100644
--- a/chromium/net/quic/core/crypto/cert_compressor.cc
+++ b/chromium/net/quic/core/crypto/cert_compressor.cc
@@ -12,6 +12,8 @@
#include "net/quic/platform/api/quic_string.h"
#include "third_party/zlib/zlib.h"
+using std::string;
+
namespace net {
namespace {
@@ -401,7 +403,7 @@ bool ParseEntries(QuicStringPiece* in_out,
if (cert.empty()) {
return false;
}
- out_certs->push_back(cert.as_string());
+ out_certs->push_back(string(cert));
break;
}
default:
@@ -627,7 +629,7 @@ bool CertCompressor::DecompressChain(
if (uncompressed.size() < cert_len) {
return false;
}
- (*out_certs)[i] = uncompressed.substr(0, cert_len).as_string();
+ (*out_certs)[i] = string(uncompressed.substr(0, cert_len));
uncompressed.remove_prefix(cert_len);
break;
case CertEntry::CACHED:
diff --git a/chromium/net/quic/core/crypto/common_cert_set.cc b/chromium/net/quic/core/crypto/common_cert_set.cc
index 83c3e976706..8d4c2ad35a7 100644
--- a/chromium/net/quic/core/crypto/common_cert_set.cc
+++ b/chromium/net/quic/core/crypto/common_cert_set.cc
@@ -10,6 +10,7 @@
#include "base/memory/singleton.h"
#include "net/quic/core/quic_utils.h"
#include "net/quic/platform/api/quic_arraysize.h"
+#include "net/quic/platform/api/quic_singleton.h"
namespace net {
@@ -143,14 +144,14 @@ class CommonCertSetsQUIC : public CommonCertSets {
}
static CommonCertSetsQUIC* GetInstance() {
- return base::Singleton<CommonCertSetsQUIC>::get();
+ return QuicSingleton<CommonCertSetsQUIC>::get();
}
private:
CommonCertSetsQUIC() {}
~CommonCertSetsQUIC() override {}
- friend struct base::DefaultSingletonTraits<CommonCertSetsQUIC>;
+ friend QuicSingletonFriend<CommonCertSetsQUIC>;
DISALLOW_COPY_AND_ASSIGN(CommonCertSetsQUIC);
};
diff --git a/chromium/net/quic/core/crypto/crypto_framer.cc b/chromium/net/quic/core/crypto/crypto_framer.cc
index 16c6e528d50..74ccacba2cc 100644
--- a/chromium/net/quic/core/crypto/crypto_framer.cc
+++ b/chromium/net/quic/core/crypto/crypto_framer.cc
@@ -9,11 +9,14 @@
#include "net/quic/core/quic_data_writer.h"
#include "net/quic/core/quic_packets.h"
#include "net/quic/platform/api/quic_fallthrough.h"
+#include "net/quic/platform/api/quic_logging.h"
#include "net/quic/platform/api/quic_ptr_util.h"
#include "net/quic/platform/api/quic_str_cat.h"
#include "net/quic/platform/api/quic_string.h"
#include "net/quic/platform/api/quic_string_piece.h"
+using std::string;
+
namespace net {
namespace {
@@ -45,7 +48,11 @@ class OneShotVisitor : public CryptoFramerVisitorInterface {
} // namespace
CryptoFramer::CryptoFramer()
- : visitor_(nullptr), error_detail_(""), num_entries_(0), values_len_(0) {
+ : visitor_(nullptr),
+ error_detail_(""),
+ num_entries_(0),
+ values_len_(0),
+ process_truncated_messages_(false) {
Clear();
}
@@ -302,11 +309,20 @@ QuicErrorCode CryptoFramer::Process(QuicStringPiece input,
}
case STATE_READING_VALUES:
if (reader.BytesRemaining() < values_len_) {
- break;
+ if (!process_truncated_messages_) {
+ break;
+ }
+ QUIC_LOG(ERROR) << "Trunacted message. Missing "
+ << values_len_ - reader.BytesRemaining() << " bytes.";
}
for (const std::pair<QuicTag, size_t>& item : tags_and_lengths_) {
QuicStringPiece value;
- reader.ReadStringPiece(&value, item.second);
+ if (!reader.ReadStringPiece(&value, item.second)) {
+ DCHECK(process_truncated_messages_);
+ // Store an empty value.
+ message_.SetStringPiece(item.first, "");
+ continue;
+ }
message_.SetStringPiece(item.first, value);
}
visitor_->OnHandshakeMessage(message_);
@@ -315,7 +331,7 @@ QuicErrorCode CryptoFramer::Process(QuicStringPiece input,
break;
}
// Save any remaining data.
- buffer_ = reader.PeekRemainingPayload().as_string();
+ buffer_ = string(reader.PeekRemainingPayload());
return QUIC_NO_ERROR;
}
diff --git a/chromium/net/quic/core/crypto/crypto_framer.h b/chromium/net/quic/core/crypto/crypto_framer.h
index a3c3d091494..c4bca2bb8d5 100644
--- a/chromium/net/quic/core/crypto/crypto_framer.h
+++ b/chromium/net/quic/core/crypto/crypto_framer.h
@@ -84,6 +84,11 @@ class QUIC_EXPORT_PRIVATE CryptoFramer : public CryptoMessageParser {
const CryptoHandshakeMessage& message,
Perspective perspective);
+ // Debug only method which permits processing truncated messages.
+ void set_process_truncated_messages(bool process_truncated_messages) {
+ process_truncated_messages_ = process_truncated_messages;
+ }
+
private:
// Clears per-message state. Does not clear the visitor.
void Clear();
@@ -123,6 +128,8 @@ class QUIC_EXPORT_PRIVATE CryptoFramer : public CryptoMessageParser {
std::vector<std::pair<QuicTag, size_t>> tags_and_lengths_;
// Cumulative length of all values in the message currently being parsed.
size_t values_len_;
+ // Set to true to allow of processing of truncated messages for debugging.
+ bool process_truncated_messages_;
};
} // namespace net
diff --git a/chromium/net/quic/core/crypto/crypto_handshake_message.cc b/chromium/net/quic/core/crypto/crypto_handshake_message.cc
index f29bb5863a0..3c9b2a678d5 100644
--- a/chromium/net/quic/core/crypto/crypto_handshake_message.cc
+++ b/chromium/net/quic/core/crypto/crypto_handshake_message.cc
@@ -17,6 +17,7 @@
#include "net/quic/platform/api/quic_string.h"
#include "net/quic/platform/api/quic_text_utils.h"
+using std::string;
namespace net {
@@ -89,7 +90,7 @@ void CryptoHandshakeMessage::SetVersion(QuicTag tag,
void CryptoHandshakeMessage::SetStringPiece(QuicTag tag,
QuicStringPiece value) {
- tag_value_map_[tag] = value.as_string();
+ tag_value_map_[tag] = string(value);
}
void CryptoHandshakeMessage::Erase(QuicTag tag) {
@@ -212,8 +213,8 @@ QuicErrorCode CryptoHandshakeMessage::GetUint64(QuicTag tag,
}
QuicErrorCode CryptoHandshakeMessage::GetUint128(QuicTag tag,
- uint128* out) const {
- return GetPOD(tag, out, sizeof(uint128));
+ QuicUint128* out) const {
+ return GetPOD(tag, out, sizeof(QuicUint128));
}
size_t CryptoHandshakeMessage::size() const {
diff --git a/chromium/net/quic/core/crypto/crypto_handshake_message.h b/chromium/net/quic/core/crypto/crypto_handshake_message.h
index abdfe4c5651..772c0365f81 100644
--- a/chromium/net/quic/core/crypto/crypto_handshake_message.h
+++ b/chromium/net/quic/core/crypto/crypto_handshake_message.h
@@ -10,11 +10,11 @@
#include <memory>
#include <vector>
-#include "net/base/int128.h"
#include "net/quic/core/quic_packets.h"
#include "net/quic/platform/api/quic_export.h"
#include "net/quic/platform/api/quic_string.h"
#include "net/quic/platform/api/quic_string_piece.h"
+#include "net/quic/platform/api/quic_uint128.h"
namespace net {
@@ -107,7 +107,7 @@ class QUIC_EXPORT_PRIVATE CryptoHandshakeMessage {
QuicStringPiece* out) const;
QuicErrorCode GetUint32(QuicTag tag, uint32_t* out) const;
QuicErrorCode GetUint64(QuicTag tag, uint64_t* out) const;
- QuicErrorCode GetUint128(QuicTag tag, uint128* out) const;
+ QuicErrorCode GetUint128(QuicTag tag, QuicUint128* out) const;
// size returns 4 (message tag) + 2 (uint16_t, number of entries) +
// (4 (tag) + 4 (end offset))*tag_value_map_.size() + ∑ value sizes.
diff --git a/chromium/net/quic/core/crypto/crypto_server_test.cc b/chromium/net/quic/core/crypto/crypto_server_test.cc
index c7a9a336d75..8012d752fc7 100644
--- a/chromium/net/quic/core/crypto/crypto_server_test.cc
+++ b/chromium/net/quic/core/crypto/crypto_server_test.cc
@@ -35,6 +35,8 @@
#include "net/quic/test_tools/quic_test_utils.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
+using std::string;
+
namespace net {
namespace test {
@@ -848,8 +850,8 @@ TEST_P(CryptoServerTest, ProofForSuppliedServerConfig) {
CryptoUtils::HashHandshakeMessage(msg, &chlo_hash, Perspective::IS_SERVER);
EXPECT_EQ(QUIC_SUCCESS,
proof_verifier->VerifyProof(
- "test.example.com", 443, scfg_str.as_string(), client_version_,
- chlo_hash, certs, "", proof.as_string(), verify_context.get(),
+ "test.example.com", 443, (string(scfg_str)), client_version_,
+ chlo_hash, certs, "", (string(proof)), verify_context.get(),
&error_details, &details, std::move(callback)));
}
@@ -1061,7 +1063,7 @@ TEST_F(CryptoServerConfigGenerationTest, SCIDIsHashOfServerConfig) {
QuicStringPiece scid;
EXPECT_TRUE(scfg->GetStringPiece(kSCID, &scid));
// Need to take a copy of |scid| has we're about to call |Erase|.
- const QuicString scid_str(scid.as_string());
+ const QuicString scid_str(scid);
scfg->Erase(kSCID);
scfg->MarkDirty();
diff --git a/chromium/net/quic/core/crypto/crypto_utils.cc b/chromium/net/quic/core/crypto/crypto_utils.cc
index fd8fe1f9224..ccd1fd71b43 100644
--- a/chromium/net/quic/core/crypto/crypto_utils.cc
+++ b/chromium/net/quic/core/crypto/crypto_utils.cc
@@ -7,6 +7,8 @@
#include <memory>
#include "crypto/hkdf.h"
+#include "net/quic/core/crypto/aes_128_gcm_decrypter.h"
+#include "net/quic/core/crypto/aes_128_gcm_encrypter.h"
#include "net/quic/core/crypto/crypto_handshake.h"
#include "net/quic/core/crypto/crypto_protocol.h"
#include "net/quic/core/crypto/quic_decrypter.h"
@@ -17,47 +19,118 @@
#include "net/quic/platform/api/quic_arraysize.h"
#include "net/quic/platform/api/quic_bug_tracker.h"
#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
#include "net/quic/platform/api/quic_string.h"
#include "third_party/boringssl/src/include/openssl/bytestring.h"
#include "third_party/boringssl/src/include/openssl/hkdf.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
+using std::string;
namespace net {
// static
-std::vector<uint8_t> CryptoUtils::HkdfExpandLabel(
+std::vector<uint8_t> CryptoUtils::QhkdfExpand(
const EVP_MD* prf,
const std::vector<uint8_t>& secret,
const QuicString& label,
size_t out_len) {
- CBB hkdf_label, inner_label;
- const char label_prefix[] = "tls13 ";
- if (!CBB_init(&hkdf_label, 1) || !CBB_add_u16(&hkdf_label, out_len) ||
- !CBB_add_u8_length_prefixed(&hkdf_label, &inner_label) ||
+ bssl::ScopedCBB quic_hkdf_label;
+ CBB inner_label;
+ const char label_prefix[] = "QUIC ";
+ // The minimum possible length for the QuicHkdfLabel is 10 bytes - 2 bytes for
+ // Length, plus 1 byte for the length of the inner label, plus the length of
+ // that label (which is at least 6), plus 1 byte at the end.
+ if (!CBB_init(quic_hkdf_label.get(), 10) ||
+ !CBB_add_u16(quic_hkdf_label.get(), out_len) ||
+ !CBB_add_u8_length_prefixed(quic_hkdf_label.get(), &inner_label) ||
!CBB_add_bytes(&inner_label,
reinterpret_cast<const uint8_t*>(label_prefix),
QUIC_ARRAYSIZE(label_prefix) - 1) ||
!CBB_add_bytes(&inner_label,
reinterpret_cast<const uint8_t*>(label.data()),
label.size()) ||
- !CBB_add_u8(&hkdf_label, 0) || !CBB_flush(&hkdf_label)) {
+ !CBB_add_u8(quic_hkdf_label.get(), 0) ||
+ !CBB_flush(quic_hkdf_label.get())) {
QUIC_LOG(ERROR) << "Building HKDF label failed";
- CBB_cleanup(&hkdf_label);
- std::vector<uint8_t>();
+ return std::vector<uint8_t>();
}
std::vector<uint8_t> out;
out.resize(out_len);
if (!HKDF_expand(out.data(), out_len, prf, secret.data(), secret.size(),
- CBB_data(&hkdf_label), CBB_len(&hkdf_label))) {
+ CBB_data(quic_hkdf_label.get()),
+ CBB_len(quic_hkdf_label.get()))) {
QUIC_LOG(ERROR) << "Running HKDF-Expand-Label failed";
- CBB_cleanup(&hkdf_label);
- std::vector<uint8_t>();
+ return std::vector<uint8_t>();
}
- CBB_cleanup(&hkdf_label);
return out;
}
+template <class QuicCrypter>
+void CryptoUtils::SetKeyAndIV(const EVP_MD* prf,
+ const std::vector<uint8_t>& pp_secret,
+ QuicCrypter* crypter) {
+ std::vector<uint8_t> key =
+ CryptoUtils::QhkdfExpand(prf, pp_secret, "key", crypter->GetKeySize());
+ std::vector<uint8_t> iv =
+ CryptoUtils::QhkdfExpand(prf, pp_secret, "iv", crypter->GetIVSize());
+ crypter->SetKey(
+ QuicStringPiece(reinterpret_cast<char*>(key.data()), key.size()));
+ crypter->SetIV(
+ QuicStringPiece(reinterpret_cast<char*>(iv.data()), iv.size()));
+}
+
+namespace {
+
+const uint8_t kQuicVersion1Salt[] = {0xaf, 0xc8, 0x24, 0xec, 0x5f, 0xc7, 0x7e,
+ 0xca, 0x1e, 0x9d, 0x36, 0xf3, 0x7f, 0xb2,
+ 0xd4, 0x65, 0x18, 0xc3, 0x66, 0x39};
+
+} // namespace
+
+// static
+void CryptoUtils::CreateTlsInitialCrypters(Perspective perspective,
+ QuicConnectionId connection_id,
+ CrypterPair* crypters) {
+ const EVP_MD* hash = EVP_sha256();
+
+ uint8_t connection_id_bytes[sizeof(connection_id)];
+ for (size_t i = 0; i < sizeof(connection_id); ++i) {
+ connection_id_bytes[i] =
+ (connection_id >> ((sizeof(connection_id) - i - 1) * 8)) & 0xff;
+ }
+
+ std::vector<uint8_t> handshake_secret;
+ handshake_secret.resize(EVP_MAX_MD_SIZE);
+ size_t handshake_secret_len;
+ if (!HKDF_extract(handshake_secret.data(), &handshake_secret_len, hash,
+ connection_id_bytes, arraysize(connection_id_bytes),
+ kQuicVersion1Salt, arraysize(kQuicVersion1Salt))) {
+ QUIC_BUG << "HKDF_extract failed when creating initial crypters";
+ }
+ handshake_secret.resize(handshake_secret_len);
+
+ const string client_label = "client hs";
+ const string server_label = "server hs";
+ string encryption_label, decryption_label;
+ if (perspective == Perspective::IS_CLIENT) {
+ encryption_label = client_label;
+ decryption_label = server_label;
+ } else {
+ encryption_label = server_label;
+ decryption_label = client_label;
+ }
+ crypters->encrypter = QuicMakeUnique<Aes128GcmEncrypter>();
+ std::vector<uint8_t> encryption_secret =
+ QhkdfExpand(hash, handshake_secret, encryption_label, EVP_MD_size(hash));
+ SetKeyAndIV(hash, encryption_secret, crypters->encrypter.get());
+
+ crypters->decrypter = QuicMakeUnique<Aes128GcmDecrypter>();
+ std::vector<uint8_t> decryption_secret =
+ QhkdfExpand(hash, handshake_secret, decryption_label, EVP_MD_size(hash));
+ SetKeyAndIV(hash, decryption_secret, crypters->decrypter.get());
+}
+
// static
void CryptoUtils::GenerateNonce(QuicWallTime now,
QuicRandom* random_generator,
@@ -105,7 +178,7 @@ bool CryptoUtils::DeriveKeys(QuicStringPiece premaster_secret,
QuicStringPiece nonce = client_nonce;
QuicString nonce_storage;
if (!server_nonce.empty()) {
- nonce_storage = client_nonce.as_string() + server_nonce.as_string();
+ nonce_storage = string(client_nonce) + string(server_nonce);
nonce = nonce_storage;
}
@@ -197,7 +270,7 @@ bool CryptoUtils::ExportKeyingMaterial(QuicStringPiece subkey_secret,
return false;
}
uint32_t context_length = static_cast<uint32_t>(context.length());
- QuicString info = label.as_string();
+ QuicString info = string(label);
info.push_back('\0');
info.append(reinterpret_cast<char*>(&context_length), sizeof(context_length));
info.append(context.data(), context.length());
diff --git a/chromium/net/quic/core/crypto/crypto_utils.h b/chromium/net/quic/core/crypto/crypto_utils.h
index fc9545a24df..ab8f492aa72 100644
--- a/chromium/net/quic/core/crypto/crypto_utils.h
+++ b/chromium/net/quic/core/crypto/crypto_utils.h
@@ -69,21 +69,37 @@ class QUIC_EXPORT_PRIVATE CryptoUtils {
DiversificationNonce* nonce_;
};
- // Implements the HKDF-Expand-Label function as defined in section 7.1 of TLS
- // 1.3. The HKDF-Expand-Label definition assumes that the TLS connection's PRF
- // will be used as the Hash function for HKDF; in this function it is
- // explicitly passed in as |prf|. The inputs to HKDF-Expand-Label are as
- // follows:
+ // Implements the QHKDF-Expand function defined in section 5.2.3 of
+ // draft-ietf-quic-tls-09. The QHKDF-Expand function takes 3 explicit
+ // arguments, as well as an implicit PRF which is the hash function negotiated
+ // by TLS. This PRF is passed in as |prf|; the explicit arguments to
+ // QHKDF-Expand - Secret, Label, and Length - are passed in as |secret|,
+ // |label|, and |out_len|, respectively.
+ static std::vector<uint8_t> QhkdfExpand(const EVP_MD* prf,
+ const std::vector<uint8_t>& secret,
+ const std::string& label,
+ size_t out_len);
+
+ // SetKeyAndIV derives the key and IV from the given packet protection secret
+ // |pp_secret| and sets those fields on the given QuicEncrypter or
+ // QuicDecrypter |*crypter|. This follows the derivation described in section
+ // 5.2.4 of draft-ietf-quic-tls-09.
+ template <class QuicCrypter>
+ static void SetKeyAndIV(const EVP_MD* prf,
+ const std::vector<uint8_t>& pp_secret,
+ QuicCrypter* crypter);
+
+ // QUIC encrypts TLS handshake messages with a version-specific key (to
+ // prevent network observers that are not aware of that QUIC version from
+ // making decisions based on the TLS handshake). This packet protection secret
+ // is derived from the connection ID in the client's Initial packet.
//
- // Secret: |secret|
- // Label: |label|
- // Context: zero-length context
- // Length: |out_len|
- static std::vector<uint8_t> HkdfExpandLabel(
- const EVP_MD* prf,
- const std::vector<uint8_t>& secret,
- const QuicString& label,
- size_t out_len);
+ // This function takes that |connection_id| and creates the encrypter and
+ // decrypter (put in |*crypters|) to use for this packet protection, as well
+ // as setting the key and IV on those crypters.
+ static void CreateTlsInitialCrypters(Perspective perspective,
+ QuicConnectionId connection_id,
+ CrypterPair* crypters);
// Generates the connection nonce. The nonce is formed as:
// <4 bytes> current time
diff --git a/chromium/net/quic/core/crypto/crypto_utils_test.cc b/chromium/net/quic/core/crypto/crypto_utils_test.cc
index 58ff13b2c94..dfecd9195bd 100644
--- a/chromium/net/quic/core/crypto/crypto_utils_test.cc
+++ b/chromium/net/quic/core/crypto/crypto_utils_test.cc
@@ -18,21 +18,19 @@ namespace {
class CryptoUtilsTest : public QuicTest {};
-TEST_F(CryptoUtilsTest, TestHkdfExpandLabel) {
- // This test vector is from
- // https://github.com/quicwg/base-drafts/wiki/Test-Vector-for-the-Clear-Text-AEAD-key-derivation
+TEST_F(CryptoUtilsTest, TestQhkdfExpand) {
const std::vector<uint8_t> secret = {
0x8f, 0x01, 0x00, 0x67, 0x9c, 0x96, 0x5a, 0xc5, 0x9f, 0x28, 0x3a,
0x02, 0x52, 0x2a, 0x6e, 0x43, 0xcf, 0xae, 0xf6, 0x3c, 0x45, 0x48,
0xb0, 0xa6, 0x8f, 0x91, 0x91, 0x40, 0xee, 0x7d, 0x9a, 0x48};
- const QuicString label = "QUIC client cleartext Secret";
+ const QuicString label = "client hs";
std::vector<uint8_t> out =
- CryptoUtils::HkdfExpandLabel(EVP_sha256(), secret, label, 32);
+ CryptoUtils::QhkdfExpand(EVP_sha256(), secret, label, 32);
std::vector<uint8_t> expected_out = {
- 0x31, 0xba, 0x96, 0x68, 0x73, 0xf7, 0xf4, 0x53, 0xe6, 0xc8, 0xa1,
- 0xbf, 0x78, 0xed, 0x70, 0x13, 0xfa, 0xd8, 0x3f, 0xfc, 0xee, 0xfc,
- 0x95, 0x68, 0x81, 0xcd, 0x24, 0x1c, 0x0a, 0xe3, 0xa7, 0xa6};
+ 0x8e, 0x28, 0x6a, 0x27, 0x38, 0xe6, 0x66, 0x50, 0xb4, 0xf8, 0x8f,
+ 0xac, 0x5d, 0xc5, 0xd0, 0xef, 0x7d, 0x36, 0x9b, 0x07, 0xd4, 0x74,
+ 0x42, 0x99, 0x1a, 0x00, 0x0c, 0x55, 0xac, 0xc4, 0x0c, 0xf4};
EXPECT_EQ(out, expected_out);
}
diff --git a/chromium/net/quic/core/crypto/null_decrypter.cc b/chromium/net/quic/core/crypto/null_decrypter.cc
index 8d76dfb7b0b..38f3fbb3c2f 100644
--- a/chromium/net/quic/core/crypto/null_decrypter.cc
+++ b/chromium/net/quic/core/crypto/null_decrypter.cc
@@ -6,10 +6,10 @@
#include <cstdint>
-#include "net/base/int128.h"
#include "net/quic/core/quic_data_reader.h"
#include "net/quic/core/quic_utils.h"
#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_uint128.h"
using std::string;
@@ -49,7 +49,7 @@ bool NullDecrypter::DecryptPacket(QuicTransportVersion version,
size_t max_output_length) {
QuicDataReader reader(ciphertext.data(), ciphertext.length(),
HOST_BYTE_ORDER);
- uint128 hash;
+ QuicUint128 hash;
if (!ReadHash(&reader, &hash)) {
return false;
@@ -89,20 +89,20 @@ uint32_t NullDecrypter::cipher_id() const {
return 0;
}
-bool NullDecrypter::ReadHash(QuicDataReader* reader, uint128* hash) {
+bool NullDecrypter::ReadHash(QuicDataReader* reader, QuicUint128* hash) {
uint64_t lo;
uint32_t hi;
if (!reader->ReadUInt64(&lo) || !reader->ReadUInt32(&hi)) {
return false;
}
- *hash = MakeUint128(hi, lo);
+ *hash = MakeQuicUint128(hi, lo);
return true;
}
-uint128 NullDecrypter::ComputeHash(QuicTransportVersion version,
- const QuicStringPiece data1,
- const QuicStringPiece data2) const {
- uint128 correct_hash;
+QuicUint128 NullDecrypter::ComputeHash(QuicTransportVersion version,
+ const QuicStringPiece data1,
+ const QuicStringPiece data2) const {
+ QuicUint128 correct_hash;
if (version > QUIC_VERSION_35) {
if (perspective_ == Perspective::IS_CLIENT) {
// Peer is a server.
@@ -115,7 +115,7 @@ uint128 NullDecrypter::ComputeHash(QuicTransportVersion version,
} else {
correct_hash = QuicUtils::FNV1a_128_Hash_Two(data1, data2);
}
- uint128 mask = MakeUint128(UINT64_C(0x0), UINT64_C(0xffffffff));
+ QuicUint128 mask = MakeQuicUint128(UINT64_C(0x0), UINT64_C(0xffffffff));
mask <<= 96;
correct_hash &= ~mask;
return correct_hash;
diff --git a/chromium/net/quic/core/crypto/null_decrypter.h b/chromium/net/quic/core/crypto/null_decrypter.h
index 0ca74fe8cc0..67743dc429c 100644
--- a/chromium/net/quic/core/crypto/null_decrypter.h
+++ b/chromium/net/quic/core/crypto/null_decrypter.h
@@ -8,13 +8,12 @@
#include <cstddef>
#include <cstdint>
-#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "net/base/int128.h"
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/quic_types.h"
#include "net/quic/platform/api/quic_export.h"
#include "net/quic/platform/api/quic_string_piece.h"
+#include "net/quic/platform/api/quic_uint128.h"
namespace net {
@@ -49,10 +48,10 @@ class QUIC_EXPORT_PRIVATE NullDecrypter : public QuicDecrypter {
uint32_t cipher_id() const override;
private:
- bool ReadHash(QuicDataReader* reader, uint128* hash);
- uint128 ComputeHash(QuicTransportVersion version,
- QuicStringPiece data1,
- QuicStringPiece data2) const;
+ bool ReadHash(QuicDataReader* reader, QuicUint128* hash);
+ QuicUint128 ComputeHash(QuicTransportVersion version,
+ QuicStringPiece data1,
+ QuicStringPiece data2) const;
Perspective perspective_;
diff --git a/chromium/net/quic/core/crypto/null_encrypter.cc b/chromium/net/quic/core/crypto/null_encrypter.cc
index 999d717c85b..4ea40c13328 100644
--- a/chromium/net/quic/core/crypto/null_encrypter.cc
+++ b/chromium/net/quic/core/crypto/null_encrypter.cc
@@ -39,7 +39,7 @@ bool NullEncrypter::EncryptPacket(QuicTransportVersion version,
if (max_output_length < len) {
return false;
}
- uint128 hash;
+ QuicUint128 hash;
if (version > QUIC_VERSION_35) {
if (perspective_ == Perspective::IS_SERVER) {
hash =
diff --git a/chromium/net/quic/core/crypto/quic_crypto_client_config.cc b/chromium/net/quic/core/crypto/quic_crypto_client_config.cc
index 6d64c19b43d..1ce64244329 100644
--- a/chromium/net/quic/core/crypto/quic_crypto_client_config.cc
+++ b/chromium/net/quic/core/crypto/quic_crypto_client_config.cc
@@ -32,6 +32,7 @@
#include "net/quic/platform/api/quic_text_utils.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
+using std::string;
namespace net {
@@ -184,7 +185,7 @@ QuicCryptoClientConfig::CachedState::SetServerConfig(
}
if (!matches_existing) {
- server_config_ = server_config.as_string();
+ server_config_ = string(server_config);
SetProofInvalid();
scfg_ = std::move(new_scfg_storage);
}
@@ -224,9 +225,9 @@ void QuicCryptoClientConfig::CachedState::SetProof(
// If the proof has changed then it needs to be revalidated.
SetProofInvalid();
certs_ = certs;
- cert_sct_ = cert_sct.as_string();
- chlo_hash_ = chlo_hash.as_string();
- server_config_sig_ = signature.as_string();
+ cert_sct_ = string(cert_sct);
+ chlo_hash_ = string(chlo_hash);
+ server_config_sig_ = string(signature);
}
void QuicCryptoClientConfig::CachedState::Clear() {
@@ -337,12 +338,12 @@ QuicCryptoClientConfig::CachedState::proof_verify_details() const {
void QuicCryptoClientConfig::CachedState::set_source_address_token(
QuicStringPiece token) {
- source_address_token_ = token.as_string();
+ source_address_token_ = string(token);
}
void QuicCryptoClientConfig::CachedState::set_cert_sct(
QuicStringPiece cert_sct) {
- cert_sct_ = cert_sct.as_string();
+ cert_sct_ = string(cert_sct);
}
void QuicCryptoClientConfig::CachedState::SetProofVerifyDetails(
@@ -818,7 +819,7 @@ QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
QuicStringPiece nonce;
if (rej.GetStringPiece(kServerNonceTag, &nonce)) {
- out_params->server_nonce = nonce.as_string();
+ out_params->server_nonce = string(nonce);
}
if (rej.tag() == kSREJ) {
@@ -830,7 +831,7 @@ QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
connection_id = QuicEndian::NetToHost64(connection_id);
cached->add_server_designated_connection_id(connection_id);
if (!nonce.empty()) {
- cached->add_server_nonce(nonce.as_string());
+ cached->add_server_nonce(string(nonce));
}
return QUIC_NO_ERROR;
}
diff --git a/chromium/net/quic/core/crypto/quic_crypto_server_config.cc b/chromium/net/quic/core/crypto/quic_crypto_server_config.cc
index 9e677ac8094..a376ea9fae6 100644
--- a/chromium/net/quic/core/crypto/quic_crypto_server_config.cc
+++ b/chromium/net/quic/core/crypto/quic_crypto_server_config.cc
@@ -45,6 +45,7 @@
#include "third_party/boringssl/src/include/openssl/sha.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
+using std::string;
namespace net {
@@ -64,7 +65,7 @@ QuicString DeriveSourceAddressTokenKey(
source_address_token_secret, QuicStringPiece() /* no salt */,
"QUIC source address token key", CryptoSecretBoxer::GetKeySize(),
0 /* no fixed IV needed */, 0 /* no subkey secret */);
- return hkdf.server_write_key().as_string();
+ return string(hkdf.server_write_key());
}
} // namespace
@@ -707,7 +708,7 @@ void QuicCryptoServerConfig::ProcessClientHello(
compressed_certs_cache, params, signed_config,
total_framing_overhead, chlo_packet_size, requested_config,
primary_config, std::move(done_cb)));
- proof_source_->GetProof(server_address, info.sni.as_string(),
+ proof_source_->GetProof(server_address, string(info.sni),
primary_config->serialized, version, chlo_hash,
std::move(cb));
helper.DetachCallback();
@@ -918,7 +919,7 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
return;
}
- params->channel_id = key.as_string();
+ params->channel_id = string(key);
}
}
@@ -952,7 +953,7 @@ void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
std::unique_ptr<KeyExchange> forward_secure_key_exchange(
key_exchange->NewKeyPair(rand));
forward_secure_public_value =
- forward_secure_key_exchange->public_value().as_string();
+ string(forward_secure_key_exchange->public_value());
if (!forward_secure_key_exchange->CalculateSharedKey(
public_value, &params->forward_secure_premaster_secret)) {
helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
@@ -1004,7 +1005,7 @@ QuicCryptoServerConfig::GetConfigWithScid(
configs_lock_.AssertReaderHeld();
if (!requested_scid.empty()) {
- ConfigMap::const_iterator it = configs_.find(requested_scid.as_string());
+ ConfigMap::const_iterator it = configs_.find((string(requested_scid)));
if (it != configs_.end()) {
// We'll use the config that the client requested in order to do
// key-agreement.
@@ -1262,7 +1263,7 @@ void QuicCryptoServerConfig::EvaluateClientHello(
*this, found_error, server_address.host(), version,
requested_config, primary_config, signed_config, client_hello_state,
std::move(done_cb)));
- proof_source_->GetProof(server_address, info->sni.as_string(),
+ proof_source_->GetProof(server_address, string(info->sni),
serialized_config, version, chlo_hash,
std::move(cb));
helper.DetachCallback();
@@ -1490,12 +1491,12 @@ void QuicCryptoServerConfig::BuildRejection(
QuicStringPiece client_common_set_hashes;
if (client_hello.GetStringPiece(kCCS, &client_common_set_hashes)) {
- params->client_common_set_hashes = client_common_set_hashes.as_string();
+ params->client_common_set_hashes = string(client_common_set_hashes);
}
QuicStringPiece client_cached_cert_hashes;
if (client_hello.GetStringPiece(kCCRT, &client_cached_cert_hashes)) {
- params->client_cached_cert_hashes = client_cached_cert_hashes.as_string();
+ params->client_cached_cert_hashes = string(client_cached_cert_hashes);
} else {
params->client_cached_cert_hashes.clear();
}
@@ -1597,7 +1598,7 @@ QuicCryptoServerConfig::ParseConfigProtobuf(
QUIC_LOG(WARNING) << "Server config message is missing SCID";
return nullptr;
}
- config->id = scid.as_string();
+ config->id = string(scid);
if (msg->GetTaglist(kAEAD, &config->aead) != QUIC_NO_ERROR) {
QUIC_LOG(WARNING) << "Server config message is missing AEAD";
diff --git a/chromium/net/quic/core/crypto/quic_crypto_server_config_test.cc b/chromium/net/quic/core/crypto/quic_crypto_server_config_test.cc
index 94350e48099..00d5e9816e5 100644
--- a/chromium/net/quic/core/crypto/quic_crypto_server_config_test.cc
+++ b/chromium/net/quic/core/crypto/quic_crypto_server_config_test.cc
@@ -23,6 +23,7 @@
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/quic_crypto_server_config_peer.h"
+using std::string;
namespace net {
namespace test {
@@ -132,7 +133,7 @@ TEST_F(QuicCryptoServerConfigTest, CompressDifferentCerts) {
QuicStringPiece different_common_certs(
reinterpret_cast<const char*>(&set_hash), sizeof(set_hash));
QuicString compressed3 = QuicCryptoServerConfigPeer::CompressChain(
- &compressed_certs_cache, chain, different_common_certs.as_string(),
+ &compressed_certs_cache, chain, string(different_common_certs),
cached_certs, common_sets.get());
EXPECT_EQ(compressed_certs_cache.Size(), 3u);
}
diff --git a/chromium/net/quic/core/crypto/quic_decrypter.cc b/chromium/net/quic/core/crypto/quic_decrypter.cc
index 73d2f2f59a3..83f97ccc07b 100644
--- a/chromium/net/quic/core/crypto/quic_decrypter.cc
+++ b/chromium/net/quic/core/crypto/quic_decrypter.cc
@@ -14,18 +14,21 @@
#include "net/quic/core/crypto/null_decrypter.h"
#include "net/quic/platform/api/quic_bug_tracker.h"
#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
#include "net/quic/platform/api/quic_string.h"
#include "third_party/boringssl/src/include/openssl/tls1.h"
+using std::string;
+
namespace net {
// static
std::unique_ptr<QuicDecrypter> QuicDecrypter::Create(QuicTag algorithm) {
switch (algorithm) {
case kAESG:
- return std::make_unique<Aes128Gcm12Decrypter>();
+ return QuicMakeUnique<Aes128Gcm12Decrypter>();
case kCC20:
- return std::make_unique<ChaCha20Poly1305Decrypter>();
+ return QuicMakeUnique<ChaCha20Poly1305Decrypter>();
default:
QUIC_LOG(FATAL) << "Unsupported algorithm: " << algorithm;
return nullptr;
@@ -33,23 +36,19 @@ std::unique_ptr<QuicDecrypter> QuicDecrypter::Create(QuicTag algorithm) {
}
// static
-QuicDecrypter* QuicDecrypter::CreateFromCipherSuite(uint32_t cipher_suite) {
- QuicDecrypter* decrypter;
+std::unique_ptr<QuicDecrypter> QuicDecrypter::CreateFromCipherSuite(
+ uint32_t cipher_suite) {
switch (cipher_suite) {
case TLS1_CK_AES_128_GCM_SHA256:
- decrypter = new Aes128GcmDecrypter();
- break;
+ return QuicMakeUnique<Aes128GcmDecrypter>();
case TLS1_CK_AES_256_GCM_SHA384:
- decrypter = new Aes256GcmDecrypter();
- break;
+ return QuicMakeUnique<Aes256GcmDecrypter>();
case TLS1_CK_CHACHA20_POLY1305_SHA256:
- decrypter = new ChaCha20Poly1305TlsDecrypter();
- break;
+ return QuicMakeUnique<ChaCha20Poly1305TlsDecrypter>();
default:
QUIC_BUG << "TLS cipher suite is unknown to QUIC";
return nullptr;
}
- return decrypter;
}
// static
@@ -60,12 +59,12 @@ void QuicDecrypter::DiversifyPreliminaryKey(QuicStringPiece preliminary_key,
size_t nonce_prefix_size,
QuicString* out_key,
QuicString* out_nonce_prefix) {
- crypto::HKDF hkdf(preliminary_key.as_string() + nonce_prefix.as_string(),
+ crypto::HKDF hkdf((string(preliminary_key)) + (string(nonce_prefix)),
QuicStringPiece(nonce.data(), nonce.size()),
"QUIC key diversification", 0, key_size, 0,
nonce_prefix_size, 0);
- *out_key = hkdf.server_write_key().as_string();
- *out_nonce_prefix = hkdf.server_write_iv().as_string();
+ *out_key = string(hkdf.server_write_key());
+ *out_nonce_prefix = string(hkdf.server_write_iv());
}
} // namespace net
diff --git a/chromium/net/quic/core/crypto/quic_decrypter.h b/chromium/net/quic/core/crypto/quic_decrypter.h
index 62d25d4bcda..2ffd26f6761 100644
--- a/chromium/net/quic/core/crypto/quic_decrypter.h
+++ b/chromium/net/quic/core/crypto/quic_decrypter.h
@@ -25,7 +25,8 @@ class QUIC_EXPORT_PRIVATE QuicDecrypter {
// Creates an IETF QuicDecrypter based on |cipher_suite| which must be an id
// returned by SSL_CIPHER_get_id. The caller is responsible for taking
// ownership of the new QuicDecrypter.
- static QuicDecrypter* CreateFromCipherSuite(uint32_t cipher_suite);
+ static std::unique_ptr<QuicDecrypter> CreateFromCipherSuite(
+ uint32_t cipher_suite);
// Sets the encryption key. Returns true on success, false on failure.
//
diff --git a/chromium/net/quic/core/crypto/quic_encrypter.cc b/chromium/net/quic/core/crypto/quic_encrypter.cc
index ef78336035e..15d84f1bc1d 100644
--- a/chromium/net/quic/core/crypto/quic_encrypter.cc
+++ b/chromium/net/quic/core/crypto/quic_encrypter.cc
@@ -13,6 +13,7 @@
#include "net/quic/core/crypto/null_encrypter.h"
#include "net/quic/platform/api/quic_bug_tracker.h"
#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
#include "third_party/boringssl/src/include/openssl/tls1.h"
namespace net {
@@ -21,9 +22,9 @@ namespace net {
std::unique_ptr<QuicEncrypter> QuicEncrypter::Create(QuicTag algorithm) {
switch (algorithm) {
case kAESG:
- return std::make_unique<Aes128Gcm12Encrypter>();
+ return QuicMakeUnique<Aes128Gcm12Encrypter>();
case kCC20:
- return std::make_unique<ChaCha20Poly1305Encrypter>();
+ return QuicMakeUnique<ChaCha20Poly1305Encrypter>();
default:
QUIC_LOG(FATAL) << "Unsupported algorithm: " << algorithm;
return nullptr;
@@ -31,23 +32,19 @@ std::unique_ptr<QuicEncrypter> QuicEncrypter::Create(QuicTag algorithm) {
}
// static
-QuicEncrypter* QuicEncrypter::CreateFromCipherSuite(uint32_t cipher_suite) {
- QuicEncrypter* encrypter;
+std::unique_ptr<QuicEncrypter> QuicEncrypter::CreateFromCipherSuite(
+ uint32_t cipher_suite) {
switch (cipher_suite) {
case TLS1_CK_AES_128_GCM_SHA256:
- encrypter = new Aes128GcmEncrypter();
- break;
+ return QuicMakeUnique<Aes128GcmEncrypter>();
case TLS1_CK_AES_256_GCM_SHA384:
- encrypter = new Aes256GcmEncrypter();
- break;
+ return QuicMakeUnique<Aes256GcmEncrypter>();
case TLS1_CK_CHACHA20_POLY1305_SHA256:
- encrypter = new ChaCha20Poly1305TlsEncrypter();
- break;
+ return QuicMakeUnique<ChaCha20Poly1305TlsEncrypter>();
default:
QUIC_BUG << "TLS cipher suite is unknown to QUIC";
return nullptr;
}
- return encrypter;
}
} // namespace net
diff --git a/chromium/net/quic/core/crypto/quic_encrypter.h b/chromium/net/quic/core/crypto/quic_encrypter.h
index bc32213a1eb..d84f4342e23 100644
--- a/chromium/net/quic/core/crypto/quic_encrypter.h
+++ b/chromium/net/quic/core/crypto/quic_encrypter.h
@@ -22,8 +22,9 @@ class QUIC_EXPORT_PRIVATE QuicEncrypter {
// Creates an IETF QuicEncrypter based on |cipher_suite| which must be an id
// returned by SSL_CIPHER_get_id. The caller is responsible for taking
- // ownership of the new QuicEncrypter.
- static QuicEncrypter* CreateFromCipherSuite(uint32_t cipher_suite);
+ // ownership of the nwe QuicEncrypter.
+ static std::unique_ptr<QuicEncrypter> CreateFromCipherSuite(
+ uint32_t cipher_suite);
// Sets the encryption key. Returns true on success, false on failure.
//
diff --git a/chromium/net/quic/core/crypto/quic_random.cc b/chromium/net/quic/core/crypto/quic_random.cc
index ac54517bff1..2c5e1e22a1b 100644
--- a/chromium/net/quic/core/crypto/quic_random.cc
+++ b/chromium/net/quic/core/crypto/quic_random.cc
@@ -8,6 +8,7 @@
#include "base/memory/singleton.h"
#include "crypto/random.h"
#include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_singleton.h"
namespace net {
@@ -26,12 +27,12 @@ class DefaultRandom : public QuicRandom {
DefaultRandom() {}
~DefaultRandom() override {}
- friend struct base::DefaultSingletonTraits<DefaultRandom>;
+ friend QuicSingletonFriend<DefaultRandom>;
DISALLOW_COPY_AND_ASSIGN(DefaultRandom);
};
DefaultRandom* DefaultRandom::GetInstance() {
- return base::Singleton<DefaultRandom>::get();
+ return QuicSingleton<DefaultRandom>::get();
}
void DefaultRandom::RandBytes(void* data, size_t len) {
diff --git a/chromium/net/quic/core/frames/quic_connection_close_frame.cc b/chromium/net/quic/core/frames/quic_connection_close_frame.cc
index 4aef61dbc15..0d6062e726f 100644
--- a/chromium/net/quic/core/frames/quic_connection_close_frame.cc
+++ b/chromium/net/quic/core/frames/quic_connection_close_frame.cc
@@ -9,6 +9,10 @@ namespace net {
QuicConnectionCloseFrame::QuicConnectionCloseFrame()
: error_code(QUIC_NO_ERROR) {}
+QuicConnectionCloseFrame::QuicConnectionCloseFrame(QuicErrorCode error_code,
+ QuicString error_details)
+ : error_code(error_code), error_details(error_details) {}
+
std::ostream& operator<<(
std::ostream& os,
const QuicConnectionCloseFrame& connection_close_frame) {
diff --git a/chromium/net/quic/core/frames/quic_connection_close_frame.h b/chromium/net/quic/core/frames/quic_connection_close_frame.h
index 31f05d1e53a..89fa51c698a 100644
--- a/chromium/net/quic/core/frames/quic_connection_close_frame.h
+++ b/chromium/net/quic/core/frames/quic_connection_close_frame.h
@@ -15,6 +15,7 @@ namespace net {
struct QUIC_EXPORT_PRIVATE QuicConnectionCloseFrame {
QuicConnectionCloseFrame();
+ QuicConnectionCloseFrame(QuicErrorCode error_code, QuicString error_details);
friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
std::ostream& os,
diff --git a/chromium/net/quic/core/frames/quic_frame.h b/chromium/net/quic/core/frames/quic_frame.h
index affa1d6d1f3..244fe3f8102 100644
--- a/chromium/net/quic/core/frames/quic_frame.h
+++ b/chromium/net/quic/core/frames/quic_frame.h
@@ -12,10 +12,16 @@
#include "net/quic/core/frames/quic_blocked_frame.h"
#include "net/quic/core/frames/quic_connection_close_frame.h"
#include "net/quic/core/frames/quic_goaway_frame.h"
+#include "net/quic/core/frames/quic_ietf_blocked_frame.h"
+#include "net/quic/core/frames/quic_ietf_max_stream_id_frame.h"
+#include "net/quic/core/frames/quic_ietf_stream_id_blocked_frame.h"
#include "net/quic/core/frames/quic_mtu_discovery_frame.h"
#include "net/quic/core/frames/quic_padding_frame.h"
+#include "net/quic/core/frames/quic_path_challenge_frame.h"
+#include "net/quic/core/frames/quic_path_response_frame.h"
#include "net/quic/core/frames/quic_ping_frame.h"
#include "net/quic/core/frames/quic_rst_stream_frame.h"
+#include "net/quic/core/frames/quic_stop_sending_frame.h"
#include "net/quic/core/frames/quic_stop_waiting_frame.h"
#include "net/quic/core/frames/quic_stream_frame.h"
#include "net/quic/core/frames/quic_window_update_frame.h"
diff --git a/chromium/net/quic/core/frames/quic_ietf_blocked_frame.cc b/chromium/net/quic/core/frames/quic_ietf_blocked_frame.cc
new file mode 100644
index 00000000000..f31f0555a1b
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_ietf_blocked_frame.cc
@@ -0,0 +1,21 @@
+// 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/quic/core/frames/quic_ietf_blocked_frame.h"
+
+namespace net {
+
+QuicIetfBlockedFrame::QuicIetfBlockedFrame() {}
+
+QuicIetfBlockedFrame::QuicIetfBlockedFrame(QuicControlFrameId control_frame_id,
+ QuicStreamOffset offset)
+ : QuicControlFrame(control_frame_id), offset(offset) {}
+
+std::ostream& operator<<(std::ostream& os, const QuicIetfBlockedFrame& frame) {
+ os << "{ control_frame_id: " << frame.control_frame_id
+ << ", offset: " << frame.offset << " }\n";
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/frames/quic_ietf_blocked_frame.h b/chromium/net/quic/core/frames/quic_ietf_blocked_frame.h
new file mode 100644
index 00000000000..b0474f2cd11
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_ietf_blocked_frame.h
@@ -0,0 +1,32 @@
+// 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 NET_QUIC_CORE_FRAMES_QUIC_IETF_BLOCKED_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_IETF_BLOCKED_FRAME_H_
+
+#include <ostream>
+
+#include "net/quic/core/frames/quic_control_frame.h"
+
+namespace net {
+
+// IETF format BLOCKED frame.
+// The sender uses the BLOCKED frame to inform the receiver that the
+// sender is unable to send data because of connection-level flow control.
+struct QUIC_EXPORT_PRIVATE QuicIetfBlockedFrame : public QuicControlFrame {
+ QuicIetfBlockedFrame();
+ QuicIetfBlockedFrame(QuicControlFrameId control_frame_id,
+ QuicStreamOffset offset);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicIetfBlockedFrame& frame);
+
+ // Offset at which the BLOCKED applies
+ QuicStreamOffset offset;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_IETF_BLOCKED_FRAME_H_
diff --git a/chromium/net/quic/core/frames/quic_ietf_max_stream_id_frame.cc b/chromium/net/quic/core/frames/quic_ietf_max_stream_id_frame.cc
new file mode 100644
index 00000000000..bd7ef723593
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_ietf_max_stream_id_frame.cc
@@ -0,0 +1,23 @@
+// 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/quic/core/frames/quic_ietf_max_stream_id_frame.h"
+
+namespace net {
+
+QuicIetfMaxStreamIdFrame::QuicIetfMaxStreamIdFrame() {}
+
+QuicIetfMaxStreamIdFrame::QuicIetfMaxStreamIdFrame(
+ QuicControlFrameId control_frame_id,
+ QuicStreamId max_stream_id)
+ : QuicControlFrame(control_frame_id), max_stream_id(max_stream_id) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicIetfMaxStreamIdFrame& frame) {
+ os << "{ control_frame_id: " << frame.control_frame_id
+ << ", stream_id: " << frame.max_stream_id << " }\n";
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/frames/quic_ietf_max_stream_id_frame.h b/chromium/net/quic/core/frames/quic_ietf_max_stream_id_frame.h
new file mode 100644
index 00000000000..bfb1a97364c
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_ietf_max_stream_id_frame.h
@@ -0,0 +1,32 @@
+// 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 NET_QUIC_CORE_FRAMES_QUIC_IETF_MAX_STREAM_ID_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_IETF_MAX_STREAM_ID_FRAME_H_
+
+#include <ostream>
+
+#include "net/quic/core/frames/quic_control_frame.h"
+
+namespace net {
+
+// 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 QuicIetfMaxStreamIdFrame : public QuicControlFrame {
+ QuicIetfMaxStreamIdFrame();
+ QuicIetfMaxStreamIdFrame(QuicControlFrameId control_frame_id,
+ QuicStreamId max_stream_id);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicIetfMaxStreamIdFrame& frame);
+
+ // The maximum stream id to support.
+ QuicStreamId max_stream_id;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_IETF_MAX_STREAM_ID_FRAME_H_
diff --git a/chromium/net/quic/core/frames/quic_ietf_stream_id_blocked_frame.cc b/chromium/net/quic/core/frames/quic_ietf_stream_id_blocked_frame.cc
new file mode 100644
index 00000000000..7cbc06ef85c
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_ietf_stream_id_blocked_frame.cc
@@ -0,0 +1,23 @@
+// 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/quic/core/frames/quic_ietf_stream_id_blocked_frame.h"
+
+namespace net {
+
+QuicIetfStreamIdBlockedFrame::QuicIetfStreamIdBlockedFrame() {}
+
+QuicIetfStreamIdBlockedFrame::QuicIetfStreamIdBlockedFrame(
+ QuicControlFrameId control_frame_id,
+ QuicStreamId stream_id)
+ : QuicControlFrame(control_frame_id), stream_id(stream_id) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicIetfStreamIdBlockedFrame& frame) {
+ os << "{ control_frame_id: " << frame.control_frame_id
+ << ", stream id: " << frame.stream_id << " }\n";
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/frames/quic_ietf_stream_id_blocked_frame.h b/chromium/net/quic/core/frames/quic_ietf_stream_id_blocked_frame.h
new file mode 100644
index 00000000000..91ad6f0eb7d
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_ietf_stream_id_blocked_frame.h
@@ -0,0 +1,33 @@
+// 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 NET_QUIC_CORE_FRAMES_QUIC_IETF_STREAM_ID_BLOCKED_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_IETF_STREAM_ID_BLOCKED_FRAME_H_
+
+#include <ostream>
+
+#include "net/quic/core/frames/quic_control_frame.h"
+
+namespace net {
+
+// 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 QuicIetfStreamIdBlockedFrame
+ : public QuicControlFrame {
+ QuicIetfStreamIdBlockedFrame();
+ QuicIetfStreamIdBlockedFrame(QuicControlFrameId control_frame_id,
+ QuicStreamId stream_id);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicIetfStreamIdBlockedFrame& frame);
+
+ QuicStreamId stream_id;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_IETF_STREAM_ID_BLOCKED_FRAME_H_
diff --git a/chromium/net/quic/core/frames/quic_path_challenge_frame.cc b/chromium/net/quic/core/frames/quic_path_challenge_frame.cc
new file mode 100644
index 00000000000..a7463e5b4ba
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_path_challenge_frame.cc
@@ -0,0 +1,35 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/frames/quic_path_challenge_frame.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+
+namespace net {
+
+QuicPathChallengeFrame::QuicPathChallengeFrame() : QuicControlFrame(0) {}
+
+QuicPathChallengeFrame::QuicPathChallengeFrame(
+ QuicControlFrameId control_frame_id,
+ const QuicPathFrameBuffer& data_buff)
+ : QuicControlFrame(control_frame_id) {
+ memcpy(data_buffer.data(), data_buff.data(), data_buffer.size());
+}
+
+QuicPathChallengeFrame::~QuicPathChallengeFrame() {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicPathChallengeFrame& frame) {
+ os << "{ control_frame_id: " << frame.control_frame_id
+ << ", data: " << static_cast<unsigned>(frame.data_buffer[0]) << " "
+ << static_cast<unsigned>(frame.data_buffer[1]) << " "
+ << static_cast<unsigned>(frame.data_buffer[2]) << " "
+ << static_cast<unsigned>(frame.data_buffer[3]) << " "
+ << static_cast<unsigned>(frame.data_buffer[4]) << " "
+ << static_cast<unsigned>(frame.data_buffer[5]) << " "
+ << static_cast<unsigned>(frame.data_buffer[6]) << " "
+ << static_cast<unsigned>(frame.data_buffer[7]) << " }\n";
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/frames/quic_path_challenge_frame.h b/chromium/net/quic/core/frames/quic_path_challenge_frame.h
new file mode 100644
index 00000000000..3fabb7b58a9
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_path_challenge_frame.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_CORE_FRAMES_QUIC_PATH_CHALLENGE_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_PATH_CHALLENGE_FRAME_H_
+
+#include <memory>
+#include <ostream>
+
+#include "net/quic/core/frames/quic_control_frame.h"
+#include "net/quic/core/quic_types.h"
+
+namespace net {
+
+// Size of the entire IETF Quic Path Challenge frame, including
+// type byte.
+const size_t kQuicPathChallengeFrameSize = (kQuicPathFrameBufferSize + 1);
+
+struct QUIC_EXPORT_PRIVATE QuicPathChallengeFrame : public QuicControlFrame {
+ QuicPathChallengeFrame();
+ QuicPathChallengeFrame(QuicControlFrameId control_frame_id,
+ const QuicPathFrameBuffer& data_buff);
+ ~QuicPathChallengeFrame();
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicPathChallengeFrame& frame);
+
+ QuicPathFrameBuffer data_buffer;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(QuicPathChallengeFrame);
+};
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_PATH_CHALLENGE_FRAME_H_
diff --git a/chromium/net/quic/core/frames/quic_path_response_frame.cc b/chromium/net/quic/core/frames/quic_path_response_frame.cc
new file mode 100644
index 00000000000..2d0068a7354
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_path_response_frame.cc
@@ -0,0 +1,34 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/frames/quic_path_response_frame.h"
+#include "net/quic/platform/api/quic_bug_tracker.h"
+
+namespace net {
+
+QuicPathResponseFrame::QuicPathResponseFrame() : QuicControlFrame(0) {}
+
+QuicPathResponseFrame::QuicPathResponseFrame(
+ QuicControlFrameId control_frame_id,
+ const QuicPathFrameBuffer& data_buff)
+ : QuicControlFrame(control_frame_id) {
+ memcpy(data_buffer.data(), data_buff.data(), data_buffer.size());
+}
+
+QuicPathResponseFrame::~QuicPathResponseFrame() {}
+
+std::ostream& operator<<(std::ostream& os, const QuicPathResponseFrame& frame) {
+ os << "{ control_frame_id: " << frame.control_frame_id
+ << ", data: " << static_cast<unsigned>(frame.data_buffer[0]) << " "
+ << static_cast<unsigned>(frame.data_buffer[1]) << " "
+ << static_cast<unsigned>(frame.data_buffer[2]) << " "
+ << static_cast<unsigned>(frame.data_buffer[3]) << " "
+ << static_cast<unsigned>(frame.data_buffer[4]) << " "
+ << static_cast<unsigned>(frame.data_buffer[5]) << " "
+ << static_cast<unsigned>(frame.data_buffer[6]) << " "
+ << static_cast<unsigned>(frame.data_buffer[7]) << " }\n";
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/frames/quic_path_response_frame.h b/chromium/net/quic/core/frames/quic_path_response_frame.h
new file mode 100644
index 00000000000..c56dc6779d2
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_path_response_frame.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_CORE_FRAMES_QUIC_PATH_RESPONSE_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_PATH_RESPONSE_FRAME_H_
+
+#include <memory>
+#include <ostream>
+
+#include "net/quic/core/frames/quic_control_frame.h"
+#include "net/quic/core/quic_types.h"
+
+namespace net {
+
+// Size of the entire IETF Quic Path Response frame, including
+// type byte.
+const size_t kQuicPathResponseFrameSize = (kQuicPathFrameBufferSize + 1);
+
+struct QUIC_EXPORT_PRIVATE QuicPathResponseFrame : public QuicControlFrame {
+ QuicPathResponseFrame();
+ QuicPathResponseFrame(QuicControlFrameId control_frame_id,
+ const QuicPathFrameBuffer& data_buff);
+ ~QuicPathResponseFrame();
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicPathResponseFrame& frame);
+
+ QuicPathFrameBuffer data_buffer;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(QuicPathResponseFrame);
+};
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_PATH_RESPONSE_FRAME_H_
diff --git a/chromium/net/quic/core/frames/quic_stop_sending_frame.cc b/chromium/net/quic/core/frames/quic_stop_sending_frame.cc
new file mode 100644
index 00000000000..203baeb6076
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_stop_sending_frame.cc
@@ -0,0 +1,27 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/frames/quic_stop_sending_frame.h"
+
+namespace net {
+
+QuicStopSendingFrame::QuicStopSendingFrame()
+ : stream_id(0), application_error_code(0) {}
+
+QuicStopSendingFrame::QuicStopSendingFrame(
+ QuicControlFrameId control_frame_id,
+ QuicStreamId stream_id,
+ QuicApplicationErrorCode application_error_code)
+ : QuicControlFrame(control_frame_id),
+ stream_id(stream_id),
+ application_error_code(application_error_code) {}
+
+std::ostream& operator<<(std::ostream& os, const QuicStopSendingFrame& frame) {
+ os << "{ control_frame_id: " << frame.control_frame_id
+ << ", stream_id: " << frame.stream_id
+ << ", application_error_code: " << frame.application_error_code << " }\n";
+ return os;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/core/frames/quic_stop_sending_frame.h b/chromium/net/quic/core/frames/quic_stop_sending_frame.h
new file mode 100644
index 00000000000..0cc2c55192e
--- /dev/null
+++ b/chromium/net/quic/core/frames/quic_stop_sending_frame.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_CORE_FRAMES_QUIC_STOP_SENDING_FRAME_H_
+#define NET_QUIC_CORE_FRAMES_QUIC_STOP_SENDING_FRAME_H_
+
+#include <ostream>
+
+#include "net/quic/core/frames/quic_control_frame.h"
+#include "net/quic/core/quic_error_codes.h"
+
+namespace net {
+
+struct QUIC_EXPORT_PRIVATE QuicStopSendingFrame : public QuicControlFrame {
+ QuicStopSendingFrame();
+ QuicStopSendingFrame(QuicControlFrameId control_frame_id,
+ QuicStreamId stream_id,
+ uint16_t application_error_code);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicStopSendingFrame& frame);
+
+ QuicStreamId stream_id;
+ QuicApplicationErrorCode application_error_code;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CORE_FRAMES_QUIC_STOP_SENDING_FRAME_H_
diff --git a/chromium/net/quic/core/frames/quic_window_update_frame.h b/chromium/net/quic/core/frames/quic_window_update_frame.h
index e94496658e7..fa2f973e66f 100644
--- a/chromium/net/quic/core/frames/quic_window_update_frame.h
+++ b/chromium/net/quic/core/frames/quic_window_update_frame.h
@@ -32,6 +32,10 @@ struct QUIC_EXPORT_PRIVATE QuicWindowUpdateFrame : public QuicControlFrame {
// Byte offset in the stream or connection. The receiver of this frame must
// not send data which would result in this offset being exceeded.
+ //
+ // TODO(fkastenholz): Rename this to max_data and change the type to
+ // QuicByteCount because the IETF defines this as the "maximum
+ // amount of data that can be sent".
QuicStreamOffset byte_offset;
};
diff --git a/chromium/net/quic/core/quic_buffered_packet_store.cc b/chromium/net/quic/core/quic_buffered_packet_store.cc
index 8dc6dd069cb..40429da6ec3 100644
--- a/chromium/net/quic/core/quic_buffered_packet_store.cc
+++ b/chromium/net/quic/core/quic_buffered_packet_store.cc
@@ -54,7 +54,8 @@ BufferedPacket& BufferedPacket::operator=(BufferedPacket&& other) = default;
BufferedPacket::~BufferedPacket() {}
-BufferedPacketList::BufferedPacketList() : creation_time(QuicTime::Zero()) {}
+BufferedPacketList::BufferedPacketList()
+ : creation_time(QuicTime::Zero()), ietf_quic(false) {}
BufferedPacketList::BufferedPacketList(BufferedPacketList&& other) = default;
@@ -78,6 +79,7 @@ QuicBufferedPacketStore::~QuicBufferedPacketStore() {}
EnqueuePacketResult QuicBufferedPacketStore::EnqueuePacket(
QuicConnectionId connection_id,
+ bool ietf_quic,
const QuicReceivedPacket& packet,
QuicSocketAddress server_address,
QuicSocketAddress client_address,
@@ -98,6 +100,7 @@ EnqueuePacketResult QuicBufferedPacketStore::EnqueuePacket(
} else if (!QuicContainsKey(undecryptable_packets_, connection_id)) {
undecryptable_packets_.emplace(
std::make_pair(connection_id, BufferedPacketList()));
+ undecryptable_packets_.back().second.ietf_quic = ietf_quic;
}
CHECK(QuicContainsKey(undecryptable_packets_, connection_id));
BufferedPacketList& queue =
diff --git a/chromium/net/quic/core/quic_buffered_packet_store.h b/chromium/net/quic/core/quic_buffered_packet_store.h
index 42e22feebda..b2271640cee 100644
--- a/chromium/net/quic/core/quic_buffered_packet_store.h
+++ b/chromium/net/quic/core/quic_buffered_packet_store.h
@@ -69,6 +69,8 @@ class QUIC_EXPORT_PRIVATE QuicBufferedPacketStore {
QuicTime creation_time;
// The alpn from the CHLO, if one was found.
QuicString alpn;
+ // Indicating whether this is an IETF QUIC connection.
+ bool ietf_quic;
};
typedef QuicLinkedHashMap<QuicConnectionId, BufferedPacketList>
@@ -95,6 +97,7 @@ class QUIC_EXPORT_PRIVATE QuicBufferedPacketStore {
// Adds a copy of packet into packet queue for given connection.
EnqueuePacketResult EnqueuePacket(QuicConnectionId connection_id,
+ bool ietf_quic,
const QuicReceivedPacket& packet,
QuicSocketAddress server_address,
QuicSocketAddress client_address,
diff --git a/chromium/net/quic/core/quic_buffered_packet_store_test.cc b/chromium/net/quic/core/quic_buffered_packet_store_test.cc
index f7dc69dbb14..aaa29ce2b19 100644
--- a/chromium/net/quic/core/quic_buffered_packet_store_test.cc
+++ b/chromium/net/quic/core/quic_buffered_packet_store_test.cc
@@ -69,8 +69,8 @@ class QuicBufferedPacketStoreTest : public QuicTest {
TEST_F(QuicBufferedPacketStoreTest, SimpleEnqueueAndDeliverPacket) {
QuicConnectionId connection_id = 1;
- store_.EnqueuePacket(connection_id, packet_, server_address_, client_address_,
- false, "");
+ store_.EnqueuePacket(connection_id, false, packet_, server_address_,
+ client_address_, false, "");
EXPECT_TRUE(store_.HasBufferedPackets(connection_id));
auto packets = store_.DeliverPackets(connection_id);
const std::list<BufferedPacket>& queue = packets.buffered_packets;
@@ -90,9 +90,9 @@ TEST_F(QuicBufferedPacketStoreTest, SimpleEnqueueAndDeliverPacket) {
TEST_F(QuicBufferedPacketStoreTest, DifferentPacketAddressOnOneConnection) {
QuicSocketAddress addr_with_new_port(QuicIpAddress::Any4(), 256);
QuicConnectionId connection_id = 1;
- store_.EnqueuePacket(connection_id, packet_, server_address_, client_address_,
- false, "");
- store_.EnqueuePacket(connection_id, packet_, server_address_,
+ store_.EnqueuePacket(connection_id, false, packet_, server_address_,
+ client_address_, false, "");
+ store_.EnqueuePacket(connection_id, false, packet_, server_address_,
addr_with_new_port, false, "");
std::list<BufferedPacket> queue =
store_.DeliverPackets(connection_id).buffered_packets;
@@ -107,9 +107,9 @@ TEST_F(QuicBufferedPacketStoreTest,
size_t num_connections = 10;
for (QuicConnectionId connection_id = 1; connection_id <= num_connections;
++connection_id) {
- store_.EnqueuePacket(connection_id, packet_, server_address_,
+ store_.EnqueuePacket(connection_id, false, packet_, server_address_,
client_address_, false, "");
- store_.EnqueuePacket(connection_id, packet_, server_address_,
+ store_.EnqueuePacket(connection_id, false, packet_, server_address_,
client_address_, false, "");
}
@@ -131,12 +131,13 @@ TEST_F(QuicBufferedPacketStoreTest,
// Arrived CHLO packet shouldn't affect how many non-CHLO pacekts store can
// keep.
EXPECT_EQ(QuicBufferedPacketStore::SUCCESS,
- store_.EnqueuePacket(connection_id, packet_, server_address_,
+ store_.EnqueuePacket(connection_id, false, packet_, server_address_,
client_address_, true, ""));
for (size_t i = 1; i <= num_packets; ++i) {
// Only first |kDefaultMaxUndecryptablePackets packets| will be buffered.
- EnqueuePacketResult result = store_.EnqueuePacket(
- connection_id, packet_, server_address_, client_address_, false, "");
+ EnqueuePacketResult result =
+ store_.EnqueuePacket(connection_id, false, packet_, server_address_,
+ client_address_, false, "");
if (i <= kDefaultMaxUndecryptablePackets) {
EXPECT_EQ(EnqueuePacketResult::SUCCESS, result);
} else {
@@ -156,8 +157,9 @@ TEST_F(QuicBufferedPacketStoreTest, ReachNonChloConnectionUpperLimit) {
const size_t kNumConnections = kMaxConnectionsWithoutCHLO + 1;
for (size_t connection_id = 1; connection_id <= kNumConnections;
++connection_id) {
- EnqueuePacketResult result = store_.EnqueuePacket(
- connection_id, packet_, server_address_, client_address_, false, "");
+ EnqueuePacketResult result =
+ store_.EnqueuePacket(connection_id, false, packet_, server_address_,
+ client_address_, false, "");
if (connection_id <= kMaxConnectionsWithoutCHLO) {
EXPECT_EQ(EnqueuePacketResult::SUCCESS, result);
} else {
@@ -185,8 +187,8 @@ TEST_F(QuicBufferedPacketStoreTest,
kDefaultMaxConnectionsInStore - kMaxConnectionsWithoutCHLO + 1;
for (size_t connection_id = 1; connection_id <= num_chlos; ++connection_id) {
EXPECT_EQ(EnqueuePacketResult::SUCCESS,
- store_.EnqueuePacket(connection_id, packet_, server_address_,
- client_address_, true, ""));
+ store_.EnqueuePacket(connection_id, false, packet_,
+ server_address_, client_address_, true, ""));
}
// Send data packets on another |kMaxConnectionsWithoutCHLO| connections.
@@ -194,7 +196,7 @@ TEST_F(QuicBufferedPacketStoreTest,
for (size_t conn_id = num_chlos + 1;
conn_id <= (kDefaultMaxConnectionsInStore + 1); ++conn_id) {
EnqueuePacketResult result = store_.EnqueuePacket(
- conn_id, packet_, server_address_, client_address_, true, "");
+ conn_id, false, packet_, server_address_, client_address_, true, "");
if (conn_id <= kDefaultMaxConnectionsInStore) {
EXPECT_EQ(EnqueuePacketResult::SUCCESS, result);
} else {
@@ -208,7 +210,7 @@ TEST_F(QuicBufferedPacketStoreTest, EnqueueChloOnTooManyDifferentConnections) {
for (QuicConnectionId conn_id = 1; conn_id <= kMaxConnectionsWithoutCHLO;
++conn_id) {
EXPECT_EQ(EnqueuePacketResult::SUCCESS,
- store_.EnqueuePacket(conn_id, packet_, server_address_,
+ store_.EnqueuePacket(conn_id, false, packet_, server_address_,
client_address_, false, ""));
}
@@ -216,8 +218,8 @@ TEST_F(QuicBufferedPacketStoreTest, EnqueueChloOnTooManyDifferentConnections) {
for (size_t i = kMaxConnectionsWithoutCHLO + 1;
i <= kDefaultMaxConnectionsInStore + 1; ++i) {
EnqueuePacketResult rs = store_.EnqueuePacket(
- /*connection_id=*/i, packet_, server_address_, client_address_, true,
- "");
+ /*connection_id=*/i, false, packet_, server_address_, client_address_,
+ true, "");
if (i <= kDefaultMaxConnectionsInStore) {
EXPECT_EQ(EnqueuePacketResult::SUCCESS, rs);
EXPECT_TRUE(store_.HasChloForConnection(/*connection_id=*/i));
@@ -232,8 +234,8 @@ TEST_F(QuicBufferedPacketStoreTest, EnqueueChloOnTooManyDifferentConnections) {
// buffered in the store should success. This is the connection should be
// delivered at last.
EXPECT_EQ(EnqueuePacketResult::SUCCESS,
- store_.EnqueuePacket(/*connection_id=*/1, packet_, server_address_,
- client_address_, true, ""));
+ store_.EnqueuePacket(/*connection_id=*/1, false, packet_,
+ server_address_, client_address_, true, ""));
EXPECT_TRUE(store_.HasChloForConnection(/*connection_id=*/1));
QuicConnectionId delivered_conn_id;
@@ -258,15 +260,15 @@ TEST_F(QuicBufferedPacketStoreTest, EnqueueChloOnTooManyDifferentConnections) {
// connections both with and without CHLOs.
TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery) {
QuicConnectionId connection_id = 1;
- store_.EnqueuePacket(connection_id, packet_, server_address_, client_address_,
- false, "");
+ store_.EnqueuePacket(connection_id, false, packet_, server_address_,
+ client_address_, false, "");
EXPECT_EQ(EnqueuePacketResult::SUCCESS,
- store_.EnqueuePacket(connection_id, packet_, server_address_,
+ store_.EnqueuePacket(connection_id, false, packet_, server_address_,
client_address_, true, ""));
QuicConnectionId connection_id2 = 2;
EXPECT_EQ(EnqueuePacketResult::SUCCESS,
- store_.EnqueuePacket(connection_id2, packet_, server_address_,
- client_address_, false, ""));
+ store_.EnqueuePacket(connection_id2, false, packet_,
+ server_address_, client_address_, false, ""));
// CHLO on connection 3 arrives 1ms later.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
@@ -274,7 +276,7 @@ TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery) {
// Use different client address to differetiate packets from different
// connections.
QuicSocketAddress another_client_address(QuicIpAddress::Any4(), 255);
- store_.EnqueuePacket(connection_id3, packet_, server_address_,
+ store_.EnqueuePacket(connection_id3, false, packet_, server_address_,
another_client_address, true, "");
// Advance clock to the time when connection 1 and 2 expires.
@@ -306,9 +308,9 @@ TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery) {
// Test the alarm is reset by enqueueing 2 packets for 4th connection and wait
// for them to expire.
QuicConnectionId connection_id4 = 4;
- store_.EnqueuePacket(connection_id4, packet_, server_address_,
+ store_.EnqueuePacket(connection_id4, false, packet_, server_address_,
client_address_, false, "");
- store_.EnqueuePacket(connection_id4, packet_, server_address_,
+ store_.EnqueuePacket(connection_id4, false, packet_, server_address_,
client_address_, false, "");
clock_.AdvanceTime(
QuicBufferedPacketStorePeer::expiration_alarm(&store_)->deadline() -
@@ -323,10 +325,10 @@ TEST_F(QuicBufferedPacketStoreTest, SimpleDiscardPackets) {
QuicConnectionId connection_id = 1;
// Enqueue some packets
- store_.EnqueuePacket(connection_id, packet_, server_address_, client_address_,
- false, "");
- store_.EnqueuePacket(connection_id, packet_, server_address_, client_address_,
- false, "");
+ store_.EnqueuePacket(connection_id, false, packet_, server_address_,
+ client_address_, false, "");
+ store_.EnqueuePacket(connection_id, false, packet_, server_address_,
+ client_address_, false, "");
EXPECT_TRUE(store_.HasBufferedPackets(connection_id));
EXPECT_FALSE(store_.HasChlosBuffered());
@@ -349,12 +351,12 @@ TEST_F(QuicBufferedPacketStoreTest, DiscardWithCHLOs) {
QuicConnectionId connection_id = 1;
// Enqueue some packets, which include a CHLO
- store_.EnqueuePacket(connection_id, packet_, server_address_, client_address_,
- false, "");
- store_.EnqueuePacket(connection_id, packet_, server_address_, client_address_,
- true, "");
- store_.EnqueuePacket(connection_id, packet_, server_address_, client_address_,
- false, "");
+ store_.EnqueuePacket(connection_id, false, packet_, server_address_,
+ client_address_, false, "");
+ store_.EnqueuePacket(connection_id, false, packet_, server_address_,
+ client_address_, true, "");
+ store_.EnqueuePacket(connection_id, false, packet_, server_address_,
+ client_address_, false, "");
EXPECT_TRUE(store_.HasBufferedPackets(connection_id));
EXPECT_TRUE(store_.HasChlosBuffered());
@@ -378,11 +380,11 @@ TEST_F(QuicBufferedPacketStoreTest, MultipleDiscardPackets) {
QuicConnectionId connection_id_2 = 2;
// Enqueue some packets for two connection IDs
- store_.EnqueuePacket(connection_id_1, packet_, server_address_,
+ store_.EnqueuePacket(connection_id_1, false, packet_, server_address_,
client_address_, false, "");
- store_.EnqueuePacket(connection_id_1, packet_, server_address_,
+ store_.EnqueuePacket(connection_id_1, false, packet_, server_address_,
client_address_, false, "");
- store_.EnqueuePacket(connection_id_2, packet_, server_address_,
+ store_.EnqueuePacket(connection_id_2, false, packet_, server_address_,
client_address_, true, "h3");
EXPECT_TRUE(store_.HasBufferedPackets(connection_id_1));
EXPECT_TRUE(store_.HasBufferedPackets(connection_id_2));
diff --git a/chromium/net/quic/core/quic_client_promised_info_test.cc b/chromium/net/quic/core/quic_client_promised_info_test.cc
index 54a4c919f16..3fae76e470c 100644
--- a/chromium/net/quic/core/quic_client_promised_info_test.cc
+++ b/chromium/net/quic/core/quic_client_promised_info_test.cc
@@ -138,14 +138,9 @@ TEST_F(QuicClientPromisedInfoTest, PushPromiseCleanupAlarm) {
ASSERT_NE(promised, nullptr);
// Fire the alarm that will cancel the promised stream.
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_,
- OnStreamReset(promise_id_, QUIC_PUSH_STREAM_TIMED_OUT));
- } else {
- EXPECT_CALL(*connection_,
- SendRstStream(promise_id_, QUIC_PUSH_STREAM_TIMED_OUT, 0));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_,
+ OnStreamReset(promise_id_, QUIC_PUSH_STREAM_TIMED_OUT));
alarm_factory_.FireAlarm(QuicClientPromisedInfoPeer::GetAlarm(promised));
// Verify that the promise is gone after the alarm fires.
@@ -157,14 +152,9 @@ TEST_F(QuicClientPromisedInfoTest, PushPromiseInvalidMethod) {
// Promise with an unsafe method
push_promise_[":method"] = "PUT";
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_,
- OnStreamReset(promise_id_, QUIC_INVALID_PROMISE_METHOD));
- } else {
- EXPECT_CALL(*connection_,
- SendRstStream(promise_id_, QUIC_INVALID_PROMISE_METHOD, 0));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_,
+ OnStreamReset(promise_id_, QUIC_INVALID_PROMISE_METHOD));
ReceivePromise(promise_id_);
// Verify that the promise headers were ignored
@@ -176,14 +166,9 @@ TEST_F(QuicClientPromisedInfoTest, PushPromiseMissingMethod) {
// Promise with a missing method
push_promise_.erase(":method");
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_,
- OnStreamReset(promise_id_, QUIC_INVALID_PROMISE_METHOD));
- } else {
- EXPECT_CALL(*connection_,
- SendRstStream(promise_id_, QUIC_INVALID_PROMISE_METHOD, 0));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_,
+ OnStreamReset(promise_id_, QUIC_INVALID_PROMISE_METHOD));
ReceivePromise(promise_id_);
// Verify that the promise headers were ignored
@@ -195,14 +180,9 @@ TEST_F(QuicClientPromisedInfoTest, PushPromiseInvalidUrl) {
// Remove required header field to make URL invalid
push_promise_.erase(":authority");
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_,
- OnStreamReset(promise_id_, QUIC_INVALID_PROMISE_URL));
- } else {
- EXPECT_CALL(*connection_,
- SendRstStream(promise_id_, QUIC_INVALID_PROMISE_URL, 0));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_,
+ OnStreamReset(promise_id_, QUIC_INVALID_PROMISE_URL));
ReceivePromise(promise_id_);
// Verify that the promise headers were ignored
@@ -213,14 +193,9 @@ TEST_F(QuicClientPromisedInfoTest, PushPromiseInvalidUrl) {
TEST_F(QuicClientPromisedInfoTest, PushPromiseUnauthorizedUrl) {
session_.set_authorized(false);
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_,
- OnStreamReset(promise_id_, QUIC_UNAUTHORIZED_PROMISE_URL));
- } else {
- EXPECT_CALL(*connection_,
- SendRstStream(promise_id_, QUIC_UNAUTHORIZED_PROMISE_URL, 0));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_,
+ OnStreamReset(promise_id_, QUIC_UNAUTHORIZED_PROMISE_URL));
ReceivePromise(promise_id_);
@@ -243,14 +218,9 @@ TEST_F(QuicClientPromisedInfoTest, PushPromiseMismatch) {
headers);
TestPushPromiseDelegate delegate(/*match=*/false);
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_,
- OnStreamReset(promise_id_, QUIC_PROMISE_VARY_MISMATCH));
- } else {
- EXPECT_CALL(*connection_,
- SendRstStream(promise_id_, QUIC_PROMISE_VARY_MISMATCH, 0));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_,
+ OnStreamReset(promise_id_, QUIC_PROMISE_VARY_MISMATCH));
EXPECT_CALL(session_, CloseStream(promise_id_));
promised->HandleClientRequest(client_request_, &delegate);
@@ -328,14 +298,8 @@ TEST_F(QuicClientPromisedInfoTest, PushPromiseWaitCancels) {
// Cancel the promised stream.
EXPECT_CALL(session_, CloseStream(promise_id_));
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_,
- OnStreamReset(promise_id_, QUIC_STREAM_CANCELLED));
- } else {
- EXPECT_CALL(*connection_,
- SendRstStream(promise_id_, QUIC_STREAM_CANCELLED, 0));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(promise_id_, QUIC_STREAM_CANCELLED));
promised->Cancel();
// Promise is gone
@@ -358,14 +322,9 @@ TEST_F(QuicClientPromisedInfoTest, PushPromiseDataClosed) {
headers);
EXPECT_CALL(session_, CloseStream(promise_id_));
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_,
- OnStreamReset(promise_id_, QUIC_STREAM_PEER_GOING_AWAY));
- } else {
- EXPECT_CALL(*connection_,
- SendRstStream(promise_id_, QUIC_STREAM_PEER_GOING_AWAY, 0));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_,
+ OnStreamReset(promise_id_, QUIC_STREAM_PEER_GOING_AWAY));
session_.SendRstStream(promise_id_, QUIC_STREAM_PEER_GOING_AWAY, 0);
// Now initiate rendezvous.
diff --git a/chromium/net/quic/core/quic_config.cc b/chromium/net/quic/core/quic_config.cc
index 4a3d18f810f..0a89a756ee6 100644
--- a/chromium/net/quic/core/quic_config.cc
+++ b/chromium/net/quic/core/quic_config.cc
@@ -17,7 +17,6 @@
#include "net/quic/platform/api/quic_string.h"
#include "net/quic/platform/api/quic_string_piece.h"
-
namespace net {
// Reads the value corresponding to |name_| from |msg| into |out|. If the
@@ -190,13 +189,13 @@ bool QuicFixedUint128::HasSendValue() const {
return has_send_value_;
}
-uint128 QuicFixedUint128::GetSendValue() const {
+QuicUint128 QuicFixedUint128::GetSendValue() const {
QUIC_BUG_IF(!has_send_value_)
<< "No send value to get for tag:" << QuicTagToString(tag_);
return send_value_;
}
-void QuicFixedUint128::SetSendValue(uint128 value) {
+void QuicFixedUint128::SetSendValue(QuicUint128 value) {
has_send_value_ = true;
send_value_ = value;
}
@@ -205,13 +204,13 @@ bool QuicFixedUint128::HasReceivedValue() const {
return has_receive_value_;
}
-uint128 QuicFixedUint128::GetReceivedValue() const {
+QuicUint128 QuicFixedUint128::GetReceivedValue() const {
QUIC_BUG_IF(!has_receive_value_)
<< "No receive value to get for tag:" << QuicTagToString(tag_);
return receive_value_;
}
-void QuicFixedUint128::SetReceivedValue(uint128 value) {
+void QuicFixedUint128::SetReceivedValue(QuicUint128 value) {
has_receive_value_ = true;
receive_value_ = value;
}
@@ -399,7 +398,6 @@ QuicConfig::QuicConfig()
initial_round_trip_time_us_(kIRTT, PRESENCE_OPTIONAL),
initial_stream_flow_control_window_bytes_(kSFCW, PRESENCE_OPTIONAL),
initial_session_flow_control_window_bytes_(kCFCW, PRESENCE_OPTIONAL),
- socket_receive_buffer_(kSRBF, PRESENCE_OPTIONAL),
connection_migration_disabled_(kNCMR, PRESENCE_OPTIONAL),
alternate_server_address_(kASAD, PRESENCE_OPTIONAL),
support_max_header_list_size_(kSMHL, PRESENCE_OPTIONAL),
@@ -633,7 +631,8 @@ bool QuicConfig::SupportMaxHeaderListSize() const {
return support_max_header_list_size_.HasReceivedValue();
}
-void QuicConfig::SetStatelessResetTokenToSend(uint128 stateless_reset_token) {
+void QuicConfig::SetStatelessResetTokenToSend(
+ QuicUint128 stateless_reset_token) {
stateless_reset_token_.SetSendValue(stateless_reset_token);
}
@@ -641,7 +640,7 @@ bool QuicConfig::HasReceivedStatelessResetToken() const {
return stateless_reset_token_.HasReceivedValue();
}
-uint128 QuicConfig::ReceivedStatelessResetToken() const {
+QuicUint128 QuicConfig::ReceivedStatelessResetToken() const {
return stateless_reset_token_.GetReceivedValue();
}
diff --git a/chromium/net/quic/core/quic_config.h b/chromium/net/quic/core/quic_config.h
index 3f2be56636d..c421198f3f9 100644
--- a/chromium/net/quic/core/quic_config.h
+++ b/chromium/net/quic/core/quic_config.h
@@ -8,11 +8,11 @@
#include <cstddef>
#include <cstdint>
-#include "net/base/int128.h"
#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_time.h"
#include "net/quic/platform/api/quic_export.h"
#include "net/quic/platform/api/quic_string.h"
+#include "net/quic/platform/api/quic_uint128.h"
namespace net {
@@ -155,15 +155,15 @@ class QUIC_EXPORT_PRIVATE QuicFixedUint128 : public QuicConfigValue {
bool HasSendValue() const;
- uint128 GetSendValue() const;
+ QuicUint128 GetSendValue() const;
- void SetSendValue(uint128 value);
+ void SetSendValue(QuicUint128 value);
bool HasReceivedValue() const;
- uint128 GetReceivedValue() const;
+ QuicUint128 GetReceivedValue() const;
- void SetReceivedValue(uint128 value);
+ void SetReceivedValue(QuicUint128 value);
// If has_send_value is true, serialises |tag_| and |send_value_| to |out|.
void ToHandshakeMessage(CryptoHandshakeMessage* out) const override;
@@ -174,9 +174,9 @@ class QUIC_EXPORT_PRIVATE QuicFixedUint128 : public QuicConfigValue {
QuicString* error_details) override;
private:
- uint128 send_value_;
+ QuicUint128 send_value_;
bool has_send_value_;
- uint128 receive_value_;
+ QuicUint128 receive_value_;
bool has_receive_value_;
};
@@ -393,11 +393,11 @@ class QUIC_EXPORT_PRIVATE QuicConfig {
bool SupportMaxHeaderListSize() const;
- void SetStatelessResetTokenToSend(uint128 stateless_reset_token);
+ void SetStatelessResetTokenToSend(QuicUint128 stateless_reset_token);
bool HasReceivedStatelessResetToken() const;
- uint128 ReceivedStatelessResetToken() const;
+ QuicUint128 ReceivedStatelessResetToken() const;
bool negotiated() const;
@@ -453,10 +453,6 @@ class QUIC_EXPORT_PRIVATE QuicConfig {
// Initial session flow control receive window in bytes.
QuicFixedUint32 initial_session_flow_control_window_bytes_;
- // Socket receive buffer in bytes.
- // TODO(ianswett): Deprecate once QUIC_VERSION_34 is deprecated.
- QuicFixedUint32 socket_receive_buffer_;
-
// Whether tell peer not to attempt connection migration.
QuicFixedUint32 connection_migration_disabled_;
diff --git a/chromium/net/quic/core/quic_config_test.cc b/chromium/net/quic/core/quic_config_test.cc
index 630f631d653..6b1f620e855 100644
--- a/chromium/net/quic/core/quic_config_test.cc
+++ b/chromium/net/quic/core/quic_config_test.cc
@@ -11,11 +11,11 @@
#include "net/quic/core/quic_utils.h"
#include "net/quic/platform/api/quic_string.h"
#include "net/quic/platform/api/quic_test.h"
+#include "net/quic/platform/api/quic_uint128.h"
#include "net/quic/test_tools/quic_config_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/test/gtest_util.h"
-
namespace net {
namespace test {
namespace {
@@ -107,7 +107,7 @@ TEST_F(QuicConfigTest, ProcessServerHello) {
QuicIpAddress host;
host.FromString("127.0.3.1");
const QuicSocketAddress kTestServerAddress = QuicSocketAddress(host, 1234);
- const uint128 kTestResetToken = MakeUint128(0, 10111100001);
+ const QuicUint128 kTestResetToken = MakeQuicUint128(0, 10111100001);
QuicConfig server_config;
QuicTagVector cgst;
cgst.push_back(kQBIC);
diff --git a/chromium/net/quic/core/quic_connection.cc b/chromium/net/quic/core/quic_connection.cc
index d7127b07efd..77ca7bd1eec 100644
--- a/chromium/net/quic/core/quic_connection.cc
+++ b/chromium/net/quic/core/quic_connection.cc
@@ -126,6 +126,19 @@ class SendAlarmDelegate : public QuicAlarm::Delegate {
DISALLOW_COPY_AND_ASSIGN(SendAlarmDelegate);
};
+class PathDegradingAlarmDelegate : public QuicAlarm::Delegate {
+ public:
+ explicit PathDegradingAlarmDelegate(QuicConnection* connection)
+ : connection_(connection) {}
+
+ void OnAlarm() override { connection_->OnPathDegradingTimeout(); }
+
+ private:
+ QuicConnection* connection_;
+
+ DISALLOW_COPY_AND_ASSIGN(PathDegradingAlarmDelegate);
+};
+
class TimeoutAlarmDelegate : public QuicAlarm::Delegate {
public:
explicit TimeoutAlarmDelegate(QuicConnection* connection)
@@ -165,6 +178,19 @@ class MtuDiscoveryAlarmDelegate : public QuicAlarm::Delegate {
DISALLOW_COPY_AND_ASSIGN(MtuDiscoveryAlarmDelegate);
};
+class RetransmittableOnWireAlarmDelegate : public QuicAlarm::Delegate {
+ public:
+ explicit RetransmittableOnWireAlarmDelegate(QuicConnection* connection)
+ : connection_(connection) {}
+
+ void OnAlarm() override { connection_->OnPingTimeout(); }
+
+ private:
+ QuicConnection* connection_;
+
+ DISALLOW_COPY_AND_ASSIGN(RetransmittableOnWireAlarmDelegate);
+};
+
} // namespace
#define ENDPOINT \
@@ -184,6 +210,7 @@ QuicConnection::QuicConnection(
perspective),
current_packet_content_(NO_FRAMES_RECEIVED),
current_peer_migration_type_(NO_CHANGE),
+ current_effective_peer_migration_type_(NO_CHANGE),
helper_(helper),
alarm_factory_(alarm_factory),
per_packet_options_(nullptr),
@@ -194,8 +221,11 @@ QuicConnection::QuicConnection(
random_generator_(helper->GetRandomGenerator()),
connection_id_(connection_id),
peer_address_(initial_peer_address),
+ direct_peer_address_(initial_peer_address),
active_peer_migration_type_(NO_CHANGE),
highest_packet_sent_before_peer_migration_(0),
+ active_effective_peer_migration_type_(NO_CHANGE),
+ highest_packet_sent_before_effective_peer_migration_(0),
last_packet_decrypted_(false),
last_size_(0),
current_packet_data_(nullptr),
@@ -225,6 +255,7 @@ QuicConnection::QuicConnection(
pending_retransmission_alarm_(false),
defer_send_in_response_to_packets_(false),
ping_timeout_(QuicTime::Delta::FromSeconds(kPingTimeoutSecs)),
+ retransmittable_on_wire_timeout_(QuicTime::Delta::Infinite()),
arena_(),
ack_alarm_(alarm_factory_->CreateAlarm(arena_.New<AckAlarmDelegate>(this),
&arena_)),
@@ -246,6 +277,12 @@ QuicConnection::QuicConnection(
mtu_discovery_alarm_(alarm_factory_->CreateAlarm(
arena_.New<MtuDiscoveryAlarmDelegate>(this),
&arena_)),
+ retransmittable_on_wire_alarm_(alarm_factory_->CreateAlarm(
+ arena_.New<RetransmittableOnWireAlarmDelegate>(this),
+ &arena_)),
+ path_degrading_alarm_(alarm_factory_->CreateAlarm(
+ arena_.New<PathDegradingAlarmDelegate>(this),
+ &arena_)),
visitor_(nullptr),
debug_visitor_(nullptr),
packet_generator_(connection_id_, &framer_, random_generator_, this),
@@ -273,9 +310,18 @@ QuicConnection::QuicConnection(
consecutive_num_packets_with_no_retransmittable_frames_(0),
fill_up_link_during_probing_(false),
probing_retransmission_pending_(false),
+ stateless_reset_token_received_(false),
+ received_stateless_reset_token_(0),
last_control_frame_id_(kInvalidControlFrameId),
- use_control_frame_manager_(
- GetQuicReloadableFlag(quic_use_control_frame_manager)) {
+ negotiate_version_early_(
+ GetQuicReloadableFlag(quic_server_early_version_negotiation)),
+ always_discard_packets_after_close_(
+ GetQuicReloadableFlag(quic_always_discard_packets_after_close)),
+ handle_write_results_for_connectivity_probe_(GetQuicReloadableFlag(
+ quic_handle_write_results_for_connectivity_probe)),
+ use_path_degrading_alarm_(
+ GetQuicReloadableFlag(quic_path_degrading_alarm)),
+ enable_server_proxy_(GetQuicReloadableFlag(quic_enable_server_proxy)) {
QUIC_DLOG(INFO) << ENDPOINT
<< "Created connection with connection_id: " << connection_id
<< " and version: "
@@ -372,6 +418,10 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
config.HasClientSentConnectionOption(kNSTP, perspective_)) {
no_stop_waiting_frames_ = true;
}
+ if (config.HasReceivedStatelessResetToken()) {
+ stateless_reset_token_received_ = true;
+ received_stateless_reset_token_ = config.ReceivedStatelessResetToken();
+ }
}
void QuicConnection::OnSendConnectionState(
@@ -468,7 +518,7 @@ bool QuicConnection::OnProtocolVersionMismatch(
QUIC_BUG << ENDPOINT << error_details;
TearDownLocalConnectionState(QUIC_INTERNAL_ERROR, error_details,
ConnectionCloseSource::FROM_SELF);
- RecordInternalErrorLocation(QUIC_CONNECTION_1);
+ RecordInternalErrorLocation(QUIC_CONNECTION_PROTOCOL_VERSION_MISMATCH);
return false;
}
DCHECK_NE(version(), received_version);
@@ -505,6 +555,7 @@ bool QuicConnection::OnProtocolVersionMismatch(
const bool set_version_early =
GetQuicReloadableFlag(quic_store_version_before_signalling);
if (set_version_early) {
+ QUIC_FLAG_COUNT(quic_reloadable_flag_quic_store_version_before_signalling);
// Store the new version.
framer_.set_version(received_version);
}
@@ -512,8 +563,7 @@ bool QuicConnection::OnProtocolVersionMismatch(
version_negotiation_state_ = NEGOTIATED_VERSION;
visitor_->OnSuccessfulVersionNegotiation(received_version);
if (debug_visitor_ != nullptr) {
- debug_visitor_->OnSuccessfulVersionNegotiation(
- received_version.transport_version);
+ debug_visitor_->OnSuccessfulVersionNegotiation(received_version);
}
QUIC_DLOG(INFO) << ENDPOINT << "version negotiated "
<< ParsedQuicVersionToString(received_version);
@@ -544,7 +594,7 @@ void QuicConnection::OnVersionNegotiationPacket(
QUIC_BUG << error_details;
TearDownLocalConnectionState(QUIC_INTERNAL_ERROR, error_details,
ConnectionCloseSource::FROM_SELF);
- RecordInternalErrorLocation(QUIC_CONNECTION_2);
+ RecordInternalErrorLocation(QUIC_CONNECTION_VERSION_NEGOTIATION_PACKET);
return;
}
if (debug_visitor_ != nullptr) {
@@ -625,7 +675,7 @@ bool QuicConnection::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
QUIC_BUG << error_details;
CloseConnection(QUIC_INTERNAL_ERROR, error_details,
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- RecordInternalErrorLocation(QUIC_CONNECTION_3);
+ RecordInternalErrorLocation(QUIC_CONNECTION_UNAUTHENTICATED_HEADER);
return false;
}
@@ -641,6 +691,31 @@ bool QuicConnection::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
return false;
}
+ if (negotiate_version_early_ &&
+ version_negotiation_state_ != NEGOTIATED_VERSION &&
+ perspective_ == Perspective::IS_SERVER) {
+ QUIC_FLAG_COUNT(quic_reloadable_flag_quic_server_early_version_negotiation);
+ if (!header.version_flag) {
+ // Packets should have the version flag till version negotiation is
+ // done.
+ QuicString error_details =
+ QuicStrCat(ENDPOINT, "Packet ", header.packet_number,
+ " without version flag before version negotiated.");
+ QUIC_DLOG(WARNING) << error_details;
+ CloseConnection(QUIC_INVALID_VERSION, error_details,
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return false;
+ } else {
+ DCHECK_EQ(header.version, version());
+ version_negotiation_state_ = NEGOTIATED_VERSION;
+ visitor_->OnSuccessfulVersionNegotiation(version());
+ if (debug_visitor_ != nullptr) {
+ debug_visitor_->OnSuccessfulVersionNegotiation(version());
+ }
+ }
+ DCHECK_EQ(NEGOTIATED_VERSION, version_negotiation_state_);
+ }
+
return true;
}
@@ -656,6 +731,14 @@ void QuicConnection::OnDecryptedPacket(EncryptionLevel level) {
}
}
+QuicSocketAddress QuicConnection::GetEffectivePeerAddressFromCurrentPacket()
+ const {
+ DCHECK(enable_server_proxy_);
+ // By default, the connection is not proxied, and the effective peer address
+ // is the packet's source address, i.e. the direct peer address.
+ return last_packet_source_address_;
+}
+
bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
if (debug_visitor_ != nullptr) {
debug_visitor_->OnPacketHeader(header);
@@ -670,26 +753,68 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
// Initialize the current packet content stats.
current_packet_content_ = NO_FRAMES_RECEIVED;
- current_peer_migration_type_ = NO_CHANGE;
- AddressChangeType peer_migration_type = QuicUtils::DetermineAddressChangeType(
- peer_address_, last_packet_source_address_);
-
- // Initiate connection migration if a non-reordered packet is received from a
- // new address.
- if (header.packet_number > received_packet_manager_.GetLargestObserved() &&
- peer_migration_type != NO_CHANGE) {
- QUIC_DLOG(INFO) << ENDPOINT << "Peer's ip:port changed from "
- << peer_address_.ToString() << " to "
- << last_packet_source_address_.ToString();
- if (perspective_ == Perspective::IS_CLIENT) {
- peer_address_ = last_packet_source_address_;
- } else if (active_peer_migration_type_ == NO_CHANGE) {
- // Only migrate connection to a new peer address if there is no
- // pending change underway.
- // Cache the current migration change type, which will start peer
- // migration immediately if this packet is not a connectivity probing
- // packet.
- current_peer_migration_type_ = peer_migration_type;
+ is_current_packet_connectivity_probing_ = false;
+
+ if (!enable_server_proxy_) {
+ current_peer_migration_type_ = NO_CHANGE;
+
+ AddressChangeType peer_migration_type =
+ QuicUtils::DetermineAddressChangeType(peer_address_,
+ last_packet_source_address_);
+ // Initiate connection migration if a non-reordered packet is received from
+ // a new address.
+ if (header.packet_number > received_packet_manager_.GetLargestObserved() &&
+ peer_migration_type != NO_CHANGE) {
+ QUIC_DLOG(INFO) << ENDPOINT << "Peer's ip:port changed from "
+ << peer_address_.ToString() << " to "
+ << last_packet_source_address_.ToString();
+ if (perspective_ == Perspective::IS_CLIENT) {
+ peer_address_ = last_packet_source_address_;
+ } else if (active_peer_migration_type_ == NO_CHANGE) {
+ // Only migrate connection to a new peer address if there is no
+ // pending change underway.
+ // Cache the current migration change type, which will start peer
+ // migration immediately if this packet is not a connectivity probing
+ // packet.
+ current_peer_migration_type_ = peer_migration_type;
+ }
+ }
+ } else {
+ current_effective_peer_migration_type_ = NO_CHANGE;
+ // Initiate connection migration if a non-reordered packet is received from
+ // a new address.
+ if (header.packet_number > received_packet_manager_.GetLargestObserved()) {
+ if (perspective_ == Perspective::IS_CLIENT) {
+ // Update peer_address_ and effective_peer_address_ immediately for
+ // client connections.
+ direct_peer_address_ = last_packet_source_address_;
+ effective_peer_address_ = GetEffectivePeerAddressFromCurrentPacket();
+ } else {
+ // At server, direct_peer_address_ and effective_peer_address_ will be
+ // updated once the current packet is confirmed to be not a connectivity
+ // probing packet.
+ AddressChangeType effective_peer_migration_type =
+ QuicUtils::DetermineAddressChangeType(
+ effective_peer_address_,
+ GetEffectivePeerAddressFromCurrentPacket());
+
+ if (effective_peer_migration_type != NO_CHANGE) {
+ QUIC_DLOG(INFO)
+ << ENDPOINT << "Effective peer's ip:port changed from "
+ << effective_peer_address_.ToString() << " to "
+ << GetEffectivePeerAddressFromCurrentPacket().ToString()
+ << ", active_effective_peer_migration_type is "
+ << active_effective_peer_migration_type_;
+ if (active_effective_peer_migration_type_ == NO_CHANGE) {
+ // Only migrate connection to a new effective peer address if there
+ // is no pending change underway. Cache the current migration change
+ // type, which will start effective peer migration immediately if
+ // this packet is not a connectivity probing packet.
+ current_effective_peer_migration_type_ =
+ effective_peer_migration_type;
+ }
+ }
+ }
}
}
@@ -772,9 +897,14 @@ bool QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
if (send_alarm_->IsSet()) {
send_alarm_->Cancel();
}
+
+ if (LargestAcked(incoming_ack) > sent_packet_manager_.GetLargestObserved()) {
+ visitor_->OnForwardProgressConfirmed();
+ }
+
largest_seen_packet_with_ack_ = last_header_.packet_number;
- sent_packet_manager_.OnIncomingAck(incoming_ack,
- time_of_last_received_packet_);
+ bool acked_new_packet = sent_packet_manager_.OnIncomingAck(
+ incoming_ack, time_of_last_received_packet_);
// If the incoming ack's packets set expresses missing packets: peer is still
// waiting for a packet lower than a packet that we are no longer planning to
// send.
@@ -782,7 +912,8 @@ bool QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
// acking packets which we never care about.
// Send an ack to raise the high water mark.
PostProcessAfterAckFrame(!incoming_ack.packets.Empty() &&
- GetLeastUnacked() > incoming_ack.packets.Min());
+ GetLeastUnacked() > incoming_ack.packets.Min(),
+ acked_new_packet);
return connected_;
}
@@ -814,7 +945,9 @@ bool QuicConnection::OnAckFrameStart(QuicPacketNumber largest_acked,
return false;
}
- if (largest_acked < sent_packet_manager_.GetLargestObserved()) {
+ if (largest_acked > sent_packet_manager_.GetLargestObserved()) {
+ visitor_->OnForwardProgressConfirmed();
+ } else if (largest_acked < sent_packet_manager_.GetLargestObserved()) {
QUIC_LOG(INFO) << ENDPOINT << "Peer's largest_observed packet decreased:"
<< largest_acked << " vs "
<< sent_packet_manager_.GetLargestObserved()
@@ -828,7 +961,8 @@ bool QuicConnection::OnAckFrameStart(QuicPacketNumber largest_acked,
return false;
}
- sent_packet_manager_.OnAckFrameStart(largest_acked, ack_delay_time);
+ sent_packet_manager_.OnAckFrameStart(largest_acked, ack_delay_time,
+ time_of_last_received_packet_);
return true;
}
@@ -845,11 +979,12 @@ bool QuicConnection::OnAckRange(QuicPacketNumber start,
return true;
}
- sent_packet_manager_.OnAckRange(start, end, last_range,
- time_of_last_received_packet_);
+ sent_packet_manager_.OnAckRange(start, end);
if (!last_range) {
return true;
}
+ bool acked_new_packet =
+ sent_packet_manager_.OnAckFrameEnd(time_of_last_received_packet_);
if (send_alarm_->IsSet()) {
send_alarm_->Cancel();
}
@@ -860,7 +995,7 @@ bool QuicConnection::OnAckRange(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);
+ PostProcessAfterAckFrame(GetLeastUnacked() > start, acked_new_packet);
return connected_;
}
@@ -1109,10 +1244,27 @@ void QuicConnection::OnPacketComplete() {
<< last_packet_destination_address_.ToString();
visitor_->OnConnectivityProbeReceived(last_packet_destination_address_,
last_packet_source_address_);
- } else if (current_peer_migration_type_ != NO_CHANGE) {
- StartPeerMigration(current_peer_migration_type_);
+ } else {
+ if (!enable_server_proxy_) {
+ if (current_peer_migration_type_ != NO_CHANGE) {
+ StartPeerMigration(current_peer_migration_type_);
+ }
+ } else {
+ if (last_header_.packet_number ==
+ received_packet_manager_.GetLargestObserved()) {
+ direct_peer_address_ = last_packet_source_address_;
+ }
+ if (current_effective_peer_migration_type_ != NO_CHANGE) {
+ StartEffectivePeerMigration(current_effective_peer_migration_type_);
+ }
+ }
+ }
+
+ if (!enable_server_proxy_) {
+ current_peer_migration_type_ = NO_CHANGE;
+ } else {
+ current_effective_peer_migration_type_ = NO_CHANGE;
}
- current_peer_migration_type_ = NO_CHANGE;
// An ack will be sent if a missing retransmittable packet was received;
const bool was_missing =
@@ -1128,6 +1280,20 @@ void QuicConnection::OnPacketComplete() {
CloseIfTooManyOutstandingSentPackets();
}
+bool QuicConnection::IsValidStatelessResetToken(uint128 token) const {
+ return stateless_reset_token_received_ &&
+ token == received_stateless_reset_token_;
+}
+
+void QuicConnection::OnAuthenticatedIetfStatelessResetPacket(
+ const QuicIetfStatelessResetPacket& packet) {
+ // TODO(fayang): Add OnAuthenticatedIetfStatelessResetPacket to
+ // debug_visitor_.
+ const std::string error_details = "Received stateless reset.";
+ TearDownLocalConnectionState(QUIC_PUBLIC_RESET, error_details,
+ ConnectionCloseSource::FROM_PEER);
+}
+
void QuicConnection::MaybeQueueAck(bool was_missing) {
++num_packets_received_since_last_ack_sent_;
// Always send an ack every 20 packets in order to allow the peer to discard
@@ -1202,11 +1368,6 @@ void QuicConnection::ClearLastFrames() {
}
void QuicConnection::CloseIfTooManyOutstandingSentPackets() {
- if (!GetQuicReloadableFlag(
- quic_close_session_on_too_many_outstanding_sent_packets)) {
- return;
- }
-
// This occurs if we don't discard old packets we've seen fast enough. It's
// possible largest observed is less than leaset unacked.
if (sent_packet_manager_.GetLargestObserved() >
@@ -1253,15 +1414,15 @@ void QuicConnection::SendVersionNegotiationPacket() {
QUIC_DLOG(INFO) << ENDPOINT << "Sending version negotiation packet: {"
<< ParsedQuicVersionVectorToString(
framer_.supported_versions())
- << "}";
+ << "}, ietf_quic: " << framer_.last_packet_is_ietf_quic();
std::unique_ptr<QuicEncryptedPacket> version_packet(
packet_generator_.SerializeVersionNegotiationPacket(
- framer_.supported_versions()));
+ framer_.last_packet_is_ietf_quic(), framer_.supported_versions()));
WriteResult result = writer_->WritePacket(
version_packet->data(), version_packet->length(), self_address().host(),
peer_address(), per_packet_options_);
- if (result.status == WRITE_STATUS_ERROR) {
+ if (IsWriteError(result.status)) {
OnWriteError(result.error_code);
return;
}
@@ -1296,7 +1457,6 @@ QuicConsumedData QuicConnection::SendStreamData(QuicStreamId id,
}
bool QuicConnection::SendControlFrame(const QuicFrame& frame) {
- DCHECK(use_control_frame_manager_);
if (!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.
@@ -1317,18 +1477,6 @@ bool QuicConnection::SendControlFrame(const QuicFrame& frame) {
return true;
}
-void QuicConnection::SendRstStream(QuicStreamId id,
- QuicRstStreamErrorCode error,
- QuicStreamOffset bytes_written) {
- DCHECK(!use_control_frame_manager_);
- // Opportunistically bundle an ack with this outgoing packet.
- ScopedPacketFlusher flusher(this, SEND_ACK_IF_PENDING);
- packet_generator_.AddControlFrame(QuicFrame(new QuicRstStreamFrame(
- ++last_control_frame_id_, id, error, bytes_written)));
-
- OnStreamReset(id, error);
-}
-
void QuicConnection::OnStreamReset(QuicStreamId id,
QuicRstStreamErrorCode error) {
if (error == QUIC_STREAM_NO_ERROR) {
@@ -1366,24 +1514,6 @@ void QuicConnection::OnStreamReset(QuicStreamId id,
// cancelled as well.
}
-void QuicConnection::SendWindowUpdate(QuicStreamId id,
- QuicStreamOffset byte_offset) {
- DCHECK(!use_control_frame_manager_);
- // Opportunistically bundle an ack with this outgoing packet.
- ScopedPacketFlusher flusher(this, SEND_ACK_IF_PENDING);
- packet_generator_.AddControlFrame(QuicFrame(
- new QuicWindowUpdateFrame(++last_control_frame_id_, id, byte_offset)));
-}
-
-void QuicConnection::SendBlocked(QuicStreamId id) {
- DCHECK(!use_control_frame_manager_);
- // Opportunistically bundle an ack with this outgoing packet.
- ScopedPacketFlusher flusher(this, SEND_ACK_IF_PENDING);
- packet_generator_.AddControlFrame(
- QuicFrame(new QuicBlockedFrame(++last_control_frame_id_, id)));
- stats_.blocked_frames_sent++;
-}
-
const QuicConnectionStats& QuicConnection::GetStats() {
const RttStats* rtt_stats = sent_packet_manager_.GetRttStats();
@@ -1421,14 +1551,34 @@ void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address,
if (!self_address_.IsInitialized()) {
self_address_ = last_packet_destination_address_;
}
- if (!peer_address_.IsInitialized()) {
- peer_address_ = last_packet_source_address_;
+
+ if (!enable_server_proxy_) {
+ if (!peer_address_.IsInitialized()) {
+ peer_address_ = last_packet_source_address_;
+ }
+ } else {
+ if (!direct_peer_address_.IsInitialized()) {
+ direct_peer_address_ = last_packet_source_address_;
+ }
+
+ if (!effective_peer_address_.IsInitialized()) {
+ QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_enable_server_proxy, 1, 3);
+ const QuicSocketAddress effective_peer_addr =
+ GetEffectivePeerAddressFromCurrentPacket();
+
+ // effective_peer_address_ must be initialized at the beginning of the
+ // first packet processed(here). If effective_peer_addr is uninitialized,
+ // just set effective_peer_address_ to the direct peer address.
+ effective_peer_address_ = effective_peer_addr.IsInitialized()
+ ? effective_peer_addr
+ : direct_peer_address_;
+ }
}
stats_.bytes_received += packet.length();
++stats_.packets_received;
- // Ensure the time coming from the packet reader is within a minute of now.
+ // Ensure the time coming from the packet reader is within 2 minutes of now.
if (std::abs((packet.receipt_time() - clock_->ApproximateNow()).ToSeconds()) >
2 * 60) {
QUIC_BUG << "Packet receipt time:"
@@ -1460,11 +1610,26 @@ void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address,
}
++stats_.packets_processed;
- if (active_peer_migration_type_ != NO_CHANGE &&
- sent_packet_manager_.GetLargestObserved() >
- highest_packet_sent_before_peer_migration_) {
- if (perspective_ == Perspective::IS_SERVER) {
- OnPeerMigrationValidated();
+ if (!enable_server_proxy_) {
+ if (active_peer_migration_type_ != NO_CHANGE &&
+ sent_packet_manager_.GetLargestObserved() >
+ highest_packet_sent_before_peer_migration_) {
+ if (perspective_ == Perspective::IS_SERVER) {
+ OnPeerMigrationValidated();
+ }
+ }
+ } else {
+ QUIC_DLOG_IF(INFO, active_effective_peer_migration_type_ != NO_CHANGE)
+ << "sent_packet_manager_.GetLargestObserved() = "
+ << sent_packet_manager_.GetLargestObserved()
+ << ", highest_packet_sent_before_effective_peer_migration_ = "
+ << highest_packet_sent_before_effective_peer_migration_;
+ if (active_effective_peer_migration_type_ != NO_CHANGE &&
+ sent_packet_manager_.GetLargestObserved() >
+ highest_packet_sent_before_effective_peer_migration_) {
+ if (perspective_ == Perspective::IS_SERVER) {
+ OnEffectivePeerMigrationValidated();
+ }
}
}
MaybeProcessUndecryptablePackets();
@@ -1480,6 +1645,14 @@ void QuicConnection::OnBlockedWriterCanWrite() {
void QuicConnection::OnCanWrite() {
DCHECK(!writer_->IsWriteBlocked());
+ // TODO(wub): Deprecate this histogram once crbug.com/818040 is fixed.
+ if (!queued_packets_.empty() &&
+ queued_packets_.front().packet_number <
+ sent_packet_manager_.GetLargestSentPacket()) {
+ UMA_HISTOGRAM_BOOLEAN(
+ "Net.QuicSession.WriteOutOfOrderQueuedPacketAfterClose", !connected_);
+ }
+
WriteQueuedPackets();
if (!session_decides_what_to_write()) {
WritePendingRetransmissions();
@@ -1519,7 +1692,14 @@ void QuicConnection::WriteIfNotBlocked() {
void QuicConnection::WriteAndBundleAcksIfNotBlocked() {
if (!writer_->IsWriteBlocked()) {
ScopedPacketFlusher flusher(this, SEND_ACK_IF_QUEUED);
- OnCanWrite();
+ if (GetQuicReloadableFlag(quic_is_write_blocked)) {
+ // TODO(ianswett): Merge OnCanWrite and WriteIfNotBlocked when deprecating
+ // this flag.
+ QUIC_FLAG_COUNT(quic_reloadable_flag_quic_is_write_blocked);
+ WriteIfNotBlocked();
+ } else {
+ OnCanWrite();
+ }
}
}
@@ -1592,7 +1772,17 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
}
if (version_negotiation_state_ != NEGOTIATED_VERSION) {
- if (perspective_ == Perspective::IS_SERVER) {
+ if (perspective_ == Perspective::IS_CLIENT) {
+ DCHECK(!header.version_flag);
+ // If the client gets a packet without the version flag from the server
+ // it should stop sending version since the version negotiation is done.
+ packet_generator_.StopSendingVersion();
+ version_negotiation_state_ = NEGOTIATED_VERSION;
+ visitor_->OnSuccessfulVersionNegotiation(version());
+ if (debug_visitor_ != nullptr) {
+ debug_visitor_->OnSuccessfulVersionNegotiation(version());
+ }
+ } else if (!negotiate_version_early_) {
if (!header.version_flag) {
// Packets should have the version flag till version negotiation is
// done.
@@ -1608,24 +1798,12 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
version_negotiation_state_ = NEGOTIATED_VERSION;
visitor_->OnSuccessfulVersionNegotiation(version());
if (debug_visitor_ != nullptr) {
- debug_visitor_->OnSuccessfulVersionNegotiation(transport_version());
+ debug_visitor_->OnSuccessfulVersionNegotiation(version());
}
}
- } else {
- DCHECK(!header.version_flag);
- // If the client gets a packet without the version flag from the server
- // it should stop sending version since the version negotiation is done.
- packet_generator_.StopSendingVersion();
- version_negotiation_state_ = NEGOTIATED_VERSION;
- visitor_->OnSuccessfulVersionNegotiation(version());
- if (debug_visitor_ != nullptr) {
- debug_visitor_->OnSuccessfulVersionNegotiation(transport_version());
- }
}
}
- DCHECK_EQ(NEGOTIATED_VERSION, version_negotiation_state_);
-
if (last_size_ > largest_received_packet_size_) {
largest_received_packet_size_ = last_size_;
}
@@ -1647,12 +1825,42 @@ void QuicConnection::WriteQueuedPackets() {
UMA_HISTOGRAM_COUNTS_1000("Net.QuicSession.NumQueuedPacketsBeforeWrite",
queued_packets_.size());
- QueuedPacketList::iterator packet_iterator = queued_packets_.begin();
- while (packet_iterator != queued_packets_.end() &&
- WritePacket(&(*packet_iterator))) {
- delete[] packet_iterator->encrypted_buffer;
- ClearSerializedPacket(&(*packet_iterator));
- packet_iterator = queued_packets_.erase(packet_iterator);
+ if (GetQuicReloadableFlag(quic_fix_write_out_of_order_queued_packet_crash)) {
+ while (!queued_packets_.empty()) {
+ QUIC_FLAG_COUNT(
+ quic_reloadable_flag_quic_fix_write_out_of_order_queued_packet_crash);
+ // WritePacket() can potentially clear all queued packets, so we need to
+ // save the first queued packet to a local variable before calling it.
+ SerializedPacket packet(std::move(queued_packets_.front()));
+ queued_packets_.pop_front();
+
+ const bool write_result = WritePacket(&packet);
+
+ if (connected_ && !write_result) {
+ // Write failed but connection is open, re-insert |packet| into the
+ // front of the queue, it will be retried later.
+ queued_packets_.emplace_front(std::move(packet));
+ break;
+ }
+
+ delete[] packet.encrypted_buffer;
+ ClearSerializedPacket(&packet);
+ if (!connected_) {
+ DCHECK(queued_packets_.empty()) << "Queued packets should have been "
+ "cleared while closing connection";
+ break;
+ }
+
+ // Continue to send the next packet in queue.
+ }
+ } else {
+ QueuedPacketList::iterator packet_iterator = queued_packets_.begin();
+ while (packet_iterator != queued_packets_.end() &&
+ WritePacket(&(*packet_iterator))) {
+ delete[] packet_iterator->encrypted_buffer;
+ ClearSerializedPacket(&(*packet_iterator));
+ packet_iterator = queued_packets_.erase(packet_iterator);
+ }
}
}
@@ -1771,19 +1979,23 @@ bool QuicConnection::CanWrite(HasRetransmittableData retransmittable) {
}
bool QuicConnection::WritePacket(SerializedPacket* packet) {
+ if (always_discard_packets_after_close_ && ShouldDiscardPacket(*packet)) {
+ QUIC_FLAG_COUNT_N(
+ quic_reloadable_flag_quic_always_discard_packets_after_close, 1, 2);
+ ++stats_.packets_discarded;
+ return true;
+ }
if (packet->packet_number < sent_packet_manager_.GetLargestSentPacket()) {
QUIC_BUG << "Attempt to write packet:" << packet->packet_number
<< " after:" << sent_packet_manager_.GetLargestSentPacket();
- CloseConnection(QUIC_INTERNAL_ERROR, "Packet written out of order.",
- ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
-
UMA_HISTOGRAM_COUNTS_1000("Net.QuicSession.NumQueuedPacketsAtOutOfOrder",
queued_packets_.size());
-
- RecordInternalErrorLocation(QUIC_CONNECTION_4);
+ CloseConnection(QUIC_INTERNAL_ERROR, "Packet written out of order.",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ RecordInternalErrorLocation(QUIC_CONNECTION_WRITE_PACKET);
return true;
}
- if (ShouldDiscardPacket(*packet)) {
+ if (!always_discard_packets_after_close_ && ShouldDiscardPacket(*packet)) {
++stats_.packets_discarded;
return true;
}
@@ -1805,8 +2017,8 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
}
// Copy the buffer so it's owned in the future.
char* buffer_copy = CopyBuffer(*packet);
- termination_packets_->push_back(std::unique_ptr<QuicEncryptedPacket>(
- new QuicEncryptedPacket(buffer_copy, encrypted_length, true)));
+ termination_packets_->emplace_back(
+ new QuicEncryptedPacket(buffer_copy, encrypted_length, true));
// This assures we won't try to write *forced* packets when blocked.
// Return true to stop processing.
if (writer_->IsWriteBlocked()) {
@@ -1855,9 +2067,7 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
// In some cases, an MTU probe can cause EMSGSIZE. This indicates that the
// MTU discovery is permanently unsuccessful.
- if (result.status == WRITE_STATUS_ERROR &&
- result.error_code == kMessageTooBigErrorCode &&
- packet->retransmittable_frames.empty() &&
+ if (IsMsgTooBig(result) && packet->retransmittable_frames.empty() &&
packet->encrypted_length > long_term_mtu_) {
mtu_discovery_target_ = 0;
mtu_discovery_alarm_->Cancel();
@@ -1865,7 +2075,7 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
return true;
}
- if (result.status == WRITE_STATUS_ERROR) {
+ if (IsWriteError(result.status)) {
OnWriteError(result.error_code);
QUIC_LOG_FIRST_N(ERROR, 10)
<< ENDPOINT << "failed writing " << encrypted_length
@@ -1875,18 +2085,30 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
return false;
}
- if (result.status != WRITE_STATUS_ERROR && debug_visitor_ != nullptr) {
+ if (debug_visitor_ != nullptr) {
// Pass the write result to the visitor.
debug_visitor_->OnPacketSent(*packet, packet->original_packet_number,
packet->transmission_type, packet_send_time);
}
- // Only adjust the last sent time (for the purpose of tracking the idle
- // timeout) if this is the first retransmittable packet sent after a
- // packet is received. If it were updated on every sent packet, then
- // sending into a black hole might never timeout.
- if (IsRetransmittable(*packet) == HAS_RETRANSMITTABLE_DATA &&
- last_send_for_timeout_ <= time_of_last_received_packet_) {
- last_send_for_timeout_ = packet_send_time;
+ if (IsRetransmittable(*packet) == HAS_RETRANSMITTABLE_DATA) {
+ // A retransmittable packet has been put on the wire, so no need for the
+ // |retransmittable_on_wire_alarm_| to possibly send a PING.
+ retransmittable_on_wire_alarm_->Cancel();
+ if (use_path_degrading_alarm_) {
+ if (!path_degrading_alarm_->IsSet()) {
+ // This is the first retransmittable packet on the wire after having
+ // none on the wire. Start the path degrading alarm.
+ SetPathDegradingAlarm();
+ }
+ }
+
+ // Only adjust the last sent time (for the purpose of tracking the idle
+ // timeout) if this is the first retransmittable packet sent after a
+ // packet is received. If it were updated on every sent packet, then
+ // sending into a black hole might never timeout.
+ if (last_send_for_timeout_ <= time_of_last_received_packet_) {
+ last_send_for_timeout_ = packet_send_time;
+ }
}
SetPingAlarm();
MaybeSetMtuAlarm(packet_number);
@@ -1917,6 +2139,12 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
return true;
}
+bool QuicConnection::IsMsgTooBig(const WriteResult& result) {
+ return (result.status == WRITE_STATUS_MSG_TOO_BIG) ||
+ (IsWriteError(result.status) &&
+ result.error_code == kMessageTooBigErrorCode);
+}
+
bool QuicConnection::ShouldDiscardPacket(const SerializedPacket& packet) {
if (!connected_) {
QUIC_DLOG(INFO) << ENDPOINT
@@ -2010,7 +2238,10 @@ void QuicConnection::OnCongestionChange() {
}
}
+// TODO(b/77267845): remove this method once
+// FLAGS_quic_reloadable_flag_quic_path_degrading_alarm is deprecated.
void QuicConnection::OnPathDegrading() {
+ DCHECK(!use_path_degrading_alarm_);
visitor_->OnPathDegrading();
}
@@ -2050,23 +2281,7 @@ void QuicConnection::SendOrQueuePacket(SerializedPacket* packet) {
void QuicConnection::OnPingTimeout() {
if (!retransmission_alarm_->IsSet()) {
- if (use_control_frame_manager_) {
- visitor_->SendPing();
- } else {
- SendPing();
- }
- }
-}
-
-void QuicConnection::SendPing() {
- DCHECK(!use_control_frame_manager_);
- ScopedPacketFlusher flusher(this, SEND_ACK_IF_QUEUED);
- packet_generator_.AddControlFrame(
- QuicFrame(QuicPingFrame(++last_control_frame_id_)));
- // Send PING frame immediately, without checking for congestion window bounds.
- packet_generator_.FlushAllQueuedFrames();
- if (debug_visitor_ != nullptr) {
- debug_visitor_->OnPingSent();
+ visitor_->SendPing();
}
}
@@ -2090,13 +2305,11 @@ void QuicConnection::SendAck() {
}
visitor_->OnAckNeedsRetransmittableFrame();
- if (!use_control_frame_manager_) {
- if (!packet_generator_.HasRetransmittableFrames()) {
- // Visitor did not add a retransmittable frame, add a ping frame.
- packet_generator_.AddControlFrame(
- QuicFrame(QuicPingFrame(++last_control_frame_id_)));
- }
- }
+}
+
+void QuicConnection::OnPathDegradingTimeout() {
+ QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_path_degrading_alarm, 2, 4);
+ visitor_->OnPathDegrading();
}
void QuicConnection::OnRetransmissionTimeout() {
@@ -2144,8 +2357,8 @@ void QuicConnection::OnRetransmissionTimeout() {
}
void QuicConnection::SetEncrypter(EncryptionLevel level,
- QuicEncrypter* encrypter) {
- packet_generator_.SetEncrypter(level, encrypter);
+ std::unique_ptr<QuicEncrypter> encrypter) {
+ packet_generator_.SetEncrypter(level, std::move(encrypter));
}
void QuicConnection::SetDiversificationNonce(
@@ -2165,14 +2378,15 @@ void QuicConnection::SetDefaultEncryptionLevel(EncryptionLevel level) {
}
void QuicConnection::SetDecrypter(EncryptionLevel level,
- QuicDecrypter* decrypter) {
- framer_.SetDecrypter(level, decrypter);
+ std::unique_ptr<QuicDecrypter> decrypter) {
+ framer_.SetDecrypter(level, std::move(decrypter));
}
-void QuicConnection::SetAlternativeDecrypter(EncryptionLevel level,
- QuicDecrypter* decrypter,
- bool latch_once_used) {
- framer_.SetAlternativeDecrypter(level, decrypter, latch_once_used);
+void QuicConnection::SetAlternativeDecrypter(
+ EncryptionLevel level,
+ std::unique_ptr<QuicDecrypter> decrypter,
+ bool latch_once_used) {
+ framer_.SetAlternativeDecrypter(level, std::move(decrypter), latch_once_used);
}
const QuicDecrypter* QuicConnection::decrypter() const {
@@ -2297,19 +2511,11 @@ void QuicConnection::CancelAllAlarms() {
send_alarm_->Cancel();
timeout_alarm_->Cancel();
mtu_discovery_alarm_->Cancel();
-}
-
-void QuicConnection::SendGoAway(QuicErrorCode error,
- QuicStreamId last_good_stream_id,
- const QuicString& reason) {
- DCHECK(!use_control_frame_manager_);
- QUIC_DLOG(INFO) << ENDPOINT << "Going away with error "
- << QuicErrorCodeToString(error) << " (" << error << ")";
-
- // Opportunistically bundle an ack with this outgoing packet.
- ScopedPacketFlusher flusher(this, SEND_ACK_IF_PENDING);
- packet_generator_.AddControlFrame(QuicFrame(new QuicGoAwayFrame(
- ++last_control_frame_id_, error, last_good_stream_id, reason)));
+ retransmittable_on_wire_alarm_->Cancel();
+ if (use_path_degrading_alarm_) {
+ QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_path_degrading_alarm, 4, 4);
+ path_degrading_alarm_->Cancel();
+ }
}
QuicByteCount QuicConnection::max_packet_length() const {
@@ -2449,6 +2655,14 @@ void QuicConnection::SetRetransmissionAlarm() {
QuicTime::Delta::FromMilliseconds(1));
}
+void QuicConnection::SetPathDegradingAlarm() {
+ DCHECK(use_path_degrading_alarm_);
+ QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_path_degrading_alarm, 1, 4);
+ const QuicTime::Delta delay = sent_packet_manager_.GetPathDegradingDelay();
+ path_degrading_alarm_->Update(clock_->ApproximateNow() + delay,
+ QuicTime::Delta::FromMilliseconds(1));
+}
+
void QuicConnection::MaybeSetMtuAlarm(QuicPacketNumber sent_packet_number) {
// Do not set the alarm if the target size is less than the current size.
// This covers the case when |mtu_discovery_target_| is at its default value,
@@ -2637,9 +2851,13 @@ bool QuicConnection::SendConnectivityProbingPacket(
QuicPacketWriter* probing_writer,
const QuicSocketAddress& peer_address) {
DCHECK(peer_address.IsInitialized());
- // TODO(zhongyi): remove this histogram once the cause of the INTERNAL_ERROR
- // increase is determined.
- UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.SentConnectivityProbe", true);
+ if (always_discard_packets_after_close_ && !connected_) {
+ QUIC_FLAG_COUNT_N(
+ quic_reloadable_flag_quic_always_discard_packets_after_close, 2, 2);
+ QUIC_BUG << "Not sending connectivity probing packet as connection is "
+ << "disconnected.";
+ return false;
+ }
if (perspective_ == Perspective::IS_SERVER && probing_writer == nullptr) {
// Server can use default packet writer to write probing packet.
probing_writer = writer_;
@@ -2647,10 +2865,31 @@ bool QuicConnection::SendConnectivityProbingPacket(
DCHECK(probing_writer);
if (probing_writer->IsWriteBlocked()) {
- QUIC_DLOG(INFO) << "Writer blocked when send connectivity probing packet";
+ QUIC_DLOG(INFO) << ENDPOINT
+ << "Writer blocked when send connectivity probing packet.";
+ if (!handle_write_results_for_connectivity_probe_) {
+ visitor_->OnWriteBlocked();
+ } else {
+ QUIC_FLAG_COUNT_N(
+ quic_reloadable_flag_quic_handle_write_results_for_connectivity_probe,
+ 1, 3);
+ if (probing_writer == writer_) {
+ // Visitor should not be write blocked if the probing writer is not the
+ // default packet writer.
+ visitor_->OnWriteBlocked();
+ }
+ }
return true;
}
+ if (GetQuicReloadableFlag(quic_fix_write_out_of_order_queued_packet_crash) &&
+ GetQuicReloadableFlag(
+ quic_clear_queued_packets_before_sending_connectivity_probing)) {
+ QUIC_FLAG_COUNT(
+ quic_reloadable_flag_quic_clear_queued_packets_before_sending_connectivity_probing); // NOLINT
+ ClearQueuedPackets();
+ }
+
QUIC_DLOG(INFO) << ENDPOINT << "Sending connectivity probing packet for "
<< "connection_id = " << connection_id_;
@@ -2663,23 +2902,42 @@ bool QuicConnection::SendConnectivityProbingPacket(
probing_packet->encrypted_buffer, probing_packet->encrypted_length,
self_address().host(), peer_address, per_packet_options_);
- if (result.status == WRITE_STATUS_ERROR) {
- QUIC_DLOG(INFO) << "Write probing packet not finished with error = "
+ if (IsWriteError(result.status)) {
+ if (!handle_write_results_for_connectivity_probe_) {
+ OnWriteError(result.error_code);
+ } else {
+ QUIC_FLAG_COUNT_N(
+ quic_reloadable_flag_quic_handle_write_results_for_connectivity_probe,
+ 2, 3);
+ // Write error for any connectivity probe should not affect the connection
+ // as it is sent on a different path.
+ }
+ QUIC_DLOG(INFO) << ENDPOINT << "Write probing packet failed with error = "
<< result.error_code;
return false;
}
- // Call OnPacketSent regardless of the write result. This treats a blocked
- // write the same as a packet loss.
+ // Call OnPacketSent regardless of the write result.
sent_packet_manager_.OnPacketSent(
probing_packet.get(), probing_packet->original_packet_number,
packet_send_time, probing_packet->transmission_type,
NO_RETRANSMITTABLE_DATA);
if (result.status == WRITE_STATUS_BLOCKED) {
- visitor_->OnWriteBlocked();
+ if (!handle_write_results_for_connectivity_probe_) {
+ visitor_->OnWriteBlocked();
+ } else {
+ QUIC_FLAG_COUNT_N(
+ quic_reloadable_flag_quic_handle_write_results_for_connectivity_probe,
+ 3, 3);
+ if (probing_writer == writer_) {
+ // Visitor should not be write blocked if the probing writer is not the
+ // default packet writer.
+ visitor_->OnWriteBlocked();
+ }
+ }
if (probing_writer->IsWriteBlockedDataBuffered()) {
- QUIC_BUG << "Write probing packet blocked";
+ QUIC_DLOG(INFO) << ENDPOINT << "Write probing packet blocked";
}
}
@@ -2710,6 +2968,7 @@ void QuicConnection::DiscoverMtu() {
}
void QuicConnection::OnPeerMigrationValidated() {
+ DCHECK(!enable_server_proxy_);
if (active_peer_migration_type_ == NO_CHANGE) {
QUIC_BUG << "No migration underway.";
return;
@@ -2723,6 +2982,7 @@ void QuicConnection::OnPeerMigrationValidated() {
// migration. This should happen even if a migration is underway, since the
// most recent migration is the one that we should pay attention to.
void QuicConnection::StartPeerMigration(AddressChangeType peer_migration_type) {
+ DCHECK(!enable_server_proxy_);
// TODO(fayang): Currently, all peer address change type are allowed. Need to
// add a method ShouldAllowPeerAddressChange(PeerAddressChangeType type) to
// determine whether |type| is allowed.
@@ -2746,12 +3006,55 @@ void QuicConnection::StartPeerMigration(AddressChangeType peer_migration_type) {
OnConnectionMigration(peer_migration_type);
}
+void QuicConnection::OnEffectivePeerMigrationValidated() {
+ DCHECK(enable_server_proxy_);
+ QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_enable_server_proxy, 3, 3);
+ if (active_effective_peer_migration_type_ == NO_CHANGE) {
+ QUIC_BUG << "No migration underway.";
+ return;
+ }
+ highest_packet_sent_before_effective_peer_migration_ = 0;
+ active_effective_peer_migration_type_ = NO_CHANGE;
+}
+
+// TODO(wub): Modify method to start migration whenever a new IP address is seen
+// from a packet with sequence number > the one that triggered the previous
+// migration. This should happen even if a migration is underway, since the
+// most recent migration is the one that we should pay attention to.
+void QuicConnection::StartEffectivePeerMigration(AddressChangeType type) {
+ DCHECK(enable_server_proxy_);
+ QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_enable_server_proxy, 2, 3);
+ // TODO(fayang): Currently, all peer address change type are allowed. Need to
+ // add a method ShouldAllowPeerAddressChange(PeerAddressChangeType type) to
+ // determine whether |type| is allowed.
+ if (active_effective_peer_migration_type_ != NO_CHANGE || type == NO_CHANGE) {
+ QUIC_BUG << "Migration underway or no new migration started.";
+ return;
+ }
+ QUIC_DLOG(INFO) << ENDPOINT << "Effective peer's ip:port changed from "
+ << effective_peer_address_.ToString() << " to "
+ << GetEffectivePeerAddressFromCurrentPacket().ToString()
+ << ", migrating connection.";
+
+ highest_packet_sent_before_effective_peer_migration_ =
+ sent_packet_manager_.GetLargestSentPacket();
+ effective_peer_address_ = GetEffectivePeerAddressFromCurrentPacket();
+ active_effective_peer_migration_type_ = type;
+
+ // TODO(wub): Move these calls to OnEffectivePeerMigrationValidated.
+ OnConnectionMigration(type);
+}
+
void QuicConnection::OnConnectionMigration(AddressChangeType addr_change_type) {
visitor_->OnConnectionMigration(addr_change_type);
sent_packet_manager_.OnConnectionMigration(addr_change_type);
}
bool QuicConnection::IsCurrentPacketConnectivityProbing() const {
+ if (enable_server_proxy_) {
+ return is_current_packet_connectivity_probing_;
+ }
+
if (current_packet_content_ != SECOND_FRAME_IS_PADDING) {
return false;
}
@@ -2798,7 +3101,8 @@ bool QuicConnection::MaybeConsiderAsMemoryCorruption(
void QuicConnection::MaybeSendProbingRetransmissions() {
DCHECK(fill_up_link_during_probing_);
- if (!sent_packet_manager_.handshake_confirmed()) {
+ if (!sent_packet_manager_.handshake_confirmed() ||
+ sent_packet_manager().HasUnackedCryptoPackets()) {
return;
}
@@ -2863,35 +3167,59 @@ void QuicConnection::UpdatePacketContent(PacketContent type) {
if (type == SECOND_FRAME_IS_PADDING) {
if (current_packet_content_ == FIRST_FRAME_IS_PING) {
current_packet_content_ = SECOND_FRAME_IS_PADDING;
+ if (enable_server_proxy_) {
+ if (perspective_ == Perspective::IS_SERVER) {
+ is_current_packet_connectivity_probing_ =
+ current_effective_peer_migration_type_ != NO_CHANGE;
+ } else {
+ is_current_packet_connectivity_probing_ =
+ (last_packet_source_address_ != peer_address_) ||
+ (last_packet_destination_address_ != self_address_);
+ }
+ }
return;
}
}
current_packet_content_ = NOT_PADDED_PING;
- if (current_peer_migration_type_ == NO_CHANGE) {
- return;
- }
+ if (!enable_server_proxy_) {
+ if (current_peer_migration_type_ == NO_CHANGE) {
+ return;
+ }
+
+ // Start peer migration immediately when the current packet is confirmed not
+ // a connectivity probing packet.
+ StartPeerMigration(current_peer_migration_type_);
+ current_peer_migration_type_ = NO_CHANGE;
+ } else {
+ if (last_header_.packet_number ==
+ received_packet_manager_.GetLargestObserved()) {
+ direct_peer_address_ = last_packet_source_address_;
+ }
+ if (current_effective_peer_migration_type_ == NO_CHANGE) {
+ return;
+ }
- // Start peer migration immediately when the current packet is confirmed not
- // a connectivity probing packet.
- StartPeerMigration(current_peer_migration_type_);
- current_peer_migration_type_ = NO_CHANGE;
+ // Start effective peer migration immediately when the current packet is
+ // confirmed not a connectivity probing packet.
+ StartEffectivePeerMigration(current_effective_peer_migration_type_);
+ current_effective_peer_migration_type_ = NO_CHANGE;
+ }
}
void QuicConnection::MaybeEnableSessionDecidesWhatToWrite() {
// Only enable session decides what to write code path for version 42+,
// because it needs the receiver to allow receiving overlapping stream data.
const bool enable_session_decides_what_to_write =
- transport_version() > QUIC_VERSION_41 &&
- GetQuicReloadableFlag(quic_streams_unblocked_by_session2) &&
- use_control_frame_manager_;
+ transport_version() > QUIC_VERSION_41;
sent_packet_manager_.SetSessionDecideWhatToWrite(
enable_session_decides_what_to_write);
packet_generator_.SetCanSetTransmissionType(
enable_session_decides_what_to_write);
}
-void QuicConnection::PostProcessAfterAckFrame(bool send_stop_waiting) {
+void QuicConnection::PostProcessAfterAckFrame(bool send_stop_waiting,
+ bool acked_new_packet) {
if (no_stop_waiting_frames_) {
received_packet_manager_.DontWaitForPacketsBefore(
sent_packet_manager_.largest_packet_peer_knows_is_acked());
@@ -2900,6 +3228,26 @@ void QuicConnection::PostProcessAfterAckFrame(bool send_stop_waiting) {
// have a better estimate of the current rtt than when it was set.
SetRetransmissionAlarm();
+ if (!sent_packet_manager_.HasUnackedPackets()) {
+ // There are no retransmittable packets on the wire, so it may be
+ // necessary to send a PING to keep a retransmittable packet on the wire.
+ if (!retransmittable_on_wire_alarm_->IsSet()) {
+ SetRetransmittableOnWireAlarm();
+ }
+ // There are no retransmittable packets on the wire, so it's impossible to
+ // say if the connection has degraded.
+ if (use_path_degrading_alarm_) {
+ QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_path_degrading_alarm, 3, 4);
+ path_degrading_alarm_->Cancel();
+ }
+ } else if (acked_new_packet) {
+ // A previously-unacked packet has been acked, which means forward progress
+ // has been made. Push back the path degrading alarm.
+ if (use_path_degrading_alarm_) {
+ SetPathDegradingAlarm();
+ }
+ }
+
if (send_stop_waiting) {
++stop_waiting_count_;
} else {
@@ -2925,4 +3273,22 @@ bool QuicConnection::session_decides_what_to_write() const {
return sent_packet_manager_.session_decides_what_to_write();
}
+void QuicConnection::SetRetransmittableOnWireAlarm() {
+ if (perspective_ == Perspective::IS_SERVER) {
+ // Only clients send pings.
+ return;
+ }
+ if (retransmittable_on_wire_timeout_.IsInfinite()) {
+ return;
+ }
+ if (!visitor_->HasOpenDynamicStreams()) {
+ retransmittable_on_wire_alarm_->Cancel();
+ // Don't send a ping unless there are open streams.
+ return;
+ }
+ retransmittable_on_wire_alarm_->Update(
+ clock_->ApproximateNow() + retransmittable_on_wire_timeout_,
+ QuicTime::Delta::Zero());
+}
+
} // namespace net
diff --git a/chromium/net/quic/core/quic_connection.h b/chromium/net/quic/core/quic_connection.h
index c07480af19c..e62454ee720 100644
--- a/chromium/net/quic/core/quic_connection.h
+++ b/chromium/net/quic/core/quic_connection.h
@@ -25,6 +25,7 @@
#include "base/macros.h"
#include "net/quic/core/crypto/quic_decrypter.h"
+#include "net/quic/core/crypto/quic_encrypter.h"
#include "net/quic/core/proto/cached_network_parameters.pb.h"
#include "net/quic/core/quic_alarm.h"
#include "net/quic/core/quic_alarm_factory.h"
@@ -51,8 +52,6 @@ namespace net {
class QuicClock;
class QuicConfig;
class QuicConnection;
-class QuicDecrypter;
-class QuicEncrypter;
class QuicRandom;
namespace test {
@@ -172,6 +171,10 @@ class QUIC_EXPORT_PRIVATE QuicConnectionVisitorInterface {
// Called when a self address change is observed. Returns true if self address
// change is allowed.
virtual bool AllowSelfAddressChange() const = 0;
+
+ // Called when an ACK is received with a larger |largest_acked| than
+ // previously observed.
+ virtual void OnForwardProgressConfirmed() = 0;
};
// Interface which gets callbacks from the QuicConnection at interesting
@@ -262,7 +265,7 @@ class QUIC_EXPORT_PRIVATE QuicConnectionDebugVisitor
// Called when the version negotiation is successful.
virtual void OnSuccessfulVersionNegotiation(
- const QuicTransportVersion& version) {}
+ const ParsedQuicVersion& version) {}
// Called when a CachedNetworkParameters is sent to the client.
virtual void OnSendConnectionState(
@@ -356,7 +359,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
void AdjustNetworkParameters(QuicBandwidth bandwidth, QuicTime::Delta rtt);
// Returns the max pacing rate for the connection.
- QuicBandwidth MaxPacingRate() const;
+ virtual QuicBandwidth MaxPacingRate() const;
// Sets the number of active streams on the connection for congestion control.
void SetNumOpenStreams(size_t num_streams);
@@ -375,20 +378,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// otherwise.
virtual bool SendControlFrame(const QuicFrame& frame);
- // Send a RST_STREAM frame to the peer.
- virtual void SendRstStream(QuicStreamId id,
- QuicRstStreamErrorCode error,
- QuicStreamOffset bytes_written);
-
// Called when stream |id| is reset because of |error|.
virtual void OnStreamReset(QuicStreamId id, QuicRstStreamErrorCode error);
- // Send a BLOCKED frame to the peer.
- virtual void SendBlocked(QuicStreamId id);
-
- // Send a WINDOW_UPDATE frame to the peer.
- virtual void SendWindowUpdate(QuicStreamId id, QuicStreamOffset byte_offset);
-
// Closes the connection.
// |connection_close_behavior| determines whether or not a connection close
// packet is sent to the peer.
@@ -397,11 +389,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
const QuicString& details,
ConnectionCloseBehavior connection_close_behavior);
- // Sends a GOAWAY frame.
- virtual void SendGoAway(QuicErrorCode error,
- QuicStreamId last_good_stream_id,
- const QuicString& reason);
-
// Returns statistics tracked for this connection.
const QuicConnectionStats& GetStats();
@@ -425,6 +412,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// network.
void OnWriteError(int error_code);
+ // Whether |result| represents a MSG TOO BIG write error.
+ bool IsMsgTooBig(const WriteResult& result);
+
// If the socket is not blocked, writes queued packets.
void WriteIfNotBlocked();
@@ -484,6 +474,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
bool OnBlockedFrame(const QuicBlockedFrame& frame) override;
void OnPacketComplete() override;
+ bool IsValidStatelessResetToken(uint128 token) const override;
+ void OnAuthenticatedIetfStatelessResetPacket(
+ const QuicIetfStatelessResetPacket& packet) override;
// QuicConnectionCloseDelegateInterface
void OnUnrecoverableError(QuicErrorCode error,
@@ -501,6 +494,8 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// QuicSentPacketManager::NetworkChangeVisitor
void OnCongestionChange() override;
+ // TODO(b/76462614): remove OnPathDegrading() once
+ // FLAGS_quic_reloadable_flag_quic_path_degrading_alarm is deprecated.
void OnPathDegrading() override;
void OnPathMtuIncreased(QuicPacketLength packet_size) override;
@@ -525,11 +520,34 @@ class QUIC_EXPORT_PRIVATE QuicConnection
}
const QuicTime::Delta ping_timeout() { return ping_timeout_; }
// Used in Chromium, but not internally.
+ // Must only be called before retransmittable_on_wire_alarm_ is set.
+ void set_retransmittable_on_wire_timeout(
+ QuicTime::Delta retransmittable_on_wire_timeout) {
+ DCHECK(!retransmittable_on_wire_alarm_->IsSet());
+ retransmittable_on_wire_timeout_ = retransmittable_on_wire_timeout;
+ }
+ const QuicTime::Delta retransmittable_on_wire_timeout() {
+ return retransmittable_on_wire_timeout_;
+ }
+ // Used in Chromium, but not internally.
void set_creator_debug_delegate(QuicPacketCreator::DebugDelegate* visitor) {
packet_generator_.set_debug_delegate(visitor);
}
const QuicSocketAddress& self_address() const { return self_address_; }
- const QuicSocketAddress& peer_address() const { return peer_address_; }
+ const QuicSocketAddress& peer_address() const {
+ if (enable_server_proxy_) {
+ return direct_peer_address_;
+ }
+ return peer_address_;
+ }
+ const QuicSocketAddress& effective_peer_address() const {
+ if (enable_server_proxy_) {
+ return effective_peer_address_;
+ }
+ QUIC_BUG << "effective_peer_address() should only be called when "
+ "enable_server_proxy_ is true.";
+ return peer_address_;
+ }
QuicConnectionId connection_id() const { return connection_id_; }
const QuicClock* clock() const { return clock_; }
QuicRandom* random_generator() const { return random_generator_; }
@@ -573,12 +591,12 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// if the retransmission alarm is not running.
void OnPingTimeout();
- // Sends a ping frame.
- void SendPing();
-
// Sets up a packet with an QuicAckFrame and sends it out.
void SendAck();
+ // Called when the path degrading alarm fires.
+ void OnPathDegradingTimeout();
+
// Called when an RTO fires. Resets the retransmission alarm if there are
// remaining unacked packets.
void OnRetransmissionTimeout();
@@ -594,9 +612,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// connection becomes forward secure and hasn't received acks for all packets.
void NeuterUnencryptedPackets();
- // Changes the encrypter used for level |level| to |encrypter|. The function
- // takes ownership of |encrypter|.
- void SetEncrypter(EncryptionLevel level, QuicEncrypter* encrypter);
+ // Changes the encrypter used for level |level| to |encrypter|.
+ void SetEncrypter(EncryptionLevel level,
+ std::unique_ptr<QuicEncrypter> encrypter);
// SetNonceForPublicHeader sets the nonce that will be transmitted in the
// header of each packet encrypted at the initial encryption level decrypted.
@@ -607,21 +625,22 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// to new packets.
void SetDefaultEncryptionLevel(EncryptionLevel level);
- // SetDecrypter sets the primary decrypter, replacing any that already exists,
- // and takes ownership. If an alternative decrypter is in place then the
- // function DCHECKs. This is intended for cases where one knows that future
- // packets will be using the new decrypter and the previous decrypter is now
- // obsolete. |level| indicates the encryption level of the new decrypter.
- void SetDecrypter(EncryptionLevel level, QuicDecrypter* decrypter);
+ // SetDecrypter sets the primary decrypter, replacing any that already exists.
+ // If an alternative decrypter is in place then the function DCHECKs. This is
+ // intended for cases where one knows that future packets will be using the
+ // new decrypter and the previous decrypter is now obsolete. |level| indicates
+ // the encryption level of the new decrypter.
+ void SetDecrypter(EncryptionLevel level,
+ std::unique_ptr<QuicDecrypter> decrypter);
// SetAlternativeDecrypter sets a decrypter that may be used to decrypt
- // future packets and takes ownership of it. |level| indicates the encryption
- // level of the decrypter. If |latch_once_used| is true, then the first time
- // that the decrypter is successful it will replace the primary decrypter.
- // Otherwise both decrypters will remain active and the primary decrypter
- // will be the one last used.
+ // future packets. |level| indicates the encryption level of the decrypter. If
+ // |latch_once_used| is true, then the first time that the decrypter is
+ // successful it will replace the primary decrypter. Otherwise both
+ // decrypters will remain active and the primary decrypter will be the one
+ // last used.
void SetAlternativeDecrypter(EncryptionLevel level,
- QuicDecrypter* decrypter,
+ std::unique_ptr<QuicDecrypter> decrypter,
bool latch_once_used);
const QuicDecrypter* decrypter() const;
@@ -748,10 +767,19 @@ class QUIC_EXPORT_PRIVATE QuicConnection
defer_send_in_response_to_packets_ = defer;
}
- bool use_control_frame_manager() const { return use_control_frame_manager_; }
-
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.
+ void set_per_packet_options(PerPacketOptions* options) {
+ per_packet_options_ = options;
+ }
+
+ bool IsServerProxyEnabled() const { return enable_server_proxy_; }
+
protected:
// Calls cancel() on all the alarms owned by this connection.
void CancelAllAlarms();
@@ -767,6 +795,33 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Called when a peer address migration is validated.
virtual void OnPeerMigrationValidated();
+ // Called after a packet is received from a new effective peer address and is
+ // decrypted. Starts validation of effective peer's address change. Calls
+ // OnConnectionMigration as soon as the address changed.
+ void StartEffectivePeerMigration(AddressChangeType type);
+
+ // Called when a effective peer address migration is validated.
+ virtual void OnEffectivePeerMigrationValidated();
+
+ // Get the effective peer address from the packet being processed. For proxied
+ // connections, effective peer address is the address of the endpoint behind
+ // the proxy. For non-proxied connections, effective peer address is the same
+ // as peer address.
+ //
+ // Notes for implementations in subclasses:
+ // - If the connection is not proxied, the overridden method should use the
+ // base implementation:
+ //
+ // return QuicConnection::GetEffectivePeerAddressFromCurrentPacket();
+ //
+ // - If the connection is proxied, the overridden method may return either of
+ // the following:
+ // a) The address of the endpoint behind the proxy. The address is used to
+ // drive effective peer migration.
+ // b) An uninitialized address, meaning the effective peer address does not
+ // change.
+ virtual QuicSocketAddress GetEffectivePeerAddressFromCurrentPacket() const;
+
// Selects and updates the version of the protocol being used by selecting a
// version from |available_versions| which is also supported. Returns true if
// such a version exists, false otherwise.
@@ -774,17 +829,15 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Returns the current per-packet options for the connection.
PerPacketOptions* per_packet_options() { return per_packet_options_; }
- // 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.
- void set_per_packet_options(PerPacketOptions* options) {
- per_packet_options_ = options;
- }
AddressChangeType active_peer_migration_type() {
return active_peer_migration_type_;
}
+ AddressChangeType active_effective_peer_migration_type() const {
+ 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.
virtual void SendConnectionClosePacket(QuicErrorCode error,
@@ -803,7 +856,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Notify various components(SendPacketManager, Session etc.) that this
// connection has been migrated.
- void OnConnectionMigration(AddressChangeType addr_change_type);
+ virtual void OnConnectionMigration(AddressChangeType addr_change_type);
// Return whether the packet being processed is a connectivity probing.
// A packet is a connectivity probing if it is a padded ping packet with self
@@ -894,6 +947,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Sets the retransmission alarm based on SentPacketManager.
void SetRetransmissionAlarm();
+ // Sets the path degrading alarm.
+ void SetPathDegradingAlarm();
+
// Sets the MTU discovery alarm if necessary.
// |sent_packet_number| is the recently sent packet number.
void MaybeSetMtuAlarm(QuicPacketNumber sent_packet_number);
@@ -922,8 +978,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
void CheckIfApplicationLimited();
// Sets |current_packet_content_| to |type| if applicable. And
- // starts peer miration if current packet is confirmed not a connectivity
- // probe and |current_peer_migration_type_| indicates peer address change.
+ // starts effective peer miration if current packet is confirmed not a
+ // connectivity probe and |current_effective_peer_migration_type_| indicates
+ // effective peer address change.
void UpdatePacketContent(PacketContent type);
// Enables session decide what to write based on version and flags.
@@ -931,17 +988,29 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Called when last received ack frame has been processed.
// |send_stop_waiting| indicates whether a stop waiting needs to be sent.
- void PostProcessAfterAckFrame(bool send_stop_waiting);
+ // |acked_new_packet| is true if a previously-unacked packet was acked.
+ void PostProcessAfterAckFrame(bool send_stop_waiting, bool acked_new_packet);
QuicFramer framer_;
// Contents received in the current packet, especially used to identify
// whether the current packet is a padded PING packet.
PacketContent current_packet_content_;
+ // True if the packet currently being processed is a connectivity probing
+ // packet. Is set to false when a new packet is received, and will be set to
+ // true as soon as |current_packet_content_| is set to
+ // SECOND_FRAME_IS_PADDING.
+ bool is_current_packet_connectivity_probing_;
// Caches the current peer migration type if a peer migration might be
// initiated. As soon as the current packet is confirmed not a connectivity
// probe, peer migration will start.
+ // TODO(wub): Remove once quic_reloadable_flag_quic_enable_server_proxy is
+ // deprecated.
AddressChangeType current_peer_migration_type_;
+ // Caches the current effective peer migration type if a effective peer
+ // migration might be initiated. As soon as the current packet is confirmed
+ // not a connectivity probe, effective peer migration will start.
+ AddressChangeType current_effective_peer_migration_type_;
QuicConnectionHelperInterface* helper_; // Not owned.
QuicAlarmFactory* alarm_factory_; // Not owned.
PerPacketOptions* per_packet_options_; // Not owned.
@@ -955,17 +1024,38 @@ class QUIC_EXPORT_PRIVATE QuicConnection
const QuicConnectionId connection_id_;
// Address on the last successfully processed packet received from the
- // client.
+ // direct peer.
QuicSocketAddress self_address_;
QuicSocketAddress peer_address_;
+ QuicSocketAddress direct_peer_address_;
+ // Address of the endpoint behind the proxy if the connection is proxied.
+ // Otherwise it is the same as |peer_address_|.
+ // NOTE: Currently |effective_peer_address_| and |peer_address_| are always
+ // the same(the address of the direct peer), but soon we'll change
+ // |effective_peer_address_| to be the address of the endpoint behind the
+ // proxy if the connection is proxied.
+ QuicSocketAddress effective_peer_address_;
+
// Records change type when the peer initiates migration to a new peer
// address. Reset to NO_CHANGE after peer migration is validated.
+ // TODO(wub): Remove once quic_reloadable_flag_quic_enable_server_proxy is
+ // deprecated.
AddressChangeType active_peer_migration_type_;
// Records highest sent packet number when peer migration is started.
+ // TODO(wub): Remove once quic_reloadable_flag_quic_enable_server_proxy is
+ // deprecated.
QuicPacketNumber highest_packet_sent_before_peer_migration_;
+ // Records change type when the effective peer initiates migration to a new
+ // address. Reset to NO_CHANGE after effective peer migration is validated.
+ AddressChangeType active_effective_peer_migration_type_;
+
+ // Records highest sent packet number when effective peer migration is
+ // started.
+ QuicPacketNumber highest_packet_sent_before_effective_peer_migration_;
+
// True if the last packet has gotten far enough in the framer to be
// decrypted.
bool last_packet_decrypted_;
@@ -1063,6 +1153,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// The timeout for PING.
QuicTime::Delta ping_timeout_;
+ // Timeout for how long the wire can have no retransmittable packets.
+ QuicTime::Delta retransmittable_on_wire_timeout_;
+
// Arena to store class implementations within the QuicConnection.
QuicConnectionArena arena_;
@@ -1084,6 +1177,11 @@ class QUIC_EXPORT_PRIVATE QuicConnection
QuicArenaScopedPtr<QuicAlarm> ping_alarm_;
// An alarm that fires when an MTU probe should be sent.
QuicArenaScopedPtr<QuicAlarm> mtu_discovery_alarm_;
+ // An alarm that fires when there have been no retransmittable packets on the
+ // wire for some period.
+ QuicArenaScopedPtr<QuicAlarm> retransmittable_on_wire_alarm_;
+ // An alarm that fires when this connection is considered degrading.
+ QuicArenaScopedPtr<QuicAlarm> path_degrading_alarm_;
// Neither visitor is owned by this class.
QuicConnectionVisitorInterface* visitor_;
@@ -1194,11 +1292,32 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// retransmission code.
bool probing_retransmission_pending_;
+ // Indicates whether a stateless reset token has been received from peer.
+ bool stateless_reset_token_received_;
+ // Stores received stateless reset token from peer. Used to verify whether a
+ // packet is a stateless reset packet.
+ uint128 received_stateless_reset_token_;
+
// Id of latest sent control frame. 0 if no control frame has been sent.
QuicControlFrameId last_control_frame_id_;
- // Latched value of quic_reloadable_flag_quic_use_control_frame_manager.
- const bool use_control_frame_manager_;
+ // Latched value of
+ // quic_reloadable_flag_quic_server_early_version_negotiation.
+ const bool negotiate_version_early_;
+
+ // Latched value of
+ // quic_reloadable_flag_quic_always_discard_packets_after_close.
+ const bool always_discard_packets_after_close_;
+ // Latched valure of
+ // quic_reloadable_flag_quic_handle_write_results_for_connectivity_probe.
+ const bool handle_write_results_for_connectivity_probe_;
+
+ // Latched value of
+ // quic_reloadable_flag_quic_path_degrading_alarm
+ const bool use_path_degrading_alarm_;
+
+ // Latched value of quic_reloadable_flag_quic_enable_server_proxy.
+ const bool enable_server_proxy_;
DISALLOW_COPY_AND_ASSIGN(QuicConnection);
};
diff --git a/chromium/net/quic/core/quic_connection_test.cc b/chromium/net/quic/core/quic_connection_test.cc
index eb05baccaee..69430cb9d03 100644
--- a/chromium/net/quic/core/quic_connection_test.cc
+++ b/chromium/net/quic/core/quic_connection_test.cc
@@ -48,6 +48,7 @@ using testing::_;
using testing::AnyNumber;
using testing::AtLeast;
using testing::DoAll;
+using testing::Exactly;
using testing::Ge;
using testing::InSequence;
using testing::Invoke;
@@ -317,7 +318,8 @@ class TestPacketWriter : public QuicPacketWriter {
}
if (use_tagging_decrypter_) {
- framer_.framer()->SetDecrypter(ENCRYPTION_NONE, new TaggingDecrypter);
+ framer_.framer()->SetDecrypter(ENCRYPTION_NONE,
+ QuicMakeUnique<TaggingDecrypter>());
}
EXPECT_TRUE(framer_.ProcessPacket(packet));
if (block_on_next_write_) {
@@ -502,7 +504,8 @@ class TestConnection : public QuicConnection {
SupportedVersions(version)),
notifier_(nullptr) {
writer->set_perspective(perspective);
- SetEncrypter(ENCRYPTION_FORWARD_SECURE, new NullEncrypter(perspective));
+ SetEncrypter(ENCRYPTION_FORWARD_SECURE,
+ QuicMakeUnique<NullEncrypter>(perspective));
SetDataProducer(&producer_);
}
@@ -528,7 +531,7 @@ class TestConnection : public QuicConnection {
ENCRYPTION_NONE, packet_number, *packet, buffer, kMaxPacketSize);
delete packet;
SerializedPacket serialized_packet(
- packet_number, PACKET_6BYTE_PACKET_NUMBER, buffer, encrypted_length,
+ packet_number, PACKET_4BYTE_PACKET_NUMBER, buffer, encrypted_length,
has_ack, has_pending_frames);
if (retransmittable == HAS_RETRANSMITTABLE_DATA) {
serialized_packet.retransmittable_frames.push_back(
@@ -655,6 +658,16 @@ class TestConnection : public QuicConnection {
QuicConnectionPeer::GetMtuDiscoveryAlarm(this));
}
+ TestAlarmFactory::TestAlarm* GetRetransmittableOnWireAlarm() {
+ return reinterpret_cast<TestAlarmFactory::TestAlarm*>(
+ QuicConnectionPeer::GetRetransmittableOnWireAlarm(this));
+ }
+
+ TestAlarmFactory::TestAlarm* GetPathDegradingAlarm() {
+ return reinterpret_cast<TestAlarmFactory::TestAlarm*>(
+ QuicConnectionPeer::GetPathDegradingAlarm(this));
+ }
+
void SetMaxTailLossProbes(size_t max_tail_loss_probes) {
QuicSentPacketManagerPeer::SetMaxTailLossProbes(
QuicConnectionPeer::GetSentPacketManager(this), max_tail_loss_probes);
@@ -667,10 +680,23 @@ class TestConnection : public QuicConnection {
void set_notifier(SimpleSessionNotifier* notifier) { notifier_ = notifier; }
+ void ReturnEffectivePeerAddressForNextPacket(const QuicSocketAddress& addr) {
+ next_effective_peer_addr_ = QuicMakeUnique<QuicSocketAddress>(addr);
+ }
+
+ using QuicConnection::IsCurrentPacketConnectivityProbing;
using QuicConnection::SelectMutualVersion;
using QuicConnection::SendProbingRetransmissions;
using QuicConnection::set_defer_send_in_response_to_packets;
+ protected:
+ QuicSocketAddress GetEffectivePeerAddressFromCurrentPacket() const override {
+ if (next_effective_peer_addr_) {
+ return *std::move(next_effective_peer_addr_);
+ }
+ return QuicConnection::GetEffectivePeerAddressFromCurrentPacket();
+ }
+
private:
TestPacketWriter* writer() {
return static_cast<TestPacketWriter*>(QuicConnection::writer());
@@ -680,6 +706,8 @@ class TestConnection : public QuicConnection {
SimpleSessionNotifier* notifier_;
+ std::unique_ptr<QuicSocketAddress> next_effective_peer_addr_;
+
DISALLOW_COPY_AND_ASSIGN(TestConnection);
};
@@ -709,6 +737,8 @@ struct TestParams {
// Constructs various test permutations.
std::vector<TestParams> GetTestParams() {
+ QuicFlagSaver flags;
+ 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) {
@@ -753,9 +783,12 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
manager_(QuicConnectionPeer::GetSentPacketManager(&connection_)),
frame1_(1, false, 0, QuicStringPiece(data1)),
frame2_(1, false, 3, QuicStringPiece(data2)),
- packet_number_length_(PACKET_6BYTE_PACKET_NUMBER),
+ packet_number_length_(PACKET_4BYTE_PACKET_NUMBER),
connection_id_length_(PACKET_8BYTE_CONNECTION_ID),
- notifier_(&connection_) {
+ notifier_(&connection_),
+ use_path_degrading_alarm_(
+ GetQuicReloadableFlag(quic_path_degrading_alarm)) {
+ SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
connection_.set_defer_send_in_response_to_packets(GetParam().ack_response ==
AckResponse::kDefer);
QuicConnectionPeer::SetNoStopWaitingFrames(&connection_,
@@ -796,6 +829,7 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
.WillRepeatedly(Return(false));
EXPECT_CALL(visitor_, OnCongestionWindowChange(_)).Times(AnyNumber());
EXPECT_CALL(visitor_, OnConnectivityProbeReceived(_, _)).Times(AnyNumber());
+ EXPECT_CALL(visitor_, OnForwardProgressConfirmed()).Times(AnyNumber());
EXPECT_CALL(*loss_algorithm_, GetLossTimeout())
.WillRepeatedly(Return(QuicTime::Zero()));
@@ -981,16 +1015,12 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
connection_.OnStreamReset(id, error);
return;
}
- if (connection_.use_control_frame_manager()) {
- std::unique_ptr<QuicRstStreamFrame> rst_stream =
- QuicMakeUnique<QuicRstStreamFrame>(1, id, error, bytes_written);
- if (connection_.SendControlFrame(QuicFrame(rst_stream.get()))) {
- rst_stream.release();
- }
- connection_.OnStreamReset(id, error);
- return;
+ std::unique_ptr<QuicRstStreamFrame> rst_stream =
+ QuicMakeUnique<QuicRstStreamFrame>(1, id, error, bytes_written);
+ if (connection_.SendControlFrame(QuicFrame(rst_stream.get()))) {
+ rst_stream.release();
}
- connection_.SendRstStream(id, error, bytes_written);
+ connection_.OnStreamReset(id, error);
}
void ProcessAckPacket(QuicPacketNumber packet_number, QuicAckFrame* frame) {
@@ -1168,6 +1198,10 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
SimpleSessionNotifier notifier_;
+ // Latched value of
+ // quic_reloadable_flag_quic_path_degrading_alarm
+ bool use_path_degrading_alarm_;
+
private:
DISALLOW_COPY_AND_ASSIGN(QuicConnectionTest);
};
@@ -1255,8 +1289,17 @@ TEST_P(QuicConnectionTest, ClientAddressChangeAndPacketReordered) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
set_perspective(Perspective::IS_SERVER);
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
- // Clear peer address.
- QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ // Clear direct_peer_address.
+ QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+ // Clear effective_peer_address, it is the same as direct_peer_address for
+ // this test.
+ QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+ QuicSocketAddress());
+ } else {
+ // Clear peer_address.
+ QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
+ }
QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 5);
QuicStreamFrame stream_frame(1u, false, 0u, QuicStringPiece());
@@ -1266,6 +1309,10 @@ TEST_P(QuicConnectionTest, ClientAddressChangeAndPacketReordered) {
/*port=*/23456);
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
kNewPeerAddress);
+ EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
+ }
// Decrease packet number to simulate out-of-order packets.
QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 4);
@@ -1273,6 +1320,10 @@ TEST_P(QuicConnectionTest, ClientAddressChangeAndPacketReordered) {
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
kPeerAddress);
+ EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
+ }
}
TEST_P(QuicConnectionTest, PeerAddressChangeAtServer) {
@@ -1281,15 +1332,28 @@ TEST_P(QuicConnectionTest, PeerAddressChangeAtServer) {
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
- // Clear peer address.
- QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
- EXPECT_FALSE(connection_.peer_address().IsInitialized());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ // Clear direct_peer_address.
+ QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+ // Clear effective_peer_address, it is the same as direct_peer_address for
+ // this test.
+ QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+ QuicSocketAddress());
+ EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
+ } else {
+ // Clear peer_address.
+ QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
+ EXPECT_FALSE(connection_.peer_address().IsInitialized());
+ }
QuicStreamFrame stream_frame(1u, false, 0u, QuicStringPiece());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
kPeerAddress);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+ }
// Process another packet with a different peer address on server side will
// start connection migration.
@@ -1299,6 +1363,78 @@ TEST_P(QuicConnectionTest, PeerAddressChangeAtServer) {
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
kNewPeerAddress);
EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
+ }
+}
+
+TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
+ if (!GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ return;
+ }
+
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ set_perspective(Perspective::IS_SERVER);
+ QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
+ EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
+
+ // Clear direct_peer_address.
+ QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+ // Clear effective_peer_address, it is different from direct_peer_address for
+ // this test.
+ QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+ QuicSocketAddress());
+ const QuicSocketAddress kEffectivePeerAddress =
+ QuicSocketAddress(QuicIpAddress::Loopback6(), /*port=*/43210);
+ connection_.ReturnEffectivePeerAddressForNextPacket(kEffectivePeerAddress);
+
+ QuicStreamFrame stream_frame(1u, false, 0u, QuicStringPiece());
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
+ ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
+ kPeerAddress);
+ EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ EXPECT_EQ(kEffectivePeerAddress, connection_.effective_peer_address());
+
+ // Process another packet with the same direct peer address and different
+ // effective peer address on server side will start connection migration.
+ const QuicSocketAddress kNewEffectivePeerAddress =
+ QuicSocketAddress(QuicIpAddress::Loopback6(), /*port=*/54321);
+ connection_.ReturnEffectivePeerAddressForNextPacket(kNewEffectivePeerAddress);
+ EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(1);
+ ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
+ kPeerAddress);
+ EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ EXPECT_EQ(kNewEffectivePeerAddress, connection_.effective_peer_address());
+
+ // Process another packet with a different direct peer address and the same
+ // effective peer address on server side will not start connection migration.
+ const QuicSocketAddress kNewPeerAddress =
+ QuicSocketAddress(QuicIpAddress::Loopback6(), /*port=*/23456);
+ connection_.ReturnEffectivePeerAddressForNextPacket(kNewEffectivePeerAddress);
+ EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
+ // ack_frame is used to complete the migration started by the last packet, it
+ // is required to complete the last migration such that the next migration can
+ // start.
+ QuicAckFrame ack_frame = InitAckFrame(1);
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _));
+ ProcessFramePacketWithAddresses(QuicFrame(&ack_frame), kSelfAddress,
+ kNewPeerAddress);
+ EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
+ EXPECT_EQ(kNewEffectivePeerAddress, connection_.effective_peer_address());
+
+ // Process another packet with different direct peer address and different
+ // effective peer address on server side will start connection migration.
+ const QuicSocketAddress kFinalEffectivePeerAddress =
+ QuicSocketAddress(QuicIpAddress::Loopback6(), /*port=*/65432);
+ const QuicSocketAddress kFinalPeerAddress =
+ QuicSocketAddress(QuicIpAddress::Loopback6(), /*port=*/34567);
+ connection_.ReturnEffectivePeerAddressForNextPacket(
+ kFinalEffectivePeerAddress);
+ EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(1);
+ ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
+ kFinalPeerAddress);
+ EXPECT_EQ(kFinalPeerAddress, connection_.peer_address());
+ EXPECT_EQ(kFinalEffectivePeerAddress, connection_.effective_peer_address());
}
TEST_P(QuicConnectionTest, ReceivePaddedPingAtServer) {
@@ -1307,15 +1443,28 @@ TEST_P(QuicConnectionTest, ReceivePaddedPingAtServer) {
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
- // Clear peer address.
- QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
- EXPECT_FALSE(connection_.peer_address().IsInitialized());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ // Clear direct_peer_address.
+ QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+ // Clear effective_peer_address, it is the same as direct_peer_address for
+ // this test.
+ QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+ QuicSocketAddress());
+ EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
+ } else {
+ // Clear peer_address.
+ QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
+ EXPECT_FALSE(connection_.peer_address().IsInitialized());
+ }
QuicStreamFrame stream_frame(1u, false, 0u, QuicStringPiece());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
kPeerAddress);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+ }
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
EXPECT_CALL(visitor_, OnConnectivityProbeReceived(_, _)).Times(0);
@@ -1331,7 +1480,77 @@ TEST_P(QuicConnectionTest, ReceivePaddedPingAtServer) {
clock_.Now()));
ProcessReceivedPacket(kSelfAddress, kPeerAddress, *received);
+
+ EXPECT_FALSE(connection_.IsCurrentPacketConnectivityProbing());
EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+ }
+}
+
+TEST_P(QuicConnectionTest, WriteOutOfOrderQueuedPackets) {
+ // When the flag is false, this test will trigger a use-after-free, which
+ // often means crashes, but not always, i.e. it can't be reliably tested.
+ SetQuicReloadableFlag(quic_fix_write_out_of_order_queued_packet_crash, true);
+ set_perspective(Perspective::IS_CLIENT);
+
+ BlockOnNextWrite();
+
+ QuicStreamId stream_id = 2;
+ connection_.SendStreamDataWithString(stream_id, "foo", 0, NO_FIN);
+
+ EXPECT_EQ(1u, connection_.NumQueuedPackets());
+
+ writer_->SetWritable();
+ connection_.SendConnectivityProbingPacket(writer_.get(),
+ connection_.peer_address());
+
+ if (GetQuicReloadableFlag(
+ quic_clear_queued_packets_before_sending_connectivity_probing)) {
+ EXPECT_EQ(0u, connection_.NumQueuedPackets());
+ connection_.OnCanWrite();
+ EXPECT_TRUE(connection_.connected());
+ } else {
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INTERNAL_ERROR,
+ "Packet written out of order.",
+ ConnectionCloseSource::FROM_SELF));
+ EXPECT_QUIC_BUG(connection_.OnCanWrite(),
+ "Attempt to write packet:1 after:2");
+ EXPECT_FALSE(connection_.connected());
+ }
+}
+
+TEST_P(QuicConnectionTest, DiscardQueuedPacketsAfterConnectionClose) {
+ // Regression test for b/74073386.
+ // When the flag is false, this test will trigger a use-after-free, which
+ // often means crashes, but not always, i.e. it can't be reliably tested.
+ SetQuicReloadableFlag(quic_fix_write_out_of_order_queued_packet_crash, true);
+ {
+ InSequence seq;
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _)).Times(1);
+ }
+
+ set_perspective(Perspective::IS_CLIENT);
+
+ writer_->SimulateNextPacketTooLarge();
+
+ // This packet write should fail, which should cause the connection to close
+ // after sending a connection close packet, then the failed packet should be
+ // queued.
+ connection_.SendStreamDataWithString(/*id=*/2, "foo", 0, NO_FIN);
+
+ EXPECT_FALSE(connection_.connected());
+ EXPECT_EQ(1u, connection_.NumQueuedPackets());
+
+ if (GetQuicReloadableFlag(quic_always_discard_packets_after_close)) {
+ EXPECT_EQ(0u, connection_.GetStats().packets_discarded);
+ connection_.OnCanWrite();
+ EXPECT_EQ(1u, connection_.GetStats().packets_discarded);
+ } else {
+ EXPECT_QUIC_BUG(connection_.OnCanWrite(),
+ "Attempt to write packet:1 after:2");
+ }
}
TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtServer) {
@@ -1340,15 +1559,28 @@ TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtServer) {
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
- // Clear peer address.
- QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
- EXPECT_FALSE(connection_.peer_address().IsInitialized());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ // Clear direct_peer_address.
+ QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+ // Clear effective_peer_address, it is the same as direct_peer_address for
+ // this test.
+ QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+ QuicSocketAddress());
+ EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
+ } else {
+ // Clear peer_address.
+ QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
+ EXPECT_FALSE(connection_.peer_address().IsInitialized());
+ }
QuicStreamFrame stream_frame(1u, false, 0u, QuicStringPiece());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
kPeerAddress);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+ }
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
EXPECT_CALL(visitor_, OnConnectivityProbeReceived(_, _)).Times(1);
@@ -1367,13 +1599,22 @@ TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtServer) {
clock_.Now()));
ProcessReceivedPacket(kSelfAddress, kNewPeerAddress, *received);
+
+ EXPECT_TRUE(connection_.IsCurrentPacketConnectivityProbing());
EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+ }
// 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);
+ EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+ }
}
TEST_P(QuicConnectionTest, MigrateAfterProbingAtServer) {
@@ -1382,15 +1623,28 @@ TEST_P(QuicConnectionTest, MigrateAfterProbingAtServer) {
QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
- // Clear peer address.
- QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
- EXPECT_FALSE(connection_.peer_address().IsInitialized());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ // Clear direct_peer_address.
+ QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+ // Clear effective_peer_address, it is the same as direct_peer_address for
+ // this test.
+ QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+ QuicSocketAddress());
+ EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
+ } else {
+ // Clear peer_address.
+ QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
+ EXPECT_FALSE(connection_.peer_address().IsInitialized());
+ }
QuicStreamFrame stream_frame(1u, false, 0u, QuicStringPiece());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
kPeerAddress);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+ }
EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
EXPECT_CALL(visitor_, OnConnectivityProbeReceived(_, _)).Times(1);
@@ -1409,6 +1663,9 @@ TEST_P(QuicConnectionTest, MigrateAfterProbingAtServer) {
clock_.Now()));
ProcessReceivedPacket(kSelfAddress, kNewPeerAddress, *received);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+ }
// Process another non-probing packet with the new peer address on server
// side will start peer migration.
@@ -1417,6 +1674,9 @@ TEST_P(QuicConnectionTest, MigrateAfterProbingAtServer) {
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
kNewPeerAddress);
EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
+ }
}
TEST_P(QuicConnectionTest, ReceivePaddedPingAtClient) {
@@ -1424,15 +1684,28 @@ TEST_P(QuicConnectionTest, ReceivePaddedPingAtClient) {
set_perspective(Perspective::IS_CLIENT);
EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
- // Clear peer address.
- QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
- EXPECT_FALSE(connection_.peer_address().IsInitialized());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ // Clear direct_peer_address.
+ QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+ // Clear effective_peer_address, it is the same as direct_peer_address for
+ // this test.
+ QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+ QuicSocketAddress());
+ EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
+ } else {
+ // Clear peer_address.
+ QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
+ EXPECT_FALSE(connection_.peer_address().IsInitialized());
+ }
QuicStreamFrame stream_frame(1u, false, 0u, QuicStringPiece());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
kPeerAddress);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+ }
// Client takes all padded PING packet as speculative connectivity
// probing packet, and reports to visitor.
@@ -1448,7 +1721,11 @@ TEST_P(QuicConnectionTest, ReceivePaddedPingAtClient) {
clock_.Now()));
ProcessReceivedPacket(kSelfAddress, kPeerAddress, *received);
+ EXPECT_FALSE(connection_.IsCurrentPacketConnectivityProbing());
EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+ }
}
TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtClient) {
@@ -1456,15 +1733,28 @@ TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtClient) {
set_perspective(Perspective::IS_CLIENT);
EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
- // Clear peer address.
- QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
- EXPECT_FALSE(connection_.peer_address().IsInitialized());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ // Clear direct_peer_address.
+ QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+ // Clear effective_peer_address, it is the same as direct_peer_address for
+ // this test.
+ QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+ QuicSocketAddress());
+ EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
+ } else {
+ // Clear peer_address.
+ QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
+ EXPECT_FALSE(connection_.peer_address().IsInitialized());
+ }
QuicStreamFrame stream_frame(1u, false, 0u, QuicStringPiece());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
kPeerAddress);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+ }
// Process a padded PING packet with a different self address on client side
// is effectively receiving a connectivity probing.
@@ -1483,7 +1773,11 @@ TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtClient) {
clock_.Now()));
ProcessReceivedPacket(kNewSelfAddress, kPeerAddress, *received);
+ EXPECT_TRUE(connection_.IsCurrentPacketConnectivityProbing());
EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+ }
}
TEST_P(QuicConnectionTest, PeerAddressChangeAtClient) {
@@ -1491,15 +1785,28 @@ TEST_P(QuicConnectionTest, PeerAddressChangeAtClient) {
set_perspective(Perspective::IS_CLIENT);
EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
- // Clear peer address.
- QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
- EXPECT_FALSE(connection_.peer_address().IsInitialized());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ // Clear direct_peer_address.
+ QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+ // Clear effective_peer_address, it is the same as direct_peer_address for
+ // this test.
+ QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+ QuicSocketAddress());
+ EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
+ } else {
+ // Clear peer_address.
+ QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
+ EXPECT_FALSE(connection_.peer_address().IsInitialized());
+ }
QuicStreamFrame stream_frame(1u, false, 0u, QuicStringPiece());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
kPeerAddress);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+ }
// Process another packet with a different peer address on client side will
// only update peer address.
@@ -1509,6 +1816,9 @@ TEST_P(QuicConnectionTest, PeerAddressChangeAtClient) {
ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
kNewPeerAddress);
EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
+ if (GetQuicReloadableFlag(quic_enable_server_proxy)) {
+ EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
+ }
}
TEST_P(QuicConnectionTest, MaxPacketSize) {
@@ -1858,16 +2168,11 @@ TEST_P(QuicConnectionTest, AckNeedsRetransmittableFrames) {
}
// Receiving Packet 40 causes 20th ack to send. Session is informed and adds
// WINDOW_UPDATE.
- if (connection_.use_control_frame_manager()) {
- EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame())
- .WillOnce(Invoke([this]() {
- connection_.SendControlFrame(
- QuicFrame(new QuicWindowUpdateFrame(1, 0, 0)));
- }));
- } else {
- EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame())
- .WillOnce(Invoke([this]() { connection_.SendWindowUpdate(0, 0); }));
- }
+ EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame())
+ .WillOnce(Invoke([this]() {
+ connection_.SendControlFrame(
+ QuicFrame(new QuicWindowUpdateFrame(1, 0, 0)));
+ }));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
EXPECT_EQ(0u, writer_->window_update_frames().size());
ProcessDataPacket(40);
@@ -1888,14 +2193,10 @@ TEST_P(QuicConnectionTest, AckNeedsRetransmittableFrames) {
EXPECT_EQ(0u, writer_->window_update_frames().size());
}
// Session does not add a retransmittable frame.
- if (connection_.use_control_frame_manager()) {
- EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame())
- .WillOnce(Invoke([this]() {
- connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
- }));
- } else {
- EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(1);
- }
+ EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame())
+ .WillOnce(Invoke([this]() {
+ connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
+ }));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
EXPECT_EQ(0u, writer_->ping_frames().size());
ProcessDataPacket(99);
@@ -1940,8 +2241,6 @@ TEST_P(QuicConnectionTest, LeastUnackedLower) {
}
TEST_P(QuicConnectionTest, TooManySentPackets) {
- SetQuicReloadableFlag(quic_close_session_on_too_many_outstanding_sent_packets,
- true);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
QuicPacketCount max_tracked_packets = 50;
@@ -2403,8 +2702,7 @@ TEST_P(QuicConnectionTest, DoNotSendQueuedPacketForResetStream) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
writer_->SetWritable();
connection_.OnCanWrite();
- if (connection_.use_control_frame_manager() &&
- !connection_.session_decides_what_to_write()) {
+ if (!connection_.session_decides_what_to_write()) {
// OnCanWrite will cause RST_STREAM be sent again.
connection_.SendControlFrame(QuicFrame(new QuicRstStreamFrame(
1, stream_id, QUIC_ERROR_PROCESSING_STREAM, 14)));
@@ -2428,8 +2726,7 @@ TEST_P(QuicConnectionTest, SendQueuedPacketForQuicRstStreamNoError) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(2));
writer_->SetWritable();
connection_.OnCanWrite();
- if (connection_.use_control_frame_manager() &&
- !connection_.session_decides_what_to_write()) {
+ if (!connection_.session_decides_what_to_write()) {
// OnCanWrite will cause RST_STREAM be sent again.
connection_.SendControlFrame(QuicFrame(
new QuicRstStreamFrame(1, stream_id, QUIC_STREAM_NO_ERROR, 14)));
@@ -2566,8 +2863,7 @@ TEST_P(QuicConnectionTest, DoNotSendPendingRetransmissionForResetStream) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
writer_->SetWritable();
connection_.OnCanWrite();
- if (connection_.use_control_frame_manager() &&
- !connection_.session_decides_what_to_write()) {
+ if (!connection_.session_decides_what_to_write()) {
// OnCanWrite will cause this RST_STREAM_FRAME be sent again.
connection_.SendControlFrame(QuicFrame(new QuicRstStreamFrame(
1, stream_id, QUIC_ERROR_PROCESSING_STREAM, 14)));
@@ -2603,17 +2899,12 @@ TEST_P(QuicConnectionTest, SendPendingRetransmissionForQuicRstStreamNoError) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(2));
writer_->SetWritable();
connection_.OnCanWrite();
- if (connection_.use_control_frame_manager()) {
- // The RST_STREAM_FRAME is sent after queued packets and pending
- // retransmission.
- connection_.SendControlFrame(QuicFrame(
- new QuicRstStreamFrame(1, stream_id, QUIC_STREAM_NO_ERROR, 14)));
- EXPECT_EQ(1u, writer_->frame_count());
- EXPECT_EQ(1u, writer_->rst_stream_frames().size());
- } else {
- EXPECT_EQ(1u, writer_->frame_count());
- EXPECT_EQ(0u, writer_->rst_stream_frames().size());
- }
+ // The RST_STREAM_FRAME is sent after queued packets and pending
+ // retransmission.
+ connection_.SendControlFrame(QuicFrame(
+ new QuicRstStreamFrame(1, stream_id, QUIC_STREAM_NO_ERROR, 14)));
+ EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_EQ(1u, writer_->rst_stream_frames().size());
}
TEST_P(QuicConnectionTest, RetransmitAckedPacket) {
@@ -2640,6 +2931,9 @@ TEST_P(QuicConnectionTest, RetransmitAckedPacket) {
// Now, ack the previous transmission.
EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _));
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(false, _, _, _, _));
+ }
QuicAckFrame ack_all = InitAckFrame(3);
ProcessAckPacket(&ack_all);
@@ -2940,11 +3234,13 @@ TEST_P(QuicConnectionTest, RetransmitWithSameEncryptionLevel) {
// 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_NONE, new TaggingEncrypter(0x01));
+ connection_.SetEncrypter(ENCRYPTION_NONE,
+ QuicMakeUnique<TaggingEncrypter>(0x01));
SendStreamDataToPeer(kCryptoStreamId, "foo", 0, NO_FIN, nullptr);
EXPECT_EQ(0x01010101u, writer_->final_bytes_of_last_packet());
- connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(0x02));
+ connection_.SetEncrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<TaggingEncrypter>(0x02));
connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
SendStreamDataToPeer(3, "foo", 0, NO_FIN, nullptr);
EXPECT_EQ(0x02020202u, writer_->final_bytes_of_last_packet());
@@ -2969,7 +3265,8 @@ TEST_P(QuicConnectionTest, SendHandshakeMessages) {
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_NONE, new TaggingEncrypter(0x01));
+ connection_.SetEncrypter(ENCRYPTION_NONE,
+ QuicMakeUnique<TaggingEncrypter>(0x01));
// Attempt to send a handshake message and have the socket block.
EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
@@ -2979,7 +3276,8 @@ TEST_P(QuicConnectionTest, SendHandshakeMessages) {
EXPECT_EQ(1u, connection_.NumQueuedPackets());
// Switch to the new encrypter.
- connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(0x02));
+ connection_.SetEncrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<TaggingEncrypter>(0x02));
connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
// Now become writeable and flush the packets.
@@ -2995,7 +3293,8 @@ TEST_P(QuicConnectionTest, SendHandshakeMessages) {
TEST_P(QuicConnectionTest,
DropRetransmitsForNullEncryptedPacketAfterForwardSecure) {
use_tagging_decrypter();
- connection_.SetEncrypter(ENCRYPTION_NONE, new TaggingEncrypter(0x01));
+ connection_.SetEncrypter(ENCRYPTION_NONE,
+ QuicMakeUnique<TaggingEncrypter>(0x01));
QuicPacketNumber packet_number;
SendStreamDataToPeer(kCryptoStreamId, "foo", 0, NO_FIN, &packet_number);
@@ -3006,7 +3305,7 @@ TEST_P(QuicConnectionTest,
// Go forward secure.
connection_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
- new TaggingEncrypter(0x02));
+ QuicMakeUnique<TaggingEncrypter>(0x02));
connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
notifier_.NeuterUnencryptedData();
connection_.NeuterUnencryptedPackets();
@@ -3020,12 +3319,14 @@ TEST_P(QuicConnectionTest,
TEST_P(QuicConnectionTest, RetransmitPacketsWithInitialEncryption) {
use_tagging_decrypter();
- connection_.SetEncrypter(ENCRYPTION_NONE, new TaggingEncrypter(0x01));
+ connection_.SetEncrypter(ENCRYPTION_NONE,
+ QuicMakeUnique<TaggingEncrypter>(0x01));
connection_.SetDefaultEncryptionLevel(ENCRYPTION_NONE);
SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr);
- connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(0x02));
+ connection_.SetEncrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<TaggingEncrypter>(0x02));
connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
SendStreamDataToPeer(2, "bar", 0, NO_FIN, nullptr);
@@ -3043,7 +3344,8 @@ TEST_P(QuicConnectionTest, BufferNonDecryptablePackets) {
use_tagging_decrypter();
const uint8_t tag = 0x07;
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<TaggingEncrypter>(tag));
// Process an encrypted packet which can not yet be decrypted which should
// result in the packet being buffered.
@@ -3051,9 +3353,11 @@ TEST_P(QuicConnectionTest, BufferNonDecryptablePackets) {
// Transition to the new encryption state and process another encrypted packet
// which should result in the original packet being processed.
- connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
+ connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<StrictTaggingDecrypter>(tag));
connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
- connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ connection_.SetEncrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<TaggingEncrypter>(tag));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(2);
ProcessDataPacketAtLevel(2, !kHasStopWaiting, ENCRYPTION_INITIAL);
@@ -3073,7 +3377,8 @@ TEST_P(QuicConnectionTest, Buffer100NonDecryptablePackets) {
use_tagging_decrypter();
const uint8_t tag = 0x07;
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<TaggingEncrypter>(tag));
// Process an encrypted packet which can not yet be decrypted which should
// result in the packet being buffered.
@@ -3083,9 +3388,11 @@ TEST_P(QuicConnectionTest, Buffer100NonDecryptablePackets) {
// Transition to the new encryption state and process another encrypted packet
// which should result in the original packets being processed.
- connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
+ connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<StrictTaggingDecrypter>(tag));
connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
- connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ connection_.SetEncrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<TaggingEncrypter>(tag));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(101);
ProcessDataPacketAtLevel(101, !kHasStopWaiting, ENCRYPTION_INITIAL);
@@ -3121,7 +3428,9 @@ TEST_P(QuicConnectionTest, TestRetransmitOrder) {
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(20));
{
InSequence s;
- EXPECT_CALL(visitor_, OnPathDegrading());
+ if (!use_path_degrading_alarm_) {
+ EXPECT_CALL(visitor_, OnPathDegrading());
+ }
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, first_packet_size, _));
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, second_packet_size, _));
}
@@ -3227,6 +3536,7 @@ TEST_P(QuicConnectionTest, InitialTimeout) {
EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
EXPECT_FALSE(connection_.GetSendAlarm()->IsSet());
EXPECT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet());
+ EXPECT_FALSE(connection_.GetRetransmittableOnWireAlarm()->IsSet());
}
TEST_P(QuicConnectionTest, HandshakeTimeout) {
@@ -3285,7 +3595,7 @@ TEST_P(QuicConnectionTest, PingAfterSend) {
EXPECT_EQ(clock_.ApproximateNow() + QuicTime::Delta::FromSeconds(15),
connection_.GetPingAlarm()->deadline());
- // Now recevie and ACK of the previous packet, which will move the
+ // Now recevie an ACK of the previous packet, which will move the
// ping alarm forward.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
QuicAckFrame frame = InitAckFrame(1);
@@ -3301,11 +3611,9 @@ TEST_P(QuicConnectionTest, PingAfterSend) {
writer_->Reset();
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(15));
- if (connection_.use_control_frame_manager()) {
- EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
- connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
- }));
- }
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
+ }));
connection_.GetPingAlarm()->Fire();
EXPECT_EQ(1u, writer_->frame_count());
ASSERT_EQ(1u, writer_->ping_frames().size());
@@ -3335,7 +3643,7 @@ TEST_P(QuicConnectionTest, ReducedPingTimeout) {
EXPECT_EQ(clock_.ApproximateNow() + QuicTime::Delta::FromSeconds(10),
connection_.GetPingAlarm()->deadline());
- // Now recevie and ACK of the previous packet, which will move the
+ // Now recevie an ACK of the previous packet, which will move the
// ping alarm forward.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
QuicAckFrame frame = InitAckFrame(1);
@@ -3351,11 +3659,9 @@ TEST_P(QuicConnectionTest, ReducedPingTimeout) {
writer_->Reset();
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(10));
- if (connection_.use_control_frame_manager()) {
- EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
- connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
- }));
- }
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
+ }));
connection_.GetPingAlarm()->Fire();
EXPECT_EQ(1u, writer_->frame_count());
ASSERT_EQ(1u, writer_->ping_frames().size());
@@ -4067,7 +4373,9 @@ TEST_P(QuicConnectionTest, TimeoutAfter5ClientRTOs) {
// Send stream data.
SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr);
- EXPECT_CALL(visitor_, OnPathDegrading());
+ if (!use_path_degrading_alarm_) {
+ EXPECT_CALL(visitor_, OnPathDegrading());
+ }
// Fire the retransmission alarm 6 times, twice for TLP and 4 times for RTO.
for (int i = 0; i < 6; ++i) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
@@ -4101,7 +4409,9 @@ TEST_P(QuicConnectionTest, TimeoutAfter3ClientRTOs) {
// Send stream data.
SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr);
- EXPECT_CALL(visitor_, OnPathDegrading());
+ if (!use_path_degrading_alarm_) {
+ EXPECT_CALL(visitor_, OnPathDegrading());
+ }
// Fire the retransmission alarm 4 times, twice for TLP and 2 times for RTO.
for (int i = 0; i < 4; ++i) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
@@ -4224,8 +4534,10 @@ TEST_P(QuicConnectionTest, SendDelayedAck) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
- connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<StrictTaggingDecrypter>(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<TaggingEncrypter>(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -4266,8 +4578,10 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimation) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
- connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<StrictTaggingDecrypter>(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<TaggingEncrypter>(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -4329,8 +4643,10 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationUnlimitedAggregation) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
- connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<StrictTaggingDecrypter>(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<TaggingEncrypter>(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -4380,8 +4696,10 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationEighthRtt) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
- connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<StrictTaggingDecrypter>(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<TaggingEncrypter>(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -4437,8 +4755,10 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReordering) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
- connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<StrictTaggingDecrypter>(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<TaggingEncrypter>(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -4502,8 +4822,10 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReordering) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
- connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<StrictTaggingDecrypter>(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<TaggingEncrypter>(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -4585,8 +4907,10 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReorderingEighthRtt) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
- connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<StrictTaggingDecrypter>(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<TaggingEncrypter>(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -4652,8 +4976,10 @@ TEST_P(QuicConnectionTest,
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
- connection_.SetDecrypter(ENCRYPTION_INITIAL, new StrictTaggingDecrypter(tag));
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(tag));
+ connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<StrictTaggingDecrypter>(tag));
+ peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ QuicMakeUnique<TaggingEncrypter>(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -4954,6 +5280,102 @@ TEST_P(QuicConnectionTest, SendWhenDisconnected) {
false, false);
}
+TEST_P(QuicConnectionTest, SendConnectivityProbingWhenDisconnected) {
+ EXPECT_TRUE(connection_.connected());
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, _,
+ ConnectionCloseSource::FROM_SELF));
+ connection_.CloseConnection(QUIC_PEER_GOING_AWAY, "no reason",
+ ConnectionCloseBehavior::SILENT_CLOSE);
+ EXPECT_FALSE(connection_.connected());
+ EXPECT_FALSE(connection_.CanWriteStreamData());
+
+ int num_packets_sent =
+ GetQuicReloadableFlag(quic_always_discard_packets_after_close) ? 0 : 1;
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _))
+ .Times(num_packets_sent);
+
+ if (GetQuicReloadableFlag(quic_always_discard_packets_after_close)) {
+ EXPECT_QUIC_BUG(connection_.SendConnectivityProbingPacket(
+ writer_.get(), connection_.peer_address()),
+ "Not sending connectivity probing packet as connection is "
+ "disconnected.");
+ } else {
+ connection_.SendConnectivityProbingPacket(writer_.get(),
+ connection_.peer_address());
+ }
+}
+
+TEST_P(QuicConnectionTest, WriteBlockedAfterClientSendsConnectivityProbe) {
+ EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
+ TestPacketWriter probing_writer(version(), &clock_);
+ // Block next write so that sending connectivity probe will encounter a
+ // blocked write when send a connectivity probe to the peer.
+ probing_writer.BlockOnNextWrite();
+ if (GetQuicReloadableFlag(quic_handle_write_results_for_connectivity_probe)) {
+ // Connection will not be marked as write blocked as connectivity probe only
+ // affects the probing_writer which is not the default.
+ EXPECT_CALL(visitor_, OnWriteBlocked()).Times(0);
+ } else {
+ EXPECT_CALL(visitor_, OnWriteBlocked()).Times(1);
+ }
+
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(1);
+ connection_.SendConnectivityProbingPacket(&probing_writer,
+ connection_.peer_address());
+}
+
+TEST_P(QuicConnectionTest, WriterBlockedAfterServerSendsConnectivityProbe) {
+ set_perspective(Perspective::IS_SERVER);
+ QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
+
+ // Block next write so that sending connectivity probe will encounter a
+ // blocked write when send a connectivity probe to the peer.
+ writer_->BlockOnNextWrite();
+ // Connection will be marked as write blocked as server uses the default
+ // writer to send connectivity probes.
+ EXPECT_CALL(visitor_, OnWriteBlocked()).Times(1);
+
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(1);
+ connection_.SendConnectivityProbingPacket(writer_.get(),
+ connection_.peer_address());
+}
+
+TEST_P(QuicConnectionTest, WriterErrorWhenClientSendsConnectivityProbe) {
+ EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
+ TestPacketWriter probing_writer(version(), &clock_);
+ probing_writer.SetShouldWriteFail();
+
+ if (GetQuicReloadableFlag(quic_handle_write_results_for_connectivity_probe)) {
+ // Connection should not be closed if a connectivity probe is failed to be
+ // sent.
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _)).Times(0);
+ } else {
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _)).Times(1);
+ }
+
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0);
+ connection_.SendConnectivityProbingPacket(&probing_writer,
+ connection_.peer_address());
+}
+
+TEST_P(QuicConnectionTest, WriterErrorWhenServerSendsConnectivityProbe) {
+ set_perspective(Perspective::IS_SERVER);
+ QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
+
+ writer_->SetShouldWriteFail();
+ if (GetQuicReloadableFlag(quic_handle_write_results_for_connectivity_probe)) {
+ // Connection should not be closed if a connectivity probe is failed to be
+ // sent.
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _)).Times(0);
+ } else {
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _)).Times(1);
+ }
+
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0);
+ connection_.SendConnectivityProbingPacket(writer_.get(),
+ connection_.peer_address());
+}
+
TEST_P(QuicConnectionTest, PublicReset) {
QuicPublicResetPacket header;
// Public reset packet in only built by server.
@@ -5131,7 +5553,7 @@ TEST_P(QuicConnectionTest, ClientHandlesVersionNegotiation) {
// Send a version negotiation packet.
std::unique_ptr<QuicEncryptedPacket> encrypted(
- peer_framer_.BuildVersionNegotiationPacket(connection_id_,
+ peer_framer_.BuildVersionNegotiationPacket(connection_id_, false,
AllSupportedVersions()));
std::unique_ptr<QuicReceivedPacket> received(
ConstructReceivedPacket(*encrypted, QuicTime::Zero()));
@@ -5166,7 +5588,7 @@ TEST_P(QuicConnectionTest, BadVersionNegotiation) {
OnConnectionClosed(QUIC_INVALID_VERSION_NEGOTIATION_PACKET, _,
ConnectionCloseSource::FROM_SELF));
std::unique_ptr<QuicEncryptedPacket> encrypted(
- framer_.BuildVersionNegotiationPacket(connection_id_,
+ framer_.BuildVersionNegotiationPacket(connection_id_, false,
AllSupportedVersions()));
std::unique_ptr<QuicReceivedPacket> received(
ConstructReceivedPacket(*encrypted, QuicTime::Zero()));
@@ -5415,11 +5837,7 @@ TEST_P(QuicConnectionTest, SendPingImmediately) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _)).Times(1);
EXPECT_CALL(debug_visitor, OnPingSent()).Times(1);
- if (connection_.use_control_frame_manager()) {
- connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
- } else {
- connection_.SendPing();
- }
+ connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
EXPECT_FALSE(connection_.HasQueuedData());
}
@@ -5430,11 +5848,7 @@ TEST_P(QuicConnectionTest, SendBlockedImmediately) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
EXPECT_CALL(debug_visitor, OnPacketSent(_, _, _, _)).Times(1);
EXPECT_EQ(0u, connection_.GetStats().blocked_frames_sent);
- if (connection_.use_control_frame_manager()) {
- connection_.SendControlFrame(QuicFrame(new QuicBlockedFrame(1, 3)));
- } else {
- connection_.SendBlocked(3);
- }
+ connection_.SendControlFrame(QuicFrame(new QuicBlockedFrame(1, 3)));
EXPECT_EQ(1u, connection_.GetStats().blocked_frames_sent);
EXPECT_FALSE(connection_.HasQueuedData());
}
@@ -5451,6 +5865,10 @@ TEST_P(QuicConnectionTest, SendingUnencryptedStreamDataFails) {
}
TEST_P(QuicConnectionTest, OnPathDegrading) {
+ if (use_path_degrading_alarm_) {
+ return;
+ }
+
QuicByteCount packet_size;
const size_t kMinTimeoutsBeforePathDegrading = 2;
@@ -5478,6 +5896,140 @@ TEST_P(QuicConnectionTest, OnPathDegrading) {
connection_.GetRetransmissionAlarm()->Fire();
}
+// Includes regression test for https://b.corp.google.com/issues/69979024.
+TEST_P(QuicConnectionTest, PathDegradingAlarm) {
+ if (!use_path_degrading_alarm_) {
+ return;
+ }
+
+ EXPECT_TRUE(connection_.connected());
+ EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+
+ const char data[] = "data";
+ size_t data_size = strlen(data);
+ QuicStreamOffset offset = 0;
+
+ for (int i = 0; i < 2; ++i) {
+ // Send a packet. Now there's a retransmittable packet on the wire, so the
+ // path degrading alarm should be set.
+ connection_.SendStreamDataWithString(1, data, offset, NO_FIN);
+ offset += data_size;
+ EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
+ // Check the deadline of the path degrading alarm.
+ QuicTime::Delta delay =
+ QuicConnectionPeer::GetSentPacketManager(&connection_)
+ ->GetPathDegradingDelay();
+ EXPECT_EQ(clock_.ApproximateNow() + delay,
+ connection_.GetPathDegradingAlarm()->deadline());
+
+ // Send a second packet. The path degrading alarm's deadline should remain
+ // the same.
+ // Regression test for https://b.corp.google.com/issues/69979024.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ QuicTime prev_deadline = connection_.GetPathDegradingAlarm()->deadline();
+ connection_.SendStreamDataWithString(1, data, offset, NO_FIN);
+ offset += data_size;
+ EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_EQ(prev_deadline, connection_.GetPathDegradingAlarm()->deadline());
+
+ // Now receive an ACK of the first packet. This should advance the path
+ // degrading alarm's deadline since forward progress has been made.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ if (i == 0) {
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ }
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
+ QuicAckFrame frame = InitAckFrame({{1u + 2u * i, 2u + 2u * i}});
+ ProcessAckPacket(&frame);
+ EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
+ // Check the deadline of the path degrading alarm.
+ delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
+ ->GetPathDegradingDelay();
+ EXPECT_EQ(clock_.ApproximateNow() + delay,
+ connection_.GetPathDegradingAlarm()->deadline());
+
+ if (i == 0) {
+ // Now receive an ACK of the second packet. Since there are no more
+ // retransmittable packets on the wire, this should cancel the path
+ // degrading alarm.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
+ frame = InitAckFrame({{2, 3}});
+ ProcessAckPacket(&frame);
+ EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ } else {
+ // Advance time to the path degrading alarm's deadline and simulate
+ // firing the alarm.
+ clock_.AdvanceTime(delay);
+ EXPECT_CALL(visitor_, OnPathDegrading());
+ connection_.GetPathDegradingAlarm()->Fire();
+ EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ }
+ }
+}
+
+TEST_P(QuicConnectionTest, RetransmittableOnWireSetsPathDegradingAlarm) {
+ if (!use_path_degrading_alarm_) {
+ return;
+ }
+ const QuicTime::Delta retransmittable_on_wire_timeout =
+ QuicTime::Delta::FromMilliseconds(50);
+ connection_.set_retransmittable_on_wire_timeout(
+ retransmittable_on_wire_timeout);
+
+ EXPECT_TRUE(connection_.connected());
+ EXPECT_CALL(visitor_, HasOpenDynamicStreams()).WillRepeatedly(Return(true));
+
+ EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_FALSE(connection_.GetRetransmittableOnWireAlarm()->IsSet());
+
+ const char data[] = "data";
+ size_t data_size = strlen(data);
+ QuicStreamOffset offset = 0;
+
+ // Send a packet.
+ connection_.SendStreamDataWithString(1, data, offset, NO_FIN);
+ offset += data_size;
+ // Now there's a retransmittable packet on the wire, so the path degrading
+ // alarm should be set.
+ // The retransmittable-on-wire alarm should not be set.
+ EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
+ QuicTime::Delta delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
+ ->GetPathDegradingDelay();
+ EXPECT_EQ(clock_.ApproximateNow() + delay,
+ connection_.GetPathDegradingAlarm()->deadline());
+ EXPECT_FALSE(connection_.GetRetransmittableOnWireAlarm()->IsSet());
+
+ // Now receive an ACK of the packet.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
+ QuicAckFrame frame = InitAckFrame({{1, 2}});
+ ProcessAckPacket(&frame);
+ // No more retransmittable packets on the wire, so the path degrading alarm
+ // should be cancelled, and the retransmittable-on-wire alarm should be set
+ // since a PING might be needed.
+ EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
+ EXPECT_TRUE(connection_.GetRetransmittableOnWireAlarm()->IsSet());
+ EXPECT_EQ(clock_.ApproximateNow() + retransmittable_on_wire_timeout,
+ connection_.GetRetransmittableOnWireAlarm()->deadline());
+
+ // Simulate firing the retransmittable-on-wire alarm and sending a PING.
+ clock_.AdvanceTime(retransmittable_on_wire_timeout);
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
+ }));
+ connection_.GetRetransmittableOnWireAlarm()->Fire();
+
+ // Now there's a retransmittable packet (PING) on the wire, so the path
+ // degrading alarm should be set.
+ EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
+ delay = QuicConnectionPeer::GetSentPacketManager(&connection_)
+ ->GetPathDegradingDelay();
+ EXPECT_EQ(clock_.ApproximateNow() + delay,
+ connection_.GetPathDegradingAlarm()->deadline());
+}
+
TEST_P(QuicConnectionTest, MultipleCallsToCloseConnection) {
// Verifies that multiple calls to CloseConnection do not
// result in multiple attempts to close the connection - it will be marked as
@@ -5741,53 +6293,195 @@ TEST_P(QuicConnectionTest,
connection_.SendProbingRetransmissions();
}
-TEST_P(QuicConnectionTest, HasPendingControlFramesWhenRetransmittingPackets) {
- if (connection_.use_control_frame_manager()) {
- // When use_control_frame_manager is true, the control frame will be
- // buffered in the control frame manager.
- return;
- }
- // This test mimics this scenario: writer get blocked when generator tries to
- // add a control frame, which will be pending. When writer get unblocked, this
- // pending control frame is sent in a packet before retransmissions.
+TEST_P(QuicConnectionTest, PingAfterLastRetransmittablePacketAcked) {
+ const QuicTime::Delta retransmittable_on_wire_timeout =
+ QuicTime::Delta::FromMilliseconds(50);
+ connection_.set_retransmittable_on_wire_timeout(
+ retransmittable_on_wire_timeout);
+
+ EXPECT_TRUE(connection_.connected());
+ EXPECT_CALL(visitor_, HasOpenDynamicStreams()).WillRepeatedly(Return(true));
+
+ const char data[] = "data";
+ size_t data_size = strlen(data);
+ QuicStreamOffset offset = 0;
+
+ // Advance 5ms, send a retransmittable packet to the peer.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ EXPECT_FALSE(connection_.GetRetransmittableOnWireAlarm()->IsSet());
+ connection_.SendStreamDataWithString(1, data, offset, NO_FIN);
+ offset += data_size;
+ EXPECT_FALSE(connection_.GetRetransmittableOnWireAlarm()->IsSet());
+
+ // Advance 5ms, send a second retransmittable packet to the peer.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ EXPECT_FALSE(connection_.GetRetransmittableOnWireAlarm()->IsSet());
+ connection_.SendStreamDataWithString(1, data, offset, NO_FIN);
+ offset += data_size;
+ EXPECT_FALSE(connection_.GetRetransmittableOnWireAlarm()->IsSet());
+
+ // Now receive an ACK of the first packet. This should not set the
+ // retransmittable-on-wire alarm since packet 2 is still on the wire.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- QuicPacketNumber last_packet;
- SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet); // Packet 1
- SendStreamDataToPeer(1, "foos", 3, NO_FIN, &last_packet); // Packet 2
- SendStreamDataToPeer(1, "foos", 7, NO_FIN, &last_packet); // Packet 3
- SendStreamDataToPeer(1, "foos", 11, NO_FIN, &last_packet); // Packet 4
- BlockOnNextWrite();
- connection_.SendStreamDataWithString(1, "foos", 15, NO_FIN); // Packet 5
- EXPECT_EQ(1u, connection_.NumQueuedPackets());
- EXPECT_TRUE(connection_.HasQueuedData());
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
+ QuicAckFrame frame = InitAckFrame({{1, 2}});
+ ProcessAckPacket(&frame);
+ EXPECT_FALSE(connection_.GetRetransmittableOnWireAlarm()->IsSet());
- // This window update frame will be pending in the generator as writer is
- // blocked.
- connection_.SendWindowUpdate(1, 100);
- // Ack 4, nack 1-3.
- QuicAckFrame nack = InitAckFrame({{4, 5}});
- // 3 packets have been NACK'd and lost.
- LostPacketVector lost_packets;
- lost_packets.push_back(LostPacket(1, kMaxPacketSize));
- lost_packets.push_back(LostPacket(2, kMaxPacketSize));
- lost_packets.push_back(LostPacket(3, kMaxPacketSize));
+ // Now receive an ACK of the second packet. This should set the
+ // retransmittable-on-wire alarm now that no retransmittable packets are on
+ // the wire.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
+ frame = InitAckFrame({{2, 3}});
+ ProcessAckPacket(&frame);
+ EXPECT_TRUE(connection_.GetRetransmittableOnWireAlarm()->IsSet());
+ EXPECT_EQ(clock_.ApproximateNow() + retransmittable_on_wire_timeout,
+ connection_.GetRetransmittableOnWireAlarm()->deadline());
+
+ // Now receive a duplicate ACK of the second packet. This should not update
+ // the retransmittable-on-wire alarm.
+ QuicTime prev_deadline =
+ connection_.GetRetransmittableOnWireAlarm()->deadline();
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ frame = InitAckFrame({{2, 3}});
+ ProcessAckPacket(&frame);
+ EXPECT_TRUE(connection_.GetRetransmittableOnWireAlarm()->IsSet());
+ EXPECT_EQ(prev_deadline,
+ connection_.GetRetransmittableOnWireAlarm()->deadline());
- EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _))
- .WillOnce(SetArgPointee<4>(lost_packets));
+ // Simulate the alarm firing and check that a PING is sent.
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
+ }));
+ connection_.GetRetransmittableOnWireAlarm()->Fire();
+ if (GetParam().no_stop_waiting) {
+ EXPECT_EQ(2u, writer_->frame_count());
+ } else {
+ EXPECT_EQ(3u, writer_->frame_count());
+ }
+ ASSERT_EQ(1u, writer_->ping_frames().size());
+}
+
+TEST_P(QuicConnectionTest, NoPingIfRetransmittablePacketSent) {
+ const QuicTime::Delta retransmittable_on_wire_timeout =
+ QuicTime::Delta::FromMilliseconds(50);
+ connection_.set_retransmittable_on_wire_timeout(
+ retransmittable_on_wire_timeout);
+
+ EXPECT_TRUE(connection_.connected());
+ EXPECT_CALL(visitor_, HasOpenDynamicStreams()).WillRepeatedly(Return(true));
+
+ const char data[] = "data";
+ size_t data_size = strlen(data);
+ QuicStreamOffset offset = 0;
+
+ // Advance 5ms, send a retransmittable packet to the peer.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ EXPECT_FALSE(connection_.GetRetransmittableOnWireAlarm()->IsSet());
+ connection_.SendStreamDataWithString(1, data, offset, NO_FIN);
+ offset += data_size;
+ EXPECT_FALSE(connection_.GetRetransmittableOnWireAlarm()->IsSet());
+
+ // Now receive an ACK of the first packet. This should set the
+ // retransmittable-on-wire alarm now that no retransmittable packets are on
+ // the wire.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- ProcessAckPacket(&nack);
+ QuicAckFrame frame = InitAckFrame({{1, 2}});
+ ProcessAckPacket(&frame);
+ EXPECT_TRUE(connection_.GetRetransmittableOnWireAlarm()->IsSet());
+ EXPECT_EQ(clock_.ApproximateNow() + retransmittable_on_wire_timeout,
+ connection_.GetRetransmittableOnWireAlarm()->deadline());
+
+ // Before the alarm fires, send another retransmittable packet. This should
+ // cancel the retransmittable-on-wire alarm since now there's a
+ // retransmittable packet on the wire.
+ connection_.SendStreamDataWithString(1, data, offset, NO_FIN);
+ offset += data_size;
+ EXPECT_FALSE(connection_.GetRetransmittableOnWireAlarm()->IsSet());
+
+ // Now receive an ACK of the second packet. This should set the
+ // retransmittable-on-wire alarm now that no retransmittable packets are on
+ // the wire.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
+ frame = InitAckFrame({{2, 3}});
+ ProcessAckPacket(&frame);
+ EXPECT_TRUE(connection_.GetRetransmittableOnWireAlarm()->IsSet());
+ EXPECT_EQ(clock_.ApproximateNow() + retransmittable_on_wire_timeout,
+ connection_.GetRetransmittableOnWireAlarm()->deadline());
- // Unblock the writer, packet 5 will be sent first, then the window update
- // frame is flushed in a single packet. Finally, packets 1 - 3 are
- // retransmitted.
- writer_->SetWritable();
- if (connection_.session_decides_what_to_write()) {
- // Stream frames 1, 2 and 3 are retransmitted in the same packet.
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(3);
+ // Simulate the alarm firing and check that a PING is sent.
+ writer_->Reset();
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
+ }));
+ connection_.GetRetransmittableOnWireAlarm()->Fire();
+ if (GetParam().no_stop_waiting) {
+ EXPECT_EQ(2u, writer_->frame_count());
} else {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(5);
+ EXPECT_EQ(3u, writer_->frame_count());
}
- connection_.OnCanWrite();
+ ASSERT_EQ(1u, writer_->ping_frames().size());
+}
+
+TEST_P(QuicConnectionTest, OnForwardProgressConfirmed) {
+ EXPECT_CALL(visitor_, OnForwardProgressConfirmed()).Times(Exactly(0));
+ EXPECT_TRUE(connection_.connected());
+
+ const char data[] = "data";
+ size_t data_size = strlen(data);
+ QuicStreamOffset offset = 0;
+
+ // Send two packets.
+ connection_.SendStreamDataWithString(1, data, offset, NO_FIN);
+ offset += data_size;
+ connection_.SendStreamDataWithString(1, data, offset, NO_FIN);
+ offset += data_size;
+
+ // Ack packet 1. This increases the largest_acked to 1, so
+ // OnForwardProgressConfirmed() should be called
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
+ EXPECT_CALL(visitor_, OnForwardProgressConfirmed());
+ QuicAckFrame frame = InitAckFrame({{1, 2}});
+ ProcessAckPacket(&frame);
+
+ // Ack packet 1 again. largest_acked remains at 1, so
+ // OnForwardProgressConfirmed() should not be called.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ frame = InitAckFrame({{1, 2}});
+ ProcessAckPacket(&frame);
+
+ // Ack packet 2. This increases the largest_acked to 2, so
+ // OnForwardProgressConfirmed() should be called.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
+ EXPECT_CALL(visitor_, OnForwardProgressConfirmed());
+ frame = InitAckFrame({{2, 3}});
+ ProcessAckPacket(&frame);
+}
+
+TEST_P(QuicConnectionTest, ValidStatelessResetToken) {
+ const uint128 kTestToken = 1010101;
+ const uint128 kWrongTestToken = 1010100;
+ QuicConfig config;
+ // No token has been received.
+ EXPECT_FALSE(connection_.IsValidStatelessResetToken(kTestToken));
+
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(2);
+ // Token is different from received token.
+ QuicConfigPeer::SetReceivedStatelessResetToken(&config, kTestToken);
+ connection_.SetFromConfig(config);
+ EXPECT_FALSE(connection_.IsValidStatelessResetToken(kWrongTestToken));
+
+ QuicConfigPeer::SetReceivedStatelessResetToken(&config, kTestToken);
+ connection_.SetFromConfig(config);
+ EXPECT_TRUE(connection_.IsValidStatelessResetToken(kTestToken));
}
} // namespace
diff --git a/chromium/net/quic/core/quic_constants.h b/chromium/net/quic/core/quic_constants.h
index 4de2bd66b45..e61b4d3d729 100644
--- a/chromium/net/quic/core/quic_constants.h
+++ b/chromium/net/quic/core/quic_constants.h
@@ -115,14 +115,6 @@ const int64_t kMaximumIdleTimeoutSecs = 60 * 10; // 10 minutes.
// The default timeout for a connection until the crypto handshake succeeds.
const int64_t kMaxTimeForCryptoHandshakeSecs = 10; // 10 secs.
-// The default maximum time QUIC session could be on non-default network before
-// migrate back to default network.
-const int64_t kMaxTimeOnNonDefaultNetworkSecs = 128;
-
-// The default maximum number of migrations to non default network on path
-// degrading per network.
-const int64_t kMaxMigrationsToNonDefaultNetworkOnPathDegrading = 5;
-
// Default limit on the number of undecryptable packets the connection buffers
// before the CHLO/SHLO arrive.
const size_t kDefaultMaxUndecryptablePackets = 10;
@@ -213,6 +205,10 @@ const QuicByteCount kMaxStreamLength = (UINT64_C(1) << 62) - 1;
// The max value that can be encoded using IETF Var Ints.
const uint64_t kMaxIetfVarInt = UINT64_C(0x3fffffffffffffff);
+
+// The maximum stream id value that is supported - (2^32)-1
+const QuicStreamId kMaxQuicStreamId = 0xffffffff;
+
} // namespace net
#endif // NET_QUIC_CORE_QUIC_CONSTANTS_H_
diff --git a/chromium/net/quic/core/quic_control_frame_manager.cc b/chromium/net/quic/core/quic_control_frame_manager.cc
index c94d7f75624..a8897fe439c 100644
--- a/chromium/net/quic/core/quic_control_frame_manager.cc
+++ b/chromium/net/quic/core/quic_control_frame_manager.cc
@@ -108,7 +108,7 @@ void QuicControlFrameManager::OnControlFrameSent(const QuicFrame& frame) {
session_->connection()->CloseConnection(
QUIC_INTERNAL_ERROR, "Try to send control frames out of order",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- RecordInternalErrorLocation(QUIC_CONTROL_FRAME_MANAGER_1);
+ RecordInternalErrorLocation(QUIC_CONTROL_FRAME_MANAGER_CONTROL_FRAME_SENT);
return;
}
++least_unsent_;
@@ -125,7 +125,7 @@ bool QuicControlFrameManager::OnControlFrameAcked(const QuicFrame& frame) {
session_->connection()->CloseConnection(
QUIC_INTERNAL_ERROR, "Try to ack unsent control frame",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- RecordInternalErrorLocation(QUIC_CONTROL_FRAME_MANAGER_2);
+ RecordInternalErrorLocation(QUIC_CONTROL_FRAME_MANAGER_CONTROL_FRAME_ACKED);
return false;
}
if (id < least_unacked_ ||
@@ -161,7 +161,7 @@ void QuicControlFrameManager::OnControlFrameLost(const QuicFrame& frame) {
session_->connection()->CloseConnection(
QUIC_INTERNAL_ERROR, "Try to mark unsent control frame as lost",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- RecordInternalErrorLocation(QUIC_CONTROL_FRAME_MANAGER_3);
+ RecordInternalErrorLocation(QUIC_CONTROL_FRAME_MANAGER_CONTROL_FRAME_LOST);
return;
}
if (id < least_unacked_ ||
@@ -225,7 +225,8 @@ bool QuicControlFrameManager::RetransmitControlFrame(const QuicFrame& frame) {
session_->connection()->CloseConnection(
QUIC_INTERNAL_ERROR, "Try to retransmit unsent control frame",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
- RecordInternalErrorLocation(QUIC_CONTROL_FRAME_MANAGER_4);
+ RecordInternalErrorLocation(
+ QUIC_CONTROL_FRAME_MANAGER_RETRANSMIT_CONTROL_FRAME);
return false;
}
if (id < least_unacked_ ||
diff --git a/chromium/net/quic/core/quic_control_frame_manager_test.cc b/chromium/net/quic/core/quic_control_frame_manager_test.cc
index bc2cc32f5a2..51a415b9f44 100644
--- a/chromium/net/quic/core/quic_control_frame_manager_test.cc
+++ b/chromium/net/quic/core/quic_control_frame_manager_test.cc
@@ -37,7 +37,6 @@ class QuicControlFrameManagerTest : public QuicTest {
protected:
void Initialize() {
- SetQuicReloadableFlag(quic_use_control_frame_manager, true);
connection_ = new MockQuicConnection(&helper_, &alarm_factory_,
Perspective::IS_SERVER);
session_ = QuicMakeUnique<StrictMock<MockQuicSession>>(connection_);
diff --git a/chromium/net/quic/core/quic_crypto_client_handshaker.cc b/chromium/net/quic/core/quic_crypto_client_handshaker.cc
index b6f57e4006f..0fe6c37bf80 100644
--- a/chromium/net/quic/core/quic_crypto_client_handshaker.cc
+++ b/chromium/net/quic/core/quic_crypto_client_handshaker.cc
@@ -328,14 +328,14 @@ void QuicCryptoClientHandshaker::DoSendCHLO(
if (max_packet_size <= kFramingOverhead) {
QUIC_DLOG(DFATAL) << "max_packet_length (" << max_packet_size
<< ") has no room for framing overhead.";
- RecordInternalErrorLocation(QUIC_CRYPTO_CLIENT_HANDSHAKER_1);
+ RecordInternalErrorLocation(QUIC_CRYPTO_CLIENT_HANDSHAKER_MAX_PACKET);
stream_->CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
"max_packet_size too smalll");
return;
}
if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) {
QUIC_DLOG(DFATAL) << "Client hello won't fit in a single packet.";
- RecordInternalErrorLocation(QUIC_CRYPTO_CLIENT_HANDSHAKER_2);
+ RecordInternalErrorLocation(QUIC_CRYPTO_CLIENT_HANDSHAKER_CHLO);
stream_->CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
"CHLO too large");
return;
@@ -384,13 +384,13 @@ void QuicCryptoClientHandshaker::DoSendCHLO(
// Be prepared to decrypt with the new server write key.
session()->connection()->SetAlternativeDecrypter(
ENCRYPTION_INITIAL,
- crypto_negotiated_params_->initial_crypters.decrypter.release(),
+ std::move(crypto_negotiated_params_->initial_crypters.decrypter),
true /* latch once used */);
// Send subsequent packets under encryption on the assumption that the
// server will accept the handshake.
session()->connection()->SetEncrypter(
ENCRYPTION_INITIAL,
- crypto_negotiated_params_->initial_crypters.encrypter.release());
+ std::move(crypto_negotiated_params_->initial_crypters.encrypter));
session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
// TODO(ianswett): Merge ENCRYPTION_REESTABLISHED and
@@ -644,10 +644,10 @@ void QuicCryptoClientHandshaker::DoReceiveSHLO(
// with the FORWARD_SECURE key until it receives a FORWARD_SECURE
// packet from the client.
session()->connection()->SetAlternativeDecrypter(
- ENCRYPTION_FORWARD_SECURE, crypters->decrypter.release(),
+ ENCRYPTION_FORWARD_SECURE, std::move(crypters->decrypter),
false /* don't latch */);
session()->connection()->SetEncrypter(ENCRYPTION_FORWARD_SECURE,
- crypters->encrypter.release());
+ std::move(crypters->encrypter));
session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
handshake_confirmed_ = true;
diff --git a/chromium/net/quic/core/quic_crypto_client_stream_test.cc b/chromium/net/quic/core/quic_crypto_client_stream_test.cc
index c62d7528a7e..5ee199732e6 100644
--- a/chromium/net/quic/core/quic_crypto_client_stream_test.cc
+++ b/chromium/net/quic/core/quic_crypto_client_stream_test.cc
@@ -98,6 +98,7 @@ TEST_F(QuicCryptoClientStreamTest, ConnectedAfterSHLO) {
TEST_F(QuicCryptoClientStreamTest, ConnectedAfterTlsHandshake) {
FLAGS_quic_supports_tls_handshake = true;
+ SetQuicReloadableFlag(delay_quic_server_handshaker_construction, true);
supported_versions_.clear();
for (QuicTransportVersion transport_version :
AllSupportedTransportVersions()) {
diff --git a/chromium/net/quic/core/quic_crypto_server_handshaker.cc b/chromium/net/quic/core/quic_crypto_server_handshaker.cc
index f80a1c91ada..351609377ec 100644
--- a/chromium/net/quic/core/quic_crypto_server_handshaker.cc
+++ b/chromium/net/quic/core/quic_crypto_server_handshaker.cc
@@ -225,25 +225,25 @@ void QuicCryptoServerHandshaker::
// NOTE: the SHLO will be encrypted with the new server write key.
session()->connection()->SetEncrypter(
ENCRYPTION_INITIAL,
- crypto_negotiated_params_->initial_crypters.encrypter.release());
+ std::move(crypto_negotiated_params_->initial_crypters.encrypter));
session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
// Set the decrypter immediately so that we no longer accept unencrypted
// packets.
session()->connection()->SetDecrypter(
ENCRYPTION_INITIAL,
- crypto_negotiated_params_->initial_crypters.decrypter.release());
+ std::move(crypto_negotiated_params_->initial_crypters.decrypter));
session()->connection()->SetDiversificationNonce(*diversification_nonce);
SendHandshakeMessage(*reply);
session()->connection()->SetEncrypter(
ENCRYPTION_FORWARD_SECURE,
- crypto_negotiated_params_->forward_secure_crypters.encrypter.release());
+ std::move(crypto_negotiated_params_->forward_secure_crypters.encrypter));
session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
session()->connection()->SetAlternativeDecrypter(
ENCRYPTION_FORWARD_SECURE,
- crypto_negotiated_params_->forward_secure_crypters.decrypter.release(),
+ std::move(crypto_negotiated_params_->forward_secure_crypters.decrypter),
false /* don't latch */);
encryption_established_ = true;
diff --git a/chromium/net/quic/core/quic_crypto_server_stream.cc b/chromium/net/quic/core/quic_crypto_server_stream.cc
index 1dff1316a09..001d4ba6135 100644
--- a/chromium/net/quic/core/quic_crypto_server_stream.cc
+++ b/chromium/net/quic/core/quic_crypto_server_stream.cc
@@ -16,6 +16,7 @@
#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_session.h"
#include "net/quic/core/tls_server_handshaker.h"
+#include "net/quic/platform/api/quic_flag_utils.h"
#include "net/quic/platform/api/quic_flags.h"
#include "net/quic/platform/api/quic_logging.h"
#include "net/quic/platform/api/quic_ptr_util.h"
@@ -171,6 +172,8 @@ void QuicCryptoServerStream::OnSuccessfulVersionNegotiation(
if (!delay_handshaker_construction_) {
return;
}
+ QUIC_FLAG_COUNT(
+ quic_reloadable_flag_delay_quic_server_handshaker_construction);
CHECK(!handshaker_);
switch (session()->connection()->version().handshake_protocol) {
case PROTOCOL_QUIC_CRYPTO:
diff --git a/chromium/net/quic/core/quic_crypto_stream.cc b/chromium/net/quic/core/quic_crypto_stream.cc
index 00c3e33d5f5..2b2e70fc893 100644
--- a/chromium/net/quic/core/quic_crypto_stream.cc
+++ b/chromium/net/quic/core/quic_crypto_stream.cc
@@ -23,7 +23,7 @@ namespace net {
" ")
QuicCryptoStream::QuicCryptoStream(QuicSession* session)
- : QuicStream(kCryptoStreamId, session) {
+ : QuicStream(kCryptoStreamId, session, /*is_static=*/true) {
// The crypto stream is exempt from connection level flow control.
DisableConnectionFlowControlForThisStream();
}
diff --git a/chromium/net/quic/core/quic_crypto_stream_test.cc b/chromium/net/quic/core/quic_crypto_stream_test.cc
index 26429163155..01dcc63aabc 100644
--- a/chromium/net/quic/core/quic_crypto_stream_test.cc
+++ b/chromium/net/quic/core/quic_crypto_stream_test.cc
@@ -68,8 +68,10 @@ class QuicCryptoStreamTest : public QuicTest {
: connection_(new MockQuicConnection(&helper_,
&alarm_factory_,
Perspective::IS_CLIENT)),
- session_(connection_),
- stream_(&session_) {
+ session_(connection_, /*create_mock_crypto_stream=*/false) {
+ stream_ = new MockQuicCryptoStream(&session_);
+ session_.SetCryptoStream(stream_);
+ session_.Initialize();
message_.set_tag(kSHLO);
message_.SetStringPiece(1, "abc");
message_.SetStringPiece(2, "def");
@@ -87,7 +89,7 @@ class QuicCryptoStreamTest : public QuicTest {
MockAlarmFactory alarm_factory_;
MockQuicConnection* connection_;
MockQuicSpdySession session_;
- MockQuicCryptoStream stream_;
+ MockQuicCryptoStream* stream_;
CryptoHandshakeMessage message_;
std::unique_ptr<QuicData> message_data_;
@@ -96,16 +98,16 @@ class QuicCryptoStreamTest : public QuicTest {
};
TEST_F(QuicCryptoStreamTest, NotInitiallyConected) {
- EXPECT_FALSE(stream_.encryption_established());
- EXPECT_FALSE(stream_.handshake_confirmed());
+ EXPECT_FALSE(stream_->encryption_established());
+ EXPECT_FALSE(stream_->handshake_confirmed());
}
TEST_F(QuicCryptoStreamTest, ProcessRawData) {
- stream_.OnStreamFrame(QuicStreamFrame(kCryptoStreamId, /*fin=*/false,
- /*offset=*/0,
- message_data_->AsStringPiece()));
- ASSERT_EQ(1u, stream_.messages()->size());
- const CryptoHandshakeMessage& message = (*stream_.messages())[0];
+ stream_->OnStreamFrame(QuicStreamFrame(kCryptoStreamId, /*fin=*/false,
+ /*offset=*/0,
+ message_data_->AsStringPiece()));
+ ASSERT_EQ(1u, stream_->messages()->size());
+ const CryptoHandshakeMessage& message = (*stream_->messages())[0];
EXPECT_EQ(kSHLO, message.tag());
EXPECT_EQ(2u, message.tag_value_map().size());
EXPECT_EQ("abc", crypto_test_utils::GetValueForTag(message, 1));
@@ -122,13 +124,13 @@ TEST_F(QuicCryptoStreamTest, ProcessBadData) {
EXPECT_CALL(*connection_, CloseConnection(QUIC_CRYPTO_TAGS_OUT_OF_ORDER,
testing::_, testing::_));
- stream_.OnStreamFrame(
+ stream_->OnStreamFrame(
QuicStreamFrame(kCryptoStreamId, /*fin=*/false, /*offset=*/0, bad));
}
TEST_F(QuicCryptoStreamTest, NoConnectionLevelFlowControl) {
EXPECT_FALSE(
- QuicStreamPeer::StreamContributesToConnectionFlowControl(&stream_));
+ QuicStreamPeer::StreamContributesToConnectionFlowControl(stream_));
}
TEST_F(QuicCryptoStreamTest, RetransmitCryptoData) {
@@ -138,21 +140,21 @@ TEST_F(QuicCryptoStreamTest, RetransmitCryptoData) {
QuicString data(1350, 'a');
EXPECT_CALL(session_, WritevData(_, kCryptoStreamId, 1350, 0, _))
.WillOnce(Invoke(MockQuicSession::ConsumeData));
- stream_.WriteOrBufferData(data, false, nullptr);
+ stream_->WriteOrBufferData(data, false, nullptr);
// Send [1350, 2700) in ENCRYPTION_INITIAL.
connection_->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
EXPECT_EQ(ENCRYPTION_INITIAL, connection_->encryption_level());
EXPECT_CALL(session_, WritevData(_, kCryptoStreamId, 1350, 1350, _))
.WillOnce(Invoke(MockQuicSession::ConsumeData));
- stream_.WriteOrBufferData(data, false, nullptr);
+ stream_->WriteOrBufferData(data, false, nullptr);
connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
// Lost [0, 1000).
- stream_.OnStreamFrameLost(0, 1000, false);
- EXPECT_TRUE(stream_.HasPendingRetransmission());
+ stream_->OnStreamFrameLost(0, 1000, false);
+ EXPECT_TRUE(stream_->HasPendingRetransmission());
// Lost [1200, 2000).
- stream_.OnStreamFrameLost(1200, 800, false);
+ stream_->OnStreamFrameLost(1200, 800, false);
EXPECT_CALL(session_, WritevData(_, kCryptoStreamId, 1000, 0, _))
.WillOnce(Invoke(MockQuicSession::ConsumeData));
// Verify [1200, 2000) are sent in [1200, 1350) and [1350, 2000) because of
@@ -161,8 +163,8 @@ TEST_F(QuicCryptoStreamTest, RetransmitCryptoData) {
.WillOnce(Invoke(MockQuicSession::ConsumeData));
EXPECT_CALL(session_, WritevData(_, kCryptoStreamId, 650, 1350, _))
.WillOnce(Invoke(MockQuicSession::ConsumeData));
- stream_.OnCanWrite();
- EXPECT_FALSE(stream_.HasPendingRetransmission());
+ stream_->OnCanWrite();
+ EXPECT_FALSE(stream_->HasPendingRetransmission());
// Verify connection's encryption level has restored.
EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
}
@@ -173,29 +175,29 @@ TEST_F(QuicCryptoStreamTest, NeuterUnencryptedStreamData) {
QuicString data(1350, 'a');
EXPECT_CALL(session_, WritevData(_, kCryptoStreamId, 1350, 0, _))
.WillOnce(Invoke(MockQuicSession::ConsumeData));
- stream_.WriteOrBufferData(data, false, nullptr);
+ stream_->WriteOrBufferData(data, false, nullptr);
// Send [1350, 2700) in ENCRYPTION_INITIAL.
connection_->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
EXPECT_EQ(ENCRYPTION_INITIAL, connection_->encryption_level());
EXPECT_CALL(session_, WritevData(_, kCryptoStreamId, 1350, 1350, _))
.WillOnce(Invoke(MockQuicSession::ConsumeData));
- stream_.WriteOrBufferData(data, false, nullptr);
+ stream_->WriteOrBufferData(data, false, nullptr);
// Lost [0, 1350).
- stream_.OnStreamFrameLost(0, 1350, false);
- EXPECT_TRUE(stream_.HasPendingRetransmission());
+ stream_->OnStreamFrameLost(0, 1350, false);
+ EXPECT_TRUE(stream_->HasPendingRetransmission());
// Neuters [0, 1350).
- stream_.NeuterUnencryptedStreamData();
- EXPECT_FALSE(stream_.HasPendingRetransmission());
+ stream_->NeuterUnencryptedStreamData();
+ EXPECT_FALSE(stream_->HasPendingRetransmission());
// Lost [0, 1350) again.
- stream_.OnStreamFrameLost(0, 1350, false);
- EXPECT_FALSE(stream_.HasPendingRetransmission());
+ stream_->OnStreamFrameLost(0, 1350, false);
+ EXPECT_FALSE(stream_->HasPendingRetransmission());
// Lost [1350, 2000).
- stream_.OnStreamFrameLost(1350, 650, false);
- EXPECT_TRUE(stream_.HasPendingRetransmission());
- stream_.NeuterUnencryptedStreamData();
- EXPECT_TRUE(stream_.HasPendingRetransmission());
+ stream_->OnStreamFrameLost(1350, 650, false);
+ EXPECT_TRUE(stream_->HasPendingRetransmission());
+ stream_->NeuterUnencryptedStreamData();
+ EXPECT_TRUE(stream_->HasPendingRetransmission());
}
TEST_F(QuicCryptoStreamTest, RetransmitStreamData) {
@@ -205,27 +207,27 @@ TEST_F(QuicCryptoStreamTest, RetransmitStreamData) {
QuicString data(1350, 'a');
EXPECT_CALL(session_, WritevData(_, kCryptoStreamId, 1350, 0, _))
.WillOnce(Invoke(MockQuicSession::ConsumeData));
- stream_.WriteOrBufferData(data, false, nullptr);
+ stream_->WriteOrBufferData(data, false, nullptr);
// Send [1350, 2700) in ENCRYPTION_INITIAL.
connection_->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
EXPECT_EQ(ENCRYPTION_INITIAL, connection_->encryption_level());
EXPECT_CALL(session_, WritevData(_, kCryptoStreamId, 1350, 1350, _))
.WillOnce(Invoke(MockQuicSession::ConsumeData));
- stream_.WriteOrBufferData(data, false, nullptr);
+ stream_->WriteOrBufferData(data, false, nullptr);
connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
// Ack [2000, 2500).
- stream_.OnStreamFrameAcked(2000, 500, false, QuicTime::Delta::Zero());
+ stream_->OnStreamFrameAcked(2000, 500, false, QuicTime::Delta::Zero());
// Force crypto stream to send [1350, 2700) and only [1350, 1500) is consumed.
EXPECT_CALL(session_, WritevData(_, kCryptoStreamId, 650, 1350, _))
.WillOnce(InvokeWithoutArgs([this]() {
- return MockQuicSession::ConsumeData(&stream_, kCryptoStreamId, 150,
- 1350, NO_FIN);
+ return MockQuicSession::ConsumeData(stream_, kCryptoStreamId, 150, 1350,
+ NO_FIN);
}));
- EXPECT_FALSE(stream_.RetransmitStreamData(1350, 1350, false));
+ EXPECT_FALSE(stream_->RetransmitStreamData(1350, 1350, false));
// Verify connection's encryption level has restored.
EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
@@ -234,13 +236,13 @@ TEST_F(QuicCryptoStreamTest, RetransmitStreamData) {
.WillOnce(Invoke(MockQuicSession::ConsumeData));
EXPECT_CALL(session_, WritevData(_, kCryptoStreamId, 200, 2500, _))
.WillOnce(Invoke(MockQuicSession::ConsumeData));
- EXPECT_TRUE(stream_.RetransmitStreamData(1350, 1350, false));
+ EXPECT_TRUE(stream_->RetransmitStreamData(1350, 1350, false));
// Verify connection's encryption level has restored.
EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
EXPECT_CALL(session_, WritevData(_, _, _, _, _)).Times(0);
// Force to send an empty frame.
- EXPECT_TRUE(stream_.RetransmitStreamData(0, 0, false));
+ EXPECT_TRUE(stream_->RetransmitStreamData(0, 0, false));
}
} // namespace
diff --git a/chromium/net/quic/core/quic_data_reader.cc b/chromium/net/quic/core/quic_data_reader.cc
index 913d3749217..e6c07e8d206 100644
--- a/chromium/net/quic/core/quic_data_reader.cc
+++ b/chromium/net/quic/core/quic_data_reader.cc
@@ -4,7 +4,6 @@
#include "net/quic/core/quic_data_reader.h"
-#include "net/base/int128.h"
#include "net/quic/core/quic_packets.h"
#include "net/quic/core/quic_utils.h"
#include "net/quic/platform/api/quic_bug_tracker.h"
@@ -267,4 +266,17 @@ bool QuicDataReader::ReadVarInt62(uint64_t* result) {
return false;
}
+bool QuicDataReader::ReadVarIntStreamId(QuicStreamId* result) {
+ uint64_t temp_uint64;
+ // TODO(fkastenholz): We should disambiguate read-errors from
+ // value errors.
+ if (!this->ReadVarInt62(&temp_uint64)) {
+ return false;
+ }
+ if (temp_uint64 > kMaxQuicStreamId) {
+ return false;
+ }
+ *result = static_cast<QuicStreamId>(temp_uint64);
+ return true;
+}
} // namespace net
diff --git a/chromium/net/quic/core/quic_data_reader.h b/chromium/net/quic/core/quic_data_reader.h
index cbd23ba8530..f59e5496864 100644
--- a/chromium/net/quic/core/quic_data_reader.h
+++ b/chromium/net/quic/core/quic_data_reader.h
@@ -9,7 +9,6 @@
#include <cstdint>
#include "base/macros.h"
-#include "net/base/int128.h"
#include "net/quic/core/quic_types.h"
#include "net/quic/platform/api/quic_endian.h"
#include "net/quic/platform/api/quic_export.h"
@@ -131,10 +130,16 @@ class QUIC_EXPORT_PRIVATE QuicDataReader {
// Returns true if it works, false if not. The only error is that
// there is not enough in the buffer to read the number.
// If there is an error, |*result| is not altered.
- // Numbers are encoded per the rules in draft-ietf-quic-transport-08.txt
+ // Numbers are encoded per the rules in draft-ietf-quic-transport-10.txt
// 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
+ // returns false if there is a read error or if the value is
+ // greater than (2^32)-1.
+ bool ReadVarIntStreamId(QuicStreamId* result);
+
private:
// Returns true if the underlying buffer has enough room to read the given
// amount of bytes.
diff --git a/chromium/net/quic/core/quic_data_writer.h b/chromium/net/quic/core/quic_data_writer.h
index b87d151267c..79d05e74c4a 100644
--- a/chromium/net/quic/core/quic_data_writer.h
+++ b/chromium/net/quic/core/quic_data_writer.h
@@ -9,7 +9,6 @@
#include <cstdint>
#include "base/macros.h"
-#include "net/base/int128.h"
#include "net/quic/core/quic_packets.h"
#include "net/quic/platform/api/quic_endian.h"
#include "net/quic/platform/api/quic_export.h"
diff --git a/chromium/net/quic/core/quic_data_writer_test.cc b/chromium/net/quic/core/quic_data_writer_test.cc
index 3e8540c2dfc..f2d8b2d7088 100644
--- a/chromium/net/quic/core/quic_data_writer_test.cc
+++ b/chromium/net/quic/core/quic_data_writer_test.cc
@@ -916,6 +916,49 @@ TEST_P(QuicDataWriterTest, MultiVarInt1) {
EXPECT_FALSE(reader.ReadVarInt62(&test_val));
}
+// Test encoding/decoding stream-id values.
+void EncodeDecodeStreamId(uint64_t value_in, bool expected_decode_result) {
+ char buffer[1 * kMultiVarCount];
+ memset(buffer, 0, sizeof(buffer));
+
+ // Encode the given Stream ID.
+ QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
+ Endianness::NETWORK_BYTE_ORDER);
+ EXPECT_TRUE(writer.WriteVarInt62(value_in));
+
+ QuicDataReader reader(buffer, sizeof(buffer), Endianness::NETWORK_BYTE_ORDER);
+ QuicStreamId received_stream_id;
+ bool read_result = reader.ReadVarIntStreamId(&received_stream_id);
+ EXPECT_EQ(expected_decode_result, read_result);
+ if (read_result) {
+ EXPECT_EQ(value_in, received_stream_id);
+ }
+}
+
+// Test writing & reading stream-ids of various value.
+TEST_P(QuicDataWriterTest, StreamId1) {
+ // Check a 1-byte QuicStreamId, should work
+ EncodeDecodeStreamId(UINT64_C(0x15), true);
+
+ // Check a 2-byte QuicStream ID. It should work.
+ EncodeDecodeStreamId(UINT64_C(0x1567), true);
+
+ // Check a QuicStreamId that requires 4 bytes of encoding
+ // This should work.
+ EncodeDecodeStreamId(UINT64_C(0x34567890), true);
+
+ // Check a QuicStreamId that requires 8 bytes of encoding
+ // but whose value is in the acceptable range.
+ // This should work.
+ EncodeDecodeStreamId(UINT64_C(0xf4567890), true);
+
+ // Check QuicStreamIds that require 8 bytes of encoding
+ // and whose value is not acceptable.
+ // This should fail.
+ EncodeDecodeStreamId(UINT64_C(0x100000000), false);
+ EncodeDecodeStreamId(UINT64_C(0x3fffffffffffffff), false);
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/core/quic_error_codes.h b/chromium/net/quic/core/quic_error_codes.h
index d79970d811c..88fcca8f2f4 100644
--- a/chromium/net/quic/core/quic_error_codes.h
+++ b/chromium/net/quic/core/quic_error_codes.h
@@ -295,34 +295,35 @@ QUIC_EXPORT_PRIVATE const char* QuicRstStreamErrorCodeToString(
QuicRstStreamErrorCode error);
// Returns the name of the QuicErrorCode as a char*
-QUIC_EXPORT_PRIVATE const char* QuicErrorCodeToString(QuicErrorCode error);
+QUIC_EXPORT const char* QuicErrorCodeToString(QuicErrorCode error);
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
// TODO(rch): Remove this once the cause of the INTERNAL_ERROR increase is
// determined.
enum QuicInternalErrorLocation {
- QUIC_CHROMIUM_CLIENT_SESSION = 0,
- QUIC_CONNECTION_1 = 1,
- QUIC_CONNECTION_2 = 2,
- QUIC_CONNECTION_3 = 3,
- QUIC_CONNECTION_4 = 4,
- QUIC_CONTROL_FRAME_MANAGER_1 = 5,
- QUIC_CONTROL_FRAME_MANAGER_2 = 6,
- QUIC_CONTROL_FRAME_MANAGER_3 = 7,
- QUIC_CONTROL_FRAME_MANAGER_4 = 8,
- QUIC_CRYPTO_CLIENT_HANDSHAKER_1 = 9,
- QUIC_CRYPTO_CLIENT_HANDSHAKER_2 = 10,
+ QUIC_CHROMIUM_CLIENT_SESSION_DESTRUCTOR = 0,
+ QUIC_CONNECTION_PROTOCOL_VERSION_MISMATCH = 1,
+ QUIC_CONNECTION_VERSION_NEGOTIATION_PACKET = 2,
+ QUIC_CONNECTION_UNAUTHENTICATED_HEADER = 3,
+ QUIC_CONNECTION_WRITE_PACKET = 4,
+ QUIC_CONTROL_FRAME_MANAGER_CONTROL_FRAME_SENT = 5,
+ QUIC_CONTROL_FRAME_MANAGER_CONTROL_FRAME_ACKED = 6,
+ QUIC_CONTROL_FRAME_MANAGER_CONTROL_FRAME_LOST = 7,
+ QUIC_CONTROL_FRAME_MANAGER_RETRANSMIT_CONTROL_FRAME = 8,
+ QUIC_CRYPTO_CLIENT_HANDSHAKER_MAX_PACKET = 9,
+ QUIC_CRYPTO_CLIENT_HANDSHAKER_CHLO = 10,
QUIC_ERROR_CODES = 11,
QUIC_FRAMER = 12,
QUIC_HEADERS_STREAM = 13,
- QUIC_SESSION_1 = 14,
- QUIC_SESSION_2 = 15,
- QUIC_SESSION_3 = 16,
+ QUIC_SESSION_ON_CAN_WRITE = 14,
+ QUIC_SESSION_WRITEV_DATA = 15,
+ QUIC_SESSION_STREAM_FRAME_RETRANSMITTED = 16,
QUIC_SPDY_SESSION = 17,
- QUIC_STREAM_1 = 18,
- QUIC_STREAM_2 = 19,
+ QUIC_STREAM_ACKED_UNSENT_DATA = 18,
+ QUIC_STREAM_ACKED_UNSENT_FIN = 19,
QUIC_STREAM_SEQUENCER_BUFFER = 20,
+ QUIC_CHROMIUM_CLIENT_SESSION_CLOSE_SESSION_ON_ERROR = 21,
INTERNAL_ERROR_LOCATION_MAX
};
diff --git a/chromium/net/quic/core/quic_flags_list.h b/chromium/net/quic/core/quic_flags_list.h
index 53c55c2f8df..25235a77f14 100644
--- a/chromium/net/quic/core/quic_flags_list.h
+++ b/chromium/net/quic/core/quic_flags_list.h
@@ -3,7 +3,9 @@
// found in the LICENSE file.
// This file intentionally does not have header guards, it's included
-// inside a macro to generate values.
+// inside a macro to generate values. The following line silences a
+// presubmit warning that would otherwise be triggered by this:
+// no-include-guard-because-multiply-included
// This file contains the list of QUIC protocol flags.
@@ -96,10 +98,6 @@ QUIC_FLAG(uint32_t, FLAGS_quic_send_buffer_max_data_slice_size, 4096u)
// protocol.
QUIC_FLAG(bool, FLAGS_quic_supports_tls_handshake, false)
-// If true, QUIC can take ownership of data provided in a reference counted
-// memory to avoid data copy.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_mem_slices, false)
-
// Allow QUIC to accept initial packet numbers that are random, not 1.
QUIC_FLAG(bool, FLAGS_quic_restart_flag_quic_enable_accept_random_ipn, false)
@@ -116,65 +114,133 @@ QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_stream_too_long, false)
// TLP instead of 2.
QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_one_tlp, false)
-// If true, QuicStreamSendBuffer keeps track of the slice which next write
-// should get data from if writing new data.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_write_index, true)
-
-// If true, when WINDOW_UPDATE is received, add stream to session's write
-// blocked list and let session unblock it later.
-QUIC_FLAG(bool,
- FLAGS_quic_reloadable_flag_quic_streams_unblocked_by_session2,
- false)
-
-// If true, inspects CHLO packets for indicator tags to allow early session
-// creation.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_inspect_chlo_tags, true)
-
-// When true, ignore the specified ack delay if it causes the RTT sample to be
-// less than min_rtt.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_min_rtt_ack_delay, true)
-
-// If true, plugin control frame manager to QuicSession, and let it manage sent
-// control frames.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_control_frame_manager, true)
// When true, allows two connection options to run experiments with using max
// ack delay as described in QUIC IETF.
QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_max_ack_delay, false)
-// If ture, sender will close connection when there are too many outstanding
-// sent packets
-QUIC_FLAG(
- bool,
- FLAGS_quic_reloadable_flag_quic_close_session_on_too_many_outstanding_sent_packets,
- false)
-
// If true, enable QUIC v99.
QUIC_FLAG(bool, FLAGS_quic_enable_version_99, false)
// If true, enable QUIC version 42.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_42_2, false)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_42_2, true)
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_37, false)
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_38, false)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_37, true)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_38, true)
QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_41, false)
// Delays construction of QuicCryptoServerStream::HandshakerDelegate
// until QuicCryptoServerStream::OnSuccessfulVersionNegotiation is called
QUIC_FLAG(bool,
FLAGS_quic_reloadable_flag_delay_quic_server_handshaker_construction,
- false)
+ true)
// Controls whether QuicConnection::OnProtocolVersionMismatch calls
// QuicFramer::set_version before or after calling
// OnSuccessfulVersionNegotiation.
QUIC_FLAG(bool,
FLAGS_quic_reloadable_flag_quic_store_version_before_signalling,
- false)
+ true)
// When true, enable connection options to have no min TLP and RTO,
// and also allow IETF style TLP.
QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_max_ack_delay2, false)
+// If true, MemSlices in the send buffer is freed out of order.
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_free_mem_slice_out_of_order,
+ false)
+
// If true, framer will process and report ack frame incrementally.
QUIC_FLAG(bool,
- FLAGS_quic_reloadable_flag_quic_use_incremental_ack_processing,
- false) \ No newline at end of file
+ FLAGS_quic_reloadable_flag_quic_use_incremental_ack_processing3,
+ false)
+
+// If true, Http2FrameDecoderAdapter will pass decoded HTTP/2 SETTINGS through
+// the SpdyFramerVisitorInterface callback OnSetting(), which will also accept
+// unknown SETTINGS IDs.
+QUIC_FLAG(bool, FLAGS_quic_restart_flag_http2_propagate_unknown_settings, true)
+
+// If true, enable fast path in QuicStream::OnStreamDataAcked.
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_fast_path_on_stream_data_acked,
+ false)
+
+// If true, fix a use-after-free bug caused by writing an out-of-order queued
+// packet.
+QUIC_FLAG(
+ bool,
+ FLAGS_quic_reloadable_flag_quic_fix_write_out_of_order_queued_packet_crash,
+ true)
+
+// If true, QUIC streams are registered in the QuicStream constructor instead
+// of in the QuicSpdyStream constructor.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_register_streams_early2, true)
+
+// If this flag and
+// FLAGS_quic_reloadable_flag_quic_fix_write_out_of_order_queued_packet_crash
+// are both ture, QUIC will clear queued packets before sending connectivity
+// probing packets.
+QUIC_FLAG(
+ bool,
+ FLAGS_quic_reloadable_flag_quic_clear_queued_packets_before_sending_connectivity_probing,
+ false)
+
+// When true, this flag has QuicConnection call
+// QuicConnectionVisitorInterface::OnSuccessfulVersionNegotiation earlier when
+// processing the packet header.
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_server_early_version_negotiation,
+ false)
+
+// If true, QUIC will always discard outgoing packets after connection close.
+// Currently out-of-order outgoing packets are not discarded
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_always_discard_packets_after_close,
+ false)
+
+// If true, stop sending a redundant PING every 20 acks.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_remove_redundant_ping, true)
+
+// If true, when a stream is reset by peer with error, it should not be added to
+// zombie streams.
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_reset_stream_is_not_zombie,
+ true)
+
+// If true, when a packet write for connectivity probe does not complete
+// successfully synchronously, connection will not be affected, i.e., blocked or
+// closed, if the probing packet writer is not the default writer.
+QUIC_FLAG(
+ bool,
+ FLAGS_quic_reloadable_flag_quic_handle_write_results_for_connectivity_probe,
+ true)
+
+// If true, a separate QuicAlarm in QuicConnection is used to trigger
+// OnPathDegrading() instead of using retransmission_alarm_.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_path_degrading_alarm, true)
+
+// Remove special logic for headers stream from QuicWriteBlockedList and
+// replace it with a static streams map.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_register_static_streams, false)
+
+// Base the QUIC crypto retransmission timer on the last sent crypto packet.
+QUIC_FLAG(bool,
+ FLAGS_quic_reloadable_flag_quic_better_crypto_retransmission,
+ false)
+
+// If true, enable server proxy support in QUIC.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_server_proxy, false)
+
+// If true, compare offset with last byte acked to determine whether it is
+// disjoint before calling IntervalSet::IsDisjoint.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fast_is_disjoint, false)
+
+// If true, enable fast path in QuicStreamSequencerBuffer::OnStreamData.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fast_path_on_stream_data, false)
+
+// When true, set the initial congestion control window from connection options
+// in QuicSentPacketManager rather than TcpCubicSenderBytes.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_unified_iw_options, false)
+
+// If true, check again that the writer isn\'t blocked before calling
+// QuicConnection::OnCanWrite from WriteAndBundleAcksIfNotBlocked
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_is_write_blocked, true)
diff --git a/chromium/net/quic/core/quic_flow_controller.cc b/chromium/net/quic/core/quic_flow_controller.cc
index 91f0c9f2889..a5e18a6faea 100644
--- a/chromium/net/quic/core/quic_flow_controller.cc
+++ b/chromium/net/quic/core/quic_flow_controller.cc
@@ -231,11 +231,7 @@ void QuicFlowController::MaybeSendBlocked() {
<< ", send limit: " << send_window_offset_;
// The entire send_window has been consumed, we are now flow control
// blocked.
- if (session_->use_control_frame_manager()) {
- session_->SendBlocked(id_);
- } else {
- connection_->SendBlocked(id_);
- }
+ session_->SendBlocked(id_);
// Keep track of when we last sent a BLOCKED frame so that we only send one
// at a given send offset.
@@ -298,11 +294,7 @@ void QuicFlowController::UpdateReceiveWindowSize(QuicStreamOffset size) {
}
void QuicFlowController::SendWindowUpdate() {
- if (session_->use_control_frame_manager()) {
- session_->SendWindowUpdate(id_, receive_window_offset_);
- return;
- }
- connection_->SendWindowUpdate(id_, receive_window_offset_);
+ session_->SendWindowUpdate(id_, receive_window_offset_);
}
} // namespace net
diff --git a/chromium/net/quic/core/quic_flow_controller_test.cc b/chromium/net/quic/core/quic_flow_controller_test.cc
index e50281707d4..aedc076f016 100644
--- a/chromium/net/quic/core/quic_flow_controller_test.cc
+++ b/chromium/net/quic/core/quic_flow_controller_test.cc
@@ -81,11 +81,7 @@ TEST_F(QuicFlowControllerTest, SendingBytes) {
EXPECT_EQ(0u, flow_controller_->SendWindowSize());
// BLOCKED frame should get sent.
- if (session_->use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
- } else {
- EXPECT_CALL(*connection_, SendBlocked(stream_id_)).Times(1);
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
flow_controller_->MaybeSendBlocked();
// Update the send window, and verify this has unblocked.
@@ -124,12 +120,7 @@ TEST_F(QuicFlowControllerTest, ReceivingBytes) {
QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
// Consume enough bytes to send a WINDOW_UPDATE frame.
- if (session_->use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
- } else {
- EXPECT_CALL(*connection_, SendWindowUpdate(stream_id_, ::testing::_))
- .Times(1);
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
flow_controller_->AddBytesConsumed(1 + receive_window_ / 2);
@@ -154,14 +145,9 @@ TEST_F(QuicFlowControllerTest, OnlySendBlockedFrameOncePerOffset) {
EXPECT_EQ(0u, flow_controller_->SendWindowSize());
// Expect that 2 BLOCKED frames should get sent in total.
- if (session_->use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(2)
- .WillRepeatedly(
- Invoke(this, &QuicFlowControllerTest::ClearControlFrame));
- } else {
- EXPECT_CALL(*connection_, SendBlocked(stream_id_)).Times(2);
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(2)
+ .WillRepeatedly(Invoke(this, &QuicFlowControllerTest::ClearControlFrame));
// BLOCKED frame should get sent.
flow_controller_->MaybeSendBlocked();
@@ -189,12 +175,7 @@ TEST_F(QuicFlowControllerTest, ReceivingBytesFastIncreasesFlowWindow) {
should_auto_tune_receive_window_ = true;
Initialize();
// This test will generate two WINDOW_UPDATE frames.
- if (session_->use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
- } else {
- EXPECT_CALL(*connection_, SendWindowUpdate(stream_id_, ::testing::_))
- .Times(1);
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
EXPECT_TRUE(flow_controller_->auto_tune_receive_window());
// Make sure clock is inititialized.
@@ -246,15 +227,9 @@ TEST_F(QuicFlowControllerTest, ReceivingBytesFastIncreasesFlowWindow) {
TEST_F(QuicFlowControllerTest, ReceivingBytesFastNoAutoTune) {
Initialize();
// This test will generate two WINDOW_UPDATE frames.
- if (session_->use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(2)
- .WillRepeatedly(
- Invoke(this, &QuicFlowControllerTest::ClearControlFrame));
- } else {
- EXPECT_CALL(*connection_, SendWindowUpdate(stream_id_, ::testing::_))
- .Times(2);
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(2)
+ .WillRepeatedly(Invoke(this, &QuicFlowControllerTest::ClearControlFrame));
EXPECT_FALSE(flow_controller_->auto_tune_receive_window());
// Make sure clock is inititialized.
@@ -307,12 +282,7 @@ TEST_F(QuicFlowControllerTest, ReceivingBytesNormalStableFlowWindow) {
should_auto_tune_receive_window_ = true;
Initialize();
// This test will generate two WINDOW_UPDATE frames.
- if (session_->use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
- } else {
- EXPECT_CALL(*connection_, SendWindowUpdate(stream_id_, ::testing::_))
- .Times(1);
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
EXPECT_TRUE(flow_controller_->auto_tune_receive_window());
// Make sure clock is inititialized.
@@ -367,15 +337,9 @@ TEST_F(QuicFlowControllerTest, ReceivingBytesNormalStableFlowWindow) {
TEST_F(QuicFlowControllerTest, ReceivingBytesNormalNoAutoTune) {
Initialize();
// This test will generate two WINDOW_UPDATE frames.
- if (connection_->use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(2)
- .WillRepeatedly(
- Invoke(this, &QuicFlowControllerTest::ClearControlFrame));
- } else {
- EXPECT_CALL(*connection_, SendWindowUpdate(stream_id_, ::testing::_))
- .Times(2);
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(2)
+ .WillRepeatedly(Invoke(this, &QuicFlowControllerTest::ClearControlFrame));
EXPECT_FALSE(flow_controller_->auto_tune_receive_window());
// Make sure clock is inititialized.
diff --git a/chromium/net/quic/core/quic_framer.cc b/chromium/net/quic/core/quic_framer.cc
index 45e6035beb8..7c0a19a3ff1 100644
--- a/chromium/net/quic/core/quic_framer.cc
+++ b/chromium/net/quic/core/quic_framer.cc
@@ -32,6 +32,7 @@
#include "net/quic/platform/api/quic_string.h"
#include "net/quic/platform/api/quic_text_utils.h"
+using std::string;
namespace net {
@@ -172,6 +173,7 @@ QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions,
largest_packet_number_(0),
last_serialized_connection_id_(0),
last_version_label_(0),
+ last_packet_is_ietf_quic_(false),
version_(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
supported_versions_(supported_versions),
decrypter_level_(ENCRYPTION_NONE),
@@ -183,9 +185,9 @@ QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions,
last_timestamp_(QuicTime::Delta::Zero()),
data_producer_(nullptr),
use_incremental_ack_processing_(
- GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
+ GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
if (use_incremental_ack_processing_) {
- QUIC_FLAG_COUNT(quic_reloadable_flag_quic_use_incremental_ack_processing);
+ QUIC_FLAG_COUNT(quic_reloadable_flag_quic_use_incremental_ack_processing3);
}
DCHECK(!supported_versions.empty());
version_ = supported_versions_[0];
@@ -557,6 +559,7 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildPublicResetPacket(
// static
std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildVersionNegotiationPacket(
QuicConnectionId connection_id,
+ bool ietf_quic,
const ParsedQuicVersionVector& versions) {
DCHECK(!versions.empty());
size_t len = GetVersionNegotiationPacketSize(versions.size());
@@ -592,6 +595,7 @@ std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildVersionNegotiationPacket(
bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) {
QuicDataReader reader(packet.data(), packet.length(), endianness());
+ last_packet_is_ietf_quic_ = false;
visitor_->OnPacket();
QuicPacketHeader header;
@@ -1091,7 +1095,7 @@ bool QuicFramer::ProcessFrameData(QuicDataReader* reader,
((frame_type & kQuicFrameTypeSpecialMask) ==
kQuicFrameTypeAckMask))) {
// TODO(fayang): Remove frame when deprecating
- // quic_reloadable_flag_quic_use_incremental_ack_processing.
+ // quic_reloadable_flag_quic_use_incremental_ack_processing3.
QuicAckFrame frame;
if (!ProcessAckFrame(reader, frame_type, &frame)) {
return RaiseError(QUIC_INVALID_ACK_DATA);
@@ -1341,25 +1345,17 @@ bool QuicFramer::ProcessIetfStreamFrame(QuicDataReader* reader,
uint8_t frame_type,
QuicStreamFrame* frame) {
// Read stream id from the frame. It's always present.
- QuicIetfStreamId streamid;
- if (!reader->ReadVarInt62(&streamid)) {
+ if (!reader->ReadVarIntStreamId(&frame->stream_id)) {
set_detailed_error("Unable to read stream_id.");
return false;
}
- if (streamid > 0xffffffff) {
- set_detailed_error("stream_id is too large.");
- return false;
- }
- frame->stream_id = static_cast<QuicStreamId>(streamid);
// If we have a data offset, read it. If not, set to 0.
if (frame_type & IETF_STREAM_FRAME_OFF_BIT) {
- QuicStreamOffset offset;
- if (!reader->ReadVarInt62(&offset)) {
+ if (!reader->ReadVarInt62(&frame->offset)) {
set_detailed_error("Unable to read stream data offset.");
return false;
}
- frame->offset = offset;
} else {
// no offset in the frame, ensure it's 0 in the Frame.
frame->offset = 0;
@@ -1373,7 +1369,7 @@ bool QuicFramer::ProcessIetfStreamFrame(QuicDataReader* reader,
return false;
}
if (length > 0xffff) {
- set_detailed_error("stream data offset is too large.");
+ set_detailed_error("Stream data length is too large.");
return false;
}
frame->data_length = length;
@@ -1593,8 +1589,8 @@ bool QuicFramer::ProcessTimestampsInAckFrame(uint8_t num_received_packets,
last_timestamp_ = CalculateTimestampFromWire(time_delta_us);
ack_frame->received_packet_times.reserve(num_received_packets);
- ack_frame->received_packet_times.push_back(
- std::make_pair(seq_num, creation_time_ + last_timestamp_));
+ ack_frame->received_packet_times.emplace_back(
+ seq_num, creation_time_ + last_timestamp_);
for (uint8_t i = 1; i < num_received_packets; ++i) {
if (!reader->ReadUInt8(&delta_from_largest_observed)) {
@@ -1614,8 +1610,8 @@ bool QuicFramer::ProcessTimestampsInAckFrame(uint8_t num_received_packets,
last_timestamp_ = last_timestamp_ + QuicTime::Delta::FromMicroseconds(
incremental_time_delta_us);
- ack_frame->received_packet_times.push_back(
- std::make_pair(seq_num, creation_time_ + last_timestamp_));
+ ack_frame->received_packet_times.emplace_back(
+ seq_num, creation_time_ + last_timestamp_);
}
}
return true;
@@ -1771,7 +1767,7 @@ bool QuicFramer::ProcessConnectionCloseFrame(QuicDataReader* reader,
set_detailed_error("Unable to read connection close error details.");
return false;
}
- frame->error_details = error_details.as_string();
+ frame->error_details = string(error_details);
return true;
}
@@ -1802,7 +1798,7 @@ bool QuicFramer::ProcessGoAwayFrame(QuicDataReader* reader,
set_detailed_error("Unable to read goaway reason.");
return false;
}
- frame->reason_phrase = reason_phrase.as_string();
+ frame->reason_phrase = string(reason_phrase);
return true;
}
@@ -1865,17 +1861,19 @@ QuicStringPiece QuicFramer::GetAssociatedDataFromEncryptedPacket(
packet_number_length));
}
-void QuicFramer::SetDecrypter(EncryptionLevel level, QuicDecrypter* decrypter) {
+void QuicFramer::SetDecrypter(EncryptionLevel level,
+ std::unique_ptr<QuicDecrypter> decrypter) {
DCHECK(alternative_decrypter_ == nullptr);
DCHECK_GE(level, decrypter_level_);
- decrypter_.reset(decrypter);
+ decrypter_ = std::move(decrypter);
decrypter_level_ = level;
}
-void QuicFramer::SetAlternativeDecrypter(EncryptionLevel level,
- QuicDecrypter* decrypter,
- bool latch_once_used) {
- alternative_decrypter_.reset(decrypter);
+void QuicFramer::SetAlternativeDecrypter(
+ EncryptionLevel level,
+ std::unique_ptr<QuicDecrypter> decrypter,
+ bool latch_once_used) {
+ alternative_decrypter_ = std::move(decrypter);
alternative_decrypter_level_ = level;
alternative_decrypter_latch_ = latch_once_used;
}
@@ -1888,10 +1886,11 @@ const QuicDecrypter* QuicFramer::alternative_decrypter() const {
return alternative_decrypter_.get();
}
-void QuicFramer::SetEncrypter(EncryptionLevel level, QuicEncrypter* encrypter) {
+void QuicFramer::SetEncrypter(EncryptionLevel level,
+ std::unique_ptr<QuicEncrypter> encrypter) {
DCHECK_GE(level, 0);
DCHECK_LT(level, NUM_ENCRYPTION_LEVELS);
- encrypter_[level].reset(encrypter);
+ encrypter_[level] = std::move(encrypter);
}
size_t QuicFramer::EncryptInPlace(EncryptionLevel level,
@@ -2304,20 +2303,20 @@ bool QuicFramer::AppendIetfStreamFrame(const QuicStreamFrame& frame,
}
// Put the type-byte in the header.
- if (writer->WriteUInt8(frame_type) == false) {
+ if (!writer->WriteUInt8(frame_type)) {
set_detailed_error("Unable to write frame-type.");
return false;
}
// Stream ID always goes in the header...
- if (writer->WriteVarInt62(static_cast<uint64_t>(frame.stream_id)) == false) {
+ if (!writer->WriteVarInt62(static_cast<uint64_t>(frame.stream_id))) {
set_detailed_error("Writing stream id failed.");
return false;
}
// Offset may go in the header...
if (frame_type & IETF_STREAM_FRAME_OFF_BIT) {
- if (writer->WriteVarInt62(static_cast<uint64_t>(frame.offset)) == false) {
+ if (!writer->WriteVarInt62(static_cast<uint64_t>(frame.offset))) {
set_detailed_error("Writing data offset failed.");
return false;
}
@@ -2325,7 +2324,7 @@ bool QuicFramer::AppendIetfStreamFrame(const QuicStreamFrame& frame,
// Frame data length...
if (frame_type & IETF_STREAM_FRAME_LEN_BIT) {
- if (writer->WriteVarInt62(frame.data_length) == false) {
+ if (!writer->WriteVarInt62(frame.data_length)) {
set_detailed_error("Writing data length failed.");
return false;
}
@@ -2621,6 +2620,7 @@ bool QuicFramer::AppendStopWaitingFrame(const QuicPacketHeader& header,
return true;
}
+
// Append IETF Format Ack Frame. The IETF Ack Frame format is, basically,
// Largest Ack'ed
// ACK Delay
@@ -2633,8 +2633,8 @@ bool QuicFramer::AppendStopWaitingFrame(const QuicPacketHeader& header,
// 1-packet-acked, 1-packet-gap, 1-packet-acked & the first
// packet has seq# LargestAcked, the last one has seq# LargestAcked-4.
-bool QuicFramer::AppendIetfAckFrameAndTypeByte(const QuicAckFrame& frame,
- QuicDataWriter* writer) {
+bool QuicFramer::AppendIetfAckFrame(const QuicAckFrame& frame,
+ QuicDataWriter* writer) {
if (!writer->WriteUInt8(IETF_ACK)) {
set_detailed_error("No room for frame-type");
return false;
@@ -2654,40 +2654,33 @@ bool QuicFramer::AppendIetfAckFrameAndTypeByte(const QuicAckFrame& frame,
DCHECK_LE(0u, frame.ack_delay_time.ToMicroseconds());
ack_delay_time_us = frame.ack_delay_time.ToMicroseconds();
- // TODO(fkastenholz) when we get real IETF QUIC, need to get
- // the currect shift from the transport parameters.
+ // TODO(fkastenholz): Use the shift from TLS transport parameters.
ack_delay_time_us = ack_delay_time_us >> kIetfAckTimestampShift;
if (!writer->WriteVarInt62(ack_delay_time_us)) {
set_detailed_error("No room for ack-delay in ack frame");
return false;
}
- // Do the block-count
uint64_t ack_block_count = frame.packets.NumIntervals();
if (ack_block_count == 0) {
QUIC_BUG << "Trying to build an ack frame with no ack blocks";
return false;
}
- // Calculate the block count we will put into the frame.
- // ID says the value is "The number of Additional ACK Block (and
- // Gap) fields after the First ACK Block." We interpret this as
- // - n(==0) means just the First ACK Block
- // - n(>0) means a First Ack block followed by N pairs
- // of Gap/Ack. So if N is 1, there is a First,
- // a Gap, and a final Ack.
+ // Subtract 1 from the block count when writing because the specification
+ // does not allow for 0 blocks.
if (!writer->WriteVarInt62(ack_block_count - 1)) {
set_detailed_error("No room for ack block count in ack frame");
return false;
}
- auto itr = frame.packets.rbegin(); // first range
- // Do the first block.
+ auto itr = frame.packets.rbegin();
+ // Write the first block.
// The ranges in frame.packets are [low...high), so
- // a) we should never see 0 and
- // b) we need to subtract 1 when writing the value out.
+ // a) 0 is invalid
+ // b) Subtract 1 when writing the value out.
uint64_t block_length = itr->max() - itr->min();
if (block_length == 0) {
- QUIC_BUG << "Have a 0-length range in QuicAckFrame::packets";
+ QUIC_BUG << "0-length range in QuicAckFrame::packets";
return false;
}
@@ -2698,31 +2691,18 @@ bool QuicFramer::AppendIetfAckFrameAndTypeByte(const QuicAckFrame& frame,
size_t previous_ack_end = itr->min();
ack_block_count--;
- // TODO(fkastenholz) this loop adds all blocks to the frame,
- // failing if the frame buffer is not large enough. In the future,
- // we should put in as many as we can, adjusting the count to
- // indicate just what we put in. Or at least have an option to do this.
+ // TODO(fkastenholz): Allow this code to write fewer ack blocks when it runs
+ // out of space in the packet.
while (ack_block_count) {
- // Do the gap separating the two ack-blocks
- // Math note: value of the gap is nr of packets separating the two
- // acks. If we have two sets of ack'd packets, 1,2,3 and 7,8,...x
- // A) The gap size is 3 (the gap is packets 4,5,6), which is
- // encoded in the frame as 2.
- // B) The two frame.packets ranges are [1,4) and [7,x) so the
- // gap calculation is (7-4)-1 ==> (3)-1 ==> 2.
-
- // next range
+ // Determine the number of packets between ack-blocks.
itr++;
-
- // Mind the gap
size_t gap = previous_ack_end - itr->max() - 1;
-
if (!writer->WriteVarInt62(gap)) {
set_detailed_error("No room for gap block in ack frame");
return false;
}
- // Add the ack-block (itr already points to it)
+ // Add the ack-block.
block_length = itr->max() - itr->min();
if (block_length == 0) {
QUIC_BUG << "Have a 0-length range in QuicAckFrame::packets";
@@ -2880,14 +2860,6 @@ bool QuicFramer::AppendIetfConnectionCloseFrame(
frame.error_details, writer);
}
-bool QuicFramer::AppendIetfConnectionCloseFrame(
- const QuicIetfTransportErrorCodes code,
- const QuicString& phrase,
- QuicDataWriter* writer) {
- return AppendIetfCloseFrame(
- IETF_CONNECTION_CLOSE, static_cast<const uint16_t>(code), phrase, writer);
-}
-
bool QuicFramer::AppendIetfApplicationCloseFrame(
const QuicConnectionCloseFrame& frame,
QuicDataWriter* writer) {
@@ -2895,11 +2867,7 @@ bool QuicFramer::AppendIetfApplicationCloseFrame(
static_cast<const uint16_t>(frame.error_code),
frame.error_details, writer);
}
-bool QuicFramer::AppendIetfApplicationCloseFrame(const uint16_t code,
- const QuicString& phrase,
- QuicDataWriter* writer) {
- return AppendIetfCloseFrame(IETF_APPLICATION_CLOSE, code, phrase, writer);
-}
+
// Generate either an IETF-Connection- or IETF-Application-close frame.
// General format is
// type-byte
@@ -2945,18 +2913,20 @@ bool QuicFramer::ProcessIetfConnectionCloseFrame(
QuicConnectionCloseFrame* frame) {
return ProcessIetfCloseFrame(reader, frame_type, frame);
}
+
bool QuicFramer::ProcessIetfApplicationCloseFrame(
QuicDataReader* reader,
const uint8_t frame_type,
QuicConnectionCloseFrame* frame) {
return ProcessIetfCloseFrame(reader, frame_type, frame);
}
+
bool QuicFramer::ProcessIetfCloseFrame(QuicDataReader* reader,
const uint8_t frame_type,
QuicConnectionCloseFrame* frame) {
uint16_t code;
if (!reader->ReadUInt16(&code)) {
- set_detailed_error("Unable to read clode frame code.");
+ set_detailed_error("Unable to read close frame code.");
return false;
}
frame->error_code = static_cast<QuicErrorCode>(code);
@@ -2971,8 +2941,324 @@ bool QuicFramer::ProcessIetfCloseFrame(QuicDataReader* reader,
set_detailed_error("Can not read extended close information phrase");
return false;
}
- frame->error_details = phrase.as_string();
+ frame->error_details = string(phrase);
+
+ return true;
+}
+
+// IETF-format Padding frames.
+// Padding is just N bytes of 0x00. There is no varint62/etc
+// encoding required.
+bool QuicFramer::AppendIetfPaddingFrame(const QuicPaddingFrame& frame,
+ QuicDataWriter* writer) {
+ DCHECK_GT(version_.transport_version, QUIC_VERSION_37);
+ // The base AppendPaddingFrame assumes that the type byte has
+ // been written. It will actually write num_padding_bytes-1
+ // bytes. This takes care of that issue.
+ if (!writer->WriteUInt8(0)) {
+ set_detailed_error("Can not write close frame type byte");
+ return false;
+ }
+ return AppendPaddingFrame(frame, writer);
+}
+
+// Read the padding. Has to do it one byte at a time, stopping
+// when we either A) reach the end of the buffer or B) reach a
+// non-0x00 byte.
+void QuicFramer::ProcessIetfPaddingFrame(QuicDataReader* reader,
+ QuicPaddingFrame* frame) {
+ DCHECK_GT(version_.transport_version, QUIC_VERSION_37);
+ ProcessPaddingFrame(reader, frame);
+}
+
+// IETF Quic Path Challenge/Response frames.
+bool QuicFramer::ProcessIetfPathChallengeFrame(QuicDataReader* reader,
+ QuicPathChallengeFrame* frame) {
+ if (!reader->ReadBytes(frame->data_buffer.data(), kQuicPathFrameBufferSize)) {
+ set_detailed_error("Can not read path Challenge data");
+ return false;
+ }
+ return true;
+}
+
+bool QuicFramer::ProcessIetfPathResponseFrame(QuicDataReader* reader,
+ QuicPathResponseFrame* frame) {
+ if (!reader->ReadBytes(frame->data_buffer.data(), kQuicPathFrameBufferSize)) {
+ set_detailed_error("Can not read path Response data");
+ return false;
+ }
+ return true;
+}
+
+bool QuicFramer::AppendIetfPathChallengeFrame(
+ const QuicPathChallengeFrame& frame,
+ QuicDataWriter* writer) {
+ if (!writer->WriteUInt8(IETF_PATH_CHALLENGE)) {
+ set_detailed_error("Can not write Path Challenge frame type byte");
+ return false;
+ }
+
+ if (!writer->WriteBytes(frame.data_buffer.data(), kQuicPathFrameBufferSize)) {
+ set_detailed_error("Writing Path Challenge data failed.");
+ return false;
+ }
+ return true;
+}
+
+bool QuicFramer::AppendIetfPathResponseFrame(const QuicPathResponseFrame& frame,
+ QuicDataWriter* writer) {
+ if (!writer->WriteUInt8(IETF_PATH_RESPONSE)) {
+ set_detailed_error("Can not write Path Response frame type byte");
+ return false;
+ }
+
+ if (!writer->WriteBytes(frame.data_buffer.data(), kQuicPathFrameBufferSize)) {
+ set_detailed_error("Writing Path Response data failed.");
+ return false;
+ }
+ return true;
+}
+
+// Add a new ietf-format stream reset frame.
+// General format is
+// stream id
+// application error code
+// final offset
+bool QuicFramer::AppendIetfResetStreamFrame(const QuicRstStreamFrame& frame,
+ QuicDataWriter* writer) {
+ // Put the type-byte in the header.
+ if (!writer->WriteUInt8(QuicIetfFrameType::IETF_RST_STREAM)) {
+ set_detailed_error("Unable to write reset-stream frame-type.");
+ return false;
+ }
+ if (!writer->WriteVarInt62(static_cast<uint64_t>(frame.stream_id))) {
+ set_detailed_error("Writing reset-stream stream id failed.");
+ return false;
+ }
+ if (!writer->WriteUInt16(static_cast<uint16_t>(frame.error_code))) {
+ set_detailed_error("Writing reset-stream error code failed.");
+ return false;
+ }
+ if (!writer->WriteVarInt62(static_cast<uint64_t>(frame.byte_offset))) {
+ set_detailed_error("Writing reset-stream final-offset failed.");
+ return false;
+ }
+ return true;
+}
+
+bool QuicFramer::ProcessIetfResetStreamFrame(QuicDataReader* reader,
+ QuicRstStreamFrame* frame) {
+ // 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)) {
+ set_detailed_error("Reading reset-stream stream id failed.");
+ return false;
+ }
+
+ uint16_t temp_uint16;
+ if (!reader->ReadUInt16(&temp_uint16)) {
+ set_detailed_error("Reading reset-stream error code failed.");
+ return false;
+ }
+ frame->error_code = static_cast<QuicRstStreamErrorCode>(temp_uint16);
+ if (!reader->ReadVarInt62(&frame->byte_offset)) {
+ set_detailed_error("Reading reset-stream final-offset failed.");
+ return false;
+ }
+ return true;
+}
+
+bool QuicFramer::ProcessIetfStopSendingFrame(
+ QuicDataReader* reader,
+ QuicStopSendingFrame* stop_sending_frame) {
+ if (!reader->ReadVarIntStreamId(&stop_sending_frame->stream_id)) {
+ set_detailed_error("Unable to read stream id");
+ return false;
+ }
+
+ if (!reader->ReadUInt16(&stop_sending_frame->application_error_code)) {
+ set_detailed_error("Unable to read application error code.");
+ return false;
+ }
+ return true;
+}
+
+bool QuicFramer::AppendIetfStopSendingFrame(
+ const QuicStopSendingFrame& stop_sending_frame,
+ QuicDataWriter* writer) {
+ if (!writer->WriteUInt8(IETF_STOP_SENDING)) {
+ set_detailed_error("Can not write stop sending frame type byte");
+ return false;
+ }
+ if (!writer->WriteVarInt62(stop_sending_frame.stream_id)) {
+ set_detailed_error("Can not write stop sending stream id");
+ return false;
+ }
+ if (!writer->WriteUInt16(stop_sending_frame.application_error_code)) {
+ set_detailed_error("Can not write application error code");
+ return false;
+ }
+ return true;
+}
+
+// Append/process IETF-Format MAX_DATA Frame
+// MAX_DATA format is a single number, the maximum number of bytes
+// that can be accepted on the connection.
+bool QuicFramer::AppendIetfMaxDataFrame(const QuicWindowUpdateFrame& frame,
+ QuicDataWriter* writer) {
+ if (!writer->WriteUInt8(IETF_MAX_DATA)) {
+ set_detailed_error("Can not write IETF_MAX_DATA frame type byte");
+ return false;
+ }
+ if (!writer->WriteVarInt62(frame.byte_offset)) {
+ set_detailed_error("Can not write IETF_MAX_DATA byte-offset");
+ return false;
+ }
+ return true;
+}
+
+bool QuicFramer::ProcessIetfMaxDataFrame(QuicDataReader* reader,
+ QuicWindowUpdateFrame* frame) {
+ frame->stream_id = 0;
+ if (!reader->ReadVarInt62(&frame->byte_offset)) {
+ set_detailed_error("Can not read IETF_MAX_DATA byte-offset");
+ return false;
+ }
+ return true;
+}
+
+// Append/process IETF-Format MAX_STREAM_DATA Frame
+// MAX_STREAM_DATA is two numbers, stream ID and then max number of bytes.
+bool QuicFramer::AppendIetfMaxStreamDataFrame(
+ const QuicWindowUpdateFrame& frame,
+ QuicDataWriter* writer) {
+ if (!writer->WriteUInt8(IETF_MAX_STREAM_DATA)) {
+ set_detailed_error("Can not write IETF_MAX_STREAM_DATA frame type byte");
+ return false;
+ }
+ if (!writer->WriteVarInt62(frame.stream_id)) {
+ set_detailed_error("Can not write IETF_MAX_STREAM_DATA stream id");
+ return false;
+ }
+ if (!writer->WriteVarInt62(frame.byte_offset)) {
+ set_detailed_error("Can not write IETF_MAX_STREAM_DATA byte-offset");
+ return false;
+ }
+ return true;
+}
+
+bool QuicFramer::ProcessIetfMaxStreamDataFrame(QuicDataReader* reader,
+ QuicWindowUpdateFrame* frame) {
+ if (!reader->ReadVarIntStreamId(&frame->stream_id)) {
+ set_detailed_error("Can not read IETF_MAX_STREAM_DATA stream id");
+ return false;
+ }
+ if (!reader->ReadVarInt62(&frame->byte_offset)) {
+ set_detailed_error("Can not read IETF_MAX_STREAM_DATA byte-count");
+ return false;
+ }
+ return true;
+}
+
+bool QuicFramer::AppendIetfMaxStreamIdFrame(
+ const QuicIetfMaxStreamIdFrame& frame,
+ QuicDataWriter* writer) {
+ if (!writer->WriteUInt8(IETF_MAX_STREAM_ID)) {
+ set_detailed_error("Can not write IETF_MAX_STREAM_ID frame type byte");
+ return false;
+ }
+ if (!writer->WriteVarInt62(frame.max_stream_id)) {
+ set_detailed_error("Can not write IETF_MAX_STREAM_ID stream id");
+ return false;
+ }
+ return true;
+}
+
+bool QuicFramer::ProcessIetfMaxStreamIdFrame(QuicDataReader* reader,
+ QuicIetfMaxStreamIdFrame* frame) {
+ if (!reader->ReadVarIntStreamId(&frame->max_stream_id)) {
+ set_detailed_error("Can not read IETF_MAX_STREAM_ID stream id");
+ return false;
+ }
+ return true;
+}
+
+bool QuicFramer::AppendIetfBlockedFrame(const QuicIetfBlockedFrame& frame,
+ QuicDataWriter* writer) {
+ if (!writer->WriteUInt8(IETF_BLOCKED)) {
+ set_detailed_error("Can not write IETF_BLOCKED frame type byte");
+ return false;
+ }
+ if (!writer->WriteVarInt62(frame.offset)) {
+ set_detailed_error("Can not write IETF_BLOCKED offset");
+ return false;
+ }
+ return true;
+}
+
+bool QuicFramer::ProcessIetfBlockedFrame(QuicDataReader* reader,
+ QuicIetfBlockedFrame* frame) {
+ if (!reader->ReadVarInt62(&frame->offset)) {
+ set_detailed_error("Can not read IETF_BLOCKED offset");
+ return false;
+ }
+ return true;
+}
+
+bool QuicFramer::AppendIetfStreamBlockedFrame(
+ const QuicWindowUpdateFrame& frame,
+ QuicDataWriter* writer) {
+ if (!writer->WriteUInt8(IETF_STREAM_BLOCKED)) {
+ set_detailed_error("Can not write IETF_STREAM_BLOCKED frame type byte");
+ return false;
+ }
+ if (!writer->WriteVarInt62(frame.stream_id)) {
+ set_detailed_error("Can not write IETF_STREAM_BLOCKED stream id");
+ return false;
+ }
+ if (!writer->WriteVarInt62(frame.byte_offset)) {
+ set_detailed_error("Can not write IETF_STREAM_BLOCKED offset");
+ return false;
+ }
+ return true;
+}
+
+bool QuicFramer::ProcessIetfStreamBlockedFrame(QuicDataReader* reader,
+ QuicWindowUpdateFrame* frame) {
+ if (!reader->ReadVarIntStreamId(&frame->stream_id)) {
+ set_detailed_error("Can not read IETF_STREAM_BLOCKED stream id");
+ return false;
+ }
+ if (!reader->ReadVarInt62(&frame->byte_offset)) {
+ set_detailed_error("Can not read IETF_STREAM_BLOCKED offset");
+ return false;
+ }
+ return true;
+}
+
+bool QuicFramer::AppendIetfStreamIdBlockedFrame(
+ const QuicIetfStreamIdBlockedFrame& frame,
+ QuicDataWriter* writer) {
+ if (!writer->WriteUInt8(IETF_STREAM_ID_BLOCKED)) {
+ set_detailed_error("Can not write IETF_STREAM_ID_BLOCKED frame type byte");
+ return false;
+ }
+ if (!writer->WriteVarInt62(frame.stream_id)) {
+ set_detailed_error("Can not write IETF_STREAM_ID_BLOCKED stream id");
+ return false;
+ }
+ return true;
+}
+
+bool QuicFramer::ProcessIetfStreamIdBlockedFrame(
+ QuicDataReader* reader,
+ QuicIetfStreamIdBlockedFrame* frame) {
+ if (!reader->ReadVarIntStreamId(&frame->stream_id)) {
+ set_detailed_error("Can not read IETF_STREAM_ID_BLOCKED stream id");
+ return false;
+ }
return true;
}
diff --git a/chromium/net/quic/core/quic_framer.h b/chromium/net/quic/core/quic_framer.h
index c08750b2e63..589d77575fd 100644
--- a/chromium/net/quic/core/quic_framer.h
+++ b/chromium/net/quic/core/quic_framer.h
@@ -10,6 +10,8 @@
#include <memory>
#include "base/macros.h"
+#include "net/quic/core/crypto/quic_decrypter.h"
+#include "net/quic/core/crypto/quic_encrypter.h"
#include "net/quic/core/quic_packets.h"
#include "net/quic/platform/api/quic_endian.h"
#include "net/quic/platform/api/quic_export.h"
@@ -24,8 +26,6 @@ class QuicFramerPeer;
class QuicDataReader;
class QuicDataWriter;
-class QuicDecrypter;
-class QuicEncrypter;
class QuicFramer;
class QuicStreamFrameDataProducer;
@@ -149,6 +149,14 @@ class QUIC_EXPORT_PRIVATE QuicFramerVisitorInterface {
// Called when a packet has been completely processed.
virtual void OnPacketComplete() = 0;
+
+ // Called to check whether |token| is a valid stateless reset token.
+ virtual bool IsValidStatelessResetToken(uint128 token) const = 0;
+
+ // Called when an IETF stateless reset packet has been parsed and validated
+ // with the stateless reset token.
+ virtual void OnAuthenticatedIetfStatelessResetPacket(
+ const QuicIetfStatelessResetPacket& packet) = 0;
};
// Class for parsing and constructing QUIC packets. It has a
@@ -281,6 +289,7 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
// Returns a new version negotiation packet.
static std::unique_ptr<QuicEncryptedPacket> BuildVersionNegotiationPacket(
QuicConnectionId connection_id,
+ bool ietf_quic,
const ParsedQuicVersionVector& versions);
// If header.version_flag is set, the version in the
@@ -295,29 +304,30 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
bool last_frame_in_packet,
QuicDataWriter* writer);
- // SetDecrypter sets the primary decrypter, replacing any that already exists,
- // and takes ownership. If an alternative decrypter is in place then the
- // function DCHECKs. This is intended for cases where one knows that future
- // packets will be using the new decrypter and the previous decrypter is now
- // obsolete. |level| indicates the encryption level of the new decrypter.
- void SetDecrypter(EncryptionLevel level, QuicDecrypter* decrypter);
+ // SetDecrypter sets the primary decrypter, replacing any that already exists.
+ // If an alternative decrypter is in place then the function DCHECKs. This is
+ // intended for cases where one knows that future packets will be using the
+ // new decrypter and the previous decrypter is now obsolete. |level| indicates
+ // the encryption level of the new decrypter.
+ void SetDecrypter(EncryptionLevel level,
+ std::unique_ptr<QuicDecrypter> decrypter);
// SetAlternativeDecrypter sets a decrypter that may be used to decrypt
- // future packets and takes ownership of it. |level| indicates the encryption
- // level of the decrypter. If |latch_once_used| is true, then the first time
- // that the decrypter is successful it will replace the primary decrypter.
- // Otherwise both decrypters will remain active and the primary decrypter
- // will be the one last used.
+ // future packets. |level| indicates the encryption level of the decrypter. If
+ // |latch_once_used| is true, then the first time that the decrypter is
+ // successful it will replace the primary decrypter. Otherwise both
+ // decrypters will remain active and the primary decrypter will be the one
+ // last used.
void SetAlternativeDecrypter(EncryptionLevel level,
- QuicDecrypter* decrypter,
+ std::unique_ptr<QuicDecrypter> decrypter,
bool latch_once_used);
const QuicDecrypter* decrypter() const;
const QuicDecrypter* alternative_decrypter() const;
- // Changes the encrypter used for level |level| to |encrypter|. The function
- // takes ownership of |encrypter|.
- void SetEncrypter(EncryptionLevel level, QuicEncrypter* encrypter);
+ // Changes the encrypter used for level |level| to |encrypter|.
+ void SetEncrypter(EncryptionLevel level,
+ std::unique_ptr<QuicEncrypter> encrypter);
// Encrypts a payload in |buffer|. |ad_len| is the length of the associated
// data. |total_len| is the length of the associated data plus plaintext.
@@ -365,6 +375,8 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
QuicVersionLabel last_version_label() const { return last_version_label_; }
+ bool last_packet_is_ietf_quic() const { return last_packet_is_ietf_quic_; }
+
void set_data_producer(QuicStreamFrameDataProducer* data_producer) {
data_producer_ = data_producer;
}
@@ -514,30 +526,10 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
bool AppendPaddingFrame(const QuicPaddingFrame& frame,
QuicDataWriter* writer);
- // IETF defined frame append/process methods.
+ // IETF frame processing methods.
bool ProcessIetfStreamFrame(QuicDataReader* reader,
uint8_t frame_type,
QuicStreamFrame* frame);
- // Append a stream frame and data to the packet.
- bool AppendIetfStreamFrame(const QuicStreamFrame& frame,
- bool last_frame_in_packet,
- QuicDataWriter* writer);
-
- // Add/process an IETF-Formatted Connection and Application close frames.
- bool AppendIetfConnectionCloseFrame(const QuicConnectionCloseFrame& frame,
- QuicDataWriter* writer);
- bool AppendIetfConnectionCloseFrame(const QuicIetfTransportErrorCodes code,
- const QuicString& phrase,
- QuicDataWriter* writer);
- bool AppendIetfApplicationCloseFrame(const QuicConnectionCloseFrame& frame,
- QuicDataWriter* writer);
- bool AppendIetfApplicationCloseFrame(const uint16_t code,
- const QuicString& phrase,
- QuicDataWriter* writer);
- bool AppendIetfCloseFrame(const QuicIetfFrameType type,
- const uint16_t code,
- const QuicString& phrase,
- QuicDataWriter* writer);
bool ProcessIetfConnectionCloseFrame(QuicDataReader* reader,
const uint8_t frame_type,
QuicConnectionCloseFrame* frame);
@@ -547,14 +539,73 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
bool ProcessIetfCloseFrame(QuicDataReader* reader,
const uint8_t frame_type,
QuicConnectionCloseFrame* frame);
-
- // Parse an IETF-format Ack frame from the packet
bool ProcessIetfAckFrame(QuicDataReader* reader,
uint8_t frame_type,
QuicAckFrame* ack_frame);
- // Append an IETf-format Ack frame to the packet
- bool AppendIetfAckFrameAndTypeByte(const QuicAckFrame& frame,
- QuicDataWriter* writer);
+ void ProcessIetfPaddingFrame(QuicDataReader* reader, QuicPaddingFrame* frame);
+ bool ProcessIetfPathChallengeFrame(QuicDataReader* reader,
+ QuicPathChallengeFrame* frame);
+ bool ProcessIetfPathResponseFrame(QuicDataReader* reader,
+ QuicPathResponseFrame* frame);
+ bool ProcessIetfResetStreamFrame(QuicDataReader* reader,
+ QuicRstStreamFrame* frame);
+ bool ProcessIetfStopSendingFrame(QuicDataReader* reader,
+ QuicStopSendingFrame* stop_sending_frame);
+
+ // IETF frame appending methods. All methods append the type byte as well.
+ bool AppendIetfStreamFrame(const QuicStreamFrame& frame,
+ bool last_frame_in_packet,
+ QuicDataWriter* writer);
+ bool AppendIetfConnectionCloseFrame(const QuicConnectionCloseFrame& frame,
+ QuicDataWriter* writer);
+ bool AppendIetfApplicationCloseFrame(const QuicConnectionCloseFrame& frame,
+ QuicDataWriter* writer);
+ bool AppendIetfCloseFrame(const QuicIetfFrameType type,
+ const uint16_t code,
+ const QuicString& phrase,
+ QuicDataWriter* writer);
+ bool AppendIetfAckFrame(const QuicAckFrame& frame, QuicDataWriter* writer);
+ bool AppendIetfPaddingFrame(const QuicPaddingFrame& frame,
+ QuicDataWriter* writer);
+ bool AppendIetfPathChallengeFrame(const QuicPathChallengeFrame& frame,
+ QuicDataWriter* writer);
+ bool AppendIetfPathResponseFrame(const QuicPathResponseFrame& frame,
+ QuicDataWriter* writer);
+ bool AppendIetfResetStreamFrame(const QuicRstStreamFrame& frame,
+ QuicDataWriter* writer);
+ bool AppendIetfStopSendingFrame(
+ const QuicStopSendingFrame& stop_sending_frame,
+ QuicDataWriter* writer);
+
+ // Append/consume IETF-Format MAX_DATA and MAX_STREAM_DATA frames
+ bool AppendIetfMaxDataFrame(const QuicWindowUpdateFrame& frame,
+ QuicDataWriter* writer);
+ bool AppendIetfMaxStreamDataFrame(const QuicWindowUpdateFrame& frame,
+ QuicDataWriter* writer);
+ bool ProcessIetfMaxDataFrame(QuicDataReader* reader,
+ QuicWindowUpdateFrame* frame);
+ bool ProcessIetfMaxStreamDataFrame(QuicDataReader* reader,
+ QuicWindowUpdateFrame* frame);
+
+ bool AppendIetfMaxStreamIdFrame(const QuicIetfMaxStreamIdFrame& frame,
+ QuicDataWriter* writer);
+ bool ProcessIetfMaxStreamIdFrame(QuicDataReader* reader,
+ QuicIetfMaxStreamIdFrame* frame);
+
+ bool AppendIetfBlockedFrame(const QuicIetfBlockedFrame& frame,
+ QuicDataWriter* writer);
+ bool ProcessIetfBlockedFrame(QuicDataReader* reader,
+ QuicIetfBlockedFrame* frame);
+
+ bool AppendIetfStreamBlockedFrame(const QuicWindowUpdateFrame& frame,
+ QuicDataWriter* writer);
+ bool ProcessIetfStreamBlockedFrame(QuicDataReader* reader,
+ QuicWindowUpdateFrame* frame);
+
+ bool AppendIetfStreamIdBlockedFrame(const QuicIetfStreamIdBlockedFrame& frame,
+ QuicDataWriter* writer);
+ bool ProcessIetfStreamIdBlockedFrame(QuicDataReader* reader,
+ QuicIetfStreamIdBlockedFrame* frame);
bool RaiseError(QuicErrorCode error);
@@ -573,6 +624,8 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
QuicConnectionId last_serialized_connection_id_;
// The last QUIC version label received.
QuicVersionLabel last_version_label_;
+ // Whether last received packet is IETF QUIC packet.
+ bool last_packet_is_ietf_quic_;
// Version of the protocol being used.
ParsedQuicVersion version_;
// This vector contains QUIC versions which we currently support.
@@ -612,7 +665,7 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
// owned. TODO(fayang): Consider add data producer to framer's constructor.
QuicStreamFrameDataProducer* data_producer_;
- // Latched value of quic_reloadable_flag_quic_use_incremental_ack_processing.
+ // Latched value of quic_reloadable_flag_quic_use_incremental_ack_processing3.
const bool use_incremental_ack_processing_;
DISALLOW_COPY_AND_ASSIGN(QuicFramer);
diff --git a/chromium/net/quic/core/quic_framer_test.cc b/chromium/net/quic/core/quic_framer_test.cc
index 05ff90c20fa..5bc570344de 100644
--- a/chromium/net/quic/core/quic_framer_test.cc
+++ b/chromium/net/quic/core/quic_framer_test.cc
@@ -26,6 +26,7 @@
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/quic/test_tools/simple_data_producer.h"
+using std::string;
using testing::_;
using testing::Return;
using testing::Truly;
@@ -34,16 +35,18 @@ namespace net {
namespace test {
namespace {
-const QuicPacketNumber kEpoch = UINT64_C(1) << 48;
+const QuicPacketNumber kEpoch = UINT64_C(1) << 32;
const QuicPacketNumber kMask = kEpoch - 1;
+const uint128 kTestStatelessResetToken = 1010101; // 0x0F69B5
+
// Use fields in which each byte is distinct to ensure that every byte is
// framed correctly. The values are otherwise arbitrary.
const QuicConnectionId kConnectionId = UINT64_C(0xFEDCBA9876543210);
-const QuicPacketNumber kPacketNumber = UINT64_C(0x123456789ABC);
+const QuicPacketNumber kPacketNumber = UINT64_C(0x12345678);
const QuicPacketNumber kSmallLargestObserved = UINT16_C(0x1234);
const QuicPacketNumber kSmallMissingPacket = UINT16_C(0x1233);
-const QuicPacketNumber kLeastUnacked = UINT64_C(0x0123456789AA0);
+const QuicPacketNumber kLeastUnacked = UINT64_C(0x012345670);
const QuicStreamId kStreamId = UINT64_C(0x01020304);
const QuicStreamOffset kStreamOffset = UINT64_C(0xBA98FEDC32107654);
const QuicPublicResetNonceProof kNonceProof = UINT64_C(0xABCDEF0123456789);
@@ -63,8 +66,8 @@ class TestEncrypter : public QuicEncrypter {
size_t max_output_length) override {
version_ = version;
packet_number_ = packet_number;
- associated_data_ = associated_data.as_string();
- plaintext_ = plaintext.as_string();
+ associated_data_ = string(associated_data);
+ plaintext_ = string(plaintext);
memcpy(output, plaintext.data(), plaintext.length());
*output_length = plaintext.length();
return true;
@@ -109,8 +112,8 @@ class TestDecrypter : public QuicDecrypter {
size_t max_output_length) override {
version_ = version;
packet_number_ = packet_number;
- associated_data_ = associated_data.as_string();
- ciphertext_ = ciphertext.as_string();
+ associated_data_ = string(associated_data);
+ ciphertext_ = string(ciphertext);
memcpy(output, ciphertext.data(), ciphertext.length());
*output_length = ciphertext.length();
return true;
@@ -260,6 +263,16 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
return true;
}
+ bool IsValidStatelessResetToken(uint128 token) const override {
+ return token == kTestStatelessResetToken;
+ }
+
+ void OnAuthenticatedIetfStatelessResetPacket(
+ const QuicIetfStatelessResetPacket& packet) override {
+ stateless_reset_packet_ =
+ QuicMakeUnique<QuicIetfStatelessResetPacket>(packet);
+ }
+
// Counters from the visitor_ callbacks.
int error_count_;
int version_mismatch_;
@@ -271,6 +284,7 @@ class TestQuicVisitor : public QuicFramerVisitorInterface {
std::unique_ptr<QuicPacketHeader> header_;
std::unique_ptr<QuicPublicResetPacket> public_reset_packet_;
+ std::unique_ptr<QuicIetfStatelessResetPacket> stateless_reset_packet_;
std::unique_ptr<QuicVersionNegotiationPacket> version_negotiation_packet_;
std::vector<std::unique_ptr<QuicStreamFrame>> stream_frames_;
std::vector<std::unique_ptr<QuicAckFrame>> ack_frames_;
@@ -294,6 +308,12 @@ struct PacketFragment {
using PacketFragments = std::vector<struct PacketFragment>;
+ParsedQuicVersionVector AllSupportedVersionsIncludingTls() {
+ QuicFlagSaver flags;
+ SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
+ return AllSupportedVersions();
+}
+
class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
public:
QuicFramerTest()
@@ -301,13 +321,25 @@ class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
decrypter_(new test::TestDecrypter()),
version_(GetParam()),
start_(QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(0x10)),
- framer_(AllSupportedVersions(), start_, Perspective::IS_SERVER) {
+ framer_(AllSupportedVersionsIncludingTls(),
+ start_,
+ Perspective::IS_SERVER) {
+ SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
framer_.set_version(version_);
- framer_.SetDecrypter(ENCRYPTION_NONE, decrypter_);
- framer_.SetEncrypter(ENCRYPTION_NONE, encrypter_);
+ framer_.SetDecrypter(ENCRYPTION_NONE,
+ std::unique_ptr<QuicDecrypter>(decrypter_));
+ framer_.SetEncrypter(ENCRYPTION_NONE,
+ std::unique_ptr<QuicEncrypter>(encrypter_));
+
framer_.set_visitor(&visitor_);
}
+ // Helper function to get unsigned char representation of the handshake
+ // protocol byte of the current QUIC version number.
+ unsigned char GetQuicVersionProtocolByte() {
+ return (CreateQuicVersionLabel(version_) >> 24) & 0xff;
+ }
+
// Helper function to get unsigned char representation of digit in the
// units place of the current QUIC version number.
unsigned char GetQuicVersionDigitOnes() {
@@ -358,13 +390,13 @@ class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
if (QuicFramer::GetAssociatedDataFromEncryptedPacket(
framer_.transport_version(), encrypted, PACKET_8BYTE_CONNECTION_ID,
includes_version, includes_diversification_nonce,
- PACKET_6BYTE_PACKET_NUMBER) != decrypter_->associated_data_) {
+ PACKET_4BYTE_PACKET_NUMBER) != decrypter_->associated_data_) {
QUIC_LOG(ERROR) << "Decrypted incorrect associated data. expected "
<< QuicFramer::GetAssociatedDataFromEncryptedPacket(
framer_.transport_version(), encrypted,
PACKET_8BYTE_CONNECTION_ID, includes_version,
includes_diversification_nonce,
- PACKET_6BYTE_PACKET_NUMBER)
+ PACKET_4BYTE_PACKET_NUMBER)
<< " actual: " << decrypter_->associated_data_;
return false;
}
@@ -372,7 +404,7 @@ class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
encrypted.AsStringPiece().substr(GetStartOfEncryptedData(
framer_.transport_version(), PACKET_8BYTE_CONNECTION_ID,
includes_version, includes_diversification_nonce,
- PACKET_6BYTE_PACKET_NUMBER)));
+ PACKET_4BYTE_PACKET_NUMBER)));
if (ciphertext != decrypter_->ciphertext_) {
QUIC_LOG(ERROR) << "Decrypted incorrect ciphertext data. expected "
<< ciphertext << " actual: " << decrypter_->ciphertext_;
@@ -450,7 +482,7 @@ class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
QuicPacketNumber wire_packet_number = expected_packet_number & kMask;
EXPECT_EQ(expected_packet_number,
QuicFramerPeer::CalculatePacketNumberFromWire(
- &framer_, PACKET_6BYTE_PACKET_NUMBER, last_packet_number,
+ &framer_, PACKET_4BYTE_PACKET_NUMBER, last_packet_number,
wire_packet_number))
<< "last_packet_number: " << last_packet_number
<< " wire_packet_number: " << wire_packet_number;
@@ -475,10 +507,19 @@ class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
test::TestQuicVisitor visitor_;
};
+// Multiple test cases of QuicFramerTest use byte arrays to define packets for
+// testing, and these byte arrays contain the QUIC version. This macro explodes
+// the 32-bit version into four bytes in network order. Since it uses methods of
+// QuicFramerTest, it is only valid to use this in a QuicFramerTest.
+#define QUIC_VERSION_BYTES \
+ GetQuicVersionProtocolByte(), '0', GetQuicVersionDigitTens(), \
+ GetQuicVersionDigitOnes()
+
// Run all framer tests with all supported versions of QUIC.
-INSTANTIATE_TEST_CASE_P(QuicFramerTests,
- QuicFramerTest,
- ::testing::ValuesIn(AllSupportedVersions()));
+INSTANTIATE_TEST_CASE_P(
+ QuicFramerTests,
+ QuicFramerTest,
+ ::testing::ValuesIn(AllSupportedVersionsIncludingTls()));
TEST_P(QuicFramerTest, CalculatePacketNumberFromWireNearEpochStart) {
// A few quick manual sanity checks.
@@ -592,11 +633,11 @@ TEST_P(QuicFramerTest, LargePacket) {
// clang-format off
unsigned char packet[kMaxPacketSize + 1] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// private flags
0x00,
};
@@ -604,7 +645,7 @@ TEST_P(QuicFramerTest, LargePacket) {
const size_t header_size = GetPacketHeaderSize(
framer_.transport_version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER);
+ !kIncludeDiversificationNonce, PACKET_4BYTE_PACKET_NUMBER);
memset(packet + header_size, 0, kMaxPacketSize - header_size);
@@ -623,25 +664,25 @@ TEST_P(QuicFramerTest, PacketHeader) {
PacketFragments packet38 = {
// public flags (8 byte connection_id)
{"Unable to read public flags.",
- {0x38}},
+ {0x28}},
// connection_id
{"Unable to read ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
- {0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12}},
+ {0x78, 0x56, 0x34, 0x12}},
};
PacketFragments packet39 = {
// public flags (8 byte connection_id)
{"Unable to read public flags.",
- {0x38}},
+ {0x28}},
// connection_id
{"Unable to read ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
- {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
};
// clang-format on
@@ -669,23 +710,21 @@ TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) {
PacketFragments packet = {
// public flags (0 byte connection_id)
{"Unable to read public flags.",
- {0x30}},
+ {0x20}},
// connection_id
// packet number
{"Unable to read packet number.",
- {0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12}}
+ {0x78, 0x56, 0x34, 0x12}}
};
PacketFragments packet39 = {
// public flags (0 byte connection_id)
{"Unable to read public flags.",
- {0x30}},
+ {0x20}},
// connection_id
// packet number
{"Unable to read packet number.",
- {0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
};
// clang-format on
@@ -709,31 +748,31 @@ TEST_P(QuicFramerTest, PacketHeaderWithVersionFlag) {
PacketFragments packet = {
// public flags (0 byte connection_id)
{"Unable to read public flags.",
- {0x39}},
+ {0x29}},
// connection_id
{"Unable to read ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// version tag
{"Unable to read protocol version.",
- {'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes()}},
+ {QUIC_VERSION_BYTES}},
// packet number
{"Unable to read packet number.",
- {0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12}},
+ {0x78, 0x56, 0x34, 0x12}},
};
PacketFragments packet39 = {
// public flags (0 byte connection_id)
{"Unable to read public flags.",
- {0x39}},
+ {0x29}},
// connection_id
{"Unable to read ConnectionId.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// version tag
{"Unable to read protocol version.",
- {'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes()}},
+ {QUIC_VERSION_BYTES}},
// packet number
{"Unable to read packet number.",
- {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
};
// clang-format on
@@ -766,7 +805,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith4BytePacketNumber) {
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
- {0xBC, 0x9A, 0x78, 0x56}},
+ {0x78, 0x56, 0x34, 0x12}},
};
PacketFragments packet39 = {
@@ -778,7 +817,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith4BytePacketNumber) {
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
- {0x56, 0x78, 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
};
// clang-format on
@@ -810,7 +849,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith2BytePacketNumber) {
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
- {0xBC, 0x9A}},
+ {0x78, 0x56}},
};
PacketFragments packet39 = {
@@ -822,7 +861,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith2BytePacketNumber) {
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
- {0x9A, 0xBC}},
+ {0x56, 0x78}},
};
// clang-format on
@@ -855,7 +894,7 @@ TEST_P(QuicFramerTest, PacketHeaderWith1BytePacketNumber) {
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
- {0xBC}},
+ {0x78}},
};
std::unique_ptr<QuicEncryptedPacket> encrypted(
@@ -891,7 +930,7 @@ TEST_P(QuicFramerTest, PacketNumberDecreasesThenIncreases) {
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(kConnectionId, visitor_.header_->connection_id);
- EXPECT_EQ(PACKET_6BYTE_PACKET_NUMBER,
+ EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER,
visitor_.header_->packet_number_length);
EXPECT_EQ(kPacketNumber - 2, visitor_.header_->packet_number);
@@ -936,7 +975,7 @@ TEST_P(QuicFramerTest, PacketWithDiversificationNonce) {
// clang-format off
unsigned char packet[] = {
// public flags: includes nonce flag
- 0x3C,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// nonce
@@ -945,7 +984,7 @@ TEST_P(QuicFramerTest, PacketWithDiversificationNonce) {
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
// packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (padding)
0x00,
@@ -954,7 +993,7 @@ TEST_P(QuicFramerTest, PacketWithDiversificationNonce) {
unsigned char packet39[] = {
// public flags: includes nonce flag
- 0x3C,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// nonce
@@ -963,7 +1002,7 @@ TEST_P(QuicFramerTest, PacketWithDiversificationNonce) {
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
// packet number
- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
+ 0x12, 0x34, 0x56, 0x78,
// frame type (padding)
0x00,
@@ -989,14 +1028,13 @@ TEST_P(QuicFramerTest, LargePublicFlagWithMismatchedVersions) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id, version flag and an unknown flag)
- 0x39,
+ 0x29,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// version tag
'Q', '0', '0', '0',
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (padding frame)
0x00,
@@ -1005,14 +1043,13 @@ TEST_P(QuicFramerTest, LargePublicFlagWithMismatchedVersions) {
unsigned char packet39[] = {
// public flags (8 byte connection_id, version flag and an unknown flag)
- 0x39,
+ 0x29,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// version tag
'Q', '0', '0', '0',
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (padding frame)
0x00,
@@ -1037,12 +1074,11 @@ TEST_P(QuicFramerTest, PaddingFrame) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (padding frame)
0x00,
@@ -1084,7 +1120,7 @@ TEST_P(QuicFramerTest, PaddingFrame) {
GetPacketHeaderSize(framer_.transport_version(),
PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
!kIncludeDiversificationNonce,
- PACKET_6BYTE_PACKET_NUMBER),
+ PACKET_4BYTE_PACKET_NUMBER),
"Packet has no frames.", QUIC_MISSING_PAYLOAD);
}
@@ -1092,12 +1128,11 @@ TEST_P(QuicFramerTest, NewPaddingFrame) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// paddings
0x00, 0x00,
@@ -1120,12 +1155,11 @@ TEST_P(QuicFramerTest, NewPaddingFrame) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// paddings
0x00, 0x00,
@@ -1148,12 +1182,11 @@ TEST_P(QuicFramerTest, NewPaddingFrame) {
unsigned char packet41[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// paddings
0x00, 0x00,
@@ -1208,14 +1241,13 @@ TEST_P(QuicFramerTest, StreamFrame) {
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12}},
+ {0x78, 0x56, 0x34, 0x12}},
// frame type (stream frame with fin)
{"",
{0xFF}},
@@ -1239,14 +1271,13 @@ TEST_P(QuicFramerTest, StreamFrame) {
PacketFragments packet39 = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFF}},
@@ -1270,14 +1301,13 @@ TEST_P(QuicFramerTest, StreamFrame) {
PacketFragments packet41 = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFF}},
@@ -1324,19 +1354,20 @@ TEST_P(QuicFramerTest, StreamFrame) {
TEST_P(QuicFramerTest, MissingDiversificationNonce) {
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
framer_.SetDecrypter(ENCRYPTION_NONE,
- new NullDecrypter(Perspective::IS_CLIENT));
+ QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT));
decrypter_ = new test::TestDecrypter();
- framer_.SetAlternativeDecrypter(ENCRYPTION_INITIAL, decrypter_, false);
+ framer_.SetAlternativeDecrypter(ENCRYPTION_INITIAL,
+ std::unique_ptr<QuicDecrypter>(decrypter_),
+ false);
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (stream frame with fin)
0xFF,
@@ -1355,12 +1386,11 @@ TEST_P(QuicFramerTest, MissingDiversificationNonce) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (stream frame with fin)
0xFF,
@@ -1379,12 +1409,11 @@ TEST_P(QuicFramerTest, MissingDiversificationNonce) {
unsigned char packet41[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (stream frame with fin)
0xFF,
@@ -1418,14 +1447,13 @@ TEST_P(QuicFramerTest, StreamFrame3ByteStreamId) {
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12}},
+ {0x78, 0x56, 0x34, 0x12}},
// frame type (stream frame with fin)
{"",
{0xFE}},
@@ -1449,14 +1477,13 @@ TEST_P(QuicFramerTest, StreamFrame3ByteStreamId) {
PacketFragments packet39 = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFE}},
@@ -1480,14 +1507,13 @@ TEST_P(QuicFramerTest, StreamFrame3ByteStreamId) {
PacketFragments packet41 = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xF7}},
@@ -1537,14 +1563,13 @@ TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) {
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12}},
+ {0x78, 0x56, 0x34, 0x12}},
// frame type (stream frame with fin)
{"",
{0xFD}},
@@ -1568,14 +1593,13 @@ TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) {
PacketFragments packet39 = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFD}},
@@ -1599,14 +1623,13 @@ TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) {
PacketFragments packet41 = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xEF}},
@@ -1656,14 +1679,13 @@ TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) {
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12}},
+ {0x78, 0x56, 0x34, 0x12}},
// frame type (stream frame with fin)
{"",
{0xFC}},
@@ -1687,14 +1709,13 @@ TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) {
PacketFragments packet39 = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFC}},
@@ -1718,14 +1739,13 @@ TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) {
PacketFragments packet41 = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xE7}},
@@ -1775,17 +1795,16 @@ TEST_P(QuicFramerTest, StreamFrameWithVersion) {
PacketFragments packet = {
// public flags (version, 8 byte connection_id)
{"",
- {0x39}},
+ {0x29}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// version tag
{"",
- {'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes()}},
+ {QUIC_VERSION_BYTES}},
// packet number
{"",
- {0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12}},
+ {0x78, 0x56, 0x34, 0x12}},
// frame type (stream frame with fin)
{"",
{0xFE}},
@@ -1809,17 +1828,16 @@ TEST_P(QuicFramerTest, StreamFrameWithVersion) {
PacketFragments packet39 = {
// public flags (version, 8 byte connection_id)
{"",
- {0x39}},
+ {0x29}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// version tag
{"",
- {'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes()}},
+ {QUIC_VERSION_BYTES}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFE}},
@@ -1843,17 +1861,16 @@ TEST_P(QuicFramerTest, StreamFrameWithVersion) {
PacketFragments packet41 = {
// public flags (version, 8 byte connection_id)
{"",
- {0x39}},
+ {0x29}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// version tag
{"",
- {'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes()}},
+ {QUIC_VERSION_BYTES}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xF7}},
@@ -1904,12 +1921,11 @@ TEST_P(QuicFramerTest, RejectPacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (stream frame with fin)
0xFF,
@@ -1928,12 +1944,11 @@ TEST_P(QuicFramerTest, RejectPacket) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (stream frame with fin)
0xFF,
@@ -1952,12 +1967,11 @@ TEST_P(QuicFramerTest, RejectPacket) {
unsigned char packet41[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (stream frame with fin)
0xFF,
@@ -1999,7 +2013,7 @@ TEST_P(QuicFramerTest, RejectPublicHeader) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
};
@@ -2018,13 +2032,13 @@ TEST_P(QuicFramerTest, AckFrameOneAckBlock) {
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
- {0x3C}},
+ {0x2C}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12}},
+ {0x78, 0x56, 0x34, 0x12}},
// frame type (ack frame)
// (one ack block, 2 byte largest observed, 2 byte block length)
{"",
@@ -2046,13 +2060,13 @@ TEST_P(QuicFramerTest, AckFrameOneAckBlock) {
PacketFragments packet39 = {
// public flags (8 byte connection_id)
{"",
- {0x3C}},
+ {0x2C}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (ack frame)
// (one ack block, 2 byte largest observed, 2 byte block length)
{"",
@@ -2074,13 +2088,13 @@ TEST_P(QuicFramerTest, AckFrameOneAckBlock) {
PacketFragments packet41 = {
// public flags (8 byte connection_id)
{"",
- {0x3C}},
+ {0x2C}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (ack frame)
// (one ack block, 2 byte largest observed, 2 byte block length)
{"",
@@ -2126,13 +2140,13 @@ TEST_P(QuicFramerTest, FirstAckFrameUnderflow) {
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
- {0x3C}},
+ {0x2C}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12}},
+ {0x78, 0x56, 0x34, 0x12}},
// frame type (ack frame)
// (one ack block, 2 byte largest observed, 2 byte block length)
{"",
@@ -2154,13 +2168,13 @@ TEST_P(QuicFramerTest, FirstAckFrameUnderflow) {
PacketFragments packet39 = {
// public flags (8 byte connection_id)
{"",
- {0x3C}},
+ {0x2C}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (ack frame)
// (one ack block, 2 byte largest observed, 2 byte block length)
{"",
@@ -2182,13 +2196,13 @@ TEST_P(QuicFramerTest, FirstAckFrameUnderflow) {
PacketFragments packet41 = {
// public flags (8 byte connection_id)
{"",
- {0x3C}},
+ {0x2C}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (ack frame)
// (one ack block, 2 byte largest observed, 2 byte block length)
{"",
@@ -2222,13 +2236,13 @@ TEST_P(QuicFramerTest, AckFrameFirstAckBlockLengthZero) {
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
- { 0x3C }},
+ { 0x2C }},
// connection_id
{"",
{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }},
// packet number
{"",
- { 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12 }},
+ { 0x78, 0x56, 0x34, 0x12 }},
// frame type (ack frame)
// (more than one ack block, 2 byte largest observed, 2 byte block length)
@@ -2263,13 +2277,13 @@ TEST_P(QuicFramerTest, AckFrameFirstAckBlockLengthZero) {
PacketFragments packet39 = {
// public flags (8 byte connection_id)
{"",
- { 0x3C }},
+ { 0x2C }},
// connection_id
{"",
{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }},
// packet number
{"",
- { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC }},
+ { 0x12, 0x34, 0x56, 0x78 }},
// frame type (ack frame)
// (more than one ack block, 2 byte largest observed, 2 byte block length)
@@ -2304,13 +2318,13 @@ TEST_P(QuicFramerTest, AckFrameFirstAckBlockLengthZero) {
PacketFragments packet41 = {
// public flags (8 byte connection_id)
{"",
- { 0x3C }},
+ { 0x2C }},
// connection_id
{"",
{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }},
// packet number
{"",
- { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC }},
+ { 0x12, 0x34, 0x56, 0x78 }},
// frame type (ack frame)
// (more than one ack block, 2 byte largest observed, 2 byte block length)
@@ -2372,20 +2386,20 @@ TEST_P(QuicFramerTest, AckFrameOneAckBlockMaxLength) {
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
- {0x3C}},
+ {0x2C}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12}},
+ {0x78, 0x56, 0x34, 0x12}},
// frame type (ack frame)
- // (one ack block, 6 byte largest observed, 2 byte block length)
+ // (one ack block, 4 byte largest observed, 2 byte block length)
{"",
- {0x4D}},
+ {0x49}},
// largest acked
{"Unable to read largest acked.",
- {0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12}},
+ {0x78, 0x56, 0x34, 0x12}},
// Zero delta time.
{"Unable to read ack delay time.",
{0x00, 0x00}},
@@ -2400,20 +2414,20 @@ TEST_P(QuicFramerTest, AckFrameOneAckBlockMaxLength) {
PacketFragments packet39 = {
// public flags (8 byte connection_id)
{"",
- {0x3C}},
+ {0x2C}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (ack frame)
- // (one ack block, 6 byte largest observed, 2 byte block length)
+ // (one ack block, 4 byte largest observed, 2 byte block length)
{"",
- {0x4D}},
+ {0x49}},
// largest acked
{"Unable to read largest acked.",
- {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// Zero delta time.
{"Unable to read ack delay time.",
{0x00, 0x00}},
@@ -2428,23 +2442,23 @@ TEST_P(QuicFramerTest, AckFrameOneAckBlockMaxLength) {
PacketFragments packet41 = {
// public flags (8 byte connection_id)
{"",
- {0x3C}},
+ {0x2C}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (ack frame)
- // (one ack block, 8 byte largest observed, 2 byte block length)
+ // (one ack block, 4 byte largest observed, 2 byte block length)
{"",
- {0xAD}},
+ {0xA9}},
// num timestamps.
{"Unable to read num received packets.",
{0x00}},
// largest acked
{"Unable to read largest acked.",
- {0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// Zero delta time.
{"Unable to read ack delay time.",
{0x00, 0x00}},
@@ -2481,13 +2495,13 @@ TEST_P(QuicFramerTest, AckFrameTwoTimeStampsMultipleAckBlocks) {
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
- { 0x3C }},
+ { 0x2C }},
// connection_id
{"",
{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }},
// packet number
{"",
- { 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12 }},
+ { 0x78, 0x56, 0x34, 0x12 }},
// frame type (ack frame)
// (more than one ack block, 2 byte largest observed, 2 byte block length)
@@ -2549,13 +2563,13 @@ TEST_P(QuicFramerTest, AckFrameTwoTimeStampsMultipleAckBlocks) {
PacketFragments packet39 = {
// public flags (8 byte connection_id)
{"",
- { 0x3C }},
+ { 0x2C }},
// connection_id
{"",
{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }},
// packet number
{"",
- { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC }},
+ { 0x12, 0x34, 0x56, 0x78 }},
// frame type (ack frame)
// (more than one ack block, 2 byte largest observed, 2 byte block length)
@@ -2617,13 +2631,13 @@ TEST_P(QuicFramerTest, AckFrameTwoTimeStampsMultipleAckBlocks) {
PacketFragments packet41 = {
// public flags (8 byte connection_id)
{"",
- { 0x3C }},
+ { 0x2C }},
// connection_id
{"",
{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }},
// packet number
{"",
- { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC }},
+ { 0x12, 0x34, 0x56, 0x78 }},
// frame type (ack frame)
// (more than one ack block, 2 byte largest observed, 2 byte block length)
@@ -2713,39 +2727,37 @@ TEST_P(QuicFramerTest, NewStopWaitingFrame) {
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
- {0x3C}},
+ {0x2C}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0xA8, 0x9A, 0x78, 0x56, 0x34, 0x12}},
+ {0x78, 0x56, 0x34, 0x12}},
// frame type (stop waiting frame)
{"",
{0x06}},
// least packet number awaiting an ack, delta from packet number.
{"Unable to read least unacked delta.",
- {0x08, 0x00, 0x00, 0x00,
- 0x00, 0x00}}
+ {0x08, 0x00, 0x00, 0x00}}
};
PacketFragments packet39 = {
// public flags (8 byte connection_id)
{"",
- {0x3C}},
+ {0x2C}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78, 0x9A, 0xA8}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (stop waiting frame)
{"",
{0x06}},
// least packet number awaiting an ack, delta from packet number.
{"Unable to read least unacked delta.",
- {0x00, 0x00, 0x00, 0x00,
- 0x00, 0x08}}
+ {0x00, 0x00, 0x00, 0x08}}
};
// clang-format on
@@ -2772,12 +2784,11 @@ TEST_P(QuicFramerTest, InvalidNewStopWaitingFrame) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x3C,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xA8, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (stop waiting frame)
0x06,
// least packet number awaiting an ack, delta from packet number.
@@ -2787,12 +2798,11 @@ TEST_P(QuicFramerTest, InvalidNewStopWaitingFrame) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x3C,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xA8,
// frame type (stop waiting frame)
0x06,
// least packet number awaiting an ack, delta from packet number.
@@ -2815,13 +2825,13 @@ TEST_P(QuicFramerTest, RstStreamFrame) {
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12}},
+ {0x78, 0x56, 0x34, 0x12}},
// frame type (rst stream frame)
{"",
{0x01}},
@@ -2840,13 +2850,13 @@ TEST_P(QuicFramerTest, RstStreamFrame) {
PacketFragments packet39 = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (rst stream frame)
{"",
{0x01}},
@@ -2865,13 +2875,13 @@ TEST_P(QuicFramerTest, RstStreamFrame) {
PacketFragments packet41 = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (rst stream frame)
{"",
{0x01}},
@@ -2912,13 +2922,13 @@ TEST_P(QuicFramerTest, ConnectionCloseFrame) {
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12}},
+ {0x78, 0x56, 0x34, 0x12}},
// frame type (connection close frame)
{"",
{0x02}},
@@ -2940,13 +2950,13 @@ TEST_P(QuicFramerTest, ConnectionCloseFrame) {
PacketFragments packet39 = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (connection close frame)
{"",
{0x02}},
@@ -2992,13 +3002,13 @@ TEST_P(QuicFramerTest, GoAwayFrame) {
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12}},
+ {0x78, 0x56, 0x34, 0x12}},
// frame type (go away frame)
{"",
{0x03}},
@@ -3023,13 +3033,13 @@ TEST_P(QuicFramerTest, GoAwayFrame) {
PacketFragments packet39 = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (go away frame)
{"",
{0x03}},
@@ -3076,13 +3086,13 @@ TEST_P(QuicFramerTest, WindowUpdateFrame) {
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12}},
+ {0x78, 0x56, 0x34, 0x12}},
// frame type (window update frame)
{"",
{0x04}},
@@ -3098,13 +3108,13 @@ TEST_P(QuicFramerTest, WindowUpdateFrame) {
PacketFragments packet39 = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (window update frame)
{"",
{0x04}},
@@ -3140,13 +3150,13 @@ TEST_P(QuicFramerTest, BlockedFrame) {
PacketFragments packet = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12}},
+ {0x78, 0x56, 0x34, 0x12}},
// frame type (blocked frame)
{"",
{0x05}},
@@ -3158,13 +3168,13 @@ TEST_P(QuicFramerTest, BlockedFrame) {
PacketFragments packet39 = {
// public flags (8 byte connection_id)
{"",
- {0x38}},
+ {0x28}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}},
+ {0x12, 0x34, 0x56, 0x78}},
// frame type (blocked frame)
{"",
{0x05}},
@@ -3194,12 +3204,11 @@ TEST_P(QuicFramerTest, PingFrame) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (ping frame)
0x07,
@@ -3207,12 +3216,11 @@ TEST_P(QuicFramerTest, PingFrame) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (ping frame)
0x07,
@@ -3430,13 +3438,13 @@ TEST_P(QuicFramerTest, VersionNegotiationPacket) {
PacketFragments packet = {
// public flags (version, 8 byte connection_id)
{"",
- {0x39}},
+ {0x29}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// version tag
{"Unable to read supported version in negotiation.",
- {'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(),
+ {QUIC_VERSION_BYTES,
'Q', '2', '.', '0'}},
};
// clang-format on
@@ -3465,13 +3473,13 @@ TEST_P(QuicFramerTest, OldVersionNegotiationPacket) {
PacketFragments packet = {
// public flags (version, 8 byte connection_id)
{"",
- {0x3D}},
+ {0x2D}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// version tag
{"Unable to read supported version in negotiation.",
- {'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(),
+ {QUIC_VERSION_BYTES,
'Q', '2', '.', '0'}},
};
// clang-format on
@@ -3507,12 +3515,11 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) {
// clang-format off
unsigned char packet[kMaxPacketSize] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (padding frame)
0x00,
@@ -3521,12 +3528,11 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) {
unsigned char packet39[kMaxPacketSize] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (padding frame)
0x00,
@@ -3536,7 +3542,7 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) {
uint64_t header_size = GetPacketHeaderSize(
framer_.transport_version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludeDiversificationNonce, PACKET_6BYTE_PACKET_NUMBER);
+ !kIncludeDiversificationNonce, PACKET_4BYTE_PACKET_NUMBER);
memset((framer_.transport_version() <= QUIC_VERSION_38 ? packet : packet39) +
header_size + 1,
0x00, kMaxPacketSize - header_size - 1);
@@ -3570,12 +3576,11 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithNewPaddingFrame) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// paddings
0x00, 0x00,
@@ -3598,12 +3603,11 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithNewPaddingFrame) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// paddings
0x00, 0x00,
@@ -3626,12 +3630,11 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithNewPaddingFrame) {
unsigned char packet41[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// paddings
0x00, 0x00,
@@ -3686,7 +3689,7 @@ TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) {
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (padding frame)
0x00,
@@ -3699,7 +3702,7 @@ TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) {
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0x56, 0x78, 0x9A, 0xBC,
+ 0x12, 0x34, 0x56, 0x78,
// frame type (padding frame)
0x00,
@@ -3741,7 +3744,7 @@ TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) {
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A,
+ 0x78, 0x56,
// frame type (padding frame)
0x00,
@@ -3754,7 +3757,7 @@ TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) {
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0x9A, 0xBC,
+ 0x56, 0x78,
// frame type (padding frame)
0x00,
@@ -3796,7 +3799,7 @@ TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) {
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC,
+ 0x78,
// frame type (padding frame)
0x00,
@@ -3832,12 +3835,11 @@ TEST_P(QuicFramerTest, BuildStreamFramePacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (stream frame with fin and no length)
0xDF,
@@ -3854,12 +3856,11 @@ TEST_P(QuicFramerTest, BuildStreamFramePacket) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (stream frame with fin and no length)
0xDF,
@@ -3876,12 +3877,11 @@ TEST_P(QuicFramerTest, BuildStreamFramePacket) {
unsigned char packet41[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (stream frame with fin and no length)
0xFE,
@@ -3925,13 +3925,13 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) {
// clang-format off
unsigned char packet[] = {
// public flags (version, 8 byte connection_id)
- 0x3D,
+ 0x2D,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// version tag
- 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(),
+ QUIC_VERSION_BYTES,
// packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (stream frame with fin and no length)
0xDF,
@@ -3945,13 +3945,13 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) {
unsigned char packet39[] = {
// public flags (version, 8 byte connection_id)
- 0x3D,
+ 0x2D,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// version tag
- 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(),
+ QUIC_VERSION_BYTES,
// packet number
- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
+ 0x12, 0x34, 0x56, 0x78,
// frame type (stream frame with fin and no length)
0xDF,
@@ -3965,13 +3965,13 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) {
unsigned char packet41[] = {
// public flags (version, 8 byte connection_id)
- 0x3D,
+ 0x2D,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// version tag
- 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(),
+ QUIC_VERSION_BYTES,
// packet number
- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
+ 0x12, 0x34, 0x56, 0x78,
// frame type (stream frame with fin and no length)
0xFE,
@@ -4007,13 +4007,13 @@ TEST_P(QuicFramerTest, BuildVersionNegotiationPacket) {
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// version tag
- 'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(),
+ QUIC_VERSION_BYTES,
};
// clang-format on
QuicConnectionId connection_id = kConnectionId;
std::unique_ptr<QuicEncryptedPacket> data(
- framer_.BuildVersionNegotiationPacket(connection_id,
+ framer_.BuildVersionNegotiationPacket(connection_id, false,
SupportedVersions(GetParam())));
test::CompareCharArraysWithHexError("constructed packet", data->data(),
data->length(), AsChars(packet),
@@ -4036,11 +4036,11 @@ TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlock) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (ack frame)
// (no ack blocks, 2 byte largest observed, 2 byte block length)
@@ -4057,11 +4057,11 @@ TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlock) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
+ 0x12, 0x34, 0x56, 0x78,
// frame type (ack frame)
// (no ack blocks, 2 byte largest observed, 2 byte block length)
@@ -4078,11 +4078,11 @@ TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlock) {
unsigned char packet41[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
+ 0x12, 0x34, 0x56, 0x78,
// frame type (ack frame)
// (no ack blocks, 2 byte largest observed, 2 byte block length)
@@ -4126,65 +4126,65 @@ TEST_P(QuicFramerTest, BuildAckFramePacketOneAckBlockMaxLength) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (ack frame)
- // (no ack blocks, 6 byte largest observed, 6 byte block length)
- 0x4F,
+ // (no ack blocks, 4 byte largest observed, 4 byte block length)
+ 0x4A,
// largest acked
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// Zero delta time.
0x00, 0x00,
// first ack block length.
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// num timestamps.
0x00,
};
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
+ 0x12, 0x34, 0x56, 0x78,
// frame type (ack frame)
- // (no ack blocks, 6 byte largest observed, 6 byte block length)
- 0x4F,
+ // (no ack blocks, 4 byte largest observed, 4 byte block length)
+ 0x4A,
// largest acked
- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
+ 0x12, 0x34, 0x56, 0x78,
// Zero delta time.
0x00, 0x00,
// first ack block length.
- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
+ 0x12, 0x34, 0x56, 0x78,
// num timestamps.
0x00,
};
unsigned char packet41[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
+ 0x12, 0x34, 0x56, 0x78,
// frame type (ack frame)
- // (no ack blocks, 8 byte largest observed, 8 byte block length)
- 0xAF,
+ // (no ack blocks, 4 byte largest observed, 4 byte block length)
+ 0xAA,
// num timestamps.
0x00,
// largest acked
- 0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
+ 0x12, 0x34, 0x56, 0x78,
// Zero delta time.
0x00, 0x00,
// first ack block length.
- 0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
+ 0x12, 0x34, 0x56, 0x78,
};
// clang-format on
unsigned char* p = packet;
@@ -4223,11 +4223,11 @@ TEST_P(QuicFramerTest, BuildAckFramePacketMultipleAckBlocks) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (ack frame)
// (has ack blocks, 2 byte largest observed, 2 byte block length)
@@ -4262,11 +4262,11 @@ TEST_P(QuicFramerTest, BuildAckFramePacketMultipleAckBlocks) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
+ 0x12, 0x34, 0x56, 0x78,
// frame type (ack frame)
// (has ack blocks, 2 byte largest observed, 2 byte block length)
@@ -4301,11 +4301,11 @@ TEST_P(QuicFramerTest, BuildAckFramePacketMultipleAckBlocks) {
unsigned char packet41[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
+ 0x12, 0x34, 0x56, 0x78,
// frame type (ack frame)
// (has ack blocks, 2 byte largest observed, 2 byte block length)
@@ -4375,11 +4375,11 @@ TEST_P(QuicFramerTest, BuildAckFramePacketMaxAckBlocks) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (ack frame)
// (has ack blocks, 2 byte largest observed, 2 byte block length)
0x65,
@@ -4468,11 +4468,11 @@ TEST_P(QuicFramerTest, BuildAckFramePacketMaxAckBlocks) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
+ 0x12, 0x34, 0x56, 0x78,
// frame type (ack frame)
// (has ack blocks, 2 byte largest observed, 2 byte block length)
0x65,
@@ -4561,11 +4561,11 @@ TEST_P(QuicFramerTest, BuildAckFramePacketMaxAckBlocks) {
unsigned char packet41[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
+ 0x12, 0x34, 0x56, 0x78,
// frame type (ack frame)
// (has ack blocks, 2 byte largest observed, 2 byte block length)
0xB5,
@@ -4682,32 +4682,30 @@ TEST_P(QuicFramerTest, BuildNewStopWaitingPacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (stop waiting frame)
0x06,
// least packet number awaiting an ack, delta from packet number.
- 0x1C, 0x00, 0x00, 0x00,
- 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00,
};
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
+ 0x12, 0x34, 0x56, 0x78,
// frame type (stop waiting frame)
0x06,
// least packet number awaiting an ack, delta from packet number.
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x1C,
+ 0x00, 0x00, 0x00, 0x08,
};
// clang-format on
@@ -4736,12 +4734,11 @@ TEST_P(QuicFramerTest, BuildRstFramePacketQuic) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (rst stream frame)
0x01,
@@ -4756,12 +4753,11 @@ TEST_P(QuicFramerTest, BuildRstFramePacketQuic) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (rst stream frame)
0x01,
@@ -4776,12 +4772,11 @@ TEST_P(QuicFramerTest, BuildRstFramePacketQuic) {
unsigned char packet41[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (rst stream frame)
0x01,
@@ -4829,12 +4824,11 @@ TEST_P(QuicFramerTest, BuildCloseFramePacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (connection close frame)
0x02,
@@ -4851,12 +4845,11 @@ TEST_P(QuicFramerTest, BuildCloseFramePacket) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (connection close frame)
0x02,
@@ -4898,12 +4891,11 @@ TEST_P(QuicFramerTest, BuildTruncatedCloseFramePacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (connection close frame)
0x02,
@@ -4948,12 +4940,11 @@ TEST_P(QuicFramerTest, BuildTruncatedCloseFramePacket) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (connection close frame)
0x02,
@@ -5028,12 +5019,11 @@ TEST_P(QuicFramerTest, BuildGoAwayPacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (go away frame)
0x03,
@@ -5052,12 +5042,11 @@ TEST_P(QuicFramerTest, BuildGoAwayPacket) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (go away frame)
0x03,
@@ -5102,12 +5091,11 @@ TEST_P(QuicFramerTest, BuildTruncatedGoAwayPacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (go away frame)
0x03,
@@ -5154,12 +5142,11 @@ TEST_P(QuicFramerTest, BuildTruncatedGoAwayPacket) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (go away frame)
0x03,
@@ -5235,12 +5222,11 @@ TEST_P(QuicFramerTest, BuildWindowUpdatePacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (window update frame)
0x04,
@@ -5253,12 +5239,11 @@ TEST_P(QuicFramerTest, BuildWindowUpdatePacket) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (window update frame)
0x04,
@@ -5295,12 +5280,11 @@ TEST_P(QuicFramerTest, BuildBlockedPacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (blocked frame)
0x05,
@@ -5310,12 +5294,11 @@ TEST_P(QuicFramerTest, BuildBlockedPacket) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (blocked frame)
0x05,
@@ -5346,12 +5329,11 @@ TEST_P(QuicFramerTest, BuildPingPacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (ping frame)
0x07,
@@ -5359,12 +5341,11 @@ TEST_P(QuicFramerTest, BuildPingPacket) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (ping frame)
0x07,
@@ -5393,12 +5374,11 @@ TEST_P(QuicFramerTest, BuildConnectivityProbingPacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (ping frame)
0x07,
@@ -5409,12 +5389,11 @@ TEST_P(QuicFramerTest, BuildConnectivityProbingPacket) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (ping frame)
0x07,
@@ -5461,12 +5440,11 @@ TEST_P(QuicFramerTest, BuildMtuDiscoveryPacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (ping frame)
0x07,
@@ -5474,12 +5452,11 @@ TEST_P(QuicFramerTest, BuildMtuDiscoveryPacket) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (ping frame)
0x07,
@@ -5579,12 +5556,11 @@ TEST_P(QuicFramerTest, EncryptPacket) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// redundancy
'a', 'b', 'c', 'd',
@@ -5595,12 +5571,11 @@ TEST_P(QuicFramerTest, EncryptPacket) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// redundancy
'a', 'b', 'c', 'd',
@@ -5615,7 +5590,7 @@ TEST_P(QuicFramerTest, EncryptPacket) {
: packet39),
QUIC_ARRAYSIZE(packet), false, PACKET_8BYTE_CONNECTION_ID,
!kIncludeVersion, !kIncludeDiversificationNonce,
- PACKET_6BYTE_PACKET_NUMBER));
+ PACKET_4BYTE_PACKET_NUMBER));
char buffer[kMaxPacketSize];
size_t encrypted_length = framer_.EncryptPayload(
ENCRYPTION_NONE, packet_number, *raw, buffer, kMaxPacketSize);
@@ -5629,14 +5604,13 @@ TEST_P(QuicFramerTest, EncryptPacketWithVersionFlag) {
// clang-format off
unsigned char packet[] = {
// public flags (version, 8 byte connection_id)
- 0x39,
+ 0x29,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// version tag
'Q', '.', '1', '0',
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// redundancy
'a', 'b', 'c', 'd',
@@ -5647,14 +5621,13 @@ TEST_P(QuicFramerTest, EncryptPacketWithVersionFlag) {
unsigned char packet39[] = {
// public flags (version, 8 byte connection_id)
- 0x39,
+ 0x29,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// version tag
'Q', '.', '1', '0',
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// redundancy
'a', 'b', 'c', 'd',
@@ -5669,7 +5642,7 @@ TEST_P(QuicFramerTest, EncryptPacketWithVersionFlag) {
: packet39),
QUIC_ARRAYSIZE(packet), false, PACKET_8BYTE_CONNECTION_ID,
kIncludeVersion, !kIncludeDiversificationNonce,
- PACKET_6BYTE_PACKET_NUMBER));
+ PACKET_4BYTE_PACKET_NUMBER));
char buffer[kMaxPacketSize];
size_t encrypted_length = framer_.EncryptPayload(
ENCRYPTION_NONE, packet_number, *raw, buffer, kMaxPacketSize);
@@ -5736,8 +5709,8 @@ TEST_P(QuicFramerTest, AckTruncationSmallPacket) {
ASSERT_EQ(1u, visitor_.ack_frames_.size());
QuicAckFrame& processed_ack_frame = *visitor_.ack_frames_[0];
EXPECT_EQ(600u, LargestAcked(processed_ack_frame));
- ASSERT_EQ(239u, processed_ack_frame.packets.NumPacketsSlow());
- EXPECT_EQ(124u, processed_ack_frame.packets.Min());
+ ASSERT_EQ(240u, processed_ack_frame.packets.NumPacketsSlow());
+ EXPECT_EQ(122u, processed_ack_frame.packets.Min());
EXPECT_EQ(600u, processed_ack_frame.packets.Max());
}
@@ -5782,12 +5755,11 @@ TEST_P(QuicFramerTest, StopPacketProcessing) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// frame type (stream frame with fin)
0xFF,
@@ -5820,12 +5792,11 @@ TEST_P(QuicFramerTest, StopPacketProcessing) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (stream frame with fin)
0xFF,
@@ -5858,12 +5829,11 @@ TEST_P(QuicFramerTest, StopPacketProcessing) {
unsigned char packet41[] = {
// public flags (8 byte connection_id)
- 0x38,
+ 0x28,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// frame type (stream frame with fin)
0xFF,
@@ -5934,14 +5904,14 @@ TEST_P(QuicFramerTest, ConstructEncryptedPacket) {
// Since we are using ConstructEncryptedPacket, we have to set the framer's
// crypto to be Null.
framer_.SetDecrypter(ENCRYPTION_NONE,
- new NullDecrypter(framer_.perspective()));
+ QuicMakeUnique<NullDecrypter>(framer_.perspective()));
framer_.SetEncrypter(ENCRYPTION_NONE,
- new NullEncrypter(framer_.perspective()));
+ QuicMakeUnique<NullEncrypter>(framer_.perspective()));
ParsedQuicVersionVector versions;
versions.push_back(framer_.version());
std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
42, false, false, kTestQuicStreamId, kTestString,
- PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, &versions));
+ PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, &versions));
MockFramerVisitor visitor;
framer_.set_visitor(&visitor);
@@ -5970,14 +5940,14 @@ TEST_P(QuicFramerTest, ConstructMisFramedEncryptedPacket) {
// Since we are using ConstructEncryptedPacket, we have to set the framer's
// crypto to be Null.
framer_.SetDecrypter(ENCRYPTION_NONE,
- new NullDecrypter(framer_.perspective()));
+ QuicMakeUnique<NullDecrypter>(framer_.perspective()));
framer_.SetEncrypter(ENCRYPTION_NONE,
- new NullEncrypter(framer_.perspective()));
+ QuicMakeUnique<NullEncrypter>(framer_.perspective()));
ParsedQuicVersionVector versions;
versions.push_back(framer_.version());
std::unique_ptr<QuicEncryptedPacket> packet(ConstructMisFramedEncryptedPacket(
42, false, false, kTestQuicStreamId, kTestString,
- PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, &versions,
+ PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, &versions,
Perspective::IS_CLIENT));
MockFramerVisitor visitor;
@@ -6010,6 +5980,7 @@ extern "C" {
void QuicFramerFuzzFunc(unsigned char* data, size_t size) {
QuicFramer framer(AllSupportedVersions(), QuicTime::Zero(),
Perspective::IS_SERVER);
+ ASSERT_EQ(GetQuicFlag(FLAGS_quic_supports_tls_handshake), true);
const char* const packet_bytes = reinterpret_cast<const char*>(data);
// Test the CryptoFramer.
@@ -6032,12 +6003,11 @@ TEST_P(QuicFramerTest, FramerFuzzTest) {
// clang-format off
unsigned char packet[] = {
// public flags (8 byte connection_id)
- 0x3C,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ 0x78, 0x56, 0x34, 0x12,
// private flags
0x00,
@@ -6058,12 +6028,11 @@ TEST_P(QuicFramerTest, FramerFuzzTest) {
unsigned char packet39[] = {
// public flags (8 byte connection_id)
- 0x3C,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// private flags
0x00,
@@ -6084,12 +6053,11 @@ TEST_P(QuicFramerTest, FramerFuzzTest) {
unsigned char packet41[] = {
// public flags (8 byte connection_id)
- 0x3C,
+ 0x2C,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
- 0x9A, 0xBC,
// private flags
0x00,
diff --git a/chromium/net/quic/core/quic_headers_stream.cc b/chromium/net/quic/core/quic_headers_stream.cc
index 22da417ce0b..52e6c41917d 100644
--- a/chromium/net/quic/core/quic_headers_stream.cc
+++ b/chromium/net/quic/core/quic_headers_stream.cc
@@ -26,7 +26,8 @@ QuicHeadersStream::CompressedHeaderInfo::CompressedHeaderInfo(
QuicHeadersStream::CompressedHeaderInfo::~CompressedHeaderInfo() {}
QuicHeadersStream::QuicHeadersStream(QuicSpdySession* session)
- : QuicStream(kHeadersStreamId, session), spdy_session_(session) {
+ : QuicStream(kHeadersStreamId, session, /*is_static=*/true),
+ spdy_session_(session) {
// The headers stream is exempt from connection level flow control.
DisableConnectionFlowControlForThisStream();
}
diff --git a/chromium/net/quic/core/quic_headers_stream_test.cc b/chromium/net/quic/core/quic_headers_stream_test.cc
index 30ca9007bc9..d515adcad4c 100644
--- a/chromium/net/quic/core/quic_headers_stream_test.cc
+++ b/chromium/net/quic/core/quic_headers_stream_test.cc
@@ -76,7 +76,8 @@ class MockVisitor : public SpdyFramerVisitorInterface {
MOCK_METHOD2(OnRstStream,
void(SpdyStreamId stream_id, SpdyErrorCode error_code));
MOCK_METHOD0(OnSettings, void());
- MOCK_METHOD2(OnSetting, void(SpdyKnownSettingsId id, uint32_t value));
+ MOCK_METHOD2(OnSettingOld, void(SpdyKnownSettingsId id, uint32_t value));
+ MOCK_METHOD2(OnSetting, void(SpdySettingsId id, uint32_t value));
MOCK_METHOD0(OnSettingsAck, void());
MOCK_METHOD0(OnSettingsEnd, void());
MOCK_METHOD2(OnPing, void(SpdyPingId unique_id, bool is_ack));
@@ -167,10 +168,11 @@ class QuicHeadersStreamTest : public QuicTestWithParam<TestParams> {
perspective(),
GetVersion())),
session_(connection_),
- headers_stream_(QuicSpdySessionPeer::GetHeadersStream(&session_)),
body_("hello world"),
stream_frame_(kHeadersStreamId, /*fin=*/false, /*offset=*/0, ""),
next_promised_stream_id_(2) {
+ session_.Initialize();
+ headers_stream_ = QuicSpdySessionPeer::GetHeadersStream(&session_);
headers_[":version"] = "HTTP/1.1";
headers_[":status"] = "200 Ok";
headers_["content-length"] = "11";
diff --git a/chromium/net/quic/core/quic_ietf_framer_test.cc b/chromium/net/quic/core/quic_ietf_framer_test.cc
index 5373d6fcf31..daed5d083e9 100644
--- a/chromium/net/quic/core/quic_ietf_framer_test.cc
+++ b/chromium/net/quic/core/quic_ietf_framer_test.cc
@@ -96,20 +96,20 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
QuicStreamFrame source_stream_frame(
stream_id, fin_bit, offset, xmit_packet_data, xmit_packet_data_size);
- // write the frame to the packet buffer.
+ // Write the frame to the packet buffer.
EXPECT_TRUE(QuicFramerPeer::AppendIetfStreamFrame(
&framer_, source_stream_frame, last_frame_bit, &writer));
- // better have something in the packet buffer.
+ // Better have something in the packet buffer.
EXPECT_NE(0u, writer.length());
- // now set up a reader to read in the thing in.
+ // Now set up a reader to read in the frame.
QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
- // read in the frame type
+ // Read in the frame type
uint8_t received_frame_type;
EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
EXPECT_EQ(received_frame_type, frame_type);
- // a StreamFrame to hold the results... we know the frame type,
+ // A StreamFrame to hold the results... we know the frame type,
// put it into the QuicIetfStreamFrame
QuicStreamFrame sink_stream_frame;
@@ -123,10 +123,10 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
EXPECT_EQ(sink_stream_frame.fin, source_stream_frame.fin);
EXPECT_EQ(sink_stream_frame.data_length, source_stream_frame.data_length);
if (frame_type & IETF_STREAM_FRAME_OFF_BIT) {
- // there was an offset in the frame, see if xmit and rcv vales equal.
+ // There was an offset in the frame, see if xmit and rcv vales equal.
EXPECT_EQ(sink_stream_frame.offset, source_stream_frame.offset);
} else {
- // offset not in frame, so it better come out 0.
+ // Offset not in frame, so it better come out 0.
EXPECT_EQ(sink_stream_frame.offset, 0u);
}
EXPECT_NE(sink_stream_frame.data_buffer, nullptr);
@@ -157,15 +157,14 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
QuicAckFrame transmit_frame = InitAckFrame(frame->ranges);
transmit_frame.ack_delay_time =
QuicTime::Delta::FromMicroseconds(frame->delay_time);
- QUIC_LOG(INFO) << "XXXXXXXXXX transmit frame is " << transmit_frame;
- // write the frame to the packet buffer.
- EXPECT_TRUE(QuicFramerPeer::AppendIetfAckFrameAndTypeByte(
- &framer_, transmit_frame, &writer));
- // better have something in the packet buffer.
+ // Write the frame to the packet buffer.
+ EXPECT_TRUE(
+ QuicFramerPeer::AppendIetfAckFrame(&framer_, transmit_frame, &writer));
+ // Better have something in the packet buffer.
EXPECT_NE(0u, writer.length());
- // now set up a reader to read in the thing in.
+ // Now set up a reader to read in the frame.
QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
// read in the frame type
@@ -179,7 +178,7 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
EXPECT_TRUE(QuicFramerPeer::ProcessIetfAckFrame(
&framer_, &reader, received_frame_type, &receive_frame));
- // Now check that things are correct
+ // Now check that the received frame matches the sent frame.
EXPECT_EQ(transmit_frame.largest_acked, receive_frame.largest_acked);
// The ~0x7 needs some explaining. The ack frame format down shifts the
// delay time by 3 (divide by 8) to allow for greater ranges in delay time.
@@ -205,6 +204,121 @@ class QuicIetfFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
return true;
}
+ // encode, decode, and check a Path Challenge frame.
+ bool TryPathChallengeFrame(char* packet_buffer,
+ size_t packet_buffer_size,
+ const QuicPathFrameBuffer& data) {
+ // Make a writer so that the serialized packet is placed in
+ // packet_buffer.
+ QuicDataWriter writer(packet_buffer_size, packet_buffer,
+ NETWORK_BYTE_ORDER);
+
+ QuicPathChallengeFrame transmit_frame(0, data);
+
+ // write the frame to the packet buffer.
+ EXPECT_TRUE(QuicFramerPeer::AppendIetfPathChallengeFrame(
+ &framer_, transmit_frame, &writer));
+
+ // Check for correct length in the packet buffer.
+ EXPECT_EQ(kQuicPathChallengeFrameSize, writer.length());
+
+ // now set up a reader to read in the frame.
+ QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+
+ // read in the frame type
+ uint8_t received_frame_type;
+ EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
+ EXPECT_EQ(received_frame_type, IETF_PATH_CHALLENGE);
+
+ QuicPathChallengeFrame receive_frame;
+
+ EXPECT_TRUE(QuicFramerPeer::ProcessIetfPathChallengeFrame(&framer_, &reader,
+ &receive_frame));
+
+ // Now check that the received frame matches the sent frame.
+ EXPECT_EQ(
+ 0, memcmp(transmit_frame.data_buffer.data(),
+ receive_frame.data_buffer.data(), kQuicPathFrameBufferSize));
+ return true;
+ }
+
+ // encode, decode, and check a Path Response frame.
+ bool TryPathResponseFrame(char* packet_buffer,
+ size_t packet_buffer_size,
+ const QuicPathFrameBuffer& data) {
+ // Make a writer so that the serialized packet is placed in
+ // packet_buffer.
+ QuicDataWriter writer(packet_buffer_size, packet_buffer,
+ NETWORK_BYTE_ORDER);
+
+ QuicPathResponseFrame transmit_frame(0, data);
+
+ // Write the frame to the packet buffer.
+ EXPECT_TRUE(QuicFramerPeer::AppendIetfPathResponseFrame(
+ &framer_, transmit_frame, &writer));
+
+ // Check for correct length in the packet buffer.
+ EXPECT_EQ(kQuicPathResponseFrameSize, writer.length());
+
+ // Set up a reader to read in the frame.
+ QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+
+ // Read in the frame type
+ uint8_t received_frame_type;
+ EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
+ EXPECT_EQ(received_frame_type, IETF_PATH_RESPONSE);
+
+ QuicPathResponseFrame receive_frame;
+
+ EXPECT_TRUE(QuicFramerPeer::ProcessIetfPathResponseFrame(&framer_, &reader,
+ &receive_frame));
+
+ // Now check that the received frame matches the sent frame.
+ EXPECT_EQ(
+ 0, memcmp(transmit_frame.data_buffer.data(),
+ receive_frame.data_buffer.data(), kQuicPathFrameBufferSize));
+ return true;
+ }
+
+ // Test the Serialization/deserialization of a Reset Stream Frame.
+ void TryResetFrame(char* packet_buffer,
+ size_t packet_buffer_size,
+ QuicStreamId stream_id,
+ QuicRstStreamErrorCode error_code,
+ QuicStreamOffset final_offset) {
+ // Initialize a writer so that the serialized packet is placed in
+ // packet_buffer.
+ QuicDataWriter writer(packet_buffer_size, packet_buffer,
+ NETWORK_BYTE_ORDER);
+
+ QuicRstStreamFrame transmit_frame(static_cast<QuicControlFrameId>(1),
+ stream_id, error_code, final_offset);
+
+ // Write the frame to the packet buffer.
+ EXPECT_TRUE(QuicFramerPeer::AppendIetfResetStreamFrame(
+ &framer_, transmit_frame, &writer));
+ // Check that the size of the serialzed frame is in the allowed range.
+ EXPECT_LT(4u, writer.length());
+ EXPECT_GT(20u, writer.length());
+ // Now set up a reader to read in the thing in.
+ QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+
+ // Read in the frame type and check that it is IETF_RST_STREAM.
+ uint8_t received_frame_type;
+ EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
+ EXPECT_EQ(received_frame_type, QuicIetfFrameType::IETF_RST_STREAM);
+
+ // A QuicRstStreamFrame to hold the results
+ QuicRstStreamFrame receive_frame;
+ EXPECT_TRUE(QuicFramerPeer::ProcessIetfResetStreamFrame(&framer_, &reader,
+ &receive_frame));
+
+ // Now check that the received values match the input.
+ EXPECT_EQ(receive_frame.stream_id, transmit_frame.stream_id);
+ EXPECT_EQ(receive_frame.error_code, transmit_frame.error_code);
+ EXPECT_EQ(receive_frame.byte_offset, transmit_frame.byte_offset);
+ }
+
QuicTime start_;
QuicFramer framer_;
};
@@ -372,11 +486,7 @@ TEST_F(QuicIetfFramerTest, StreamFrame) {
}
}
-// tests for the ietf connection/application close frames.
-// These are not regular enough to be table driven, so doing
-// explicit tests is what we need to do...
-
-TEST_F(QuicIetfFramerTest, ConnectionClose1) {
+TEST_F(QuicIetfFramerTest, ConnectionCloseEmptyString) {
char packet_buffer[kNormalPacketBufferSize];
// initialize a writer so that the serialized packet is placed in
@@ -384,16 +494,19 @@ TEST_F(QuicIetfFramerTest, ConnectionClose1) {
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
NETWORK_BYTE_ORDER);
- QuicString test_string = "This is a test of the emergency broadcast system";
+ // empty string,
+ QuicString test_string = "Ich Bin Ein Jelly Donut?";
+ QuicConnectionCloseFrame sent_frame;
+ sent_frame.error_code = static_cast<QuicErrorCode>(0);
+ sent_frame.error_details = test_string;
// write the frame to the packet buffer.
EXPECT_TRUE(QuicFramerPeer::AppendIetfConnectionCloseFrame(
- &framer_, QuicIetfTransportErrorCodes::VERSION_NEGOTIATION_ERROR,
- test_string, &writer));
+ &framer_, sent_frame, &writer));
// better have something in the packet buffer.
EXPECT_NE(0u, writer.length());
- // now set up a reader to read in the thing in.
+ // now set up a reader to read in the frame.
QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
// read in the frame type
@@ -408,14 +521,11 @@ TEST_F(QuicIetfFramerTest, ConnectionClose1) {
&framer_, &reader, received_frame_type, &sink_frame));
// Now check that received == sent
- EXPECT_EQ(sink_frame.error_code,
- static_cast<QuicErrorCode>(
- QuicIetfTransportErrorCodes::VERSION_NEGOTIATION_ERROR));
+ EXPECT_EQ(sink_frame.error_code, static_cast<QuicErrorCode>(0));
EXPECT_EQ(sink_frame.error_details, test_string);
}
-// test case of having no string. also the 0 error code,
-TEST_F(QuicIetfFramerTest, ConnectionClose2) {
+TEST_F(QuicIetfFramerTest, ApplicationCloseEmptyString) {
char packet_buffer[kNormalPacketBufferSize];
// initialize a writer so that the serialized packet is placed in
@@ -424,212 +534,515 @@ TEST_F(QuicIetfFramerTest, ConnectionClose2) {
NETWORK_BYTE_ORDER);
// empty string,
- QuicString test_string;
+ QuicString test_string = "Ich Bin Ein Jelly Donut?";
+ QuicConnectionCloseFrame sent_frame;
+ sent_frame.error_code = static_cast<QuicErrorCode>(0);
+ sent_frame.error_details = test_string;
// write the frame to the packet buffer.
- EXPECT_TRUE(QuicFramerPeer::AppendIetfConnectionCloseFrame(
- &framer_,
- QuicIetfTransportErrorCodes::NO_IETF_QUIC_ERROR, // NO_ERROR == 0
- test_string, &writer));
+ EXPECT_TRUE(QuicFramerPeer::AppendIetfApplicationCloseFrame(
+ &framer_, sent_frame, &writer));
// better have something in the packet buffer.
EXPECT_NE(0u, writer.length());
- // now set up a reader to read in the thing in.
+ // now set up a reader to read in the frame.
QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
// read in the frame type
uint8_t received_frame_type;
EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
- EXPECT_EQ(received_frame_type, QuicIetfFrameType::IETF_CONNECTION_CLOSE);
+ EXPECT_EQ(received_frame_type, QuicIetfFrameType::IETF_APPLICATION_CLOSE);
// a QuicConnectionCloseFrame to hold the results.
QuicConnectionCloseFrame sink_frame;
- EXPECT_TRUE(QuicFramerPeer::ProcessIetfConnectionCloseFrame(
+ EXPECT_TRUE(QuicFramerPeer::ProcessIetfApplicationCloseFrame(
&framer_, &reader, received_frame_type, &sink_frame));
// Now check that received == sent
- EXPECT_EQ(sink_frame.error_code,
- static_cast<QuicErrorCode>(
- QuicIetfTransportErrorCodes::NO_IETF_QUIC_ERROR));
+ EXPECT_EQ(sink_frame.error_code, static_cast<QuicErrorCode>(0));
EXPECT_EQ(sink_frame.error_details, test_string);
}
-// Set fields of the frame via a QuicConnectionClose object
-// test case of having no string. also the 0 error code,
-TEST_F(QuicIetfFramerTest, ConnectionClose3) {
+
+// Testing for the IETF ACK framer.
+// clang-format off
+struct ack_frame ack_frame_variants[] = {
+ { 90000, {{1000, 2001}} },
+ { 0, {{1000, 2001}} },
+ { 1, {{1, 2}, {5, 6}} },
+ { 63, {{1, 2}, {5, 6}} },
+ { 64, {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}}},
+ { 10000, {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}}},
+ { 100000000, {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}}},
+};
+// clang-format on
+
+TEST_F(QuicIetfFramerTest, AckFrame) {
char packet_buffer[kNormalPacketBufferSize];
+ for (auto ack_frame_variant : ack_frame_variants) {
+ EXPECT_TRUE(
+ TryAckFrame(packet_buffer, sizeof(packet_buffer), &ack_frame_variant));
+ }
+}
- // initialize a writer so that the serialized packet is placed in
- // packet_buffer.
+TEST_F(QuicIetfFramerTest, PaddingEntirePacket) {
+ char packet_buffer[kNormalPacketBufferSize];
+
+ // ensure that buffer is not all 0 prior to the test.
+ memset(packet_buffer, 0xff, sizeof(packet_buffer));
+
+ // Set up the writer and transmit QuicPaddingFrame
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
NETWORK_BYTE_ORDER);
+ QuicPaddingFrame transmit_frame(sizeof(packet_buffer));
- // empty string,
- QuicString test_string = "Ich Bin Ein Jelly Donut?";
- QuicConnectionCloseFrame sent_frame;
- sent_frame.error_code = static_cast<QuicErrorCode>(0);
- sent_frame.error_details = test_string;
- // write the frame to the packet buffer.
- EXPECT_TRUE(QuicFramerPeer::AppendIetfConnectionCloseFrame(
- &framer_, sent_frame, &writer));
+ // Fill buffer with padding.
+ EXPECT_TRUE(QuicFramerPeer::AppendIetfPaddingFrame(&framer_, transmit_frame,
+ &writer));
- // better have something in the packet buffer.
- EXPECT_NE(0u, writer.length());
+ // better have written to the entire packet buffer.
+ EXPECT_EQ(kNormalPacketBufferSize, writer.length());
- // now set up a reader to read in the thing in.
+ // see if entire buffer is 0
+ for (auto i = 0; i != sizeof(packet_buffer); i++) {
+ EXPECT_EQ(0, packet_buffer[i])
+ << "Packet_buffer[" << i << "] is " << packet_buffer[i] << " not 0x00";
+ }
+
+ // set up reader and empty receive QuicPaddingFrame.
QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicPaddingFrame receive_frame;
// read in the frame type
uint8_t received_frame_type;
EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
- EXPECT_EQ(received_frame_type, QuicIetfFrameType::IETF_CONNECTION_CLOSE);
-
- // a QuicConnectionCloseFrame to hold the results.
- QuicConnectionCloseFrame sink_frame;
+ EXPECT_EQ(received_frame_type, 0u);
- EXPECT_TRUE(QuicFramerPeer::ProcessIetfConnectionCloseFrame(
- &framer_, &reader, received_frame_type, &sink_frame));
+ // deframe it
+ QuicFramerPeer::ProcessIetfPaddingFrame(&framer_, &reader, &receive_frame);
// Now check that received == sent
- EXPECT_EQ(sink_frame.error_code, static_cast<QuicErrorCode>(0));
- EXPECT_EQ(sink_frame.error_details, test_string);
+ EXPECT_EQ(transmit_frame.num_padding_bytes, receive_frame.num_padding_bytes);
+ int packet_buffer_size = static_cast<int>(sizeof(packet_buffer));
+ EXPECT_EQ(packet_buffer_size, receive_frame.num_padding_bytes);
+ EXPECT_EQ(packet_buffer_size, transmit_frame.num_padding_bytes);
}
-TEST_F(QuicIetfFramerTest, ApplicationClose1) {
+// Place a padding frame between two non-padding frames:
+// app_close
+// padding
+// connection_close
+// we do a loop, with different amounts of padding in each.
+TEST_F(QuicIetfFramerTest, PaddingSandwich) {
+ int pad_lengths[] = {1, 2, 5, 10, 20, 50, 100, 200, 500, 0};
+ int* pad_length = pad_lengths;
+ while (*pad_length) {
+ char packet_buffer[kNormalPacketBufferSize];
+
+ // ensure that buffer is not all 0 prior to the test.
+ memset(packet_buffer, 0xff, sizeof(packet_buffer));
+
+ // Set up the writer and transmit Quic...Frames
+ QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
+ NETWORK_BYTE_ORDER);
+ QuicPaddingFrame transmit_pad_frame(*pad_length);
+ QuicString app_close_test_string = "Ich Bin Ein Jelly Donut?";
+ QuicConnectionCloseFrame transmit_app_close_frame;
+ transmit_app_close_frame.error_code = static_cast<QuicErrorCode>(0);
+ transmit_app_close_frame.error_details = app_close_test_string;
+
+ QuicString conn_close_test_string = "I am a Berliner?";
+ QuicConnectionCloseFrame transmit_conn_close_frame;
+ transmit_conn_close_frame.error_code = static_cast<QuicErrorCode>(0);
+ transmit_conn_close_frame.error_details = conn_close_test_string;
+
+ // Put in the frames. App close first.
+ EXPECT_TRUE(QuicFramerPeer::AppendIetfApplicationCloseFrame(
+ &framer_, transmit_app_close_frame, &writer));
+
+ size_t pre_padding_len = writer.length();
+ // padding next.
+ EXPECT_TRUE(QuicFramerPeer::AppendIetfPaddingFrame(
+ &framer_, transmit_pad_frame, &writer));
+ size_t post_padding_len = writer.length();
+ EXPECT_EQ(static_cast<int>(post_padding_len - pre_padding_len),
+ *pad_length);
+
+ // finally, connection close
+ EXPECT_TRUE(QuicFramerPeer::AppendIetfConnectionCloseFrame(
+ &framer_, transmit_conn_close_frame, &writer));
+
+ // see if buffer from offset pre_padding_len, for *pad_len, is 0
+ for (auto i = pre_padding_len; i != pre_padding_len + (*pad_length); i++) {
+ EXPECT_EQ(0, packet_buffer[i]) << "Packet_buffer[" << i << "] is "
+ << packet_buffer[i] << " not 0x00";
+ }
+
+ // set up reader and empty receive QuicFrames.
+ QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicPaddingFrame receive_pad_frame;
+ QuicConnectionCloseFrame receive_app_close_frame;
+ QuicConnectionCloseFrame receive_conn_close_frame;
+
+ // read in the frame type and data for the app-close frame
+ uint8_t received_frame_type;
+ EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
+ EXPECT_EQ(received_frame_type, IETF_APPLICATION_CLOSE);
+ EXPECT_TRUE(QuicFramerPeer::ProcessIetfApplicationCloseFrame(
+ &framer_, &reader, received_frame_type, &receive_app_close_frame));
+
+ // Now the padding.
+ EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
+ EXPECT_EQ(received_frame_type, IETF_PADDING);
+ QuicFramerPeer::ProcessIetfPaddingFrame(&framer_, &reader,
+ &receive_pad_frame);
+ // check that pad size is correct
+ EXPECT_EQ(receive_pad_frame.num_padding_bytes, *pad_length);
+
+ // Now get the connection close frame.
+ EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
+ EXPECT_EQ(received_frame_type, IETF_CONNECTION_CLOSE);
+ EXPECT_TRUE(QuicFramerPeer::ProcessIetfConnectionCloseFrame(
+ &framer_, &reader, received_frame_type, &receive_conn_close_frame));
+
+ pad_length++;
+ }
+}
+
+TEST_F(QuicIetfFramerTest, PathChallengeFrame) {
+ // Double-braces needed on some platforms due to
+ // https://bugs.llvm.org/show_bug.cgi?id=21629
+ QuicPathFrameBuffer buffer0 = {{0, 0, 0, 0, 0, 0, 0, 0}};
+ QuicPathFrameBuffer buffer1 = {
+ {0x80, 0x91, 0xa2, 0xb3, 0xc4, 0xd5, 0xe5, 0xf7}};
char packet_buffer[kNormalPacketBufferSize];
+ EXPECT_TRUE(
+ TryPathChallengeFrame(packet_buffer, sizeof(packet_buffer), buffer0));
+ EXPECT_TRUE(
+ TryPathChallengeFrame(packet_buffer, sizeof(packet_buffer), buffer1));
+}
- // initialize a writer so that the serialized packet is placed in
+TEST_F(QuicIetfFramerTest, PathResponseFrame) {
+ // Double-braces needed on some platforms due to
+ // https://bugs.llvm.org/show_bug.cgi?id=21629
+ QuicPathFrameBuffer buffer0 = {{0, 0, 0, 0, 0, 0, 0, 0}};
+ QuicPathFrameBuffer buffer1 = {
+ {0x80, 0x91, 0xa2, 0xb3, 0xc4, 0xd5, 0xe5, 0xf7}};
+ char packet_buffer[kNormalPacketBufferSize];
+ EXPECT_TRUE(
+ TryPathResponseFrame(packet_buffer, sizeof(packet_buffer), buffer0));
+ EXPECT_TRUE(
+ TryPathResponseFrame(packet_buffer, sizeof(packet_buffer), buffer1));
+}
+
+TEST_F(QuicIetfFramerTest, ResetStreamFrame) {
+ char packet_buffer[kNormalPacketBufferSize];
+ struct resets {
+ QuicStreamId stream_id;
+ QuicRstStreamErrorCode error_code;
+ QuicStreamOffset final_offset;
+ } reset_frames[] = {
+ {0, QUIC_STREAM_NO_ERROR, 0}, {0x10, QUIC_HEADERS_TOO_LARGE, 0x300},
+ };
+ for (auto reset : reset_frames) {
+ TryResetFrame(packet_buffer, sizeof(packet_buffer), reset.stream_id,
+ reset.error_code, reset.final_offset);
+ }
+}
+
+TEST_F(QuicIetfFramerTest, StopSendingFrame) {
+ char packet_buffer[kNormalPacketBufferSize];
+
+ // Make a writer so that the serialized packet is placed in
// packet_buffer.
QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
NETWORK_BYTE_ORDER);
- QuicString test_string = "This is a test of the emergency broadcast system";
- // write the frame to the packet buffer.
- EXPECT_TRUE(QuicFramerPeer::AppendIetfApplicationCloseFrame(
- &framer_,
- static_cast<uint16_t>(QuicErrorCode::QUIC_CRYPTO_VERSION_NOT_SUPPORTED),
- test_string, &writer));
+ QuicStopSendingFrame transmit_frame;
+ transmit_frame.stream_id = 12345;
+ transmit_frame.application_error_code = 543;
- // better have something in the packet buffer.
- EXPECT_NE(0u, writer.length());
+ // Write the frame to the packet buffer.
+ EXPECT_TRUE(QuicFramerPeer::AppendIetfStopSendingFrame(
+ &framer_, transmit_frame, &writer));
+ // Check that the number of bytes in the buffer is in the
+ // allowed range.
+ EXPECT_LE(4u, writer.length());
+ EXPECT_GE(11u, writer.length());
- // now set up a reader to read in the thing in.
QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
- // read in the frame type
+ // Read in the frame type
uint8_t received_frame_type;
EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
- EXPECT_EQ(received_frame_type, QuicIetfFrameType::IETF_APPLICATION_CLOSE);
+ EXPECT_EQ(received_frame_type, IETF_STOP_SENDING);
- // a QuicConnectionCloseFrame to hold the results.
- QuicConnectionCloseFrame sink_frame;
+ // A frame to hold the results
+ QuicStopSendingFrame receive_frame;
- EXPECT_TRUE(QuicFramerPeer::ProcessIetfApplicationCloseFrame(
- &framer_, &reader, received_frame_type, &sink_frame));
+ EXPECT_TRUE(QuicFramerPeer::ProcessIetfStopSendingFrame(&framer_, &reader,
+ &receive_frame));
- // Now check that received == sent
- EXPECT_EQ(sink_frame.error_code,
- QuicErrorCode::QUIC_CRYPTO_VERSION_NOT_SUPPORTED);
- EXPECT_EQ(sink_frame.error_details, test_string);
+ // Verify that the transmitted and received values are the same.
+ EXPECT_EQ(receive_frame.stream_id, 12345u);
+ EXPECT_EQ(receive_frame.application_error_code, 543u);
+ EXPECT_EQ(receive_frame.stream_id, transmit_frame.stream_id);
+ EXPECT_EQ(receive_frame.application_error_code,
+ transmit_frame.application_error_code);
}
-// test case of having no string. also the 0 error code,
-TEST_F(QuicIetfFramerTest, ApplicationClose2) {
+TEST_F(QuicIetfFramerTest, MaxDataFrame) {
char packet_buffer[kNormalPacketBufferSize];
+ QuicStreamOffset window_sizes[] = {0, 1, 2, 5, 10,
+ 20, 50, 100, 200, 500,
+ 1000000, kOffset8, kOffset4, kOffset2};
+ for (QuicStreamOffset window_size : window_sizes) {
+ memset(packet_buffer, 0, sizeof(packet_buffer));
+
+ // Set up the writer and transmit QuicWindowUpdateFrame
+ QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
+ NETWORK_BYTE_ORDER);
+ QuicWindowUpdateFrame transmit_frame(0, 99, window_size);
- // initialize a writer so that the serialized packet is placed in
- // packet_buffer.
- QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- NETWORK_BYTE_ORDER);
+ // Add the frame.
+ EXPECT_TRUE(QuicFramerPeer::AppendIetfMaxDataFrame(&framer_, transmit_frame,
+ &writer));
- // empty string,
- QuicString test_string;
- // write the frame to the packet buffer.
- EXPECT_TRUE(QuicFramerPeer::AppendIetfApplicationCloseFrame(
- &framer_, 0, test_string, &writer));
+ // Check that the number of bytes in the buffer is in the expected range.
+ EXPECT_LE(2u, writer.length());
+ EXPECT_GE(9u, writer.length());
- // better have something in the packet buffer.
- EXPECT_NE(0u, writer.length());
+ // Set up reader and an empty QuicWindowUpdateFrame
+ QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicWindowUpdateFrame receive_frame;
- // now set up a reader to read in the thing in.
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ // Read in the frame type
+ uint8_t received_frame_type;
+ EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
+ EXPECT_EQ(received_frame_type, IETF_MAX_DATA);
- // read in the frame type
- uint8_t received_frame_type;
- EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
- EXPECT_EQ(received_frame_type, QuicIetfFrameType::IETF_APPLICATION_CLOSE);
+ // Deframe it
+ EXPECT_TRUE(QuicFramerPeer::ProcessIetfMaxDataFrame(&framer_, &reader,
+ &receive_frame));
- // a QuicConnectionCloseFrame to hold the results.
- QuicConnectionCloseFrame sink_frame;
+ // Now check that the received data equals the sent data.
+ EXPECT_EQ(transmit_frame.byte_offset, window_size);
+ EXPECT_EQ(transmit_frame.byte_offset, receive_frame.byte_offset);
+ EXPECT_EQ(0u, receive_frame.stream_id);
+ }
+}
- EXPECT_TRUE(QuicFramerPeer::ProcessIetfApplicationCloseFrame(
- &framer_, &reader, received_frame_type, &sink_frame));
+TEST_F(QuicIetfFramerTest, MaxStreamDataFrame) {
+ char packet_buffer[kNormalPacketBufferSize];
+ QuicStreamOffset window_sizes[] = {0, 1, 2, 5, 10,
+ 20, 50, 100, 200, 500,
+ 1000000, kOffset8, kOffset4, kOffset2};
+ QuicIetfStreamId stream_ids[] = {kStreamId4, kStreamId2, kStreamId1,
+ kStreamId0};
+
+ for (QuicIetfStreamId stream_id : stream_ids) {
+ for (QuicStreamOffset window_size : window_sizes) {
+ memset(packet_buffer, 0, sizeof(packet_buffer));
+
+ // Set up the writer and transmit QuicWindowUpdateFrame
+ QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
+ NETWORK_BYTE_ORDER);
+ QuicWindowUpdateFrame transmit_frame(0, stream_id, window_size);
+
+ // Add the frame.
+ EXPECT_TRUE(QuicFramerPeer::AppendIetfMaxStreamDataFrame(
+ &framer_, transmit_frame, &writer));
+
+ // Check that number of bytes in the buffer is in the expected range.
+ EXPECT_LE(3u, writer.length());
+ EXPECT_GE(17u, writer.length());
+
+ // Set up reader and empty receive QuicPaddingFrame.
+ QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicWindowUpdateFrame receive_frame;
+
+ // Read in the frame type
+ uint8_t received_frame_type;
+ EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
+ EXPECT_EQ(received_frame_type, IETF_MAX_STREAM_DATA);
+
+ // Deframe it
+ EXPECT_TRUE(QuicFramerPeer::ProcessIetfMaxStreamDataFrame(
+ &framer_, &reader, &receive_frame));
+
+ // Now check that received data and sent data are equal.
+ EXPECT_EQ(transmit_frame.byte_offset, window_size);
+ EXPECT_EQ(transmit_frame.byte_offset, receive_frame.byte_offset);
+ EXPECT_EQ(stream_id, receive_frame.stream_id);
+ EXPECT_EQ(transmit_frame.stream_id, receive_frame.stream_id);
+ }
+ }
+}
- // Now check that received == sent
- EXPECT_EQ(sink_frame.error_code, 0);
- EXPECT_EQ(sink_frame.error_details, test_string);
+TEST_F(QuicIetfFramerTest, MaxStreamIdFrame) {
+ char packet_buffer[kNormalPacketBufferSize];
+ QuicIetfStreamId stream_ids[] = {kStreamId4, kStreamId2, kStreamId1,
+ kStreamId0};
+
+ for (QuicIetfStreamId stream_id : stream_ids) {
+ memset(packet_buffer, 0, sizeof(packet_buffer));
+
+ // Set up the writer and transmit QuicIetfMaxStreamIdFrame
+ QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
+ NETWORK_BYTE_ORDER);
+ QuicIetfMaxStreamIdFrame transmit_frame(0, stream_id);
+
+ // Add the frame.
+ EXPECT_TRUE(QuicFramerPeer::AppendIetfMaxStreamIdFrame(
+ &framer_, transmit_frame, &writer));
+
+ // Check that buffer length is in the expected range
+ EXPECT_LE(2u, writer.length());
+ EXPECT_GE(9u, writer.length());
+
+ // Set up reader and empty receive QuicPaddingFrame.
+ QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicIetfMaxStreamIdFrame receive_frame;
+
+ // Read in the frame type
+ uint8_t received_frame_type;
+ EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
+ EXPECT_EQ(received_frame_type, IETF_MAX_STREAM_ID);
+
+ // Deframe it
+ EXPECT_TRUE(QuicFramerPeer::ProcessIetfMaxStreamIdFrame(&framer_, &reader,
+ &receive_frame));
+
+ // 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);
+ }
}
-// Set fields of the frame via a QuicConnectionClose object wahoo
-// test case of having no string. also the 0 error code,
-TEST_F(QuicIetfFramerTest, ApplicationClose3) {
+TEST_F(QuicIetfFramerTest, BlockedFrame) {
char packet_buffer[kNormalPacketBufferSize];
+ QuicStreamOffset offsets[] = {kOffset8, kOffset4, kOffset2, kOffset1,
+ kOffset0};
- // initialize a writer so that the serialized packet is placed in
- // packet_buffer.
- QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
- NETWORK_BYTE_ORDER);
+ for (QuicStreamOffset offset : offsets) {
+ memset(packet_buffer, 0, sizeof(packet_buffer));
- // empty string,
- QuicString test_string = "Ich Bin Ein Jelly Donut?";
- QuicConnectionCloseFrame sent_frame;
- sent_frame.error_code = static_cast<QuicErrorCode>(0);
- sent_frame.error_details = test_string;
- // write the frame to the packet buffer.
- EXPECT_TRUE(QuicFramerPeer::AppendIetfApplicationCloseFrame(
- &framer_, sent_frame, &writer));
+ // Set up the writer and transmit QuicIetfBlockedFrame
+ QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
+ NETWORK_BYTE_ORDER);
+ QuicIetfBlockedFrame transmit_frame(0, offset);
- // better have something in the packet buffer.
- EXPECT_NE(0u, writer.length());
+ // Add the frame.
+ EXPECT_TRUE(QuicFramerPeer::AppendIetfBlockedFrame(&framer_, transmit_frame,
+ &writer));
- // now set up a reader to read in the thing in.
- QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ // Check that buffer length is in the expected range
+ EXPECT_LE(2u, writer.length());
+ EXPECT_GE(9u, writer.length());
- // read in the frame type
- uint8_t received_frame_type;
- EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
- EXPECT_EQ(received_frame_type, QuicIetfFrameType::IETF_APPLICATION_CLOSE);
+ // Set up reader and empty receive QuicFrame.
+ QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicIetfBlockedFrame receive_frame;
- // a QuicConnectionCloseFrame to hold the results.
- QuicConnectionCloseFrame sink_frame;
+ // Read in the frame type
+ uint8_t received_frame_type;
+ EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
+ EXPECT_EQ(received_frame_type, IETF_BLOCKED);
- EXPECT_TRUE(QuicFramerPeer::ProcessIetfApplicationCloseFrame(
- &framer_, &reader, received_frame_type, &sink_frame));
+ // Deframe it
+ EXPECT_TRUE(QuicFramerPeer::ProcessIetfBlockedFrame(&framer_, &reader,
+ &receive_frame));
- // Now check that received == sent
- EXPECT_EQ(sink_frame.error_code, static_cast<QuicErrorCode>(0));
- EXPECT_EQ(sink_frame.error_details, test_string);
+ // Check that received and sent data are equivalent
+ EXPECT_EQ(offset, receive_frame.offset);
+ EXPECT_EQ(transmit_frame.offset, receive_frame.offset);
+ }
}
-// Testing for the IETF ACK framer.
-// clang-format off
-struct ack_frame ack_frame_variants[] = {
- { 90000, {{1000, 2001}} },
- { 0, {{1000, 2001}} },
- { 1, {{1, 2}, {5, 6}} },
- { 63, {{1, 2}, {5, 6}} },
- { 64, {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}}},
- { 10000, {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}}},
- { 100000000, {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}}},
-};
-// clang-format on
+TEST_F(QuicIetfFramerTest, StreamBlockedFrame) {
+ char packet_buffer[kNormalPacketBufferSize];
+ QuicStreamOffset offsets[] = {0, 1, 2, 5, 10,
+ 20, 50, 100, 200, 500,
+ 1000000, kOffset8, kOffset4, kOffset2};
+ QuicIetfStreamId stream_ids[] = {kStreamId4, kStreamId2, kStreamId1,
+ kStreamId0};
+
+ for (QuicIetfStreamId stream_id : stream_ids) {
+ for (QuicStreamOffset offset : offsets) {
+ memset(packet_buffer, 0, sizeof(packet_buffer));
+
+ // Set up the writer and transmit QuicWindowUpdateFrame
+ QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
+ NETWORK_BYTE_ORDER);
+ QuicWindowUpdateFrame transmit_frame(0, stream_id, offset);
+
+ // Add the frame.
+ EXPECT_TRUE(QuicFramerPeer::AppendIetfStreamBlockedFrame(
+ &framer_, transmit_frame, &writer));
+
+ // Check that number of bytes in the buffer is in the expected range.
+ EXPECT_LE(3u, writer.length());
+ EXPECT_GE(17u, writer.length());
+
+ // Set up reader and empty receive QuicPaddingFrame.
+ QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicWindowUpdateFrame receive_frame;
+
+ // Read in the frame type
+ uint8_t received_frame_type;
+ EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
+ EXPECT_EQ(received_frame_type, IETF_STREAM_BLOCKED);
+
+ // Deframe it
+ EXPECT_TRUE(QuicFramerPeer::ProcessIetfStreamBlockedFrame(
+ &framer_, &reader, &receive_frame));
+
+ // Now check that received == sent
+ EXPECT_EQ(transmit_frame.byte_offset, offset);
+ EXPECT_EQ(transmit_frame.byte_offset, receive_frame.byte_offset);
+ EXPECT_EQ(stream_id, receive_frame.stream_id);
+ EXPECT_EQ(transmit_frame.stream_id, receive_frame.stream_id);
+ }
+ }
+}
-TEST_F(QuicIetfFramerTest, AckFrame) {
+TEST_F(QuicIetfFramerTest, StreamIdBlockedFrame) {
char packet_buffer[kNormalPacketBufferSize];
- for (auto ack_frame_variant : ack_frame_variants) {
- QUIC_LOG(INFO) << "Doing an ack, delay = " << ack_frame_variant.delay_time;
- EXPECT_TRUE(
- TryAckFrame(packet_buffer, sizeof(packet_buffer), &ack_frame_variant));
+ QuicIetfStreamId stream_ids[] = {kStreamId4, kStreamId2, kStreamId1,
+ kStreamId0};
+
+ for (QuicIetfStreamId stream_id : stream_ids) {
+ memset(packet_buffer, 0, sizeof(packet_buffer));
+
+ // Set up the writer and transmit QuicIetfStreamIdBlockedFrame
+ QuicDataWriter writer(sizeof(packet_buffer), packet_buffer,
+ NETWORK_BYTE_ORDER);
+ QuicIetfStreamIdBlockedFrame transmit_frame(0, stream_id);
+
+ // Add the frame.
+ EXPECT_TRUE(QuicFramerPeer::AppendIetfStreamIdBlockedFrame(
+ &framer_, transmit_frame, &writer));
+
+ // Check that buffer length is in the expected range
+ EXPECT_LE(2u, writer.length());
+ EXPECT_GE(9u, writer.length());
+
+ // Set up reader and empty receive QuicPaddingFrame.
+ QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicIetfStreamIdBlockedFrame receive_frame;
+
+ // Read in the frame type
+ uint8_t received_frame_type;
+ EXPECT_TRUE(reader.ReadUInt8(&received_frame_type));
+ EXPECT_EQ(received_frame_type, IETF_STREAM_ID_BLOCKED);
+
+ // Deframe it
+ EXPECT_TRUE(QuicFramerPeer::ProcessIetfStreamIdBlockedFrame(
+ &framer_, &reader, &receive_frame));
+
+ // Now check that received == sent
+ EXPECT_EQ(stream_id, receive_frame.stream_id);
+ EXPECT_EQ(transmit_frame.stream_id, receive_frame.stream_id);
}
}
diff --git a/chromium/net/quic/core/quic_packet_creator.cc b/chromium/net/quic/core/quic_packet_creator.cc
index 27ed0b93401..0d05a8c2dee 100644
--- a/chromium/net/quic/core/quic_packet_creator.cc
+++ b/chromium/net/quic/core/quic_packet_creator.cc
@@ -54,8 +54,8 @@ QuicPacketCreator::~QuicPacketCreator() {
}
void QuicPacketCreator::SetEncrypter(EncryptionLevel level,
- QuicEncrypter* encrypter) {
- framer_->SetEncrypter(level, encrypter);
+ std::unique_ptr<QuicEncrypter> encrypter) {
+ framer_->SetEncrypter(level, std::move(encrypter));
max_plaintext_size_ = framer_->GetMaxPlaintextSize(max_packet_length_);
}
@@ -182,7 +182,7 @@ void QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
QuicFrame* frame) {
DCHECK_GT(max_packet_length_,
StreamFramePacketOverhead(framer_->transport_version(),
- connection_id_length_, kIncludeVersion,
+ GetConnectionIdLength(), kIncludeVersion,
IncludeNonceInPublicHeader(),
PACKET_6BYTE_PACKET_NUMBER, offset));
@@ -398,10 +398,10 @@ size_t QuicPacketCreator::PacketSize() {
if (!queued_frames_.empty()) {
return packet_size_;
}
- packet_size_ =
- GetPacketHeaderSize(framer_->transport_version(), connection_id_length_,
- send_version_in_packet_, IncludeNonceInPublicHeader(),
- packet_.packet_number_length);
+ packet_size_ = GetPacketHeaderSize(
+ framer_->transport_version(), GetConnectionIdLength(),
+ IncludeVersionInHeader(), IncludeNonceInPublicHeader(),
+ GetPacketNumberLength());
return packet_size_;
}
@@ -467,10 +467,11 @@ void QuicPacketCreator::SerializePacket(char* encrypted_buffer,
std::unique_ptr<QuicEncryptedPacket>
QuicPacketCreator::SerializeVersionNegotiationPacket(
+ bool ietf_quic,
const ParsedQuicVersionVector& supported_versions) {
DCHECK_EQ(Perspective::IS_SERVER, framer_->perspective());
std::unique_ptr<QuicEncryptedPacket> encrypted =
- QuicFramer::BuildVersionNegotiationPacket(connection_id_,
+ QuicFramer::BuildVersionNegotiationPacket(connection_id_, ietf_quic,
supported_versions);
DCHECK(encrypted);
DCHECK_GE(max_packet_length_, encrypted->length());
@@ -504,17 +505,25 @@ QuicPacketCreator::SerializeConnectivityProbingPacket() {
return serialize_packet;
}
-// TODO(jri): Make this a public method of framer?
+// TODO(b/74062209): Make this a public method of framer?
SerializedPacket QuicPacketCreator::NoPacket() {
return SerializedPacket(0, PACKET_1BYTE_PACKET_NUMBER, nullptr, 0, false,
false);
}
+QuicConnectionIdLength QuicPacketCreator::GetConnectionIdLength() const {
+ return connection_id_length_;
+}
+
+QuicPacketNumberLength QuicPacketCreator::GetPacketNumberLength() const {
+ return packet_.packet_number_length;
+}
+
void QuicPacketCreator::FillPacketHeader(QuicPacketHeader* header) {
header->connection_id = connection_id_;
- header->connection_id_length = connection_id_length_;
+ header->connection_id_length = GetConnectionIdLength();
header->reset_flag = false;
- header->version_flag = send_version_in_packet_;
+ header->version_flag = IncludeVersionInHeader();
if (IncludeNonceInPublicHeader()) {
DCHECK_EQ(Perspective::IS_SERVER, framer_->perspective());
header->nonce = &diversification_nonce_;
@@ -553,7 +562,7 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
}
size_t frame_len = framer_->GetSerializedFrameLength(
frame, BytesFree(), queued_frames_.empty(), true,
- packet_.packet_number_length);
+ GetPacketNumberLength());
if (frame_len == 0) {
// Current open packet is full.
Flush();
@@ -618,11 +627,15 @@ void QuicPacketCreator::MaybeAddPadding() {
DCHECK(success);
}
-bool QuicPacketCreator::IncludeNonceInPublicHeader() {
+bool QuicPacketCreator::IncludeNonceInPublicHeader() const {
return have_diversification_nonce_ &&
packet_.encryption_level == ENCRYPTION_INITIAL;
}
+bool QuicPacketCreator::IncludeVersionInHeader() const {
+ return send_version_in_packet_;
+}
+
void QuicPacketCreator::AddPendingPadding(QuicByteCount size) {
pending_padding_bytes_ += size;
}
@@ -644,8 +657,9 @@ void QuicPacketCreator::SetConnectionIdLength(QuicConnectionIdLength length) {
void QuicPacketCreator::SetTransmissionType(TransmissionType type) {
DCHECK(can_set_transmission_type_);
- QUIC_DVLOG(1) << "Setting Transmission type to "
- << QuicUtils::TransmissionTypeToString(type);
+ QUIC_DVLOG_IF(1, type != packet_.transmission_type)
+ << "Setting Transmission type to "
+ << QuicUtils::TransmissionTypeToString(type);
packet_.transmission_type = type;
}
diff --git a/chromium/net/quic/core/quic_packet_creator.h b/chromium/net/quic/core/quic_packet_creator.h
index b03e5803868..03af92ff215 100644
--- a/chromium/net/quic/core/quic_packet_creator.h
+++ b/chromium/net/quic/core/quic_packet_creator.h
@@ -153,6 +153,7 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// Creates a version negotiation packet which supports |supported_versions|.
std::unique_ptr<QuicEncryptedPacket> SerializeVersionNegotiationPacket(
+ bool ietf_quic,
const ParsedQuicVersionVector& supported_versions);
// Creates a connectivity probing packet.
@@ -161,6 +162,9 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// Returns a dummy packet that is valid but contains no useful information.
static SerializedPacket NoPacket();
+ // Returns length of connection ID to send over the wire.
+ QuicConnectionIdLength GetConnectionIdLength() const;
+
// Sets the encryption level that will be applied to new packets.
void set_encryption_level(EncryptionLevel level) {
packet_.encryption_level = level;
@@ -170,10 +174,6 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// created.
QuicPacketNumber packet_number() const { return packet_.packet_number; }
- QuicConnectionIdLength connection_id_length() const {
- return connection_id_length_;
- }
-
void SetConnectionIdLength(QuicConnectionIdLength length);
QuicByteCount max_packet_length() const { return max_packet_length_; }
@@ -184,7 +184,8 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// Sets the encrypter to use for the encryption level and updates the max
// plaintext size.
- void SetEncrypter(EncryptionLevel level, QuicEncrypter* encrypter);
+ void SetEncrypter(EncryptionLevel level,
+ std::unique_ptr<QuicEncrypter> encrypter);
// Indicates whether the packet creator is in a state where it can change
// current maximum packet length.
@@ -251,7 +252,15 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// Returns true if a diversification nonce should be included in the current
// packet's header.
- bool IncludeNonceInPublicHeader();
+ bool IncludeNonceInPublicHeader() const;
+
+ // Returns true if version should be included in current packet's header.
+ bool IncludeVersionInHeader() const;
+
+ // Returns length of packet number to send over the wire.
+ // packet_.packet_number_length should never be read directly, use this
+ // function instead.
+ QuicPacketNumberLength GetPacketNumberLength() const;
// Returns true if |frame| starts with CHLO.
bool StreamFrameStartsWithChlo(const QuicStreamFrame& frame) const;
@@ -262,6 +271,8 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
QuicFramer* framer_;
// Controls whether version should be included while serializing the packet.
+ // send_version_in_packet_ should never be read directly, use
+ // IncludeVersionInHeader() instead.
bool send_version_in_packet_;
// If true, then |diversification_nonce_| will be included in the header of
// all packets created at the initial encryption level.
@@ -270,7 +281,8 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// Maximum length including headers and encryption (UDP payload length.)
QuicByteCount max_packet_length_;
size_t max_plaintext_size_;
- // Length of connection_id to send over the wire.
+ // Length of connection_id to send over the wire. connection_id_length_ should
+ // never be read directly, use GetConnectionIdLength() instead.
QuicConnectionIdLength connection_id_length_;
// Frames to be added to the next SerializedPacket
diff --git a/chromium/net/quic/core/quic_packet_creator_test.cc b/chromium/net/quic/core/quic_packet_creator_test.cc
index 7dbb617d3ee..342b5b2ec2a 100644
--- a/chromium/net/quic/core/quic_packet_creator_test.cc
+++ b/chromium/net/quic/core/quic_packet_creator_test.cc
@@ -135,10 +135,11 @@ class QuicPacketCreatorTest : public QuicTestWithParam<TestParams> {
data_("foo"),
creator_(connection_id_, &client_framer_, &delegate_, &producer_),
serialized_packet_(creator_.NoPacket()) {
- creator_.SetEncrypter(ENCRYPTION_INITIAL,
- new NullEncrypter(Perspective::IS_CLIENT));
- creator_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
- new NullEncrypter(Perspective::IS_CLIENT));
+ creator_.SetEncrypter(ENCRYPTION_INITIAL, QuicMakeUnique<NullEncrypter>(
+ Perspective::IS_CLIENT));
+ creator_.SetEncrypter(
+ ENCRYPTION_FORWARD_SECURE,
+ QuicMakeUnique<NullEncrypter>(Perspective::IS_CLIENT));
client_framer_.set_visitor(&framer_visitor_);
server_framer_.set_visitor(&framer_visitor_);
client_framer_.set_data_producer(&producer_);
@@ -186,7 +187,8 @@ class QuicPacketCreatorTest : public QuicTestWithParam<TestParams> {
// the version.
size_t GetPacketHeaderOverhead(QuicTransportVersion version) {
return GetPacketHeaderSize(
- version, creator_.connection_id_length(), kIncludeVersion,
+ version, creator_.GetConnectionIdLength(),
+ QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
!kIncludeDiversificationNonce,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_));
}
@@ -668,7 +670,7 @@ TEST_P(QuicPacketCreatorTest, SerializeVersionNegotiationPacket) {
ParsedQuicVersionVector versions;
versions.push_back(test::QuicVersionMax());
std::unique_ptr<QuicEncryptedPacket> encrypted(
- creator_.SerializeVersionNegotiationPacket(versions));
+ creator_.SerializeVersionNegotiationPacket(false, versions));
{
InSequence s;
@@ -798,8 +800,9 @@ TEST_P(QuicPacketCreatorTest, ConsumeDataLargerThanOneStreamFrame) {
creator_.SetMaxPacketLength(GetPacketLengthForOneStream(
client_framer_.transport_version(),
QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
- !kIncludeDiversificationNonce, creator_.connection_id_length(),
- PACKET_1BYTE_PACKET_NUMBER, &payload_length));
+ !kIncludeDiversificationNonce, creator_.GetConnectionIdLength(),
+ QuicPacketCreatorPeer::GetPacketNumberLength(&creator_),
+ &payload_length));
QuicFrame frame;
const QuicString too_long_payload(payload_length * 2, 'a');
MakeIOVector(too_long_payload, &iov_);
@@ -827,9 +830,10 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndFlush) {
EXPECT_EQ(max_plaintext_size -
GetPacketHeaderSize(
client_framer_.transport_version(),
- creator_.connection_id_length(),
+ creator_.GetConnectionIdLength(),
QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
- !kIncludeDiversificationNonce, PACKET_1BYTE_PACKET_NUMBER),
+ !kIncludeDiversificationNonce,
+ QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)),
creator_.BytesFree());
// Add a variety of frame types and then a padding frame.
@@ -874,9 +878,10 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndFlush) {
EXPECT_EQ(max_plaintext_size -
GetPacketHeaderSize(
client_framer_.transport_version(),
- creator_.connection_id_length(),
+ creator_.GetConnectionIdLength(),
QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
- !kIncludeDiversificationNonce, PACKET_1BYTE_PACKET_NUMBER),
+ !kIncludeDiversificationNonce,
+ QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)),
creator_.BytesFree());
}
@@ -982,9 +987,9 @@ TEST_P(QuicPacketCreatorTest, SendPendingPaddingInRetransmission) {
QuicFrames frames;
frames.push_back(QuicFrame(stream_frame));
char buffer[kMaxPacketSize];
- QuicPendingRetransmission retransmission(
- CreateRetransmission(frames, true, /*num_padding_bytes=*/0,
- ENCRYPTION_NONE, PACKET_1BYTE_PACKET_NUMBER));
+ QuicPendingRetransmission retransmission(CreateRetransmission(
+ frames, true, /*num_padding_bytes=*/0, ENCRYPTION_NONE,
+ QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)));
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
creator_.AddPendingPadding(kMaxNumRandomPaddingBytes);
diff --git a/chromium/net/quic/core/quic_packet_generator.cc b/chromium/net/quic/core/quic_packet_generator.cc
index 85814b40409..5c2471c2f4d 100644
--- a/chromium/net/quic/core/quic_packet_generator.cc
+++ b/chromium/net/quic/core/quic_packet_generator.cc
@@ -309,8 +309,10 @@ void QuicPacketGenerator::SetMaxPacketLength(QuicByteCount length) {
std::unique_ptr<QuicEncryptedPacket>
QuicPacketGenerator::SerializeVersionNegotiationPacket(
+ bool ietf_quic,
const ParsedQuicVersionVector& supported_versions) {
- return packet_creator_.SerializeVersionNegotiationPacket(supported_versions);
+ return packet_creator_.SerializeVersionNegotiationPacket(ietf_quic,
+ supported_versions);
}
OwningSerializedPacketPointer
@@ -344,9 +346,10 @@ void QuicPacketGenerator::set_encryption_level(EncryptionLevel level) {
packet_creator_.set_encryption_level(level);
}
-void QuicPacketGenerator::SetEncrypter(EncryptionLevel level,
- QuicEncrypter* encrypter) {
- packet_creator_.SetEncrypter(level, encrypter);
+void QuicPacketGenerator::SetEncrypter(
+ EncryptionLevel level,
+ std::unique_ptr<QuicEncrypter> encrypter) {
+ packet_creator_.SetEncrypter(level, std::move(encrypter));
}
void QuicPacketGenerator::AddRandomPadding() {
diff --git a/chromium/net/quic/core/quic_packet_generator.h b/chromium/net/quic/core/quic_packet_generator.h
index f1cfd7978e9..08176a969ff 100644
--- a/chromium/net/quic/core/quic_packet_generator.h
+++ b/chromium/net/quic/core/quic_packet_generator.h
@@ -137,6 +137,7 @@ class QUIC_EXPORT_PRIVATE QuicPacketGenerator {
// Creates a version negotiation packet which supports |supported_versions|.
std::unique_ptr<QuicEncryptedPacket> SerializeVersionNegotiationPacket(
+ bool ietf_quic,
const ParsedQuicVersionVector& supported_versions);
// Creates a connectivity probing packet.
@@ -157,7 +158,8 @@ class QUIC_EXPORT_PRIVATE QuicPacketGenerator {
void SetConnectionIdLength(uint32_t length);
// Sets the encrypter to use for the encryption level.
- void SetEncrypter(EncryptionLevel level, QuicEncrypter* encrypter);
+ void SetEncrypter(EncryptionLevel level,
+ std::unique_ptr<QuicEncrypter> encrypter);
// Returns true if there are control frames or current constructed packet has
// pending retransmittable frames.
diff --git a/chromium/net/quic/core/quic_packet_generator_test.cc b/chromium/net/quic/core/quic_packet_generator_test.cc
index 074eb4ebbdc..b2e4905f6cd 100644
--- a/chromium/net/quic/core/quic_packet_generator_test.cc
+++ b/chromium/net/quic/core/quic_packet_generator_test.cc
@@ -26,6 +26,7 @@
#include "net/quic/test_tools/simple_data_producer.h"
#include "net/quic/test_tools/simple_quic_framer.h"
+using std::string;
using testing::_;
using testing::InSequence;
using testing::Return;
@@ -150,8 +151,9 @@ class QuicPacketGeneratorTest : public QuicTest {
Perspective::IS_CLIENT),
generator_(42, &framer_, &random_generator_, &delegate_, &producer_),
creator_(QuicPacketGeneratorPeer::GetPacketCreator(&generator_)) {
- creator_->SetEncrypter(ENCRYPTION_FORWARD_SECURE,
- new NullEncrypter(Perspective::IS_CLIENT));
+ creator_->SetEncrypter(
+ ENCRYPTION_FORWARD_SECURE,
+ QuicMakeUnique<NullEncrypter>(Perspective::IS_CLIENT));
creator_->set_encryption_level(ENCRYPTION_FORWARD_SECURE);
framer_.set_data_producer(&producer_);
generator_.AttachPacketFlusher();
@@ -511,8 +513,9 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) {
size_t length =
NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
GetPacketHeaderSize(
- framer_.transport_version(), creator_->connection_id_length(),
- kIncludeVersion, !kIncludeDiversificationNonce,
+ framer_.transport_version(), creator_->GetConnectionIdLength(),
+ QuicPacketCreatorPeer::SendVersionInPacket(creator_),
+ !kIncludeDiversificationNonce,
QuicPacketCreatorPeer::GetPacketNumberLength(creator_)) +
// Add an extra 3 bytes for the payload and 1 byte so BytesFree is larger
// than the GetMinStreamFrameSize.
@@ -774,11 +777,11 @@ TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) {
TEST_F(QuicPacketGeneratorTest, TestConnectionIdLength) {
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
generator_.SetConnectionIdLength(0);
- EXPECT_EQ(PACKET_0BYTE_CONNECTION_ID, creator_->connection_id_length());
+ EXPECT_EQ(PACKET_0BYTE_CONNECTION_ID, creator_->GetConnectionIdLength());
for (size_t i = 1; i < 10; i++) {
generator_.SetConnectionIdLength(i);
- EXPECT_EQ(PACKET_8BYTE_CONNECTION_ID, creator_->connection_id_length());
+ EXPECT_EQ(PACKET_8BYTE_CONNECTION_ID, creator_->GetConnectionIdLength());
}
}
@@ -1066,7 +1069,7 @@ TEST_F(QuicPacketGeneratorTest, ConnectionCloseFrameLargerThanPacketSize) {
frame->error_code = QUIC_PACKET_WRITE_ERROR;
char buf[2000] = {};
QuicStringPiece error_details(buf, 2000);
- frame->error_details = error_details.as_string();
+ frame->error_details = string(error_details);
generator_.AddControlFrame(QuicFrame(frame));
EXPECT_TRUE(generator_.HasQueuedFrames());
EXPECT_TRUE(generator_.HasRetransmittableFrames());
@@ -1081,8 +1084,9 @@ TEST_F(QuicPacketGeneratorTest, RandomPaddingAfterFinSingleStreamSinglePacket) {
size_t length =
NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
GetPacketHeaderSize(
- framer_.transport_version(), creator_->connection_id_length(),
- kIncludeVersion, !kIncludeDiversificationNonce,
+ framer_.transport_version(), creator_->GetConnectionIdLength(),
+ QuicPacketCreatorPeer::SendVersionInPacket(creator_),
+ !kIncludeDiversificationNonce,
QuicPacketCreatorPeer::GetPacketNumberLength(creator_)) +
QuicFramer::GetMinStreamFrameSize(framer_.transport_version(),
kDataStreamId, 0,
@@ -1118,8 +1122,9 @@ TEST_F(QuicPacketGeneratorTest,
size_t length =
NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
GetPacketHeaderSize(
- framer_.transport_version(), creator_->connection_id_length(),
- kIncludeVersion, !kIncludeDiversificationNonce,
+ framer_.transport_version(), creator_->GetConnectionIdLength(),
+ QuicPacketCreatorPeer::SendVersionInPacket(creator_),
+ !kIncludeDiversificationNonce,
QuicPacketCreatorPeer::GetPacketNumberLength(creator_)) +
QuicFramer::GetMinStreamFrameSize(framer_.transport_version(),
kDataStreamId, 0,
@@ -1163,8 +1168,9 @@ TEST_F(QuicPacketGeneratorTest,
size_t length =
NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
GetPacketHeaderSize(
- framer_.transport_version(), creator_->connection_id_length(),
- kIncludeVersion, !kIncludeDiversificationNonce,
+ framer_.transport_version(), creator_->GetConnectionIdLength(),
+ QuicPacketCreatorPeer::SendVersionInPacket(creator_),
+ !kIncludeDiversificationNonce,
QuicPacketCreatorPeer::GetPacketNumberLength(creator_)) +
QuicFramer::GetMinStreamFrameSize(framer_.transport_version(),
kDataStreamId1, 0,
diff --git a/chromium/net/quic/core/quic_packets.cc b/chromium/net/quic/core/quic_packets.cc
index 35013e0fadc..c157fd0ece0 100644
--- a/chromium/net/quic/core/quic_packets.cc
+++ b/chromium/net/quic/core/quic_packets.cc
@@ -53,7 +53,7 @@ QuicPacketHeader::QuicPacketHeader()
connection_id_length(PACKET_8BYTE_CONNECTION_ID),
reset_flag(false),
version_flag(false),
- packet_number_length(PACKET_6BYTE_PACKET_NUMBER),
+ packet_number_length(PACKET_4BYTE_PACKET_NUMBER),
version(
ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED)),
nonce(nullptr),
@@ -81,6 +81,19 @@ QuicVersionNegotiationPacket::QuicVersionNegotiationPacket(
QuicVersionNegotiationPacket::~QuicVersionNegotiationPacket() {}
+QuicIetfStatelessResetPacket::QuicIetfStatelessResetPacket()
+ : stateless_reset_token(0) {}
+
+QuicIetfStatelessResetPacket::QuicIetfStatelessResetPacket(
+ const QuicPacketHeader& header,
+ uint128 token)
+ : header(header), stateless_reset_token(token) {}
+
+QuicIetfStatelessResetPacket::QuicIetfStatelessResetPacket(
+ const QuicIetfStatelessResetPacket& other) = default;
+
+QuicIetfStatelessResetPacket::~QuicIetfStatelessResetPacket() {}
+
std::ostream& operator<<(std::ostream& os, const QuicPacketHeader& header) {
os << "{ connection_id: " << header.connection_id
<< ", connection_id_length: " << header.connection_id_length
diff --git a/chromium/net/quic/core/quic_packets.h b/chromium/net/quic/core/quic_packets.h
index b3866c36557..085bb422df8 100644
--- a/chromium/net/quic/core/quic_packets.h
+++ b/chromium/net/quic/core/quic_packets.h
@@ -26,6 +26,7 @@
#include "net/quic/platform/api/quic_export.h"
#include "net/quic/platform/api/quic_socket_address.h"
#include "net/quic/platform/api/quic_string_piece.h"
+#include "net/quic/platform/api/quic_uint128.h"
namespace net {
@@ -97,6 +98,17 @@ struct QUIC_EXPORT_PRIVATE QuicVersionNegotiationPacket {
ParsedQuicVersionVector versions;
};
+struct QUIC_EXPORT_PRIVATE QuicIetfStatelessResetPacket {
+ QuicIetfStatelessResetPacket();
+ QuicIetfStatelessResetPacket(const QuicPacketHeader& header,
+ QuicUint128 token);
+ QuicIetfStatelessResetPacket(const QuicIetfStatelessResetPacket& other);
+ ~QuicIetfStatelessResetPacket();
+
+ QuicPacketHeader header;
+ QuicUint128 stateless_reset_token;
+};
+
class QUIC_EXPORT_PRIVATE QuicData {
public:
QuicData(const char* buffer, size_t length);
diff --git a/chromium/net/quic/core/quic_sent_packet_manager.cc b/chromium/net/quic/core/quic_sent_packet_manager.cc
index 5b61f6dd065..af956ea8c2f 100644
--- a/chromium/net/quic/core/quic_sent_packet_manager.cc
+++ b/chromium/net/quic/core/quic_sent_packet_manager.cc
@@ -31,8 +31,8 @@ static const int64_t kMaxRetransmissionTimeMs = 60000;
static const size_t kMaxRetransmissions = 10;
// Maximum number of packets retransmitted upon an RTO.
static const size_t kMaxRetransmissionsOnTimeout = 2;
-// Minimum number of consecutive RTOs before path is considered to be degrading.
-const size_t kMinTimeoutsBeforePathDegrading = 2;
+// The path degrading delay is the sum of this number of consecutive RTO delays.
+const size_t kNumRetransmissionDelaysForPathDegradingDelay = 2;
// Ensure the handshake timer isnt't faster than 10ms.
// This limits the tenth retransmitted packet to 10s after the initial CHLO.
@@ -90,7 +90,14 @@ QuicSentPacketManager::QuicSentPacketManager(
handshake_confirmed_(false),
largest_packet_peer_knows_is_acked_(0),
delayed_ack_time_(
- QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs)) {
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs)),
+ rtt_updated_(false),
+ acked_packets_iter_(last_ack_frame_.packets.rbegin()),
+ use_path_degrading_alarm_(
+ GetQuicReloadableFlag(quic_path_degrading_alarm)),
+ use_better_crypto_retransmission_(
+ GetQuicReloadableFlag(quic_better_crypto_retransmission)) {
+ QUIC_FLAG_COUNT(quic_reloadable_flag_quic_better_crypto_retransmission);
SetSendAlgorithm(congestion_control_type);
}
@@ -127,13 +134,11 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
min_rto_timeout_ = QuicTime::Delta::Zero();
}
if (GetQuicReloadableFlag(quic_max_ack_delay2) &&
- GetQuicReloadableFlag(quic_min_rtt_ack_delay) &&
config.HasClientSentConnectionOption(kMAD4, perspective_)) {
QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_max_ack_delay2, 3, 4);
ietf_style_tlp_ = true;
}
if (GetQuicReloadableFlag(quic_max_ack_delay2) &&
- GetQuicReloadableFlag(quic_min_rtt_ack_delay) &&
config.HasClientSentConnectionOption(kMAD5, perspective_)) {
QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_max_ack_delay2, 4, 4);
ietf_style_2x_tlp_ = true;
@@ -154,6 +159,25 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
config.HasClientRequestedIndependentOption(kTPCC, perspective_)) {
SetSendAlgorithm(kPCC);
}
+ // Initial window.
+ if (GetQuicReloadableFlag(quic_unified_iw_options)) {
+ if (config.HasClientRequestedIndependentOption(kIW03, perspective_)) {
+ initial_congestion_window_ = 3;
+ send_algorithm_->SetInitialCongestionWindowInPackets(3);
+ }
+ if (config.HasClientRequestedIndependentOption(kIW10, perspective_)) {
+ initial_congestion_window_ = 10;
+ send_algorithm_->SetInitialCongestionWindowInPackets(10);
+ }
+ if (config.HasClientRequestedIndependentOption(kIW20, perspective_)) {
+ initial_congestion_window_ = 20;
+ send_algorithm_->SetInitialCongestionWindowInPackets(20);
+ }
+ if (config.HasClientRequestedIndependentOption(kIW50, perspective_)) {
+ initial_congestion_window_ = 50;
+ send_algorithm_->SetInitialCongestionWindowInPackets(50);
+ }
+ }
using_pacing_ = !FLAGS_quic_disable_pacing_for_perf_tests;
@@ -237,21 +261,34 @@ void QuicSentPacketManager::SetHandshakeConfirmed() {
handshake_confirmed_ = true;
}
-void QuicSentPacketManager::OnIncomingAck(const QuicAckFrame& ack_frame,
+bool QuicSentPacketManager::OnIncomingAck(const QuicAckFrame& ack_frame,
QuicTime ack_receive_time) {
DCHECK_LE(LargestAcked(ack_frame), unacked_packets_.largest_sent_packet());
QuicByteCount prior_in_flight = unacked_packets_.bytes_in_flight();
- bool rtt_updated = MaybeUpdateRTT(ack_frame, ack_receive_time);
+ bool rtt_updated = MaybeUpdateRTT(LargestAcked(ack_frame),
+ ack_frame.ack_delay_time, ack_receive_time);
DCHECK_GE(LargestAcked(ack_frame), unacked_packets_.largest_observed());
unacked_packets_.IncreaseLargestObserved(LargestAcked(ack_frame));
HandleAckForSentPackets(ack_frame);
+ const bool acked_new_packet = !packets_acked_.empty();
+ PostProcessAfterMarkingPacketHandled(ack_frame, ack_receive_time, rtt_updated,
+ prior_in_flight);
+ return acked_new_packet;
+}
+
+void QuicSentPacketManager::PostProcessAfterMarkingPacketHandled(
+ const QuicAckFrame& ack_frame,
+ QuicTime ack_receive_time,
+ bool rtt_updated,
+ QuicByteCount prior_bytes_in_flight) {
InvokeLossDetection(ack_receive_time);
// Ignore losses in RTO mode.
if (consecutive_rto_count_ > 0 && !use_new_rto_) {
packets_lost_.clear();
}
- MaybeInvokeCongestionEvent(rtt_updated, prior_in_flight, ack_receive_time);
+ MaybeInvokeCongestionEvent(rtt_updated, prior_bytes_in_flight,
+ ack_receive_time);
unacked_packets_.RemoveObsoletePackets();
sustained_bandwidth_recorder_.RecordEstimate(
@@ -337,8 +374,8 @@ void QuicSentPacketManager::HandleAckForSentPackets(
// If data is associated with the most recent transmission of this
// packet, then inform the caller.
if (it->in_flight) {
- packets_acked_.push_back(
- AckedPacket(packet_number, it->bytes_sent, QuicTime::Zero()));
+ packets_acked_.emplace_back(packet_number, it->bytes_sent,
+ QuicTime::Zero());
} else {
// Unackable packets are skipped earlier.
largest_newly_acked_ = packet_number;
@@ -398,6 +435,9 @@ void QuicSentPacketManager::MarkForRetransmission(
QuicTransmissionInfo* transmission_info =
unacked_packets_.GetMutableTransmissionInfo(packet_number);
QUIC_BUG_IF(!unacked_packets_.HasRetransmittableFrames(*transmission_info));
+ // Handshake packets should never be sent as probing retransmissions.
+ DCHECK(!transmission_info->has_crypto_handshake ||
+ transmission_type != PROBING_RETRANSMISSION);
// Both TLP and the new RTO leave the packets in flight and let the loss
// detection decide if packets are lost.
if (transmission_type != TLP_RETRANSMISSION &&
@@ -572,6 +612,10 @@ bool QuicSentPacketManager::HasUnackedPackets() const {
return unacked_packets_.HasUnackedPackets();
}
+bool QuicSentPacketManager::HasUnackedCryptoPackets() const {
+ return unacked_packets_.HasPendingCryptoPackets();
+}
+
QuicPacketNumber QuicSentPacketManager::GetLeastUnacked() const {
return unacked_packets_.GetLeastUnacked();
}
@@ -646,10 +690,13 @@ void QuicSentPacketManager::OnRetransmissionTimeout() {
case RTO_MODE:
++stats_->rto_count;
RetransmitRtoPackets();
- if (!session_decides_what_to_write() &&
- network_change_visitor_ != nullptr &&
- consecutive_rto_count_ == kMinTimeoutsBeforePathDegrading) {
- network_change_visitor_->OnPathDegrading();
+ if (!use_path_degrading_alarm_) {
+ if (!session_decides_what_to_write() &&
+ network_change_visitor_ != nullptr &&
+ consecutive_rto_count_ ==
+ kNumRetransmissionDelaysForPathDegradingDelay) {
+ network_change_visitor_->OnPathDegrading();
+ }
}
return;
}
@@ -754,9 +801,12 @@ void QuicSentPacketManager::RetransmitRtoPackets() {
++consecutive_rto_count_;
}
if (session_decides_what_to_write()) {
- if (network_change_visitor_ != nullptr &&
- consecutive_rto_count_ == kMinTimeoutsBeforePathDegrading) {
- network_change_visitor_->OnPathDegrading();
+ if (!use_path_degrading_alarm_) {
+ if (network_change_visitor_ != nullptr &&
+ consecutive_rto_count_ ==
+ kNumRetransmissionDelaysForPathDegradingDelay) {
+ network_change_visitor_->OnPathDegrading();
+ }
}
for (QuicPacketNumber retransmission : retransmissions) {
MarkForRetransmission(retransmission, RTO_RETRANSMISSION);
@@ -809,26 +859,27 @@ void QuicSentPacketManager::InvokeLossDetection(QuicTime time) {
}
}
-bool QuicSentPacketManager::MaybeUpdateRTT(const QuicAckFrame& ack_frame,
+bool QuicSentPacketManager::MaybeUpdateRTT(QuicPacketNumber largest_acked,
+ QuicTime::Delta ack_delay_time,
QuicTime ack_receive_time) {
// We rely on ack_delay_time to compute an RTT estimate, so we
// only update rtt when the largest observed gets acked.
- if (!unacked_packets_.IsUnacked(LargestAcked(ack_frame))) {
+ if (!unacked_packets_.IsUnacked(largest_acked)) {
return false;
}
// We calculate the RTT based on the highest ACKed packet number, the lower
// packet numbers will include the ACK aggregation delay.
const QuicTransmissionInfo& transmission_info =
- unacked_packets_.GetTransmissionInfo(LargestAcked(ack_frame));
+ unacked_packets_.GetTransmissionInfo(largest_acked);
// Ensure the packet has a valid sent time.
if (transmission_info.sent_time == QuicTime::Zero()) {
QUIC_BUG << "Acked packet has zero sent time, largest_observed:"
- << LargestAcked(ack_frame);
+ << largest_acked;
return false;
}
QuicTime::Delta send_delta = ack_receive_time - transmission_info.sent_time;
- rtt_stats_.UpdateRtt(send_delta, ack_frame.ack_delay_time, ack_receive_time);
+ rtt_stats_.UpdateRtt(send_delta, ack_delay_time, ack_receive_time);
return true;
}
@@ -862,6 +913,10 @@ const QuicTime QuicSentPacketManager::GetRetransmissionTime() const {
}
switch (GetRetransmissionMode()) {
case HANDSHAKE_MODE:
+ if (use_better_crypto_retransmission_) {
+ return unacked_packets_.GetLastCryptoPacketSentTime() +
+ GetCryptoRetransmissionDelay();
+ }
return clock_->ApproximateNow() + GetCryptoRetransmissionDelay();
case LOSS_MODE:
return loss_algorithm_->GetLossTimeout();
@@ -888,6 +943,17 @@ const QuicTime QuicSentPacketManager::GetRetransmissionTime() const {
return QuicTime::Zero();
}
+const QuicTime::Delta QuicSentPacketManager::GetPathDegradingDelay() const {
+ QuicTime::Delta delay = QuicTime::Delta::Zero();
+ for (size_t i = 0; i < max_tail_loss_probes_; ++i) {
+ delay = delay + GetTailLossProbeDelay(i);
+ }
+ for (size_t i = 0; i < kNumRetransmissionDelaysForPathDegradingDelay; ++i) {
+ delay = delay + GetRetransmissionDelay(i);
+ }
+ return delay;
+}
+
const QuicTime::Delta QuicSentPacketManager::GetCryptoRetransmissionDelay()
const {
// This is equivalent to the TailLossProbeDelay, but slightly more aggressive
@@ -907,9 +973,10 @@ const QuicTime::Delta QuicSentPacketManager::GetCryptoRetransmissionDelay()
delay_ms << consecutive_crypto_retransmission_count_);
}
-const QuicTime::Delta QuicSentPacketManager::GetTailLossProbeDelay() const {
+const QuicTime::Delta QuicSentPacketManager::GetTailLossProbeDelay(
+ size_t consecutive_tlp_count) const {
QuicTime::Delta srtt = rtt_stats_.SmoothedOrInitialRtt();
- if (enable_half_rtt_tail_loss_probe_ && consecutive_tlp_count_ == 0u) {
+ if (enable_half_rtt_tail_loss_probe_ && consecutive_tlp_count == 0u) {
return std::max(min_tlp_timeout_, srtt * 0.5);
}
if (ietf_style_tlp_) {
@@ -927,7 +994,12 @@ const QuicTime::Delta QuicSentPacketManager::GetTailLossProbeDelay() const {
return std::max(min_tlp_timeout_, 2 * srtt);
}
-const QuicTime::Delta QuicSentPacketManager::GetRetransmissionDelay() const {
+const QuicTime::Delta QuicSentPacketManager::GetTailLossProbeDelay() const {
+ return GetTailLossProbeDelay(consecutive_tlp_count_);
+}
+
+const QuicTime::Delta QuicSentPacketManager::GetRetransmissionDelay(
+ size_t consecutive_rto_count) const {
QuicTime::Delta retransmission_delay = QuicTime::Delta::Zero();
if (rtt_stats_.smoothed_rtt().IsZero()) {
// We are in the initial state, use default timeout values.
@@ -944,7 +1016,7 @@ const QuicTime::Delta QuicSentPacketManager::GetRetransmissionDelay() const {
// Calculate exponential back off.
retransmission_delay =
retransmission_delay *
- (1 << std::min<size_t>(consecutive_rto_count_, kMaxRetransmissions));
+ (1 << std::min<size_t>(consecutive_rto_count, kMaxRetransmissions));
if (retransmission_delay.ToMilliseconds() > kMaxRetransmissionTimeMs) {
return QuicTime::Delta::FromMilliseconds(kMaxRetransmissionTimeMs);
@@ -952,6 +1024,10 @@ const QuicTime::Delta QuicSentPacketManager::GetRetransmissionDelay() const {
return retransmission_delay;
}
+const QuicTime::Delta QuicSentPacketManager::GetRetransmissionDelay() const {
+ return GetRetransmissionDelay(consecutive_rto_count_);
+}
+
const RttStats* QuicSentPacketManager::GetRttStats() const {
return &rtt_stats_;
}
@@ -1034,22 +1110,98 @@ void QuicSentPacketManager::OnConnectionMigration(AddressChangeType type) {
}
void QuicSentPacketManager::OnAckFrameStart(QuicPacketNumber largest_acked,
- QuicTime::Delta ack_delay_time) {
- last_ack_frame_.largest_acked = largest_acked;
+ QuicTime::Delta ack_delay_time,
+ QuicTime ack_receive_time) {
+ DCHECK(packets_acked_.empty());
+ DCHECK_LE(largest_acked, unacked_packets_.largest_sent_packet());
+ rtt_updated_ =
+ MaybeUpdateRTT(largest_acked, ack_delay_time, ack_receive_time);
+ DCHECK_GE(largest_acked, unacked_packets_.largest_observed());
last_ack_frame_.ack_delay_time = ack_delay_time;
+ acked_packets_iter_ = last_ack_frame_.packets.rbegin();
}
void QuicSentPacketManager::OnAckRange(QuicPacketNumber start,
- QuicPacketNumber end,
- bool last_range,
- QuicTime ack_receive_time) {
- last_ack_frame_.packets.AddRange(start, end);
- if (!last_range) {
+ QuicPacketNumber end) {
+ if (end > last_ack_frame_.largest_acked + 1) {
+ // Largest acked increases.
+ unacked_packets_.IncreaseLargestObserved(end - 1);
+ last_ack_frame_.largest_acked = end - 1;
+ }
+ // Drop ack ranges which ack packets below least_unacked.
+ QuicPacketNumber least_unacked = unacked_packets_.GetLeastUnacked();
+ if (end <= least_unacked) {
return;
}
- OnIncomingAck(last_ack_frame_, ack_receive_time);
- // Clear last_ack_frame_.
- last_ack_frame_.Clear();
+ start = std::max(start, least_unacked);
+ DCHECK_LT(start, end);
+ do {
+ QuicPacketNumber newly_acked_start = start;
+ if (acked_packets_iter_ != last_ack_frame_.packets.rend()) {
+ newly_acked_start = std::max(start, acked_packets_iter_->max());
+ }
+ for (QuicPacketNumber acked = end - 1; acked >= newly_acked_start;
+ --acked) {
+ // Check if end is above the current range. If so add newly acked packets
+ // in descending order.
+ packets_acked_.push_back(AckedPacket(acked, 0, QuicTime::Zero()));
+ }
+ if (acked_packets_iter_ == last_ack_frame_.packets.rend() ||
+ start > acked_packets_iter_->min()) {
+ // Finish adding all newly acked packets.
+ return;
+ }
+ end = std::min(end, acked_packets_iter_->min());
+ ++acked_packets_iter_;
+ } while (start < end);
+}
+
+bool QuicSentPacketManager::OnAckFrameEnd(QuicTime ack_receive_time) {
+ QuicByteCount prior_bytes_in_flight = unacked_packets_.bytes_in_flight();
+ // Reverse packets_acked_ so that it is in ascending order.
+ reverse(packets_acked_.begin(), packets_acked_.end());
+ for (AckedPacket& acked_packet : packets_acked_) {
+ QuicTransmissionInfo* info =
+ unacked_packets_.GetMutableTransmissionInfo(acked_packet.packet_number);
+ if (!QuicUtils::IsAckable(info->state)) {
+ if (info->state == ACKED) {
+ QUIC_BUG << "Trying to ack an already acked packet: "
+ << acked_packet.packet_number;
+ } else {
+ QUIC_PEER_BUG << "Received ack for unackable packet: "
+ << acked_packet.packet_number << " with state: "
+ << QuicUtils::SentPacketStateToString(info->state);
+ }
+ continue;
+ }
+ QUIC_DVLOG(1) << ENDPOINT << "Got an ack for packet "
+ << acked_packet.packet_number;
+ last_ack_frame_.packets.Add(acked_packet.packet_number);
+ if (info->largest_acked > 0) {
+ largest_packet_peer_knows_is_acked_ =
+ std::max(largest_packet_peer_knows_is_acked_, info->largest_acked);
+ }
+ // If data is associated with the most recent transmission of this
+ // packet, then inform the caller.
+ if (info->in_flight) {
+ acked_packet.bytes_acked = info->bytes_sent;
+ } else {
+ // Unackable packets are skipped earlier.
+ largest_newly_acked_ = acked_packet.packet_number;
+ }
+ MarkPacketHandled(acked_packet.packet_number, info,
+ last_ack_frame_.ack_delay_time);
+ }
+ const bool acked_new_packet = !packets_acked_.empty();
+ PostProcessAfterMarkingPacketHandled(last_ack_frame_, ack_receive_time,
+ rtt_updated_, prior_bytes_in_flight);
+ // TODO(fayang): Move this line to PostProcessAfterMarkingPacketHandled
+ // when deprecating quic_reloadable_flag_quic_use_incremental_ack_processing3.
+ // Remove packets below least unacked from all_packets_acked_ and
+ // last_ack_frame_.
+ last_ack_frame_.packets.RemoveUpTo(unacked_packets_.GetLeastUnacked());
+
+ return acked_new_packet;
}
void QuicSentPacketManager::SetDebugDelegate(DebugDelegate* debug_delegate) {
diff --git a/chromium/net/quic/core/quic_sent_packet_manager.h b/chromium/net/quic/core/quic_sent_packet_manager.h
index d067950c721..4c916ea3d99 100644
--- a/chromium/net/quic/core/quic_sent_packet_manager.h
+++ b/chromium/net/quic/core/quic_sent_packet_manager.h
@@ -82,6 +82,8 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// Called with the path may be degrading. Note that the path may only be
// temporarily degrading.
+ // TODO(b/76462761): remove this once
+ // FLAGS_quic_reloadable_flag_quic_path_degrading_alarm is deprecated.
virtual void OnPathDegrading() = 0;
// Called when the Path MTU may have increased.
@@ -110,8 +112,9 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
void SetHandshakeConfirmed();
- // Processes the incoming ack.
- void OnIncomingAck(const QuicAckFrame& ack_frame, QuicTime ack_receive_time);
+ // Processes the incoming ack. Returns true if a previously-unacked packet is
+ // acked.
+ bool OnIncomingAck(const QuicAckFrame& ack_frame, QuicTime ack_receive_time);
// Requests retransmission of all unacked packets of |retransmission_type|.
// The behavior of this method depends on the value of |retransmission_type|:
@@ -148,6 +151,9 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
bool HasUnackedPackets() const;
+ // Returns true if there's outstanding crypto data.
+ bool HasUnackedCryptoPackets() const;
+
// Returns the smallest packet number of a serialized packet which has not
// been acked by the peer.
QuicPacketNumber GetLeastUnacked() const;
@@ -176,6 +182,10 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// there are no retransmittable packets.
const QuicTime GetRetransmissionTime() const;
+ // Returns the current delay for the path degrading timer, which is used to
+ // notify the session that this connection is degrading.
+ const QuicTime::Delta GetPathDegradingDelay() const;
+
const RttStats* GetRttStats() const;
// Returns the estimated bandwidth calculated by the congestion algorithm.
@@ -218,13 +228,16 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// Called when an ack frame is initially parsed.
void OnAckFrameStart(QuicPacketNumber largest_acked,
- QuicTime::Delta ack_delay_time);
+ QuicTime::Delta ack_delay_time,
+ QuicTime ack_receive_time);
+
+ // Called when ack range [start, end) is received. Populates packets_acked_
+ // with newly acked packets.
+ void OnAckRange(QuicPacketNumber start, QuicPacketNumber end);
- // Called when ack range [start, end) is received.
- void OnAckRange(QuicPacketNumber start,
- QuicPacketNumber end,
- bool last_range,
- QuicTime ack_receive_time);
+ // Called when an ack frame is parsed completely. Returns true if a previously
+ // -unacked packet is acked.
+ bool OnAckFrameEnd(QuicTime ack_receive_time);
// Called to enable/disable letting session decide what to write.
void SetSessionDecideWhatToWrite(bool session_decides_what_to_write);
@@ -249,6 +262,10 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
void SetSessionNotifier(SessionNotifierInterface* session_notifier);
+ QuicPacketCount initial_congestion_window() const {
+ return initial_congestion_window_;
+ }
+
QuicPacketNumber largest_packet_peer_knows_is_acked() const {
return largest_packet_peer_knows_is_acked_;
}
@@ -301,13 +318,26 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// packets from flight.
void RetransmitRtoPackets();
- // Returns the timer for retransmitting crypto handshake packets.
+ // Returns the timeout for retransmitting crypto handshake packets.
const QuicTime::Delta GetCryptoRetransmissionDelay() const;
- // Returns the timer for a new tail loss probe.
+ // Returns the timeout for a new tail loss probe. |consecutive_tlp_count| is
+ // the number of consecutive tail loss probes that have already been sent.
+ const QuicTime::Delta GetTailLossProbeDelay(
+ size_t consecutive_tlp_count) const;
+
+ // Calls GetTailLossProbeDelay() with values from the current state of this
+ // packet manager as its params.
const QuicTime::Delta GetTailLossProbeDelay() const;
// Returns the retransmission timeout, after which a full RTO occurs.
+ // |consecutive_rto_count| is the number of consecutive RTOs that have already
+ // occurred.
+ const QuicTime::Delta GetRetransmissionDelay(
+ size_t consecutive_rto_count) const;
+
+ // Calls GetRetransmissionDelay() with values from the current state of this
+ // packet manager as its params.
const QuicTime::Delta GetRetransmissionDelay() const;
// Returns the newest transmission associated with a packet.
@@ -317,7 +347,9 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// Update the RTT if the ack is for the largest acked packet number.
// Returns true if the rtt was updated.
- bool MaybeUpdateRTT(const QuicAckFrame& ack_frame, QuicTime ack_receive_time);
+ bool MaybeUpdateRTT(QuicPacketNumber largest_acked,
+ QuicTime::Delta ack_delay_time,
+ QuicTime ack_receive_time);
// Invokes the loss detection algorithm and loses and retransmits packets if
// necessary.
@@ -345,6 +377,13 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
void MarkForRetransmission(QuicPacketNumber packet_number,
TransmissionType transmission_type);
+ // Called after packets have been marked handled with last received ack frame.
+ void PostProcessAfterMarkingPacketHandled(
+ const QuicAckFrame& ack_frame,
+ QuicTime ack_receive_time,
+ bool rtt_updated,
+ QuicByteCount prior_bytes_in_flight);
+
// Notify observers that packet with QuicTransmissionInfo |info| is a spurious
// retransmission. It is caller's responsibility to guarantee the packet with
// QuicTransmissionInfo |info| is a spurious retransmission before calling
@@ -389,7 +428,7 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
DebugDelegate* debug_delegate_;
NetworkChangeVisitor* network_change_visitor_;
- const QuicPacketCount initial_congestion_window_;
+ QuicPacketCount initial_congestion_window_;
RttStats rtt_stats_;
std::unique_ptr<SendAlgorithmInterface> send_algorithm_;
// Not owned. Always points to |general_loss_algorithm_| outside of tests.
@@ -459,6 +498,23 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// Latest received ack frame.
QuicAckFrame last_ack_frame_;
+ // Record whether RTT gets updated by last largest acked. This is only used
+ // when quic_reloadable_flag_quic_use_incremental_ack_processing3 is true.
+ bool rtt_updated_;
+
+ // A reverse iterator of last_ack_frame_.packets. This is reset in
+ // OnAckRangeStart, and gradually moves in OnAckRange. This is only used
+ // when quic_reloadable_flag_quic_use_incremental_ack_processing3 is true.
+ PacketNumberQueue::const_reverse_iterator acked_packets_iter_;
+
+ // Latched value of
+ // quic_reloadable_flag_quic_path_degrading_alarm
+ const bool use_path_degrading_alarm_;
+
+ // Latched value of
+ // quic_reloadable_flag_quic_better_crypto_retransmission
+ const bool use_better_crypto_retransmission_;
+
DISALLOW_COPY_AND_ASSIGN(QuicSentPacketManager);
};
diff --git a/chromium/net/quic/core/quic_sent_packet_manager_test.cc b/chromium/net/quic/core/quic_sent_packet_manager_test.cc
index 49ae651f2c6..17154215e04 100644
--- a/chromium/net/quic/core/quic_sent_packet_manager_test.cc
+++ b/chromium/net/quic/core/quic_sent_packet_manager_test.cc
@@ -86,7 +86,9 @@ class QuicSentPacketManagerTest : public QuicTestWithParam<bool> {
QuicSentPacketManagerTest()
: manager_(Perspective::IS_SERVER, &clock_, &stats_, kCubicBytes, kNack),
send_algorithm_(new StrictMock<MockSendAlgorithm>),
- network_change_visitor_(new StrictMock<MockNetworkChangeVisitor>) {
+ network_change_visitor_(new StrictMock<MockNetworkChangeVisitor>),
+ use_path_degrading_alarm_(
+ GetQuicReloadableFlag(quic_path_degrading_alarm)) {
QuicSentPacketManagerPeer::SetSendAlgorithm(&manager_, send_algorithm_);
// Disable tail loss probes for most tests.
QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 0);
@@ -255,7 +257,7 @@ class QuicSentPacketManagerTest : public QuicTestWithParam<bool> {
SerializedPacket CreatePacket(QuicPacketNumber packet_number,
bool retransmittable) {
- SerializedPacket packet(packet_number, PACKET_6BYTE_PACKET_NUMBER, nullptr,
+ SerializedPacket packet(packet_number, PACKET_4BYTE_PACKET_NUMBER, nullptr,
kDefaultLength, false, false);
if (retransmittable) {
packet.retransmittable_frames.push_back(QuicFrame(
@@ -318,6 +320,10 @@ class QuicSentPacketManagerTest : public QuicTestWithParam<bool> {
MockSendAlgorithm* send_algorithm_;
std::unique_ptr<MockNetworkChangeVisitor> network_change_visitor_;
StrictMock<MockSessionNotifier> notifier_;
+
+ // Latched value of
+ // quic_reloadable_flag_quic_path_degrading_alarm
+ bool use_path_degrading_alarm_;
};
INSTANTIATE_TEST_CASE_P(Tests, QuicSentPacketManagerTest, testing::Bool());
@@ -357,11 +363,12 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAck) {
QuicAckFrame ack_frame = InitAckFrame({{2, 3}});
ExpectAck(2);
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite());
- manager_.OnAckRange(2, 3, /*last_range=*/true, clock_.Now());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(2, 3);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.Now());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
}
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
@@ -391,11 +398,12 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAckBeforeSend) {
// Ack 1.
QuicAckFrame ack_frame = InitAckFrame(1);
ExpectAck(1);
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite());
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.Now());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.Now());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
}
// There should no longer be a pending retransmission.
@@ -448,11 +456,12 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAckPrevious) {
// Ack 1 but not 2.
ExpectAck(1);
QuicAckFrame ack_frame = InitAckFrame(1);
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite());
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
}
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
@@ -467,9 +476,10 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAckPrevious) {
EXPECT_CALL(notifier_, OnFrameAcked(_, _)).WillOnce(Return(false));
ExpectAck(2);
QuicAckFrame ack_frame2 = InitAckFrame(2);
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite());
- manager_.OnAckRange(1, 3, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(1, 3);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
manager_.OnIncomingAck(ack_frame2, clock_.ApproximateNow());
}
@@ -487,11 +497,12 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAckPreviousThenNackRetransmit) {
// First, ACK packet 1 which makes packet 2 non-retransmittable.
ExpectAck(1);
QuicAckFrame ack_frame = InitAckFrame(1);
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite());
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
}
SendDataPacket(3);
@@ -503,22 +514,24 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAckPreviousThenNackRetransmit) {
ack_frame = InitAckFrame({{1, 2}, {3, 4}});
ExpectAck(3);
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite());
- manager_.OnAckRange(3, 4, /*last_range=*/false, clock_.ApproximateNow());
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(3, 4);
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
}
ack_frame = InitAckFrame({{1, 2}, {3, 5}});
ExpectAck(4);
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite());
- manager_.OnAckRange(3, 5, /*last_range=*/false, clock_.ApproximateNow());
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(3, 5);
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
}
ack_frame = InitAckFrame({{1, 2}, {3, 6}});
@@ -527,12 +540,13 @@ TEST_P(QuicSentPacketManagerTest, RetransmitThenAckPreviousThenNackRetransmit) {
// Frames in all packets are acked.
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
}
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite());
- manager_.OnAckRange(3, 6, /*last_range=*/false, clock_.ApproximateNow());
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(3, 6);
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
}
// No packets remain unacked.
@@ -562,11 +576,12 @@ TEST_P(QuicSentPacketManagerTest,
QuicAckFrame ack_frame = InitAckFrame(1);
ExpectUpdatedRtt(1);
EXPECT_CALL(*send_algorithm_, RevertRetransmissionTimeout());
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite());
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
}
// Since 2 was marked for retransmit, when 1 is acked, 2 is kept for RTT.
@@ -602,11 +617,12 @@ TEST_P(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
// Ack 1 but not 2 or 3.
ExpectAck(1);
QuicAckFrame ack_frame = InitAckFrame(1);
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite());
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
}
if (manager_.session_decides_what_to_write()) {
// Frames in packets 2 and 3 are acked.
@@ -632,12 +648,13 @@ TEST_P(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
ack_frame = InitAckFrame({{1, 2}, {3, 5}});
QuicPacketNumber acked[] = {3, 4};
ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite());
- manager_.OnAckRange(3, 5, /*last_range=*/false, clock_.ApproximateNow());
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(3, 5);
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
}
QuicPacketNumber unacked2[] = {2};
@@ -652,12 +669,13 @@ TEST_P(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
// Frames in all packetss are acked.
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
}
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite());
- manager_.OnAckRange(3, 6, /*last_range=*/false, clock_.ApproximateNow());
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(3, 6);
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
}
VerifyUnackedPackets(nullptr, 0);
@@ -684,11 +702,12 @@ TEST_P(QuicSentPacketManagerTest, AckOriginalTransmission) {
QuicAckFrame ack_frame = InitAckFrame(1);
ExpectAck(1);
EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _));
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite());
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.Now());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.Now());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
}
}
@@ -699,27 +718,33 @@ TEST_P(QuicSentPacketManagerTest, AckOriginalTransmission) {
QuicAckFrame ack_frame = InitAckFrame({{1, 2}, {4, 5}});
ExpectAck(4);
EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _));
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite());
- manager_.OnAckRange(4, 5, /*last_range=*/false, clock_.Now());
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.Now());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(4, 5);
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.Now());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
}
RetransmitAndSendPacket(3, 5, LOSS_RETRANSMISSION);
}
// Ack 3, which causes SpuriousRetransmitDetected to be called.
{
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ QuicPacketNumber acked[] = {3};
+ ExpectAcksAndLosses(false, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+ }
QuicAckFrame ack_frame = InitAckFrame({{1, 2}, {3, 5}});
EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _));
EXPECT_CALL(*loss_algorithm, SpuriousRetransmitDetected(_, _, _, 5));
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite());
- manager_.OnAckRange(3, 5, /*last_range=*/false, clock_.Now());
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.Now());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(3, 5);
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.Now());
+ EXPECT_FALSE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
}
if (manager_.session_decides_what_to_write()) {
// Ack 3 will not cause 5 be considered as a spurious retransmission. Ack
@@ -729,10 +754,11 @@ TEST_P(QuicSentPacketManagerTest, AckOriginalTransmission) {
EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _));
EXPECT_CALL(notifier_, OnFrameAcked(_, _)).WillOnce(Return(false));
QuicAckFrame ack_frame2 = InitAckFrame({{1, 2}, {3, 6}});
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite());
- manager_.OnAckRange(3, 6, /*last_range=*/false, clock_.Now());
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.Now());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(3, 6);
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
manager_.OnIncomingAck(ack_frame2, clock_.Now());
}
@@ -758,12 +784,19 @@ TEST_P(QuicSentPacketManagerTest, AckAckAndUpdateRtt) {
QuicAckFrame ack_frame = InitAckFrame(2);
ack_frame.ack_delay_time = QuicTime::Delta::FromMilliseconds(5);
- ExpectAck(1);
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(2, QuicTime::Delta::FromMilliseconds(5));
- manager_.OnAckRange(1, 3, /*last_range=*/true, clock_.Now());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ QuicPacketNumber acked[] = {1, 2};
+ ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+ } else {
+ ExpectAck(1);
+ }
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(2, QuicTime::Delta::FromMilliseconds(5),
+ clock_.Now());
+ manager_.OnAckRange(1, 3);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.Now());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
}
EXPECT_EQ(1u, manager_.largest_packet_peer_knows_is_acked());
@@ -771,12 +804,18 @@ TEST_P(QuicSentPacketManagerTest, AckAckAndUpdateRtt) {
// Now ack the ack and expect only an RTT update.
ack_frame = InitAckFrame(3);
- ExpectUpdatedRtt(3);
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite());
- manager_.OnAckRange(1, 4, /*last_range=*/true, clock_.Now());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ QuicPacketNumber acked[] = {3};
+ ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
} else {
- manager_.OnIncomingAck(ack_frame, clock_.Now());
+ ExpectUpdatedRtt(3);
+ }
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(1, 4);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
+ } else {
+ EXPECT_FALSE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
}
EXPECT_EQ(3u, manager_.largest_packet_peer_knows_is_acked());
}
@@ -789,11 +828,12 @@ TEST_P(QuicSentPacketManagerTest, Rtt) {
ExpectAck(packet_number);
QuicAckFrame ack_frame = InitAckFrame(packet_number);
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite());
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.Now());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.Now());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
}
EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
}
@@ -810,11 +850,13 @@ TEST_P(QuicSentPacketManagerTest, RttWithInvalidDelta) {
ExpectAck(packet_number);
QuicAckFrame ack_frame = InitAckFrame(packet_number);
ack_frame.ack_delay_time = QuicTime::Delta::FromMilliseconds(11);
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(1, QuicTime::Delta::FromMilliseconds(11));
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.Now());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(1, QuicTime::Delta::FromMilliseconds(11),
+ clock_.Now());
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.Now());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
}
EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
}
@@ -830,11 +872,12 @@ TEST_P(QuicSentPacketManagerTest, RttWithInfiniteDelta) {
ExpectAck(packet_number);
QuicAckFrame ack_frame = InitAckFrame(packet_number);
ack_frame.ack_delay_time = QuicTime::Delta::Infinite();
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite());
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.Now());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.Now());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
}
EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
}
@@ -850,11 +893,12 @@ TEST_P(QuicSentPacketManagerTest, RttZeroDelta) {
ExpectAck(packet_number);
QuicAckFrame ack_frame = InitAckFrame(packet_number);
ack_frame.ack_delay_time = QuicTime::Delta::Zero();
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(1, QuicTime::Delta::Zero());
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.Now());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(1, QuicTime::Delta::Zero(), clock_.Now());
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.Now());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
}
EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
}
@@ -904,11 +948,12 @@ TEST_P(QuicSentPacketManagerTest, TailLossProbeTimeout) {
ExpectAck(3);
QuicAckFrame ack_frame = InitAckFrame({{3, 4}});
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite());
- manager_.OnAckRange(3, 4, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(3, 4);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
}
EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
@@ -925,11 +970,12 @@ TEST_P(QuicSentPacketManagerTest, TailLossProbeTimeout) {
// Frames in all packets are acked.
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
}
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite());
- manager_.OnAckRange(3, 6, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(3, 6);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
}
EXPECT_FALSE(manager_.HasPendingRetransmissions());
@@ -1038,11 +1084,12 @@ TEST_P(QuicSentPacketManagerTest, TailLossProbeThenRTO) {
// Packets 1, 2 and [4, 102] are lost.
EXPECT_CALL(notifier_, OnFrameLost(_)).Times(101);
}
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(103, QuicTime::Delta::Infinite());
- manager_.OnAckRange(103, 104, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(103, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(103, 104);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
}
// All packets before 103 should be lost.
if (manager_.session_decides_what_to_write()) {
@@ -1106,12 +1153,13 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeout) {
EXPECT_CALL(notifier_, HasPendingCryptoData())
.WillRepeatedly(Return(false));
}
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(9, QuicTime::Delta::Infinite());
- manager_.OnAckRange(8, 10, /*last_range=*/false, clock_.ApproximateNow());
- manager_.OnAckRange(3, 6, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(9, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(8, 10);
+ manager_.OnAckRange(3, 6);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
}
EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
@@ -1179,11 +1227,12 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeTimeoutVersionNegotiation) {
QuicPacketNumber acked[] = {8, 9};
ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
QuicAckFrame ack_frame = InitAckFrame({{8, 10}});
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(9, QuicTime::Delta::Infinite());
- manager_.OnAckRange(8, 10, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(9, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(8, 10);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
}
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, HasPendingCryptoData())
@@ -1219,18 +1268,24 @@ TEST_P(QuicSentPacketManagerTest, CryptoHandshakeSpuriousRetransmission) {
// Now ack the second crypto packet, and ensure the first gets removed, but
// the third does not.
- ExpectUpdatedRtt(2);
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ QuicPacketNumber acked[] = {2};
+ ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+ } else {
+ ExpectUpdatedRtt(2);
+ }
QuicAckFrame ack_frame = InitAckFrame({{2, 3}});
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, HasPendingCryptoData())
.WillRepeatedly(Return(false));
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
}
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite());
- manager_.OnAckRange(2, 3, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(2, 3);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
+ EXPECT_FALSE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
}
EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
@@ -1347,12 +1402,18 @@ TEST_P(QuicSentPacketManagerTest,
// Ensure both packets get discarded when packet 2 is acked.
QuicAckFrame ack_frame = InitAckFrame({{3, 4}});
- ExpectUpdatedRtt(3);
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite());
- manager_.OnAckRange(3, 4, /*last_range=*/true, clock_.Now());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ QuicPacketNumber acked[] = {3};
+ ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
+ } else {
+ ExpectUpdatedRtt(3);
+ }
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(3, 4);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.Now());
+ EXPECT_FALSE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
}
VerifyUnackedPackets(nullptr, 0);
VerifyRetransmittablePackets(nullptr, 0);
@@ -1420,11 +1481,12 @@ TEST_P(QuicSentPacketManagerTest, RetransmissionTimeout) {
// retransmittable frames as packet 102 is acked.
EXPECT_CALL(notifier_, OnFrameLost(_)).Times(98);
}
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(102, QuicTime::Delta::Zero());
- manager_.OnAckRange(102, 103, /*last_range=*/true, clock_.Now());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(102, QuicTime::Delta::Zero(), clock_.Now());
+ manager_.OnAckRange(102, 103);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.Now());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
}
}
@@ -1495,11 +1557,12 @@ TEST_P(QuicSentPacketManagerTest, NewRetransmissionTimeout) {
// retransmittable frames as packet 102 is acked.
EXPECT_CALL(notifier_, OnFrameLost(_)).Times(98);
}
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(102, QuicTime::Delta::Zero());
- manager_.OnAckRange(102, 103, /*last_range=*/true, clock_.Now());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(102, QuicTime::Delta::Zero(), clock_.Now());
+ manager_.OnAckRange(102, 103);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.Now());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
}
}
@@ -1525,7 +1588,9 @@ TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckSecond) {
}
// Rto a second time.
- EXPECT_CALL(*network_change_visitor_, OnPathDegrading());
+ if (!use_path_degrading_alarm_) {
+ EXPECT_CALL(*network_change_visitor_, OnPathDegrading());
+ }
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, RetransmitFrames(_, _))
.WillOnce(WithArgs<1>(Invoke(
@@ -1548,11 +1613,12 @@ TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckSecond) {
QuicAckFrame ack_frame = InitAckFrame({{2, 3}});
ack_frame.ack_delay_time = QuicTime::Delta::Zero();
ExpectAck(2);
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(2, QuicTime::Delta::Zero());
- manager_.OnAckRange(2, 3, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(2, QuicTime::Delta::Zero(), clock_.Now());
+ manager_.OnAckRange(2, 3);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
}
// The original packet and newest should be outstanding.
@@ -1582,7 +1648,9 @@ TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckFirst) {
}
// Rto a second time.
- EXPECT_CALL(*network_change_visitor_, OnPathDegrading());
+ if (!use_path_degrading_alarm_) {
+ EXPECT_CALL(*network_change_visitor_, OnPathDegrading());
+ }
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, RetransmitFrames(_, _))
.WillOnce(WithArgs<1>(Invoke(
@@ -1605,11 +1673,12 @@ TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckFirst) {
QuicAckFrame ack_frame = InitAckFrame({{3, 4}});
ack_frame.ack_delay_time = QuicTime::Delta::Zero();
ExpectAck(3);
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(3, QuicTime::Delta::Zero());
- manager_.OnAckRange(3, 4, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(3, QuicTime::Delta::Zero(), clock_.Now());
+ manager_.OnAckRange(3, 4);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
}
// The first two packets should still be outstanding.
@@ -1618,6 +1687,10 @@ TEST_P(QuicSentPacketManagerTest, TwoRetransmissionTimeoutsAckFirst) {
}
TEST_P(QuicSentPacketManagerTest, OnPathDegrading) {
+ if (use_path_degrading_alarm_) {
+ return;
+ }
+
SendDataPacket(1);
for (size_t i = 1; i < kMinTimeoutsBeforePathDegrading; ++i) {
if (manager_.session_decides_what_to_write()) {
@@ -1645,6 +1718,7 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionTime) {
}
TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeCryptoHandshake) {
+ QuicTime crypto_packet_send_time = clock_.Now();
SendCryptoPacket(1);
// Check the min.
@@ -1665,6 +1739,7 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeCryptoHandshake) {
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, RetransmitFrames(_, _))
.WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(2); }));
+ crypto_packet_send_time = clock_.Now();
}
manager_.OnRetransmissionTimeout();
if (!manager_.session_decides_what_to_write()) {
@@ -1672,7 +1747,11 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeCryptoHandshake) {
}
// The retransmission time should now be twice as far in the future.
- expected_time = clock_.Now() + srtt * 2 * 1.5;
+ if (GetQuicReloadableFlag(quic_better_crypto_retransmission)) {
+ expected_time = crypto_packet_send_time + srtt * 2 * 1.5;
+ } else {
+ expected_time = clock_.Now() + srtt * 2 * 1.5;
+ }
EXPECT_EQ(expected_time, manager_.GetRetransmissionTime());
}
@@ -1691,6 +1770,7 @@ TEST_P(QuicSentPacketManagerTest,
EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
.WillRepeatedly(Return(10 * kDefaultTCPMSS));
+ QuicTime crypto_packet_send_time = clock_.Now();
SendCryptoPacket(1);
// Check the min.
@@ -1711,6 +1791,7 @@ TEST_P(QuicSentPacketManagerTest,
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, RetransmitFrames(_, _))
.WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(2); }));
+ crypto_packet_send_time = clock_.Now();
}
manager_.OnRetransmissionTimeout();
if (!manager_.session_decides_what_to_write()) {
@@ -1718,7 +1799,11 @@ TEST_P(QuicSentPacketManagerTest,
}
// The retransmission time should now be twice as far in the future.
- expected_time = clock_.Now() + srtt * 2 * 2;
+ if (GetQuicReloadableFlag(quic_better_crypto_retransmission)) {
+ expected_time = crypto_packet_send_time + srtt * 2 * 2;
+ } else {
+ expected_time = clock_.Now() + srtt * 2 * 2;
+ }
EXPECT_EQ(expected_time, manager_.GetRetransmissionTime());
}
@@ -1811,11 +1896,12 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionTimeSpuriousRTO) {
// original value and OnRetransmissionTimeout is not called or reverted.
QuicAckFrame ack_frame = InitAckFrame({{2, 3}});
ExpectAck(2);
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite());
- manager_.OnAckRange(2, 3, /*last_range=*/true, clock_.ApproximateNow());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(2, 3);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.ApproximateNow()));
}
EXPECT_FALSE(manager_.HasPendingRetransmissions());
EXPECT_EQ(5 * kDefaultLength,
@@ -1841,10 +1927,14 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionDelayMin) {
// If the delay is smaller than the min, ensure it exponentially backs off
// from the min.
- EXPECT_CALL(*network_change_visitor_, OnPathDegrading());
+ if (!use_path_degrading_alarm_) {
+ EXPECT_CALL(*network_change_visitor_, OnPathDegrading());
+ }
for (int i = 0; i < 5; ++i) {
EXPECT_EQ(delay,
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
+ EXPECT_EQ(delay,
+ QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, i));
delay = delay + delay;
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, RetransmitFrames(_, _))
@@ -1868,6 +1958,8 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionDelayMax) {
EXPECT_EQ(QuicTime::Delta::FromSeconds(60),
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
+ EXPECT_EQ(QuicTime::Delta::FromSeconds(60),
+ QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, 0));
}
TEST_P(QuicSentPacketManagerTest, GetTransmissionDelayExponentialBackoff) {
@@ -1875,10 +1967,14 @@ TEST_P(QuicSentPacketManagerTest, GetTransmissionDelayExponentialBackoff) {
QuicTime::Delta delay = QuicTime::Delta::FromMilliseconds(500);
// Delay should back off exponentially.
- EXPECT_CALL(*network_change_visitor_, OnPathDegrading());
+ if (!use_path_degrading_alarm_) {
+ EXPECT_CALL(*network_change_visitor_, OnPathDegrading());
+ }
for (int i = 0; i < 5; ++i) {
EXPECT_EQ(delay,
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
+ EXPECT_EQ(delay,
+ QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, i));
delay = delay + delay;
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, RetransmitFrames(_, _))
@@ -1908,6 +2004,8 @@ TEST_P(QuicSentPacketManagerTest, RetransmissionDelay) {
QuicTime::Delta::FromMilliseconds(kRttMs + kRttMs / 2 * 4);
EXPECT_EQ(expected_delay,
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
+ EXPECT_EQ(expected_delay,
+ QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, 0));
for (int i = 0; i < 100; ++i) {
// Run to make sure that we converge.
@@ -1925,6 +2023,8 @@ TEST_P(QuicSentPacketManagerTest, RetransmissionDelay) {
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_)
.ToMilliseconds(),
1);
+ EXPECT_EQ(QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, 0),
+ QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
}
TEST_P(QuicSentPacketManagerTest, GetLossDelay) {
@@ -1941,11 +2041,12 @@ TEST_P(QuicSentPacketManagerTest, GetLossDelay) {
ExpectAck(2);
EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _));
QuicAckFrame ack_frame = InitAckFrame({{2, 3}});
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite());
- manager_.OnAckRange(2, 3, /*last_range=*/true, clock_.Now());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(2, 3);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.Now());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
}
QuicTime timeout(clock_.Now() + QuicTime::Delta::FromMilliseconds(10));
@@ -2116,12 +2217,16 @@ TEST_F(QuicSentPacketManagerTest,
// The TLP with fewer than 2 packets outstanding includes 1/2 min RTO(200ms).
EXPECT_EQ(QuicTime::Delta::FromMicroseconds(100002),
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
+ EXPECT_EQ(QuicTime::Delta::FromMicroseconds(100002),
+ QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
// Send two packets, and the TLP should be 2 us.
SendDataPacket(1);
SendDataPacket(2);
EXPECT_EQ(QuicTime::Delta::FromMicroseconds(2),
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
+ EXPECT_EQ(QuicTime::Delta::FromMicroseconds(2),
+ QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
}
TEST_F(QuicSentPacketManagerTest,
@@ -2146,18 +2251,20 @@ TEST_F(QuicSentPacketManagerTest,
// The TLP with fewer than 2 packets outstanding includes 1/2 min RTO(200ms).
EXPECT_EQ(QuicTime::Delta::FromMicroseconds(100002),
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
-
+ EXPECT_EQ(QuicTime::Delta::FromMicroseconds(100002),
+ QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
// Send two packets, and the TLP should be 2 us.
SendDataPacket(1);
SendDataPacket(2);
EXPECT_EQ(QuicTime::Delta::FromMicroseconds(2),
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
+ EXPECT_EQ(QuicTime::Delta::FromMicroseconds(2),
+ QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
}
TEST_F(QuicSentPacketManagerTest,
DISABLED_NegotiateIETFTLPFromOptionsAtServer) {
SetQuicReloadableFlag(quic_max_ack_delay2, true);
- SetQuicReloadableFlag(quic_min_rtt_ack_delay, true);
QuicConfig config;
QuicTagVector options;
@@ -2173,18 +2280,21 @@ TEST_F(QuicSentPacketManagerTest,
// Expect 1.5x * SRTT + 0ms MAD
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(150),
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(150),
+ QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
// Expect 1.5x * SRTT + 50ms MAD
rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(150),
QuicTime::Delta::FromMilliseconds(50), QuicTime::Zero());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100), rtt_stats->smoothed_rtt());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200),
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200),
+ QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
}
TEST_F(QuicSentPacketManagerTest,
DISABLED_NegotiateIETFTLPFromOptionsAtClient) {
SetQuicReloadableFlag(quic_max_ack_delay2, true);
- SetQuicReloadableFlag(quic_min_rtt_ack_delay, true);
QuicConfig client_config;
QuicTagVector options;
@@ -2201,12 +2311,16 @@ TEST_F(QuicSentPacketManagerTest,
// Expect 1.5x * SRTT + 0ms MAD
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(150),
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(150),
+ QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
// Expect 1.5x * SRTT + 50ms MAD
rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(150),
QuicTime::Delta::FromMilliseconds(50), QuicTime::Zero());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100), rtt_stats->smoothed_rtt());
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200),
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200),
+ QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
}
TEST_F(QuicSentPacketManagerTest,
@@ -2226,9 +2340,13 @@ TEST_F(QuicSentPacketManagerTest,
QuicTime::Delta::Zero(), QuicTime::Zero());
EXPECT_EQ(QuicTime::Delta::FromMicroseconds(1),
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
+ EXPECT_EQ(QuicTime::Delta::FromMicroseconds(1),
+ QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, 0));
// The TLP with fewer than 2 packets outstanding includes 1/2 min RTO(0ms).
EXPECT_EQ(QuicTime::Delta::FromMicroseconds(2),
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
+ EXPECT_EQ(QuicTime::Delta::FromMicroseconds(2),
+ QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
}
TEST_F(QuicSentPacketManagerTest,
@@ -2249,9 +2367,13 @@ TEST_F(QuicSentPacketManagerTest,
QuicTime::Delta::Zero(), QuicTime::Zero());
EXPECT_EQ(QuicTime::Delta::FromMicroseconds(1),
QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_));
+ EXPECT_EQ(QuicTime::Delta::FromMicroseconds(1),
+ QuicSentPacketManagerPeer::GetRetransmissionDelay(&manager_, 0));
// The TLP with fewer than 2 packets outstanding includes 1/2 min RTO(0ms).
EXPECT_EQ(QuicTime::Delta::FromMicroseconds(2),
QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_));
+ EXPECT_EQ(QuicTime::Delta::FromMicroseconds(2),
+ QuicSentPacketManagerPeer::GetTailLossProbeDelay(&manager_, 0));
}
TEST_F(QuicSentPacketManagerTest, DISABLED_NegotiateNoTLPFromOptionsAtServer) {
@@ -2444,7 +2566,7 @@ TEST_P(QuicSentPacketManagerTest, ConnectionMigrationPortChange) {
TEST_P(QuicSentPacketManagerTest, PathMtuIncreased) {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, BytesInFlight(), 1, _, _));
- SerializedPacket packet(1, PACKET_6BYTE_PACKET_NUMBER, nullptr,
+ SerializedPacket packet(1, PACKET_4BYTE_PACKET_NUMBER, nullptr,
kDefaultLength + 100, false, false);
manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION,
HAS_RETRANSMITTABLE_DATA);
@@ -2454,12 +2576,41 @@ TEST_P(QuicSentPacketManagerTest, PathMtuIncreased) {
EXPECT_CALL(*network_change_visitor_,
OnPathMtuIncreased(kDefaultLength + 100));
QuicAckFrame ack_frame = InitAckFrame(1);
- if (GetQuicReloadableFlag(quic_use_incremental_ack_processing)) {
- manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite());
- manager_.OnAckRange(1, 2, /*last_range=*/true, clock_.Now());
+ if (GetQuicReloadableFlag(quic_use_incremental_ack_processing3)) {
+ manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(1, 2);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
} else {
- manager_.OnIncomingAck(ack_frame, clock_.Now());
+ EXPECT_TRUE(manager_.OnIncomingAck(ack_frame, clock_.Now()));
+ }
+}
+
+TEST_P(QuicSentPacketManagerTest, OnAckRangeSlowPath) {
+ SetQuicReloadableFlag(quic_use_incremental_ack_processing3, true);
+ // Send packets 1 - 20.
+ for (size_t i = 1; i <= 20; ++i) {
+ SendDataPacket(i);
}
+ // Ack [5, 7), [10, 12), [15, 17).
+ QuicPacketNumber acked1[] = {5, 6, 10, 11, 15, 16};
+ QuicPacketNumber lost1[] = {1, 2, 3, 4, 7, 8, 9, 12, 13};
+ ExpectAcksAndLosses(true, acked1, QUIC_ARRAYSIZE(acked1), lost1,
+ QUIC_ARRAYSIZE(lost1));
+ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(AnyNumber());
+ manager_.OnAckFrameStart(16, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(15, 17);
+ manager_.OnAckRange(10, 12);
+ manager_.OnAckRange(5, 7);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
+
+ // Ack [4, 8), [9, 13), [14, 21).
+ QuicPacketNumber acked2[] = {4, 7, 9, 12, 14, 17, 18, 19, 20};
+ ExpectAcksAndLosses(true, acked2, QUIC_ARRAYSIZE(acked2), nullptr, 0);
+ manager_.OnAckFrameStart(20, QuicTime::Delta::Infinite(), clock_.Now());
+ manager_.OnAckRange(14, 21);
+ manager_.OnAckRange(9, 13);
+ manager_.OnAckRange(4, 8);
+ EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
}
} // namespace
diff --git a/chromium/net/quic/core/quic_server_session_base_test.cc b/chromium/net/quic/core/quic_server_session_base_test.cc
index afc48cc1b62..cb8dd785c81 100644
--- a/chromium/net/quic/core/quic_server_session_base_test.cc
+++ b/chromium/net/quic/core/quic_server_session_base_test.cc
@@ -207,14 +207,9 @@ TEST_P(QuicServerSessionBaseTest, CloseStreamDueToReset) {
QuicRstStreamFrame rst1(kInvalidControlFrameId, GetNthClientInitiatedId(0),
QUIC_ERROR_PROCESSING_STREAM, 0);
EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
- if (session_->use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_, OnStreamReset(GetNthClientInitiatedId(0),
- QUIC_RST_ACKNOWLEDGEMENT));
- } else {
- EXPECT_CALL(*connection_, SendRstStream(GetNthClientInitiatedId(0),
- QUIC_RST_ACKNOWLEDGEMENT, 0));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(GetNthClientInitiatedId(0),
+ QUIC_RST_ACKNOWLEDGEMENT));
visitor_->OnRstStream(rst1);
EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
@@ -231,14 +226,9 @@ TEST_P(QuicServerSessionBaseTest, NeverOpenStreamDueToReset) {
QuicRstStreamFrame rst1(kInvalidControlFrameId, GetNthClientInitiatedId(0),
QUIC_ERROR_PROCESSING_STREAM, 0);
EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
- if (session_->use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_, OnStreamReset(GetNthClientInitiatedId(0),
- QUIC_RST_ACKNOWLEDGEMENT));
- } else {
- EXPECT_CALL(*connection_, SendRstStream(GetNthClientInitiatedId(0),
- QUIC_RST_ACKNOWLEDGEMENT, 0));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(GetNthClientInitiatedId(0),
+ QUIC_RST_ACKNOWLEDGEMENT));
visitor_->OnRstStream(rst1);
EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
@@ -266,14 +256,9 @@ TEST_P(QuicServerSessionBaseTest, AcceptClosedStream) {
QuicRstStreamFrame rst(kInvalidControlFrameId, GetNthClientInitiatedId(0),
QUIC_ERROR_PROCESSING_STREAM, 0);
EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
- if (session_->use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_, OnStreamReset(GetNthClientInitiatedId(0),
- QUIC_RST_ACKNOWLEDGEMENT));
- } else {
- EXPECT_CALL(*connection_, SendRstStream(GetNthClientInitiatedId(0),
- QUIC_RST_ACKNOWLEDGEMENT, 0));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(GetNthClientInitiatedId(0),
+ QUIC_RST_ACKNOWLEDGEMENT));
visitor_->OnRstStream(rst);
// If we were tracking, we'd probably want to reject this because it's data
@@ -322,12 +307,8 @@ TEST_P(QuicServerSessionBaseTest, MaxOpenStreams) {
// Now violate the server's internal stream limit.
stream_id += QuicSpdySessionPeer::NextStreamId(*session_);
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
- if (session_->use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_, OnStreamReset(stream_id, QUIC_REFUSED_STREAM));
- } else {
- EXPECT_CALL(*connection_, SendRstStream(stream_id, QUIC_REFUSED_STREAM, 0));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(stream_id, QUIC_REFUSED_STREAM));
// Even if the connection remains open, the stream creation should fail.
EXPECT_FALSE(QuicServerSessionBasePeer::GetOrCreateDynamicStream(
session_.get(), stream_id));
@@ -424,10 +405,20 @@ TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) {
const QuicString serving_region = "not a real region";
session_->set_serving_region(serving_region);
+ if (GetQuicReloadableFlag(quic_register_streams_early2) &&
+ GetQuicReloadableFlag(quic_register_static_streams)) {
+ session_->UnregisterStreamPriority(kHeadersStreamId, /*is_static=*/true);
+ }
+ QuicServerSessionBasePeer::SetCryptoStream(session_.get(), nullptr);
MockQuicCryptoServerStream* crypto_stream =
new MockQuicCryptoServerStream(&crypto_config_, &compressed_certs_cache_,
session_.get(), &stream_helper_);
QuicServerSessionBasePeer::SetCryptoStream(session_.get(), crypto_stream);
+ if (GetQuicReloadableFlag(quic_register_streams_early2) &&
+ GetQuicReloadableFlag(quic_register_static_streams)) {
+ session_->RegisterStreamPriority(kHeadersStreamId, /*is_static=*/true,
+ QuicStream::kDefaultPriority);
+ }
// Set some initial bandwidth values.
QuicSentPacketManager* sent_packet_manager =
@@ -474,7 +465,7 @@ TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) {
// Bandwidth estimate has now changed sufficiently, enough time has passed,
// and enough packets have been sent.
SerializedPacket packet(1 + kMinPacketsBetweenServerConfigUpdates,
- PACKET_6BYTE_PACKET_NUMBER, nullptr, 1000, false,
+ PACKET_4BYTE_PACKET_NUMBER, nullptr, 1000, false,
false);
sent_packet_manager->OnPacketSent(&packet, 0, now, NOT_RETRANSMISSION,
HAS_RETRANSMITTABLE_DATA);
@@ -615,7 +606,7 @@ TEST_P(StreamMemberLifetimeTest, Basic) {
QuicString(chlo.GetSerialized(Perspective::IS_CLIENT)
.AsStringPiece()
.as_string()),
- PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER,
+ PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER,
&packet_version_list));
EXPECT_CALL(stream_helper_, CanAcceptClientHello(_, _, _))
diff --git a/chromium/net/quic/core/quic_session.cc b/chromium/net/quic/core/quic_session.cc
index 636e2ed8ccc..91157d7db7f 100644
--- a/chromium/net/quic/core/quic_session.cc
+++ b/chromium/net/quic/core/quic_session.cc
@@ -17,13 +17,15 @@
#include "net/quic/platform/api/quic_str_cat.h"
#include "net/quic/platform/api/quic_string.h"
+using net::SpdyPriority;
+
namespace net {
namespace {
// Stateless reset token used in IETF public reset packet.
// TODO(fayang): use a real stateless reset token instead of a hard code one.
-const uint128 kStatelessResetToken = 1010101;
+const QuicUint128 kStatelessResetToken = 1010101;
} // namespace
@@ -35,6 +37,11 @@ QuicSession::QuicSession(QuicConnection* connection,
const QuicConfig& config)
: connection_(connection),
visitor_(owner),
+ register_streams_early_(
+ GetQuicReloadableFlag(quic_register_streams_early2)),
+ write_blocked_streams_(
+ GetQuicReloadableFlag(quic_register_static_streams) &&
+ register_streams_early_),
config_(config),
max_open_outgoing_streams_(kDefaultMaxStreamsPerConnection),
max_open_incoming_streams_(config_.GetMaxIncomingDynamicStreamsToSend()),
@@ -56,12 +63,9 @@ QuicSession::QuicSession(QuicConnection* connection,
currently_writing_stream_id_(0),
goaway_sent_(false),
goaway_received_(false),
- control_frame_manager_(this),
- can_use_slices_(GetQuicReloadableFlag(quic_use_mem_slices)),
- session_unblocks_stream_(
- GetQuicReloadableFlag(quic_streams_unblocked_by_session2)) {
- if (use_control_frame_manager()) {
- QUIC_FLAG_COUNT(quic_reloadable_flag_quic_use_control_frame_manager);
+ control_frame_manager_(this) {
+ if (register_streams_early()) {
+ QUIC_FLAG_COUNT(quic_reloadable_flag_quic_register_streams_early2);
}
}
@@ -212,6 +216,8 @@ bool QuicSession::AllowSelfAddressChange() const {
return false;
}
+void QuicSession::OnForwardProgressConfirmed() {}
+
void QuicSession::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
// Stream may be closed by the time we receive a WINDOW_UPDATE, so we can't
// assume that it still exists.
@@ -299,35 +305,27 @@ void QuicSession::OnCanWrite() {
// streams become pending, WillingAndAbleToWrite will be true, which will
// cause the connection to request resumption before yielding to other
// connections.
- size_t num_writes = write_blocked_streams_.NumBlockedStreams();
- if (flow_controller_.IsBlocked()) {
- // If we are connection level flow control blocked, then only allow the
- // crypto and headers streams to try writing as all other streams will be
- // blocked.
- num_writes = 0;
- if (write_blocked_streams_.crypto_stream_blocked()) {
- num_writes += 1;
- }
- if (write_blocked_streams_.headers_stream_blocked()) {
- num_writes += 1;
- }
- }
- if (num_writes == 0 && (!use_control_frame_manager() ||
- !control_frame_manager_.WillingToWrite())) {
+ // If we are connection level flow control blocked, then only allow the
+ // crypto and headers streams to try writing as all other streams will be
+ // blocked.
+ size_t num_writes = flow_controller_.IsBlocked()
+ ? write_blocked_streams_.NumBlockedSpecialStreams()
+ : write_blocked_streams_.NumBlockedStreams();
+ if (num_writes == 0 && !control_frame_manager_.WillingToWrite()) {
return;
}
QuicConnection::ScopedPacketFlusher flusher(
connection_, QuicConnection::SEND_ACK_IF_QUEUED);
- if (use_control_frame_manager() && control_frame_manager_.WillingToWrite()) {
+ if (control_frame_manager_.WillingToWrite()) {
control_frame_manager_.OnCanWrite();
}
for (size_t i = 0; i < num_writes; ++i) {
- if (!(write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
+ if (!(write_blocked_streams_.HasWriteBlockedSpecialStream() ||
write_blocked_streams_.HasWriteBlockedDataStreams())) {
// Writing one stream removed another!? Something's broken.
QUIC_BUG << "WriteBlockedStream is missing";
- RecordInternalErrorLocation(QUIC_SESSION_1);
+ RecordInternalErrorLocation(QUIC_SESSION_ON_CAN_WRITE);
connection_->CloseConnection(QUIC_INTERNAL_ERROR,
"WriteBlockedStream is missing",
ConnectionCloseBehavior::SILENT_CLOSE);
@@ -361,10 +359,9 @@ bool QuicSession::WillingAndAbleToWrite() const {
// 3) If the crypto or headers streams are blocked, or
// 4) connection is not flow control blocked and there are write blocked
// streams.
- return (use_control_frame_manager() &&
- control_frame_manager_.WillingToWrite()) ||
+ return control_frame_manager_.WillingToWrite() ||
!streams_with_pending_retransmission_.empty() ||
- write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
+ write_blocked_streams_.HasWriteBlockedSpecialStream() ||
(!flow_controller_.IsBlocked() &&
write_blocked_streams_.HasWriteBlockedDataStreams());
}
@@ -372,7 +369,7 @@ bool QuicSession::WillingAndAbleToWrite() const {
bool QuicSession::HasPendingHandshake() const {
return QuicContainsKey(streams_with_pending_retransmission_,
kCryptoStreamId) ||
- write_blocked_streams_.crypto_stream_blocked();
+ write_blocked_streams_.IsStreamBlocked(kCryptoStreamId);
}
bool QuicSession::HasOpenDynamicStreams() const {
@@ -398,7 +395,7 @@ QuicConsumedData QuicSession::WritevData(QuicStream* stream,
// seems like a reasonable mitigation.
if (id == kCryptoStreamId && stream != GetMutableCryptoStream()) {
QUIC_BUG << "Stream id mismatch";
- RecordInternalErrorLocation(QUIC_SESSION_2);
+ RecordInternalErrorLocation(QUIC_SESSION_WRITEV_DATA);
connection_->CloseConnection(
QUIC_INTERNAL_ERROR,
"Non-crypto stream attempted to write data as crypto stream.",
@@ -420,7 +417,6 @@ QuicConsumedData QuicSession::WritevData(QuicStream* stream,
}
bool QuicSession::WriteControlFrame(const QuicFrame& frame) {
- DCHECK(use_control_frame_manager());
return connection_->SendControlFrame(frame);
}
@@ -434,12 +430,8 @@ void QuicSession::SendRstStream(QuicStreamId id,
if (connection()->connected()) {
// Only send a RST_STREAM frame if still connected.
- if (use_control_frame_manager()) {
- control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written);
- connection_->OnStreamReset(id, error);
- } else {
- connection_->SendRstStream(id, error, bytes_written);
- }
+ control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written);
+ connection_->OnStreamReset(id, error);
}
CloseStreamInner(id, true);
}
@@ -450,23 +442,16 @@ void QuicSession::SendGoAway(QuicErrorCode error_code,
return;
}
goaway_sent_ = true;
- if (use_control_frame_manager()) {
- control_frame_manager_.WriteOrBufferGoAway(
- error_code, largest_peer_created_stream_id_, reason);
- } else {
- connection_->SendGoAway(error_code, largest_peer_created_stream_id_,
- reason);
- }
+ control_frame_manager_.WriteOrBufferGoAway(
+ error_code, largest_peer_created_stream_id_, reason);
}
void QuicSession::SendBlocked(QuicStreamId id) {
- DCHECK(use_control_frame_manager());
control_frame_manager_.WriteOrBufferBlocked(id);
}
void QuicSession::SendWindowUpdate(QuicStreamId id,
QuicStreamOffset byte_offset) {
- DCHECK(use_control_frame_manager());
control_frame_manager_.WriteOrBufferWindowUpdate(id, byte_offset);
}
@@ -484,14 +469,14 @@ void QuicSession::InsertLocallyClosedStreamsHighestOffset(
}
void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool locally_reset) {
- QUIC_DLOG(INFO) << ENDPOINT << "Closing stream " << stream_id;
+ QUIC_DVLOG(1) << ENDPOINT << "Closing stream " << stream_id;
DynamicStreamMap::iterator it = dynamic_stream_map_.find(stream_id);
if (it == dynamic_stream_map_.end()) {
// When CloseStreamInner has been called recursively (via
// QuicStream::OnClose), the stream will already have been deleted
// from stream_map_, so return immediately.
- QUIC_DLOG(INFO) << ENDPOINT << "Stream is already closed: " << stream_id;
+ QUIC_DVLOG(1) << ENDPOINT << "Stream is already closed: " << stream_id;
return;
}
QuicStream* stream = it->second.get();
@@ -752,14 +737,48 @@ void QuicSession::OnCryptoHandshakeMessageSent(
void QuicSession::OnCryptoHandshakeMessageReceived(
const CryptoHandshakeMessage& /*message*/) {}
+void QuicSession::RegisterStreamPriority(QuicStreamId id,
+ bool is_static,
+ SpdyPriority priority) {
+ // Static streams should not be registered unless register_streams_early
+ // is true.
+ DCHECK(register_streams_early() || !is_static);
+ // Static streams do not need to be registered with the write blocked list,
+ // since it has special handling for them.
+ if (!write_blocked_streams()->register_static_streams() &&
+ register_streams_early() && is_static) {
+ return;
+ }
+
+ write_blocked_streams()->RegisterStream(id, is_static, priority);
+}
+
+void QuicSession::UnregisterStreamPriority(QuicStreamId id, bool is_static) {
+ // Static streams should not be registered unless register_streams_early
+ // is true.
+ DCHECK(register_streams_early() || !is_static);
+ // Static streams do not need to be registered with the write blocked list,
+ // since it has special handling for them.
+ if (!write_blocked_streams()->register_static_streams() &&
+ register_streams_early() && is_static) {
+ return;
+ }
+ write_blocked_streams()->UnregisterStream(id, is_static);
+}
+
+void QuicSession::UpdateStreamPriority(QuicStreamId id,
+ SpdyPriority new_priority) {
+ write_blocked_streams()->UpdateStreamPriority(id, new_priority);
+}
+
QuicConfig* QuicSession::config() {
return &config_;
}
void QuicSession::ActivateStream(std::unique_ptr<QuicStream> stream) {
QuicStreamId stream_id = stream->id();
- QUIC_DLOG(INFO) << ENDPOINT << "num_streams: " << dynamic_stream_map_.size()
- << ". activating " << stream_id;
+ QUIC_DVLOG(1) << ENDPOINT << "num_streams: " << dynamic_stream_map_.size()
+ << ". activating " << stream_id;
DCHECK(!QuicContainsKey(dynamic_stream_map_, stream_id));
DCHECK(!QuicContainsKey(static_stream_map_, stream_id));
dynamic_stream_map_[stream_id] = std::move(stream);
@@ -837,14 +856,6 @@ bool QuicSession::ShouldYield(QuicStreamId stream_id) {
return write_blocked_streams()->ShouldYield(stream_id);
}
-void QuicSession::NeuterUnencryptedStreamData() {
- QuicCryptoStream* crypto_stream = GetMutableCryptoStream();
- crypto_stream->NeuterUnencryptedStreamData();
- if (!crypto_stream->HasPendingRetransmission()) {
- streams_with_pending_retransmission_.erase(kCryptoStreamId);
- }
-}
-
QuicStream* QuicSession::GetOrCreateDynamicStream(
const QuicStreamId stream_id) {
DCHECK(!QuicContainsKey(static_stream_map_, stream_id))
@@ -927,9 +938,9 @@ size_t QuicSession::GetNumOpenIncomingStreams() const {
}
size_t QuicSession::GetNumOpenOutgoingStreams() const {
- CHECK_GE(GetNumDynamicOutgoingStreams() +
- GetNumLocallyClosedOutgoingStreamsHighestOffset(),
- GetNumDrainingOutgoingStreams());
+ DCHECK_GE(GetNumDynamicOutgoingStreams() +
+ GetNumLocallyClosedOutgoingStreamsHighestOffset(),
+ GetNumDrainingOutgoingStreams());
return GetNumDynamicOutgoingStreams() +
GetNumLocallyClosedOutgoingStreamsHighestOffset() -
GetNumDrainingOutgoingStreams();
@@ -951,12 +962,11 @@ void QuicSession::MarkConnectionLevelWriteBlocked(QuicStreamId id) {
}
bool QuicSession::HasDataToWrite() const {
- return write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
+ return write_blocked_streams_.HasWriteBlockedSpecialStream() ||
write_blocked_streams_.HasWriteBlockedDataStreams() ||
connection_->HasQueuedData() ||
!streams_with_pending_retransmission_.empty() ||
- (use_control_frame_manager() &&
- control_frame_manager_.WillingToWrite());
+ control_frame_manager_.WillingToWrite();
}
void QuicSession::PostProcessAfterData() {
@@ -965,13 +975,16 @@ void QuicSession::PostProcessAfterData() {
void QuicSession::OnAckNeedsRetransmittableFrame() {
flow_controller_.SendWindowUpdate();
- if (use_control_frame_manager() && !control_frame_manager_.WillingToWrite()) {
+ if (GetQuicReloadableFlag(quic_remove_redundant_ping)) {
+ QUIC_FLAG_COUNT(quic_reloadable_flag_quic_remove_redundant_ping);
+ return;
+ }
+ if (!control_frame_manager_.WillingToWrite()) {
SendPing();
}
}
void QuicSession::SendPing() {
- DCHECK(use_control_frame_manager());
control_frame_manager_.WritePing();
}
@@ -1049,10 +1062,7 @@ QuicStream* QuicSession::GetStream(QuicStreamId id) const {
bool QuicSession::OnFrameAcked(const QuicFrame& frame,
QuicTime::Delta ack_delay_time) {
if (frame.type != STREAM_FRAME) {
- if (use_control_frame_manager()) {
- return control_frame_manager_.OnControlFrameAcked(frame);
- }
- return false;
+ return control_frame_manager_.OnControlFrameAcked(frame);
}
bool new_stream_data_acked = false;
QuicStream* stream = GetStream(frame.stream_frame->stream_id);
@@ -1073,7 +1083,7 @@ void QuicSession::OnStreamFrameRetransmitted(const QuicStreamFrame& frame) {
if (stream == nullptr) {
QUIC_BUG << "Stream: " << frame.stream_id << " is closed when " << frame
<< " is retransmitted.";
- RecordInternalErrorLocation(QUIC_SESSION_3);
+ RecordInternalErrorLocation(QUIC_SESSION_STREAM_FRAME_RETRANSMITTED);
connection()->CloseConnection(
QUIC_INTERNAL_ERROR, "Attempt to retransmit frame of a closed stream",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -1085,9 +1095,7 @@ void QuicSession::OnStreamFrameRetransmitted(const QuicStreamFrame& frame) {
void QuicSession::OnFrameLost(const QuicFrame& frame) {
if (frame.type != STREAM_FRAME) {
- if (use_control_frame_manager()) {
- control_frame_manager_.OnControlFrameLost(frame);
- }
+ control_frame_manager_.OnControlFrameLost(frame);
return;
}
QuicStream* stream = GetStream(frame.stream_frame->stream_id);
@@ -1112,8 +1120,7 @@ void QuicSession::RetransmitFrames(const QuicFrames& frames,
SetTransmissionType(type);
for (const QuicFrame& frame : frames) {
if (frame.type != STREAM_FRAME) {
- if (use_control_frame_manager() &&
- !control_frame_manager_.RetransmitControlFrame(frame)) {
+ if (!control_frame_manager_.RetransmitControlFrame(frame)) {
break;
}
continue;
@@ -1130,10 +1137,7 @@ void QuicSession::RetransmitFrames(const QuicFrames& frames,
bool QuicSession::IsFrameOutstanding(const QuicFrame& frame) const {
if (frame.type != STREAM_FRAME) {
- if (use_control_frame_manager()) {
- return control_frame_manager_.IsControlFrameOutstanding(frame);
- }
- return false;
+ return control_frame_manager_.IsControlFrameOutstanding(frame);
}
QuicStream* stream = GetStream(frame.stream_frame->stream_id);
return stream != nullptr &&
@@ -1160,7 +1164,7 @@ bool QuicSession::WriteStreamData(QuicStreamId id,
return stream->WriteStreamData(offset, data_length, writer);
}
-uint128 QuicSession::GetStatelessResetToken() const {
+QuicUint128 QuicSession::GetStatelessResetToken() const {
return kStatelessResetToken;
}
@@ -1180,8 +1184,7 @@ bool QuicSession::RetransmitLostData() {
streams_with_pending_retransmission_.erase(kCryptoStreamId);
}
}
- if (use_control_frame_manager() &&
- control_frame_manager_.HasPendingRetransmission()) {
+ if (control_frame_manager_.HasPendingRetransmission()) {
SetTransmissionType(LOSS_RETRANSMISSION);
control_frame_manager_.OnCanWrite();
if (control_frame_manager_.HasPendingRetransmission()) {
@@ -1229,10 +1232,6 @@ void QuicSession::SetTransmissionType(TransmissionType type) {
connection_->SetTransmissionType(type);
}
-bool QuicSession::use_control_frame_manager() const {
- return connection_->use_control_frame_manager();
-}
-
bool QuicSession::session_decides_what_to_write() const {
return connection_->session_decides_what_to_write();
}
diff --git a/chromium/net/quic/core/quic_session.h b/chromium/net/quic/core/quic_session.h
index a1db9b35a8e..c853834d134 100644
--- a/chromium/net/quic/core/quic_session.h
+++ b/chromium/net/quic/core/quic_session.h
@@ -14,7 +14,6 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "net/base/int128.h"
#include "net/quic/core/quic_connection.h"
#include "net/quic/core/quic_control_frame_manager.h"
#include "net/quic/core/quic_crypto_stream.h"
@@ -117,6 +116,7 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
bool HasOpenDynamicStreams() const override;
void OnPathDegrading() override;
bool AllowSelfAddressChange() const override;
+ void OnForwardProgressConfirmed() override;
// QuicStreamFrameDataProducer
bool WriteStreamData(QuicStreamId id,
@@ -200,6 +200,17 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
virtual void OnCryptoHandshakeMessageReceived(
const CryptoHandshakeMessage& message);
+ // Called by the stream on creation to set priority in the write blocked list.
+ virtual void RegisterStreamPriority(QuicStreamId id,
+ bool is_static,
+ SpdyPriority priority);
+ // Called by the stream on deletion to clear priority crom the write blocked
+ // list.
+ virtual void UnregisterStreamPriority(QuicStreamId id, bool is_static);
+ // Called by the stream on SetPriority to update priority on the write blocked
+ // list.
+ virtual void UpdateStreamPriority(QuicStreamId id, SpdyPriority new_priority);
+
// Returns mutable config for this session. Returned config is owned
// by QuicSession.
QuicConfig* config();
@@ -294,17 +305,10 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
// Returns true if this stream should yield writes to another blocked stream.
bool ShouldYield(QuicStreamId stream_id);
- // Called to cancel retransmission of unencrypted stream data.
- void NeuterUnencryptedStreamData();
-
// Set transmission type of next sending packets.
void SetTransmissionType(TransmissionType type);
- bool can_use_slices() const { return can_use_slices_; }
-
- bool session_unblocks_stream() const { return session_unblocks_stream_; }
-
- bool use_control_frame_manager() const;
+ bool register_streams_early() const { return register_streams_early_; }
bool session_decides_what_to_write() const;
@@ -424,7 +428,7 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
// Returns a stateless reset token which will be included in the public reset
// packet.
- virtual uint128 GetStatelessResetToken() const;
+ virtual QuicUint128 GetStatelessResetToken() const;
QuicControlFrameManager& control_frame_manager() {
return control_frame_manager_;
@@ -474,8 +478,15 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
// May be null.
Visitor* visitor_;
- ClosedStreams closed_streams_;
+ // Latched value of quic_reloadable_flag_quic_register_streams_early2.
+ const bool register_streams_early_;
+
+ // A list of streams which need to write more data. Stream register
+ // themselves in their constructor, and unregisterm themselves in their
+ // destructors, so the write blocked list must outlive all streams.
+ QuicWriteBlockedList write_blocked_streams_;
+ ClosedStreams closed_streams_;
// Streams which are closed, but need to be kept alive. Currently, the only
// reason is the stream's sent data (including FIN) does not get fully acked.
ZombieStreamMap zombie_streams_;
@@ -507,9 +518,6 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
// been consumed.
QuicUnorderedSet<QuicStreamId> draining_streams_;
- // A list of streams which need to write more data.
- QuicWriteBlockedList write_blocked_streams_;
-
QuicStreamId largest_peer_created_stream_id_;
// A counter for peer initiated streams which are in the dynamic_stream_map_.
@@ -540,18 +548,11 @@ class QUIC_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface,
QuicControlFrameManager control_frame_manager_;
- // QUIC stream can take ownership of application data provided in reference
- // counted memory to avoid data copy.
- const bool can_use_slices_;
-
// TODO(fayang): switch to linked_hash_set when chromium supports it. The bool
// is not used here.
// List of streams with pending retransmissions.
QuicLinkedHashMap<QuicStreamId, bool> streams_with_pending_retransmission_;
- // Latched value of quic_reloadable_flag_quic_streams_unblocked_by_session2.
- const bool session_unblocks_stream_;
-
DISALLOW_COPY_AND_ASSIGN(QuicSession);
};
diff --git a/chromium/net/quic/core/quic_session_test.cc b/chromium/net/quic/core/quic_session_test.cc
new file mode 100644
index 00000000000..abc67d61a8c
--- /dev/null
+++ b/chromium/net/quic/core/quic_session_test.cc
@@ -0,0 +1,1427 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/quic_session.h"
+
+#include <cstdint>
+#include <set>
+#include <utility>
+
+#include "base/callback.h"
+#include "base/rand_util.h"
+#include "build/build_config.h"
+#include "net/quic/core/crypto/crypto_protocol.h"
+#include "net/quic/core/crypto/null_encrypter.h"
+#include "net/quic/core/quic_crypto_stream.h"
+#include "net/quic/core/quic_data_writer.h"
+#include "net/quic/core/quic_packets.h"
+#include "net/quic/core/quic_stream.h"
+#include "net/quic/core/quic_utils.h"
+#include "net/quic/platform/api/quic_flags.h"
+#include "net/quic/platform/api/quic_map_util.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
+#include "net/quic/platform/api/quic_str_cat.h"
+#include "net/quic/platform/api/quic_string.h"
+#include "net/quic/platform/api/quic_string_piece.h"
+#include "net/quic/platform/api/quic_test.h"
+#include "net/quic/test_tools/quic_config_peer.h"
+#include "net/quic/test_tools/quic_connection_peer.h"
+#include "net/quic/test_tools/quic_flow_controller_peer.h"
+#include "net/quic/test_tools/quic_session_peer.h"
+#include "net/quic/test_tools/quic_stream_peer.h"
+#include "net/quic/test_tools/quic_stream_send_buffer_peer.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+#include "net/test/gtest_util.h"
+#include "testing/gmock_mutant.h"
+
+using net::kV3HighestPriority;
+using net::SpdyPriority;
+using testing::_;
+using testing::AtLeast;
+using testing::InSequence;
+using testing::Invoke;
+using testing::Return;
+using testing::StrictMock;
+
+namespace net {
+namespace test {
+namespace {
+
+class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker {
+ public:
+ explicit TestCryptoStream(QuicSession* session)
+ : QuicCryptoStream(session),
+ QuicCryptoHandshaker(this, session),
+ encryption_established_(false),
+ handshake_confirmed_(false),
+ params_(new QuicCryptoNegotiatedParameters) {}
+
+ void OnHandshakeMessage(const CryptoHandshakeMessage& /*message*/) override {
+ encryption_established_ = true;
+ handshake_confirmed_ = true;
+ CryptoHandshakeMessage msg;
+ QuicString error_details;
+ session()->config()->SetInitialStreamFlowControlWindowToSend(
+ kInitialStreamFlowControlWindowForTest);
+ session()->config()->SetInitialSessionFlowControlWindowToSend(
+ kInitialSessionFlowControlWindowForTest);
+ session()->config()->ToHandshakeMessage(&msg);
+ const QuicErrorCode error =
+ session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
+ EXPECT_EQ(QUIC_NO_ERROR, error);
+ session()->OnConfigNegotiated();
+ session()->connection()->SetDefaultEncryptionLevel(
+ ENCRYPTION_FORWARD_SECURE);
+ session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
+ }
+
+ // QuicCryptoStream implementation
+ bool encryption_established() const override {
+ return encryption_established_;
+ }
+ bool handshake_confirmed() const override { return handshake_confirmed_; }
+ const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
+ const override {
+ return *params_;
+ }
+ CryptoMessageParser* crypto_message_parser() override {
+ return QuicCryptoHandshaker::crypto_message_parser();
+ }
+
+ MOCK_METHOD0(OnCanWrite, void());
+
+ MOCK_CONST_METHOD0(HasPendingRetransmission, bool());
+
+ private:
+ using QuicCryptoStream::session;
+
+ bool encryption_established_;
+ bool handshake_confirmed_;
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
+};
+
+class TestStream : public QuicStream {
+ public:
+ TestStream(QuicStreamId id, QuicSession* session)
+ : QuicStream(id, session, /*is_static=*/false) {
+ if (!session->register_streams_early()) {
+ session->RegisterStreamPriority(id, false, QuicStream::kDefaultPriority);
+ }
+ }
+
+ ~TestStream() override {
+ if (!session()->register_streams_early()) {
+ session()->UnregisterStreamPriority(id(), false);
+ }
+ }
+
+ using QuicStream::CloseWriteSide;
+
+ void OnDataAvailable() override {}
+
+ MOCK_METHOD0(OnCanWrite, void());
+ MOCK_METHOD3(RetransmitStreamData,
+ bool(QuicStreamOffset, QuicByteCount, bool));
+
+ MOCK_CONST_METHOD0(HasPendingRetransmission, bool());
+};
+
+class TestSession : public QuicSession {
+ public:
+ explicit TestSession(QuicConnection* connection)
+ : QuicSession(connection, nullptr, DefaultQuicConfig()),
+ crypto_stream_(this),
+ writev_consumes_all_data_(false) {
+ Initialize();
+ this->connection()->SetEncrypter(
+ ENCRYPTION_FORWARD_SECURE,
+ QuicMakeUnique<NullEncrypter>(connection->perspective()));
+ }
+
+ ~TestSession() override { delete connection(); }
+
+ TestCryptoStream* GetMutableCryptoStream() override {
+ return &crypto_stream_;
+ }
+
+ const TestCryptoStream* GetCryptoStream() const override {
+ return &crypto_stream_;
+ }
+
+ TestStream* CreateOutgoingDynamicStream() override {
+ TestStream* stream = new TestStream(GetNextOutgoingStreamId(), this);
+ ActivateStream(QuicWrapUnique(stream));
+ return stream;
+ }
+
+ TestStream* CreateIncomingDynamicStream(QuicStreamId id) override {
+ // Enforce the limit on the number of open streams.
+ if (GetNumOpenIncomingStreams() + 1 > max_open_incoming_streams()) {
+ connection()->CloseConnection(
+ QUIC_TOO_MANY_OPEN_STREAMS, "Too many streams!",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return nullptr;
+ } else {
+ TestStream* stream = new TestStream(id, this);
+ ActivateStream(QuicWrapUnique(stream));
+ return stream;
+ }
+ }
+
+ bool IsClosedStream(QuicStreamId id) {
+ return QuicSession::IsClosedStream(id);
+ }
+
+ QuicStream* GetOrCreateDynamicStream(QuicStreamId stream_id) {
+ return QuicSession::GetOrCreateDynamicStream(stream_id);
+ }
+
+ QuicConsumedData WritevData(QuicStream* stream,
+ QuicStreamId id,
+ size_t write_length,
+ QuicStreamOffset offset,
+ StreamSendingState state) override {
+ bool fin = state != NO_FIN;
+ QuicConsumedData consumed(write_length, fin);
+ if (!writev_consumes_all_data_) {
+ consumed =
+ QuicSession::WritevData(stream, id, write_length, offset, state);
+ }
+ if (fin && consumed.fin_consumed) {
+ stream->set_fin_sent(true);
+ }
+ QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream(
+ id, consumed.bytes_consumed);
+ return consumed;
+ }
+
+ void set_writev_consumes_all_data(bool val) {
+ writev_consumes_all_data_ = val;
+ }
+
+ QuicConsumedData SendStreamData(QuicStream* stream) {
+ struct iovec iov;
+ if (stream->id() != kCryptoStreamId) {
+ this->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ }
+ MakeIOVector("not empty", &iov);
+ QuicStreamPeer::SendBuffer(stream).SaveStreamData(&iov, 1, 0, 9);
+ QuicConsumedData consumed = WritevData(stream, stream->id(), 9, 0, FIN);
+ QuicStreamPeer::SendBuffer(stream).OnStreamDataConsumed(
+ consumed.bytes_consumed);
+ return consumed;
+ }
+
+ bool ClearControlFrame(const QuicFrame& frame) {
+ DeleteFrame(&const_cast<QuicFrame&>(frame));
+ return true;
+ }
+
+ QuicConsumedData SendLargeFakeData(QuicStream* stream, int bytes) {
+ DCHECK(writev_consumes_all_data_);
+ return WritevData(stream, stream->id(), bytes, 0, FIN);
+ }
+
+ using QuicSession::closed_streams;
+ using QuicSession::next_outgoing_stream_id;
+ using QuicSession::PostProcessAfterData;
+ using QuicSession::zombie_streams;
+
+ private:
+ StrictMock<TestCryptoStream> crypto_stream_;
+
+ bool writev_consumes_all_data_;
+};
+
+class QuicSessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
+ protected:
+ explicit QuicSessionTestBase(Perspective perspective)
+ : connection_(
+ new StrictMock<MockQuicConnection>(&helper_,
+ &alarm_factory_,
+ perspective,
+ SupportedVersions(GetParam()))),
+ session_(connection_) {
+ session_.config()->SetInitialStreamFlowControlWindowToSend(
+ kInitialStreamFlowControlWindowForTest);
+ session_.config()->SetInitialSessionFlowControlWindowToSend(
+ kInitialSessionFlowControlWindowForTest);
+ connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
+ TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
+ EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
+ .Times(testing::AnyNumber());
+ }
+
+ void CheckClosedStreams() {
+ for (QuicStreamId i = kCryptoStreamId; i < 100; i++) {
+ if (!QuicContainsKey(closed_streams_, i)) {
+ EXPECT_FALSE(session_.IsClosedStream(i)) << " stream id: " << i;
+ } else {
+ EXPECT_TRUE(session_.IsClosedStream(i)) << " stream id: " << i;
+ }
+ }
+ }
+
+ void CloseStream(QuicStreamId id) {
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(id, _));
+ session_.CloseStream(id);
+ closed_streams_.insert(id);
+ }
+
+ QuicTransportVersion transport_version() const {
+ return connection_->transport_version();
+ }
+
+ QuicStreamId GetNthClientInitiatedId(int n) { return 3 + 2 * n; }
+
+ QuicStreamId GetNthServerInitiatedId(int n) { return 2 + 2 * n; }
+
+ MockQuicConnectionHelper helper_;
+ MockAlarmFactory alarm_factory_;
+ StrictMock<MockQuicConnection>* connection_;
+ TestSession session_;
+ std::set<QuicStreamId> closed_streams_;
+};
+
+class QuicSessionTestServer : public QuicSessionTestBase {
+ protected:
+ QuicSessionTestServer() : QuicSessionTestBase(Perspective::IS_SERVER) {}
+};
+
+INSTANTIATE_TEST_CASE_P(Tests,
+ QuicSessionTestServer,
+ ::testing::ValuesIn(AllSupportedVersions()));
+
+TEST_P(QuicSessionTestServer, PeerAddress) {
+ EXPECT_EQ(QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort),
+ session_.peer_address());
+}
+
+TEST_P(QuicSessionTestServer, SelfAddress) {
+ EXPECT_EQ(QuicSocketAddress(), session_.self_address());
+}
+
+TEST_P(QuicSessionTestServer, IsCryptoHandshakeConfirmed) {
+ EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed());
+ CryptoHandshakeMessage message;
+ session_.GetMutableCryptoStream()->OnHandshakeMessage(message);
+ EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed());
+}
+
+TEST_P(QuicSessionTestServer, IsClosedStreamDefault) {
+ // Ensure that no streams are initially closed.
+ for (QuicStreamId i = kCryptoStreamId; i < 100; i++) {
+ EXPECT_FALSE(session_.IsClosedStream(i)) << "stream id: " << i;
+ }
+}
+
+TEST_P(QuicSessionTestServer, AvailableStreams) {
+ ASSERT_TRUE(session_.GetOrCreateDynamicStream(9) != nullptr);
+ // Both 5 and 7 should be available.
+ EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 5));
+ EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 7));
+ ASSERT_TRUE(session_.GetOrCreateDynamicStream(7) != nullptr);
+ ASSERT_TRUE(session_.GetOrCreateDynamicStream(5) != nullptr);
+}
+
+TEST_P(QuicSessionTestServer, IsClosedStreamLocallyCreated) {
+ TestStream* stream2 = session_.CreateOutgoingDynamicStream();
+ EXPECT_EQ(GetNthServerInitiatedId(0), stream2->id());
+ TestStream* stream4 = session_.CreateOutgoingDynamicStream();
+ EXPECT_EQ(GetNthServerInitiatedId(1), stream4->id());
+
+ CheckClosedStreams();
+ CloseStream(GetNthServerInitiatedId(0));
+ CheckClosedStreams();
+ CloseStream(GetNthServerInitiatedId(1));
+ CheckClosedStreams();
+}
+
+TEST_P(QuicSessionTestServer, IsClosedStreamPeerCreated) {
+ QuicStreamId stream_id1 = GetNthClientInitiatedId(0);
+ QuicStreamId stream_id2 = GetNthClientInitiatedId(1);
+ session_.GetOrCreateDynamicStream(stream_id1);
+ session_.GetOrCreateDynamicStream(stream_id2);
+
+ CheckClosedStreams();
+ CloseStream(stream_id1);
+ CheckClosedStreams();
+ CloseStream(stream_id2);
+ // Create a stream, and make another available.
+ QuicStream* stream3 = session_.GetOrCreateDynamicStream(stream_id2 + 4);
+ CheckClosedStreams();
+ // Close one, but make sure the other is still not closed
+ CloseStream(stream3->id());
+ CheckClosedStreams();
+}
+
+TEST_P(QuicSessionTestServer, MaximumAvailableOpenedStreams) {
+ QuicStreamId stream_id = GetNthClientInitiatedId(0);
+ session_.GetOrCreateDynamicStream(stream_id);
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
+ EXPECT_NE(nullptr,
+ session_.GetOrCreateDynamicStream(
+ stream_id + 2 * (session_.max_open_incoming_streams() - 1)));
+}
+
+TEST_P(QuicSessionTestServer, TooManyAvailableStreams) {
+ QuicStreamId stream_id1 = GetNthClientInitiatedId(0);
+ QuicStreamId stream_id2;
+ EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id1));
+ // A stream ID which is too large to create.
+ stream_id2 = GetNthClientInitiatedId(2 * session_.MaxAvailableStreams() + 4);
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_TOO_MANY_AVAILABLE_STREAMS, _, _));
+ EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(stream_id2));
+}
+
+TEST_P(QuicSessionTestServer, 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);
+ QuicStreamId stream_id = GetNthClientInitiatedId(0);
+ // Create one stream.
+ session_.GetOrCreateDynamicStream(stream_id);
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
+ // Create the largest stream ID of a threatened total of 200 streams.
+ session_.GetOrCreateDynamicStream(stream_id + 2 * (200 - 1));
+}
+
+TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) {
+ TestStream* stream2 = session_.CreateOutgoingDynamicStream();
+ QuicStreamId closed_stream_id = stream2->id();
+ // Close the stream.
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(closed_stream_id, _));
+ stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD);
+ QuicString msg =
+ QuicStrCat("Marking unknown stream ", closed_stream_id, " blocked.");
+ EXPECT_QUIC_BUG(session_.MarkConnectionLevelWriteBlocked(closed_stream_id),
+ msg);
+}
+
+TEST_P(QuicSessionTestServer, OnCanWrite) {
+ session_.set_writev_consumes_all_data(true);
+ TestStream* stream2 = session_.CreateOutgoingDynamicStream();
+ TestStream* stream4 = session_.CreateOutgoingDynamicStream();
+ TestStream* stream6 = session_.CreateOutgoingDynamicStream();
+
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+ session_.MarkConnectionLevelWriteBlocked(stream6->id());
+ session_.MarkConnectionLevelWriteBlocked(stream4->id());
+
+ InSequence s;
+
+ // Reregister, to test the loop limit.
+ EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
+ session_.SendStreamData(stream2);
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+ }));
+ // 2 will get called a second time as it didn't finish its block
+ EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
+ session_.SendStreamData(stream2);
+ }));
+ EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
+ session_.SendStreamData(stream6);
+ }));
+ // 4 will not get called, as we exceeded the loop limit.
+ session_.OnCanWrite();
+ EXPECT_TRUE(session_.WillingAndAbleToWrite());
+}
+
+TEST_P(QuicSessionTestServer, TestBatchedWrites) {
+ session_.set_writev_consumes_all_data(true);
+ TestStream* stream2 = session_.CreateOutgoingDynamicStream();
+ TestStream* stream4 = session_.CreateOutgoingDynamicStream();
+ TestStream* stream6 = session_.CreateOutgoingDynamicStream();
+
+ session_.set_writev_consumes_all_data(true);
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+ session_.MarkConnectionLevelWriteBlocked(stream4->id());
+
+ // With two sessions blocked, we should get two write calls. They should both
+ // go to the first stream as it will only write 6k and mark itself blocked
+ // again.
+ InSequence s;
+ EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
+ session_.SendLargeFakeData(stream2, 6000);
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+ }));
+ EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
+ session_.SendLargeFakeData(stream2, 6000);
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+ }));
+ session_.OnCanWrite();
+
+ // We should get one more call for stream2, at which point it has used its
+ // write quota and we move over to stream 4.
+ EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
+ session_.SendLargeFakeData(stream2, 6000);
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+ }));
+ EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
+ session_.SendLargeFakeData(stream4, 6000);
+ session_.MarkConnectionLevelWriteBlocked(stream4->id());
+ }));
+ session_.OnCanWrite();
+
+ // Now let stream 4 do the 2nd of its 3 writes, but add a block for a high
+ // priority stream 6. 4 should be preempted. 6 will write but *not* block so
+ // will cede back to 4.
+ stream6->SetPriority(kV3HighestPriority);
+ EXPECT_CALL(*stream4, OnCanWrite())
+ .WillOnce(Invoke([this, stream4, stream6]() {
+ session_.SendLargeFakeData(stream4, 6000);
+ session_.MarkConnectionLevelWriteBlocked(stream4->id());
+ session_.MarkConnectionLevelWriteBlocked(stream6->id());
+ }));
+ EXPECT_CALL(*stream6, OnCanWrite())
+ .WillOnce(Invoke([this, stream4, stream6]() {
+ session_.SendStreamData(stream6);
+ session_.SendLargeFakeData(stream4, 6000);
+ }));
+ session_.OnCanWrite();
+
+ // Stream4 alread did 6k worth of writes, so after doing another 12k it should
+ // cede and 2 should resume.
+ EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
+ session_.SendLargeFakeData(stream4, 12000);
+ session_.MarkConnectionLevelWriteBlocked(stream4->id());
+ }));
+ EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
+ session_.SendLargeFakeData(stream2, 6000);
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+ }));
+ session_.OnCanWrite();
+}
+
+TEST_P(QuicSessionTestServer, OnCanWriteBundlesStreams) {
+ // Encryption needs to be established before data can be sent.
+ CryptoHandshakeMessage msg;
+ MockPacketWriter* writer = static_cast<MockPacketWriter*>(
+ QuicConnectionPeer::GetWriter(session_.connection()));
+ session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
+
+ // Drive congestion control manually.
+ MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
+ QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
+
+ TestStream* stream2 = session_.CreateOutgoingDynamicStream();
+ TestStream* stream4 = session_.CreateOutgoingDynamicStream();
+ TestStream* stream6 = session_.CreateOutgoingDynamicStream();
+
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+ session_.MarkConnectionLevelWriteBlocked(stream6->id());
+ session_.MarkConnectionLevelWriteBlocked(stream4->id());
+
+ EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
+ EXPECT_CALL(*send_algorithm, GetCongestionWindow())
+ .WillRepeatedly(Return(kMaxPacketSize * 10));
+ EXPECT_CALL(*send_algorithm, InRecovery()).WillRepeatedly(Return(false));
+ EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
+ session_.SendStreamData(stream2);
+ }));
+ EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
+ session_.SendStreamData(stream4);
+ }));
+ EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
+ session_.SendStreamData(stream6);
+ }));
+
+ // Expect that we only send one packet, the writes from different streams
+ // should be bundled together.
+ EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
+ EXPECT_CALL(*send_algorithm, OnPacketSent(_, _, _, _, _));
+ EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
+ session_.OnCanWrite();
+ EXPECT_FALSE(session_.WillingAndAbleToWrite());
+}
+
+TEST_P(QuicSessionTestServer, OnCanWriteCongestionControlBlocks) {
+ session_.set_writev_consumes_all_data(true);
+ InSequence s;
+
+ // Drive congestion control manually.
+ MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
+ QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
+
+ TestStream* stream2 = session_.CreateOutgoingDynamicStream();
+ TestStream* stream4 = session_.CreateOutgoingDynamicStream();
+ TestStream* stream6 = session_.CreateOutgoingDynamicStream();
+
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+ session_.MarkConnectionLevelWriteBlocked(stream6->id());
+ session_.MarkConnectionLevelWriteBlocked(stream4->id());
+
+ EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
+ EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
+ session_.SendStreamData(stream2);
+ }));
+ EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
+ EXPECT_CALL(*stream6, OnCanWrite()).WillOnce(Invoke([this, stream6]() {
+ session_.SendStreamData(stream6);
+ }));
+ EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(false));
+ // stream4->OnCanWrite is not called.
+
+ session_.OnCanWrite();
+ EXPECT_TRUE(session_.WillingAndAbleToWrite());
+
+ // Still congestion-control blocked.
+ EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(false));
+ session_.OnCanWrite();
+ EXPECT_TRUE(session_.WillingAndAbleToWrite());
+
+ // stream4->OnCanWrite is called once the connection stops being
+ // congestion-control blocked.
+ EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
+ EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
+ session_.SendStreamData(stream4);
+ }));
+ EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
+ session_.OnCanWrite();
+ EXPECT_FALSE(session_.WillingAndAbleToWrite());
+}
+
+TEST_P(QuicSessionTestServer, OnCanWriteWriterBlocks) {
+ // Drive congestion control manually in order to ensure that
+ // application-limited signaling is handled correctly.
+ MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
+ QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
+ EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
+
+ // Drive packet writer manually.
+ MockPacketWriter* writer = static_cast<MockPacketWriter*>(
+ QuicConnectionPeer::GetWriter(session_.connection()));
+ EXPECT_CALL(*writer, IsWriteBlocked()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*writer, IsWriteBlockedDataBuffered())
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(*writer, WritePacket(_, _, _, _, _)).Times(0);
+
+ TestStream* stream2 = session_.CreateOutgoingDynamicStream();
+
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+
+ EXPECT_CALL(*stream2, OnCanWrite()).Times(0);
+ EXPECT_CALL(*send_algorithm, OnApplicationLimited(_)).Times(0);
+
+ session_.OnCanWrite();
+ EXPECT_TRUE(session_.WillingAndAbleToWrite());
+}
+
+TEST_P(QuicSessionTestServer, BufferedHandshake) {
+ session_.set_writev_consumes_all_data(true);
+ EXPECT_FALSE(session_.HasPendingHandshake()); // Default value.
+
+ // Test that blocking other streams does not change our status.
+ TestStream* stream2 = session_.CreateOutgoingDynamicStream();
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+ EXPECT_FALSE(session_.HasPendingHandshake());
+
+ TestStream* stream3 = session_.CreateOutgoingDynamicStream();
+ session_.MarkConnectionLevelWriteBlocked(stream3->id());
+ EXPECT_FALSE(session_.HasPendingHandshake());
+
+ // Blocking (due to buffering of) the Crypto stream is detected.
+ session_.MarkConnectionLevelWriteBlocked(kCryptoStreamId);
+ EXPECT_TRUE(session_.HasPendingHandshake());
+
+ TestStream* stream4 = session_.CreateOutgoingDynamicStream();
+ session_.MarkConnectionLevelWriteBlocked(stream4->id());
+ EXPECT_TRUE(session_.HasPendingHandshake());
+
+ InSequence s;
+ // Force most streams to re-register, which is common scenario when we block
+ // the Crypto stream, and only the crypto stream can "really" write.
+
+ // Due to prioritization, we *should* be asked to write the crypto stream
+ // first.
+ // Don't re-register the crypto stream (which signals complete writing).
+ TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
+ EXPECT_CALL(*crypto_stream, OnCanWrite());
+
+ EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
+ session_.SendStreamData(stream2);
+ }));
+ EXPECT_CALL(*stream3, OnCanWrite()).WillOnce(Invoke([this, stream3]() {
+ session_.SendStreamData(stream3);
+ }));
+ EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
+ session_.SendStreamData(stream4);
+ session_.MarkConnectionLevelWriteBlocked(stream4->id());
+ }));
+
+ session_.OnCanWrite();
+ EXPECT_TRUE(session_.WillingAndAbleToWrite());
+ EXPECT_FALSE(session_.HasPendingHandshake()); // Crypto stream wrote.
+}
+
+TEST_P(QuicSessionTestServer, OnCanWriteWithClosedStream) {
+ session_.set_writev_consumes_all_data(true);
+ TestStream* stream2 = session_.CreateOutgoingDynamicStream();
+ TestStream* stream4 = session_.CreateOutgoingDynamicStream();
+ TestStream* stream6 = session_.CreateOutgoingDynamicStream();
+
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+ session_.MarkConnectionLevelWriteBlocked(stream6->id());
+ session_.MarkConnectionLevelWriteBlocked(stream4->id());
+ CloseStream(stream6->id());
+
+ InSequence s;
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
+ EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
+ session_.SendStreamData(stream2);
+ }));
+ EXPECT_CALL(*stream4, OnCanWrite()).WillOnce(Invoke([this, stream4]() {
+ session_.SendStreamData(stream4);
+ }));
+ session_.OnCanWrite();
+ EXPECT_FALSE(session_.WillingAndAbleToWrite());
+}
+
+TEST_P(QuicSessionTestServer, OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
+ // Drive congestion control manually in order to ensure that
+ // application-limited signaling is handled correctly.
+ MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
+ QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
+ EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(true));
+
+ // Ensure connection level flow control blockage.
+ QuicFlowControllerPeer::SetSendWindowOffset(session_.flow_controller(), 0);
+ EXPECT_TRUE(session_.flow_controller()->IsBlocked());
+ EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
+ EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
+
+ // Mark the crypto and headers streams as write blocked, we expect them to be
+ // allowed to write later.
+ session_.MarkConnectionLevelWriteBlocked(kCryptoStreamId);
+
+ // 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.
+ TestStream* stream = session_.CreateOutgoingDynamicStream();
+ session_.MarkConnectionLevelWriteBlocked(stream->id());
+ EXPECT_CALL(*stream, OnCanWrite()).Times(0);
+
+ // 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());
+
+ // After the crypto and header streams perform a write, the connection will be
+ // blocked by the flow control, hence it should become application-limited.
+ EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
+
+ session_.OnCanWrite();
+ EXPECT_FALSE(session_.WillingAndAbleToWrite());
+}
+
+TEST_P(QuicSessionTestServer, SendGoAway) {
+ MockPacketWriter* writer = static_cast<MockPacketWriter*>(
+ QuicConnectionPeer::GetWriter(session_.connection()));
+ EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
+
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(
+ Invoke(connection_, &MockQuicConnection::ReallySendControlFrame));
+ session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
+ EXPECT_TRUE(session_.goaway_sent());
+
+ const QuicStreamId kTestStreamId = 5u;
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
+ EXPECT_CALL(*connection_,
+ OnStreamReset(kTestStreamId, QUIC_STREAM_PEER_GOING_AWAY))
+ .Times(0);
+ EXPECT_TRUE(session_.GetOrCreateDynamicStream(kTestStreamId));
+}
+
+TEST_P(QuicSessionTestServer, DoNotSendGoAwayTwice) {
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
+ session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
+ EXPECT_TRUE(session_.goaway_sent());
+ session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
+}
+
+TEST_P(QuicSessionTestServer, InvalidGoAway) {
+ QuicGoAwayFrame go_away(kInvalidControlFrameId, QUIC_PEER_GOING_AWAY,
+ session_.next_outgoing_stream_id(), "");
+ session_.OnGoAway(go_away);
+}
+
+// Test that server session will send a connectivity probe in response to a
+// connectivity probe on the same path.
+TEST_P(QuicSessionTestServer, ServerReplyToConnecitivityProbe) {
+ QuicSocketAddress old_peer_address =
+ QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort);
+ EXPECT_EQ(old_peer_address, session_.peer_address());
+
+ QuicSocketAddress new_peer_address =
+ QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort + 1);
+
+ MockPacketWriter* writer = static_cast<MockPacketWriter*>(
+ QuicConnectionPeer::GetWriter(session_.connection()));
+ EXPECT_CALL(*writer, WritePacket(_, _, _, new_peer_address, _))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
+ EXPECT_CALL(*connection_,
+ SendConnectivityProbingPacket(nullptr, new_peer_address))
+ .WillOnce(
+ Invoke(connection_,
+ &MockQuicConnection::ReallySendConnectivityProbingPacket));
+ session_.OnConnectivityProbeReceived(session_.self_address(),
+ new_peer_address);
+ EXPECT_EQ(old_peer_address, session_.peer_address());
+}
+
+TEST_P(QuicSessionTestServer, IncreasedTimeoutAfterCryptoHandshake) {
+ EXPECT_EQ(kInitialIdleTimeoutSecs + 3,
+ QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
+ CryptoHandshakeMessage msg;
+ session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
+ EXPECT_EQ(kMaximumIdleTimeoutSecs + 3,
+ QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
+}
+
+TEST_P(QuicSessionTestServer, OnStreamFrameFinStaticStreamId) {
+ // Send two bytes of payload.
+ QuicStreamFrame data1(kCryptoStreamId, true, 0, QuicStringPiece("HT"));
+ EXPECT_CALL(*connection_,
+ CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Attempt to close a static stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
+ session_.OnStreamFrame(data1);
+}
+
+TEST_P(QuicSessionTestServer, OnRstStreamStaticStreamId) {
+ // Send two bytes of payload.
+ QuicRstStreamFrame rst1(kInvalidControlFrameId, kCryptoStreamId,
+ QUIC_ERROR_PROCESSING_STREAM, 0);
+ EXPECT_CALL(*connection_,
+ CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Attempt to reset a static stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
+ session_.OnRstStream(rst1);
+}
+
+TEST_P(QuicSessionTestServer, OnStreamFrameInvalidStreamId) {
+ // Send two bytes of payload.
+ QuicStreamFrame data1(kInvalidStreamId, true, 0, QuicStringPiece("HT"));
+ EXPECT_CALL(*connection_,
+ CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Recevied data for an invalid stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
+ session_.OnStreamFrame(data1);
+}
+
+TEST_P(QuicSessionTestServer, OnRstStreamInvalidStreamId) {
+ // Send two bytes of payload.
+ QuicRstStreamFrame rst1(kInvalidControlFrameId, kInvalidStreamId,
+ QUIC_ERROR_PROCESSING_STREAM, 0);
+ EXPECT_CALL(*connection_,
+ CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Recevied data for an invalid stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET));
+ session_.OnRstStream(rst1);
+}
+
+TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedStream) {
+ // Test that if a stream is flow control blocked, then on receipt of the SHLO
+ // containing a suitable send window offset, the stream becomes unblocked.
+
+ // Ensure that Writev consumes all the data it is given (simulate no socket
+ // blocking).
+ session_.set_writev_consumes_all_data(true);
+
+ // Create a stream, and send enough data to make it flow control blocked.
+ TestStream* stream2 = session_.CreateOutgoingDynamicStream();
+ QuicString body(kMinimumFlowControlSendWindow, '.');
+ EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
+ EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
+ EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(AtLeast(1));
+ stream2->WriteOrBufferData(body, false, nullptr);
+ EXPECT_TRUE(stream2->flow_controller()->IsBlocked());
+ EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
+ EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
+
+ // Now complete the crypto handshake, resulting in an increased flow control
+ // send window.
+ CryptoHandshakeMessage msg;
+ session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
+ EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(&session_, stream2->id()));
+ // Stream is now unblocked.
+ EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
+ EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
+ EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
+}
+
+TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedCryptoStream) {
+ // Test that if the crypto 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);
+ TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
+ EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
+ EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
+ EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
+ EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
+ EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
+ for (QuicStreamId i = 0;
+ !crypto_stream->flow_controller()->IsBlocked() && i < 1000u; i++) {
+ EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
+ EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
+ QuicStreamOffset offset = crypto_stream->stream_bytes_written();
+ QuicConfig config;
+ CryptoHandshakeMessage crypto_message;
+ config.ToHandshakeMessage(&crypto_message);
+ crypto_stream->SendHandshakeMessage(crypto_message);
+ char buf[1000];
+ QuicDataWriter writer(1000, buf, NETWORK_BYTE_ORDER);
+ crypto_stream->WriteStreamData(offset, crypto_message.size(), &writer);
+ }
+ EXPECT_TRUE(crypto_stream->flow_controller()->IsBlocked());
+ EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
+ EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
+ EXPECT_FALSE(session_.HasDataToWrite());
+ EXPECT_TRUE(crypto_stream->HasBufferedData());
+
+ // Now complete the crypto handshake, resulting in an increased flow control
+ // send window.
+ CryptoHandshakeMessage msg;
+ session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
+ EXPECT_TRUE(
+ QuicSessionPeer::IsStreamWriteBlocked(&session_, kCryptoStreamId));
+ // Stream is now unblocked and will no longer have buffered data.
+ EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
+ EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
+ EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
+}
+
+TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstOutOfOrder) {
+ // Test that when we receive an out of order stream RST we correctly adjust
+ // our connection level flow control receive window.
+ // On close, the stream should mark as consumed all bytes between the highest
+ // byte consumed so far and the final byte offset from the RST frame.
+ TestStream* stream = session_.CreateOutgoingDynamicStream();
+
+ const QuicStreamOffset kByteOffset =
+ 1 + kInitialSessionFlowControlWindowForTest / 2;
+
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(2)
+ .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
+ QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
+ QUIC_STREAM_CANCELLED, kByteOffset);
+ session_.OnRstStream(rst_frame);
+ session_.PostProcessAfterData();
+ EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed());
+}
+
+TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAndLocalReset) {
+ // Test the situation where we receive a FIN on a stream, and before we fully
+ // consume all the data from the sequencer buffer we locally RST the stream.
+ // The bytes between highest consumed byte, and the final byte offset that we
+ // determined when the FIN arrived, should be marked as consumed at the
+ // connection level flow controller when the stream is reset.
+ TestStream* stream = session_.CreateOutgoingDynamicStream();
+
+ const QuicStreamOffset kByteOffset =
+ kInitialSessionFlowControlWindowForTest / 2 - 1;
+ QuicStreamFrame frame(stream->id(), true, kByteOffset, ".");
+ session_.OnStreamFrame(frame);
+ session_.PostProcessAfterData();
+ EXPECT_TRUE(connection_->connected());
+
+ EXPECT_EQ(0u, stream->flow_controller()->bytes_consumed());
+ EXPECT_EQ(kByteOffset + frame.data_length,
+ stream->flow_controller()->highest_received_byte_offset());
+
+ // Reset stream locally.
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
+ stream->Reset(QUIC_STREAM_CANCELLED);
+ EXPECT_EQ(kByteOffset + frame.data_length,
+ session_.flow_controller()->bytes_consumed());
+}
+
+TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAfterRst) {
+ // Test that when we RST the stream (and tear down stream state), and then
+ // receive a FIN from the peer, we correctly adjust our connection level flow
+ // control receive window.
+
+ // Connection starts with some non-zero highest received byte offset,
+ // due to other active streams.
+ const uint64_t kInitialConnectionBytesConsumed = 567;
+ const uint64_t kInitialConnectionHighestReceivedOffset = 1234;
+ EXPECT_LT(kInitialConnectionBytesConsumed,
+ kInitialConnectionHighestReceivedOffset);
+ session_.flow_controller()->UpdateHighestReceivedOffset(
+ kInitialConnectionHighestReceivedOffset);
+ session_.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed);
+
+ // Reset our stream: this results in the stream being closed locally.
+ TestStream* stream = session_.CreateOutgoingDynamicStream();
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
+ stream->Reset(QUIC_STREAM_CANCELLED);
+
+ // Now receive a response from the peer with a FIN. We should handle this by
+ // adjusting the connection level flow control receive window to take into
+ // account the total number of bytes sent by the peer.
+ const QuicStreamOffset kByteOffset = 5678;
+ QuicString body = "hello";
+ QuicStreamFrame frame(stream->id(), true, kByteOffset, QuicStringPiece(body));
+ session_.OnStreamFrame(frame);
+
+ QuicStreamOffset total_stream_bytes_sent_by_peer =
+ kByteOffset + body.length();
+ EXPECT_EQ(kInitialConnectionBytesConsumed + total_stream_bytes_sent_by_peer,
+ session_.flow_controller()->bytes_consumed());
+ EXPECT_EQ(
+ kInitialConnectionHighestReceivedOffset + total_stream_bytes_sent_by_peer,
+ session_.flow_controller()->highest_received_byte_offset());
+}
+
+TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstAfterRst) {
+ // Test that when we RST the stream (and tear down stream state), and then
+ // receive a RST from the peer, we correctly adjust our connection level flow
+ // control receive window.
+
+ // Connection starts with some non-zero highest received byte offset,
+ // due to other active streams.
+ const uint64_t kInitialConnectionBytesConsumed = 567;
+ const uint64_t kInitialConnectionHighestReceivedOffset = 1234;
+ EXPECT_LT(kInitialConnectionBytesConsumed,
+ kInitialConnectionHighestReceivedOffset);
+ session_.flow_controller()->UpdateHighestReceivedOffset(
+ kInitialConnectionHighestReceivedOffset);
+ session_.flow_controller()->AddBytesConsumed(kInitialConnectionBytesConsumed);
+
+ // Reset our stream: this results in the stream being closed locally.
+ TestStream* stream = session_.CreateOutgoingDynamicStream();
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
+ stream->Reset(QUIC_STREAM_CANCELLED);
+ EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream));
+
+ // Now receive a RST from the peer. We should handle this by adjusting the
+ // connection level flow control receive window to take into account the total
+ // number of bytes sent by the peer.
+ const QuicStreamOffset kByteOffset = 5678;
+ QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
+ QUIC_STREAM_CANCELLED, kByteOffset);
+ session_.OnRstStream(rst_frame);
+
+ EXPECT_EQ(kInitialConnectionBytesConsumed + kByteOffset,
+ session_.flow_controller()->bytes_consumed());
+ EXPECT_EQ(kInitialConnectionHighestReceivedOffset + kByteOffset,
+ session_.flow_controller()->highest_received_byte_offset());
+}
+
+TEST_P(QuicSessionTestServer, InvalidStreamFlowControlWindowInHandshake) {
+ // Test that receipt of an invalid (< default) stream flow control window from
+ // the peer results in the connection being torn down.
+ const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
+ QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(session_.config(),
+ kInvalidWindow);
+
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
+ session_.OnConfigNegotiated();
+}
+
+TEST_P(QuicSessionTestServer, InvalidSessionFlowControlWindowInHandshake) {
+ // Test that receipt of an invalid (< default) session flow control window
+ // from the peer results in the connection being torn down.
+ const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
+ QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(session_.config(),
+ kInvalidWindow);
+
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
+ session_.OnConfigNegotiated();
+}
+
+// Test negotiation of custom server initial flow control window.
+TEST_P(QuicSessionTestServer, CustomFlowControlWindow) {
+ QuicTagVector copt;
+ copt.push_back(kIFW7);
+ QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
+
+ session_.OnConfigNegotiated();
+ EXPECT_EQ(192 * 1024u, QuicFlowControllerPeer::ReceiveWindowSize(
+ session_.flow_controller()));
+}
+
+TEST_P(QuicSessionTestServer, FlowControlWithInvalidFinalOffset) {
+ // Test that if we receive a stream RST with a highest byte offset that
+ // violates flow control, that we close the connection.
+ const uint64_t kLargeOffset = kInitialSessionFlowControlWindowForTest + 1;
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _))
+ .Times(2);
+
+ // Check that stream frame + FIN results in connection close.
+ TestStream* stream = session_.CreateOutgoingDynamicStream();
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
+ stream->Reset(QUIC_STREAM_CANCELLED);
+ QuicStreamFrame frame(stream->id(), true, kLargeOffset, QuicStringPiece());
+ session_.OnStreamFrame(frame);
+
+ // Check that RST results in connection close.
+ QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
+ QUIC_STREAM_CANCELLED, kLargeOffset);
+ session_.OnRstStream(rst_frame);
+}
+
+TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) {
+ // If a buggy/malicious peer creates too many streams that are not ended
+ // with a FIN or RST then we send an RST to refuse streams.
+ const QuicStreamId kMaxStreams = 5;
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
+ const QuicStreamId kFirstStreamId = GetNthClientInitiatedId(0);
+ const QuicStreamId kFinalStreamId = GetNthClientInitiatedId(kMaxStreams);
+ // Create kMaxStreams data streams, and close them all without receiving a
+ // FIN or a RST_STREAM from the client.
+ for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += 2) {
+ QuicStreamFrame data1(i, false, 0, QuicStringPiece("HT"));
+ session_.OnStreamFrame(data1);
+ // EXPECT_EQ(1u, session_.GetNumOpenStreams());
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(i, _));
+ session_.CloseStream(i);
+ }
+
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
+ EXPECT_CALL(*connection_, OnStreamReset(kFinalStreamId, QUIC_REFUSED_STREAM))
+ .Times(1);
+ // Create one more data streams to exceed limit of open stream.
+ QuicStreamFrame data1(kFinalStreamId, false, 0, QuicStringPiece("HT"));
+ session_.OnStreamFrame(data1);
+
+ // Called after any new data is received by the session, and triggers the
+ // call to close the connection.
+ session_.PostProcessAfterData();
+}
+
+TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpened) {
+ // Verify that a draining stream (which has received a FIN but not consumed
+ // it) does not count against the open quota (because it is closed from the
+ // protocol point of view).
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
+ EXPECT_CALL(*connection_, OnStreamReset(_, QUIC_REFUSED_STREAM)).Times(0);
+ const QuicStreamId kMaxStreams = 5;
+ QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
+
+ // Create kMaxStreams + 1 data streams, and mark them draining.
+ const QuicStreamId kFirstStreamId = GetNthClientInitiatedId(0);
+ const QuicStreamId kFinalStreamId =
+ GetNthClientInitiatedId(2 * kMaxStreams + 1);
+ for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += 2) {
+ QuicStreamFrame data1(i, true, 0, QuicStringPiece("HT"));
+ session_.OnStreamFrame(data1);
+ EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
+ session_.StreamDraining(i);
+ EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
+ }
+
+ // Called after any new data is received by the session, and triggers the call
+ // to close the connection.
+ session_.PostProcessAfterData();
+}
+
+TEST_P(QuicSessionTestServer, TestMaxIncomingAndOutgoingStreamsAllowed) {
+ // Tests that on server side, the value of max_open_incoming/outgoing streams
+ // are setup correctly during negotiation.
+ // The value for outgoing stream is limited to negotiated value and for
+ // incoming stream it is set to be larger than that.
+ session_.OnConfigNegotiated();
+ // The max number of open outgoing streams is less than that of incoming
+ // streams, and it should be same as negotiated value.
+ EXPECT_LT(session_.max_open_outgoing_streams(),
+ session_.max_open_incoming_streams());
+ EXPECT_EQ(session_.max_open_outgoing_streams(),
+ kDefaultMaxStreamsPerConnection);
+ EXPECT_GT(session_.max_open_incoming_streams(),
+ kDefaultMaxStreamsPerConnection);
+}
+
+class QuicSessionTestClient : public QuicSessionTestBase {
+ protected:
+ QuicSessionTestClient() : QuicSessionTestBase(Perspective::IS_CLIENT) {}
+};
+
+INSTANTIATE_TEST_CASE_P(Tests,
+ QuicSessionTestClient,
+ ::testing::ValuesIn(AllSupportedVersions()));
+
+TEST_P(QuicSessionTestClient, AvailableStreamsClient) {
+ ASSERT_TRUE(session_.GetOrCreateDynamicStream(6) != nullptr);
+ // Both 2 and 4 should be available.
+ EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 2));
+ EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 4));
+ ASSERT_TRUE(session_.GetOrCreateDynamicStream(2) != nullptr);
+ ASSERT_TRUE(session_.GetOrCreateDynamicStream(4) != nullptr);
+ // And 5 should be not available.
+ EXPECT_FALSE(QuicSessionPeer::IsStreamAvailable(&session_, 5));
+}
+
+TEST_P(QuicSessionTestClient, RecordFinAfterReadSideClosed) {
+ // Verify that an incoming FIN is recorded in a stream object even if the read
+ // side has been closed. This prevents an entry from being made in
+ // locally_closed_streams_highest_offset_ (which will never be deleted).
+ TestStream* stream = session_.CreateOutgoingDynamicStream();
+ QuicStreamId stream_id = stream->id();
+
+ // Close the read side manually.
+ QuicStreamPeer::CloseReadSide(stream);
+
+ // Receive a stream data frame with FIN.
+ QuicStreamFrame frame(stream_id, true, 0, QuicStringPiece());
+ session_.OnStreamFrame(frame);
+ EXPECT_TRUE(stream->fin_received());
+
+ // Reset stream locally.
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
+ stream->Reset(QUIC_STREAM_CANCELLED);
+ EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream));
+
+ // Allow the session to delete the stream object.
+ session_.PostProcessAfterData();
+ EXPECT_TRUE(connection_->connected());
+ EXPECT_TRUE(QuicSessionPeer::IsStreamClosed(&session_, stream_id));
+ EXPECT_FALSE(QuicSessionPeer::IsStreamCreated(&session_, stream_id));
+
+ // The stream is not waiting for the arrival of the peer's final offset as it
+ // was received with the FIN earlier.
+ EXPECT_EQ(
+ 0u,
+ QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(&session_).size());
+}
+
+TEST_P(QuicSessionTestClient, TestMaxIncomingAndOutgoingStreamsAllowed) {
+ // Tests that on client side, the value of max_open_incoming/outgoing streams
+ // are setup correctly during negotiation.
+ // When flag is true, the value for outgoing stream is limited to negotiated
+ // value and for incoming stream it is set to be larger than that.
+ session_.OnConfigNegotiated();
+ EXPECT_LT(session_.max_open_outgoing_streams(),
+ session_.max_open_incoming_streams());
+ EXPECT_EQ(session_.max_open_outgoing_streams(),
+ kDefaultMaxStreamsPerConnection);
+}
+
+TEST_P(QuicSessionTestServer, ZombieStreams) {
+ TestStream* stream2 = session_.CreateOutgoingDynamicStream();
+ QuicStreamPeer::SetStreamBytesWritten(3, stream2);
+ EXPECT_TRUE(stream2->IsWaitingForAcks());
+
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(2, _));
+ session_.CloseStream(2);
+ if (GetQuicReloadableFlag(quic_reset_stream_is_not_zombie)) {
+ EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), 2));
+ ASSERT_EQ(1u, session_.closed_streams()->size());
+ EXPECT_EQ(2u, session_.closed_streams()->front()->id());
+ } else {
+ EXPECT_TRUE(QuicContainsKey(session_.zombie_streams(), 2));
+ EXPECT_TRUE(session_.closed_streams()->empty());
+ }
+ session_.OnStreamDoneWaitingForAcks(2);
+ EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), 2));
+ EXPECT_EQ(1u, session_.closed_streams()->size());
+ EXPECT_EQ(2u, session_.closed_streams()->front()->id());
+}
+
+// Regression test of b/71548958.
+TEST_P(QuicSessionTestServer, TestZombieStreams) {
+ session_.set_writev_consumes_all_data(true);
+
+ TestStream* stream2 = session_.CreateOutgoingDynamicStream();
+ QuicString body(100, '.');
+ stream2->WriteOrBufferData(body, false, nullptr);
+ EXPECT_TRUE(stream2->IsWaitingForAcks());
+ EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream2).size());
+
+ QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream2->id(),
+ QUIC_STREAM_CANCELLED, 1234);
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
+ EXPECT_CALL(*connection_,
+ OnStreamReset(stream2->id(), QUIC_RST_ACKNOWLEDGEMENT));
+ stream2->OnStreamReset(rst_frame);
+ if (GetQuicReloadableFlag(quic_reset_stream_is_not_zombie)) {
+ EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
+ ASSERT_EQ(1u, session_.closed_streams()->size());
+ EXPECT_EQ(stream2->id(), session_.closed_streams()->front()->id());
+ } else {
+ // Stream reset by peer, and it becomes zombie stream and the data will be
+ // NEVER be acked because the frames in unacked packet map are removed.
+ EXPECT_TRUE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
+ EXPECT_TRUE(session_.closed_streams()->empty());
+ EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream2).size());
+ }
+
+ TestStream* stream4 = session_.CreateOutgoingDynamicStream();
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
+ EXPECT_CALL(*connection_,
+ OnStreamReset(stream4->id(), QUIC_STREAM_CANCELLED));
+ stream4->WriteOrBufferData(body, false, nullptr);
+ stream4->Reset(QUIC_STREAM_CANCELLED);
+ EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream4->id()));
+ if (GetQuicReloadableFlag(quic_reset_stream_is_not_zombie)) {
+ EXPECT_EQ(2u, session_.closed_streams()->size());
+ } else {
+ EXPECT_EQ(1u, session_.closed_streams()->size());
+ }
+}
+
+TEST_P(QuicSessionTestServer, OnStreamFrameLost) {
+ QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
+ InSequence s;
+
+ // Drive congestion control manually.
+ MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
+ QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
+
+ TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
+ TestStream* stream2 = session_.CreateOutgoingDynamicStream();
+ TestStream* stream4 = session_.CreateOutgoingDynamicStream();
+
+ QuicStreamFrame frame1(kCryptoStreamId, false, 0, 1300);
+ QuicStreamFrame frame2(stream2->id(), false, 0, 9);
+ QuicStreamFrame frame3(stream4->id(), false, 0, 9);
+
+ // Lost data on cryption stream, streams 2 and 4.
+ EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(true));
+ EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
+ .WillOnce(Return(true));
+ EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(true));
+ session_.OnFrameLost(QuicFrame(&frame3));
+ session_.OnFrameLost(QuicFrame(&frame1));
+ session_.OnFrameLost(QuicFrame(&frame2));
+ EXPECT_TRUE(session_.WillingAndAbleToWrite());
+
+ // Mark streams 2 and 4 write blocked.
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+ session_.MarkConnectionLevelWriteBlocked(stream4->id());
+
+ // Lost data is retransmitted before new data, and retransmissions for crypto
+ // stream go first.
+ // Do not check congestion window when crypto stream has lost data.
+ EXPECT_CALL(*send_algorithm, CanSend(_)).Times(0);
+ EXPECT_CALL(*crypto_stream, OnCanWrite());
+ EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
+ .WillOnce(Return(false));
+ // Check congestion window for non crypto streams.
+ EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
+ EXPECT_CALL(*stream4, OnCanWrite());
+ EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(false));
+ // Connection is blocked.
+ EXPECT_CALL(*send_algorithm, CanSend(_)).WillRepeatedly(Return(false));
+
+ session_.OnCanWrite();
+ EXPECT_TRUE(session_.WillingAndAbleToWrite());
+
+ // Unblock connection.
+ // Stream 2 retransmits lost data.
+ EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
+ EXPECT_CALL(*stream2, OnCanWrite());
+ EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(false));
+ EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
+ // Stream 2 sends new data.
+ EXPECT_CALL(*stream2, OnCanWrite());
+ EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
+ EXPECT_CALL(*stream4, OnCanWrite());
+ EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
+
+ session_.OnCanWrite();
+ EXPECT_FALSE(session_.WillingAndAbleToWrite());
+}
+
+TEST_P(QuicSessionTestServer, DonotRetransmitDataOfClosedStreams) {
+ QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
+ InSequence s;
+
+ TestStream* stream2 = session_.CreateOutgoingDynamicStream();
+ TestStream* stream4 = session_.CreateOutgoingDynamicStream();
+ TestStream* stream6 = session_.CreateOutgoingDynamicStream();
+
+ QuicStreamFrame frame1(stream2->id(), false, 0, 9);
+ QuicStreamFrame frame2(stream4->id(), false, 0, 9);
+ QuicStreamFrame frame3(stream6->id(), false, 0, 9);
+
+ EXPECT_CALL(*stream6, HasPendingRetransmission()).WillOnce(Return(true));
+ EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(true));
+ EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(true));
+ session_.OnFrameLost(QuicFrame(&frame3));
+ session_.OnFrameLost(QuicFrame(&frame2));
+ session_.OnFrameLost(QuicFrame(&frame1));
+
+ session_.MarkConnectionLevelWriteBlocked(stream2->id());
+ session_.MarkConnectionLevelWriteBlocked(stream4->id());
+ session_.MarkConnectionLevelWriteBlocked(stream6->id());
+
+ // Reset stream 4 locally.
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(stream4->id(), _));
+ stream4->Reset(QUIC_STREAM_CANCELLED);
+
+ // Verify stream 4 is removed from streams with lost data list.
+ EXPECT_CALL(*stream6, OnCanWrite());
+ EXPECT_CALL(*stream6, HasPendingRetransmission()).WillOnce(Return(false));
+ EXPECT_CALL(*stream2, OnCanWrite());
+ EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(false));
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
+ EXPECT_CALL(*stream2, OnCanWrite());
+ EXPECT_CALL(*stream6, OnCanWrite());
+ session_.OnCanWrite();
+}
+
+TEST_P(QuicSessionTestServer, RetransmitFrames) {
+ QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
+ MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
+ QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
+ InSequence s;
+
+ TestStream* stream2 = session_.CreateOutgoingDynamicStream();
+ TestStream* stream4 = session_.CreateOutgoingDynamicStream();
+ TestStream* stream6 = session_.CreateOutgoingDynamicStream();
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
+ session_.SendWindowUpdate(stream2->id(), 9);
+
+ QuicStreamFrame frame1(stream2->id(), false, 0, 9);
+ QuicStreamFrame frame2(stream4->id(), false, 0, 9);
+ QuicStreamFrame frame3(stream6->id(), false, 0, 9);
+ QuicWindowUpdateFrame window_update(1, stream2->id(), 9);
+ QuicFrames frames;
+ frames.push_back(QuicFrame(&frame1));
+ frames.push_back(QuicFrame(&window_update));
+ frames.push_back(QuicFrame(&frame2));
+ frames.push_back(QuicFrame(&frame3));
+ EXPECT_FALSE(session_.WillingAndAbleToWrite());
+
+ EXPECT_CALL(*stream2, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
+ EXPECT_CALL(*stream4, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
+ EXPECT_CALL(*stream6, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
+ EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
+ session_.RetransmitFrames(frames, TLP_RETRANSMISSION);
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/core/quic_spdy_session.cc b/chromium/net/quic/core/quic_spdy_session.cc
index a64af281494..f05447305e3 100644
--- a/chromium/net/quic/core/quic_spdy_session.cc
+++ b/chromium/net/quic/core/quic_spdy_session.cc
@@ -119,7 +119,50 @@ class QuicSpdySession::SpdyFramerVisitor
QUIC_INVALID_HEADERS_STREAM_DATA);
}
- void OnSetting(SpdyKnownSettingsId id, uint32_t value) override {
+ void OnSettingOld(SpdyKnownSettingsId id, uint32_t value) override {
+ QUIC_BUG_IF(GetQuicRestartFlag(http2_propagate_unknown_settings));
+ if (!GetQuicReloadableFlag(quic_respect_http2_settings_frame)) {
+ CloseConnection("SPDY SETTINGS frame received.",
+ QUIC_INVALID_HEADERS_STREAM_DATA);
+ return;
+ }
+ switch (id) {
+ case SETTINGS_HEADER_TABLE_SIZE:
+ session_->UpdateHeaderEncoderTableSize(value);
+ break;
+ case SETTINGS_ENABLE_PUSH:
+ if (session_->perspective() == Perspective::IS_SERVER) {
+ // See rfc7540, Section 6.5.2.
+ if (value > 1) {
+ CloseConnection(
+ QuicStrCat("Invalid value for SETTINGS_ENABLE_PUSH: ", value),
+ QUIC_INVALID_HEADERS_STREAM_DATA);
+ return;
+ }
+ session_->UpdateEnableServerPush(value > 0);
+ break;
+ } else {
+ CloseConnection(
+ QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ", id),
+ QUIC_INVALID_HEADERS_STREAM_DATA);
+ }
+ break;
+ // TODO(fayang): Need to support SETTINGS_MAX_HEADER_LIST_SIZE when
+ // clients are actually sending it.
+ case SETTINGS_MAX_HEADER_LIST_SIZE:
+ if (GetQuicReloadableFlag(quic_send_max_header_list_size)) {
+ break;
+ }
+ QUIC_FALLTHROUGH_INTENDED;
+ default:
+ CloseConnection(
+ QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ", id),
+ QUIC_INVALID_HEADERS_STREAM_DATA);
+ }
+ }
+
+ void OnSetting(SpdySettingsId id, uint32_t value) override {
+ QUIC_BUG_IF(!GetQuicRestartFlag(http2_propagate_unknown_settings));
if (!GetQuicReloadableFlag(quic_respect_http2_settings_frame)) {
CloseConnection("SPDY SETTINGS frame received.",
QUIC_INVALID_HEADERS_STREAM_DATA);
@@ -490,20 +533,6 @@ void QuicSpdySession::OnHeadersHeadOfLineBlocking(QuicTime::Delta delta) {
// Implemented in Chromium for stats tracking.
}
-void QuicSpdySession::RegisterStreamPriority(QuicStreamId id,
- SpdyPriority priority) {
- write_blocked_streams()->RegisterStream(id, priority);
-}
-
-void QuicSpdySession::UnregisterStreamPriority(QuicStreamId id) {
- write_blocked_streams()->UnregisterStream(id);
-}
-
-void QuicSpdySession::UpdateStreamPriority(QuicStreamId id,
- SpdyPriority new_priority) {
- write_blocked_streams()->UpdateStreamPriority(id, new_priority);
-}
-
QuicSpdyStream* QuicSpdySession::GetSpdyDataStream(
const QuicStreamId stream_id) {
return static_cast<QuicSpdyStream*>(GetOrCreateDynamicStream(stream_id));
diff --git a/chromium/net/quic/core/quic_spdy_session.h b/chromium/net/quic/core/quic_spdy_session.h
index 7268cc2ba70..fd9600a20bc 100644
--- a/chromium/net/quic/core/quic_spdy_session.h
+++ b/chromium/net/quic/core/quic_spdy_session.h
@@ -120,15 +120,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession : public QuicSession {
// |delta| indicates how long that piece of data has been blocked.
virtual void OnHeadersHeadOfLineBlocking(QuicTime::Delta delta);
- // Called by the stream on creation to set priority in the write blocked list.
- virtual void RegisterStreamPriority(QuicStreamId id, SpdyPriority priority);
- // Called by the stream on deletion to clear priority crom the write blocked
- // list.
- virtual void UnregisterStreamPriority(QuicStreamId id);
- // Called by the stream on SetPriority to update priority on the write blocked
- // list.
- virtual void UpdateStreamPriority(QuicStreamId id, SpdyPriority new_priority);
-
void OnConfigNegotiated() override;
bool server_push_enabled() const { return server_push_enabled_; }
diff --git a/chromium/net/quic/core/quic_spdy_session_test.cc b/chromium/net/quic/core/quic_spdy_session_test.cc
index 8267f8060ab..77b1753ceca 100644
--- a/chromium/net/quic/core/quic_spdy_session_test.cc
+++ b/chromium/net/quic/core/quic_spdy_session_test.cc
@@ -135,7 +135,7 @@ class TestSession : public QuicSpdySession {
Initialize();
this->connection()->SetEncrypter(
ENCRYPTION_FORWARD_SECURE,
- new NullEncrypter(connection->perspective()));
+ QuicMakeUnique<NullEncrypter>(connection->perspective()));
}
~TestSession() override { delete connection(); }
@@ -239,9 +239,9 @@ class TestSession : public QuicSpdySession {
bool writev_consumes_all_data_;
};
-class QuicSessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
+class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
protected:
- explicit QuicSessionTestBase(Perspective perspective)
+ explicit QuicSpdySessionTestBase(Perspective perspective)
: connection_(
new StrictMock<MockQuicConnection>(&helper_,
&alarm_factory_,
@@ -296,13 +296,9 @@ class QuicSessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
}
void CloseStream(QuicStreamId id) {
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
- EXPECT_CALL(*connection_, OnStreamReset(id, _));
- } else {
- EXPECT_CALL(*connection_, SendRstStream(id, _, _));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(id, _));
session_.CloseStream(id);
closed_streams_.insert(id);
}
@@ -329,39 +325,40 @@ class QuicSessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
SpdyHeaderBlock headers_;
};
-class QuicSessionTestServer : public QuicSessionTestBase {
+class QuicSpdySessionTestServer : public QuicSpdySessionTestBase {
protected:
- QuicSessionTestServer() : QuicSessionTestBase(Perspective::IS_SERVER) {}
+ QuicSpdySessionTestServer()
+ : QuicSpdySessionTestBase(Perspective::IS_SERVER) {}
};
INSTANTIATE_TEST_CASE_P(Tests,
- QuicSessionTestServer,
+ QuicSpdySessionTestServer,
::testing::ValuesIn(AllSupportedVersions()));
-TEST_P(QuicSessionTestServer, PeerAddress) {
+TEST_P(QuicSpdySessionTestServer, PeerAddress) {
EXPECT_EQ(QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort),
session_.peer_address());
}
-TEST_P(QuicSessionTestServer, SelfAddress) {
+TEST_P(QuicSpdySessionTestServer, SelfAddress) {
EXPECT_EQ(QuicSocketAddress(), session_.self_address());
}
-TEST_P(QuicSessionTestServer, IsCryptoHandshakeConfirmed) {
+TEST_P(QuicSpdySessionTestServer, IsCryptoHandshakeConfirmed) {
EXPECT_FALSE(session_.IsCryptoHandshakeConfirmed());
CryptoHandshakeMessage message;
session_.GetMutableCryptoStream()->OnHandshakeMessage(message);
EXPECT_TRUE(session_.IsCryptoHandshakeConfirmed());
}
-TEST_P(QuicSessionTestServer, IsClosedStreamDefault) {
+TEST_P(QuicSpdySessionTestServer, IsClosedStreamDefault) {
// Ensure that no streams are initially closed.
for (QuicStreamId i = kCryptoStreamId; i < 100; i++) {
EXPECT_FALSE(session_.IsClosedStream(i)) << "stream id: " << i;
}
}
-TEST_P(QuicSessionTestServer, AvailableStreams) {
+TEST_P(QuicSpdySessionTestServer, AvailableStreams) {
ASSERT_TRUE(session_.GetOrCreateDynamicStream(9) != nullptr);
// Both 5 and 7 should be available.
EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 5));
@@ -370,7 +367,7 @@ TEST_P(QuicSessionTestServer, AvailableStreams) {
ASSERT_TRUE(session_.GetOrCreateDynamicStream(5) != nullptr);
}
-TEST_P(QuicSessionTestServer, IsClosedStreamLocallyCreated) {
+TEST_P(QuicSpdySessionTestServer, IsClosedStreamLocallyCreated) {
TestStream* stream2 = session_.CreateOutgoingDynamicStream();
EXPECT_EQ(GetNthServerInitiatedId(0), stream2->id());
QuicSpdyStream* stream4 = session_.CreateOutgoingDynamicStream();
@@ -383,7 +380,7 @@ TEST_P(QuicSessionTestServer, IsClosedStreamLocallyCreated) {
CheckClosedStreams();
}
-TEST_P(QuicSessionTestServer, IsClosedStreamPeerCreated) {
+TEST_P(QuicSpdySessionTestServer, IsClosedStreamPeerCreated) {
QuicStreamId stream_id1 = GetNthClientInitiatedId(0);
QuicStreamId stream_id2 = GetNthClientInitiatedId(1);
session_.GetOrCreateDynamicStream(stream_id1);
@@ -401,7 +398,7 @@ TEST_P(QuicSessionTestServer, IsClosedStreamPeerCreated) {
CheckClosedStreams();
}
-TEST_P(QuicSessionTestServer, MaximumAvailableOpenedStreams) {
+TEST_P(QuicSpdySessionTestServer, MaximumAvailableOpenedStreams) {
QuicStreamId stream_id = GetNthClientInitiatedId(0);
session_.GetOrCreateDynamicStream(stream_id);
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
@@ -410,7 +407,7 @@ TEST_P(QuicSessionTestServer, MaximumAvailableOpenedStreams) {
stream_id + 2 * (session_.max_open_incoming_streams() - 1)));
}
-TEST_P(QuicSessionTestServer, TooManyAvailableStreams) {
+TEST_P(QuicSpdySessionTestServer, TooManyAvailableStreams) {
QuicStreamId stream_id1 = GetNthClientInitiatedId(0);
QuicStreamId stream_id2;
EXPECT_NE(nullptr, session_.GetOrCreateDynamicStream(stream_id1));
@@ -421,7 +418,7 @@ TEST_P(QuicSessionTestServer, TooManyAvailableStreams) {
EXPECT_EQ(nullptr, session_.GetOrCreateDynamicStream(stream_id2));
}
-TEST_P(QuicSessionTestServer, ManyAvailableStreams) {
+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);
@@ -433,16 +430,13 @@ TEST_P(QuicSessionTestServer, ManyAvailableStreams) {
session_.GetOrCreateDynamicStream(stream_id + 2 * (200 - 1));
}
-TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) {
+TEST_P(QuicSpdySessionTestServer,
+ DebugDFatalIfMarkingClosedStreamWriteBlocked) {
TestStream* stream2 = session_.CreateOutgoingDynamicStream();
QuicStreamId closed_stream_id = stream2->id();
// Close the stream.
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_, OnStreamReset(closed_stream_id, _));
- } else {
- EXPECT_CALL(*connection_, SendRstStream(closed_stream_id, _, _));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(closed_stream_id, _));
stream2->Reset(QUIC_BAD_APPLICATION_PAYLOAD);
QuicString msg =
QuicStrCat("Marking unknown stream ", closed_stream_id, " blocked.");
@@ -450,7 +444,7 @@ TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) {
msg);
}
-TEST_P(QuicSessionTestServer, OnCanWrite) {
+TEST_P(QuicSpdySessionTestServer, OnCanWrite) {
session_.set_writev_consumes_all_data(true);
TestStream* stream2 = session_.CreateOutgoingDynamicStream();
TestStream* stream4 = session_.CreateOutgoingDynamicStream();
@@ -479,7 +473,7 @@ TEST_P(QuicSessionTestServer, OnCanWrite) {
EXPECT_TRUE(session_.WillingAndAbleToWrite());
}
-TEST_P(QuicSessionTestServer, TestBatchedWrites) {
+TEST_P(QuicSpdySessionTestServer, TestBatchedWrites) {
session_.set_writev_consumes_all_data(true);
TestStream* stream2 = session_.CreateOutgoingDynamicStream();
TestStream* stream4 = session_.CreateOutgoingDynamicStream();
@@ -545,7 +539,7 @@ TEST_P(QuicSessionTestServer, TestBatchedWrites) {
session_.OnCanWrite();
}
-TEST_P(QuicSessionTestServer, OnCanWriteBundlesStreams) {
+TEST_P(QuicSpdySessionTestServer, OnCanWriteBundlesStreams) {
// Encryption needs to be established before data can be sent.
CryptoHandshakeMessage msg;
MockPacketWriter* writer = static_cast<MockPacketWriter*>(
@@ -592,7 +586,7 @@ TEST_P(QuicSessionTestServer, OnCanWriteBundlesStreams) {
EXPECT_FALSE(session_.WillingAndAbleToWrite());
}
-TEST_P(QuicSessionTestServer, OnCanWriteCongestionControlBlocks) {
+TEST_P(QuicSpdySessionTestServer, OnCanWriteCongestionControlBlocks) {
session_.set_writev_consumes_all_data(true);
InSequence s;
@@ -638,7 +632,7 @@ TEST_P(QuicSessionTestServer, OnCanWriteCongestionControlBlocks) {
EXPECT_FALSE(session_.WillingAndAbleToWrite());
}
-TEST_P(QuicSessionTestServer, OnCanWriteWriterBlocks) {
+TEST_P(QuicSpdySessionTestServer, OnCanWriteWriterBlocks) {
// Drive congestion control manually in order to ensure that
// application-limited signaling is handled correctly.
MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
@@ -664,7 +658,7 @@ TEST_P(QuicSessionTestServer, OnCanWriteWriterBlocks) {
EXPECT_TRUE(session_.WillingAndAbleToWrite());
}
-TEST_P(QuicSessionTestServer, BufferedHandshake) {
+TEST_P(QuicSpdySessionTestServer, BufferedHandshake) {
session_.set_writev_consumes_all_data(true);
EXPECT_FALSE(session_.HasPendingHandshake()); // Default value.
@@ -711,7 +705,7 @@ TEST_P(QuicSessionTestServer, BufferedHandshake) {
EXPECT_FALSE(session_.HasPendingHandshake()); // Crypto stream wrote.
}
-TEST_P(QuicSessionTestServer, OnCanWriteWithClosedStream) {
+TEST_P(QuicSpdySessionTestServer, OnCanWriteWithClosedStream) {
session_.set_writev_consumes_all_data(true);
TestStream* stream2 = session_.CreateOutgoingDynamicStream();
TestStream* stream4 = session_.CreateOutgoingDynamicStream();
@@ -723,10 +717,8 @@ TEST_P(QuicSessionTestServer, OnCanWriteWithClosedStream) {
CloseStream(stream6->id());
InSequence s;
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
EXPECT_CALL(*stream2, OnCanWrite()).WillOnce(Invoke([this, stream2]() {
session_.SendStreamData(stream2);
}));
@@ -737,7 +729,8 @@ TEST_P(QuicSessionTestServer, OnCanWriteWithClosedStream) {
EXPECT_FALSE(session_.WillingAndAbleToWrite());
}
-TEST_P(QuicSessionTestServer, OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
+TEST_P(QuicSpdySessionTestServer,
+ OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
// Drive congestion control manually in order to ensure that
// application-limited signaling is handled correctly.
MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
@@ -753,7 +746,6 @@ TEST_P(QuicSessionTestServer, OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
// Mark the crypto and headers streams as write blocked, we expect them to be
// allowed to write later.
session_.MarkConnectionLevelWriteBlocked(kCryptoStreamId);
- session_.MarkConnectionLevelWriteBlocked(kHeadersStreamId);
// 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.
@@ -765,8 +757,10 @@ TEST_P(QuicSessionTestServer, OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
// 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);
+ session_.MarkConnectionLevelWriteBlocked(kHeadersStreamId);
EXPECT_CALL(*headers_stream, OnCanWrite());
// After the crypto and header streams perform a write, the connection will be
@@ -777,52 +771,35 @@ TEST_P(QuicSessionTestServer, OnCanWriteLimitsNumWritesIfFlowControlBlocked) {
EXPECT_FALSE(session_.WillingAndAbleToWrite());
}
-TEST_P(QuicSessionTestServer, SendGoAway) {
+TEST_P(QuicSpdySessionTestServer, SendGoAway) {
MockPacketWriter* writer = static_cast<MockPacketWriter*>(
QuicConnectionPeer::GetWriter(session_.connection()));
EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillOnce(
- Invoke(connection_, &MockQuicConnection::ReallySendControlFrame));
- } else {
- EXPECT_CALL(*connection_, SendGoAway(_, _, _))
- .WillOnce(Invoke(connection_, &MockQuicConnection::ReallySendGoAway));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(
+ Invoke(connection_, &MockQuicConnection::ReallySendControlFrame));
session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
EXPECT_TRUE(session_.goaway_sent());
const QuicStreamId kTestStreamId = 5u;
- if (session_.use_control_frame_manager()) {
EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
EXPECT_CALL(*connection_,
OnStreamReset(kTestStreamId, QUIC_STREAM_PEER_GOING_AWAY))
.Times(0);
- } else {
- EXPECT_CALL(*connection_,
- SendRstStream(kTestStreamId, QUIC_STREAM_PEER_GOING_AWAY, 0))
- .Times(0);
- }
EXPECT_TRUE(session_.GetOrCreateDynamicStream(kTestStreamId));
}
-TEST_P(QuicSessionTestServer, DoNotSendGoAwayTwice) {
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
- } else {
- EXPECT_CALL(*connection_, SendGoAway(QUIC_PEER_GOING_AWAY, kHeadersStreamId,
- "Going Away."))
- .Times(1);
- }
+TEST_P(QuicSpdySessionTestServer, DoNotSendGoAwayTwice) {
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
EXPECT_TRUE(session_.goaway_sent());
session_.SendGoAway(QUIC_PEER_GOING_AWAY, "Going Away.");
}
-TEST_P(QuicSessionTestServer, InvalidGoAway) {
+TEST_P(QuicSpdySessionTestServer, InvalidGoAway) {
QuicGoAwayFrame go_away(kInvalidControlFrameId, QUIC_PEER_GOING_AWAY,
session_.next_outgoing_stream_id(), "");
session_.OnGoAway(go_away);
@@ -830,7 +807,7 @@ TEST_P(QuicSessionTestServer, InvalidGoAway) {
// Test that server session will send a connectivity probe in response to a
// connectivity probe on the same path.
-TEST_P(QuicSessionTestServer, ServerReplyToConnecitivityProbe) {
+TEST_P(QuicSpdySessionTestServer, ServerReplyToConnecitivityProbe) {
QuicSocketAddress old_peer_address =
QuicSocketAddress(QuicIpAddress::Loopback4(), kTestPort);
EXPECT_EQ(old_peer_address, session_.peer_address());
@@ -852,7 +829,7 @@ TEST_P(QuicSessionTestServer, ServerReplyToConnecitivityProbe) {
EXPECT_EQ(old_peer_address, session_.peer_address());
}
-TEST_P(QuicSessionTestServer, IncreasedTimeoutAfterCryptoHandshake) {
+TEST_P(QuicSpdySessionTestServer, IncreasedTimeoutAfterCryptoHandshake) {
EXPECT_EQ(kInitialIdleTimeoutSecs + 3,
QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
CryptoHandshakeMessage msg;
@@ -861,19 +838,15 @@ TEST_P(QuicSessionTestServer, IncreasedTimeoutAfterCryptoHandshake) {
QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds());
}
-TEST_P(QuicSessionTestServer, RstStreamBeforeHeadersDecompressed) {
+TEST_P(QuicSpdySessionTestServer, RstStreamBeforeHeadersDecompressed) {
// Send two bytes of payload.
QuicStreamFrame data1(GetNthClientInitiatedId(0), false, 0,
QuicStringPiece("HT"));
session_.OnStreamFrame(data1);
EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_, OnStreamReset(GetNthClientInitiatedId(0), _));
- } else {
- EXPECT_CALL(*connection_, SendRstStream(GetNthClientInitiatedId(0), _, _));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(GetNthClientInitiatedId(0), _));
QuicRstStreamFrame rst1(kInvalidControlFrameId, GetNthClientInitiatedId(0),
QUIC_ERROR_PROCESSING_STREAM, 0);
session_.OnRstStream(rst1);
@@ -882,7 +855,7 @@ TEST_P(QuicSessionTestServer, RstStreamBeforeHeadersDecompressed) {
EXPECT_TRUE(connection_->connected());
}
-TEST_P(QuicSessionTestServer, OnStreamFrameFinStaticStreamId) {
+TEST_P(QuicSpdySessionTestServer, OnStreamFrameFinStaticStreamId) {
// Send two bytes of payload.
QuicStreamFrame data1(kCryptoStreamId, true, 0, QuicStringPiece("HT"));
EXPECT_CALL(*connection_,
@@ -892,7 +865,7 @@ TEST_P(QuicSessionTestServer, OnStreamFrameFinStaticStreamId) {
session_.OnStreamFrame(data1);
}
-TEST_P(QuicSessionTestServer, OnRstStreamStaticStreamId) {
+TEST_P(QuicSpdySessionTestServer, OnRstStreamStaticStreamId) {
// Send two bytes of payload.
QuicRstStreamFrame rst1(kInvalidControlFrameId, kCryptoStreamId,
QUIC_ERROR_PROCESSING_STREAM, 0);
@@ -903,7 +876,7 @@ TEST_P(QuicSessionTestServer, OnRstStreamStaticStreamId) {
session_.OnRstStream(rst1);
}
-TEST_P(QuicSessionTestServer, OnStreamFrameInvalidStreamId) {
+TEST_P(QuicSpdySessionTestServer, OnStreamFrameInvalidStreamId) {
// Send two bytes of payload.
QuicStreamFrame data1(kInvalidStreamId, true, 0, QuicStringPiece("HT"));
EXPECT_CALL(*connection_,
@@ -913,7 +886,7 @@ TEST_P(QuicSessionTestServer, OnStreamFrameInvalidStreamId) {
session_.OnStreamFrame(data1);
}
-TEST_P(QuicSessionTestServer, OnRstStreamInvalidStreamId) {
+TEST_P(QuicSpdySessionTestServer, OnRstStreamInvalidStreamId) {
// Send two bytes of payload.
QuicRstStreamFrame rst1(kInvalidControlFrameId, kInvalidStreamId,
QUIC_ERROR_PROCESSING_STREAM, 0);
@@ -924,7 +897,7 @@ TEST_P(QuicSessionTestServer, OnRstStreamInvalidStreamId) {
session_.OnRstStream(rst1);
}
-TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedStream) {
+TEST_P(QuicSpdySessionTestServer, HandshakeUnblocksFlowControlBlockedStream) {
// Test that if a stream is flow control blocked, then on receipt of the SHLO
// containing a suitable send window offset, the stream becomes unblocked.
@@ -938,40 +911,25 @@ TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedStream) {
EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(AtLeast(1));
- } else {
- EXPECT_CALL(*connection_, SendBlocked(_)).Times(AtLeast(1));
- EXPECT_CALL(*connection_, SendBlocked(0));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(AtLeast(1));
stream2->WriteOrBufferBody(body, false, nullptr);
EXPECT_TRUE(stream2->flow_controller()->IsBlocked());
EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
- if (!session_.session_unblocks_stream()) {
- // The handshake message will call OnCanWrite, so the stream can resume
- // writing.
- EXPECT_CALL(*stream2, OnCanWrite());
- }
// Now complete the crypto handshake, resulting in an increased flow control
// send window.
CryptoHandshakeMessage msg;
session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
- if (session_.session_unblocks_stream()) {
- EXPECT_TRUE(
- QuicSessionPeer::IsStreamWriteBlocked(&session_, stream2->id()));
- } else {
- EXPECT_FALSE(
- QuicSessionPeer::IsStreamWriteBlocked(&session_, stream2->id()));
- }
+ EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(&session_, stream2->id()));
// Stream is now unblocked.
EXPECT_FALSE(stream2->flow_controller()->IsBlocked());
EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
}
-TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedCryptoStream) {
+TEST_P(QuicSpdySessionTestServer,
+ HandshakeUnblocksFlowControlBlockedCryptoStream) {
// Test that if the crypto 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);
@@ -984,13 +942,8 @@ TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedCryptoStream) {
EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked());
EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
- } else {
- // Write until the crypto stream is flow control blocked.
- EXPECT_CALL(*connection_, SendBlocked(kCryptoStreamId));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
for (QuicStreamId i = 0;
!crypto_stream->flow_controller()->IsBlocked() && i < 1000u; i++) {
EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
@@ -1011,22 +964,12 @@ TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedCryptoStream) {
EXPECT_FALSE(session_.HasDataToWrite());
EXPECT_TRUE(crypto_stream->HasBufferedData());
- if (!session_.session_unblocks_stream()) {
- // The handshake message will call OnCanWrite, so the stream can
- // resume writing.
- EXPECT_CALL(*crypto_stream, OnCanWrite());
- }
// Now complete the crypto handshake, resulting in an increased flow control
// send window.
CryptoHandshakeMessage msg;
session_.GetMutableCryptoStream()->OnHandshakeMessage(msg);
- if (session_.session_unblocks_stream()) {
- EXPECT_TRUE(
- QuicSessionPeer::IsStreamWriteBlocked(&session_, kCryptoStreamId));
- } else {
- EXPECT_FALSE(
- QuicSessionPeer::IsStreamWriteBlocked(&session_, kCryptoStreamId));
- }
+ EXPECT_TRUE(
+ QuicSessionPeer::IsStreamWriteBlocked(&session_, kCryptoStreamId));
// Stream is now unblocked and will no longer have buffered data.
EXPECT_FALSE(crypto_stream->flow_controller()->IsBlocked());
EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
@@ -1039,7 +982,7 @@ TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedCryptoStream) {
// NOTE: It's not possible to use the standard MAYBE_ convention to disable
// this test on iOS because when this test gets instantiated it ends up with
// various names that are dependent on the parameters passed.
-TEST_P(QuicSessionTestServer,
+TEST_P(QuicSpdySessionTestServer,
HandshakeUnblocksFlowControlBlockedHeadersStream) {
// Test that if the header stream is flow control blocked, then if the SHLO
// contains a larger send window offset, the stream becomes unblocked.
@@ -1055,12 +998,8 @@ TEST_P(QuicSessionTestServer,
EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
QuicStreamId stream_id = 5;
// Write until the header stream is flow control blocked.
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
- } else {
- EXPECT_CALL(*connection_, SendBlocked(kHeadersStreamId));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
SpdyHeaderBlock headers;
while (!headers_stream->flow_controller()->IsBlocked() && stream_id < 2000) {
EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
@@ -1090,19 +1029,14 @@ TEST_P(QuicSessionTestServer,
EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked());
EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
- if (session_.session_unblocks_stream()) {
- EXPECT_TRUE(headers_stream->HasBufferedData());
- EXPECT_TRUE(
- QuicSessionPeer::IsStreamWriteBlocked(&session_, kHeadersStreamId));
- } else {
- EXPECT_FALSE(headers_stream->HasBufferedData());
- EXPECT_FALSE(
- QuicSessionPeer::IsStreamWriteBlocked(&session_, kHeadersStreamId));
- }
+ EXPECT_TRUE(headers_stream->HasBufferedData());
+ EXPECT_TRUE(
+ QuicSessionPeer::IsStreamWriteBlocked(&session_, kHeadersStreamId));
}
#endif // !defined(OS_IOS)
-TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstOutOfOrder) {
+TEST_P(QuicSpdySessionTestServer,
+ ConnectionFlowControlAccountingRstOutOfOrder) {
// Test that when we receive an out of order stream RST we correctly adjust
// our connection level flow control receive window.
// On close, the stream should mark as consumed all bytes between the highest
@@ -1112,21 +1046,10 @@ TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstOutOfOrder) {
const QuicStreamOffset kByteOffset =
1 + kInitialSessionFlowControlWindowForTest / 2;
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(2)
- .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
- EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
- } else {
- // Expect no stream WINDOW_UPDATE frames, as stream read side closed.
- EXPECT_CALL(*connection_, SendWindowUpdate(stream->id(), _)).Times(0);
- // We do expect a connection level WINDOW_UPDATE when the stream is reset.
- EXPECT_CALL(*connection_,
- SendWindowUpdate(
- 0, kInitialSessionFlowControlWindowForTest + kByteOffset));
-
- EXPECT_CALL(*connection_, SendRstStream(stream->id(), _, _));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(2)
+ .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
QUIC_STREAM_CANCELLED, kByteOffset);
session_.OnRstStream(rst_frame);
@@ -1134,7 +1057,8 @@ TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstOutOfOrder) {
EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed());
}
-TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAndLocalReset) {
+TEST_P(QuicSpdySessionTestServer,
+ ConnectionFlowControlAccountingFinAndLocalReset) {
// Test the situation where we receive a FIN on a stream, and before we fully
// consume all the data from the sequencer buffer we locally RST the stream.
// The bytes between highest consumed byte, and the final byte offset that we
@@ -1154,18 +1078,14 @@ TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAndLocalReset) {
stream->flow_controller()->highest_received_byte_offset());
// Reset stream locally.
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
- } else {
- EXPECT_CALL(*connection_, SendRstStream(stream->id(), _, _));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
stream->Reset(QUIC_STREAM_CANCELLED);
EXPECT_EQ(kByteOffset + frame.data_length,
session_.flow_controller()->bytes_consumed());
}
-TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAfterRst) {
+TEST_P(QuicSpdySessionTestServer, ConnectionFlowControlAccountingFinAfterRst) {
// Test that when we RST the stream (and tear down stream state), and then
// receive a FIN from the peer, we correctly adjust our connection level flow
// control receive window.
@@ -1182,12 +1102,8 @@ TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAfterRst) {
// Reset our stream: this results in the stream being closed locally.
TestStream* stream = session_.CreateOutgoingDynamicStream();
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
- } else {
- EXPECT_CALL(*connection_, SendRstStream(stream->id(), _, _));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
stream->Reset(QUIC_STREAM_CANCELLED);
// Now receive a response from the peer with a FIN. We should handle this by
@@ -1207,7 +1123,7 @@ TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAfterRst) {
session_.flow_controller()->highest_received_byte_offset());
}
-TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstAfterRst) {
+TEST_P(QuicSpdySessionTestServer, ConnectionFlowControlAccountingRstAfterRst) {
// Test that when we RST the stream (and tear down stream state), and then
// receive a RST from the peer, we correctly adjust our connection level flow
// control receive window.
@@ -1224,12 +1140,8 @@ TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstAfterRst) {
// Reset our stream: this results in the stream being closed locally.
TestStream* stream = session_.CreateOutgoingDynamicStream();
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
- } else {
- EXPECT_CALL(*connection_, SendRstStream(stream->id(), _, _));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
stream->Reset(QUIC_STREAM_CANCELLED);
EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream));
@@ -1247,7 +1159,7 @@ TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstAfterRst) {
session_.flow_controller()->highest_received_byte_offset());
}
-TEST_P(QuicSessionTestServer, InvalidStreamFlowControlWindowInHandshake) {
+TEST_P(QuicSpdySessionTestServer, InvalidStreamFlowControlWindowInHandshake) {
// Test that receipt of an invalid (< default) stream flow control window from
// the peer results in the connection being torn down.
const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
@@ -1259,7 +1171,7 @@ TEST_P(QuicSessionTestServer, InvalidStreamFlowControlWindowInHandshake) {
session_.OnConfigNegotiated();
}
-TEST_P(QuicSessionTestServer, InvalidSessionFlowControlWindowInHandshake) {
+TEST_P(QuicSpdySessionTestServer, InvalidSessionFlowControlWindowInHandshake) {
// Test that receipt of an invalid (< default) session flow control window
// from the peer results in the connection being torn down.
const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
@@ -1272,7 +1184,7 @@ TEST_P(QuicSessionTestServer, InvalidSessionFlowControlWindowInHandshake) {
}
// Test negotiation of custom server initial flow control window.
-TEST_P(QuicSessionTestServer, CustomFlowControlWindow) {
+TEST_P(QuicSpdySessionTestServer, CustomFlowControlWindow) {
QuicTagVector copt;
copt.push_back(kIFW7);
QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
@@ -1282,7 +1194,7 @@ TEST_P(QuicSessionTestServer, CustomFlowControlWindow) {
session_.flow_controller()));
}
-TEST_P(QuicSessionTestServer, FlowControlWithInvalidFinalOffset) {
+TEST_P(QuicSpdySessionTestServer, FlowControlWithInvalidFinalOffset) {
// Test that if we receive a stream RST with a highest byte offset that
// violates flow control, that we close the connection.
const uint64_t kLargeOffset = kInitialSessionFlowControlWindowForTest + 1;
@@ -1292,12 +1204,8 @@ TEST_P(QuicSessionTestServer, FlowControlWithInvalidFinalOffset) {
// Check that stream frame + FIN results in connection close.
TestStream* stream = session_.CreateOutgoingDynamicStream();
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
- } else {
- EXPECT_CALL(*connection_, SendRstStream(stream->id(), _, _));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
stream->Reset(QUIC_STREAM_CANCELLED);
QuicStreamFrame frame(stream->id(), true, kLargeOffset, QuicStringPiece());
session_.OnStreamFrame(frame);
@@ -1308,7 +1216,7 @@ TEST_P(QuicSessionTestServer, FlowControlWithInvalidFinalOffset) {
session_.OnRstStream(rst_frame);
}
-TEST_P(QuicSessionTestServer, WindowUpdateUnblocksHeadersStream) {
+TEST_P(QuicSpdySessionTestServer, WindowUpdateUnblocksHeadersStream) {
// Test that a flow control blocked headers stream gets unblocked on recipt of
// a WINDOW_UPDATE frame.
@@ -1331,7 +1239,8 @@ TEST_P(QuicSessionTestServer, WindowUpdateUnblocksHeadersStream) {
EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
}
-TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) {
+TEST_P(QuicSpdySessionTestServer,
+ TooManyUnfinishedStreamsCauseServerRejectStream) {
// If a buggy/malicious peer creates too many streams that are not ended
// with a FIN or RST then we send an RST to refuse streams.
const QuicStreamId kMaxStreams = 5;
@@ -1345,26 +1254,15 @@ TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) {
QuicStreamFrame data1(i, false, 0, QuicStringPiece("HT"));
session_.OnStreamFrame(data1);
// EXPECT_EQ(1u, session_.GetNumOpenStreams());
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
- EXPECT_CALL(*connection_, OnStreamReset(i, _));
- } else {
- EXPECT_CALL(*connection_, SendRstStream(i, _, _));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(i, _));
session_.CloseStream(i);
}
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
- EXPECT_CALL(*connection_,
- OnStreamReset(kFinalStreamId, QUIC_REFUSED_STREAM))
- .Times(1);
- } else {
- EXPECT_CALL(*connection_,
- SendRstStream(kFinalStreamId, QUIC_REFUSED_STREAM, _))
- .Times(1);
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
+ EXPECT_CALL(*connection_, OnStreamReset(kFinalStreamId, QUIC_REFUSED_STREAM))
+ .Times(1);
// Create one more data streams to exceed limit of open stream.
QuicStreamFrame data1(kFinalStreamId, false, 0, QuicStringPiece("HT"));
session_.OnStreamFrame(data1);
@@ -1374,17 +1272,12 @@ TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) {
session_.PostProcessAfterData();
}
-TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpened) {
+TEST_P(QuicSpdySessionTestServer, DrainingStreamsDoNotCountAsOpened) {
// Verify that a draining stream (which has received a FIN but not consumed
// it) does not count against the open quota (because it is closed from the
// protocol point of view).
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
- EXPECT_CALL(*connection_, OnStreamReset(_, QUIC_REFUSED_STREAM)).Times(0);
- } else {
- EXPECT_CALL(*connection_, SendRstStream(_, QUIC_REFUSED_STREAM, _))
- .Times(0);
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
+ EXPECT_CALL(*connection_, OnStreamReset(_, QUIC_REFUSED_STREAM)).Times(0);
const QuicStreamId kMaxStreams = 5;
QuicSessionPeer::SetMaxOpenIncomingStreams(&session_, kMaxStreams);
@@ -1405,7 +1298,7 @@ TEST_P(QuicSessionTestServer, DrainingStreamsDoNotCountAsOpened) {
session_.PostProcessAfterData();
}
-TEST_P(QuicSessionTestServer, TestMaxIncomingAndOutgoingStreamsAllowed) {
+TEST_P(QuicSpdySessionTestServer, TestMaxIncomingAndOutgoingStreamsAllowed) {
// Tests that on server side, the value of max_open_incoming/outgoing streams
// are setup correctly during negotiation.
// The value for outgoing stream is limited to negotiated value and for
@@ -1421,16 +1314,17 @@ TEST_P(QuicSessionTestServer, TestMaxIncomingAndOutgoingStreamsAllowed) {
kDefaultMaxStreamsPerConnection);
}
-class QuicSessionTestClient : public QuicSessionTestBase {
+class QuicSpdySessionTestClient : public QuicSpdySessionTestBase {
protected:
- QuicSessionTestClient() : QuicSessionTestBase(Perspective::IS_CLIENT) {}
+ QuicSpdySessionTestClient()
+ : QuicSpdySessionTestBase(Perspective::IS_CLIENT) {}
};
INSTANTIATE_TEST_CASE_P(Tests,
- QuicSessionTestClient,
+ QuicSpdySessionTestClient,
::testing::ValuesIn(AllSupportedVersions()));
-TEST_P(QuicSessionTestClient, AvailableStreamsClient) {
+TEST_P(QuicSpdySessionTestClient, AvailableStreamsClient) {
ASSERT_TRUE(session_.GetOrCreateDynamicStream(6) != nullptr);
// Both 2 and 4 should be available.
EXPECT_TRUE(QuicSessionPeer::IsStreamAvailable(&session_, 2));
@@ -1441,7 +1335,7 @@ TEST_P(QuicSessionTestClient, AvailableStreamsClient) {
EXPECT_FALSE(QuicSessionPeer::IsStreamAvailable(&session_, 5));
}
-TEST_P(QuicSessionTestClient, RecordFinAfterReadSideClosed) {
+TEST_P(QuicSpdySessionTestClient, RecordFinAfterReadSideClosed) {
// Verify that an incoming FIN is recorded in a stream object even if the read
// side has been closed. This prevents an entry from being made in
// locally_closed_streams_highest_offset_ (which will never be deleted).
@@ -1457,12 +1351,8 @@ TEST_P(QuicSessionTestClient, RecordFinAfterReadSideClosed) {
EXPECT_TRUE(stream->fin_received());
// Reset stream locally.
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
- } else {
- EXPECT_CALL(*connection_, SendRstStream(stream->id(), _, _));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
stream->Reset(QUIC_STREAM_CANCELLED);
EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream));
@@ -1479,7 +1369,7 @@ TEST_P(QuicSessionTestClient, RecordFinAfterReadSideClosed) {
QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(&session_).size());
}
-TEST_P(QuicSessionTestClient, TestMaxIncomingAndOutgoingStreamsAllowed) {
+TEST_P(QuicSpdySessionTestClient, TestMaxIncomingAndOutgoingStreamsAllowed) {
// Tests that on client side, the value of max_open_incoming/outgoing streams
// are setup correctly during negotiation.
// When flag is true, the value for outgoing stream is limited to negotiated
@@ -1491,7 +1381,7 @@ TEST_P(QuicSessionTestClient, TestMaxIncomingAndOutgoingStreamsAllowed) {
kDefaultMaxStreamsPerConnection);
}
-TEST_P(QuicSessionTestClient, EnableDHDTThroughConnectionOption) {
+TEST_P(QuicSpdySessionTestClient, EnableDHDTThroughConnectionOption) {
QuicTagVector copt;
copt.push_back(kDHDT);
QuicConfigPeer::SetConnectionOptionsToSend(session_.config(), copt);
@@ -1501,7 +1391,8 @@ TEST_P(QuicSessionTestClient, EnableDHDTThroughConnectionOption) {
0UL);
}
-TEST_P(QuicSessionTestClient, WritePriority) {
+TEST_P(QuicSpdySessionTestClient, WritePriority) {
+ QuicSpdySessionPeer::SetHeadersStream(&session_, nullptr);
TestHeadersStream* headers_stream = new TestHeadersStream(&session_);
QuicSpdySessionPeer::SetHeadersStream(&session_, headers_stream);
@@ -1536,27 +1427,29 @@ TEST_P(QuicSessionTestClient, WritePriority) {
}
}
-TEST_P(QuicSessionTestServer, ZombieStreams) {
+TEST_P(QuicSpdySessionTestServer, ZombieStreams) {
TestStream* stream2 = session_.CreateOutgoingDynamicStream();
QuicStreamPeer::SetStreamBytesWritten(3, stream2);
EXPECT_TRUE(stream2->IsWaitingForAcks());
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_, OnStreamReset(2, _));
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(2, _));
+ session_.CloseStream(2);
+ if (GetQuicReloadableFlag(quic_reset_stream_is_not_zombie)) {
+ EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), 2));
+ ASSERT_EQ(1u, session_.closed_streams()->size());
+ EXPECT_EQ(2u, session_.closed_streams()->front()->id());
} else {
- EXPECT_CALL(*connection_, SendRstStream(2, _, _));
+ EXPECT_TRUE(QuicContainsKey(session_.zombie_streams(), 2));
+ EXPECT_TRUE(session_.closed_streams()->empty());
}
- session_.CloseStream(2);
- EXPECT_TRUE(QuicContainsKey(session_.zombie_streams(), 2));
- EXPECT_TRUE(session_.closed_streams()->empty());
session_.OnStreamDoneWaitingForAcks(2);
EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), 2));
EXPECT_EQ(1u, session_.closed_streams()->size());
EXPECT_EQ(2u, session_.closed_streams()->front()->id());
}
-TEST_P(QuicSessionTestServer, OnStreamFrameLost) {
+TEST_P(QuicSpdySessionTestServer, OnStreamFrameLost) {
QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
InSequence s;
@@ -1619,7 +1512,7 @@ TEST_P(QuicSessionTestServer, OnStreamFrameLost) {
EXPECT_FALSE(session_.WillingAndAbleToWrite());
}
-TEST_P(QuicSessionTestServer, DonotRetransmitDataOfClosedStreams) {
+TEST_P(QuicSpdySessionTestServer, DonotRetransmitDataOfClosedStreams) {
QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
InSequence s;
@@ -1643,12 +1536,8 @@ TEST_P(QuicSessionTestServer, DonotRetransmitDataOfClosedStreams) {
session_.MarkConnectionLevelWriteBlocked(stream6->id());
// Reset stream 4 locally.
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_, OnStreamReset(stream4->id(), _));
- } else {
- EXPECT_CALL(*connection_, SendRstStream(stream4->id(), _, _));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(stream4->id(), _));
stream4->Reset(QUIC_STREAM_CANCELLED);
// Verify stream 4 is removed from streams with lost data list.
@@ -1656,16 +1545,14 @@ TEST_P(QuicSessionTestServer, DonotRetransmitDataOfClosedStreams) {
EXPECT_CALL(*stream6, HasPendingRetransmission()).WillOnce(Return(false));
EXPECT_CALL(*stream2, OnCanWrite());
EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(false));
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
EXPECT_CALL(*stream2, OnCanWrite());
EXPECT_CALL(*stream6, OnCanWrite());
session_.OnCanWrite();
}
-TEST_P(QuicSessionTestServer, RetransmitFrames) {
+TEST_P(QuicSpdySessionTestServer, RetransmitFrames) {
QuicConnectionPeer::SetSessionDecidesWhatToWrite(connection_);
MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
@@ -1674,11 +1561,9 @@ TEST_P(QuicSessionTestServer, RetransmitFrames) {
TestStream* stream2 = session_.CreateOutgoingDynamicStream();
TestStream* stream4 = session_.CreateOutgoingDynamicStream();
TestStream* stream6 = session_.CreateOutgoingDynamicStream();
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
- session_.SendWindowUpdate(stream2->id(), 9);
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
+ session_.SendWindowUpdate(stream2->id(), 9);
QuicStreamFrame frame1(stream2->id(), false, 0, 9);
QuicStreamFrame frame2(stream4->id(), false, 0, 9);
@@ -1692,17 +1577,15 @@ TEST_P(QuicSessionTestServer, RetransmitFrames) {
EXPECT_FALSE(session_.WillingAndAbleToWrite());
EXPECT_CALL(*stream2, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
- if (session_.use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
EXPECT_CALL(*stream4, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
EXPECT_CALL(*stream6, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
session_.RetransmitFrames(frames, TLP_RETRANSMISSION);
}
-TEST_P(QuicSessionTestServer, OnPriorityFrame) {
+TEST_P(QuicSpdySessionTestServer, OnPriorityFrame) {
QuicStreamId stream_id = GetNthClientInitiatedId(0);
TestStream* stream = session_.CreateIncomingDynamicStream(stream_id);
session_.OnPriorityFrame(stream_id, kV3HighestPriority);
diff --git a/chromium/net/quic/core/quic_spdy_stream.cc b/chromium/net/quic/core/quic_spdy_stream.cc
index 016587ca85c..48c17cdd8d5 100644
--- a/chromium/net/quic/core/quic_spdy_stream.cc
+++ b/chromium/net/quic/core/quic_spdy_stream.cc
@@ -26,23 +26,25 @@ namespace net {
" ")
QuicSpdyStream::QuicSpdyStream(QuicStreamId id, QuicSpdySession* spdy_session)
- : QuicStream(id, spdy_session),
+ : QuicStream(id, spdy_session, /*is_static=*/false),
spdy_session_(spdy_session),
visitor_(nullptr),
headers_decompressed_(false),
- priority_(kDefaultPriority),
trailers_decompressed_(false),
trailers_consumed_(false) {
DCHECK_NE(kCryptoStreamId, id);
// Don't receive any callbacks from the sequencer until headers
// are complete.
sequencer()->SetBlockedUntilFlush();
- spdy_session_->RegisterStreamPriority(id, priority_);
+ if (!session()->register_streams_early()) {
+ spdy_session_->RegisterStreamPriority(id, /*is_static=*/false, priority());
+ }
}
QuicSpdyStream::~QuicSpdyStream() {
- if (spdy_session_ != nullptr) {
- spdy_session_->UnregisterStreamPriority(id());
+ if (spdy_session_ != nullptr && !session()->register_streams_early()) {
+ spdy_session_->UnregisterStreamPriority(id(),
+ /*is_static=*/false);
}
}
@@ -51,7 +53,7 @@ size_t QuicSpdyStream::WriteHeaders(
bool fin,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
size_t bytes_written = spdy_session_->WriteHeaders(
- id(), std::move(header_block), fin, priority_, std::move(ack_listener));
+ id(), std::move(header_block), fin, priority(), std::move(ack_listener));
if (fin) {
// TODO(rch): Add test to ensure fin_sent_ is set whenever a fin is sent.
set_fin_sent(true);
@@ -87,8 +89,9 @@ size_t QuicSpdyStream::WriteTrailers(
// 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 = spdy_session_->WriteHeaders(
- id(), std::move(trailer_block), kFin, priority_, std::move(ack_listener));
+ size_t bytes_written =
+ spdy_session_->WriteHeaders(id(), std::move(trailer_block), kFin,
+ priority(), std::move(ack_listener));
set_fin_sent(kFin);
// Trailers are the last thing to be sent on a stream, but if there is still
@@ -137,12 +140,6 @@ void QuicSpdyStream::ConsumeHeaderList() {
}
}
-void QuicSpdyStream::SetPriority(SpdyPriority priority) {
- DCHECK_EQ(0u, stream_bytes_written());
- priority_ = priority;
- spdy_session_->UpdateStreamPriority(id(), priority);
-}
-
void QuicSpdyStream::OnStreamHeadersPriority(SpdyPriority priority) {
DCHECK_EQ(Perspective::IS_SERVER, session()->connection()->perspective());
SetPriority(priority);
@@ -308,10 +305,6 @@ bool QuicSpdyStream::FinishedReadingTrailers() const {
}
}
-SpdyPriority QuicSpdyStream::priority() const {
- return priority_;
-}
-
void QuicSpdyStream::ClearSession() {
spdy_session_ = nullptr;
}
diff --git a/chromium/net/quic/core/quic_spdy_stream.h b/chromium/net/quic/core/quic_spdy_stream.h
index 48e92200021..947b323bf5c 100644
--- a/chromium/net/quic/core/quic_spdy_stream.h
+++ b/chromium/net/quic/core/quic_spdy_stream.h
@@ -35,12 +35,6 @@ class QuicStreamPeer;
class QuicSpdySession;
-// This is somewhat arbitrary. It's possible, but unlikely, we will either fail
-// to set a priority client-side, or cancel a stream before stripping the
-// priority from the wire server-side. In either case, start out with a
-// priority in the middle.
-const SpdyPriority kDefaultPriority = 3;
-
// A QUIC stream that can send and receive HTTP2 (SPDY) headers.
class QUIC_EXPORT_PRIVATE QuicSpdyStream : public QuicStream {
public:
@@ -164,12 +158,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream : public QuicStream {
// been received and there are no trailers.
bool FinishedReadingTrailers() const;
- SpdyPriority priority() const;
-
- // Sets priority_ to priority. This should only be called before bytes are
- // written to the server.
- void SetPriority(SpdyPriority priority);
-
// Called when owning session is getting deleted to avoid subsequent
// use of the spdy_session_ member.
void ClearSession();
@@ -202,8 +190,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream : public QuicStream {
Visitor* visitor_;
// True if the headers have been completely decompressed.
bool headers_decompressed_;
- // The priority of the stream, once parsed.
- SpdyPriority priority_;
// Contains a copy of the decompressed header (name, value) pairs until they
// are consumed via Readv.
QuicHeaderList header_list_;
diff --git a/chromium/net/quic/core/quic_spdy_stream_test.cc b/chromium/net/quic/core/quic_spdy_stream_test.cc
index 1b524942177..10b596c3880 100644
--- a/chromium/net/quic/core/quic_spdy_stream_test.cc
+++ b/chromium/net/quic/core/quic_spdy_stream_test.cc
@@ -126,6 +126,7 @@ class QuicSpdyStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
SupportedVersions(GetParam()));
session_ =
QuicMakeUnique<testing::StrictMock<MockQuicSpdySession>>(connection_);
+ session_->Initialize();
stream_ = new TestStream(GetNthClientInitiatedId(0), session_.get(),
stream_should_process_data);
session_->ActivateStream(QuicWrapUnique(stream_));
@@ -436,11 +437,7 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlBlocked) {
const uint64_t kOverflow = 15;
QuicString body(kWindow + kOverflow, 'a');
- if (session_->use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- } else {
- EXPECT_CALL(*connection_, SendBlocked(GetNthClientInitiatedId(0)));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillOnce(Return(QuicConsumedData(kWindow, true)));
stream_->WriteOrBufferData(body, false, nullptr);
@@ -527,15 +524,7 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlWindowUpdate) {
// window of kWindow bytes.
QuicStreamFrame frame2(GetNthClientInitiatedId(0), false, kWindow / 3,
QuicStringPiece(body));
- if (session_->use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- } else {
- EXPECT_CALL(*connection_,
- SendWindowUpdate(GetNthClientInitiatedId(0),
- QuicFlowControllerPeer::ReceiveWindowOffset(
- stream_->flow_controller()) +
- 2 * kWindow / 3));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
stream_->OnStreamFrame(frame2);
EXPECT_EQ(kWindow, QuicFlowControllerPeer::ReceiveWindowSize(
stream_->flow_controller()));
@@ -584,18 +573,7 @@ TEST_P(QuicSpdyStreamTest, ConnectionFlowControlWindowUpdate) {
// Now receive a further single byte on one stream - again this does not
// trigger a stream WINDOW_UPDATE, but now the connection flow control window
// is over half full and thus a connection WINDOW_UPDATE is sent.
- if (session_->use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_));
- } else {
- EXPECT_CALL(*connection_, SendWindowUpdate(GetNthClientInitiatedId(0), _))
- .Times(0);
- EXPECT_CALL(*connection_, SendWindowUpdate(GetNthClientInitiatedId(1), _))
- .Times(0);
- EXPECT_CALL(*connection_,
- SendWindowUpdate(0, QuicFlowControllerPeer::ReceiveWindowOffset(
- session_->flow_controller()) +
- 1 + kWindow / 2));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_));
QuicStreamFrame frame3(GetNthClientInitiatedId(0), false, (kWindow / 4),
QuicStringPiece("a"));
stream_->OnStreamFrame(frame3);
diff --git a/chromium/net/quic/core/quic_stream.cc b/chromium/net/quic/core/quic_stream.cc
index 2ca58558bef..72e15671f23 100644
--- a/chromium/net/quic/core/quic_stream.cc
+++ b/chromium/net/quic/core/quic_stream.cc
@@ -13,6 +13,8 @@
#include "net/quic/platform/api/quic_str_cat.h"
#include "net/quic/platform/api/quic_string.h"
+using net::SpdyPriority;
+
namespace net {
#define ENDPOINT \
@@ -40,10 +42,14 @@ size_t GetReceivedFlowControlWindow(QuicSession* session) {
} // namespace
-QuicStream::QuicStream(QuicStreamId id, QuicSession* session)
+// static
+const SpdyPriority QuicStream::kDefaultPriority;
+
+QuicStream::QuicStream(QuicStreamId id, QuicSession* session, bool is_static)
: sequencer_(this, session->connection()->clock()),
id_(id),
session_(session),
+ priority_(kDefaultPriority),
stream_bytes_read_(0),
stream_error_(QUIC_STREAM_NO_ERROR),
connection_error_(QUIC_NO_ERROR),
@@ -72,9 +78,12 @@ QuicStream::QuicStream(QuicStreamId id, QuicSession* session)
ack_listener_(nullptr),
send_buffer_(
session->connection()->helper()->GetStreamSendBufferAllocator()),
- buffered_data_threshold_(
- GetQuicFlag(FLAGS_quic_buffered_data_threshold)) {
+ buffered_data_threshold_(GetQuicFlag(FLAGS_quic_buffered_data_threshold)),
+ is_static_(is_static) {
SetFromConfig();
+ if (session_->register_streams_early()) {
+ session_->RegisterStreamPriority(id, is_static_, priority_);
+ }
}
QuicStream::~QuicStream() {
@@ -85,6 +94,9 @@ QuicStream::~QuicStream() {
<< send_buffer_.stream_bytes_outstanding()
<< ", fin_outstanding: " << fin_outstanding_;
}
+ if (session_ != nullptr && session_->register_streams_early()) {
+ session_->UnregisterStreamPriority(id(), is_static_);
+ }
}
void QuicStream::SetFromConfig() {}
@@ -215,6 +227,16 @@ void QuicStream::CloseConnectionWithDetails(QuicErrorCode error,
error, details, ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
+SpdyPriority QuicStream::priority() const {
+ return priority_;
+}
+
+void QuicStream::SetPriority(SpdyPriority priority) {
+ DCHECK_EQ(0u, stream_bytes_written());
+ priority_ = priority;
+ session_->UpdateStreamPriority(id(), priority);
+}
+
void QuicStream::WriteOrBufferData(
QuicStringPiece data,
bool fin,
@@ -263,24 +285,7 @@ void QuicStream::WriteOrBufferData(
void QuicStream::OnCanWrite() {
if (HasPendingRetransmission()) {
- const bool session_unblocks_stream = session_->session_unblocks_stream();
WritePendingRetransmission();
- if (session_unblocks_stream) {
- // Exit early to allow other streams to write pending retransmissions if
- // any.
- return;
- }
- if (HasPendingRetransmission()) {
- // Stream did not finish retransmission, session will unblock this stream
- // later.
- return;
- }
- const bool fin_only = !HasBufferedData() && fin_buffered_ && !fin_sent_;
- if ((!flow_controller_.IsBlocked() && HasBufferedData()) || fin_only) {
- // Stream finished retransmission. If there is new data which can be sent,
- // tell the session to unblock this stream later.
- session_->MarkConnectionLevelWriteBlocked(id_);
- }
// Exit early to allow other streams to write pending retransmissions if
// any.
return;
@@ -374,7 +379,6 @@ QuicConsumedData QuicStream::WritevData(const struct iovec* iov,
}
QuicConsumedData QuicStream::WriteMemSlices(QuicMemSliceSpan span, bool fin) {
- DCHECK(session_->can_use_slices());
QuicConsumedData consumed_data(0, false);
if (span.empty() && !fin) {
QUIC_BUG << "span.empty() && !fin";
@@ -448,13 +452,13 @@ void QuicStream::CloseReadSide() {
if (read_side_closed_) {
return;
}
- QUIC_DLOG(INFO) << ENDPOINT << "Done reading from stream " << id();
+ QUIC_DVLOG(1) << ENDPOINT << "Done reading from stream " << id();
read_side_closed_ = true;
sequencer_.ReleaseBuffer();
if (write_side_closed_) {
- QUIC_DLOG(INFO) << ENDPOINT << "Closing stream " << id();
+ QUIC_DVLOG(1) << ENDPOINT << "Closing stream " << id();
session_->CloseStream(id());
}
}
@@ -463,11 +467,11 @@ void QuicStream::CloseWriteSide() {
if (write_side_closed_) {
return;
}
- QUIC_DLOG(INFO) << ENDPOINT << "Done writing to stream " << id();
+ QUIC_DVLOG(1) << ENDPOINT << "Done writing to stream " << id();
write_side_closed_ = true;
if (read_side_closed_) {
- QUIC_DLOG(INFO) << ENDPOINT << "Closing stream " << id();
+ QUIC_DVLOG(1) << ENDPOINT << "Closing stream " << id();
session_->CloseStream(id());
}
}
@@ -486,7 +490,7 @@ HandshakeProtocol QuicStream::handshake_protocol() const {
}
void QuicStream::StopReading() {
- QUIC_DLOG(INFO) << ENDPOINT << "Stop reading from stream " << id();
+ QUIC_DVLOG(1) << ENDPOINT << "Stop reading from stream " << id();
sequencer_.StopReading();
}
@@ -503,6 +507,10 @@ void QuicStream::OnClose() {
// written on this stream before termination. Done here if needed, using a
// RST_STREAM frame.
QUIC_DLOG(INFO) << ENDPOINT << "Sending RST_STREAM in OnClose: " << id();
+ if (GetQuicReloadableFlag(quic_reset_stream_is_not_zombie)) {
+ QUIC_FLAG_COUNT(quic_reloadable_flag_quic_reset_stream_is_not_zombie);
+ session_->OnStreamDoneWaitingForAcks(id_);
+ }
session_->SendRstStream(id(), QUIC_RST_ACKNOWLEDGEMENT,
stream_bytes_written());
rst_sent_ = true;
@@ -524,18 +532,8 @@ void QuicStream::OnClose() {
void QuicStream::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
if (flow_controller_.UpdateSendWindowOffset(frame.byte_offset)) {
- if (session_->session_unblocks_stream()) {
- QUIC_FLAG_COUNT(quic_reloadable_flag_quic_streams_unblocked_by_session2);
- // Let session unblock this stream.
- session_->MarkConnectionLevelWriteBlocked(id_);
- } else {
- // Writing can be done again!
- // TODO(rjshade): This does not respect priorities (e.g. multiple
- // outstanding POSTs are unblocked on arrival of
- // SHLO with initial window).
- // As long as the connection is not flow control blocked, write on!
- OnCanWrite();
- }
+ // Let session unblock this stream.
+ session_->MarkConnectionLevelWriteBlocked(id_);
}
}
@@ -578,12 +576,8 @@ void QuicStream::AddBytesConsumed(QuicByteCount bytes) {
void QuicStream::UpdateSendWindowOffset(QuicStreamOffset new_window) {
if (flow_controller_.UpdateSendWindowOffset(new_window)) {
- if (session_->session_unblocks_stream()) {
- // Let session unblock this stream.
- session_->MarkConnectionLevelWriteBlocked(id_);
- } else {
- OnCanWrite();
- }
+ // Let session unblock this stream.
+ session_->MarkConnectionLevelWriteBlocked(id_);
}
}
@@ -601,13 +595,13 @@ bool QuicStream::OnStreamFrameAcked(QuicStreamOffset offset,
QuicByteCount newly_acked_length = 0;
if (!send_buffer_.OnStreamDataAcked(offset, data_length,
&newly_acked_length)) {
- RecordInternalErrorLocation(QUIC_STREAM_1);
+ RecordInternalErrorLocation(QUIC_STREAM_ACKED_UNSENT_DATA);
CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
"Trying to ack unsent data.");
return false;
}
if (!fin_sent_ && fin_acked) {
- RecordInternalErrorLocation(QUIC_STREAM_2);
+ RecordInternalErrorLocation(QUIC_STREAM_ACKED_UNSENT_FIN);
CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
"Trying to ack unsent fin.");
return false;
diff --git a/chromium/net/quic/core/quic_stream.h b/chromium/net/quic/core/quic_stream.h
index adc027992e1..f8c75afe7da 100644
--- a/chromium/net/quic/core/quic_stream.h
+++ b/chromium/net/quic/core/quic_stream.h
@@ -34,6 +34,7 @@
#include "net/quic/platform/api/quic_reference_counted.h"
#include "net/quic/platform/api/quic_string.h"
#include "net/quic/platform/api/quic_string_piece.h"
+#include "net/spdy/core/spdy_protocol.h"
namespace net {
@@ -45,7 +46,19 @@ class QuicSession;
class QUIC_EXPORT_PRIVATE QuicStream {
public:
- QuicStream(QuicStreamId id, QuicSession* session);
+ // This is somewhat arbitrary. It's possible, but unlikely, we will either
+ // fail to set a priority client-side, or cancel a stream before stripping the
+ // priority from the wire server-side. In either case, start out with a
+ // priority in the middle.
+ static const SpdyPriority kDefaultPriority = 3;
+ static_assert(kDefaultPriority ==
+ (kV3LowestPriority + kV3HighestPriority) / 2,
+ "Unexpected value of kDefaultPriority");
+
+ // Creates a new stream with stream_id |id| associated with |session|. If
+ // |is_static| is true, then the stream will be given precedence
+ // over other streams when determing what streams should write next.
+ QuicStream(QuicStreamId id, QuicSession* session, bool is_static);
virtual ~QuicStream();
@@ -93,6 +106,12 @@ class QUIC_EXPORT_PRIVATE QuicStream {
virtual void CloseConnectionWithDetails(QuicErrorCode error,
const QuicString& details);
+ SpdyPriority priority() const;
+
+ // Sets priority_ to priority. This should only be called before bytes are
+ // written to the server.
+ void SetPriority(SpdyPriority priority);
+
// Returns true if this stream is still waiting for acks of sent data.
// This will return false if all data has been acked, or if the stream
// is no longer interested in data being acked (which happens when
@@ -338,6 +357,8 @@ class QUIC_EXPORT_PRIVATE QuicStream {
QuicStreamId id_;
// Pointer to the owning QuicSession object.
QuicSession* session_;
+ // The priority of the stream, once parsed.
+ SpdyPriority priority_;
// Bytes read refers to payload bytes only: they do not include framing,
// encryption overhead etc.
uint64_t stream_bytes_read_;
@@ -410,6 +431,10 @@ class QUIC_EXPORT_PRIVATE QuicStream {
// Latched value of FLAGS_quic_buffered_data_threshold.
const QuicByteCount buffered_data_threshold_;
+ // If true, then this stream has precedence over other streams for write
+ // scheduling.
+ const bool is_static_;
+
DISALLOW_COPY_AND_ASSIGN(QuicStream);
};
diff --git a/chromium/net/quic/core/quic_stream_send_buffer.cc b/chromium/net/quic/core/quic_stream_send_buffer.cc
index d92205c4575..ac1ab6ef1bd 100644
--- a/chromium/net/quic/core/quic_stream_send_buffer.cc
+++ b/chromium/net/quic/core/quic_stream_send_buffer.cc
@@ -15,6 +15,16 @@
namespace net {
+namespace {
+
+struct CompareOffset {
+ bool operator()(const BufferedSlice& slice, QuicStreamOffset offset) const {
+ return slice.offset + slice.slice.length() < offset;
+ }
+};
+
+} // namespace
+
BufferedSlice::BufferedSlice(QuicMemSlice mem_slice, QuicStreamOffset offset)
: slice(std::move(mem_slice)), offset(offset) {}
@@ -35,7 +45,11 @@ QuicStreamSendBuffer::QuicStreamSendBuffer(QuicBufferAllocator* allocator)
stream_bytes_written_(0),
stream_bytes_outstanding_(0),
write_index_(-1),
- use_write_index_(GetQuicReloadableFlag(quic_use_write_index)) {}
+ free_mem_slice_out_of_order_(
+ GetQuicReloadableFlag(quic_free_mem_slice_out_of_order)),
+ enable_fast_path_on_data_acked_(
+ free_mem_slice_out_of_order_ &&
+ GetQuicReloadableFlag(quic_fast_path_on_stream_data_acked)) {}
QuicStreamSendBuffer::~QuicStreamSendBuffer() {}
@@ -81,32 +95,6 @@ void QuicStreamSendBuffer::OnStreamDataConsumed(size_t bytes_consumed) {
bool QuicStreamSendBuffer::WriteStreamData(QuicStreamOffset offset,
QuicByteCount data_length,
QuicDataWriter* writer) {
- if (use_write_index_) {
- return WriteStreamDataWithIndex(offset, data_length, writer);
- }
- for (const BufferedSlice& slice : buffered_slices_) {
- if (data_length == 0 || offset < slice.offset) {
- break;
- }
- if (offset >= slice.offset + slice.slice.length()) {
- continue;
- }
- QuicByteCount slice_offset = offset - slice.offset;
- QuicByteCount copy_length =
- std::min(data_length, slice.slice.length() - slice_offset);
- if (!writer->WriteBytes(slice.slice.data() + slice_offset, copy_length)) {
- return false;
- }
- offset += copy_length;
- data_length -= copy_length;
- }
-
- return data_length == 0;
-}
-
-bool QuicStreamSendBuffer::WriteStreamDataWithIndex(QuicStreamOffset offset,
- QuicByteCount data_length,
- QuicDataWriter* writer) {
bool write_index_hit = false;
QuicDeque<BufferedSlice>::iterator slice_it =
write_index_ == -1
@@ -121,7 +109,6 @@ bool QuicStreamSendBuffer::WriteStreamDataWithIndex(QuicStreamOffset offset,
// Determine if write actually happens at indexed slice.
if (offset >= slice_it->offset) {
write_index_hit = true;
- QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_use_write_index, 1, 2);
} else {
// Write index missed, move iterator to the beginning.
slice_it = buffered_slices_.begin();
@@ -172,6 +159,36 @@ bool QuicStreamSendBuffer::OnStreamDataAcked(
if (data_length == 0) {
return true;
}
+ if (enable_fast_path_on_data_acked_) {
+ QUIC_FLAG_COUNT(quic_reloadable_flag_quic_fast_path_on_stream_data_acked);
+ bool is_disjoint = false;
+ if (GetQuicReloadableFlag(quic_fast_is_disjoint)) {
+ is_disjoint =
+ bytes_acked_.Empty() || offset >= bytes_acked_.rbegin()->max();
+ QUIC_FLAG_COUNT(quic_reloadable_flag_quic_fast_is_disjoint);
+ }
+ if (is_disjoint || bytes_acked_.IsDisjoint(Interval<QuicStreamOffset>(
+ offset, offset + data_length))) {
+ // Optimization for the typical case, when all data is newly acked.
+ if (stream_bytes_outstanding_ < data_length) {
+ return false;
+ }
+ bytes_acked_.Add(offset, offset + data_length);
+ *newly_acked_length = data_length;
+ stream_bytes_outstanding_ -= data_length;
+ pending_retransmissions_.Difference(offset, offset + data_length);
+ if (!FreeMemSlices(offset, offset + data_length)) {
+ return false;
+ }
+ CleanUpBufferedSlices();
+ return true;
+ }
+ // Exit if no new data gets acked.
+ if (bytes_acked_.Contains(offset, offset + data_length)) {
+ return true;
+ }
+ }
+ // Execute the slow path if newly acked data fill in existing holes.
QuicIntervalSet<QuicStreamOffset> newly_acked(offset, offset + data_length);
newly_acked.Difference(bytes_acked_);
for (const auto& interval : newly_acked) {
@@ -183,25 +200,34 @@ bool QuicStreamSendBuffer::OnStreamDataAcked(
stream_bytes_outstanding_ -= *newly_acked_length;
bytes_acked_.Add(offset, offset + data_length);
pending_retransmissions_.Difference(offset, offset + data_length);
+ if (free_mem_slice_out_of_order_) {
+ QUIC_FLAG_COUNT(quic_reloadable_flag_quic_free_mem_slice_out_of_order);
+ if (newly_acked.Empty()) {
+ return true;
+ }
+ if (!FreeMemSlices(newly_acked.begin()->min(),
+ newly_acked.rbegin()->max())) {
+ return false;
+ }
+ CleanUpBufferedSlices();
+ return true;
+ }
while (!buffered_slices_.empty() &&
bytes_acked_.Contains(buffered_slices_.front().offset,
buffered_slices_.front().offset +
buffered_slices_.front().slice.length())) {
// Remove data which stops waiting for acks. Please note, data can be
// acked out of order, but send buffer is cleaned up in order.
- if (use_write_index_) {
- QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_use_write_index, 2, 2);
- QUIC_BUG_IF(write_index_ == 0)
- << "Fail to advance current_write_slice_. It points to the slice "
- "whose data has all be written and ACK'ed or ignored. "
- "current_write_slice_ offset "
- << buffered_slices_[write_index_].offset << " length "
- << buffered_slices_[write_index_].slice.length();
- if (write_index_ > 0) {
- // If write index is pointing to any slice, reduce the index as the
- // slices are all shifted to the left by one.
- --write_index_;
- }
+ QUIC_BUG_IF(write_index_ == 0)
+ << "Fail to advance current_write_slice_. It points to the slice "
+ "whose data has all be written and ACK'ed or ignored. "
+ "current_write_slice_ offset "
+ << buffered_slices_[write_index_].offset << " length "
+ << buffered_slices_[write_index_].slice.length();
+ if (write_index_ > 0) {
+ // If write index is pointing to any slice, reduce the index as the
+ // slices are all shifted to the left by one.
+ --write_index_;
}
buffered_slices_.pop_front();
}
@@ -247,6 +273,50 @@ StreamPendingRetransmission QuicStreamSendBuffer::NextPendingRetransmission()
return {0, 0};
}
+bool QuicStreamSendBuffer::FreeMemSlices(QuicStreamOffset start,
+ QuicStreamOffset end) {
+ DCHECK(free_mem_slice_out_of_order_);
+ // Find it, such that buffered_slices_[it - 1].end < start <=
+ // buffered_slices_[it].end.
+ auto it = std::lower_bound(buffered_slices_.begin(), buffered_slices_.end(),
+ start, CompareOffset());
+ if (it == buffered_slices_.end() || it->slice.empty()) {
+ QUIC_DLOG(ERROR) << "Offset " << start
+ << " does not exist or it has already been acked.";
+ return false;
+ }
+ for (; it != buffered_slices_.end(); ++it) {
+ if (it->offset >= end) {
+ break;
+ }
+ if (!it->slice.empty() &&
+ bytes_acked_.Contains(it->offset, it->offset + it->slice.length())) {
+ it->slice.Reset();
+ }
+ }
+ return true;
+}
+
+void QuicStreamSendBuffer::CleanUpBufferedSlices() {
+ DCHECK(free_mem_slice_out_of_order_);
+ while (!buffered_slices_.empty() && buffered_slices_.front().slice.empty()) {
+ // Remove data which stops waiting for acks. Please note, mem slices can
+ // be released out of order, but send buffer is cleaned up in order.
+ QUIC_BUG_IF(write_index_ == 0)
+ << "Fail to advance current_write_slice_. It points to the slice "
+ "whose data has all be written and ACK'ed or ignored. "
+ "current_write_slice_ offset "
+ << buffered_slices_[write_index_].offset << " length "
+ << buffered_slices_[write_index_].slice.length();
+ if (write_index_ > 0) {
+ // If write index is pointing to any slice, reduce the index as the
+ // slices are all shifted to the left by one.
+ --write_index_;
+ }
+ buffered_slices_.pop_front();
+ }
+}
+
bool QuicStreamSendBuffer::IsStreamDataOutstanding(
QuicStreamOffset offset,
QuicByteCount data_length) const {
diff --git a/chromium/net/quic/core/quic_stream_send_buffer.h b/chromium/net/quic/core/quic_stream_send_buffer.h
index 30a12700f11..ff8d552b83c 100644
--- a/chromium/net/quic/core/quic_stream_send_buffer.h
+++ b/chromium/net/quic/core/quic_stream_send_buffer.h
@@ -123,14 +123,13 @@ class QUIC_EXPORT_PRIVATE QuicStreamSendBuffer {
friend class test::QuicStreamSendBufferPeer;
friend class test::QuicStreamPeer;
- // Another version of WriteStreamData() to be able to start writing from
- // write_index_ points to instead of searching through the slices to find the
- // place to write.
- // TODO(danzh): inline this method into WriteStreamData() after
- // quic_reloadable_flag_quic_use_write_index is deprecated.
- bool WriteStreamDataWithIndex(QuicStreamOffset offset,
- QuicByteCount data_length,
- QuicDataWriter* writer);
+ // Called when data within offset [start, end) gets acked. Frees fully
+ // acked buffered slices if any. Returns false if the corresponding data does
+ // not exist or has been acked.
+ bool FreeMemSlices(QuicStreamOffset start, QuicStreamOffset end);
+
+ // Cleanup empty slices in order from buffered_slices_.
+ void CleanUpBufferedSlices();
QuicDeque<BufferedSlice> buffered_slices_;
@@ -155,8 +154,12 @@ class QUIC_EXPORT_PRIVATE QuicStreamSendBuffer {
// time. -1 if send buffer is empty or all data has been written.
int32_t write_index_;
- // Latched value of quic_reloadable_flag_quic_stream_send_buffer_write_index.
- const bool use_write_index_;
+ // Latched value of quic_reloadable_flag_quic_free_mem_slice_out_of_order.
+ const bool free_mem_slice_out_of_order_;
+
+ // Latched value of quic_reloadable_flag_quic_free_mem_slice_out_of_order and
+ // quic_reloadable_flag_quic_fast_path_on_stream_data_acked.
+ const bool enable_fast_path_on_data_acked_;
};
} // namespace net
diff --git a/chromium/net/quic/core/quic_stream_send_buffer_test.cc b/chromium/net/quic/core/quic_stream_send_buffer_test.cc
index fc7abc262b8..a83f5260888 100644
--- a/chromium/net/quic/core/quic_stream_send_buffer_test.cc
+++ b/chromium/net/quic/core/quic_stream_send_buffer_test.cc
@@ -105,12 +105,8 @@ TEST_F(QuicStreamSendBufferTest, CopyDataToBuffer) {
// Invalid data copy.
QuicDataWriter writer3(4000, buf, HOST_BYTE_ORDER);
EXPECT_FALSE(send_buffer_.WriteStreamData(3000, 1024, &writer3));
- if (GetQuicReloadableFlag(quic_use_write_index)) {
- EXPECT_DFATAL(send_buffer_.WriteStreamData(0, 4000, &writer3),
- "Writer fails to write.");
- } else {
- EXPECT_FALSE(send_buffer_.WriteStreamData(0, 4000, &writer3));
- }
+ EXPECT_DFATAL(send_buffer_.WriteStreamData(0, 4000, &writer3),
+ "Writer fails to write.");
send_buffer_.OnStreamDataConsumed(3840);
EXPECT_EQ(3840u, send_buffer_.stream_bytes_written());
@@ -188,6 +184,40 @@ TEST_F(QuicStreamSendBufferTest, AckStreamDataMultipleTimes) {
EXPECT_FALSE(send_buffer_.OnStreamDataAcked(4000, 100, &newly_acked_length));
}
+TEST_F(QuicStreamSendBufferTest, AckStreamDataOutOfOrder) {
+ WriteAllData();
+ QuicByteCount newly_acked_length;
+ EXPECT_TRUE(send_buffer_.OnStreamDataAcked(500, 1000, &newly_acked_length));
+ EXPECT_EQ(1000u, newly_acked_length);
+ EXPECT_EQ(4u, send_buffer_.size());
+ EXPECT_EQ(3840u, QuicStreamSendBufferPeer::TotalLength(&send_buffer_));
+
+ EXPECT_TRUE(send_buffer_.OnStreamDataAcked(1200, 1000, &newly_acked_length));
+ EXPECT_EQ(700u, newly_acked_length);
+ EXPECT_EQ(4u, send_buffer_.size());
+ if (GetQuicReloadableFlag(quic_free_mem_slice_out_of_order)) {
+ // Slice 2 gets fully acked.
+ EXPECT_EQ(2816u, QuicStreamSendBufferPeer::TotalLength(&send_buffer_));
+ } else {
+ EXPECT_EQ(3840u, QuicStreamSendBufferPeer::TotalLength(&send_buffer_));
+ }
+
+ EXPECT_TRUE(send_buffer_.OnStreamDataAcked(2000, 1840, &newly_acked_length));
+ EXPECT_EQ(1640u, newly_acked_length);
+ EXPECT_EQ(4u, send_buffer_.size());
+ if (GetQuicReloadableFlag(quic_free_mem_slice_out_of_order)) {
+ // Slices 3 and 4 get fully acked.
+ EXPECT_EQ(1024u, QuicStreamSendBufferPeer::TotalLength(&send_buffer_));
+ } else {
+ EXPECT_EQ(3840u, QuicStreamSendBufferPeer::TotalLength(&send_buffer_));
+ }
+
+ EXPECT_TRUE(send_buffer_.OnStreamDataAcked(0, 1000, &newly_acked_length));
+ EXPECT_EQ(500u, newly_acked_length);
+ EXPECT_EQ(0u, send_buffer_.size());
+ EXPECT_EQ(0u, QuicStreamSendBufferPeer::TotalLength(&send_buffer_));
+}
+
TEST_F(QuicStreamSendBufferTest, PendingRetransmission) {
WriteAllData();
EXPECT_TRUE(send_buffer_.IsStreamDataOutstanding(0, 3840));
@@ -230,9 +260,6 @@ TEST_F(QuicStreamSendBufferTest, PendingRetransmission) {
}
TEST_F(QuicStreamSendBufferTest, CurrentWriteIndex) {
- if (!GetQuicReloadableFlag(quic_use_write_index)) {
- return;
- }
char buf[4000];
QuicDataWriter writer(4000, buf, HOST_BYTE_ORDER);
// With data buffered, index points to the 1st slice of data.
diff --git a/chromium/net/quic/core/quic_stream_sequencer_buffer.cc b/chromium/net/quic/core/quic_stream_sequencer_buffer.cc
index f978b59a588..ac3a42e73dd 100644
--- a/chromium/net/quic/core/quic_stream_sequencer_buffer.cc
+++ b/chromium/net/quic/core/quic_stream_sequencer_buffer.cc
@@ -103,7 +103,40 @@ QuicErrorCode QuicStreamSequencerBuffer::OnStreamData(
RecordInternalErrorLocation(QUIC_STREAM_SEQUENCER_BUFFER);
return QUIC_INTERNAL_ERROR;
}
-
+ if (GetQuicReloadableFlag(quic_fast_path_on_stream_data) &&
+ (bytes_received_.Empty() ||
+ starting_offset >= bytes_received_.rbegin()->max() ||
+ bytes_received_.IsDisjoint(Interval<QuicStreamOffset>(
+ starting_offset, starting_offset + size)))) {
+ // Optimization for the typical case, when all data is newly received.
+ QUIC_FLAG_COUNT(quic_reloadable_flag_quic_fast_path_on_stream_data);
+ 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<Interval<QuicPacketNumber>*>(&(*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;
+ }
+ }
+ size_t bytes_copy = 0;
+ if (!CopyStreamData(starting_offset, data, &bytes_copy, error_details)) {
+ return QUIC_STREAM_SEQUENCER_INVALID_STATE;
+ }
+ *bytes_buffered += bytes_copy;
+ frame_arrival_time_map_.insert(
+ std::make_pair(starting_offset, FrameInfo(size, timestamp)));
+ num_bytes_buffered_ += *bytes_buffered;
+ return QUIC_NO_ERROR;
+ }
+ // Slow path, received data overlaps with received data.
QuicIntervalSet<QuicStreamOffset> newly_received(starting_offset,
starting_offset + size);
newly_received.Difference(bytes_received_);
diff --git a/chromium/net/quic/core/quic_stream_sequencer_test.cc b/chromium/net/quic/core/quic_stream_sequencer_test.cc
index 4ec52a03d16..3d608e4ff45 100644
--- a/chromium/net/quic/core/quic_stream_sequencer_test.cc
+++ b/chromium/net/quic/core/quic_stream_sequencer_test.cc
@@ -34,7 +34,8 @@ namespace test {
class MockStream : public QuicStream {
public:
- MockStream(QuicSession* session, QuicStreamId id) : QuicStream(id, session) {}
+ MockStream(QuicSession* session, QuicStreamId id)
+ : QuicStream(id, session, /*is_static=*/false) {}
MOCK_METHOD0(OnFinRead, void());
MOCK_METHOD0(OnDataAvailable, void());
diff --git a/chromium/net/quic/core/quic_stream_test.cc b/chromium/net/quic/core/quic_stream_test.cc
index af56b2effae..7b7d1a5429c 100644
--- a/chromium/net/quic/core/quic_stream_test.cc
+++ b/chromium/net/quic/core/quic_stream_test.cc
@@ -50,7 +50,7 @@ const bool kShouldNotProcessData = false;
class TestStream : public QuicStream {
public:
TestStream(QuicStreamId id, QuicSession* session, bool should_process_data)
- : QuicStream(id, session) {}
+ : QuicStream(id, session, /*is_static=*/false) {}
void OnDataAvailable() override {}
@@ -123,7 +123,11 @@ class QuicStreamTest : public QuicTestWithParam<bool> {
.Times(AnyNumber());
write_blocked_list_ =
QuicSessionPeer::GetWriteBlockedStreams(session_.get());
- write_blocked_list_->RegisterStream(kTestStreamId, kV3HighestPriority);
+ if (!session_->register_streams_early()) {
+ write_blocked_list_->RegisterStream(kTestStreamId,
+ /*is_static_stream=*/false,
+ kV3HighestPriority);
+ }
}
bool fin_sent() { return QuicStreamPeer::FinSent(stream_); }
@@ -134,7 +138,7 @@ class QuicStreamTest : public QuicTestWithParam<bool> {
}
bool HasWriteBlockedStreams() {
- return write_blocked_list_->HasWriteBlockedCryptoOrHeadersStream() ||
+ return write_blocked_list_->HasWriteBlockedSpecialStream() ||
write_blocked_list_->HasWriteBlockedDataStreams();
}
@@ -173,7 +177,7 @@ TEST_F(QuicStreamTest, WriteAllData) {
1 + QuicPacketCreator::StreamFramePacketOverhead(
connection_->transport_version(), PACKET_8BYTE_CONNECTION_ID,
!kIncludeVersion, !kIncludeDiversificationNonce,
- PACKET_6BYTE_PACKET_NUMBER, 0u);
+ PACKET_4BYTE_PACKET_NUMBER, 0u);
connection_->SetMaxPacketLength(length);
EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _))
@@ -254,7 +258,7 @@ TEST_F(QuicStreamTest, WriteOrBufferData) {
1 + QuicPacketCreator::StreamFramePacketOverhead(
connection_->transport_version(), PACKET_8BYTE_CONNECTION_ID,
!kIncludeVersion, !kIncludeDiversificationNonce,
- PACKET_6BYTE_PACKET_NUMBER, 0u);
+ PACKET_4BYTE_PACKET_NUMBER, 0u);
connection_->SetMaxPacketLength(length);
EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
@@ -457,13 +461,9 @@ TEST_F(QuicStreamTest, StopReadingSendsFlowControl) {
EXPECT_CALL(*connection_,
CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _))
.Times(0);
- if (session_->use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(AtLeast(1))
- .WillRepeatedly(Invoke(this, &QuicStreamTest::ClearControlFrame));
- } else {
- EXPECT_CALL(*connection_, SendWindowUpdate(_, _)).Times(AtLeast(1));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(AtLeast(1))
+ .WillRepeatedly(Invoke(this, &QuicStreamTest::ClearControlFrame));
QuicString data(1000, 'x');
for (QuicStreamOffset offset = 0;
@@ -821,7 +821,7 @@ TEST_F(QuicStreamTest, RstFrameReceivedStreamFinishSending) {
QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(),
QUIC_STREAM_CANCELLED, 1234);
stream_->OnStreamReset(rst_frame);
- // Stream stops waiting for acks as it has unacked data.
+ // Stream still waits for acks as it finishes sending and has unacked data.
EXPECT_TRUE(stream_->IsWaitingForAcks());
EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
}
@@ -969,9 +969,6 @@ TEST_F(QuicStreamTest, WriteMemSlices) {
set_initial_flow_control_window_bytes(500000);
Initialize(kShouldProcessData);
- if (!session_->can_use_slices()) {
- return;
- }
char data[1024];
std::vector<std::pair<char*, size_t>> buffers;
buffers.push_back(std::make_pair(data, QUIC_ARRAYSIZE(data)));
@@ -1034,9 +1031,6 @@ TEST_F(QuicStreamTest, WriteMemSlices) {
TEST_F(QuicStreamTest, WriteMemSlicesReachStreamLimit) {
SetQuicReloadableFlag(quic_stream_too_long, true);
Initialize(kShouldProcessData);
- if (!session_->can_use_slices()) {
- return;
- }
QuicStreamPeer::SetStreamBytesWritten(kMaxStreamLength - 5u, stream_);
char data[5];
std::vector<std::pair<char*, size_t>> buffers;
@@ -1215,12 +1209,8 @@ TEST_F(QuicStreamTest, MarkConnectionLevelWriteBlockedOnWindowUpdateFrame) {
EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
- if (session_->use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillOnce(Invoke(this, &QuicStreamTest::ClearControlFrame));
- } else {
- EXPECT_CALL(*connection_, SendBlocked(stream_->id()));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(this, &QuicStreamTest::ClearControlFrame));
QuicString data(1024, '.');
stream_->WriteOrBufferData(data, false, nullptr);
EXPECT_FALSE(HasWriteBlockedStreams());
@@ -1229,20 +1219,14 @@ TEST_F(QuicStreamTest, MarkConnectionLevelWriteBlockedOnWindowUpdateFrame) {
1234);
stream_->OnWindowUpdateFrame(window_update);
- if (session_->session_unblocks_stream()) {
- // Verify stream is marked connection level write blocked.
- EXPECT_TRUE(HasWriteBlockedStreams());
- EXPECT_TRUE(stream_->HasBufferedData());
- } else {
- EXPECT_FALSE(HasWriteBlockedStreams());
- EXPECT_FALSE(stream_->HasBufferedData());
- }
+ // Verify stream is marked connection level write blocked.
+ EXPECT_TRUE(HasWriteBlockedStreams());
+ EXPECT_TRUE(stream_->HasBufferedData());
}
// Regression test for b/73282665.
TEST_F(QuicStreamTest,
MarkConnectionLevelWriteBlockedOnWindowUpdateFrameWithNoBufferedData) {
- SetQuicReloadableFlag(quic_streams_unblocked_by_session2, true);
// Set a small initial flow control window size.
const uint32_t kSmallWindow = 100;
set_initial_flow_control_window_bytes(kSmallWindow);
@@ -1251,12 +1235,8 @@ TEST_F(QuicStreamTest,
QuicString data(kSmallWindow, '.');
EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
- if (session_->use_control_frame_manager()) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillOnce(Invoke(this, &QuicStreamTest::ClearControlFrame));
- } else {
- EXPECT_CALL(*connection_, SendBlocked(stream_->id()));
- }
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .WillOnce(Invoke(this, &QuicStreamTest::ClearControlFrame));
stream_->WriteOrBufferData(data, false, nullptr);
EXPECT_FALSE(HasWriteBlockedStreams());
diff --git a/chromium/net/quic/core/quic_types.h b/chromium/net/quic/core/quic_types.h
index d237227e047..9671b45eaed 100644
--- a/chromium/net/quic/core/quic_types.h
+++ b/chromium/net/quic/core/quic_types.h
@@ -33,6 +33,12 @@ typedef uint64_t QuicIetfStreamDataLength;
typedef uint64_t QuicIetfStreamId;
typedef uint64_t QuicIetfStreamOffset;
+const size_t kQuicPathFrameBufferSize = 8;
+typedef std::array<uint8_t, kQuicPathFrameBufferSize> QuicPathFrameBuffer;
+
+// Application error code used in the QUIC Stop Sending frame.
+typedef uint16_t QuicApplicationErrorCode;
+
// A struct for functions which consume data payloads and fins.
struct QUIC_EXPORT_PRIVATE QuicConsumedData {
QuicConsumedData(size_t bytes_consumed, bool fin_consumed);
@@ -66,9 +72,17 @@ enum QuicAsyncStatus {
enum WriteStatus {
WRITE_STATUS_OK,
WRITE_STATUS_BLOCKED,
+ // To make the IsWriteError(WriteStatus) function work properly:
+ // - Non-errors MUST be added before WRITE_STATUS_ERROR.
+ // - Errors MUST be added after WRITE_STATUS_ERROR.
WRITE_STATUS_ERROR,
+ WRITE_STATUS_MSG_TOO_BIG,
};
+inline bool IsWriteError(WriteStatus status) {
+ return status >= WRITE_STATUS_ERROR;
+}
+
// A struct used to return the result of write calls including either the number
// of bytes written or the error code, depending upon the status.
struct QUIC_EXPORT_PRIVATE WriteResult {
@@ -156,8 +170,9 @@ enum QuicIetfFrameType : int8_t {
IETF_STREAM_ID_BLOCKED = 0x0a,
IETF_NEW_CONNECTION_ID = 0x0b,
IETF_STOP_SENDING = 0x0c,
- IETF_PONG = 0x0d,
- IETF_ACK = 0x0e,
+ IETF_ACK = 0x0d,
+ IETF_PATH_CHALLENGE = 0x0e,
+ IETF_PATH_RESPONSE = 0x0f,
// the low-3 bits of the stream frame type value are actually flags
// declaring what parts of the frame are/are-not present, as well as
// some other control information. The code would then do something
diff --git a/chromium/net/quic/core/quic_unacked_packet_map.cc b/chromium/net/quic/core/quic_unacked_packet_map.cc
index 678bc5334b8..a70ac7f3b4e 100644
--- a/chromium/net/quic/core/quic_unacked_packet_map.cc
+++ b/chromium/net/quic/core/quic_unacked_packet_map.cc
@@ -17,6 +17,7 @@ QuicUnackedPacketMap::QuicUnackedPacketMap()
least_unacked_(1),
bytes_in_flight_(0),
pending_crypto_packet_count_(0),
+ last_crypto_packet_sent_time_(QuicTime::Zero()),
session_notifier_(nullptr),
session_decides_what_to_write_(false) {}
@@ -63,6 +64,7 @@ void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* packet,
if (old_packet_number == 0) {
if (has_crypto_handshake) {
++pending_crypto_packet_count_;
+ last_crypto_packet_sent_time_ = sent_time;
}
packet->retransmittable_frames.swap(
@@ -302,6 +304,10 @@ QuicTime QuicUnackedPacketMap::GetLastPacketSentTime() const {
return QuicTime::Zero();
}
+QuicTime QuicUnackedPacketMap::GetLastCryptoPacketSentTime() const {
+ return last_crypto_packet_sent_time_;
+}
+
size_t QuicUnackedPacketMap::GetNumUnackedPacketsDebugOnly() const {
size_t unacked_packet_count = 0;
QuicPacketNumber packet_number = least_unacked_;
diff --git a/chromium/net/quic/core/quic_unacked_packet_map.h b/chromium/net/quic/core/quic_unacked_packet_map.h
index 0bafe98f6b1..30091975f5d 100644
--- a/chromium/net/quic/core/quic_unacked_packet_map.h
+++ b/chromium/net/quic/core/quic_unacked_packet_map.h
@@ -128,6 +128,9 @@ class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
// Returns the time that the last unacked packet was sent.
QuicTime GetLastPacketSentTime() const;
+ // Returns the time that the last unacked crypto packet was sent.
+ QuicTime GetLastCryptoPacketSentTime() const;
+
// Returns the number of unacked packets.
size_t GetNumUnackedPacketsDebugOnly() const;
@@ -213,6 +216,9 @@ class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
// Number of retransmittable crypto handshake packets.
size_t pending_crypto_packet_count_;
+ // Time that the last unacked crypto packet was sent.
+ QuicTime last_crypto_packet_sent_time_;
+
// Receives notifications of frames being retransmitted or acknowledged.
SessionNotifierInterface* session_notifier_;
diff --git a/chromium/net/quic/core/quic_utils.cc b/chromium/net/quic/core/quic_utils.cc
index 49ec2198baa..c5c00e77d61 100644
--- a/chromium/net/quic/core/quic_utils.cc
+++ b/chromium/net/quic/core/quic_utils.cc
@@ -13,6 +13,7 @@
#include "net/quic/platform/api/quic_flags.h"
#include "net/quic/platform/api/quic_prefetch.h"
#include "net/quic/platform/api/quic_string.h"
+#include "net/quic/platform/api/quic_uint128.h"
namespace net {
namespace {
@@ -27,9 +28,9 @@ namespace {
#endif
#ifdef QUIC_UTIL_HAS_UINT128
-uint128 IncrementalHashFast(uint128 uhash, QuicStringPiece data) {
+QuicUint128 IncrementalHashFast(QuicUint128 uhash, QuicStringPiece data) {
// This code ends up faster than the naive implementation for 2 reasons:
- // 1. uint128 from base/int128.h is sufficiently complicated that the compiler
+ // 1. QuicUint128 is sufficiently complicated that the compiler
// cannot transform the multiplication by kPrime into a shift-multiply-add;
// it has go through all of the instructions for a 128-bit multiply.
// 2. Because there are so fewer instructions (around 13), the hot loop fits
@@ -37,13 +38,14 @@ uint128 IncrementalHashFast(uint128 uhash, QuicStringPiece data) {
// kPrime = 309485009821345068724781371
static const __uint128_t kPrime =
(static_cast<__uint128_t>(16777216) << 64) + 315;
- __uint128_t xhash = (static_cast<__uint128_t>(Uint128High64(uhash)) << 64) +
- Uint128Low64(uhash);
+ auto hi = QuicUint128High64(uhash);
+ auto lo = QuicUint128Low64(uhash);
+ __uint128_t xhash = (static_cast<__uint128_t>(hi) << 64) + lo;
const uint8_t* octets = reinterpret_cast<const uint8_t*>(data.data());
for (size_t i = 0; i < data.length(); ++i) {
xhash = (xhash ^ octets[i]) * kPrime;
}
- return MakeUint128(
+ return MakeQuicUint128(
static_cast<uint64_t>(xhash >> 64),
static_cast<uint64_t>(xhash & UINT64_C(0xFFFFFFFFFFFFFFFF)));
}
@@ -51,19 +53,19 @@ uint128 IncrementalHashFast(uint128 uhash, QuicStringPiece data) {
#ifndef QUIC_UTIL_HAS_UINT128
// Slow implementation of IncrementalHash. In practice, only used by Chromium.
-uint128 IncrementalHashSlow(uint128 hash, QuicStringPiece data) {
+QuicUint128 IncrementalHashSlow(QuicUint128 hash, QuicStringPiece data) {
// kPrime = 309485009821345068724781371
- static const uint128 kPrime = MakeUint128(16777216, 315);
+ static const uint128 kPrime = MakeQuicUint128(16777216, 315);
const uint8_t* octets = reinterpret_cast<const uint8_t*>(data.data());
for (size_t i = 0; i < data.length(); ++i) {
- hash = hash ^ MakeUint128(0, octets[i]);
+ hash = hash ^ MakeQuicUint128(0, octets[i]);
hash = hash * kPrime;
}
return hash;
}
#endif
-uint128 IncrementalHash(uint128 hash, QuicStringPiece data) {
+QuicUint128 IncrementalHash(QuicUint128 hash, QuicStringPiece data) {
#ifdef QUIC_UTIL_HAS_UINT128
return IncrementalHashFast(hash, data);
#else
@@ -91,27 +93,27 @@ uint64_t QuicUtils::FNV1a_64_Hash(QuicStringPiece data) {
}
// static
-uint128 QuicUtils::FNV1a_128_Hash(QuicStringPiece data) {
+QuicUint128 QuicUtils::FNV1a_128_Hash(QuicStringPiece data) {
return FNV1a_128_Hash_Three(data, QuicStringPiece(), QuicStringPiece());
}
// static
-uint128 QuicUtils::FNV1a_128_Hash_Two(QuicStringPiece data1,
- QuicStringPiece data2) {
+QuicUint128 QuicUtils::FNV1a_128_Hash_Two(QuicStringPiece data1,
+ QuicStringPiece data2) {
return FNV1a_128_Hash_Three(data1, data2, QuicStringPiece());
}
// static
-uint128 QuicUtils::FNV1a_128_Hash_Three(QuicStringPiece data1,
- QuicStringPiece data2,
- QuicStringPiece data3) {
+QuicUint128 QuicUtils::FNV1a_128_Hash_Three(QuicStringPiece data1,
+ QuicStringPiece data2,
+ QuicStringPiece data3) {
// The two constants are defined as part of the hash algorithm.
// see http://www.isthe.com/chongo/tech/comp/fnv/
// kOffset = 144066263297769815596495629667062367629
- const uint128 kOffset =
- MakeUint128(UINT64_C(7809847782465536322), UINT64_C(7113472399480571277));
+ const QuicUint128 kOffset = MakeQuicUint128(UINT64_C(7809847782465536322),
+ UINT64_C(7113472399480571277));
- uint128 hash = IncrementalHash(kOffset, data1);
+ QuicUint128 hash = IncrementalHash(kOffset, data1);
if (data2.empty()) {
return hash;
}
@@ -124,9 +126,9 @@ uint128 QuicUtils::FNV1a_128_Hash_Three(QuicStringPiece data1,
}
// static
-void QuicUtils::SerializeUint128Short(uint128 v, uint8_t* out) {
- const uint64_t lo = Uint128Low64(v);
- const uint64_t hi = Uint128High64(v);
+void QuicUtils::SerializeUint128Short(QuicUint128 v, uint8_t* out) {
+ const uint64_t lo = QuicUint128Low64(v);
+ const uint64_t hi = QuicUint128High64(v);
// This assumes that the system is little-endian.
memcpy(out, &lo, sizeof(lo));
memcpy(out + sizeof(lo), &hi, sizeof(hi) / 2);
@@ -175,6 +177,21 @@ QuicString QuicUtils::AddressChangeTypeToString(AddressChangeType type) {
return "INVALID_ADDRESS_CHANGE_TYPE";
}
+const char* QuicUtils::SentPacketStateToString(SentPacketState state) {
+ switch (state) {
+ RETURN_STRING_LITERAL(OUTSTANDING);
+ RETURN_STRING_LITERAL(NEVER_SENT);
+ RETURN_STRING_LITERAL(ACKED);
+ RETURN_STRING_LITERAL(UNACKABLE);
+ RETURN_STRING_LITERAL(HANDSHAKE_RETRANSMITTED);
+ RETURN_STRING_LITERAL(LOST);
+ RETURN_STRING_LITERAL(TLP_RETRANSMITTED);
+ RETURN_STRING_LITERAL(RTO_RETRANSMITTED);
+ RETURN_STRING_LITERAL(PROBE_RETRANSMITTED);
+ }
+ return "INVALID_SENT_PACKET_STATE";
+}
+
// static
AddressChangeType QuicUtils::DetermineAddressChangeType(
const QuicSocketAddress& old_address,
diff --git a/chromium/net/quic/core/quic_utils.h b/chromium/net/quic/core/quic_utils.h
index 9790c41f727..a891beba292 100644
--- a/chromium/net/quic/core/quic_utils.h
+++ b/chromium/net/quic/core/quic_utils.h
@@ -9,7 +9,6 @@
#include <cstdint>
#include "base/macros.h"
-#include "net/base/int128.h"
#include "net/base/iovec.h"
#include "net/quic/core/quic_error_codes.h"
#include "net/quic/core/quic_types.h"
@@ -17,6 +16,7 @@
#include "net/quic/platform/api/quic_socket_address.h"
#include "net/quic/platform/api/quic_string.h"
#include "net/quic/platform/api/quic_string_piece.h"
+#include "net/quic/platform/api/quic_uint128.h"
namespace net {
@@ -28,22 +28,22 @@ class QUIC_EXPORT_PRIVATE QuicUtils {
// Returns the 128 bit FNV1a hash of the data. See
// http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
- static uint128 FNV1a_128_Hash(QuicStringPiece data);
+ static QuicUint128 FNV1a_128_Hash(QuicStringPiece data);
// Returns the 128 bit FNV1a hash of the two sequences of data. See
// http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
- static uint128 FNV1a_128_Hash_Two(QuicStringPiece data1,
- QuicStringPiece data2);
+ static QuicUint128 FNV1a_128_Hash_Two(QuicStringPiece data1,
+ QuicStringPiece data2);
// Returns the 128 bit FNV1a hash of the three sequences of data. See
// http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
- static uint128 FNV1a_128_Hash_Three(QuicStringPiece data1,
- QuicStringPiece data2,
- QuicStringPiece data3);
+ static QuicUint128 FNV1a_128_Hash_Three(QuicStringPiece data1,
+ QuicStringPiece data2,
+ QuicStringPiece data3);
// SerializeUint128 writes the first 96 bits of |v| in little-endian form
// to |out|.
- static void SerializeUint128Short(uint128 v, uint8_t* out);
+ static void SerializeUint128Short(QuicUint128 v, uint8_t* out);
// Returns the level of encryption as a char*
static const char* EncryptionLevelToString(EncryptionLevel level);
@@ -54,6 +54,9 @@ class QUIC_EXPORT_PRIVATE QuicUtils {
// Returns AddressChangeType as a std::string.
static QuicString AddressChangeTypeToString(AddressChangeType type);
+ // Returns SentPacketState as a char*.
+ static const char* SentPacketStateToString(SentPacketState state);
+
// Determines and returns change type of address change from |old_address| to
// |new_address|.
static AddressChangeType DetermineAddressChangeType(
diff --git a/chromium/net/quic/core/quic_utils_test.cc b/chromium/net/quic/core/quic_utils_test.cc
index a27f90f145f..c797937742c 100644
--- a/chromium/net/quic/core/quic_utils_test.cc
+++ b/chromium/net/quic/core/quic_utils_test.cc
@@ -73,17 +73,17 @@ TEST_F(QuicUtilsTest, DetermineAddressChangeType) {
QuicUtils::DetermineAddressChangeType(old_address, new_address));
}
-uint128 IncrementalHashReference(const void* data, size_t len) {
+QuicUint128 IncrementalHashReference(const void* data, size_t len) {
// The two constants are defined as part of the hash algorithm.
// see http://www.isthe.com/chongo/tech/comp/fnv/
// hash = 144066263297769815596495629667062367629
- uint128 hash =
- MakeUint128(UINT64_C(7809847782465536322), UINT64_C(7113472399480571277));
+ QuicUint128 hash = MakeQuicUint128(UINT64_C(7809847782465536322),
+ UINT64_C(7113472399480571277));
// kPrime = 309485009821345068724781371
- const uint128 kPrime = MakeUint128(16777216, 315);
+ const QuicUint128 kPrime = MakeQuicUint128(16777216, 315);
const uint8_t* octets = reinterpret_cast<const uint8_t*>(data);
for (size_t i = 0; i < len; ++i) {
- hash = hash ^ MakeUint128(0, octets[i]);
+ hash = hash ^ MakeQuicUint128(0, octets[i]);
hash = hash * kPrime;
}
return hash;
diff --git a/chromium/net/quic/core/quic_versions.cc b/chromium/net/quic/core/quic_versions.cc
index bac51f16959..f3094a1497e 100644
--- a/chromium/net/quic/core/quic_versions.cc
+++ b/chromium/net/quic/core/quic_versions.cc
@@ -25,6 +25,16 @@ QuicVersionLabel MakeVersionLabel(char a, char b, char c, char d) {
} // namespace
+ParsedQuicVersion::ParsedQuicVersion(HandshakeProtocol handshake_protocol,
+ QuicTransportVersion transport_version)
+ : handshake_protocol(handshake_protocol),
+ transport_version(transport_version) {
+ if (handshake_protocol == PROTOCOL_TLS1_3 &&
+ !FLAGS_quic_supports_tls_handshake) {
+ QUIC_BUG << "TLS use attempted when not enabled";
+ }
+}
+
std::ostream& operator<<(std::ostream& os, const ParsedQuicVersion& version) {
os << ParsedQuicVersionToString(version);
return os;
@@ -37,9 +47,6 @@ QuicVersionLabel CreateQuicVersionLabel(ParsedQuicVersion parsed_version) {
proto = 'Q';
break;
case PROTOCOL_TLS1_3:
- if (!FLAGS_quic_supports_tls_handshake) {
- QUIC_BUG << "TLS use attempted when not enabled";
- }
proto = 'T';
break;
default:
diff --git a/chromium/net/quic/core/quic_versions.h b/chromium/net/quic/core/quic_versions.h
index e2b45fece26..2f97db34a62 100644
--- a/chromium/net/quic/core/quic_versions.h
+++ b/chromium/net/quic/core/quic_versions.h
@@ -52,14 +52,12 @@ enum HandshakeProtocol {
// A parsed QUIC version label which determines that handshake protocol
// and the transport version.
-struct ParsedQuicVersion {
+struct QUIC_EXPORT_PRIVATE ParsedQuicVersion {
HandshakeProtocol handshake_protocol;
QuicTransportVersion transport_version;
ParsedQuicVersion(HandshakeProtocol handshake_protocol,
- QuicTransportVersion transport_version)
- : handshake_protocol(handshake_protocol),
- transport_version(transport_version) {}
+ QuicTransportVersion transport_version);
ParsedQuicVersion(const ParsedQuicVersion& other)
: handshake_protocol(other.handshake_protocol),
diff --git a/chromium/net/quic/core/quic_write_blocked_list.cc b/chromium/net/quic/core/quic_write_blocked_list.cc
index 32f23cf3eb9..f5e9775df80 100644
--- a/chromium/net/quic/core/quic_write_blocked_list.cc
+++ b/chromium/net/quic/core/quic_write_blocked_list.cc
@@ -4,12 +4,15 @@
#include "net/quic/core/quic_write_blocked_list.h"
+#include "net/quic/platform/api/quic_flags.h"
+
namespace net {
-QuicWriteBlockedList::QuicWriteBlockedList()
+QuicWriteBlockedList::QuicWriteBlockedList(bool register_static_streams)
: last_priority_popped_(0),
crypto_stream_blocked_(false),
- headers_stream_blocked_(false) {
+ headers_stream_blocked_(false),
+ register_static_streams_(register_static_streams) {
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/quic/core/quic_write_blocked_list.h b/chromium/net/quic/core/quic_write_blocked_list.h
index a2b6033d1a4..1a5b3d4b354 100644
--- a/chromium/net/quic/core/quic_write_blocked_list.h
+++ b/chromium/net/quic/core/quic_write_blocked_list.h
@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "net/quic/core/quic_packets.h"
#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_map_util.h"
#include "net/spdy/core/priority_write_scheduler.h"
namespace net {
@@ -23,57 +24,100 @@ class QUIC_EXPORT_PRIVATE QuicWriteBlockedList {
typedef PriorityWriteScheduler<QuicStreamId> QuicPriorityWriteScheduler;
public:
- QuicWriteBlockedList();
+ explicit QuicWriteBlockedList(bool register_static_streams);
~QuicWriteBlockedList();
bool HasWriteBlockedDataStreams() const {
return priority_write_scheduler_.HasReadyStreams();
}
- bool HasWriteBlockedCryptoOrHeadersStream() const {
+ bool HasWriteBlockedSpecialStream() const {
+ if (register_static_streams_) {
+ for (const auto& stream : static_streams_) {
+ if (stream.second) {
+ return true;
+ }
+ }
+ return false;
+ }
return crypto_stream_blocked_ || headers_stream_blocked_;
}
- size_t NumBlockedStreams() const {
- size_t num_blocked = priority_write_scheduler_.NumReadyStreams();
- if (crypto_stream_blocked_) {
- ++num_blocked;
- }
- if (headers_stream_blocked_) {
- ++num_blocked;
+ size_t NumBlockedSpecialStreams() const {
+ size_t num_blocked = 0;
+ if (register_static_streams_) {
+ for (const auto& stream : static_streams_) {
+ if (stream.second) {
+ ++num_blocked;
+ }
+ }
+ } else {
+ if (crypto_stream_blocked_) {
+ ++num_blocked;
+ }
+ if (headers_stream_blocked_) {
+ ++num_blocked;
+ }
}
-
return num_blocked;
}
+ size_t NumBlockedStreams() const {
+ return NumBlockedSpecialStreams() +
+ priority_write_scheduler_.NumReadyStreams();
+ }
+
bool ShouldYield(QuicStreamId id) const {
- if (id == kCryptoStreamId) {
- return false; // The crypto stream yields to none.
- }
- if (crypto_stream_blocked_) {
- return true; // If the crypto stream is blocked, all other streams yield.
- }
- if (id == kHeadersStreamId) {
- return false; // The crypto stream isn't blocked so headers won't yield.
+ if (register_static_streams_) {
+ for (const auto& stream : static_streams_) {
+ if (stream.first == id) {
+ // Static streams should never yield to data streams, or to lower
+ // priority static stream.
+ return false;
+ }
+ if (stream.second) {
+ return true; // All data streams yield to static streams.
+ }
+ }
+ } else {
+ if (id == kCryptoStreamId) {
+ return false; // The crypto stream yields to none.
+ }
+ if (crypto_stream_blocked_) {
+ return true; // If the crypto stream is blocked, all other streams
+ // yield.
+ }
+ if (id == kHeadersStreamId) {
+ return false; // The crypto stream isn't blocked so headers won't
+ // yield.
+ }
+ if (headers_stream_blocked_) {
+ return true; // All data streams yield to the headers stream.
+ }
}
- if (headers_stream_blocked_) {
- return true; // All data streams yield to the headers stream.
- }
-
return priority_write_scheduler_.ShouldYield(id);
}
// Pops the highest priorty stream, special casing crypto and headers streams.
// Latches the most recently popped data stream for batch writing purposes.
QuicStreamId PopFront() {
- if (crypto_stream_blocked_) {
- crypto_stream_blocked_ = false;
- return kCryptoStreamId;
- }
-
- if (headers_stream_blocked_) {
- headers_stream_blocked_ = false;
- return kHeadersStreamId;
+ if (register_static_streams_) {
+ for (auto& stream : static_streams_) {
+ if (stream.second) {
+ stream.second = false;
+ return stream.first;
+ }
+ }
+ } else {
+ if (crypto_stream_blocked_) {
+ crypto_stream_blocked_ = false;
+ return kCryptoStreamId;
+ }
+
+ if (headers_stream_blocked_) {
+ headers_stream_blocked_ = false;
+ return kHeadersStreamId;
+ }
}
const auto id_and_precedence =
@@ -97,16 +141,34 @@ class QUIC_EXPORT_PRIVATE QuicWriteBlockedList {
return id;
}
- void RegisterStream(QuicStreamId stream_id, SpdyPriority priority) {
+ void RegisterStream(QuicStreamId stream_id,
+ bool is_static_stream,
+ SpdyPriority priority) {
+ if (register_static_streams_ && is_static_stream) {
+ DCHECK(!priority_write_scheduler_.StreamRegistered(stream_id));
+ DCHECK(!QuicContainsKey(static_streams_, stream_id));
+ DCHECK(static_streams_.empty() ||
+ stream_id > static_streams_.back().first)
+ << "stream_id: " << stream_id
+ << " last static stream: " << static_streams_.back().first;
+ static_streams_[stream_id] = false;
+ return;
+ }
+ DCHECK(!priority_write_scheduler_.StreamRegistered(stream_id));
priority_write_scheduler_.RegisterStream(stream_id,
SpdyStreamPrecedence(priority));
}
- void UnregisterStream(QuicStreamId stream_id) {
+ void UnregisterStream(QuicStreamId stream_id, bool is_static) {
+ if (register_static_streams_ && is_static) {
+ static_streams_.erase(stream_id);
+ return;
+ }
priority_write_scheduler_.UnregisterStream(stream_id);
}
void UpdateStreamPriority(QuicStreamId stream_id, SpdyPriority new_priority) {
+ DCHECK(!QuicContainsKey(static_streams_, stream_id));
priority_write_scheduler_.UpdateStreamPrecedence(
stream_id, SpdyStreamPrecedence(new_priority));
}
@@ -125,16 +187,24 @@ class QUIC_EXPORT_PRIVATE QuicWriteBlockedList {
// the list for its priority level.
// Headers and crypto streams are special cased to always resume first.
void AddStream(QuicStreamId stream_id) {
- if (stream_id == kCryptoStreamId) {
- // TODO(avd) Add DCHECK(!crypto_stream_blocked_)
- crypto_stream_blocked_ = true;
- return;
- }
-
- if (stream_id == kHeadersStreamId) {
- // TODO(avd) Add DCHECK(!headers_stream_blocked_);
- headers_stream_blocked_ = true;
- return;
+ if (register_static_streams_) {
+ auto it = static_streams_.find(stream_id);
+ if (it != static_streams_.end()) {
+ it->second = true;
+ return;
+ }
+ } else {
+ if (stream_id == kCryptoStreamId) {
+ // TODO(avd) Add DCHECK(!crypto_stream_blocked_)
+ crypto_stream_blocked_ = true;
+ return;
+ }
+
+ if (stream_id == kHeadersStreamId) {
+ // TODO(avd) Add DCHECK(!headers_stream_blocked_);
+ headers_stream_blocked_ = true;
+ return;
+ }
}
bool push_front =
stream_id == batch_write_stream_id_[last_priority_popped_] &&
@@ -145,19 +215,25 @@ class QUIC_EXPORT_PRIVATE QuicWriteBlockedList {
// This function is used for debugging and test only. Returns true if stream
// with |stream_id| is write blocked.
bool IsStreamBlocked(QuicStreamId stream_id) const {
- if (stream_id == kCryptoStreamId) {
- return crypto_stream_blocked_;
- }
-
- if (stream_id == kHeadersStreamId) {
- return headers_stream_blocked_;
+ if (register_static_streams_) {
+ auto it = static_streams_.find(stream_id);
+ if (it != static_streams_.end()) {
+ return it->second;
+ }
+ } else {
+ if (stream_id == kCryptoStreamId) {
+ return crypto_stream_blocked_;
+ }
+
+ if (stream_id == kHeadersStreamId) {
+ return headers_stream_blocked_;
+ }
}
return priority_write_scheduler_.IsStreamReady(stream_id);
}
- bool crypto_stream_blocked() const { return crypto_stream_blocked_; }
- bool headers_stream_blocked() const { return headers_stream_blocked_; }
+ bool register_static_streams() const { return register_static_streams_; }
private:
QuicPriorityWriteScheduler priority_write_scheduler_;
@@ -177,6 +253,10 @@ class QUIC_EXPORT_PRIVATE QuicWriteBlockedList {
bool crypto_stream_blocked_;
bool headers_stream_blocked_;
+ // Latched value of quic_reloadable_flag_quic_register_static_streams.
+ const bool register_static_streams_;
+ QuicLinkedHashMapImpl<QuicStreamId, bool> static_streams_;
+
DISALLOW_COPY_AND_ASSIGN(QuicWriteBlockedList);
};
diff --git a/chromium/net/quic/core/quic_write_blocked_list_test.cc b/chromium/net/quic/core/quic_write_blocked_list_test.cc
index 91d0313b3ff..44da95eeb37 100644
--- a/chromium/net/quic/core/quic_write_blocked_list_test.cc
+++ b/chromium/net/quic/core/quic_write_blocked_list_test.cc
@@ -7,25 +7,27 @@
#include "net/quic/platform/api/quic_test.h"
#include "net/quic/test_tools/quic_test_utils.h"
-using net::kV3LowestPriority;
-using net::kV3HighestPriority;
+// using kV3HighestPriority;
+// using kV3LowestPriority;
namespace net {
namespace test {
namespace {
-class QuicWriteBlockedListTest : public QuicTest {};
+class QuicWriteBlockedListTest : public QuicTestWithParam<bool> {};
-TEST_F(QuicWriteBlockedListTest, PriorityOrder) {
- QuicWriteBlockedList write_blocked_list;
+INSTANTIATE_TEST_CASE_P(Tests, QuicWriteBlockedListTest, testing::Bool());
+
+TEST_P(QuicWriteBlockedListTest, PriorityOrder) {
+ QuicWriteBlockedList write_blocked_list(GetParam());
// Mark streams blocked in roughly reverse priority order, and
// verify that streams are sorted.
- write_blocked_list.RegisterStream(40, kV3LowestPriority);
- write_blocked_list.RegisterStream(23, kV3HighestPriority);
- write_blocked_list.RegisterStream(17, kV3HighestPriority);
- write_blocked_list.RegisterStream(kHeadersStreamId, kV3HighestPriority);
- write_blocked_list.RegisterStream(kCryptoStreamId, kV3HighestPriority);
+ 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(kCryptoStreamId, true, kV3HighestPriority);
+ write_blocked_list.RegisterStream(kHeadersStreamId, true, kV3HighestPriority);
write_blocked_list.AddStream(40);
EXPECT_TRUE(write_blocked_list.IsStreamBlocked(40));
@@ -39,13 +41,16 @@ TEST_F(QuicWriteBlockedListTest, PriorityOrder) {
EXPECT_TRUE(write_blocked_list.IsStreamBlocked(kCryptoStreamId));
EXPECT_EQ(5u, write_blocked_list.NumBlockedStreams());
- EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream());
+ 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(kCryptoStreamId, write_blocked_list.PopFront());
+ EXPECT_EQ(1u, write_blocked_list.NumBlockedSpecialStreams());
EXPECT_FALSE(write_blocked_list.IsStreamBlocked(kCryptoStreamId));
// Followed by the Headers stream.
EXPECT_EQ(kHeadersStreamId, write_blocked_list.PopFront());
+ EXPECT_EQ(0u, write_blocked_list.NumBlockedSpecialStreams());
EXPECT_FALSE(write_blocked_list.IsStreamBlocked(kHeadersStreamId));
// Streams with same priority are popped in the order they were inserted.
EXPECT_EQ(23u, write_blocked_list.PopFront());
@@ -57,61 +62,61 @@ TEST_F(QuicWriteBlockedListTest, PriorityOrder) {
EXPECT_FALSE(write_blocked_list.IsStreamBlocked(40));
EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams());
- EXPECT_FALSE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream());
+ EXPECT_FALSE(write_blocked_list.HasWriteBlockedSpecialStream());
EXPECT_FALSE(write_blocked_list.HasWriteBlockedDataStreams());
}
-TEST_F(QuicWriteBlockedListTest, CryptoStream) {
- QuicWriteBlockedList write_blocked_list;
- write_blocked_list.RegisterStream(kCryptoStreamId, kV3HighestPriority);
+TEST_P(QuicWriteBlockedListTest, CryptoStream) {
+ QuicWriteBlockedList write_blocked_list(GetParam());
+ write_blocked_list.RegisterStream(kCryptoStreamId, true, kV3HighestPriority);
write_blocked_list.AddStream(kCryptoStreamId);
EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams());
- EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream());
+ EXPECT_TRUE(write_blocked_list.HasWriteBlockedSpecialStream());
EXPECT_EQ(kCryptoStreamId, write_blocked_list.PopFront());
EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams());
- EXPECT_FALSE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream());
+ EXPECT_FALSE(write_blocked_list.HasWriteBlockedSpecialStream());
}
-TEST_F(QuicWriteBlockedListTest, HeadersStream) {
- QuicWriteBlockedList write_blocked_list;
- write_blocked_list.RegisterStream(kHeadersStreamId, kV3HighestPriority);
+TEST_P(QuicWriteBlockedListTest, HeadersStream) {
+ QuicWriteBlockedList write_blocked_list(GetParam());
+ write_blocked_list.RegisterStream(kHeadersStreamId, true, kV3HighestPriority);
write_blocked_list.AddStream(kHeadersStreamId);
EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams());
- EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream());
+ EXPECT_TRUE(write_blocked_list.HasWriteBlockedSpecialStream());
EXPECT_EQ(kHeadersStreamId, write_blocked_list.PopFront());
EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams());
- EXPECT_FALSE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream());
+ EXPECT_FALSE(write_blocked_list.HasWriteBlockedSpecialStream());
}
-TEST_F(QuicWriteBlockedListTest, VerifyHeadersStream) {
- QuicWriteBlockedList write_blocked_list;
- write_blocked_list.RegisterStream(5, kV3HighestPriority);
- write_blocked_list.RegisterStream(kHeadersStreamId, kV3HighestPriority);
+TEST_P(QuicWriteBlockedListTest, VerifyHeadersStream) {
+ QuicWriteBlockedList write_blocked_list(GetParam());
+ write_blocked_list.RegisterStream(5, false, kV3HighestPriority);
+ write_blocked_list.RegisterStream(kHeadersStreamId, true, kV3HighestPriority);
write_blocked_list.AddStream(5);
write_blocked_list.AddStream(kHeadersStreamId);
EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams());
- EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream());
+ 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(kHeadersStreamId, write_blocked_list.PopFront());
EXPECT_EQ(5u, write_blocked_list.PopFront());
EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams());
- EXPECT_FALSE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream());
+ EXPECT_FALSE(write_blocked_list.HasWriteBlockedSpecialStream());
EXPECT_FALSE(write_blocked_list.HasWriteBlockedDataStreams());
}
-TEST_F(QuicWriteBlockedListTest, NoDuplicateEntries) {
+TEST_P(QuicWriteBlockedListTest, NoDuplicateEntries) {
// Test that QuicWriteBlockedList doesn't allow duplicate entries.
- QuicWriteBlockedList write_blocked_list;
+ QuicWriteBlockedList write_blocked_list(GetParam());
// Try to add a stream to the write blocked list multiple times at the same
// priority.
const QuicStreamId kBlockedId = kHeadersStreamId + 2;
- write_blocked_list.RegisterStream(kBlockedId, kV3HighestPriority);
+ write_blocked_list.RegisterStream(kBlockedId, false, kV3HighestPriority);
write_blocked_list.AddStream(kBlockedId);
write_blocked_list.AddStream(kBlockedId);
write_blocked_list.AddStream(kBlockedId);
@@ -126,15 +131,15 @@ TEST_F(QuicWriteBlockedListTest, NoDuplicateEntries) {
EXPECT_FALSE(write_blocked_list.HasWriteBlockedDataStreams());
}
-TEST_F(QuicWriteBlockedListTest, BatchingWrites) {
- QuicWriteBlockedList write_blocked_list;
+TEST_P(QuicWriteBlockedListTest, BatchingWrites) {
+ QuicWriteBlockedList write_blocked_list(GetParam());
const QuicStreamId id1 = kHeadersStreamId + 2;
const QuicStreamId id2 = id1 + 2;
const QuicStreamId id3 = id2 + 2;
- write_blocked_list.RegisterStream(id1, kV3LowestPriority);
- write_blocked_list.RegisterStream(id2, kV3LowestPriority);
- write_blocked_list.RegisterStream(id3, 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);
@@ -179,16 +184,16 @@ TEST_F(QuicWriteBlockedListTest, BatchingWrites) {
EXPECT_EQ(id1, write_blocked_list.PopFront());
}
-TEST_F(QuicWriteBlockedListTest, Ceding) {
- QuicWriteBlockedList write_blocked_list;
+TEST_P(QuicWriteBlockedListTest, Ceding) {
+ QuicWriteBlockedList write_blocked_list(GetParam());
- write_blocked_list.RegisterStream(15, kV3HighestPriority);
- write_blocked_list.RegisterStream(16, kV3HighestPriority);
- write_blocked_list.RegisterStream(5, 5);
- write_blocked_list.RegisterStream(4, 5);
- write_blocked_list.RegisterStream(7, 7);
- write_blocked_list.RegisterStream(kHeadersStreamId, kV3HighestPriority);
- write_blocked_list.RegisterStream(kCryptoStreamId, 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(kCryptoStreamId, true, kV3HighestPriority);
+ write_blocked_list.RegisterStream(kHeadersStreamId, true, kV3HighestPriority);
// When nothing is on the list, nothing yields.
EXPECT_FALSE(write_blocked_list.ShouldYield(5));
diff --git a/chromium/net/quic/core/tls_client_handshaker.cc b/chromium/net/quic/core/tls_client_handshaker.cc
index 76bf14622ff..eb5c40d5985 100644
--- a/chromium/net/quic/core/tls_client_handshaker.cc
+++ b/chromium/net/quic/core/tls_client_handshaker.cc
@@ -60,6 +60,13 @@ bssl::UniquePtr<SSL_CTX> TlsClientHandshaker::CreateSslCtx() {
}
bool TlsClientHandshaker::CryptoConnect() {
+ CrypterPair crypters;
+ CryptoUtils::CreateTlsInitialCrypters(Perspective::IS_CLIENT,
+ session()->connection_id(), &crypters);
+ session()->connection()->SetEncrypter(ENCRYPTION_NONE,
+ std::move(crypters.encrypter));
+ session()->connection()->SetDecrypter(ENCRYPTION_NONE,
+ std::move(crypters.decrypter));
state_ = STATE_HANDSHAKE_RUNNING;
// Configure certificate verification.
// TODO(nharper): This only verifies certs on initial connection, not on
@@ -180,16 +187,21 @@ void TlsClientHandshaker::FinishHandshake() {
}
QUIC_LOG(INFO) << "Client: setting crypters";
- QuicEncrypter* initial_encrypter = CreateEncrypter(client_secret);
- session()->connection()->SetEncrypter(ENCRYPTION_INITIAL, initial_encrypter);
- QuicEncrypter* encrypter = CreateEncrypter(client_secret);
- session()->connection()->SetEncrypter(ENCRYPTION_FORWARD_SECURE, encrypter);
-
- QuicDecrypter* initial_decrypter = CreateDecrypter(server_secret);
- session()->connection()->SetDecrypter(ENCRYPTION_INITIAL, initial_decrypter);
- QuicDecrypter* decrypter = CreateDecrypter(server_secret);
+ std::unique_ptr<QuicEncrypter> initial_encrypter =
+ CreateEncrypter(client_secret);
+ session()->connection()->SetEncrypter(ENCRYPTION_INITIAL,
+ std::move(initial_encrypter));
+ std::unique_ptr<QuicEncrypter> encrypter = CreateEncrypter(client_secret);
+ session()->connection()->SetEncrypter(ENCRYPTION_FORWARD_SECURE,
+ std::move(encrypter));
+
+ std::unique_ptr<QuicDecrypter> initial_decrypter =
+ CreateDecrypter(server_secret);
+ session()->connection()->SetDecrypter(ENCRYPTION_INITIAL,
+ std::move(initial_decrypter));
+ std::unique_ptr<QuicDecrypter> decrypter = CreateDecrypter(server_secret);
session()->connection()->SetAlternativeDecrypter(ENCRYPTION_FORWARD_SECURE,
- decrypter, true);
+ std::move(decrypter), true);
session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
diff --git a/chromium/net/quic/core/tls_handshaker.cc b/chromium/net/quic/core/tls_handshaker.cc
index 06b95ec5090..032dece493f 100644
--- a/chromium/net/quic/core/tls_handshaker.cc
+++ b/chromium/net/quic/core/tls_handshaker.cc
@@ -7,8 +7,8 @@
#include "base/no_destructor.h"
#include "net/quic/core/quic_crypto_stream.h"
#include "net/quic/core/tls_client_handshaker.h"
-#include "net/quic/core/tls_server_handshaker.h"
#include "net/quic/platform/api/quic_arraysize.h"
+#include "net/quic/platform/api/quic_singleton.h"
namespace net {
@@ -23,9 +23,8 @@ namespace {
class SslIndexSingleton {
public:
- static const SslIndexSingleton* GetInstance() {
- static const base::NoDestructor<SslIndexSingleton> instance;
- return instance.get();
+ static SslIndexSingleton* GetInstance() {
+ return QuicSingleton<SslIndexSingleton>::get();
}
int HandshakerIndex() const { return ssl_ex_data_index_handshaker_; }
@@ -37,7 +36,7 @@ class SslIndexSingleton {
CHECK_LE(0, ssl_ex_data_index_handshaker_);
}
- friend class base::NoDestructor<SslIndexSingleton>;
+ friend QuicSingletonFriend<SslIndexSingleton>;
int ssl_ex_data_index_handshaker_;
@@ -70,37 +69,21 @@ bool TlsHandshaker::DeriveSecrets(std::vector<uint8_t>* client_secret_out,
QUIC_ARRAYSIZE(kServerLabel) - 1, nullptr, 0, 0) == 1);
}
-namespace {
-
-template <class QuicCrypter>
-void SetKeyAndIV(const EVP_MD* prf,
- const std::vector<uint8_t>& pp_secret,
- QuicCrypter* crypter) {
- std::vector<uint8_t> key = CryptoUtils::HkdfExpandLabel(
- prf, pp_secret, "key", crypter->GetKeySize());
- std::vector<uint8_t> iv =
- CryptoUtils::HkdfExpandLabel(prf, pp_secret, "iv", crypter->GetIVSize());
- crypter->SetKey(
- QuicStringPiece(reinterpret_cast<char*>(key.data()), key.size()));
- crypter->SetIV(
- QuicStringPiece(reinterpret_cast<char*>(iv.data()), iv.size()));
-}
-
-} // namespace
-
-QuicEncrypter* TlsHandshaker::CreateEncrypter(
+std::unique_ptr<QuicEncrypter> TlsHandshaker::CreateEncrypter(
const std::vector<uint8_t>& pp_secret) {
- QuicEncrypter* encrypter = QuicEncrypter::CreateFromCipherSuite(
- SSL_CIPHER_get_id(SSL_get_current_cipher(ssl())));
- SetKeyAndIV(Prf(), pp_secret, encrypter);
+ std::unique_ptr<QuicEncrypter> encrypter =
+ QuicEncrypter::CreateFromCipherSuite(
+ SSL_CIPHER_get_id(SSL_get_current_cipher(ssl())));
+ CryptoUtils::SetKeyAndIV(Prf(), pp_secret, encrypter.get());
return encrypter;
}
-QuicDecrypter* TlsHandshaker::CreateDecrypter(
+std::unique_ptr<QuicDecrypter> TlsHandshaker::CreateDecrypter(
const std::vector<uint8_t>& pp_secret) {
- QuicDecrypter* decrypter = QuicDecrypter::CreateFromCipherSuite(
- SSL_CIPHER_get_id(SSL_get_current_cipher(ssl())));
- SetKeyAndIV(Prf(), pp_secret, decrypter);
+ std::unique_ptr<QuicDecrypter> decrypter =
+ QuicDecrypter::CreateFromCipherSuite(
+ SSL_CIPHER_get_id(SSL_get_current_cipher(ssl())));
+ CryptoUtils::SetKeyAndIV(Prf(), pp_secret, decrypter.get());
return decrypter;
}
diff --git a/chromium/net/quic/core/tls_handshaker.h b/chromium/net/quic/core/tls_handshaker.h
index c542be36aff..963f129f953 100644
--- a/chromium/net/quic/core/tls_handshaker.h
+++ b/chromium/net/quic/core/tls_handshaker.h
@@ -65,8 +65,10 @@ class QUIC_EXPORT_PRIVATE TlsHandshaker : public QuicTlsAdapter::Visitor {
bool DeriveSecrets(std::vector<uint8_t>* client_secret_out,
std::vector<uint8_t>* server_secret_out);
- QuicEncrypter* CreateEncrypter(const std::vector<uint8_t>& pp_secret);
- QuicDecrypter* CreateDecrypter(const std::vector<uint8_t>& pp_secret);
+ std::unique_ptr<QuicEncrypter> CreateEncrypter(
+ const std::vector<uint8_t>& pp_secret);
+ std::unique_ptr<QuicDecrypter> CreateDecrypter(
+ const std::vector<uint8_t>& pp_secret);
SSL* ssl() { return ssl_.get(); }
QuicCryptoStream* stream() { return stream_; }
diff --git a/chromium/net/quic/core/tls_handshaker_test.cc b/chromium/net/quic/core/tls_handshaker_test.cc
index 27821c30999..de84861321d 100644
--- a/chromium/net/quic/core/tls_handshaker_test.cc
+++ b/chromium/net/quic/core/tls_handshaker_test.cc
@@ -251,13 +251,15 @@ class TlsHandshakerTest : public QuicTest {
server_conn_(new MockQuicConnection(&conn_helper_,
&alarm_factory_,
Perspective::IS_SERVER)),
- client_session_(client_conn_),
- server_session_(server_conn_),
- client_stream_(&client_session_),
- server_stream_(
- new TestQuicCryptoServerStream(&server_session_, &proof_source_)) {
- EXPECT_FALSE(client_stream_.encryption_established());
- EXPECT_FALSE(client_stream_.handshake_confirmed());
+ client_session_(client_conn_, /*create_mock_crypto_stream=*/false),
+ server_session_(server_conn_, /*create_mock_crypto_stream=*/false) {
+ client_stream_ = new TestQuicCryptoClientStream(&client_session_);
+ client_session_.SetCryptoStream(client_stream_);
+ server_stream_ =
+ new TestQuicCryptoServerStream(&server_session_, &proof_source_);
+ server_session_.SetCryptoStream(server_stream_);
+ EXPECT_FALSE(client_stream_->encryption_established());
+ EXPECT_FALSE(client_stream_->handshake_confirmed());
EXPECT_FALSE(server_stream_->encryption_established());
EXPECT_FALSE(server_stream_->handshake_confirmed());
}
@@ -269,19 +271,19 @@ class TlsHandshakerTest : public QuicTest {
MockQuicSession client_session_;
MockQuicSession server_session_;
- TestQuicCryptoClientStream client_stream_;
FakeProofSource proof_source_;
- std::unique_ptr<TestQuicCryptoServerStream> server_stream_;
+ TestQuicCryptoClientStream* client_stream_;
+ TestQuicCryptoServerStream* server_stream_;
};
TEST_F(TlsHandshakerTest, CryptoHandshake) {
EXPECT_CALL(*client_conn_, CloseConnection(_, _, _)).Times(0);
EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
- client_stream_.CryptoConnect();
- MoveStreamFrames(&client_stream_, server_stream_.get());
+ client_stream_->CryptoConnect();
+ MoveStreamFrames(client_stream_, server_stream_);
- EXPECT_TRUE(client_stream_.handshake_confirmed());
- EXPECT_TRUE(client_stream_.encryption_established());
+ EXPECT_TRUE(client_stream_->handshake_confirmed());
+ EXPECT_TRUE(client_stream_->encryption_established());
EXPECT_TRUE(server_stream_->handshake_confirmed());
EXPECT_TRUE(server_stream_->encryption_established());
}
@@ -295,16 +297,16 @@ TEST_F(TlsHandshakerTest, HandshakeWithAsyncProofSource) {
proof_source->Activate();
// Start handshake.
- client_stream_.CryptoConnect();
- MoveStreamFrames(&client_stream_, server_stream_.get());
+ client_stream_->CryptoConnect();
+ MoveStreamFrames(client_stream_, server_stream_);
ASSERT_EQ(proof_source->NumPendingCallbacks(), 1);
proof_source->InvokePendingCallback(0);
- MoveStreamFrames(&client_stream_, server_stream_.get());
+ MoveStreamFrames(client_stream_, server_stream_);
- EXPECT_TRUE(client_stream_.handshake_confirmed());
- EXPECT_TRUE(client_stream_.encryption_established());
+ EXPECT_TRUE(client_stream_->handshake_confirmed());
+ EXPECT_TRUE(client_stream_->encryption_established());
EXPECT_TRUE(server_stream_->handshake_confirmed());
EXPECT_TRUE(server_stream_->encryption_established());
}
@@ -318,11 +320,11 @@ TEST_F(TlsHandshakerTest, CancelPendingProofSource) {
proof_source->Activate();
// Start handshake.
- client_stream_.CryptoConnect();
- MoveStreamFrames(&client_stream_, server_stream_.get());
+ client_stream_->CryptoConnect();
+ MoveStreamFrames(client_stream_, server_stream_);
ASSERT_EQ(proof_source->NumPendingCallbacks(), 1);
- server_stream_.reset();
+ server_stream_ = nullptr;
proof_source->InvokePendingCallback(0);
}
@@ -332,27 +334,27 @@ TEST_F(TlsHandshakerTest, HandshakeWithAsyncProofVerifier) {
EXPECT_CALL(*server_conn_, CloseConnection(_, _, _)).Times(0);
// Enable FakeProofVerifier to capture call to VerifyCertChain and run it
// asynchronously.
- FakeProofVerifier* proof_verifier = client_stream_.GetFakeProofVerifier();
+ FakeProofVerifier* proof_verifier = client_stream_->GetFakeProofVerifier();
proof_verifier->Activate();
// Start handshake.
- client_stream_.CryptoConnect();
- MoveStreamFrames(&client_stream_, server_stream_.get());
+ client_stream_->CryptoConnect();
+ MoveStreamFrames(client_stream_, server_stream_);
ASSERT_EQ(proof_verifier->NumPendingCallbacks(), 1u);
proof_verifier->InvokePendingCallback(0);
- MoveStreamFrames(&client_stream_, server_stream_.get());
+ MoveStreamFrames(client_stream_, server_stream_);
- EXPECT_TRUE(client_stream_.handshake_confirmed());
- EXPECT_TRUE(client_stream_.encryption_established());
+ EXPECT_TRUE(client_stream_->handshake_confirmed());
+ EXPECT_TRUE(client_stream_->encryption_established());
EXPECT_TRUE(server_stream_->handshake_confirmed());
EXPECT_TRUE(server_stream_->encryption_established());
}
TEST_F(TlsHandshakerTest, ClientConnectionClosedOnTlsAlert) {
// Have client send ClientHello.
- client_stream_.CryptoConnect();
+ client_stream_->CryptoConnect();
EXPECT_CALL(*client_conn_, CloseConnection(QUIC_HANDSHAKE_FAILED, _, _));
// Send fake "internal_error" fatal TLS alert from server to client.
@@ -366,11 +368,11 @@ TEST_F(TlsHandshakerTest, ClientConnectionClosedOnTlsAlert) {
80, // AlertDescription internal_error
};
QuicStreamFrame alert(kCryptoStreamId, false,
- client_stream_.stream_bytes_read(),
+ client_stream_->stream_bytes_read(),
QuicStringPiece(alert_msg, QUIC_ARRAYSIZE(alert_msg)));
- client_stream_.OnStreamFrame(alert);
+ client_stream_->OnStreamFrame(alert);
- EXPECT_FALSE(client_stream_.handshake_confirmed());
+ EXPECT_FALSE(client_stream_->handshake_confirmed());
}
TEST_F(TlsHandshakerTest, ServerConnectionClosedOnTlsAlert) {
diff --git a/chromium/net/quic/core/tls_server_handshaker.cc b/chromium/net/quic/core/tls_server_handshaker.cc
index f0f6a4e5fbc..17db9f02f47 100644
--- a/chromium/net/quic/core/tls_server_handshaker.cc
+++ b/chromium/net/quic/core/tls_server_handshaker.cc
@@ -60,6 +60,13 @@ TlsServerHandshaker::TlsServerHandshaker(QuicCryptoStream* stream,
: TlsHandshaker(stream, session, ssl_ctx),
proof_source_(proof_source),
crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {
+ CrypterPair crypters;
+ CryptoUtils::CreateTlsInitialCrypters(Perspective::IS_SERVER,
+ session->connection_id(), &crypters);
+ session->connection()->SetEncrypter(ENCRYPTION_NONE,
+ std::move(crypters.encrypter));
+ session->connection()->SetDecrypter(ENCRYPTION_NONE,
+ std::move(crypters.decrypter));
// Set callback to provide SNI.
// SSL_CTX_set_tlsext_servername_callback(ssl_ctx, SelectCertificateCallback);
@@ -195,16 +202,21 @@ void TlsServerHandshaker::FinishHandshake() {
}
QUIC_LOG(INFO) << "Server: setting crypters";
- QuicEncrypter* initial_encrypter = CreateEncrypter(server_secret);
- session()->connection()->SetEncrypter(ENCRYPTION_INITIAL, initial_encrypter);
- QuicEncrypter* encrypter = CreateEncrypter(server_secret);
- session()->connection()->SetEncrypter(ENCRYPTION_FORWARD_SECURE, encrypter);
-
- QuicDecrypter* initial_decrypter = CreateDecrypter(client_secret);
- session()->connection()->SetDecrypter(ENCRYPTION_INITIAL, initial_decrypter);
- QuicDecrypter* decrypter = CreateDecrypter(client_secret);
+ std::unique_ptr<QuicEncrypter> initial_encrypter =
+ CreateEncrypter(server_secret);
+ session()->connection()->SetEncrypter(ENCRYPTION_INITIAL,
+ std::move(initial_encrypter));
+ std::unique_ptr<QuicEncrypter> encrypter = CreateEncrypter(server_secret);
+ session()->connection()->SetEncrypter(ENCRYPTION_FORWARD_SECURE,
+ std::move(encrypter));
+
+ std::unique_ptr<QuicDecrypter> initial_decrypter =
+ CreateDecrypter(client_secret);
+ session()->connection()->SetDecrypter(ENCRYPTION_INITIAL,
+ std::move(initial_decrypter));
+ std::unique_ptr<QuicDecrypter> decrypter = CreateDecrypter(client_secret);
session()->connection()->SetAlternativeDecrypter(ENCRYPTION_FORWARD_SECURE,
- decrypter, true);
+ std::move(decrypter), true);
session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
diff --git a/chromium/net/quic/http/decoder/quic_http_frame_decoder_adapter.cc b/chromium/net/quic/http/decoder/quic_http_frame_decoder_adapter.cc
index 7bbfc68e9c3..6f70e0c9c71 100644
--- a/chromium/net/quic/http/decoder/quic_http_frame_decoder_adapter.cc
+++ b/chromium/net/quic/http/decoder/quic_http_frame_decoder_adapter.cc
@@ -22,6 +22,7 @@
#include "net/quic/http/decoder/quic_http_frame_decoder_listener.h"
#include "net/quic/http/quic_http_constants.h"
#include "net/quic/http/quic_http_structures.h"
+#include "net/quic/platform/api/quic_flags.h"
#include "net/quic/platform/api/quic_ptr_util.h"
#include "net/quic/platform/api/quic_string_utils.h"
#include "net/spdy/core/hpack/hpack_decoder_adapter.h"
@@ -450,7 +451,13 @@ void QuicHttpDecoderAdapter::OnSetting(
}
return;
}
- visitor()->OnSetting(setting_id, setting_fields.value);
+ // TODO(quic): Consider whether to add support for handling unknown SETTINGS
+ // IDs, which currently cause a connection close.
+ if (GetQuicRestartFlag(http2_propagate_unknown_settings)) {
+ visitor()->OnSetting(setting_id, setting_fields.value);
+ } else {
+ visitor()->OnSettingOld(setting_id, setting_fields.value);
+ }
}
void QuicHttpDecoderAdapter::OnSettingsEnd() {
diff --git a/chromium/net/quic/http/quic_http_structures.h b/chromium/net/quic/http/quic_http_structures.h
index 10c7d9e0d44..eb3f7a91ecb 100644
--- a/chromium/net/quic/http/quic_http_structures.h
+++ b/chromium/net/quic/http/quic_http_structures.h
@@ -249,7 +249,6 @@ QUIC_EXPORT_PRIVATE std::ostream& operator<<(
struct QuicHttpPingFields {
static constexpr size_t EncodedSize() { return 8; }
- // TODO(jamessynge): Rename opaque_bytes to opaque_bytes.
uint8_t opaque_bytes[8];
};
diff --git a/chromium/net/quic/http/tools/quic_http_random_util.cc b/chromium/net/quic/http/tools/quic_http_random_util.cc
index 7e7b259ba8d..afe4d064ce3 100644
--- a/chromium/net/quic/http/tools/quic_http_random_util.cc
+++ b/chromium/net/quic/http/tools/quic_http_random_util.cc
@@ -51,22 +51,6 @@ size_t GenerateUniformInRange(size_t lo, size_t hi, QuicTestRandomBase* rng) {
return lo + rng->Rand64() % (hi - lo);
}
-// Here "word" means something that starts with a lower-case letter, and has
-// zero or more additional characters that are numbers or lower-case letters.
-QuicString GenerateQuicHttpHeaderName(size_t len, QuicTestRandomBase* rng) {
- QuicStringPiece alpha_lc = "abcdefghijklmnopqrstuvwxyz";
- // If the name is short, just make it one word.
- if (len < 8) {
- return RandomString(rng, len, alpha_lc);
- }
- // If the name is longer, ensure it starts with a word, and after that may
- // have any character in alphanumdash_lc. 4 is arbitrary, could be as low
- // as 1.
- QuicStringPiece alphanumdash_lc = "abcdefghijklmnopqrstuvwxyz0123456789-";
- return RandomString(rng, 4, alpha_lc) +
- RandomString(rng, len - 4, alphanumdash_lc);
-}
-
QuicString GenerateWebSafeString(size_t len, QuicTestRandomBase* rng) {
return RandomString(rng, len, kWebsafe64);
}
diff --git a/chromium/net/quic/http/tools/quic_http_random_util.h b/chromium/net/quic/http/tools/quic_http_random_util.h
index da0245a4da5..1d6788a6ffd 100644
--- a/chromium/net/quic/http/tools/quic_http_random_util.h
+++ b/chromium/net/quic/http/tools/quic_http_random_util.h
@@ -16,15 +16,10 @@ namespace test {
// Returns a random integer in the range [lo, hi).
size_t GenerateUniformInRange(size_t lo, size_t hi, QuicTestRandomBase* rng);
-// Generate a std::string with the allowed character set for HTTP/2 /
-// HPQUIC_HTTP_ACK header names.
-QuicString GenerateQuicHttpHeaderName(size_t len, QuicTestRandomBase* rng);
-
-// Generate a std::string with the web-safe std::string character set of
-// specified len.
+// Generate a string with the web-safe string character set of specified len.
QuicString GenerateWebSafeString(size_t len, QuicTestRandomBase* rng);
-// Generate a std::string with the web-safe std::string character set of length
+// Generate a string with the web-safe string character set of length
// [lo, hi).
QuicString GenerateWebSafeString(size_t lo, size_t hi, QuicTestRandomBase* rng);
diff --git a/chromium/net/quic/platform/api/quic_logging.h b/chromium/net/quic/platform/api/quic_logging.h
index 14b1bffa3d6..798bfbf8252 100644
--- a/chromium/net/quic/platform/api/quic_logging.h
+++ b/chromium/net/quic/platform/api/quic_logging.h
@@ -13,6 +13,8 @@
// they would simply be translated to LOG.
#define QUIC_DVLOG(verbose_level) QUIC_DVLOG_IMPL(verbose_level)
+#define QUIC_DVLOG_IF(verbose_level, condition) \
+ QUIC_DVLOG_IF_IMPL(verbose_level, condition)
#define QUIC_DLOG(severity) QUIC_DLOG_IMPL(severity)
#define QUIC_DLOG_IF(severity, condition) QUIC_DLOG_IF_IMPL(severity, condition)
#define QUIC_VLOG(verbose_level) QUIC_VLOG_IMPL(verbose_level)
diff --git a/chromium/net/quic/platform/api/quic_mem_slice.h b/chromium/net/quic/platform/api/quic_mem_slice.h
index 11205af5c1d..ba0c03bb17a 100644
--- a/chromium/net/quic/platform/api/quic_mem_slice.h
+++ b/chromium/net/quic/platform/api/quic_mem_slice.h
@@ -41,6 +41,10 @@ class QUIC_EXPORT_PRIVATE QuicMemSlice {
~QuicMemSlice() = default;
+ // Release the underlying reference. Further access the memory will result in
+ // undefined behavior.
+ void Reset() { impl_.Reset(); }
+
// Returns a const char pointer to underlying data buffer.
const char* data() const { return impl_.data(); }
// Returns the length of underlying data buffer.
diff --git a/chromium/net/quic/platform/api/quic_singleton.h b/chromium/net/quic/platform/api/quic_singleton.h
new file mode 100644
index 00000000000..f9d393f8a89
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_singleton.h
@@ -0,0 +1,48 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_PLATFORM_API_QUIC_SINGLETON_H_
+#define NET_QUIC_PLATFORM_API_QUIC_SINGLETON_H_
+
+#include "net/quic/platform/impl/quic_singleton_impl.h"
+
+namespace net {
+
+// Singleton utility. Example usage:
+//
+// In your header:
+// #include "net/quic/platform/api/quic_singleton.h"
+// class Foo {
+// public:
+// static Foo* GetInstance();
+// void Bar() { ... }
+// private:
+// Foo() { ... }
+// friend net::QuicSingletonFriend<Foo>;
+// };
+//
+// In your source file:
+// Foo* Foo::GetInstance() {
+// return net::QuicSingleton<Foo>::get();
+// }
+//
+// To use the singleton:
+// Foo::GetInstance()->Bar();
+//
+// NOTE: The method accessing Singleton<T>::get() has to be named as GetInstance
+// and it is important that Foo::GetInstance() is not inlined in the
+// header. This makes sure that when source files from multiple targets include
+// this header they don't end up with different copies of the inlined code
+// creating multiple copies of the singleton.
+template <typename T>
+using QuicSingleton = QuicSingletonImpl<T>;
+
+// Type that a class using QuicSingleton must declare as a friend, in order for
+// QuicSingleton to be able to access the class's private constructor.
+template <typename T>
+using QuicSingletonFriend = QuicSingletonFriendImpl<T>;
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_API_QUIC_SINGLETON_H_
diff --git a/chromium/net/quic/platform/api/quic_singleton_test.cc b/chromium/net/quic/platform/api/quic_singleton_test.cc
new file mode 100644
index 00000000000..e6a2ec5e628
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_singleton_test.cc
@@ -0,0 +1,32 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/platform/api/quic_singleton.h"
+
+#include "net/quic/platform/api/quic_test.h"
+
+namespace net {
+namespace test {
+namespace {
+
+class Foo {
+ public:
+ static Foo* GetInstance() { return net::QuicSingleton<Foo>::get(); }
+
+ private:
+ Foo() = default;
+ friend net::QuicSingletonFriend<Foo>;
+};
+
+class QuicSingletonTest : public QuicTest {};
+
+TEST_F(QuicSingletonTest, Get) {
+ Foo* f1 = Foo::GetInstance();
+ Foo* f2 = Foo::GetInstance();
+ EXPECT_EQ(f1, f2);
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/platform/api/quic_test.h b/chromium/net/quic/platform/api/quic_test.h
index b976b452a52..ca0b71e6564 100644
--- a/chromium/net/quic/platform/api/quic_test.h
+++ b/chromium/net/quic/platform/api/quic_test.h
@@ -7,6 +7,8 @@
#include "net/quic/platform/impl/quic_test_impl.h"
+using QuicFlagSaver = QuicFlagSaverImpl;
+
// Defines the base classes to be used in QUIC tests.
using QuicTest = QuicTestImpl;
template <class T>
diff --git a/chromium/net/quic/platform/api/quic_uint128.h b/chromium/net/quic/platform/api/quic_uint128.h
new file mode 100644
index 00000000000..afe252c3ba0
--- /dev/null
+++ b/chromium/net/quic/platform/api/quic_uint128.h
@@ -0,0 +1,19 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_PLATFORM_API_QUIC_UINT128_H_
+#define NET_QUIC_PLATFORM_API_QUIC_UINT128_H_
+
+#include "net/quic/platform/impl/quic_uint128_impl.h"
+
+namespace net {
+
+using QuicUint128 = QuicUint128Impl;
+#define MakeQuicUint128(hi, lo) MakeQuicUint128Impl(hi, lo);
+#define QuicUint128Low64(x) QuicUint128Low64Impl(x);
+#define QuicUint128High64(x) QuicUint128High64Impl(x);
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_API_QUIC_UINT128_H_
diff --git a/chromium/net/quic/platform/impl/quic_logging_impl.h b/chromium/net/quic/platform/impl/quic_logging_impl.h
index 37aa990b365..fb9add316fb 100644
--- a/chromium/net/quic/platform/impl/quic_logging_impl.h
+++ b/chromium/net/quic/platform/impl/quic_logging_impl.h
@@ -42,6 +42,8 @@
#define QUIC_CHROMIUM_DLOG_IF_DFATAL(condition) DLOG_IF(DFATAL, condition)
#define QUIC_DVLOG_IMPL(verbose_level) DVLOG(verbose_level)
+#define QUIC_DVLOG_IF_IMPL(verbose_level, condition) \
+ DVLOG_IF(verbose_level, condition)
#if defined(OS_WIN)
// wingdi.h defines ERROR to be 0. When we call QUIC_DLOG(ERROR), it gets
diff --git a/chromium/net/quic/platform/impl/quic_mem_slice_impl.cc b/chromium/net/quic/platform/impl/quic_mem_slice_impl.cc
index 5fdeb24a408..e82fcf1493c 100644
--- a/chromium/net/quic/platform/impl/quic_mem_slice_impl.cc
+++ b/chromium/net/quic/platform/impl/quic_mem_slice_impl.cc
@@ -34,6 +34,11 @@ QuicMemSliceImpl& QuicMemSliceImpl::operator=(QuicMemSliceImpl&& other) {
QuicMemSliceImpl::~QuicMemSliceImpl() = default;
+void QuicMemSliceImpl::Reset() {
+ io_buffer_ = nullptr;
+ length_ = 0;
+}
+
const char* QuicMemSliceImpl::data() const {
if (io_buffer_ == nullptr) {
return nullptr;
diff --git a/chromium/net/quic/platform/impl/quic_mem_slice_impl.h b/chromium/net/quic/platform/impl/quic_mem_slice_impl.h
index 43b9aad460a..1acf9f7b3f9 100644
--- a/chromium/net/quic/platform/impl/quic_mem_slice_impl.h
+++ b/chromium/net/quic/platform/impl/quic_mem_slice_impl.h
@@ -34,6 +34,10 @@ class QUIC_EXPORT_PRIVATE QuicMemSliceImpl {
~QuicMemSliceImpl();
+ // Release the underlying reference. Further access the memory will result in
+ // undefined behavior.
+ void Reset();
+
// Returns a char pointer to underlying data buffer.
const char* data() const;
// Returns the length of underlying data buffer.
diff --git a/chromium/net/quic/platform/impl/quic_singleton_impl.h b/chromium/net/quic/platform/impl/quic_singleton_impl.h
new file mode 100644
index 00000000000..9c02071cc53
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_singleton_impl.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_SINGLETON_IMPL_H_
+#define NET_QUIC_PLATFORM_IMPL_QUIC_SINGLETON_IMPL_H_
+
+#include "base/memory/singleton.h"
+
+namespace net {
+
+template <typename T>
+using QuicSingletonImpl = base::Singleton<T, base::DefaultSingletonTraits<T>>;
+
+template <typename T>
+using QuicSingletonFriendImpl = base::DefaultSingletonTraits<T>;
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_IMPL_QUIC_SINGLETON_IMPL_H_
diff --git a/chromium/net/quic/platform/impl/quic_test_impl.cc b/chromium/net/quic/platform/impl/quic_test_impl.cc
index dc1709b2856..6e22a9f5922 100644
--- a/chromium/net/quic/platform/impl/quic_test_impl.cc
+++ b/chromium/net/quic/platform/impl/quic_test_impl.cc
@@ -4,20 +4,14 @@
#include "net/quic/platform/impl/quic_test_impl.h"
-#include "base/logging.h"
-#include "net/quic/platform/api/quic_flags.h"
-
-QuicFlagSaver::QuicFlagSaver() {
-#define QUIC_FLAG(type, flag, value) \
- CHECK_EQ(value, flag) \
- << "Flag set to an unexpected value. A prior test is likely " \
- << "setting a flag without using a QuicFlagSaver";
+QuicFlagSaverImpl::QuicFlagSaverImpl() {
+#define QUIC_FLAG(type, flag, value) saved_##flag##_ = flag;
#include "net/quic/core/quic_flags_list.h"
#undef QUIC_FLAG
}
-QuicFlagSaver::~QuicFlagSaver() {
-#define QUIC_FLAG(type, flag, value) flag = value;
+QuicFlagSaverImpl::~QuicFlagSaverImpl() {
+#define QUIC_FLAG(type, flag, value) flag = saved_##flag##_;
#include "net/quic/core/quic_flags_list.h"
#undef QUIC_FLAG
}
diff --git a/chromium/net/quic/platform/impl/quic_test_impl.h b/chromium/net/quic/platform/impl/quic_test_impl.h
index 6be16527516..98ae8760cc2 100644
--- a/chromium/net/quic/platform/impl/quic_test_impl.h
+++ b/chromium/net/quic/platform/impl/quic_test_impl.h
@@ -5,26 +5,49 @@
#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_TEST_IMPL_H_
#define NET_QUIC_PLATFORM_IMPL_QUIC_TEST_IMPL_H_
+#include "base/logging.h"
+#include "net/quic/platform/api/quic_flags.h"
#include "testing/gmock/include/gmock/gmock.h" // IWYU pragma: export
#include "testing/gtest/include/gtest/gtest.h" // IWYU pragma: export
-// When constructed, checks that all QUIC flags have their correct default
-// values and when destructed, restores those values.
-class QuicFlagSaver {
+// When constructed, saves the current values of all QUIC flags. When
+// destructed, restores all QUIC flags to the saved values.
+class QuicFlagSaverImpl {
public:
- QuicFlagSaver();
- ~QuicFlagSaver();
+ QuicFlagSaverImpl();
+ ~QuicFlagSaverImpl();
+
+ private:
+#define QUIC_FLAG(type, flag, value) type saved_##flag##_;
+#include "net/quic/core/quic_flags_list.h"
+#undef QUIC_FLAG
+};
+
+// Checks if all QUIC flags are on their default values on construction.
+class QuicFlagChecker {
+ public:
+ QuicFlagChecker() {
+#define QUIC_FLAG(type, flag, value) \
+ CHECK_EQ(value, flag) \
+ << "Flag set to an unexpected value. A prior test is likely " \
+ << "setting a flag without using a QuicFlagSaver. Use QuicTest to " \
+ "avoid this issue.";
+#include "net/quic/core/quic_flags_list.h"
+#undef QUIC_FLAG
+ }
};
class QuicTestImpl : public ::testing::Test {
private:
- QuicFlagSaver flags_; // Save/restore all QUIC flag values.
+ QuicFlagChecker checker_;
+ QuicFlagSaverImpl saver_; // Save/restore all QUIC flag values.
};
template <class T>
class QuicTestWithParamImpl : public ::testing::TestWithParam<T> {
private:
- QuicFlagSaver flags_; // Save/restore all QUIC flag values.
+ QuicFlagChecker checker_;
+ QuicFlagSaverImpl saver_; // Save/restore all QUIC flag values.
};
#endif // NET_QUIC_PLATFORM_IMPL_QUIC_TEST_IMPL_H_
diff --git a/chromium/net/quic/platform/impl/quic_uint128_impl.h b/chromium/net/quic/platform/impl/quic_uint128_impl.h
new file mode 100644
index 00000000000..cad9a6eea7d
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_uint128_impl.h
@@ -0,0 +1,19 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_UINT128_IMPL_H_
+#define NET_QUIC_PLATFORM_IMPL_QUIC_UINT128_IMPL_H_
+
+#include "net/base/int128.h"
+
+namespace net {
+
+using QuicUint128Impl = uint128;
+#define MakeQuicUint128Impl(hi, lo) MakeUint128(hi, lo)
+#define QuicUint128Low64Impl(x) Uint128Low64(x);
+#define QuicUint128High64Impl(x) Uint128High64(x);
+
+} // namespace net
+
+#endif // NET_QUIC_PLATFORM_IMPL_QUIC_UINT128_IMPL_H_
diff --git a/chromium/net/quic/quartc/quartc_factory.cc b/chromium/net/quic/quartc/quartc_factory.cc
index 3e182fa99e1..68912accf47 100644
--- a/chromium/net/quic/quartc/quartc_factory.cc
+++ b/chromium/net/quic/quartc/quartc_factory.cc
@@ -106,6 +106,8 @@ QuartcFactory::~QuartcFactory() {}
std::unique_ptr<QuartcSessionInterface> QuartcFactory::CreateQuartcSession(
const QuartcSessionConfig& quartc_session_config) {
DCHECK(quartc_session_config.packet_transport);
+ SetQuicReloadableFlag(quic_better_crypto_retransmission, true);
+ SetQuicReloadableFlag(quic_is_write_blocked, true);
Perspective perspective = quartc_session_config.is_server
? Perspective::IS_SERVER
@@ -121,6 +123,7 @@ std::unique_ptr<QuartcSessionInterface> QuartcFactory::CreateQuartcSession(
// Note: These settings have no effect for Exoblaze builds since
// SetQuicReloadableFlag() gets stubbed out.
SetQuicReloadableFlag(quic_bbr_less_probe_rtt, true);
+ SetQuicReloadableFlag(quic_unified_iw_options, true);
for (const auto option : quartc_session_config.bbr_options) {
switch (option) {
case (QuartcBbrOptions::kSlowerStartup):
@@ -141,6 +144,24 @@ std::unique_ptr<QuartcSessionInterface> QuartcFactory::CreateQuartcSession(
case (QuartcBbrOptions::kFillUpLinkDuringProbing):
quic_connection->set_fill_up_link_during_probing(true);
break;
+ case (QuartcBbrOptions::kInitialWindow3):
+ copt.push_back(kIW03);
+ break;
+ case (QuartcBbrOptions::kInitialWindow10):
+ copt.push_back(kIW10);
+ break;
+ case (QuartcBbrOptions::kInitialWindow20):
+ copt.push_back(kIW20);
+ break;
+ case (QuartcBbrOptions::kInitialWindow50):
+ copt.push_back(kIW50);
+ break;
+ case (QuartcBbrOptions::kStartup1RTT):
+ copt.push_back(k1RTT);
+ break;
+ case (QuartcBbrOptions::kStartup2RTT):
+ copt.push_back(k2RTT);
+ break;
}
}
}
diff --git a/chromium/net/quic/quartc/quartc_factory_interface.h b/chromium/net/quic/quartc/quartc_factory_interface.h
index 33dd6aa15ee..1007509ce45 100644
--- a/chromium/net/quic/quartc/quartc_factory_interface.h
+++ b/chromium/net/quic/quartc/quartc_factory_interface.h
@@ -37,6 +37,12 @@ enum class QuartcBbrOptions {
// once.
kFillUpLinkDuringProbing, // Sends probing retransmissions whenever we
// become application limited.
+ kInitialWindow3, // Use a 3-packet initial congestion window.
+ kInitialWindow10, // Use a 10-packet initial congestion window.
+ kInitialWindow20, // Use a 20-packet initial congestion window.
+ kInitialWindow50, // Use a 50-packet initial congestion window.
+ kStartup1RTT, // Stay in STARTUP for 1 RTT.
+ kStartup2RTT, // Stay in STARTUP for 2 RTTs.
};
// Used to create instances for Quartc objects such as QuartcSession.
diff --git a/chromium/net/quic/quartc/quartc_session.cc b/chromium/net/quic/quartc/quartc_session.cc
index 5bb483b297d..097f165d740 100644
--- a/chromium/net/quic/quartc/quartc_session.cc
+++ b/chromium/net/quic/quartc/quartc_session.cc
@@ -14,10 +14,6 @@ namespace net {
namespace {
-// Default priority for incoming QUIC streams.
-// TODO(zhihuang): Determine if this value is correct.
-static const SpdyPriority kDefaultPriority = 3;
-
// Arbitrary server port number for net::QuicCryptoClientConfig.
const int kQuicServerPort = 0;
@@ -165,8 +161,10 @@ QuicCryptoStream* QuartcSession::GetMutableCryptoStream() {
}
QuartcStream* QuartcSession::CreateOutgoingDynamicStream() {
- return ActivateDataStream(
- CreateDataStream(GetNextOutgoingStreamId(), kDefaultPriority));
+ // Use default priority for incoming QUIC streams.
+ // TODO(zhihuang): Determine if this value is correct.
+ return ActivateDataStream(CreateDataStream(GetNextOutgoingStreamId(),
+ QuicStream::kDefaultPriority));
}
void QuartcSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
@@ -186,7 +184,9 @@ void QuartcSession::CloseStream(QuicStreamId stream_id) {
// QuicStream::OnClose), the stream is already closed so return.
return;
}
- write_blocked_streams()->UnregisterStream(stream_id);
+ if (!register_streams_early()) {
+ write_blocked_streams()->UnregisterStream(stream_id, /*is_static=*/false);
+ }
QuicSession::CloseStream(stream_id);
}
@@ -284,6 +284,11 @@ void QuartcSession::SetDelegate(
DCHECK(session_delegate_);
}
+void QuartcSession::SetSessionVisitor(QuartcSessionVisitor* debug_visitor) {
+ debug_visitor->SetQuicConnection(connection_.get());
+ connection_->set_debug_visitor(debug_visitor->GetConnectionVisitor());
+}
+
void QuartcSession::OnTransportCanWrite() {
connection()->writer()->SetWritable();
if (HasDataToWrite()) {
@@ -319,7 +324,7 @@ void QuartcSession::SetServerCryptoConfig(
}
QuicStream* QuartcSession::CreateIncomingDynamicStream(QuicStreamId id) {
- return ActivateDataStream(CreateDataStream(id, kDefaultPriority));
+ return ActivateDataStream(CreateDataStream(id, QuicStream::kDefaultPriority));
}
std::unique_ptr<QuartcStream> QuartcSession::CreateDataStream(
@@ -334,7 +339,12 @@ std::unique_ptr<QuartcStream> QuartcSession::CreateDataStream(
// Register the stream to the QuicWriteBlockedList. |priority| is clamped
// between 0 and 7, with 0 being the highest priority and 7 the lowest
// priority.
- write_blocked_streams()->RegisterStream(stream->id(), priority);
+ if (!register_streams_early()) {
+ write_blocked_streams()->RegisterStream(
+ stream->id(), /* is_static_stream= */ false, priority);
+ } else {
+ write_blocked_streams()->UpdateStreamPriority(stream->id(), priority);
+ }
if (IsIncomingStream(id)) {
DCHECK(session_delegate_);
diff --git a/chromium/net/quic/quartc/quartc_session.h b/chromium/net/quic/quartc/quartc_session.h
index a07bf22a8b2..5ead026632e 100644
--- a/chromium/net/quic/quartc/quartc_session.h
+++ b/chromium/net/quic/quartc/quartc_session.h
@@ -80,6 +80,8 @@ class QUIC_EXPORT_PRIVATE QuartcSession
void SetDelegate(QuartcSessionInterface::Delegate* session_delegate) override;
+ void SetSessionVisitor(QuartcSessionVisitor* debug_visitor) override;
+
void OnTransportCanWrite() override;
// Decrypts an incoming QUIC packet to a data stream.
diff --git a/chromium/net/quic/quartc/quartc_session_interface.h b/chromium/net/quic/quartc/quartc_session_interface.h
index 59233839d52..3ea50d980fd 100644
--- a/chromium/net/quic/quartc/quartc_session_interface.h
+++ b/chromium/net/quic/quartc/quartc_session_interface.h
@@ -14,6 +14,7 @@
#include "net/quic/core/quic_time.h"
#include "net/quic/core/quic_types.h"
#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/quartc/quartc_session_visitor_interface.h"
#include "net/quic/quartc/quartc_stream_interface.h"
namespace net {
@@ -130,6 +131,9 @@ class QUIC_EXPORT_PRIVATE QuartcSessionInterface {
// The |delegate| is not owned by QuartcSession.
virtual void SetDelegate(Delegate* delegate) = 0;
+
+ // Sets a visitor for the session.
+ virtual void SetSessionVisitor(QuartcSessionVisitor* debug_visitor) = 0;
};
} // namespace net
diff --git a/chromium/net/quic/quartc/quartc_session_test.cc b/chromium/net/quic/quartc/quartc_session_test.cc
index 6117233e92f..c49d710a230 100644
--- a/chromium/net/quic/quartc/quartc_session_test.cc
+++ b/chromium/net/quic/quartc/quartc_session_test.cc
@@ -10,6 +10,7 @@
#include "net/quic/core/tls_client_handshaker.h"
#include "net/quic/core/tls_server_handshaker.h"
#include "net/quic/platform/api/quic_ptr_util.h"
+#include "net/quic/platform/api/quic_test_mem_slice_vector.h"
#include "net/quic/quartc/quartc_factory.h"
#include "net/quic/quartc/quartc_factory_interface.h"
#include "net/quic/quartc/quartc_packet_writer.h"
@@ -351,7 +352,7 @@ class FakeQuartcStreamDelegate : public QuartcStreamInterface::Delegate {
void OnClose(QuartcStreamInterface* stream) override {}
- void OnCanWrite(QuartcStreamInterface* stream) override {}
+ void OnBufferChanged(QuartcStreamInterface* stream) override {}
string data() { return last_received_data_; }
@@ -531,9 +532,10 @@ class QuartcSessionTest : public ::testing::Test,
outgoing_stream->SetDelegate(server_peer_->stream_delegate());
// Send a test message from peer 1 to peer 2.
- const char kTestMessage[] = "Hello";
- outgoing_stream->Write(kTestMessage, strlen(kTestMessage),
- kDefaultWriteParam);
+ char kTestMessage[] = "Hello";
+ test::QuicTestMemSliceVector data(
+ {std::make_pair(kTestMessage, strlen(kTestMessage))});
+ outgoing_stream->Write(data.span(), kDefaultWriteParam);
RunTasks();
// Wait for peer 2 to receive messages.
@@ -546,8 +548,10 @@ class QuartcSessionTest : public ::testing::Test,
EXPECT_EQ(client_peer_->data(), kTestMessage);
// Send a test message from peer 2 to peer 1.
- const char kTestResponse[] = "Response";
- incoming->Write(kTestResponse, strlen(kTestResponse), kDefaultWriteParam);
+ char kTestResponse[] = "Response";
+ test::QuicTestMemSliceVector response(
+ {std::make_pair(kTestResponse, strlen(kTestResponse))});
+ incoming->Write(response.span(), kDefaultWriteParam);
RunTasks();
// Wait for peer 1 to receive messages.
ASSERT_TRUE(server_peer_->has_data());
diff --git a/chromium/net/quic/quartc/quartc_session_visitor_interface.h b/chromium/net/quic/quartc/quartc_session_visitor_interface.h
new file mode 100644
index 00000000000..48d4521ac3b
--- /dev/null
+++ b/chromium/net/quic/quartc/quartc_session_visitor_interface.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_QUARTC_QUARTC_SESSION_VISITOR_INTERFACE_H_
+#define NET_QUIC_QUARTC_QUARTC_SESSION_VISITOR_INTERFACE_H_
+
+#include "net/quic/core/quic_connection.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+class QUIC_EXPORT_PRIVATE QuartcSessionVisitor {
+ public:
+ virtual ~QuartcSessionVisitor() {}
+
+ // Sets the |QuicConnection| for this debug visitor. Called before
+ // |GetConnectionVisitor|.
+ virtual void SetQuicConnection(QuicConnection* connection) = 0;
+
+ // Gets the |QuicConnectionDebugVisitor| associated with this Quartc visitor.
+ virtual QuicConnectionDebugVisitor* GetConnectionVisitor() const = 0;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_QUARTC_QUARTC_SESSION_VISITOR_INTERFACE_H_
diff --git a/chromium/net/quic/quartc/quartc_stream.cc b/chromium/net/quic/quartc/quartc_stream.cc
index 8aa818edb5a..adf936847a3 100644
--- a/chromium/net/quic/quartc/quartc_stream.cc
+++ b/chromium/net/quic/quartc/quartc_stream.cc
@@ -9,7 +9,7 @@
namespace net {
QuartcStream::QuartcStream(QuicStreamId id, QuicSession* session)
- : QuicStream(id, session) {}
+ : QuicStream(id, session, /*is_static=*/false) {}
QuartcStream::~QuartcStream() {}
void QuartcStream::OnDataAvailable() {
@@ -35,22 +35,27 @@ void QuartcStream::OnClose() {
delegate_->OnClose(this);
}
-void QuartcStream::OnCanWrite() {
- QuicStream::OnCanWrite();
+void QuartcStream::OnStreamDataConsumed(size_t bytes_consumed) {
+ QuicStream::OnStreamDataConsumed(bytes_consumed);
+
DCHECK(delegate_);
- // Don't call the delegate if the write-side is closed or a fin is buffered.
- // It is already done with this stream.
- if (!write_side_closed() && !fin_buffered()) {
- delegate_->OnCanWrite(this);
- }
+ delegate_->OnBufferChanged(this);
+}
+
+void QuartcStream::OnDataBuffered(
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ const QuicReferenceCountedPointer<QuicAckListenerInterface>& ack_listener) {
+ DCHECK(delegate_);
+ delegate_->OnBufferChanged(this);
}
uint32_t QuartcStream::stream_id() {
return id();
}
-uint64_t QuartcStream::bytes_written() {
- return stream_bytes_written();
+uint64_t QuartcStream::bytes_buffered() {
+ return BufferedDataBytes();
}
bool QuartcStream::fin_sent() {
@@ -61,15 +66,8 @@ int QuartcStream::stream_error() {
return QuicStream::stream_error();
}
-int QuartcStream::connection_error() {
- return QuicStream::connection_error();
-}
-
-void QuartcStream::Write(const char* data,
- size_t size,
- const WriteParameters& param) {
- struct iovec iov = {const_cast<char*>(data), size};
- WritevData(&iov, 1, param.fin);
+void QuartcStream::Write(QuicMemSliceSpan data, const WriteParameters& param) {
+ WriteMemSlices(data, param.fin);
}
void QuartcStream::FinishWriting() {
diff --git a/chromium/net/quic/quartc/quartc_stream.h b/chromium/net/quic/quartc/quartc_stream.h
index 8b7a777fa89..a33a176b7d2 100644
--- a/chromium/net/quic/quartc/quartc_stream.h
+++ b/chromium/net/quic/quartc/quartc_stream.h
@@ -25,22 +25,24 @@ class QUIC_EXPORT_PRIVATE QuartcStream : public QuicStream,
void OnClose() override;
- void OnCanWrite() override;
+ void OnStreamDataConsumed(size_t bytes_consumed) override;
+
+ void OnDataBuffered(
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ const QuicReferenceCountedPointer<QuicAckListenerInterface>& ack_listener)
+ override;
// QuartcStreamInterface overrides.
uint32_t stream_id() override;
- uint64_t bytes_written() override;
+ uint64_t bytes_buffered() override;
bool fin_sent() override;
int stream_error() override;
- int connection_error() override;
-
- void Write(const char* data,
- size_t size,
- const WriteParameters& param) override;
+ void Write(QuicMemSliceSpan data, const WriteParameters& param) override;
void FinishWriting() override;
diff --git a/chromium/net/quic/quartc/quartc_stream_interface.h b/chromium/net/quic/quartc/quartc_stream_interface.h
index 304190aa662..cae57f69c44 100644
--- a/chromium/net/quic/quartc/quartc_stream_interface.h
+++ b/chromium/net/quic/quartc/quartc_stream_interface.h
@@ -9,6 +9,7 @@
#include <stdint.h>
#include "net/quic/platform/api/quic_export.h"
+#include "net/quic/platform/api/quic_mem_slice_span.h"
namespace net {
@@ -23,8 +24,8 @@ class QUIC_EXPORT_PRIVATE QuartcStreamInterface {
// The QUIC stream ID.
virtual uint32_t stream_id() = 0;
- // The amount of data sent on this stream.
- virtual uint64_t bytes_written() = 0;
+ // The amount of data buffered on this stream.
+ virtual uint64_t bytes_buffered() = 0;
// Return true if the FIN has been sent. Used by the outgoing streams to
// determine if all the data has been sent
@@ -32,21 +33,16 @@ class QUIC_EXPORT_PRIVATE QuartcStreamInterface {
virtual int stream_error() = 0;
- virtual int connection_error() = 0;
-
struct WriteParameters {
- WriteParameters() : fin(false) {}
// |fin| is set to be true when there is no more data need to be send
// through a particular stream. The receiving side will used it to determine
// if the sender finish sending data.
- bool fin;
+ bool fin = false;
};
// Sends data reliably and in-order. Returns the amount sent.
// Does not buffer data.
- virtual void Write(const char* data,
- size_t size,
- const WriteParameters& param) = 0;
+ virtual void Write(QuicMemSliceSpan data, const WriteParameters& param) = 0;
// Marks this stream as finished writing. Asynchronously sends a FIN and
// closes the write-side. The stream will no longer call OnCanWrite().
@@ -83,8 +79,8 @@ class QUIC_EXPORT_PRIVATE QuartcStreamInterface {
// error code.
virtual void OnClose(QuartcStreamInterface* stream) = 0;
- // Called when more data may be written to a stream.
- virtual void OnCanWrite(QuartcStreamInterface* stream) = 0;
+ // Called when the contents of the stream's buffer changes.
+ virtual void OnBufferChanged(QuartcStreamInterface* stream) = 0;
};
// The |delegate| is not owned by QuartcStream.
diff --git a/chromium/net/quic/quartc/quartc_stream_test.cc b/chromium/net/quic/quartc/quartc_stream_test.cc
index 27065ada2d8..5ab681beb43 100644
--- a/chromium/net/quic/quartc/quartc_stream_test.cc
+++ b/chromium/net/quic/quartc/quartc_stream_test.cc
@@ -9,6 +9,7 @@
#include "net/quic/core/quic_session.h"
#include "net/quic/core/quic_simple_buffer_allocator.h"
#include "net/quic/platform/api/quic_ptr_util.h"
+#include "net/quic/platform/api/quic_test_mem_slice_vector.h"
#include "net/quic/quartc/quartc_clock_interface.h"
#include "net/quic/quartc/quartc_factory.h"
#include "net/quic/test_tools/mock_clock.h"
@@ -20,7 +21,6 @@ namespace net {
namespace {
-static const SpdyPriority kDefaultPriority = 3;
static const QuicStreamId kStreamId = 5;
static const QuartcStreamInterface::WriteParameters kDefaultParam;
@@ -78,7 +78,9 @@ class MockQuicSession : public QuicSession {
// Tracks whether the stream is write blocked and its priority.
void RegisterReliableStream(QuicStreamId stream_id, SpdyPriority priority) {
- write_blocked_streams()->RegisterStream(stream_id, priority);
+ write_blocked_streams()->RegisterStream(stream_id,
+ /*is_static_stream=*/false,
+ priority);
}
// The session take ownership of the stream.
@@ -125,8 +127,8 @@ class MockQuartcStreamDelegate : public QuartcStreamInterface::Delegate {
MockQuartcStreamDelegate(int id, std::string* read_buffer)
: id_(id), read_buffer_(read_buffer) {}
- void OnCanWrite(QuartcStreamInterface* stream) override {
- ++on_can_write_callbacks_;
+ void OnBufferChanged(QuartcStreamInterface* stream) override {
+ last_bytes_buffered_ = stream->bytes_buffered();
}
void OnReceived(QuartcStreamInterface* stream,
@@ -140,7 +142,7 @@ class MockQuartcStreamDelegate : public QuartcStreamInterface::Delegate {
bool closed() { return closed_; }
- int32_t on_can_write_callbacks() { return on_can_write_callbacks_; }
+ uint64_t last_bytes_buffered() { return last_bytes_buffered_; }
protected:
uint32_t id_;
@@ -148,8 +150,9 @@ class MockQuartcStreamDelegate : public QuartcStreamInterface::Delegate {
std::string* read_buffer_;
// Whether the QuicStream is closed.
bool closed_ = false;
- // How many times OnCanWrite has been called.
- int32_t on_can_write_callbacks_ = 0;
+
+ // Last amount of data observed as buffered.
+ uint64_t last_bytes_buffered_ = 0;
};
class QuartcStreamTest : public ::testing::Test,
@@ -177,7 +180,10 @@ class QuartcStreamTest : public ::testing::Test,
QuicMakeUnique<MockQuartcStreamDelegate>(kStreamId, &read_buffer_);
stream_ = new QuartcStream(kStreamId, session_.get());
stream_->SetDelegate(mock_stream_delegate_.get());
- session_->RegisterReliableStream(stream_->stream_id(), kDefaultPriority);
+ if (!session_->register_streams_early()) {
+ session_->RegisterReliableStream(stream_->stream_id(),
+ QuicStream::kDefaultPriority);
+ }
session_->ActivateReliableStream(std::unique_ptr<QuartcStream>(stream_));
}
@@ -212,42 +218,67 @@ class QuartcStreamTest : public ::testing::Test,
// Write an entire string.
TEST_F(QuartcStreamTest, WriteDataWhole) {
CreateReliableQuicStream();
- stream_->Write("Foo bar", 7, kDefaultParam);
+ char message[] = "Foo bar";
+ test::QuicTestMemSliceVector data({std::make_pair(message, 7)});
+ stream_->Write(data.span(), kDefaultParam);
EXPECT_EQ("Foo bar", write_buffer_);
}
// Write part of a string.
TEST_F(QuartcStreamTest, WriteDataPartial) {
CreateReliableQuicStream();
- stream_->Write("Foo bar", 5, kDefaultParam);
+ char message[] = "Foo bar";
+ test::QuicTestMemSliceVector data({std::make_pair(message, 5)});
+ stream_->Write(data.span(), kDefaultParam);
EXPECT_EQ("Foo b", write_buffer_);
}
-// Test that strings are not buffered.
-TEST_F(QuartcStreamTest, NoBuffer) {
+// Test that a QuartcStream buffers writes correctly.
+TEST_F(QuartcStreamTest, StreamBuffersData) {
CreateReliableQuicStream();
+ char message[] = "Foo bar";
+ test::QuicTestMemSliceVector data({std::make_pair(message, 7)});
+
+ // The stream is not yet writable, so data will be buffered.
session_->set_writable(false);
- stream_->Write("Foo bar", 7, kDefaultParam);
- // The data will not be buffered.
+ stream_->Write(data.span(), kDefaultParam);
+
+ // Check that data is buffered.
+ EXPECT_TRUE(stream_->HasBufferedData());
+ EXPECT_EQ(7u, stream_->bytes_buffered());
+
+ // Check that the stream told its delegate about the buffer change.
+ EXPECT_EQ(7u, mock_stream_delegate_->last_bytes_buffered());
+
+ // Check that none of the data was written yet.
+ // Note that |write_buffer_| actually holds data written by the QuicSession
+ // (not data buffered by the stream).
EXPECT_EQ(0ul, write_buffer_.size());
+
+ char message1[] = "xyzzy";
+ test::QuicTestMemSliceVector data1({std::make_pair(message1, 5)});
+
+ // More writes go into the buffer.
+ stream_->Write(data1.span(), kDefaultParam);
+
EXPECT_TRUE(stream_->HasBufferedData());
- EXPECT_EQ(0u, stream_->bytes_written());
- // The stream is writable, but there's nothing to send.
+ EXPECT_EQ(12u, stream_->bytes_buffered());
+ EXPECT_EQ(12u, mock_stream_delegate_->last_bytes_buffered());
+ EXPECT_EQ(0ul, write_buffer_.size());
+
+ // The stream becomes writable, so it sends the buffered data.
session_->set_writable(true);
stream_->OnCanWrite();
- EXPECT_EQ(7u, stream_->bytes_written());
- EXPECT_EQ(7ul, write_buffer_.size());
- EXPECT_FALSE(stream_->HasBufferedData());
- stream_->Write("xyzzy", 5, kDefaultParam);
+ EXPECT_FALSE(stream_->HasBufferedData());
+ EXPECT_EQ(0u, stream_->bytes_buffered());
+ EXPECT_EQ(0u, mock_stream_delegate_->last_bytes_buffered());
EXPECT_EQ("Foo barxyzzy", write_buffer_);
- EXPECT_EQ(12u, stream_->bytes_written());
}
// Finish writing to a stream.
-// The stream no longer calls OnCanWrite(). It delivers the fin bit and closes
-// the write-side as soon as possible.
+// It delivers the fin bit and closes the write-side as soon as possible.
TEST_F(QuartcStreamTest, FinishWriting) {
CreateReliableQuicStream();
@@ -255,16 +286,11 @@ TEST_F(QuartcStreamTest, FinishWriting) {
stream_->FinishWriting();
EXPECT_FALSE(stream_->fin_sent());
- // Fin is buffered, no callback to OnCanWrite.
- stream_->OnCanWrite();
- EXPECT_EQ(0, mock_stream_delegate_->on_can_write_callbacks());
- EXPECT_FALSE(stream_->fin_sent());
-
- // Fin is sent, no callback to OnCanWrite.
+ // Fin is sent as soon as the stream becomes writable.
session_->set_writable(true);
stream_->OnCanWrite();
- EXPECT_EQ(0, mock_stream_delegate_->on_can_write_callbacks());
EXPECT_TRUE(stream_->fin_sent());
+ EXPECT_TRUE(stream_->write_side_closed());
}
// Read an entire string.
@@ -319,7 +345,8 @@ TEST_F(QuartcStreamTest, CloseOnFins) {
QuartcStreamInterface::WriteParameters param;
param.fin = true;
- stream_->Write(nullptr, 0, param);
+ test::QuicTestMemSliceVector data({});
+ stream_->Write(data.span(), param);
// Check that the OnClose() callback occurred.
EXPECT_TRUE(mock_stream_delegate_->closed());
diff --git a/chromium/net/quic/test_tools/crypto_test_utils.cc b/chromium/net/quic/test_tools/crypto_test_utils.cc
index d2e4147b5e1..e451532f08e 100644
--- a/chromium/net/quic/test_tools/crypto_test_utils.cc
+++ b/chromium/net/quic/test_tools/crypto_test_utils.cc
@@ -623,7 +623,7 @@ uint64_t LeafCertHashForTesting() {
class MockCommonCertSets : public CommonCertSets {
public:
MockCommonCertSets(QuicStringPiece cert, uint64_t hash, uint32_t index)
- : cert_(cert.as_string()), hash_(hash), index_(index) {}
+ : cert_(cert), hash_(hash), index_(index) {}
QuicStringPiece GetCommonHashes() const override {
QUIC_BUG << "not implemented";
@@ -901,7 +901,7 @@ CryptoHandshakeMessage CreateCHLO(
CryptoFramer::ConstructHandshakeMessage(msg, Perspective::IS_CLIENT));
std::unique_ptr<CryptoHandshakeMessage> parsed(CryptoFramer::ParseMessage(
bytes->AsStringPiece(), Perspective::IS_CLIENT));
- CHECK(parsed.get());
+ CHECK(parsed);
return *parsed;
}
@@ -916,6 +916,13 @@ void MovePacketsForTlsHandshake(PacketSavingConnection* source_conn,
PacketSavingConnection* dest_conn,
Perspective dest_perspective) {
SimpleQuicFramer framer(source_conn->supported_versions(), dest_perspective);
+ std::vector<std::unique_ptr<QuicStreamFrame>> stream_frames;
+ std::vector<std::vector<char>> buffers;
+
+ QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
+
+ SimpleQuicFramer null_encryption_framer(source_conn->supported_versions(),
+ dest_perspective);
size_t index = *inout_packet_index;
for (; index < source_conn->encrypted_packets_.size(); index++) {
if (!framer.ProcessPacket(*source_conn->encrypted_packets_[index])) {
@@ -923,12 +930,37 @@ void MovePacketsForTlsHandshake(PacketSavingConnection* source_conn,
// the handshake is complete. Don't treat them as handshake packets.
break;
}
+ // Try to process the packet with a framer that only has the NullDecrypter
+ // for decryption. If ProcessPacket succeeds, that means the packet was
+ // encrypted with the NullEncrypter. With the TLS handshaker in use, no
+ // packets should ever be encrypted with the NullEncrypter, instead they're
+ // encrypted with an obfuscation cipher based on QUIC version and connection
+ // ID.
+ ASSERT_FALSE(null_encryption_framer.ProcessPacket(
+ *source_conn->encrypted_packets_[index]))
+ << "No TLS packets should be encrypted with the NullEncrypter";
for (const auto& stream_frame : framer.stream_frames()) {
- dest_conn->OnStreamFrame(*stream_frame);
+ // The stream frames from SimpleQuicFramer::stream_frames() are only valid
+ // until the next call to ProcessPacket. This copies the stream frames to
+ // |stream_frames|, including making a copy of the data buffer, since a
+ // QuicStreamFrame does not own the data it points to.
+ std::vector<char> buffer(stream_frame->data_length);
+ memcpy(buffer.data(), stream_frame->data_buffer,
+ stream_frame->data_length);
+ auto frame = QuicMakeUnique<QuicStreamFrame>(
+ stream_frame->stream_id, stream_frame->fin, stream_frame->offset,
+ QuicStringPiece(buffer.data(), buffer.size()));
+ stream_frames.push_back(std::move(frame));
+ buffers.push_back(std::move(buffer));
}
}
*inout_packet_index = index;
+ QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
+
+ for (const auto& stream_frame : stream_frames) {
+ dest_conn->OnStreamFrame(*stream_frame);
+ }
}
void MovePackets(PacketSavingConnection* source_conn,
diff --git a/chromium/net/quic/test_tools/mock_crypto_client_stream.cc b/chromium/net/quic/test_tools/mock_crypto_client_stream.cc
index 2ccd8f06eb6..d0ecd118e60 100644
--- a/chromium/net/quic/test_tools/mock_crypto_client_stream.cc
+++ b/chromium/net/quic/test_tools/mock_crypto_client_stream.cc
@@ -9,6 +9,7 @@
#include "net/quic/core/crypto/quic_decrypter.h"
#include "net/quic/core/crypto/quic_encrypter.h"
#include "net/quic/core/quic_spdy_client_session_base.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
#include "net/quic/test_tools/mock_decrypter.h"
#include "net/quic/test_tools/mock_encrypter.h"
#include "net/quic/test_tools/quic_config_peer.h"
@@ -77,14 +78,18 @@ bool MockCryptoClientStream::CryptoConnect() {
}
if (use_mock_crypter_) {
session()->connection()->SetDecrypter(
- ENCRYPTION_INITIAL, new MockDecrypter(Perspective::IS_CLIENT));
+ ENCRYPTION_INITIAL,
+ QuicMakeUnique<MockDecrypter>(Perspective::IS_CLIENT));
session()->connection()->SetEncrypter(
- ENCRYPTION_INITIAL, new MockEncrypter(Perspective::IS_CLIENT));
+ ENCRYPTION_INITIAL,
+ QuicMakeUnique<MockEncrypter>(Perspective::IS_CLIENT));
} else {
session()->connection()->SetDecrypter(
- ENCRYPTION_INITIAL, new NullDecrypter(Perspective::IS_CLIENT));
+ ENCRYPTION_INITIAL,
+ QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT));
session()->connection()->SetEncrypter(
- ENCRYPTION_INITIAL, new NullEncrypter(Perspective::IS_CLIENT));
+ ENCRYPTION_INITIAL,
+ QuicMakeUnique<NullEncrypter>(Perspective::IS_CLIENT));
}
session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
session()->OnCryptoHandshakeEvent(
@@ -105,17 +110,17 @@ bool MockCryptoClientStream::CryptoConnect() {
if (use_mock_crypter_) {
session()->connection()->SetDecrypter(
ENCRYPTION_FORWARD_SECURE,
- new MockDecrypter(Perspective::IS_CLIENT));
+ QuicMakeUnique<MockDecrypter>(Perspective::IS_CLIENT));
session()->connection()->SetEncrypter(
ENCRYPTION_FORWARD_SECURE,
- new MockEncrypter(Perspective::IS_CLIENT));
+ QuicMakeUnique<MockEncrypter>(Perspective::IS_CLIENT));
} else {
session()->connection()->SetDecrypter(
ENCRYPTION_FORWARD_SECURE,
- new NullDecrypter(Perspective::IS_CLIENT));
+ QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT));
session()->connection()->SetEncrypter(
ENCRYPTION_FORWARD_SECURE,
- new NullEncrypter(Perspective::IS_CLIENT));
+ QuicMakeUnique<NullEncrypter>(Perspective::IS_CLIENT));
}
session()->connection()->SetDefaultEncryptionLevel(
ENCRYPTION_FORWARD_SECURE);
@@ -163,14 +168,18 @@ void MockCryptoClientStream::SendOnCryptoHandshakeEvent(
SetConfigNegotiated();
if (use_mock_crypter_) {
session()->connection()->SetDecrypter(
- ENCRYPTION_FORWARD_SECURE, new MockDecrypter(Perspective::IS_CLIENT));
+ ENCRYPTION_FORWARD_SECURE,
+ QuicMakeUnique<MockDecrypter>(Perspective::IS_CLIENT));
session()->connection()->SetEncrypter(
- ENCRYPTION_FORWARD_SECURE, new MockEncrypter(Perspective::IS_CLIENT));
+ ENCRYPTION_FORWARD_SECURE,
+ QuicMakeUnique<MockEncrypter>(Perspective::IS_CLIENT));
} else {
session()->connection()->SetDecrypter(
- ENCRYPTION_FORWARD_SECURE, new NullDecrypter(Perspective::IS_CLIENT));
+ ENCRYPTION_FORWARD_SECURE,
+ QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT));
session()->connection()->SetEncrypter(
- ENCRYPTION_FORWARD_SECURE, new NullEncrypter(Perspective::IS_CLIENT));
+ ENCRYPTION_FORWARD_SECURE,
+ QuicMakeUnique<NullEncrypter>(Perspective::IS_CLIENT));
}
session()->connection()->SetDefaultEncryptionLevel(
ENCRYPTION_FORWARD_SECURE);
diff --git a/chromium/net/quic/test_tools/quic_config_peer.cc b/chromium/net/quic/test_tools/quic_config_peer.cc
index 7fa9db79013..749efbbb817 100644
--- a/chromium/net/quic/test_tools/quic_config_peer.cc
+++ b/chromium/net/quic/test_tools/quic_config_peer.cc
@@ -10,13 +10,6 @@ namespace net {
namespace test {
// static
-void QuicConfigPeer::SetReceivedSocketReceiveBuffer(
- QuicConfig* config,
- uint32_t receive_buffer_bytes) {
- config->socket_receive_buffer_.SetReceivedValue(receive_buffer_bytes);
-}
-
-// static
void QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(
QuicConfig* config,
uint32_t window_bytes) {
@@ -64,5 +57,11 @@ void QuicConfigPeer::SetConnectionOptionsToSend(QuicConfig* config,
config->SetConnectionOptionsToSend(options);
}
+// static
+void QuicConfigPeer::SetReceivedStatelessResetToken(QuicConfig* config,
+ uint128 token) {
+ config->stateless_reset_token_.SetReceivedValue(token);
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/test_tools/quic_config_peer.h b/chromium/net/quic/test_tools/quic_config_peer.h
index 9af9341add0..ece91bf7bbf 100644
--- a/chromium/net/quic/test_tools/quic_config_peer.h
+++ b/chromium/net/quic/test_tools/quic_config_peer.h
@@ -8,6 +8,7 @@
#include "base/macros.h"
#include "net/quic/core/quic_config.h"
#include "net/quic/core/quic_packets.h"
+#include "net/quic/platform/api/quic_uint128.h"
namespace net {
@@ -17,9 +18,6 @@ namespace test {
class QuicConfigPeer {
public:
- static void SetReceivedSocketReceiveBuffer(QuicConfig* config,
- uint32_t receive_buffer_bytes);
-
static void SetReceivedInitialStreamFlowControlWindow(QuicConfig* config,
uint32_t window_bytes);
@@ -40,6 +38,8 @@ class QuicConfigPeer {
static void SetConnectionOptionsToSend(QuicConfig* config,
const QuicTagVector& options);
+ static void SetReceivedStatelessResetToken(QuicConfig* config, uint128 token);
+
private:
DISALLOW_COPY_AND_ASSIGN(QuicConfigPeer);
};
diff --git a/chromium/net/quic/test_tools/quic_connection_peer.cc b/chromium/net/quic/test_tools/quic_connection_peer.cc
index d5c1ae6ca23..11e4227e493 100644
--- a/chromium/net/quic/test_tools/quic_connection_peer.cc
+++ b/chromium/net/quic/test_tools/quic_connection_peer.cc
@@ -98,6 +98,20 @@ void QuicConnectionPeer::SetPeerAddress(QuicConnection* connection,
}
// static
+void QuicConnectionPeer::SetDirectPeerAddress(
+ QuicConnection* connection,
+ const QuicSocketAddress& direct_peer_address) {
+ connection->direct_peer_address_ = direct_peer_address;
+}
+
+// static
+void QuicConnectionPeer::SetEffectivePeerAddress(
+ QuicConnection* connection,
+ const QuicSocketAddress& effective_peer_address) {
+ connection->effective_peer_address_ = effective_peer_address;
+}
+
+// static
bool QuicConnectionPeer::IsSilentCloseEnabled(QuicConnection* connection) {
return connection->idle_timeout_connection_close_behavior_ ==
ConnectionCloseBehavior::SILENT_CLOSE;
@@ -172,6 +186,18 @@ QuicAlarm* QuicConnectionPeer::GetMtuDiscoveryAlarm(
}
// static
+QuicAlarm* QuicConnectionPeer::GetRetransmittableOnWireAlarm(
+ QuicConnection* connection) {
+ return connection->retransmittable_on_wire_alarm_.get();
+}
+
+// static
+QuicAlarm* QuicConnectionPeer::GetPathDegradingAlarm(
+ QuicConnection* connection) {
+ return connection->path_degrading_alarm_.get();
+}
+
+// static
QuicPacketWriter* QuicConnectionPeer::GetWriter(QuicConnection* connection) {
return connection->writer_;
}
diff --git a/chromium/net/quic/test_tools/quic_connection_peer.h b/chromium/net/quic/test_tools/quic_connection_peer.h
index efcee9eb414..d67cb753b57 100644
--- a/chromium/net/quic/test_tools/quic_connection_peer.h
+++ b/chromium/net/quic/test_tools/quic_connection_peer.h
@@ -64,6 +64,14 @@ class QuicConnectionPeer {
static void SetPeerAddress(QuicConnection* connection,
const QuicSocketAddress& peer_address);
+ static void SetDirectPeerAddress(
+ QuicConnection* connection,
+ const QuicSocketAddress& direct_peer_address);
+
+ static void SetEffectivePeerAddress(
+ QuicConnection* connection,
+ const QuicSocketAddress& effective_peer_address);
+
static bool IsSilentCloseEnabled(QuicConnection* connection);
static void SwapCrypters(QuicConnection* connection, QuicFramer* framer);
@@ -84,6 +92,8 @@ class QuicConnectionPeer {
static QuicAlarm* GetSendAlarm(QuicConnection* connection);
static QuicAlarm* GetTimeoutAlarm(QuicConnection* connection);
static QuicAlarm* GetMtuDiscoveryAlarm(QuicConnection* connection);
+ static QuicAlarm* GetRetransmittableOnWireAlarm(QuicConnection* connection);
+ static QuicAlarm* GetPathDegradingAlarm(QuicConnection* connection);
static QuicPacketWriter* GetWriter(QuicConnection* connection);
// If |owns_writer| is true, takes ownership of |writer|.
diff --git a/chromium/net/quic/test_tools/quic_framer_peer.cc b/chromium/net/quic/test_tools/quic_framer_peer.cc
index e9d65f42678..37c91f6bbda 100644
--- a/chromium/net/quic/test_tools/quic_framer_peer.cc
+++ b/chromium/net/quic/test_tools/quic_framer_peer.cc
@@ -49,6 +49,7 @@ bool QuicFramerPeer::ProcessIetfStreamFrame(QuicFramer* framer,
QuicStreamFrame* frame) {
return framer->ProcessIetfStreamFrame(reader, frame_type, frame);
}
+
// static
bool QuicFramerPeer::AppendIetfStreamFrame(QuicFramer* framer,
const QuicStreamFrame& frame,
@@ -56,6 +57,7 @@ bool QuicFramerPeer::AppendIetfStreamFrame(QuicFramer* framer,
QuicDataWriter* writer) {
return framer->AppendIetfStreamFrame(frame, last_frame_in_packet, writer);
}
+
// static
bool QuicFramerPeer::ProcessIetfAckFrame(QuicFramer* framer,
QuicDataReader* reader,
@@ -63,11 +65,12 @@ bool QuicFramerPeer::ProcessIetfAckFrame(QuicFramer* framer,
QuicAckFrame* ack_frame) {
return framer->ProcessIetfAckFrame(reader, frame_type, ack_frame);
}
+
// static
-bool QuicFramerPeer::AppendIetfAckFrameAndTypeByte(QuicFramer* framer,
- const QuicAckFrame& frame,
- QuicDataWriter* writer) {
- return framer->AppendIetfAckFrameAndTypeByte(frame, writer);
+bool QuicFramerPeer::AppendIetfAckFrame(QuicFramer* framer,
+ const QuicAckFrame& frame,
+ QuicDataWriter* writer) {
+ return framer->AppendIetfAckFrame(frame, writer);
}
// static
@@ -77,14 +80,7 @@ bool QuicFramerPeer::AppendIetfConnectionCloseFrame(
QuicDataWriter* writer) {
return framer->AppendIetfConnectionCloseFrame(frame, writer);
}
-// static
-bool QuicFramerPeer::AppendIetfConnectionCloseFrame(
- QuicFramer* framer,
- const QuicIetfTransportErrorCodes code,
- const string& phrase,
- QuicDataWriter* writer) {
- return framer->AppendIetfConnectionCloseFrame(code, phrase, writer);
-}
+
// static
bool QuicFramerPeer::AppendIetfApplicationCloseFrame(
QuicFramer* framer,
@@ -92,13 +88,7 @@ bool QuicFramerPeer::AppendIetfApplicationCloseFrame(
QuicDataWriter* writer) {
return framer->AppendIetfApplicationCloseFrame(frame, writer);
}
-// static
-bool QuicFramerPeer::AppendIetfApplicationCloseFrame(QuicFramer* framer,
- const uint16_t code,
- const string& phrase,
- QuicDataWriter* writer) {
- return framer->AppendIetfApplicationCloseFrame(code, phrase, writer);
-}
+
// static
bool QuicFramerPeer::ProcessIetfConnectionCloseFrame(
QuicFramer* framer,
@@ -107,6 +97,7 @@ bool QuicFramerPeer::ProcessIetfConnectionCloseFrame(
QuicConnectionCloseFrame* frame) {
return framer->ProcessIetfConnectionCloseFrame(reader, frame_type, frame);
}
+
// static
bool QuicFramerPeer::ProcessIetfApplicationCloseFrame(
QuicFramer* framer,
@@ -117,6 +108,176 @@ bool QuicFramerPeer::ProcessIetfApplicationCloseFrame(
}
// static
+bool QuicFramerPeer::AppendIetfPaddingFrame(QuicFramer* framer,
+ const QuicPaddingFrame& frame,
+ QuicDataWriter* writer) {
+ return framer->AppendIetfPaddingFrame(frame, writer);
+}
+
+// static
+void QuicFramerPeer::ProcessIetfPaddingFrame(QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicPaddingFrame* frame) {
+ framer->ProcessIetfPaddingFrame(reader, frame);
+}
+
+// static
+bool QuicFramerPeer::ProcessIetfPathChallengeFrame(
+ QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicPathChallengeFrame* frame) {
+ return framer->ProcessIetfPathChallengeFrame(reader, frame);
+}
+
+// static
+bool QuicFramerPeer::ProcessIetfPathResponseFrame(
+ QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicPathResponseFrame* frame) {
+ return framer->ProcessIetfPathResponseFrame(reader, frame);
+}
+
+// static
+bool QuicFramerPeer::AppendIetfPathChallengeFrame(
+ QuicFramer* framer,
+ const QuicPathChallengeFrame& frame,
+ QuicDataWriter* writer) {
+ return framer->AppendIetfPathChallengeFrame(frame, writer);
+}
+
+// static
+bool QuicFramerPeer::AppendIetfPathResponseFrame(
+ QuicFramer* framer,
+ const QuicPathResponseFrame& frame,
+ QuicDataWriter* writer) {
+ return framer->AppendIetfPathResponseFrame(frame, writer);
+}
+
+// static
+bool QuicFramerPeer::AppendIetfResetStreamFrame(QuicFramer* framer,
+ const QuicRstStreamFrame& frame,
+ QuicDataWriter* writer) {
+ return framer->AppendIetfResetStreamFrame(frame, writer);
+}
+
+// static
+bool QuicFramerPeer::ProcessIetfResetStreamFrame(QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicRstStreamFrame* frame) {
+ return framer->ProcessIetfResetStreamFrame(reader, frame);
+}
+
+// static
+bool QuicFramerPeer::ProcessIetfStopSendingFrame(
+ QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicStopSendingFrame* stop_sending_frame) {
+ return framer->ProcessIetfStopSendingFrame(reader, stop_sending_frame);
+}
+
+// static
+bool QuicFramerPeer::AppendIetfStopSendingFrame(
+ QuicFramer* framer,
+ const QuicStopSendingFrame& stop_sending_frame,
+ QuicDataWriter* writer) {
+ return framer->AppendIetfStopSendingFrame(stop_sending_frame, writer);
+}
+
+// Append/consume IETF-Format MAX_DATA and MAX_STREAM_DATA frames
+// static
+// static
+bool QuicFramerPeer::AppendIetfMaxDataFrame(QuicFramer* framer,
+ const QuicWindowUpdateFrame& frame,
+ QuicDataWriter* writer) {
+ return framer->AppendIetfMaxDataFrame(frame, writer);
+}
+
+// static
+bool QuicFramerPeer::AppendIetfMaxStreamDataFrame(
+ QuicFramer* framer,
+ const QuicWindowUpdateFrame& frame,
+ QuicDataWriter* writer) {
+ return framer->AppendIetfMaxStreamDataFrame(frame, writer);
+}
+
+// static
+bool QuicFramerPeer::ProcessIetfMaxDataFrame(QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicWindowUpdateFrame* frame) {
+ return framer->ProcessIetfMaxDataFrame(reader, frame);
+}
+
+// static
+bool QuicFramerPeer::ProcessIetfMaxStreamDataFrame(
+ QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicWindowUpdateFrame* frame) {
+ return framer->ProcessIetfMaxStreamDataFrame(reader, frame);
+}
+
+// static
+bool QuicFramerPeer::AppendIetfMaxStreamIdFrame(
+ QuicFramer* framer,
+ const QuicIetfMaxStreamIdFrame& frame,
+ QuicDataWriter* writer) {
+ return framer->AppendIetfMaxStreamIdFrame(frame, writer);
+}
+
+// static
+bool QuicFramerPeer::ProcessIetfMaxStreamIdFrame(
+ QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicIetfMaxStreamIdFrame* frame) {
+ return framer->ProcessIetfMaxStreamIdFrame(reader, frame);
+}
+
+// static
+bool QuicFramerPeer::AppendIetfBlockedFrame(QuicFramer* framer,
+ const QuicIetfBlockedFrame& frame,
+ QuicDataWriter* writer) {
+ return framer->AppendIetfBlockedFrame(frame, writer);
+}
+
+// static
+bool QuicFramerPeer::ProcessIetfBlockedFrame(QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicIetfBlockedFrame* frame) {
+ return framer->ProcessIetfBlockedFrame(reader, frame);
+}
+
+// static
+bool QuicFramerPeer::AppendIetfStreamBlockedFrame(
+ QuicFramer* framer,
+ const QuicWindowUpdateFrame& frame,
+ QuicDataWriter* writer) {
+ return framer->AppendIetfStreamBlockedFrame(frame, writer);
+}
+
+// static
+bool QuicFramerPeer::ProcessIetfStreamBlockedFrame(
+ QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicWindowUpdateFrame* frame) {
+ return framer->ProcessIetfStreamBlockedFrame(reader, frame);
+}
+
+// static
+bool QuicFramerPeer::AppendIetfStreamIdBlockedFrame(
+ QuicFramer* framer,
+ const QuicIetfStreamIdBlockedFrame& frame,
+ QuicDataWriter* writer) {
+ return framer->AppendIetfStreamIdBlockedFrame(frame, writer);
+}
+
+// static
+bool QuicFramerPeer::ProcessIetfStreamIdBlockedFrame(
+ QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicIetfStreamIdBlockedFrame* frame) {
+ return framer->ProcessIetfStreamIdBlockedFrame(reader, frame);
+}
+
+// static
void QuicFramerPeer::SwapCrypters(QuicFramer* framer1, QuicFramer* framer2) {
for (int i = ENCRYPTION_NONE; i < NUM_ENCRYPTION_LEVELS; i++) {
framer1->encrypter_[i].swap(framer2->encrypter_[i]);
diff --git a/chromium/net/quic/test_tools/quic_framer_peer.h b/chromium/net/quic/test_tools/quic_framer_peer.h
index de18e9e959f..a4372d2ab12 100644
--- a/chromium/net/quic/test_tools/quic_framer_peer.h
+++ b/chromium/net/quic/test_tools/quic_framer_peer.h
@@ -47,19 +47,10 @@ class QuicFramerPeer {
QuicFramer* framer,
const QuicConnectionCloseFrame& frame,
QuicDataWriter* writer);
- static bool AppendIetfConnectionCloseFrame(
- QuicFramer* framer,
- const QuicIetfTransportErrorCodes code,
- const std::string& phrase,
- QuicDataWriter* writer);
static bool AppendIetfApplicationCloseFrame(
QuicFramer* framer,
const QuicConnectionCloseFrame& frame,
QuicDataWriter* writer);
- static bool AppendIetfApplicationCloseFrame(QuicFramer* framer,
- const uint16_t code,
- const std::string& phrase,
- QuicDataWriter* writer);
static bool ProcessIetfConnectionCloseFrame(QuicFramer* framer,
QuicDataReader* reader,
const uint8_t frame_type,
@@ -68,14 +59,92 @@ class QuicFramerPeer {
QuicDataReader* reader,
const uint8_t frame_type,
QuicConnectionCloseFrame* frame);
-
static bool ProcessIetfAckFrame(QuicFramer* framer,
QuicDataReader* reader,
uint8_t frame_type,
QuicAckFrame* ack_frame);
- static bool AppendIetfAckFrameAndTypeByte(QuicFramer* framer,
- const QuicAckFrame& frame,
- QuicDataWriter* writer);
+ static bool AppendIetfAckFrame(QuicFramer* framer,
+ const QuicAckFrame& frame,
+ QuicDataWriter* writer);
+ static bool AppendIetfResetStreamFrame(QuicFramer* framer,
+ const QuicRstStreamFrame& frame,
+ QuicDataWriter* writer);
+ static bool ProcessIetfResetStreamFrame(QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicRstStreamFrame* frame);
+
+ // Add/remove IETF-Format padding.
+ static bool AppendIetfPaddingFrame(QuicFramer* framer,
+ const QuicPaddingFrame& frame,
+ QuicDataWriter* writer);
+ static void ProcessIetfPaddingFrame(QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicPaddingFrame* frame);
+
+ static bool ProcessIetfPathChallengeFrame(QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicPathChallengeFrame* frame);
+ static bool ProcessIetfPathResponseFrame(QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicPathResponseFrame* frame);
+
+ static bool AppendIetfPathChallengeFrame(QuicFramer* framer,
+ const QuicPathChallengeFrame& frame,
+ QuicDataWriter* writer);
+ static bool AppendIetfPathResponseFrame(QuicFramer* framer,
+ const QuicPathResponseFrame& frame,
+ QuicDataWriter* writer);
+
+ static bool ProcessIetfStopSendingFrame(
+ QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicStopSendingFrame* stop_sending_frame);
+ static bool AppendIetfStopSendingFrame(
+ QuicFramer* framer,
+ const QuicStopSendingFrame& stop_sending_frame,
+ QuicDataWriter* writer);
+
+ // Append/consume IETF-Format MAX_DATA and MAX_STREAM_DATA frames
+ static bool AppendIetfMaxDataFrame(QuicFramer* framer,
+ const QuicWindowUpdateFrame& frame,
+ QuicDataWriter* writer);
+ static bool AppendIetfMaxStreamDataFrame(QuicFramer* framer,
+ const QuicWindowUpdateFrame& frame,
+ QuicDataWriter* writer);
+ static bool ProcessIetfMaxDataFrame(QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicWindowUpdateFrame* frame);
+ static bool ProcessIetfMaxStreamDataFrame(QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicWindowUpdateFrame* frame);
+ static bool AppendIetfMaxStreamIdFrame(QuicFramer* framer,
+ const QuicIetfMaxStreamIdFrame& frame,
+ QuicDataWriter* writer);
+ static bool ProcessIetfMaxStreamIdFrame(QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicIetfMaxStreamIdFrame* frame);
+ static bool AppendIetfBlockedFrame(QuicFramer* framer,
+ const QuicIetfBlockedFrame& frame,
+ QuicDataWriter* writer);
+ static bool ProcessIetfBlockedFrame(QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicIetfBlockedFrame* frame);
+
+ static bool AppendIetfStreamBlockedFrame(QuicFramer* framer,
+ const QuicWindowUpdateFrame& frame,
+ QuicDataWriter* writer);
+ static bool ProcessIetfStreamBlockedFrame(QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicWindowUpdateFrame* frame);
+
+ static bool AppendIetfStreamIdBlockedFrame(
+ QuicFramer* framer,
+ const QuicIetfStreamIdBlockedFrame& frame,
+ QuicDataWriter* writer);
+ static bool ProcessIetfStreamIdBlockedFrame(
+ QuicFramer* framer,
+ QuicDataReader* reader,
+ QuicIetfStreamIdBlockedFrame* frame);
private:
DISALLOW_COPY_AND_ASSIGN(QuicFramerPeer);
diff --git a/chromium/net/quic/test_tools/quic_packet_creator_peer.cc b/chromium/net/quic/test_tools/quic_packet_creator_peer.cc
index b502a9b97b4..62e482a891f 100644
--- a/chromium/net/quic/test_tools/quic_packet_creator_peer.cc
+++ b/chromium/net/quic/test_tools/quic_packet_creator_peer.cc
@@ -11,7 +11,7 @@ namespace test {
// static
bool QuicPacketCreatorPeer::SendVersionInPacket(QuicPacketCreator* creator) {
- return creator->send_version_in_packet_;
+ return creator->IncludeVersionInHeader();
}
// static
@@ -31,7 +31,7 @@ void QuicPacketCreatorPeer::SetPacketNumberLength(
// static
QuicPacketNumberLength QuicPacketCreatorPeer::GetPacketNumberLength(
QuicPacketCreator* creator) {
- return creator->packet_.packet_number_length;
+ return creator->GetPacketNumberLength();
}
void QuicPacketCreatorPeer::SetPacketNumber(QuicPacketCreator* creator,
diff --git a/chromium/net/quic/test_tools/quic_sent_packet_manager_peer.cc b/chromium/net/quic/test_tools/quic_sent_packet_manager_peer.cc
index 8650eabf115..0999690a659 100644
--- a/chromium/net/quic/test_tools/quic_sent_packet_manager_peer.cc
+++ b/chromium/net/quic/test_tools/quic_sent_packet_manager_peer.cc
@@ -113,12 +113,26 @@ void QuicSentPacketManagerPeer::MarkForRetransmission(
// static
QuicTime::Delta QuicSentPacketManagerPeer::GetRetransmissionDelay(
+ const QuicSentPacketManager* sent_packet_manager,
+ size_t consecutive_rto_count) {
+ return sent_packet_manager->GetRetransmissionDelay(consecutive_rto_count);
+}
+
+// static
+QuicTime::Delta QuicSentPacketManagerPeer::GetRetransmissionDelay(
const QuicSentPacketManager* sent_packet_manager) {
return sent_packet_manager->GetRetransmissionDelay();
}
// static
QuicTime::Delta QuicSentPacketManagerPeer::GetTailLossProbeDelay(
+ const QuicSentPacketManager* sent_packet_manager,
+ size_t consecutive_tlp_count) {
+ return sent_packet_manager->GetTailLossProbeDelay(consecutive_tlp_count);
+}
+
+// static
+QuicTime::Delta QuicSentPacketManagerPeer::GetTailLossProbeDelay(
const QuicSentPacketManager* sent_packet_manager) {
return sent_packet_manager->GetTailLossProbeDelay();
}
diff --git a/chromium/net/quic/test_tools/quic_sent_packet_manager_peer.h b/chromium/net/quic/test_tools/quic_sent_packet_manager_peer.h
index 713ae888e6d..d1363ef2c7a 100644
--- a/chromium/net/quic/test_tools/quic_sent_packet_manager_peer.h
+++ b/chromium/net/quic/test_tools/quic_sent_packet_manager_peer.h
@@ -57,8 +57,14 @@ class QuicSentPacketManagerPeer {
TransmissionType transmission_type);
static QuicTime::Delta GetRetransmissionDelay(
+ const QuicSentPacketManager* sent_packet_manager,
+ size_t consecutive_rto_count);
+ static QuicTime::Delta GetRetransmissionDelay(
const QuicSentPacketManager* sent_packet_manager);
static QuicTime::Delta GetTailLossProbeDelay(
+ const QuicSentPacketManager* sent_packet_manager,
+ size_t consecutive_tlp_count);
+ static QuicTime::Delta GetTailLossProbeDelay(
const QuicSentPacketManager* sent_packet_manager);
static bool HasUnackedCryptoPackets(
diff --git a/chromium/net/quic/test_tools/quic_stream_send_buffer_peer.cc b/chromium/net/quic/test_tools/quic_stream_send_buffer_peer.cc
index 5ca41adbfd2..7bb4410d467 100644
--- a/chromium/net/quic/test_tools/quic_stream_send_buffer_peer.cc
+++ b/chromium/net/quic/test_tools/quic_stream_send_buffer_peer.cc
@@ -23,6 +23,17 @@ const BufferedSlice* QuicStreamSendBufferPeer::CurrentWriteSlice(
}
return &send_buffer->buffered_slices_[send_buffer->write_index_];
}
+
+// static
+QuicByteCount QuicStreamSendBufferPeer::TotalLength(
+ QuicStreamSendBuffer* send_buffer) {
+ QuicByteCount length = 0;
+ for (const auto& slice : send_buffer->buffered_slices_) {
+ length += slice.slice.length();
+ }
+ return length;
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/test_tools/quic_stream_send_buffer_peer.h b/chromium/net/quic/test_tools/quic_stream_send_buffer_peer.h
index 6b8b115e718..54c53e9c534 100644
--- a/chromium/net/quic/test_tools/quic_stream_send_buffer_peer.h
+++ b/chromium/net/quic/test_tools/quic_stream_send_buffer_peer.h
@@ -18,6 +18,8 @@ class QuicStreamSendBufferPeer {
static const BufferedSlice* CurrentWriteSlice(
QuicStreamSendBuffer* send_buffer);
+
+ static QuicByteCount TotalLength(QuicStreamSendBuffer* send_buffer);
};
} // namespace test
diff --git a/chromium/net/quic/test_tools/quic_test_utils.cc b/chromium/net/quic/test_tools/quic_test_utils.cc
index c3546dfc861..60a70cca68a 100644
--- a/chromium/net/quic/test_tools/quic_test_utils.cc
+++ b/chromium/net/quic/test_tools/quic_test_utils.cc
@@ -233,6 +233,10 @@ bool NoOpFramerVisitor::OnBlockedFrame(const QuicBlockedFrame& frame) {
return true;
}
+bool NoOpFramerVisitor::IsValidStatelessResetToken(uint128 token) const {
+ return false;
+}
+
MockQuicConnectionVisitor::MockQuicConnectionVisitor() {}
MockQuicConnectionVisitor::~MockQuicConnectionVisitor() {}
@@ -374,9 +378,14 @@ void PacketSavingConnection::SendOrQueuePacket(SerializedPacket* packet) {
}
MockQuicSession::MockQuicSession(QuicConnection* connection)
+ : MockQuicSession(connection, true) {}
+
+MockQuicSession::MockQuicSession(QuicConnection* connection,
+ bool create_mock_crypto_stream)
: QuicSession(connection, nullptr, DefaultQuicConfig()) {
- crypto_stream_ = QuicMakeUnique<MockQuicCryptoStream>(this);
- Initialize();
+ if (create_mock_crypto_stream) {
+ crypto_stream_ = QuicMakeUnique<MockQuicCryptoStream>(this);
+ }
ON_CALL(*this, WritevData(_, _, _, _, _))
.WillByDefault(testing::Return(QuicConsumedData(0, false)));
}
@@ -393,6 +402,10 @@ const QuicCryptoStream* MockQuicSession::GetCryptoStream() const {
return crypto_stream_.get();
}
+void MockQuicSession::SetCryptoStream(QuicCryptoStream* crypto_stream) {
+ crypto_stream_.reset(crypto_stream);
+}
+
// static
QuicConsumedData MockQuicSession::ConsumeData(QuicStream* stream,
QuicStreamId /*id*/,
@@ -432,9 +445,15 @@ CryptoMessageParser* MockQuicCryptoStream::crypto_message_parser() {
}
MockQuicSpdySession::MockQuicSpdySession(QuicConnection* connection)
+ : MockQuicSpdySession(connection, true) {}
+
+MockQuicSpdySession::MockQuicSpdySession(QuicConnection* connection,
+ bool create_mock_crypto_stream)
: QuicSpdySession(connection, nullptr, DefaultQuicConfig()) {
- crypto_stream_ = QuicMakeUnique<MockQuicCryptoStream>(this);
- Initialize();
+ if (create_mock_crypto_stream) {
+ crypto_stream_ = QuicMakeUnique<MockQuicCryptoStream>(this);
+ }
+
ON_CALL(*this, WritevData(_, _, _, _, _))
.WillByDefault(testing::Return(QuicConsumedData(0, false)));
}
@@ -451,6 +470,10 @@ const QuicCryptoStream* MockQuicSpdySession::GetCryptoStream() const {
return crypto_stream_.get();
}
+void MockQuicSpdySession::SetCryptoStream(QuicCryptoStream* crypto_stream) {
+ crypto_stream_.reset(crypto_stream);
+}
+
size_t MockQuicSpdySession::WriteHeaders(
QuicStreamId id,
SpdyHeaderBlock headers,
@@ -642,7 +665,7 @@ QuicEncryptedPacket* ConstructEncryptedPacket(QuicConnectionId connection_id,
const string& data) {
return ConstructEncryptedPacket(
connection_id, version_flag, reset_flag, packet_number, data,
- PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER);
+ PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER);
}
QuicEncryptedPacket* ConstructEncryptedPacket(
diff --git a/chromium/net/quic/test_tools/quic_test_utils.h b/chromium/net/quic/test_tools/quic_test_utils.h
index 8544ec8dbec..9d2b75a0455 100644
--- a/chromium/net/quic/test_tools/quic_test_utils.h
+++ b/chromium/net/quic/test_tools/quic_test_utils.h
@@ -107,7 +107,7 @@ QuicEncryptedPacket* ConstructEncryptedPacket(
QuicPacketNumberLength packet_number_length);
// This form assumes |connection_id_length| == PACKET_8BYTE_CONNECTION_ID,
-// |packet_number_length| == PACKET_6BYTE_PACKET_NUMBER and
+// |packet_number_length| == PACKET_4BYTE_PACKET_NUMBER and
// |versions| == nullptr.
QuicEncryptedPacket* ConstructEncryptedPacket(QuicConnectionId connection_id,
bool version_flag,
@@ -260,6 +260,9 @@ class MockFramerVisitor : public QuicFramerVisitorInterface {
MOCK_METHOD1(OnWindowUpdateFrame, bool(const QuicWindowUpdateFrame& frame));
MOCK_METHOD1(OnBlockedFrame, bool(const QuicBlockedFrame& frame));
MOCK_METHOD0(OnPacketComplete, void());
+ MOCK_CONST_METHOD1(IsValidStatelessResetToken, bool(uint128));
+ MOCK_METHOD1(OnAuthenticatedIetfStatelessResetPacket,
+ void(const QuicIetfStatelessResetPacket&));
private:
DISALLOW_COPY_AND_ASSIGN(MockFramerVisitor);
@@ -295,6 +298,9 @@ class NoOpFramerVisitor : public QuicFramerVisitorInterface {
bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
bool OnBlockedFrame(const QuicBlockedFrame& frame) override;
void OnPacketComplete() override {}
+ bool IsValidStatelessResetToken(uint128 token) const override;
+ void OnAuthenticatedIetfStatelessResetPacket(
+ const QuicIetfStatelessResetPacket& packet) override {}
private:
DISALLOW_COPY_AND_ASSIGN(NoOpFramerVisitor);
@@ -332,6 +338,7 @@ class MockQuicConnectionVisitor : public QuicConnectionVisitorInterface {
MOCK_METHOD0(OnAckNeedsRetransmittableFrame, void());
MOCK_METHOD0(SendPing, void());
MOCK_CONST_METHOD0(AllowSelfAddressChange, bool());
+ MOCK_METHOD0(OnForwardProgressConfirmed, void());
private:
DISALLOW_COPY_AND_ASSIGN(MockQuicConnectionVisitor);
@@ -470,11 +477,6 @@ class MockQuicConnection : public QuicConnection {
bool ReallySendControlFrame(const QuicFrame& frame) {
return QuicConnection::SendControlFrame(frame);
}
- void ReallySendGoAway(QuicErrorCode error,
- QuicStreamId last_good_stream_id,
- const std::string& reason) {
- QuicConnection::SendGoAway(error, last_good_stream_id, reason);
- }
bool ReallySendConnectivityProbingPacket(
QuicPacketWriter* probing_writer,
@@ -511,11 +513,15 @@ class PacketSavingConnection : public MockQuicConnection {
class MockQuicSession : public QuicSession {
public:
// Takes ownership of |connection|.
+ MockQuicSession(QuicConnection* connection, bool create_mock_crypto_stream);
+
+ // Takes ownership of |connection|.
explicit MockQuicSession(QuicConnection* connection);
~MockQuicSession() override;
QuicCryptoStream* GetMutableCryptoStream() override;
const QuicCryptoStream* GetCryptoStream() const override;
+ void SetCryptoStream(QuicCryptoStream* crypto_stream);
MOCK_METHOD3(OnConnectionClosed,
void(QuicErrorCode error,
@@ -582,10 +588,14 @@ class MockQuicSpdySession : public QuicSpdySession {
public:
// Takes ownership of |connection|.
explicit MockQuicSpdySession(QuicConnection* connection);
+ // Takes ownership of |connection|.
+ MockQuicSpdySession(QuicConnection* connection,
+ bool create_mock_crypto_stream);
~MockQuicSpdySession() override;
QuicCryptoStream* GetMutableCryptoStream() override;
const QuicCryptoStream* GetCryptoStream() const override;
+ void SetCryptoStream(QuicCryptoStream* crypto_stream);
const SpdyHeaderBlock& GetWriteHeaders() { return write_headers_; }
// From QuicSession.
@@ -775,6 +785,8 @@ class MockSendAlgorithm : public SendAlgorithmInterface {
MOCK_METHOD2(SetFromConfig,
void(const QuicConfig& config, Perspective perspective));
MOCK_METHOD1(SetNumEmulatedConnections, void(int num_connections));
+ MOCK_METHOD1(SetInitialCongestionWindowInPackets,
+ void(QuicPacketCount packets));
MOCK_METHOD1(SetMaxCongestionWindow,
void(QuicByteCount max_congestion_window));
MOCK_METHOD5(OnCongestionEvent,
@@ -858,6 +870,8 @@ class MockNetworkChangeVisitor
~MockNetworkChangeVisitor() override;
MOCK_METHOD0(OnCongestionChange, void());
+ // TODO(b/76462509): remove OnPathDegrading() once
+ // FLAGS_quic_reloadable_flag_quic_path_degrading_alarm is deprecated.
MOCK_METHOD0(OnPathDegrading, void());
MOCK_METHOD1(OnPathMtuIncreased, void(QuicPacketLength));
@@ -891,8 +905,7 @@ class MockQuicConnectionDebugVisitor : public QuicConnectionDebugVisitor {
MOCK_METHOD1(OnPacketHeader, void(const QuicPacketHeader& header));
- MOCK_METHOD1(OnSuccessfulVersionNegotiation,
- void(const QuicTransportVersion&));
+ MOCK_METHOD1(OnSuccessfulVersionNegotiation, void(const ParsedQuicVersion&));
MOCK_METHOD1(OnStreamFrame, void(const QuicStreamFrame&));
diff --git a/chromium/net/quic/test_tools/simple_quic_framer.cc b/chromium/net/quic/test_tools/simple_quic_framer.cc
index a92c0075d01..405cfde0bdf 100644
--- a/chromium/net/quic/test_tools/simple_quic_framer.cc
+++ b/chromium/net/quic/test_tools/simple_quic_framer.cc
@@ -127,6 +127,16 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
void OnPacketComplete() override {}
+ bool IsValidStatelessResetToken(uint128 token) const override {
+ return false;
+ }
+
+ void OnAuthenticatedIetfStatelessResetPacket(
+ const QuicIetfStatelessResetPacket& packet) override {
+ stateless_reset_packet_ =
+ QuicMakeUnique<QuicIetfStatelessResetPacket>(packet);
+ }
+
const QuicPacketHeader& header() const { return header_; }
const std::vector<QuicAckFrame>& ack_frames() const { return ack_frames_; }
const std::vector<QuicConnectionCloseFrame>& connection_close_frames() const {
@@ -161,6 +171,7 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
QuicPacketHeader header_;
std::unique_ptr<QuicVersionNegotiationPacket> version_negotiation_packet_;
std::unique_ptr<QuicPublicResetPacket> public_reset_packet_;
+ std::unique_ptr<QuicIetfStatelessResetPacket> stateless_reset_packet_;
std::vector<QuicAckFrame> ack_frames_;
std::vector<QuicStopWaitingFrame> stop_waiting_frames_;
std::vector<QuicPaddingFrame> padding_frames_;
diff --git a/chromium/net/quic/test_tools/simple_session_notifier.cc b/chromium/net/quic/test_tools/simple_session_notifier.cc
index 61ba9238349..689a6599c12 100644
--- a/chromium/net/quic/test_tools/simple_session_notifier.cc
+++ b/chromium/net/quic/test_tools/simple_session_notifier.cc
@@ -24,18 +24,6 @@ SimpleSessionNotifier::~SimpleSessionNotifier() {
}
}
-std::ostream& operator<<(std::ostream& os,
- const SimpleSessionNotifier::StreamState& s) {
- os << "bytes_total: " << s.bytes_total << " bytes_sent: " << s.bytes_sent
- << " bytes_acked " << s.bytes_acked
- << " pending_retransmissions: " << s.pending_retransmissions
- << " fin_buffered: " << s.fin_buffered << " fin_sent: " << s.fin_sent
- << " fin_outstanding: " << s.fin_outstanding
- << " fin_lost: " << s.fin_lost;
-
- return os;
-}
-
SimpleSessionNotifier::StreamState::StreamState()
: bytes_total(0),
bytes_sent(0),
@@ -477,7 +465,7 @@ bool SimpleSessionNotifier::RetransmitLostStreamData() {
}
if (length > consumed.bytes_consumed ||
(can_bundle_fin && !consumed.fin_consumed)) {
- DLOG(INFO) << "Connection is write blocked";
+ DVLOG(1) << "Connection is write blocked";
break;
}
}
diff --git a/chromium/net/quic/test_tools/simple_session_notifier.h b/chromium/net/quic/test_tools/simple_session_notifier.h
index b5700286540..845e2eca3b2 100644
--- a/chromium/net/quic/test_tools/simple_session_notifier.h
+++ b/chromium/net/quic/test_tools/simple_session_notifier.h
@@ -31,9 +31,6 @@ class SimpleSessionNotifier : public SessionNotifierInterface {
QuicRstStreamErrorCode error,
QuicStreamOffset bytes_written);
- // Called when |frame| is sent.
- void OnControlFrameSent(const QuicFrame& frame);
-
// Neuters unencrypted data of crypto stream.
void NeuterUnencryptedData();
diff --git a/chromium/net/quic/test_tools/simple_session_notifier_test.cc b/chromium/net/quic/test_tools/simple_session_notifier_test.cc
index 0b0f6630cf6..545ae483f8b 100644
--- a/chromium/net/quic/test_tools/simple_session_notifier_test.cc
+++ b/chromium/net/quic/test_tools/simple_session_notifier_test.cc
@@ -29,13 +29,6 @@ class MockQuicConnectionWithSendStreamData : public MockQuicConnection {
size_t write_length,
QuicStreamOffset offset,
StreamSendingState state));
-
- static QuicConsumedData ConsumeAllData(QuicStreamId /*id*/,
- size_t write_length,
- QuicStreamOffset /*offset*/,
- StreamSendingState state) {
- return QuicConsumedData(write_length, state != NO_FIN);
- }
};
class SimpleSessionNotifierTest : public QuicTest {
diff --git a/chromium/net/quic/test_tools/simulator/quic_endpoint.cc b/chromium/net/quic/test_tools/simulator/quic_endpoint.cc
index 2b46e83858a..a02af996c48 100644
--- a/chromium/net/quic/test_tools/simulator/quic_endpoint.cc
+++ b/chromium/net/quic/test_tools/simulator/quic_endpoint.cc
@@ -84,9 +84,9 @@ QuicEndpoint::QuicEndpoint(Simulator* simulator,
connection_.SetSelfAddress(GetAddressFromName(name));
connection_.set_visitor(this);
connection_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
- new NullEncrypter(perspective));
+ QuicMakeUnique<NullEncrypter>(perspective));
connection_.SetDecrypter(ENCRYPTION_FORWARD_SECURE,
- new NullDecrypter(perspective));
+ QuicMakeUnique<NullDecrypter>(perspective));
connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
connection_.SetDataProducer(&producer_);
connection_.SetSessionNotifier(this);
diff --git a/chromium/net/quic/test_tools/simulator/quic_endpoint.h b/chromium/net/quic/test_tools/simulator/quic_endpoint.h
index bd983e4d593..c064560fee6 100644
--- a/chromium/net/quic/test_tools/simulator/quic_endpoint.h
+++ b/chromium/net/quic/test_tools/simulator/quic_endpoint.h
@@ -98,6 +98,7 @@ class QuicEndpoint : public Endpoint,
void OnAckNeedsRetransmittableFrame() override {}
void SendPing() override {}
bool AllowSelfAddressChange() const override;
+ void OnForwardProgressConfirmed() override {}
// End QuicConnectionVisitorInterface implementation.
// Begin SessionNotifierInterface methods:
diff --git a/chromium/net/quic/test_tools/simulator/quic_endpoint_test.cc b/chromium/net/quic/test_tools/simulator/quic_endpoint_test.cc
index 2d8c87ee6b0..edff605c9b5 100644
--- a/chromium/net/quic/test_tools/simulator/quic_endpoint_test.cc
+++ b/chromium/net/quic/test_tools/simulator/quic_endpoint_test.cc
@@ -177,7 +177,7 @@ TEST_F(QuicEndpointTest, Competition) {
endpoint_b->AddBytesToTransfer(2 * 1024 * 1024);
endpoint_c->AddBytesToTransfer(2 * 1024 * 1024);
QuicTime end_time =
- simulator_.GetClock()->Now() + QuicTime::Delta::FromSeconds(8);
+ simulator_.GetClock()->Now() + QuicTime::Delta::FromSeconds(10);
simulator_.RunUntil(
[this, end_time]() { return simulator_.GetClock()->Now() >= end_time; });