diff options
author | rtenneti <rtenneti@chromium.org> | 2015-10-15 14:54:30 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-10-15 21:55:16 +0000 |
commit | 5ca6eeeb62cfe6d3d2f8fa1e00a8112949f26791 (patch) | |
tree | 61887923c823474d876e12bf79fa5c0b5e53a523 /net | |
parent | 631a99a61cbe3e7e03e372b3d37c6a37fa700392 (diff) | |
download | chromium_src-5ca6eeeb62cfe6d3d2f8fa1e00a8112949f26791.zip chromium_src-5ca6eeeb62cfe6d3d2f8fa1e00a8112949f26791.tar.gz chromium_src-5ca6eeeb62cfe6d3d2f8fa1e00a8112949f26791.tar.bz2 |
Landing Recent QUIC changes until 9/30/2015 20:43 UTC.
This CL doesn't include "remove inscure QUIC support" CL.
relnote: Inline all frames smaller than a pointer into QuicFrame.
No functional change.
Merge internal change: 104330302
https://codereview.chromium.org/1399893005/
relnote: Avoid redundant recvmmsg when the previous recvmmsg returned
less than the requested number of packets. Guarded by
FLAGS_quic_read_packets_full_recvmmsg.
This has no measurable effect on the QUIC microbenchmark, though it should
avoid an extra call to recvmmsg at a minimum.
Merge internal change: 104327020
https://codereview.chromium.org/1404873003/
relnote: n/a (QUIC test tools). Cleanup: use C++11 delegate constructor
in quic_test_client, and clang-format to Chromium style:
clang-format -i --style="{BasedOnStyle: Chromium, Standard: Cpp11}" quic_test_client.cc
Merge internal change: 104305494
https://codereview.chromium.org/1407473005/
relnote: n/a (standalone quic_server binary). Cleanup: Use C++11 delegate
constructor in quic_server
Merge internal change: 104305451
https://codereview.chromium.org/1405843003/
relnote: Reduce the size of QUIC's TransmissionInfo struct based on
suggestions from ClassLayoutOptimizer. No functional change.
Merge internal change: 104242241
https://codereview.chromium.org/1401053005/
relnote: add test cases to catch failure on uninitialized self_address_
on chromium side, always set the self_address_ when client creates a new
session and connection.
There's a corner case in quic_client, when it tries to write to the
first packet, the write fails. Previously we did not set self_address_
immediately when we created a new quic_connection. This leads to a crash
on chromium side when logging the uninitialized self_address.
Merge internal change: 104130818
https://codereview.chromium.org/1395423009/
relnote: n/a (comment only). Add comment about |proof_source|, adds
ownership comment about |server_nonce_entropy|.
Merge internal change: 104108540
https://codereview.chromium.org/1403643005/
relnote: Cache-align the encryption buffer in QuicPacketCreator::SerializePacket.
Merge internal change: 104095714
https://codereview.chromium.org/1402943004/
relnote: Disables strike register lookups when talking QUIC_VERSION_27
or higher (not yet used by Chrome).
Merge internal change: 103965712
https://codereview.chromium.org/1404053002/
relnote: Remove unused supported_versions argument from QuicTimeWaitListManager.
No behavior change.
Merge internal change: 103964623
https://codereview.chromium.org/1404013002/
relnote: Check QUIC handshake reject_reasons to decide whether to send a
REJ. No behavior change, not protected.
Simplifies things a little in the server crypto code. Instead of storing
both a reject_reason *and* a boolean indicating whether there was a
problem, just store the reject reason and use the presence of any such
reasons to decide to send a REJ.
Merge internal change: 103949902
https://codereview.chromium.org/1404523004/
relnote: Create Quic version 28. The receiver refuses to create a stream
if too many streams are open, rather than closing the connection.
FIXED=22475509,22476505
Merge internal change: 103943396
https://codereview.chromium.org/1398403006/
R=rch@chromium.org
Review URL: https://codereview.chromium.org/1406983002
Cr-Commit-Position: refs/heads/master@{#354371}
Diffstat (limited to 'net')
33 files changed, 240 insertions, 217 deletions
diff --git a/net/quic/crypto/crypto_server_test.cc b/net/quic/crypto/crypto_server_test.cc index a905597..5bcbc70 100644 --- a/net/quic/crypto/crypto_server_test.cc +++ b/net/quic/crypto/crypto_server_test.cc @@ -408,22 +408,18 @@ TEST_P(CryptoServerTest, BadSNI) { } } -// TODO(rtenneti): Enable the DefaultCert test after implementing ProofSource. -// See http://crbug.com/514472. TEST_P(CryptoServerTest, DefaultCert) { // Check that the server replies with a default certificate when no SNI is - // specified. + // specified. The CHLO is constructed to generate a REJ with certs, so must + // not contain a valid STK, and must include PDMD. // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( "CHLO", "AEAD", "AESG", "KEXS", "C255", - "SCID", scid_hex_.c_str(), - "#004b5453", srct_hex_.c_str(), "PUBS", pub_hex_.c_str(), "NONC", nonce_hex_.c_str(), "PDMD", "X509", - "XLCT", XlctHexString().c_str(), "VER\0", client_version_string_.c_str(), "$padding", static_cast<int>(kClientHelloMinimumSize), nullptr); @@ -435,9 +431,15 @@ TEST_P(CryptoServerTest, DefaultCert) { EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof)); EXPECT_NE(0u, cert.size()); EXPECT_NE(0u, proof.size()); - const HandshakeFailureReason kRejectReasons[] = { - CLIENT_NONCE_INVALID_TIME_FAILURE}; - CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); + if (client_version_ <= QUIC_VERSION_26) { + const HandshakeFailureReason kRejectReasons[] = { + CLIENT_NONCE_INVALID_TIME_FAILURE}; + CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); + } else { + const HandshakeFailureReason kRejectReasons[] = { + SERVER_CONFIG_INCHOATE_HELLO_FAILURE}; + CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); + } } TEST_P(CryptoServerTest, TooSmall) { @@ -614,14 +616,23 @@ TEST_P(CryptoServerTest, CorruptMultipleTags) { // clang-format on ShouldSucceed(msg); CheckRejectTag(); - const HandshakeFailureReason kRejectReasons[] = { - SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, CLIENT_NONCE_INVALID_FAILURE, - SERVER_NONCE_DECRYPTION_FAILURE, + + if (client_version_ <= QUIC_VERSION_26) { + const HandshakeFailureReason kRejectReasons[] = { + SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, CLIENT_NONCE_INVALID_FAILURE, + SERVER_NONCE_DECRYPTION_FAILURE}; + CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); + } else { + const HandshakeFailureReason kRejectReasons[] = { + SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, CLIENT_NONCE_INVALID_FAILURE}; + CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); }; - CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); } TEST_P(CryptoServerTest, ReplayProtection) { + if (client_version_ > QUIC_VERSION_26) { + return; + } // This tests that disabling replay protection works. // clang-format off CryptoHandshakeMessage msg = CryptoTestUtils::Message( diff --git a/net/quic/crypto/quic_crypto_server_config.cc b/net/quic/crypto/quic_crypto_server_config.cc index 8481a0e..5371438 100644 --- a/net/quic/crypto/quic_crypto_server_config.cc +++ b/net/quic/crypto/quic_crypto_server_config.cc @@ -120,7 +120,6 @@ class VerifyNonceIsValidAndUniqueCallback InsertStatus nonce_error) override { DVLOG(1) << "Using client nonce, unique: " << nonce_is_valid_and_unique << " nonce_error: " << nonce_error; - result_->info.unique = nonce_is_valid_and_unique; if (!nonce_is_valid_and_unique) { HandshakeFailureReason client_nonce_error; switch (nonce_error) { @@ -168,12 +167,7 @@ const char QuicCryptoServerConfig::TESTING[] = "secret string for testing"; ClientHelloInfo::ClientHelloInfo(const IPAddressNumber& in_client_ip, QuicWallTime in_now) - : client_ip(in_client_ip), - now(in_now), - valid_source_address_token(false), - client_nonce_well_formed(false), - unique(false) { -} + : client_ip(in_client_ip), now(in_now), valid_source_address_token(false) {} ClientHelloInfo::~ClientHelloInfo() { } @@ -617,10 +611,7 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello( return QUIC_HANDSHAKE_FAILED; } - if (!info.valid_source_address_token || - !info.client_nonce_well_formed || - !info.unique || - !requested_config.get()) { + if (!info.reject_reasons.empty() || !requested_config.get()) { BuildRejection(*primary_config, client_hello, info, validate_chlo_result.cached_network_params, use_stateless_rejects, server_designated_connection_id, rand, @@ -1032,10 +1023,8 @@ void QuicCryptoServerConfig::EvaluateClientHello( } } - if (client_hello.GetStringPiece(kNONC, &info->client_nonce) && - info->client_nonce.size() == kNonceSize) { - info->client_nonce_well_formed = true; - } else { + if (!client_hello.GetStringPiece(kNONC, &info->client_nonce) || + info->client_nonce.size() != kNonceSize) { info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE); // Invalid client nonce. DVLOG(1) << "Invalid client nonce."; @@ -1046,27 +1035,36 @@ void QuicCryptoServerConfig::EvaluateClientHello( found_error = true; } - if (!replay_protection_) { - if (!found_error) { - info->unique = true; + // Server nonce is optional, and used for key derivation if present. + client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce); + + if (version > QUIC_VERSION_26) { + DVLOG(1) << "No 0-RTT replay protection in QUIC_VERSION_27 and higher."; + // If the server nonce is empty and we're requiring handshake confirmation + // for DoS reasons then we must reject the CHLO. + if (FLAGS_quic_require_handshake_confirmation && + info->server_nonce.empty()) { + info->reject_reasons.push_back(SERVER_NONCE_REQUIRED_FAILURE); } + helper.ValidationComplete(QUIC_NO_ERROR, ""); + return; + } + + if (!replay_protection_) { DVLOG(1) << "No replay protection."; helper.ValidationComplete(QUIC_NO_ERROR, ""); return; } - client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce); if (!info->server_nonce.empty()) { // If the server nonce is present, use it to establish uniqueness. HandshakeFailureReason server_nonce_error = ValidateServerNonce(info->server_nonce, info->now); - if (server_nonce_error == HANDSHAKE_OK) { - info->unique = true; - } else { + bool is_unique = server_nonce_error == HANDSHAKE_OK; + if (!is_unique) { info->reject_reasons.push_back(server_nonce_error); - info->unique = false; } - DVLOG(1) << "Using server nonce, unique: " << info->unique; + DVLOG(1) << "Using server nonce, unique: " << is_unique; helper.ValidationComplete(QUIC_NO_ERROR, ""); return; } diff --git a/net/quic/crypto/quic_crypto_server_config.h b/net/quic/crypto/quic_crypto_server_config.h index 4a5c83f..cb3f776 100644 --- a/net/quic/crypto/quic_crypto_server_config.h +++ b/net/quic/crypto/quic_crypto_server_config.h @@ -50,8 +50,6 @@ struct ClientHelloInfo { // Outputs from EvaluateClientHello. bool valid_source_address_token; - bool client_nonce_well_formed; - bool unique; base::StringPiece sni; base::StringPiece client_nonce; base::StringPiece server_nonce; @@ -145,7 +143,9 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig { // into a KDF before use. In tests, use TESTING. // |server_nonce_entropy|: an entropy source used to generate the orbit and // key for server nonces, which are always local to a given instance of a - // server. + // server. Not owned. + // |proof_source|: provides certificate chains and signatures. This class + // takes ownership of |proof_source|. QuicCryptoServerConfig(base::StringPiece source_address_token_secret, QuicRandom* server_nonce_entropy); ~QuicCryptoServerConfig(); diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc index f639eb7..74a2626 100644 --- a/net/quic/quic_connection.cc +++ b/net/quic/quic_connection.cc @@ -1626,7 +1626,9 @@ bool QuicConnection::WritePacketInner(QueuedPacket* packet) { OnWriteError(result.error_code); DLOG(ERROR) << ENDPOINT << "failed writing " << encrypted->length() << " bytes " - << " from host " << self_address().ToStringWithoutPort() + << " from host " << (self_address().address().empty() + ? " empty address " + : self_address().ToStringWithoutPort()) << " to address " << peer_address().ToString(); return false; } @@ -1763,7 +1765,7 @@ void QuicConnection::SendPing() { if (retransmission_alarm_->IsSet()) { return; } - packet_generator_.AddControlFrame(QuicFrame(new QuicPingFrame)); + packet_generator_.AddControlFrame(QuicFrame(QuicPingFrame())); } void QuicConnection::SendAck() { diff --git a/net/quic/quic_connection_logger.cc b/net/quic/quic_connection_logger.cc index 9be77b9..956138f 100644 --- a/net/quic/quic_connection_logger.cc +++ b/net/quic/quic_connection_logger.cc @@ -416,8 +416,7 @@ void QuicConnectionLogger::OnFrameAddedToPacket(const QuicFrame& frame) { ++num_blocked_frames_sent_; net_log_.AddEvent( NetLog::TYPE_QUIC_SESSION_BLOCKED_FRAME_SENT, - base::Bind(&NetLogQuicBlockedFrameCallback, - frame.blocked_frame)); + base::Bind(&NetLogQuicBlockedFrameCallback, frame.blocked_frame)); break; case STOP_WAITING_FRAME: net_log_.AddEvent( diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc index f60c84e..306f496 100644 --- a/net/quic/quic_connection_test.cc +++ b/net/quic/quic_connection_test.cc @@ -239,6 +239,7 @@ class TestPacketWriter : public QuicPacketWriter { framer_(SupportedVersions(version_)), last_packet_size_(0), write_blocked_(false), + write_should_fail_(false), block_on_next_write_(false), is_write_blocked_data_buffered_(false), final_bytes_of_last_packet_(0), @@ -274,6 +275,11 @@ class TestPacketWriter : public QuicPacketWriter { if (IsWriteBlocked()) { return WriteResult(WRITE_STATUS_BLOCKED, -1); } + + if (ShouldWriteFail()) { + return WriteResult(WRITE_STATUS_ERROR, 0); + } + last_packet_size_ = packet.length(); if (!write_pause_time_delta_.IsZero()) { @@ -286,10 +292,14 @@ class TestPacketWriter : public QuicPacketWriter { return is_write_blocked_data_buffered_; } + bool ShouldWriteFail() { return write_should_fail_; } + bool IsWriteBlocked() const override { return write_blocked_; } void SetWritable() override { write_blocked_ = false; } + void SetShouldWriteFail() { write_should_fail_ = true; } + QuicByteCount GetMaxPacketSize( const IPEndPoint& /*peer_address*/) const override { return max_packet_size_; @@ -383,6 +393,7 @@ class TestPacketWriter : public QuicPacketWriter { SimpleQuicFramer framer_; size_t last_packet_size_; bool write_blocked_; + bool write_should_fail_; bool block_on_next_write_; bool is_write_blocked_data_buffered_; uint32 final_bytes_of_last_packet_; @@ -1076,7 +1087,7 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSize) { QuicFrames frames; QuicPaddingFrame padding; frames.push_back(QuicFrame(&frame1_)); - frames.push_back(QuicFrame(&padding)); + frames.push_back(QuicFrame(padding)); scoped_ptr<QuicPacket> packet(ConstructPacket(header, frames)); char buffer[kMaxPacketSize]; scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPayload( @@ -1107,7 +1118,7 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSizeWhileWriterLimited) { QuicFrames frames; QuicPaddingFrame padding; frames.push_back(QuicFrame(&frame1_)); - frames.push_back(QuicFrame(&padding)); + frames.push_back(QuicFrame(padding)); scoped_ptr<QuicPacket> packet(ConstructPacket(header, frames)); char buffer[kMaxPacketSize]; scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPayload( @@ -3650,6 +3661,16 @@ TEST_P(QuicConnectionTest, SendScheduler) { EXPECT_EQ(0u, connection_.NumQueuedPackets()); } +TEST_P(QuicConnectionTest, FailToSendFirstPacket) { + // Test that the connection does not crash when it fails to send the first + // packet at which point self_address_ might be uninitialized. + EXPECT_CALL(visitor_, OnConnectionClosed(_, _)).Times(1); + QuicPacket* packet = ConstructDataPacket(1, 0, !kEntropyFlag); + writer_->SetShouldWriteFail(); + connection_.SendPacket(ENCRYPTION_NONE, 1, packet, kTestEntropyHash, + HAS_RETRANSMITTABLE_DATA, false, false); +} + TEST_P(QuicConnectionTest, SendSchedulerEAGAIN) { QuicPacket* packet = ConstructDataPacket(1, 0, !kEntropyFlag); BlockOnNextWrite(); diff --git a/net/quic/quic_crypto_server_stream_test.cc b/net/quic/quic_crypto_server_stream_test.cc index 5a999ed..88b6de2 100644 --- a/net/quic/quic_crypto_server_stream_test.cc +++ b/net/quic/quic_crypto_server_stream_test.cc @@ -141,6 +141,9 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> { } bool AsyncStrikeRegisterVerification() { + if (server_connection_->version() > QUIC_VERSION_26) { + return false; + } return GetParam(); } diff --git a/net/quic/quic_flags.cc b/net/quic/quic_flags.cc index d3e5a40..3feb646 100644 --- a/net/quic/quic_flags.cc +++ b/net/quic/quic_flags.cc @@ -51,7 +51,7 @@ bool FLAGS_quic_limit_max_cwnd = true; // If true, require handshake confirmation for QUIC connections, functionally // disabling 0-rtt handshakes. -// TODO(rtenneti): Enable this flag after fixing tests. +// TODO(rtenneti): Enable this flag after CryptoServerTest's are fixed. bool FLAGS_quic_require_handshake_confirmation = false; // Disables special treatment of truncated acks, since older retransmissions are @@ -80,3 +80,8 @@ bool FLAGS_shift_quic_cubic_epoch_when_app_limited = true; // If true, accounts for available (implicitly opened) streams under a separate // quota from open streams, which is 10 times larger. bool FLAGS_allow_many_available_streams = true; + +// If true, QuicPacketReader::ReadAndDispatchPackets will only return true if +// recvmmsg fills all of the passed in messages. Otherwise, it will return true +// if recvmmsg read any messages. +bool FLAGS_quic_read_packets_full_recvmmsg = true; diff --git a/net/quic/quic_flags.h b/net/quic/quic_flags.h index e613ea6..bb66a23 100644 --- a/net/quic/quic_flags.h +++ b/net/quic/quic_flags.h @@ -28,5 +28,6 @@ NET_EXPORT_PRIVATE extern bool FLAGS_reset_cubic_epoch_when_app_limited; NET_EXPORT_PRIVATE extern bool FLAGS_quic_packet_queue_use_interval_set; NET_EXPORT_PRIVATE extern bool FLAGS_shift_quic_cubic_epoch_when_app_limited; NET_EXPORT_PRIVATE extern bool FLAGS_allow_many_available_streams; +NET_EXPORT_PRIVATE extern bool FLAGS_quic_read_packets_full_recvmmsg; #endif // NET_QUIC_QUIC_FLAGS_H_ diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc index a04824a..9dd3d90 100644 --- a/net/quic/quic_framer.cc +++ b/net/quic/quic_framer.cc @@ -268,7 +268,8 @@ size_t QuicFramer::GetSerializedFrameLength( InFecGroup is_in_fec_group, QuicPacketNumberLength packet_number_length) { // Prevent a rare crash reported in b/19458523. - if (frame.stream_frame == nullptr) { + if ((frame.type == STREAM_FRAME || frame.type == ACK_FRAME) && + frame.stream_frame == nullptr) { LOG(DFATAL) << "Cannot compute the length of a null frame. " << "type:" << frame.type << "free_bytes:" << free_bytes << " first_frame:" << first_frame diff --git a/net/quic/quic_framer_test.cc b/net/quic/quic_framer_test.cc index 45710c1..5d3a7b7 100644 --- a/net/quic/quic_framer_test.cc +++ b/net/quic/quic_framer_test.cc @@ -2924,7 +2924,7 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) { QuicPaddingFrame padding_frame; QuicFrames frames; - frames.push_back(QuicFrame(&padding_frame)); + frames.push_back(QuicFrame(padding_frame)); // clang-format off unsigned char packet[kMaxPacketSize] = { @@ -2973,7 +2973,7 @@ TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) { QuicPaddingFrame padding_frame; QuicFrames frames; - frames.push_back(QuicFrame(&padding_frame)); + frames.push_back(QuicFrame(padding_frame)); // clang-format off unsigned char packet[kMaxPacketSize] = { @@ -3021,7 +3021,7 @@ TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) { QuicPaddingFrame padding_frame; QuicFrames frames; - frames.push_back(QuicFrame(&padding_frame)); + frames.push_back(QuicFrame(padding_frame)); // clang-format off unsigned char packet[kMaxPacketSize] = { @@ -3069,7 +3069,7 @@ TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) { QuicPaddingFrame padding_frame; QuicFrames frames; - frames.push_back(QuicFrame(&padding_frame)); + frames.push_back(QuicFrame(padding_frame)); // clang-format off unsigned char packet[kMaxPacketSize] = { @@ -3944,7 +3944,7 @@ TEST_P(QuicFramerTest, BuildPingPacket) { QuicPingFrame ping_frame; QuicFrames frames; - frames.push_back(QuicFrame(&ping_frame)); + frames.push_back(QuicFrame(ping_frame)); // clang-format off unsigned char packet[] = { @@ -3986,7 +3986,7 @@ TEST_P(QuicFramerTest, BuildMtuDiscoveryPacket) { QuicMtuDiscoveryFrame mtu_discovery_frame; QuicFrames frames; - frames.push_back(QuicFrame(&mtu_discovery_frame)); + frames.push_back(QuicFrame(mtu_discovery_frame)); // clang-format off unsigned char packet[] = { diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc index 18a719a..8e4f174 100644 --- a/net/quic/quic_packet_creator.cc +++ b/net/quic/quic_packet_creator.cc @@ -451,7 +451,11 @@ SerializedPacket QuicPacketCreator::SerializePacket( bool possibly_truncated_by_length = packet_size_ == max_plaintext_size_ && queued_frames_.size() == 1 && queued_frames_.back().type == ACK_FRAME; - char buffer[kMaxPacketSize]; + // The optimized encryption algorithm implementations run faster when + // operating on aligned memory. + // TODO(rtenneti): Change the default 64 alignas value (used the default + // value from CACHELINE_SIZE). + ALIGNAS(64) char buffer[kMaxPacketSize]; scoped_ptr<QuicPacket> packet; // Use the packet_size_ instead of the buffer size to ensure smaller // packet sizes are properly used. @@ -638,8 +642,7 @@ void QuicPacketCreator::MaybeAddPadding() { return; } - QuicPaddingFrame padding; - bool success = AddFrame(QuicFrame(&padding), false, false, nullptr); + bool success = AddFrame(QuicFrame(QuicPaddingFrame()), false, false, nullptr); DCHECK(success); } diff --git a/net/quic/quic_packet_creator_test.cc b/net/quic/quic_packet_creator_test.cc index c0565ed..4e73ba1 100644 --- a/net/quic/quic_packet_creator_test.cc +++ b/net/quic/quic_packet_creator_test.cc @@ -1006,7 +1006,7 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndSerialize) { EXPECT_TRUE(creator_.HasPendingFrames()); QuicPaddingFrame padding_frame; - EXPECT_TRUE(creator_.AddSavedFrame(QuicFrame(&padding_frame))); + EXPECT_TRUE(creator_.AddSavedFrame(QuicFrame(padding_frame))); EXPECT_TRUE(creator_.HasPendingFrames()); EXPECT_EQ(0u, creator_.BytesFree()); diff --git a/net/quic/quic_packet_generator.cc b/net/quic/quic_packet_generator.cc index eed8ec7..a1a7dd2 100644 --- a/net/quic/quic_packet_generator.cc +++ b/net/quic/quic_packet_generator.cc @@ -57,7 +57,8 @@ QuicPacketGenerator::~QuicPacketGenerator() { for (QuicFrame& frame : queued_control_frames_) { switch (frame.type) { case PADDING_FRAME: - delete frame.padding_frame; + case MTU_DISCOVERY_FRAME: + case PING_FRAME: break; case STREAM_FRAME: delete frame.stream_frame; @@ -65,9 +66,6 @@ QuicPacketGenerator::~QuicPacketGenerator() { case ACK_FRAME: delete frame.ack_frame; break; - case MTU_DISCOVERY_FRAME: - delete frame.mtu_discovery_frame; - break; case RST_STREAM_FRAME: delete frame.rst_stream_frame; break; @@ -86,9 +84,6 @@ QuicPacketGenerator::~QuicPacketGenerator() { case STOP_WAITING_FRAME: delete frame.stop_waiting_frame; break; - case PING_FRAME: - delete frame.ping_frame; - break; case NUM_FRAME_TYPES: DCHECK(false) << "Cannot delete type: " << frame.type; } @@ -250,7 +245,7 @@ void QuicPacketGenerator::GenerateMtuDiscoveryPacket( // The MTU discovery frame is allocated on the stack, since it is going to be // serialized within this function. QuicMtuDiscoveryFrame mtu_discovery_frame; - QuicFrame frame(&mtu_discovery_frame); + QuicFrame frame(mtu_discovery_frame); // Send the probe packet with the new length. SetMaxPacketLength(target_mtu, /*force=*/true); diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc index d281358..e04902f 100644 --- a/net/quic/quic_protocol.cc +++ b/net/quic/quic_protocol.cc @@ -142,6 +142,8 @@ QuicTag QuicVersionToQuicTag(const QuicVersion version) { return MakeQuicTag('Q', '0', '2', '6'); case QUIC_VERSION_27: return MakeQuicTag('Q', '0', '2', '7'); + case QUIC_VERSION_28: + return MakeQuicTag('Q', '0', '2', '8'); default: // This shold be an ERROR because we should never attempt to convert an // invalid QuicVersion to be written to the wire. @@ -172,6 +174,7 @@ string QuicVersionToString(const QuicVersion version) { RETURN_STRING_LITERAL(QUIC_VERSION_25); RETURN_STRING_LITERAL(QUIC_VERSION_26); RETURN_STRING_LITERAL(QUIC_VERSION_27); + RETURN_STRING_LITERAL(QUIC_VERSION_28); default: return "QUIC_VERSION_UNSUPPORTED"; } @@ -263,59 +266,37 @@ QuicConnectionCloseFrame::QuicConnectionCloseFrame() QuicFrame::QuicFrame() {} -QuicFrame::QuicFrame(QuicPaddingFrame* padding_frame) - : type(PADDING_FRAME), - padding_frame(padding_frame) { -} +QuicFrame::QuicFrame(QuicPaddingFrame padding_frame) + : type(PADDING_FRAME), padding_frame(padding_frame) {} QuicFrame::QuicFrame(QuicStreamFrame* stream_frame) - : type(STREAM_FRAME), - stream_frame(stream_frame) { -} + : type(STREAM_FRAME), stream_frame(stream_frame) {} -QuicFrame::QuicFrame(QuicAckFrame* frame) - : type(ACK_FRAME), - ack_frame(frame) { -} +QuicFrame::QuicFrame(QuicAckFrame* frame) : type(ACK_FRAME), ack_frame(frame) {} -QuicFrame::QuicFrame(QuicMtuDiscoveryFrame* frame) - : type(MTU_DISCOVERY_FRAME), mtu_discovery_frame(frame) { -} +QuicFrame::QuicFrame(QuicMtuDiscoveryFrame frame) + : type(MTU_DISCOVERY_FRAME), mtu_discovery_frame(frame) {} QuicFrame::QuicFrame(QuicStopWaitingFrame* frame) - : type(STOP_WAITING_FRAME), - stop_waiting_frame(frame) { -} + : type(STOP_WAITING_FRAME), stop_waiting_frame(frame) {} -QuicFrame::QuicFrame(QuicPingFrame* frame) - : type(PING_FRAME), - ping_frame(frame) { -} +QuicFrame::QuicFrame(QuicPingFrame frame) + : type(PING_FRAME), ping_frame(frame) {} QuicFrame::QuicFrame(QuicRstStreamFrame* frame) - : type(RST_STREAM_FRAME), - rst_stream_frame(frame) { -} + : type(RST_STREAM_FRAME), rst_stream_frame(frame) {} QuicFrame::QuicFrame(QuicConnectionCloseFrame* frame) - : type(CONNECTION_CLOSE_FRAME), - connection_close_frame(frame) { -} + : type(CONNECTION_CLOSE_FRAME), connection_close_frame(frame) {} QuicFrame::QuicFrame(QuicGoAwayFrame* frame) - : type(GOAWAY_FRAME), - goaway_frame(frame) { -} + : type(GOAWAY_FRAME), goaway_frame(frame) {} QuicFrame::QuicFrame(QuicWindowUpdateFrame* frame) - : type(WINDOW_UPDATE_FRAME), - window_update_frame(frame) { -} + : type(WINDOW_UPDATE_FRAME), window_update_frame(frame) {} QuicFrame::QuicFrame(QuicBlockedFrame* frame) - : type(BLOCKED_FRAME), - blocked_frame(frame) { -} + : type(BLOCKED_FRAME), blocked_frame(frame) {} QuicFecData::QuicFecData() : fec_group(0) {} @@ -785,43 +766,39 @@ RetransmittableFrames::RetransmittableFrames(EncryptionLevel level) } RetransmittableFrames::~RetransmittableFrames() { - for (QuicFrames::iterator it = frames_.begin(); it != frames_.end(); ++it) { - switch (it->type) { + for (QuicFrame& frame : frames_) { + switch (frame.type) { + // Frames smaller than a pointer are inlined, so don't need to be deleted. case PADDING_FRAME: - delete it->padding_frame; + case MTU_DISCOVERY_FRAME: + case PING_FRAME: break; case STREAM_FRAME: - delete it->stream_frame; + delete frame.stream_frame; break; case ACK_FRAME: - delete it->ack_frame; - break; - case MTU_DISCOVERY_FRAME: - delete it->mtu_discovery_frame; + delete frame.ack_frame; break; case STOP_WAITING_FRAME: - delete it->stop_waiting_frame; - break; - case PING_FRAME: - delete it->ping_frame; + delete frame.stop_waiting_frame; break; case RST_STREAM_FRAME: - delete it->rst_stream_frame; + delete frame.rst_stream_frame; break; case CONNECTION_CLOSE_FRAME: - delete it->connection_close_frame; + delete frame.connection_close_frame; break; case GOAWAY_FRAME: - delete it->goaway_frame; + delete frame.goaway_frame; break; case WINDOW_UPDATE_FRAME: - delete it->window_update_frame; + delete frame.window_update_frame; break; case BLOCKED_FRAME: - delete it->blocked_frame; + delete frame.blocked_frame; break; case NUM_FRAME_TYPES: - DCHECK(false) << "Cannot delete type: " << it->type; + DCHECK(false) << "Cannot delete type: " << frame.type; } } // TODO(rtenneti): Delete the for loop once chrome has c++11 library support @@ -893,31 +870,31 @@ ostream& operator<<(ostream& os, const QuicEncryptedPacket& s) { TransmissionInfo::TransmissionInfo() : retransmittable_frames(nullptr), packet_number_length(PACKET_1BYTE_PACKET_NUMBER), - sent_time(QuicTime::Zero()), bytes_sent(0), nack_count(0), + sent_time(QuicTime::Zero()), transmission_type(NOT_RETRANSMISSION), - all_transmissions(nullptr), in_flight(false), is_unackable(false), - is_fec_packet(false) {} + is_fec_packet(false), + all_transmissions(nullptr) {} TransmissionInfo::TransmissionInfo( RetransmittableFrames* retransmittable_frames, QuicPacketNumberLength packet_number_length, TransmissionType transmission_type, QuicTime sent_time, - QuicByteCount bytes_sent, + QuicPacketLength bytes_sent, bool is_fec_packet) : retransmittable_frames(retransmittable_frames), packet_number_length(packet_number_length), - sent_time(sent_time), bytes_sent(bytes_sent), nack_count(0), + sent_time(sent_time), transmission_type(transmission_type), - all_transmissions(nullptr), in_flight(false), is_unackable(false), - is_fec_packet(is_fec_packet) {} + is_fec_packet(is_fec_packet), + all_transmissions(nullptr) {} } // namespace net diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h index c942b8d..9d4ad54 100644 --- a/net/quic/quic_protocol.h +++ b/net/quic/quic_protocol.h @@ -51,6 +51,7 @@ typedef std::map<QuicTag, std::string> QuicTagValueMap; // TODO(rtenneti): Didn't use SpdyPriority because SpdyPriority is uint8 and // QuicPriority is uint32. Use SpdyPriority when we change the QUIC_VERSION. typedef uint32 QuicPriority; +typedef uint16 QuicPacketLength; // Default initial maximum size in bytes of a QUIC packet. const QuicByteCount kDefaultMaxPacketSize = 1350; @@ -346,6 +347,7 @@ enum QuicVersion { // from QuicRstStreamFrame QUIC_VERSION_26 = 26, // In CHLO, send XLCT tag containing hash of leaf cert QUIC_VERSION_27 = 27, // Sends a nonce in the SHLO. + QUIC_VERSION_28 = 28, // Receiver can refuse to create a requested stream. }; // This vector contains QUIC versions which we currently support. @@ -356,7 +358,8 @@ enum QuicVersion { // IMPORTANT: if you are adding to this list, follow the instructions at // http://sites/quic/adding-and-removing-versions static const QuicVersion kSupportedQuicVersions[] = { - QUIC_VERSION_27, QUIC_VERSION_26, QUIC_VERSION_25, QUIC_VERSION_24}; + QUIC_VERSION_28, QUIC_VERSION_27, QUIC_VERSION_26, QUIC_VERSION_25, + QUIC_VERSION_24}; typedef std::vector<QuicVersion> QuicVersionVector; @@ -436,6 +439,10 @@ enum QuicRstStreamErrorCode { // Closing stream locally, sending a RST to allow for proper flow control // accounting. Sent in response to a RST from the peer. QUIC_RST_ACKNOWLEDGEMENT, + // Receiver refused to create the stream (because its limit on open streams + // has been reached). The sender should retry the request later (using + // another stream). + QUIC_REFUSED_STREAM, // No error. Used as bound while iterating. QUIC_STREAM_LAST_ERROR, @@ -685,13 +692,11 @@ enum QuicVersionNegotiationState { typedef QuicPacketPublicHeader QuicVersionNegotiationPacket; // A padding frame contains no payload. -struct NET_EXPORT_PRIVATE QuicPaddingFrame { -}; +struct NET_EXPORT_PRIVATE QuicPaddingFrame {}; // A ping frame contains no payload, though it is retransmittable, // and ACK'd just like other normal frames. -struct NET_EXPORT_PRIVATE QuicPingFrame { -}; +struct NET_EXPORT_PRIVATE QuicPingFrame {}; // A path MTU discovery frame contains no payload and is serialized as a ping // frame. @@ -994,15 +999,15 @@ enum EncryptionLevel { struct NET_EXPORT_PRIVATE QuicFrame { QuicFrame(); - explicit QuicFrame(QuicPaddingFrame* padding_frame); + explicit QuicFrame(QuicPaddingFrame padding_frame); + explicit QuicFrame(QuicMtuDiscoveryFrame frame); + explicit QuicFrame(QuicPingFrame frame); + explicit QuicFrame(QuicStreamFrame* stream_frame); explicit QuicFrame(QuicAckFrame* frame); - explicit QuicFrame(QuicMtuDiscoveryFrame* frame); - explicit QuicFrame(QuicRstStreamFrame* frame); explicit QuicFrame(QuicConnectionCloseFrame* frame); explicit QuicFrame(QuicStopWaitingFrame* frame); - explicit QuicFrame(QuicPingFrame* frame); explicit QuicFrame(QuicGoAwayFrame* frame); explicit QuicFrame(QuicWindowUpdateFrame* frame); explicit QuicFrame(QuicBlockedFrame* frame); @@ -1012,14 +1017,15 @@ struct NET_EXPORT_PRIVATE QuicFrame { QuicFrameType type; union { - QuicPaddingFrame* padding_frame; + // Frames smaller than a pointer are inline. + QuicPaddingFrame padding_frame; + QuicMtuDiscoveryFrame mtu_discovery_frame; + QuicPingFrame ping_frame; + + // Frames larger than a pointer. QuicStreamFrame* stream_frame; QuicAckFrame* ack_frame; - QuicMtuDiscoveryFrame* mtu_discovery_frame; - QuicStopWaitingFrame* stop_waiting_frame; - - QuicPingFrame* ping_frame; QuicRstStreamFrame* rst_stream_frame; QuicConnectionCloseFrame* connection_close_frame; QuicGoAwayFrame* goaway_frame; @@ -1027,6 +1033,9 @@ struct NET_EXPORT_PRIVATE QuicFrame { QuicBlockedFrame* blocked_frame; }; }; +// QuicFrameType consumes 8 bytes with padding. +static_assert(sizeof(QuicFrame) <= 16, + "Frames larger than 8 bytes should be referenced by pointer."); typedef std::vector<QuicFrame> QuicFrames; @@ -1180,25 +1189,25 @@ struct NET_EXPORT_PRIVATE TransmissionInfo { QuicPacketNumberLength packet_number_length, TransmissionType transmission_type, QuicTime sent_time, - QuicByteCount bytes_sent, + QuicPacketLength bytes_sent, bool is_fec_packet); RetransmittableFrames* retransmittable_frames; QuicPacketNumberLength packet_number_length; + QuicPacketLength bytes_sent; + uint16 nack_count; QuicTime sent_time; - QuicByteCount bytes_sent; - QuicPacketCount nack_count; // Reason why this packet was transmitted. TransmissionType transmission_type; - // Stores the packet numbers of all transmissions of this packet. - // Must always be nullptr or have multiple elements. - PacketNumberList* all_transmissions; // In flight packets have not been abandoned or lost. bool in_flight; // True if the packet can never be acked, so it can be removed. bool is_unackable; // True if the packet is an FEC packet. bool is_fec_packet; + // Stores the packet numbers of all transmissions of this packet. + // Must always be nullptr or have multiple elements. + PacketNumberList* all_transmissions; }; // Convenience wrapper to wrap an iovec array and the total length, which must diff --git a/net/quic/quic_protocol_test.cc b/net/quic/quic_protocol_test.cc index c74d3d1..fcadbe9 100644 --- a/net/quic/quic_protocol_test.cc +++ b/net/quic/quic_protocol_test.cc @@ -14,7 +14,7 @@ namespace test { namespace { TEST(QuicProtocolTest, AdjustErrorForVersion) { - ASSERT_EQ(8, QUIC_STREAM_LAST_ERROR) + ASSERT_EQ(9, QUIC_STREAM_LAST_ERROR) << "Any additions to QuicRstStreamErrorCode require an addition to " << "AdjustErrorForVersion and this associated test."; diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc index 7875bb8..12d1903 100644 --- a/net/quic/quic_session.cc +++ b/net/quic/quic_session.cc @@ -679,7 +679,12 @@ ReliableQuicStream* QuicSession::GetIncomingDynamicStream( // Check if the new number of open streams would cause the number of // open streams to exceed the limit. if (GetNumOpenStreams() >= get_max_open_streams()) { - CloseConnection(QUIC_TOO_MANY_OPEN_STREAMS); + if (connection()->version() <= QUIC_VERSION_27) { + CloseConnection(QUIC_TOO_MANY_OPEN_STREAMS); + } else { + // Refuse to open the stream. + SendRstStream(stream_id, QUIC_REFUSED_STREAM, 0); + } return nullptr; } } diff --git a/net/quic/quic_unacked_packet_map.cc b/net/quic/quic_unacked_packet_map.cc index 71088ae..bbe7b3f 100644 --- a/net/quic/quic_unacked_packet_map.cc +++ b/net/quic/quic_unacked_packet_map.cc @@ -185,7 +185,7 @@ bool QuicUnackedPacketMap::HasRetransmittableFrames( } void QuicUnackedPacketMap::NackPacket(QuicPacketNumber packet_number, - QuicPacketCount min_nacks) { + uint16 min_nacks) { DCHECK_GE(packet_number, least_unacked_); DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size()); unacked_packets_[packet_number - least_unacked_].nack_count = max( diff --git a/net/quic/quic_unacked_packet_map.h b/net/quic/quic_unacked_packet_map.h index 1926d31..358491d 100644 --- a/net/quic/quic_unacked_packet_map.h +++ b/net/quic/quic_unacked_packet_map.h @@ -42,7 +42,7 @@ class NET_EXPORT_PRIVATE QuicUnackedPacketMap { bool IsUnacked(QuicPacketNumber packet_number) const; // Sets the nack count to the max of the current nack count and |min_nacks|. - void NackPacket(QuicPacketNumber packet_number, QuicPacketCount min_nacks); + void NackPacket(QuicPacketNumber packet_number, uint16 min_nacks); // Marks |packet_number| as no longer in flight. void RemoveFromInFlight(QuicPacketNumber packet_number); diff --git a/net/quic/quic_utils.cc b/net/quic/quic_utils.cc index 641818e..b336202 100644 --- a/net/quic/quic_utils.cc +++ b/net/quic/quic_utils.cc @@ -146,6 +146,7 @@ const char* QuicUtils::StreamErrorToString(QuicRstStreamErrorCode error) { RETURN_STRING_LITERAL(QUIC_STREAM_PEER_GOING_AWAY); RETURN_STRING_LITERAL(QUIC_STREAM_CANCELLED); RETURN_STRING_LITERAL(QUIC_RST_ACKNOWLEDGEMENT); + RETURN_STRING_LITERAL(QUIC_REFUSED_STREAM); RETURN_STRING_LITERAL(QUIC_STREAM_LAST_ERROR); } // Return a default value so that we return this when |error| doesn't match diff --git a/net/quic/test_tools/crypto_test_utils_chromium.cc b/net/quic/test_tools/crypto_test_utils_chromium.cc index 366dd5e..ffa1788 100644 --- a/net/quic/test_tools/crypto_test_utils_chromium.cc +++ b/net/quic/test_tools/crypto_test_utils_chromium.cc @@ -116,7 +116,7 @@ ProofSource* CryptoTestUtils::ProofSourceForTesting() { ProofSourceChromium* source = new ProofSourceChromium(); base::FilePath certs_dir = GetTestCertsDirectory(); CHECK(source->Initialize( - certs_dir.AppendASCII("quic_chain.crt"), + certs_dir.AppendASCII("quic_test.example.com.crt"), certs_dir.AppendASCII("quic_test.example.com.key.pkcs8"))); return source; } diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc index 9f4ccaa..dd13bcb 100644 --- a/net/tools/quic/end_to_end_test.cc +++ b/net/tools/quic/end_to_end_test.cc @@ -1100,9 +1100,15 @@ TEST_P(EndToEndTest, NegotiateMaxOpenStreams) { } client_->WaitForResponse(); - EXPECT_FALSE(client_->connected()); - EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error()); - EXPECT_EQ(QUIC_TOO_MANY_OPEN_STREAMS, client_->connection_error()); + if (negotiated_version_ <= QUIC_VERSION_27) { + EXPECT_FALSE(client_->connected()); + EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error()); + EXPECT_EQ(QUIC_TOO_MANY_OPEN_STREAMS, client_->connection_error()); + } else { + EXPECT_TRUE(client_->connected()); + EXPECT_EQ(QUIC_REFUSED_STREAM, client_->stream_error()); + EXPECT_EQ(QUIC_NO_ERROR, client_->connection_error()); + } } TEST_P(EndToEndTest, NegotiateCongestionControl) { diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc index 0a103ac..31cc8e3 100644 --- a/net/tools/quic/quic_dispatcher.cc +++ b/net/tools/quic/quic_dispatcher.cc @@ -487,7 +487,7 @@ QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() { time_wait_list_writer_.reset( packet_writer_factory_->Create(writer_.get(), nullptr)); return new QuicTimeWaitListManager(time_wait_list_writer_.get(), this, - helper_.get(), supported_versions()); + helper_.get()); } bool QuicDispatcher::HandlePacketForTimeWait( diff --git a/net/tools/quic/quic_packet_reader.cc b/net/tools/quic/quic_packet_reader.cc index 1982269..1f368a6 100644 --- a/net/tools/quic/quic_packet_reader.cc +++ b/net/tools/quic/quic_packet_reader.cc @@ -14,6 +14,7 @@ #include "base/logging.h" #include "net/base/ip_endpoint.h" +#include "net/quic/quic_flags.h" #include "net/tools/quic/quic_dispatcher.h" #include "net/tools/quic/quic_socket_utils.h" @@ -103,7 +104,12 @@ bool QuicPacketReader::ReadAndDispatchPackets( packets_dropped); } - return true; + if (FLAGS_quic_read_packets_full_recvmmsg) { + // We may not have read all of the packets available on the socket. + return packets_read == kNumPacketsPerReadMmsgCall; + } else { + return true; + } #else LOG(FATAL) << "Unsupported"; return false; diff --git a/net/tools/quic/quic_packet_reader.h b/net/tools/quic/quic_packet_reader.h index 479fc6d..e667d59 100644 --- a/net/tools/quic/quic_packet_reader.h +++ b/net/tools/quic/quic_packet_reader.h @@ -37,8 +37,8 @@ class QuicPacketReader { virtual ~QuicPacketReader(); // Reads a number of packets from the given fd, and then passes them off to - // the PacketProcessInterface. Returns true if at least 1 packet is read, - // false otherwise. + // the PacketProcessInterface. Returns true if there may be additional + // packets available on the socket. // Populates |packets_dropped| if it is non-null and the socket is configured // to track dropped packets and some packets are read. virtual bool ReadAndDispatchPackets(int fd, diff --git a/net/tools/quic/quic_server.cc b/net/tools/quic/quic_server.cc index 392963d..e0cd873 100644 --- a/net/tools/quic/quic_server.cc +++ b/net/tools/quic/quic_server.cc @@ -47,17 +47,7 @@ const char kSourceAddressTokenSecret[] = "secret"; } // namespace -QuicServer::QuicServer() - : port_(0), - fd_(-1), - packets_dropped_(0), - overflow_supported_(false), - use_recvmmsg_(false), - crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()), - supported_versions_(QuicSupportedVersions()), - packet_reader_(new QuicPacketReader()) { - Initialize(); -} +QuicServer::QuicServer() : QuicServer(QuicConfig(), QuicSupportedVersions()) {} QuicServer::QuicServer(const QuicConfig& config, const QuicVersionVector& supported_versions) @@ -215,14 +205,14 @@ void QuicServer::OnEvent(int fd, EpollEvent* event) { if (event->in_events & EPOLLIN) { DVLOG(1) << "EPOLLIN"; - bool read = true; - while (read) { + bool more_to_read = true; + while (more_to_read) { if (use_recvmmsg_) { - read = packet_reader_->ReadAndDispatchPackets( + more_to_read = packet_reader_->ReadAndDispatchPackets( fd_, port_, dispatcher_.get(), overflow_supported_ ? &packets_dropped_ : nullptr); } else { - read = QuicPacketReader::ReadAndDispatchSinglePacket( + more_to_read = QuicPacketReader::ReadAndDispatchSinglePacket( fd_, port_, dispatcher_.get(), overflow_supported_ ? &packets_dropped_ : nullptr); } diff --git a/net/tools/quic/quic_server_session_test.cc b/net/tools/quic/quic_server_session_test.cc index 7123496..d24b837 100644 --- a/net/tools/quic/quic_server_session_test.cc +++ b/net/tools/quic/quic_server_session_test.cc @@ -189,9 +189,9 @@ TEST_P(QuicServerSessionTest, AcceptClosedStream) { } TEST_P(QuicServerSessionTest, MaxOpenStreams) { - // Test that the server closes the connection if a client attempts to open too - // many data streams. The server accepts slightly more than the negotiated - // stream limit to deal with rare cases where a client FIN/RST is lost. + // Test that the server refuses if a client attempts to open too many data + // streams. The server accepts slightly more than the negotiated stream limit + // to deal with rare cases where a client FIN/RST is lost. // The slightly increased stream limit is set during config negotiation. It // is either an increase of 10 over negotiated limit, or a fixed percentage @@ -220,8 +220,14 @@ TEST_P(QuicServerSessionTest, MaxOpenStreams) { // Now violate the server's internal stream limit. stream_id += 2; - EXPECT_CALL(*connection_, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS)); - EXPECT_CALL(*connection_, SendRstStream(_, _, _)).Times(0); + if (connection_->version() <= QUIC_VERSION_27) { + EXPECT_CALL(*connection_, SendConnectionClose(QUIC_TOO_MANY_OPEN_STREAMS)); + EXPECT_CALL(*connection_, SendRstStream(_, _, _)).Times(0); + } else { + EXPECT_CALL(*connection_, SendConnectionClose(_)).Times(0); + EXPECT_CALL(*connection_, SendRstStream(stream_id, QUIC_REFUSED_STREAM, 0)); + } + // Even if the connection remains open, the stream creation should fail. EXPECT_FALSE(QuicServerSessionPeer::GetIncomingDynamicStream(session_.get(), stream_id)); } diff --git a/net/tools/quic/quic_time_wait_list_manager.cc b/net/tools/quic/quic_time_wait_list_manager.cc index 68d1b9e..1e433e5 100644 --- a/net/tools/quic/quic_time_wait_list_manager.cc +++ b/net/tools/quic/quic_time_wait_list_manager.cc @@ -80,8 +80,7 @@ class QuicTimeWaitListManager::QueuedPacket { QuicTimeWaitListManager::QuicTimeWaitListManager( QuicPacketWriter* writer, QuicServerSessionVisitor* visitor, - QuicConnectionHelperInterface* helper, - const QuicVersionVector& supported_versions) + QuicConnectionHelperInterface* helper) : time_wait_period_( QuicTime::Delta::FromSeconds(FLAGS_quic_time_wait_list_seconds)), connection_id_clean_up_alarm_( diff --git a/net/tools/quic/quic_time_wait_list_manager.h b/net/tools/quic/quic_time_wait_list_manager.h index 9a9eccd..092f116 100644 --- a/net/tools/quic/quic_time_wait_list_manager.h +++ b/net/tools/quic/quic_time_wait_list_manager.h @@ -44,8 +44,7 @@ class QuicTimeWaitListManager : public QuicBlockedWriterInterface { // helper - used to run clean up alarms. (Owned by the dispatcher) QuicTimeWaitListManager(QuicPacketWriter* writer, QuicServerSessionVisitor* visitor, - QuicConnectionHelperInterface* helper, - const QuicVersionVector& supported_versions); + QuicConnectionHelperInterface* helper); ~QuicTimeWaitListManager() override; // Adds the given connection_id to time wait state for time_wait_period_. diff --git a/net/tools/quic/quic_time_wait_list_manager_test.cc b/net/tools/quic/quic_time_wait_list_manager_test.cc index e6baf7d..8f5fd89 100644 --- a/net/tools/quic/quic_time_wait_list_manager_test.cc +++ b/net/tools/quic/quic_time_wait_list_manager_test.cc @@ -96,10 +96,7 @@ class QuicTimeWaitListManagerTest : public ::testing::Test { protected: QuicTimeWaitListManagerTest() : helper_(&epoll_server_), - time_wait_list_manager_(&writer_, - &visitor_, - &helper_, - QuicSupportedVersions()), + time_wait_list_manager_(&writer_, &visitor_, &helper_), framer_(QuicSupportedVersions(), QuicTime::Zero(), Perspective::IS_SERVER), diff --git a/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.cc b/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.cc index 7801db5..8e972f3 100644 --- a/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.cc +++ b/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.cc @@ -16,10 +16,7 @@ MockTimeWaitListManager::MockTimeWaitListManager( QuicPacketWriter* writer, QuicServerSessionVisitor* visitor, QuicConnectionHelperInterface* helper) - : QuicTimeWaitListManager(writer, - visitor, - helper, - QuicSupportedVersions()) { + : QuicTimeWaitListManager(writer, visitor, helper) { // Though AddConnectionIdToTimeWait is mocked, we want to retain its // functionality. EXPECT_CALL(*this, AddConnectionIdToTimeWait(_, _, _, _)) diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc index 718f0cf..708b4f8 100644 --- a/net/tools/quic/test_tools/quic_test_client.cc +++ b/net/tools/quic/test_tools/quic_test_client.cc @@ -109,12 +109,11 @@ MockableQuicClient::MockableQuicClient( const QuicServerId& server_id, const QuicVersionVector& supported_versions, EpollServer* epoll_server) - : QuicClient(server_address, - server_id, - supported_versions, - epoll_server), - override_connection_id_(0), - test_writer_(nullptr) {} + : MockableQuicClient(server_address, + server_id, + QuicConfig(), + supported_versions, + epoll_server) {} MockableQuicClient::MockableQuicClient( IPEndPoint server_address, @@ -164,36 +163,29 @@ QuicTestClient::QuicTestClient(IPEndPoint server_address, const string& server_hostname, bool secure, const QuicVersionVector& supported_versions) + : QuicTestClient(server_address, + server_hostname, + secure, + QuicConfig(), + supported_versions) {} + +QuicTestClient::QuicTestClient(IPEndPoint server_address, + const string& server_hostname, + bool secure, + const QuicConfig& config, + const QuicVersionVector& supported_versions) : client_(new MockableQuicClient(server_address, QuicServerId(server_hostname, server_address.port(), secure, PRIVACY_MODE_DISABLED), + config, supported_versions, &epoll_server_)) { Initialize(secure); } -QuicTestClient::QuicTestClient( - IPEndPoint server_address, - const string& server_hostname, - bool secure, - const QuicConfig& config, - const QuicVersionVector& supported_versions) - : client_( - new MockableQuicClient(server_address, - QuicServerId(server_hostname, - server_address.port(), - secure, - PRIVACY_MODE_DISABLED), - config, - supported_versions, - &epoll_server_)) { - Initialize(secure); -} - -QuicTestClient::QuicTestClient() { -} +QuicTestClient::QuicTestClient() {} QuicTestClient::~QuicTestClient() { if (stream_) { |