diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-08-24 12:15:48 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-08-28 13:30:04 +0000 |
commit | b014812705fc80bff0a5c120dfcef88f349816dc (patch) | |
tree | 25a2e2d9fa285f1add86aa333389a839f81a39ae /chromium/net/tools/quic | |
parent | 9f4560b1027ae06fdb497023cdcaf91b8511fa74 (diff) | |
download | qtwebengine-chromium-b014812705fc80bff0a5c120dfcef88f349816dc.tar.gz |
BASELINE: Update Chromium to 68.0.3440.125
Change-Id: I23f19369e01f688e496f5bf179abb521ad73874f
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/net/tools/quic')
117 files changed, 123 insertions, 21598 deletions
diff --git a/chromium/net/tools/quic/chlo_extractor.cc b/chromium/net/tools/quic/chlo_extractor.cc deleted file mode 100644 index 7ef853a939c..00000000000 --- a/chromium/net/tools/quic/chlo_extractor.cc +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright (c) 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/chlo_extractor.h" - -#include "net/quic/core/crypto/crypto_framer.h" -#include "net/quic/core/crypto/crypto_handshake_message.h" -#include "net/quic/core/crypto/crypto_protocol.h" -#include "net/quic/core/crypto/quic_decrypter.h" -#include "net/quic/core/crypto/quic_encrypter.h" -#include "net/quic/core/quic_framer.h" -#include "net/quic/platform/api/quic_string_piece.h" -#include "net/quic/platform/api/quic_text_utils.h" - -namespace net { - -namespace { - -class ChloFramerVisitor : public QuicFramerVisitorInterface, - public CryptoFramerVisitorInterface { - public: - ChloFramerVisitor(QuicFramer* framer, - const QuicTagVector& create_session_tag_indicators, - ChloExtractor::Delegate* delegate); - - ~ChloFramerVisitor() override = default; - - // QuicFramerVisitorInterface implementation - void OnError(QuicFramer* framer) override {} - bool OnProtocolVersionMismatch(ParsedQuicVersion version) override; - void OnPacket() override {} - void OnPublicResetPacket(const QuicPublicResetPacket& packet) override {} - void OnVersionNegotiationPacket( - const QuicVersionNegotiationPacket& packet) override {} - bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override; - bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override; - void OnDecryptedPacket(EncryptionLevel level) override {} - bool OnPacketHeader(const QuicPacketHeader& header) override; - bool OnStreamFrame(const QuicStreamFrame& frame) override; - bool OnAckFrame(const QuicAckFrame& frame) override; - bool OnAckFrameStart(QuicPacketNumber largest_acked, - QuicTime::Delta ack_delay_time) override; - bool OnAckRange(QuicPacketNumber start, - QuicPacketNumber end, - bool last_range) override; - bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override; - bool OnPingFrame(const QuicPingFrame& frame) override; - bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override; - bool OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override; - bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override; - bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override; - bool OnBlockedFrame(const QuicBlockedFrame& frame) override; - bool OnPaddingFrame(const QuicPaddingFrame& frame) override; - void OnPacketComplete() override {} - bool IsValidStatelessResetToken(uint128 token) const override; - void OnAuthenticatedIetfStatelessResetPacket( - const QuicIetfStatelessResetPacket& packet) override {} - - // CryptoFramerVisitorInterface implementation. - void OnError(CryptoFramer* framer) override; - void OnHandshakeMessage(const CryptoHandshakeMessage& message) override; - - bool found_chlo() { return found_chlo_; } - bool chlo_contains_tags() { return chlo_contains_tags_; } - - private: - QuicFramer* framer_; - const QuicTagVector& create_session_tag_indicators_; - ChloExtractor::Delegate* delegate_; - bool found_chlo_; - bool chlo_contains_tags_; - QuicConnectionId connection_id_; -}; - -ChloFramerVisitor::ChloFramerVisitor( - QuicFramer* framer, - const QuicTagVector& create_session_tag_indicators, - ChloExtractor::Delegate* delegate) - : framer_(framer), - create_session_tag_indicators_(create_session_tag_indicators), - delegate_(delegate), - found_chlo_(false), - chlo_contains_tags_(false), - connection_id_(0) {} - -bool ChloFramerVisitor::OnProtocolVersionMismatch(ParsedQuicVersion version) { - if (!framer_->IsSupportedVersion(version)) { - return false; - } - framer_->set_version(version); - return true; -} - -bool ChloFramerVisitor::OnUnauthenticatedPublicHeader( - const QuicPacketHeader& header) { - connection_id_ = header.connection_id; - return true; -} -bool ChloFramerVisitor::OnUnauthenticatedHeader( - const QuicPacketHeader& header) { - return true; -} -bool ChloFramerVisitor::OnPacketHeader(const QuicPacketHeader& header) { - return true; -} -bool ChloFramerVisitor::OnStreamFrame(const QuicStreamFrame& frame) { - QuicStringPiece data(frame.data_buffer, frame.data_length); - if (frame.stream_id == kCryptoStreamId && frame.offset == 0 && - QuicTextUtils::StartsWith(data, "CHLO")) { - CryptoFramer crypto_framer; - crypto_framer.set_visitor(this); - if (!crypto_framer.ProcessInput(data, Perspective::IS_SERVER)) { - return false; - } - // Interrogate the crypto framer and see if there are any - // intersecting tags between what we saw in the maybe-CHLO and the - // indicator set. - for (const QuicTag tag : create_session_tag_indicators_) { - if (crypto_framer.HasTag(tag)) { - chlo_contains_tags_ = true; - } - } - if (chlo_contains_tags_ && delegate_) { - // Unfortunately, because this is a partial CHLO, - // OnHandshakeMessage was never called, so the ALPN was never - // extracted. Fake it up a bit and send it to the delegate so that - // the correct dispatch can happen. - crypto_framer.ForceHandshake(); - } - } - - return true; -} - -bool ChloFramerVisitor::OnAckFrame(const QuicAckFrame& frame) { - return true; -} - -bool ChloFramerVisitor::OnAckFrameStart(QuicPacketNumber /*largest_acked*/, - QuicTime::Delta /*ack_delay_time*/) { - return true; -} - -bool ChloFramerVisitor::OnAckRange(QuicPacketNumber /*start*/, - QuicPacketNumber /*end*/, - bool /*last_range*/) { - return true; -} - -bool ChloFramerVisitor::OnStopWaitingFrame(const QuicStopWaitingFrame& frame) { - return true; -} - -bool ChloFramerVisitor::OnPingFrame(const QuicPingFrame& frame) { - return true; -} - -bool ChloFramerVisitor::OnRstStreamFrame(const QuicRstStreamFrame& frame) { - return true; -} - -bool ChloFramerVisitor::OnConnectionCloseFrame( - const QuicConnectionCloseFrame& frame) { - return true; -} - -bool ChloFramerVisitor::OnGoAwayFrame(const QuicGoAwayFrame& frame) { - return true; -} - -bool ChloFramerVisitor::OnWindowUpdateFrame( - const QuicWindowUpdateFrame& frame) { - return true; -} - -bool ChloFramerVisitor::OnBlockedFrame(const QuicBlockedFrame& frame) { - return true; -} - -bool ChloFramerVisitor::OnPaddingFrame(const QuicPaddingFrame& frame) { - return true; -} - -bool ChloFramerVisitor::IsValidStatelessResetToken(uint128 token) const { - return false; -} - -void ChloFramerVisitor::OnError(CryptoFramer* framer) {} - -void ChloFramerVisitor::OnHandshakeMessage( - const CryptoHandshakeMessage& message) { - if (delegate_ != nullptr) { - delegate_->OnChlo(framer_->transport_version(), connection_id_, message); - } - found_chlo_ = true; -} - -} // namespace - -// static -bool ChloExtractor::Extract(const QuicEncryptedPacket& packet, - const ParsedQuicVersionVector& versions, - const QuicTagVector& create_session_tag_indicators, - Delegate* delegate) { - QuicFramer framer(versions, QuicTime::Zero(), Perspective::IS_SERVER); - ChloFramerVisitor visitor(&framer, create_session_tag_indicators, delegate); - framer.set_visitor(&visitor); - if (!framer.ProcessPacket(packet)) { - return false; - } - return visitor.found_chlo() || visitor.chlo_contains_tags(); -} - -} // namespace net diff --git a/chromium/net/tools/quic/chlo_extractor.h b/chromium/net/tools/quic/chlo_extractor.h deleted file mode 100644 index dd0fe907dac..00000000000 --- a/chromium/net/tools/quic/chlo_extractor.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_CHLO_EXTRACTOR_H_ -#define NET_TOOLS_QUIC_CHLO_EXTRACTOR_H_ - -#include "net/quic/core/crypto/crypto_handshake_message.h" -#include "net/quic/core/quic_packets.h" - -namespace net { - -// A utility for extracting QUIC Client Hello messages from packets, -// without needs to spin up a full QuicSession. -class ChloExtractor { - public: - class Delegate { - public: - virtual ~Delegate() {} - - // Called when a CHLO message is found in the packets. - virtual void OnChlo(QuicTransportVersion version, - QuicConnectionId connection_id, - const CryptoHandshakeMessage& chlo) = 0; - }; - - // Extracts a CHLO message from |packet| and invokes the OnChlo - // method of |delegate|. Return true if a CHLO message was found, - // and false otherwise. If non-empty, - // |create_session_tag_indicators| contains a list of QUIC tags that - // if found will result in the session being created early, to - // enable support for multi-packet CHLOs. - static bool Extract(const QuicEncryptedPacket& packet, - const ParsedQuicVersionVector& versions, - const QuicTagVector& create_session_tag_indicators, - Delegate* delegate); - - ChloExtractor(const ChloExtractor&) = delete; - ChloExtractor operator=(const ChloExtractor&) = delete; -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_CHLO_EXTRACTOR_H_ diff --git a/chromium/net/tools/quic/chlo_extractor_test.cc b/chromium/net/tools/quic/chlo_extractor_test.cc deleted file mode 100644 index f02b5d1bb30..00000000000 --- a/chromium/net/tools/quic/chlo_extractor_test.cc +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/chlo_extractor.h" - -#include <memory> - -#include "net/quic/core/quic_framer.h" -#include "net/quic/platform/api/quic_arraysize.h" -#include "net/quic/platform/api/quic_ptr_util.h" -#include "net/quic/platform/api/quic_string.h" -#include "net/quic/platform/api/quic_test.h" -#include "net/quic/test_tools/crypto_test_utils.h" -#include "net/quic/test_tools/quic_test_utils.h" - -using std::string; - -namespace net { -namespace test { -namespace { - -class TestDelegate : public ChloExtractor::Delegate { - public: - TestDelegate() = default; - ~TestDelegate() override = default; - - // ChloExtractor::Delegate implementation - void OnChlo(QuicTransportVersion version, - QuicConnectionId connection_id, - const CryptoHandshakeMessage& chlo) override { - version_ = version; - connection_id_ = connection_id; - chlo_ = chlo.DebugString(Perspective::IS_SERVER); - } - - QuicConnectionId connection_id() const { return connection_id_; } - QuicTransportVersion transport_version() const { return version_; } - const QuicString& chlo() const { return chlo_; } - - private: - QuicConnectionId connection_id_; - QuicTransportVersion version_; - QuicString chlo_; -}; - -class ChloExtractorTest : public QuicTest { - public: - ChloExtractorTest() { - header_.connection_id = 42; - header_.connection_id_length = PACKET_8BYTE_CONNECTION_ID; - header_.version_flag = true; - header_.version = AllSupportedVersions().front(); - header_.reset_flag = false; - header_.packet_number_length = PACKET_4BYTE_PACKET_NUMBER; - header_.packet_number = 1; - } - - void MakePacket(QuicStreamFrame* stream_frame) { - QuicFrame frame(stream_frame); - QuicFrames frames; - frames.push_back(frame); - QuicFramer framer(SupportedVersions(header_.version), QuicTime::Zero(), - Perspective::IS_CLIENT); - std::unique_ptr<QuicPacket> packet( - BuildUnsizedDataPacket(&framer, header_, frames)); - EXPECT_TRUE(packet != nullptr); - size_t encrypted_length = - framer.EncryptPayload(ENCRYPTION_NONE, header_.packet_number, *packet, - buffer_, QUIC_ARRAYSIZE(buffer_)); - ASSERT_NE(0u, encrypted_length); - packet_ = QuicMakeUnique<QuicEncryptedPacket>(buffer_, encrypted_length); - EXPECT_TRUE(packet_ != nullptr); - delete stream_frame; - } - - protected: - TestDelegate delegate_; - QuicPacketHeader header_; - std::unique_ptr<QuicEncryptedPacket> packet_; - char buffer_[kMaxPacketSize]; -}; - -TEST_F(ChloExtractorTest, FindsValidChlo) { - CryptoHandshakeMessage client_hello; - client_hello.set_tag(kCHLO); - - string client_hello_str((string( - client_hello.GetSerialized(Perspective::IS_CLIENT).AsStringPiece()))); - // Construct a CHLO with each supported version - for (ParsedQuicVersion version : AllSupportedVersions()) { - ParsedQuicVersionVector versions(SupportedVersions(version)); - header_.version = version; - MakePacket( - new QuicStreamFrame(kCryptoStreamId, false, 0, client_hello_str)); - EXPECT_TRUE(ChloExtractor::Extract(*packet_, versions, {}, &delegate_)) - << ParsedQuicVersionToString(version); - EXPECT_EQ(version.transport_version, delegate_.transport_version()); - EXPECT_EQ(header_.connection_id, delegate_.connection_id()); - EXPECT_EQ(client_hello.DebugString(Perspective::IS_SERVER), - delegate_.chlo()) - << ParsedQuicVersionToString(version); - } -} - -TEST_F(ChloExtractorTest, DoesNotFindValidChloOnWrongStream) { - CryptoHandshakeMessage client_hello; - client_hello.set_tag(kCHLO); - - string client_hello_str((string( - client_hello.GetSerialized(Perspective::IS_CLIENT).AsStringPiece()))); - MakePacket( - new QuicStreamFrame(kCryptoStreamId + 1, false, 0, client_hello_str)); - EXPECT_FALSE( - ChloExtractor::Extract(*packet_, AllSupportedVersions(), {}, &delegate_)); -} - -TEST_F(ChloExtractorTest, DoesNotFindValidChloOnWrongOffset) { - CryptoHandshakeMessage client_hello; - client_hello.set_tag(kCHLO); - - string client_hello_str((string( - client_hello.GetSerialized(Perspective::IS_CLIENT).AsStringPiece()))); - MakePacket(new QuicStreamFrame(kCryptoStreamId, false, 1, client_hello_str)); - EXPECT_FALSE( - ChloExtractor::Extract(*packet_, AllSupportedVersions(), {}, &delegate_)); -} - -TEST_F(ChloExtractorTest, DoesNotFindInvalidChlo) { - MakePacket(new QuicStreamFrame(kCryptoStreamId, false, 0, "foo")); - EXPECT_FALSE( - ChloExtractor::Extract(*packet_, AllSupportedVersions(), {}, &delegate_)); -} - -} // namespace -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/crypto_message_printer_bin.cc b/chromium/net/tools/quic/crypto_message_printer_bin.cc index 260175441ef..dfb5db2e83f 100644 --- a/chromium/net/tools/quic/crypto_message_printer_bin.cc +++ b/chromium/net/tools/quic/crypto_message_printer_bin.cc @@ -10,8 +10,8 @@ #include <iostream> #include "base/command_line.h" -#include "net/quic/core/crypto/crypto_framer.h" -#include "net/quic/platform/api/quic_text_utils.h" +#include "net/third_party/quic/core/crypto/crypto_framer.h" +#include "net/third_party/quic/platform/api/quic_text_utils.h" using net::Perspective; using std::cerr; diff --git a/chromium/net/tools/quic/end_to_end_test.cc b/chromium/net/tools/quic/end_to_end_test.cc deleted file mode 100644 index d43f8c3ef02..00000000000 --- a/chromium/net/tools/quic/end_to_end_test.cc +++ /dev/null @@ -1,3116 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <sys/epoll.h> - -#include <cstdint> -#include <list> -#include <memory> -#include <ostream> -#include <utility> -#include <vector> - -#include "base/memory/singleton.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/platform_thread.h" -#include "base/time/time.h" -#include "net/base/ip_address.h" -#include "net/base/ip_endpoint.h" -#include "net/quic/core/crypto/aes_128_gcm_12_encrypter.h" -#include "net/quic/core/crypto/null_encrypter.h" -#include "net/quic/core/quic_framer.h" -#include "net/quic/core/quic_packet_creator.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/core/quic_server_id.h" -#include "net/quic/core/quic_session.h" -#include "net/quic/core/quic_spdy_client_session_base.h" -#include "net/quic/core/quic_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" -#include "net/quic/platform/api/quic_socket_address.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/platform/api/quic_test_loopback.h" -#include "net/quic/platform/api/quic_text_utils.h" -#include "net/quic/test_tools/crypto_test_utils.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_sent_packet_manager_peer.h" -#include "net/quic/test_tools/quic_session_peer.h" -#include "net/quic/test_tools/quic_spdy_session_peer.h" -#include "net/quic/test_tools/quic_stream_peer.h" -#include "net/quic/test_tools/quic_stream_sequencer_peer.h" -#include "net/quic/test_tools/quic_test_utils.h" -#include "net/test/gtest_util.h" -#include "net/tools/epoll_server/epoll_server.h" -#include "net/tools/quic/platform/impl/quic_socket_utils.h" -#include "net/tools/quic/quic_epoll_connection_helper.h" -#include "net/tools/quic/quic_http_response_cache.h" -#include "net/tools/quic/quic_packet_writer_wrapper.h" -#include "net/tools/quic/quic_server.h" -#include "net/tools/quic/quic_simple_server_stream.h" -#include "net/tools/quic/quic_spdy_client_stream.h" -#include "net/tools/quic/test_tools/bad_packet_writer.h" -#include "net/tools/quic/test_tools/packet_dropping_test_writer.h" -#include "net/tools/quic/test_tools/packet_reordering_writer.h" -#include "net/tools/quic/test_tools/quic_client_peer.h" -#include "net/tools/quic/test_tools/quic_dispatcher_peer.h" -#include "net/tools/quic/test_tools/quic_server_peer.h" -#include "net/tools/quic/test_tools/quic_test_client.h" -#include "net/tools/quic/test_tools/quic_test_server.h" -#include "net/tools/quic/test_tools/server_thread.h" -#include "testing/gtest/include/gtest/gtest.h" - -using base::IntToString; -using base::WaitableEvent; - -namespace net { -namespace test { -namespace { - -const char kFooResponseBody[] = "Artichoke hearts make me happy."; -const char kBarResponseBody[] = "Palm hearts are pretty delicious, also."; -const float kSessionToStreamRatio = 1.5; - -// Run all tests with the cross products of all versions. -struct TestParams { - TestParams(const ParsedQuicVersionVector& client_supported_versions, - const ParsedQuicVersionVector& server_supported_versions, - ParsedQuicVersion negotiated_version, - bool client_supports_stateless_rejects, - bool server_uses_stateless_rejects_if_peer_supported, - QuicTag congestion_control_tag, - bool disable_hpack_dynamic_table, - bool use_cheap_stateless_reject) - : client_supported_versions(client_supported_versions), - server_supported_versions(server_supported_versions), - negotiated_version(negotiated_version), - client_supports_stateless_rejects(client_supports_stateless_rejects), - server_uses_stateless_rejects_if_peer_supported( - server_uses_stateless_rejects_if_peer_supported), - congestion_control_tag(congestion_control_tag), - disable_hpack_dynamic_table(disable_hpack_dynamic_table), - use_cheap_stateless_reject(use_cheap_stateless_reject) {} - - friend std::ostream& operator<<(std::ostream& os, const TestParams& p) { - os << "{ server_supported_versions: " - << ParsedQuicVersionVectorToString(p.server_supported_versions); - os << " client_supported_versions: " - << ParsedQuicVersionVectorToString(p.client_supported_versions); - os << " negotiated_version: " - << ParsedQuicVersionToString(p.negotiated_version); - os << " client_supports_stateless_rejects: " - << p.client_supports_stateless_rejects; - os << " server_uses_stateless_rejects_if_peer_supported: " - << p.server_uses_stateless_rejects_if_peer_supported; - os << " congestion_control_tag: " - << QuicTagToString(p.congestion_control_tag); - os << " disable_hpack_dynamic_table: " << p.disable_hpack_dynamic_table; - os << " use_cheap_stateless_reject: " << p.use_cheap_stateless_reject - << " }"; - return os; - } - - ParsedQuicVersionVector client_supported_versions; - ParsedQuicVersionVector server_supported_versions; - ParsedQuicVersion negotiated_version; - bool client_supports_stateless_rejects; - bool server_uses_stateless_rejects_if_peer_supported; - QuicTag congestion_control_tag; - bool disable_hpack_dynamic_table; - bool use_cheap_stateless_reject; -}; - -// Constructs various test permutations. -std::vector<TestParams> GetTestParams(bool use_tls_handshake) { - // Divide the versions into buckets in which the intra-frame format - // is compatible. When clients encounter QUIC version negotiation - // they simply retransmit all packets using the new version's - // QUIC framing. However, they are unable to change the intra-frame - // layout (for example to change HTTP/2 headers to SPDY/3, or a change in the - // handshake protocol). So these tests need to ensure that clients are never - // attempting to do 0-RTT across incompatible versions. Chromium only - // supports a single version at a time anyway. :) - FLAGS_quic_supports_tls_handshake = use_tls_handshake; - ParsedQuicVersionVector all_supported_versions = AllSupportedVersions(); - // Buckets are separated by the handshake protocol (QUIC crypto or TLS) in - // use, since if the handshake protocol changes, the ClientHello/CHLO must be - // reconstructed for the correct protocol. - ParsedQuicVersionVector version_buckets[2]; - - for (const ParsedQuicVersion& version : all_supported_versions) { - // Versions: 35+ - // QUIC_VERSION_35 allows endpoints to independently set stream limit. - if (version.handshake_protocol == PROTOCOL_TLS1_3) { - version_buckets[1].push_back(version); - } else { - version_buckets[0].push_back(version); - } - } - - // This must be kept in sync with the number of nested for-loops below as it - // is used to prune the number of tests that are run. - const int kMaxEnabledOptions = 4; - int max_enabled_options = 0; - std::vector<TestParams> params; - for (bool server_uses_stateless_rejects_if_peer_supported : {true, false}) { - for (bool client_supports_stateless_rejects : {true, false}) { - for (const QuicTag congestion_control_tag : - {kRENO, kTBBR, kQBIC, kTPCC}) { - for (bool disable_hpack_dynamic_table : {false}) { - for (bool use_cheap_stateless_reject : {true, false}) { - int enabled_options = 0; - if (congestion_control_tag != kQBIC) { - ++enabled_options; - } - if (disable_hpack_dynamic_table) { - ++enabled_options; - } - if (client_supports_stateless_rejects) { - ++enabled_options; - } - if (server_uses_stateless_rejects_if_peer_supported) { - ++enabled_options; - } - if (use_cheap_stateless_reject) { - ++enabled_options; - } - CHECK_GE(kMaxEnabledOptions, enabled_options); - if (enabled_options > max_enabled_options) { - max_enabled_options = enabled_options; - } - - // Run tests with no options, a single option, or all the - // options enabled to avoid a combinatorial explosion. - if (enabled_options > 1 && enabled_options < kMaxEnabledOptions) { - continue; - } - - for (const ParsedQuicVersionVector& client_versions : - version_buckets) { - if (FilterSupportedVersions(client_versions).empty()) { - continue; - } - // Add an entry for server and client supporting all - // versions. - params.push_back(TestParams( - client_versions, all_supported_versions, - client_versions.front(), client_supports_stateless_rejects, - server_uses_stateless_rejects_if_peer_supported, - congestion_control_tag, disable_hpack_dynamic_table, - use_cheap_stateless_reject)); - - // Run version negotiation tests tests with no options, or - // all the options enabled to avoid a combinatorial - // explosion. - if (enabled_options > 1 && enabled_options < kMaxEnabledOptions) { - continue; - } - - // Test client supporting all versions and server supporting - // 1 version. Simulate an old server and exercise version - // downgrade in the client. Protocol negotiation should - // occur. Skip the i = 0 case because it is essentially the - // same as the default case. - for (size_t i = 1; i < client_versions.size(); ++i) { - ParsedQuicVersionVector server_supported_versions; - server_supported_versions.push_back(client_versions[i]); - if (FilterSupportedVersions(server_supported_versions) - .empty()) { - continue; - } - params.push_back(TestParams( - client_versions, server_supported_versions, - server_supported_versions.front(), - client_supports_stateless_rejects, - server_uses_stateless_rejects_if_peer_supported, - congestion_control_tag, disable_hpack_dynamic_table, - use_cheap_stateless_reject)); - } // End of version for loop. - } // End of 2nd version for loop. - } // End of use_cheap_stateless_reject for loop. - } // End of disable_hpack_dynamic_table for loop. - } // End of congestion_control_tag for loop. - } // End of client_supports_stateless_rejects for loop. - CHECK_EQ(kMaxEnabledOptions, max_enabled_options); - } // End of server_uses_stateless_rejects_if_peer_supported for loop. - return params; -} - -class ServerDelegate : public PacketDroppingTestWriter::Delegate { - public: - explicit ServerDelegate(QuicDispatcher* dispatcher) - : dispatcher_(dispatcher) {} - ~ServerDelegate() override = default; - void OnCanWrite() override { dispatcher_->OnCanWrite(); } - - private: - QuicDispatcher* dispatcher_; -}; - -class ClientDelegate : public PacketDroppingTestWriter::Delegate { - public: - explicit ClientDelegate(QuicClient* client) : client_(client) {} - ~ClientDelegate() override = default; - void OnCanWrite() override { - EpollEvent event(EPOLLOUT); - client_->epoll_network_helper()->OnEvent(client_->GetLatestFD(), &event); - } - - private: - QuicClient* client_; -}; - -class EndToEndTest : public QuicTestWithParam<TestParams> { - protected: - EndToEndTest() - : initialized_(false), - server_address_(QuicSocketAddress(TestLoopback(), 0)), - server_hostname_("test.example.com"), - client_writer_(nullptr), - server_writer_(nullptr), - server_started_(false), - negotiated_version_(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), - chlo_multiplier_(0), - stream_factory_(nullptr), - support_server_push_(false) { - FLAGS_quic_supports_tls_handshake = true; - FLAGS_quic_reloadable_flag_quic_store_version_before_signalling = true; - client_supported_versions_ = GetParam().client_supported_versions; - server_supported_versions_ = GetParam().server_supported_versions; - negotiated_version_ = GetParam().negotiated_version; - - QUIC_LOG(INFO) << "Using Configuration: " << GetParam(); - - // Use different flow control windows for client/server. - client_config_.SetInitialStreamFlowControlWindowToSend( - 2 * kInitialStreamFlowControlWindowForTest); - client_config_.SetInitialSessionFlowControlWindowToSend( - 2 * kInitialSessionFlowControlWindowForTest); - server_config_.SetInitialStreamFlowControlWindowToSend( - 3 * kInitialStreamFlowControlWindowForTest); - server_config_.SetInitialSessionFlowControlWindowToSend( - 3 * kInitialSessionFlowControlWindowForTest); - - // The default idle timeouts can be too strict when running on a busy - // machine. - const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(30); - client_config_.set_max_time_before_crypto_handshake(timeout); - client_config_.set_max_idle_time_before_crypto_handshake(timeout); - server_config_.set_max_time_before_crypto_handshake(timeout); - server_config_.set_max_idle_time_before_crypto_handshake(timeout); - - AddToCache("/foo", 200, kFooResponseBody); - AddToCache("/bar", 200, kBarResponseBody); - } - - ~EndToEndTest() override { - // TODO(rtenneti): port RecycleUnusedPort if needed. - // RecycleUnusedPort(server_address_.port()); - } - - virtual void CreateClientWithWriter() { - client_.reset(CreateQuicClient(client_writer_)); - } - - QuicTestClient* CreateQuicClient(QuicPacketWriterWrapper* writer) { - QuicTestClient* client = - new QuicTestClient(server_address_, server_hostname_, client_config_, - client_supported_versions_, - crypto_test_utils::ProofVerifierForTesting()); - client->UseWriter(writer); - client->Connect(); - return client; - } - - void set_smaller_flow_control_receive_window() { - const uint32_t kClientIFCW = 64 * 1024; - const uint32_t kServerIFCW = 1024 * 1024; - set_client_initial_stream_flow_control_receive_window(kClientIFCW); - set_client_initial_session_flow_control_receive_window( - kSessionToStreamRatio * kClientIFCW); - set_server_initial_stream_flow_control_receive_window(kServerIFCW); - set_server_initial_session_flow_control_receive_window( - kSessionToStreamRatio * kServerIFCW); - } - - void set_client_initial_stream_flow_control_receive_window(uint32_t window) { - CHECK(client_ == nullptr); - QUIC_DLOG(INFO) << "Setting client initial stream flow control window: " - << window; - client_config_.SetInitialStreamFlowControlWindowToSend(window); - } - - void set_client_initial_session_flow_control_receive_window(uint32_t window) { - CHECK(client_ == nullptr); - QUIC_DLOG(INFO) << "Setting client initial session flow control window: " - << window; - client_config_.SetInitialSessionFlowControlWindowToSend(window); - } - - void set_server_initial_stream_flow_control_receive_window(uint32_t window) { - CHECK(server_thread_ == nullptr); - QUIC_DLOG(INFO) << "Setting server initial stream flow control window: " - << window; - server_config_.SetInitialStreamFlowControlWindowToSend(window); - } - - void set_server_initial_session_flow_control_receive_window(uint32_t window) { - CHECK(server_thread_ == nullptr); - QUIC_DLOG(INFO) << "Setting server initial session flow control window: " - << window; - server_config_.SetInitialSessionFlowControlWindowToSend(window); - } - - const QuicSentPacketManager* GetSentPacketManagerFromFirstServerSession() - const { - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - QuicSession* session = dispatcher->session_map().begin()->second.get(); - return &session->connection()->sent_packet_manager(); - } - - bool Initialize() { - QuicTagVector copt; - server_config_.SetConnectionOptionsToSend(copt); - copt = client_extra_copts_; - - // TODO(nimia): Consider setting the congestion control algorithm for the - // client as well according to the test parameter. - copt.push_back(GetParam().congestion_control_tag); - if (GetParam().congestion_control_tag == kTPCC && - GetQuicReloadableFlag(quic_enable_pcc)) { - copt.push_back(kTPCC); - } - - if (support_server_push_) { - copt.push_back(kSPSH); - } - if (GetParam().client_supports_stateless_rejects) { - copt.push_back(kSREJ); - } - if (GetParam().disable_hpack_dynamic_table) { - copt.push_back(kDHDT); - } - client_config_.SetConnectionOptionsToSend(copt); - - // Start the server first, because CreateQuicClient() attempts - // to connect to the server. - StartServer(); - - CreateClientWithWriter(); - static EpollEvent event(EPOLLOUT); - if (client_writer_ != nullptr) { - client_writer_->Initialize( - QuicConnectionPeer::GetHelper( - client_->client()->client_session()->connection()), - QuicConnectionPeer::GetAlarmFactory( - client_->client()->client_session()->connection()), - new ClientDelegate(client_->client())); - } - initialized_ = true; - return client_->client()->connected(); - } - - void SetUp() override { - // The ownership of these gets transferred to the QuicPacketWriterWrapper - // when Initialize() is executed. - client_writer_ = new PacketDroppingTestWriter(); - server_writer_ = new PacketDroppingTestWriter(); - } - - void TearDown() override { - ASSERT_TRUE(initialized_) << "You must call Initialize() in every test " - << "case. Otherwise, your test will leak memory."; - StopServer(); - } - - void StartServer() { - SetQuicReloadableFlag(quic_use_cheap_stateless_rejects, - GetParam().use_cheap_stateless_reject); - - auto* test_server = new QuicTestServer( - crypto_test_utils::ProofSourceForTesting(), server_config_, - server_supported_versions_, &response_cache_); - server_thread_ = QuicMakeUnique<ServerThread>(test_server, server_address_); - if (chlo_multiplier_ != 0) { - server_thread_->server()->SetChloMultiplier(chlo_multiplier_); - } - server_thread_->Initialize(); - server_address_ = - QuicSocketAddress(server_address_.host(), server_thread_->GetPort()); - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - QuicDispatcherPeer::UseWriter(dispatcher, server_writer_); - - SetQuicReloadableFlag( - enable_quic_stateless_reject_support, - GetParam().server_uses_stateless_rejects_if_peer_supported); - - server_writer_->Initialize(QuicDispatcherPeer::GetHelper(dispatcher), - QuicDispatcherPeer::GetAlarmFactory(dispatcher), - new ServerDelegate(dispatcher)); - if (stream_factory_ != nullptr) { - static_cast<QuicTestServer*>(server_thread_->server()) - ->SetSpdyStreamFactory(stream_factory_); - } - - server_thread_->Start(); - server_started_ = true; - } - - void StopServer() { - if (!server_started_) - return; - if (server_thread_) { - server_thread_->Quit(); - server_thread_->Join(); - } - } - - void AddToCache(QuicStringPiece path, - int response_code, - QuicStringPiece body) { - response_cache_.AddSimpleResponse(server_hostname_, path, response_code, - body); - } - - void SetPacketLossPercentage(int32_t loss) { - // TODO(rtenneti): enable when we can do random packet loss tests in - // chrome's tree. - if (loss != 0 && loss != 100) - return; - client_writer_->set_fake_packet_loss_percentage(loss); - server_writer_->set_fake_packet_loss_percentage(loss); - } - - void SetPacketSendDelay(QuicTime::Delta delay) { - // TODO(rtenneti): enable when we can do random packet send delay tests in - // chrome's tree. - // client_writer_->set_fake_packet_delay(delay); - // server_writer_->set_fake_packet_delay(delay); - } - - void SetReorderPercentage(int32_t reorder) { - // TODO(rtenneti): enable when we can do random packet reorder tests in - // chrome's tree. - // client_writer_->set_fake_reorder_percentage(reorder); - // server_writer_->set_fake_reorder_percentage(reorder); - } - - // Verifies that the client and server connections were both free of packets - // being discarded, based on connection stats. - // Calls server_thread_ Pause() and Resume(), which may only be called once - // per test. - void VerifyCleanConnection(bool had_packet_loss) { - QuicConnectionStats client_stats = - client_->client()->client_session()->connection()->GetStats(); - // TODO(ianswett): Determine why this becomes even more flaky with BBR - // enabled. b/62141144 - if (!had_packet_loss && !GetQuicReloadableFlag(quic_default_to_bbr)) { - EXPECT_EQ(0u, client_stats.packets_lost); - } - EXPECT_EQ(0u, client_stats.packets_discarded); - // When doing 0-RTT with stateless rejects, the encrypted requests cause - // a retranmission of the SREJ packets which are dropped by the client. - if (!BothSidesSupportStatelessRejects()) { - EXPECT_EQ(0u, client_stats.packets_dropped); - } - EXPECT_EQ(client_stats.packets_received, client_stats.packets_processed); - - const int num_expected_stateless_rejects = - (BothSidesSupportStatelessRejects() && - client_->client()->client_session()->GetNumSentClientHellos() > 0) - ? 1 - : 0; - EXPECT_EQ(num_expected_stateless_rejects, - client_->client()->num_stateless_rejects_received()); - - server_thread_->Pause(); - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - ASSERT_EQ(1u, dispatcher->session_map().size()); - QuicSession* session = dispatcher->session_map().begin()->second.get(); - QuicConnectionStats server_stats = session->connection()->GetStats(); - if (!had_packet_loss) { - EXPECT_EQ(0u, server_stats.packets_lost); - } - EXPECT_EQ(0u, server_stats.packets_discarded); - // TODO(ianswett): Restore the check for packets_dropped equals 0. - // The expect for packets received is equal to packets processed fails - // due to version negotiation packets. - server_thread_->Resume(); - } - - bool BothSidesSupportStatelessRejects() { - return (GetParam().server_uses_stateless_rejects_if_peer_supported && - GetParam().client_supports_stateless_rejects); - } - - void ExpectFlowControlsSynced(QuicFlowController* client, - QuicFlowController* server) { - EXPECT_EQ(QuicFlowControllerPeer::SendWindowSize(client), - QuicFlowControllerPeer::ReceiveWindowSize(server)); - EXPECT_EQ(QuicFlowControllerPeer::ReceiveWindowSize(client), - QuicFlowControllerPeer::SendWindowSize(server)); - } - - // Must be called before Initialize to have effect. - void SetSpdyStreamFactory(QuicTestServer::StreamFactory* factory) { - stream_factory_ = factory; - } - - QuicStreamId GetNthClientInitiatedId(int n) { - return QuicSpdySessionPeer::GetNthClientInitiatedStreamId( - *client_->client()->client_session(), n); - } - - QuicStreamId GetNthServerInitiatedId(int n) { - return QuicSpdySessionPeer::GetNthServerInitiatedStreamId( - *client_->client()->client_session(), n); - } - - bool initialized_; - QuicSocketAddress server_address_; - QuicString server_hostname_; - QuicHttpResponseCache response_cache_; - std::unique_ptr<ServerThread> server_thread_; - std::unique_ptr<QuicTestClient> client_; - PacketDroppingTestWriter* client_writer_; - PacketDroppingTestWriter* server_writer_; - bool server_started_; - QuicConfig client_config_; - QuicConfig server_config_; - ParsedQuicVersionVector client_supported_versions_; - ParsedQuicVersionVector server_supported_versions_; - QuicTagVector client_extra_copts_; - ParsedQuicVersion negotiated_version_; - size_t chlo_multiplier_; - QuicTestServer::StreamFactory* stream_factory_; - bool support_server_push_; -}; - -class EndToEndTestWithTls : public EndToEndTest { - protected: - EndToEndTestWithTls() : EndToEndTest() { - FLAGS_quic_reloadable_flag_delay_quic_server_handshaker_construction = true; - SetQuicReloadableFlag(quic_server_early_version_negotiation, true); - } -}; - -// Run all end to end tests with all supported versions. -INSTANTIATE_TEST_CASE_P(EndToEndTests, - EndToEndTest, - ::testing::ValuesIn(GetTestParams(false))); - -INSTANTIATE_TEST_CASE_P(EndToEndTestsWithTls, - EndToEndTestWithTls, - ::testing::ValuesIn(GetTestParams(true))); - -TEST_P(EndToEndTestWithTls, HandshakeSuccessful) { - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - server_thread_->WaitForCryptoHandshakeConfirmed(); - QuicCryptoStream* crypto_stream = QuicSessionPeer::GetMutableCryptoStream( - client_->client()->client_session()); - QuicStreamSequencer* sequencer = QuicStreamPeer::sequencer(crypto_stream); - EXPECT_FALSE(QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer)); - server_thread_->Pause(); - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - QuicSession* server_session = dispatcher->session_map().begin()->second.get(); - crypto_stream = QuicSessionPeer::GetMutableCryptoStream(server_session); - sequencer = QuicStreamPeer::sequencer(crypto_stream); - EXPECT_FALSE(QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer)); -} - -TEST_P(EndToEndTest, SimpleRequestResponse) { - ASSERT_TRUE(Initialize()); - - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); -} - -TEST_P(EndToEndTest, SimpleRequestResponseWithLargeReject) { - chlo_multiplier_ = 1; - ASSERT_TRUE(Initialize()); - - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - EXPECT_EQ(3, client_->client()->GetNumSentClientHellos()); -} - -TEST_P(EndToEndTestWithTls, SimpleRequestResponsev6) { - server_address_ = - QuicSocketAddress(QuicIpAddress::Loopback6(), server_address_.port()); - ASSERT_TRUE(Initialize()); - - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); -} - -TEST_P(EndToEndTestWithTls, SeparateFinPacket) { - ASSERT_TRUE(Initialize()); - - // Send a request in two parts: the request and then an empty packet with FIN. - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - client_->SendMessage(headers, "", /*fin=*/false); - client_->SendData("", true); - client_->WaitForResponse(); - EXPECT_EQ(kFooResponseBody, client_->response_body()); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - - // Now do the same thing but with a content length. - headers["content-length"] = "3"; - client_->SendMessage(headers, "", /*fin=*/false); - client_->SendData("foo", true); - client_->WaitForResponse(); - EXPECT_EQ(kFooResponseBody, client_->response_body()); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); -} - -TEST_P(EndToEndTestWithTls, MultipleRequestResponse) { - ASSERT_TRUE(Initialize()); - - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); -} - -TEST_P(EndToEndTestWithTls, MultipleStreams) { - // Verifies quic_test_client can track responses of all active streams. - ASSERT_TRUE(Initialize()); - - const int kNumRequests = 10; - - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - headers["content-length"] = "3"; - - for (int i = 0; i < kNumRequests; ++i) { - client_->SendMessage(headers, "bar", /*fin=*/true); - } - - while (kNumRequests > client_->num_responses()) { - client_->ClearPerRequestState(); - client_->WaitForResponse(); - EXPECT_EQ(kFooResponseBody, client_->response_body()); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - } -} - -TEST_P(EndToEndTestWithTls, MultipleClients) { - ASSERT_TRUE(Initialize()); - std::unique_ptr<QuicTestClient> client2(CreateQuicClient(nullptr)); - - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - headers["content-length"] = "3"; - - client_->SendMessage(headers, "", /*fin=*/false); - client2->SendMessage(headers, "", /*fin=*/false); - - client_->SendData("bar", true); - client_->WaitForResponse(); - EXPECT_EQ(kFooResponseBody, client_->response_body()); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - - client2->SendData("eep", true); - client2->WaitForResponse(); - EXPECT_EQ(kFooResponseBody, client2->response_body()); - EXPECT_EQ("200", client2->response_headers()->find(":status")->second); -} - -TEST_P(EndToEndTestWithTls, RequestOverMultiplePackets) { - // Send a large enough request to guarantee fragmentation. - QuicString huge_request = - "/some/path?query=" + QuicString(kMaxPacketSize, '.'); - AddToCache(huge_request, 200, kBarResponseBody); - - ASSERT_TRUE(Initialize()); - - EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest(huge_request)); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); -} - -TEST_P(EndToEndTestWithTls, MultiplePacketsRandomOrder) { - // Send a large enough request to guarantee fragmentation. - QuicString huge_request = - "/some/path?query=" + QuicString(kMaxPacketSize, '.'); - AddToCache(huge_request, 200, kBarResponseBody); - - ASSERT_TRUE(Initialize()); - SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2)); - SetReorderPercentage(50); - - EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest(huge_request)); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); -} - -TEST_P(EndToEndTestWithTls, PostMissingBytes) { - ASSERT_TRUE(Initialize()); - - // Add a content length header with no body. - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - headers["content-length"] = "3"; - - // This should be detected as stream fin without complete request, - // triggering an error response. - client_->SendCustomSynchronousRequest(headers, ""); - EXPECT_EQ(QuicSimpleServerStream::kErrorResponseBody, - client_->response_body()); - EXPECT_EQ("500", client_->response_headers()->find(":status")->second); -} - -TEST_P(EndToEndTest, LargePostNoPacketLoss) { - ASSERT_TRUE(Initialize()); - - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - // 1 MB body. - QuicString body(1024 * 1024, 'a'); - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - - EXPECT_EQ(kFooResponseBody, - client_->SendCustomSynchronousRequest(headers, body)); - // TODO(ianswett): There should not be packet loss in this test, but on some - // platforms the receive buffer overflows. - VerifyCleanConnection(true); -} - -TEST_P(EndToEndTest, LargePostNoPacketLoss1sRTT) { - ASSERT_TRUE(Initialize()); - SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(1000)); - - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - // 100 KB body. - QuicString body(100 * 1024, 'a'); - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - - EXPECT_EQ(kFooResponseBody, - client_->SendCustomSynchronousRequest(headers, body)); - VerifyCleanConnection(false); -} - -TEST_P(EndToEndTest, LargePostWithPacketLoss) { - if (!BothSidesSupportStatelessRejects()) { - // Connect with lower fake packet loss than we'd like to test. - // Until b/10126687 is fixed, losing handshake packets is pretty - // brutal. - // TODO(jokulik): Until we support redundant SREJ packets, don't - // drop handshake packets for stateless rejects. - SetPacketLossPercentage(5); - } - ASSERT_TRUE(Initialize()); - - // Wait for the server SHLO before upping the packet loss. - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - SetPacketLossPercentage(30); - - // 10 KB body. - QuicString body(1024 * 10, 'a'); - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - - EXPECT_EQ(kFooResponseBody, - client_->SendCustomSynchronousRequest(headers, body)); - VerifyCleanConnection(true); -} - -TEST_P(EndToEndTest, LargePostWithPacketLossAndBlockedSocket) { - if (!BothSidesSupportStatelessRejects()) { - // Connect with lower fake packet loss than we'd like to test. Until - // b/10126687 is fixed, losing handshake packets is pretty brutal. - // TODO(jokulik): Until we support redundant SREJ packets, don't - // drop handshake packets for stateless rejects. - SetPacketLossPercentage(5); - } - ASSERT_TRUE(Initialize()); - - // Wait for the server SHLO before upping the packet loss. - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - SetPacketLossPercentage(10); - client_writer_->set_fake_blocked_socket_percentage(10); - - // 10 KB body. - QuicString body(1024 * 10, 'a'); - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - - EXPECT_EQ(kFooResponseBody, - client_->SendCustomSynchronousRequest(headers, body)); -} - -TEST_P(EndToEndTest, LargePostNoPacketLossWithDelayAndReordering) { - ASSERT_TRUE(Initialize()); - - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - // Both of these must be called when the writer is not actively used. - SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2)); - SetReorderPercentage(30); - - // 1 MB body. - QuicString body(1024 * 1024, 'a'); - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - - EXPECT_EQ(kFooResponseBody, - client_->SendCustomSynchronousRequest(headers, body)); -} - -TEST_P(EndToEndTest, LargePostZeroRTTFailure) { - // Send a request and then disconnect. This prepares the client to attempt - // a 0-RTT handshake for the next request. - ASSERT_TRUE(Initialize()); - - QuicString body(20480, 'a'); - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - - EXPECT_EQ(kFooResponseBody, - client_->SendCustomSynchronousRequest(headers, body)); - // In the non-stateless case, the same session is used for both - // hellos, so the number of hellos sent on that session is 2. In - // the stateless case, the first client session will be completely - // torn down after the reject. The number of hellos on the latest - // session is 1. - const int expected_num_hellos_latest_session = - BothSidesSupportStatelessRejects() ? 1 : 2; - EXPECT_EQ(expected_num_hellos_latest_session, - client_->client()->client_session()->GetNumSentClientHellos()); - EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); - - client_->Disconnect(); - - // The 0-RTT handshake should succeed. - client_->Connect(); - client_->WaitForInitialResponse(); - ASSERT_TRUE(client_->client()->connected()); - EXPECT_EQ(kFooResponseBody, - client_->SendCustomSynchronousRequest(headers, body)); - - EXPECT_EQ(1, client_->client()->client_session()->GetNumSentClientHellos()); - EXPECT_EQ(1, client_->client()->GetNumSentClientHellos()); - - client_->Disconnect(); - - // Restart the server so that the 0-RTT handshake will take 1 RTT. - StopServer(); - server_writer_ = new PacketDroppingTestWriter(); - StartServer(); - - client_->Connect(); - ASSERT_TRUE(client_->client()->connected()); - EXPECT_EQ(kFooResponseBody, - client_->SendCustomSynchronousRequest(headers, body)); - // In the non-stateless case, the same session is used for both - // hellos, so the number of hellos sent on that session is 2. In - // the stateless case, the first client session will be completely - // torn down after the reject. The number of hellos sent on the - // latest session is 1. - EXPECT_EQ(expected_num_hellos_latest_session, - client_->client()->client_session()->GetNumSentClientHellos()); - EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); - - VerifyCleanConnection(false); -} - -TEST_P(EndToEndTest, SynchronousRequestZeroRTTFailure) { - // Send a request and then disconnect. This prepares the client to attempt - // a 0-RTT handshake for the next request. - ASSERT_TRUE(Initialize()); - - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - // In the non-stateless case, the same session is used for both - // hellos, so the number of hellos sent on that session is 2. In - // the stateless case, the first client session will be completely - // torn down after the reject. The number of hellos on that second - // latest session is 1. - const int expected_num_hellos_latest_session = - BothSidesSupportStatelessRejects() ? 1 : 2; - EXPECT_EQ(expected_num_hellos_latest_session, - client_->client()->client_session()->GetNumSentClientHellos()); - EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); - - client_->Disconnect(); - - // The 0-RTT handshake should succeed. - client_->Connect(); - client_->WaitForInitialResponse(); - ASSERT_TRUE(client_->client()->connected()); - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - - EXPECT_EQ(1, client_->client()->client_session()->GetNumSentClientHellos()); - EXPECT_EQ(1, client_->client()->GetNumSentClientHellos()); - - client_->Disconnect(); - - // Restart the server so that the 0-RTT handshake will take 1 RTT. - StopServer(); - server_writer_ = new PacketDroppingTestWriter(); - StartServer(); - - client_->Connect(); - ASSERT_TRUE(client_->client()->connected()); - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - // In the non-stateless case, the same session is used for both - // hellos, so the number of hellos sent on that session is 2. In - // the stateless case, the first client session will be completely - // torn down after the reject. The number of hellos sent on the - // latest session is 1. - EXPECT_EQ(expected_num_hellos_latest_session, - client_->client()->client_session()->GetNumSentClientHellos()); - EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); - - VerifyCleanConnection(false); -} - -TEST_P(EndToEndTest, LargePostSynchronousRequest) { - // Send a request and then disconnect. This prepares the client to attempt - // a 0-RTT handshake for the next request. - ASSERT_TRUE(Initialize()); - - QuicString body(20480, 'a'); - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - - EXPECT_EQ(kFooResponseBody, - client_->SendCustomSynchronousRequest(headers, body)); - // In the non-stateless case, the same session is used for both - // hellos, so the number of hellos sent on that session is 2. In - // the stateless case, the first client session will be completely - // torn down after the reject. The number of hellos on the latest - // session is 1. - const int expected_num_hellos_latest_session = - BothSidesSupportStatelessRejects() ? 1 : 2; - EXPECT_EQ(expected_num_hellos_latest_session, - client_->client()->client_session()->GetNumSentClientHellos()); - EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); - - client_->Disconnect(); - - // The 0-RTT handshake should succeed. - client_->Connect(); - client_->WaitForInitialResponse(); - ASSERT_TRUE(client_->client()->connected()); - EXPECT_EQ(kFooResponseBody, - client_->SendCustomSynchronousRequest(headers, body)); - - EXPECT_EQ(1, client_->client()->client_session()->GetNumSentClientHellos()); - EXPECT_EQ(1, client_->client()->GetNumSentClientHellos()); - - client_->Disconnect(); - - // Restart the server so that the 0-RTT handshake will take 1 RTT. - StopServer(); - server_writer_ = new PacketDroppingTestWriter(); - StartServer(); - - client_->Connect(); - ASSERT_TRUE(client_->client()->connected()); - EXPECT_EQ(kFooResponseBody, - client_->SendCustomSynchronousRequest(headers, body)); - // In the non-stateless case, the same session is used for both - // hellos, so the number of hellos sent on that session is 2. In - // the stateless case, the first client session will be completely - // torn down after the reject. The number of hellos sent on the - // latest session is 1. - EXPECT_EQ(expected_num_hellos_latest_session, - client_->client()->client_session()->GetNumSentClientHellos()); - EXPECT_EQ(2, client_->client()->GetNumSentClientHellos()); - - VerifyCleanConnection(false); -} - -TEST_P(EndToEndTest, StatelessRejectWithPacketLoss) { - // In this test, we intentionally drop the first packet from the - // server, which corresponds with the initial REJ/SREJ response from - // the server. - server_writer_->set_fake_drop_first_n_packets(1); - ASSERT_TRUE(Initialize()); -} - -TEST_P(EndToEndTest, SetInitialReceivedConnectionOptions) { - QuicTagVector initial_received_options; - initial_received_options.push_back(kTBBR); - initial_received_options.push_back(kIW10); - initial_received_options.push_back(kPRST); - EXPECT_TRUE(server_config_.SetInitialReceivedConnectionOptions( - initial_received_options)); - - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - server_thread_->WaitForCryptoHandshakeConfirmed(); - - EXPECT_FALSE(server_config_.SetInitialReceivedConnectionOptions( - initial_received_options)); - - // Verify that server's configuration is correct. - server_thread_->Pause(); - EXPECT_TRUE(server_config_.HasReceivedConnectionOptions()); - EXPECT_TRUE( - ContainsQuicTag(server_config_.ReceivedConnectionOptions(), kTBBR)); - EXPECT_TRUE( - ContainsQuicTag(server_config_.ReceivedConnectionOptions(), kIW10)); - EXPECT_TRUE( - ContainsQuicTag(server_config_.ReceivedConnectionOptions(), kPRST)); -} - -TEST_P(EndToEndTest, LargePostSmallBandwidthLargeBuffer) { - ASSERT_TRUE(Initialize()); - SetPacketSendDelay(QuicTime::Delta::FromMicroseconds(1)); - // 256KB per second with a 256KB buffer from server to client. Wireless - // clients commonly have larger buffers, but our max CWND is 200. - server_writer_->set_max_bandwidth_and_buffer_size( - QuicBandwidth::FromBytesPerSecond(256 * 1024), 256 * 1024); - - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - // 1 MB body. - QuicString body(1024 * 1024, 'a'); - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - - EXPECT_EQ(kFooResponseBody, - client_->SendCustomSynchronousRequest(headers, body)); - // This connection may drop packets, because the buffer is smaller than the - // max CWND. - VerifyCleanConnection(true); -} - -TEST_P(EndToEndTestWithTls, - DoNotSetResumeWriteAlarmIfConnectionFlowControlBlocked) { - // Regression test for b/14677858. - // Test that the resume write alarm is not set in QuicConnection::OnCanWrite - // if currently connection level flow control blocked. If set, this results in - // an infinite loop in the EpollServer, as the alarm fires and is immediately - // rescheduled. - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - // Ensure both stream and connection level are flow control blocked by setting - // the send window offset to 0. - const uint64_t flow_control_window = - server_config_.GetInitialStreamFlowControlWindowToSend(); - QuicSpdyClientStream* stream = client_->GetOrCreateStream(); - QuicSession* session = client_->client()->client_session(); - QuicFlowControllerPeer::SetSendWindowOffset(stream->flow_controller(), 0); - QuicFlowControllerPeer::SetSendWindowOffset(session->flow_controller(), 0); - EXPECT_TRUE(stream->flow_controller()->IsBlocked()); - EXPECT_TRUE(session->flow_controller()->IsBlocked()); - - // Make sure that the stream has data pending so that it will be marked as - // write blocked when it receives a stream level WINDOW_UPDATE. - stream->WriteOrBufferBody("hello", false, nullptr); - - // The stream now attempts to write, fails because it is still connection - // level flow control blocked, and is added to the write blocked list. - QuicWindowUpdateFrame window_update(kInvalidControlFrameId, stream->id(), - 2 * flow_control_window); - stream->OnWindowUpdateFrame(window_update); - - // Prior to fixing b/14677858 this call would result in an infinite loop in - // Chromium. As a proxy for detecting this, we now check whether the - // resume_writes_alarm is set after OnCanWrite. It should not be, as the - // connection is still flow control blocked. - session->connection()->OnCanWrite(); - - QuicAlarm* resume_writes_alarm = - QuicConnectionPeer::GetResumeWritesAlarm(session->connection()); - EXPECT_FALSE(resume_writes_alarm->IsSet()); -} - -// TODO(fkastenholz): this test seems to cause net_unittests timeouts -// reverted from EndToEndTestWithTls to EndToEndTest -TEST_P(EndToEndTest, InvalidStream) { - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - QuicString body(kMaxPacketSize, 'a'); - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - - // Force the client to write with a stream ID belonging to a nonexistent - // server-side stream. - QuicSpdySession* session = client_->client()->client_session(); - QuicSessionPeer::SetNextOutgoingStreamId(session, GetNthServerInitiatedId(0)); - - client_->SendCustomSynchronousRequest(headers, body); - EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error()); - EXPECT_EQ(QUIC_INVALID_STREAM_ID, client_->connection_error()); -} - -// Test that if the server will close the connection if the client attempts -// to send a request with overly large headers. -TEST_P(EndToEndTest, LargeHeaders) { - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - QuicString body(kMaxPacketSize, 'a'); - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - headers["key1"] = QuicString(15 * 1024, 'a'); - headers["key2"] = QuicString(15 * 1024, 'a'); - headers["key3"] = QuicString(15 * 1024, 'a'); - - client_->SendCustomSynchronousRequest(headers, body); - EXPECT_EQ(QUIC_HEADERS_TOO_LARGE, client_->stream_error()); - EXPECT_EQ(QUIC_NO_ERROR, client_->connection_error()); -} - -TEST_P(EndToEndTest, EarlyResponseWithQuicStreamNoError) { - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - QuicString large_body(1024 * 1024, 'a'); - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - // Insert an invalid content_length field in request to trigger an early - // response from server. - headers["content-length"] = "-3"; - - client_->SendCustomSynchronousRequest(headers, large_body); - EXPECT_EQ("bad", client_->response_body()); - EXPECT_EQ("500", client_->response_headers()->find(":status")->second); - EXPECT_EQ(QUIC_STREAM_NO_ERROR, client_->stream_error()); - EXPECT_EQ(QUIC_NO_ERROR, client_->connection_error()); -} - -// TODO(rch): this test seems to cause net_unittests timeouts :| -TEST_P(EndToEndTestWithTls, DISABLED_MultipleTermination) { - ASSERT_TRUE(Initialize()); - - // Set the offset so we won't frame. Otherwise when we pick up termination - // before HTTP framing is complete, we send an error and close the stream, - // and the second write is picked up as writing on a closed stream. - QuicSpdyClientStream* stream = client_->GetOrCreateStream(); - ASSERT_TRUE(stream != nullptr); - QuicStreamPeer::SetStreamBytesWritten(3, stream); - - client_->SendData("bar", true); - client_->WaitForWriteToFlush(); - - // By default the stream protects itself from writes after terminte is set. - // Override this to test the server handling buggy clients. - QuicStreamPeer::SetWriteSideClosed(false, client_->GetOrCreateStream()); - - EXPECT_QUIC_BUG(client_->SendData("eep", true), "Fin already buffered"); -} - -// TODO(fkastenholz): this test seems to cause net_unittests timeouts -// reverted from EndToEndTestWithTls to EndToEndTest -TEST_P(EndToEndTest, Timeout) { - client_config_.SetIdleNetworkTimeout(QuicTime::Delta::FromMicroseconds(500), - QuicTime::Delta::FromMicroseconds(500)); - // Note: we do NOT ASSERT_TRUE: we may time out during initial handshake: - // that's enough to validate timeout in this case. - Initialize(); - while (client_->client()->connected()) { - client_->client()->WaitForEvents(); - } -} - -TEST_P(EndToEndTestWithTls, MaxIncomingDynamicStreamsLimitRespected) { - // Set a limit on maximum number of incoming dynamic streams. - // Make sure the limit is respected. - const uint32_t kServerMaxIncomingDynamicStreams = 1; - server_config_.SetMaxIncomingDynamicStreamsToSend( - kServerMaxIncomingDynamicStreams); - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - // Make the client misbehave after negotiation. - const int kServerMaxStreams = kMaxStreamsMinimumIncrement + 1; - QuicSessionPeer::SetMaxOpenOutgoingStreams( - client_->client()->client_session(), kServerMaxStreams + 1); - - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - headers["content-length"] = "3"; - - // The server supports a small number of additional streams beyond the - // negotiated limit. Open enough streams to go beyond that limit. - for (int i = 0; i < kServerMaxStreams + 1; ++i) { - client_->SendMessage(headers, "", /*fin=*/false); - } - client_->WaitForResponse(); - - EXPECT_TRUE(client_->connected()); - EXPECT_EQ(QUIC_REFUSED_STREAM, client_->stream_error()); - EXPECT_EQ(QUIC_NO_ERROR, client_->connection_error()); -} - -TEST_P(EndToEndTest, SetIndependentMaxIncomingDynamicStreamsLimits) { - // Each endpoint can set max incoming dynamic streams independently. - const uint32_t kClientMaxIncomingDynamicStreams = 2; - const uint32_t kServerMaxIncomingDynamicStreams = 1; - client_config_.SetMaxIncomingDynamicStreamsToSend( - kClientMaxIncomingDynamicStreams); - server_config_.SetMaxIncomingDynamicStreamsToSend( - kServerMaxIncomingDynamicStreams); - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - // The client has received the server's limit and vice versa. - EXPECT_EQ(kServerMaxIncomingDynamicStreams, - client_->client()->client_session()->max_open_outgoing_streams()); - server_thread_->Pause(); - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - QuicSession* server_session = dispatcher->session_map().begin()->second.get(); - EXPECT_EQ(kClientMaxIncomingDynamicStreams, - server_session->max_open_outgoing_streams()); - server_thread_->Resume(); -} - -TEST_P(EndToEndTest, NegotiateCongestionControl) { - ASSERT_TRUE(Initialize()); - - // For PCC, the underlying implementation may be a stub with a - // different name-tag. Skip the rest of this test. - if (GetParam().congestion_control_tag == kTPCC) { - return; - } - - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - CongestionControlType expected_congestion_control_type = kRenoBytes; - switch (GetParam().congestion_control_tag) { - case kRENO: - expected_congestion_control_type = kRenoBytes; - break; - case kTBBR: - expected_congestion_control_type = kBBR; - break; - case kQBIC: - expected_congestion_control_type = kCubicBytes; - break; - default: - QUIC_DLOG(FATAL) << "Unexpected congestion control tag"; - } - - server_thread_->Pause(); - EXPECT_EQ(expected_congestion_control_type, - QuicSentPacketManagerPeer::GetSendAlgorithm( - *GetSentPacketManagerFromFirstServerSession()) - ->GetCongestionControlType()); - server_thread_->Resume(); -} - -TEST_P(EndToEndTest, ClientSuggestsRTT) { - // Client suggests initial RTT, verify it is used. - const QuicTime::Delta kInitialRTT = QuicTime::Delta::FromMicroseconds(20000); - client_config_.SetInitialRoundTripTimeUsToSend(kInitialRTT.ToMicroseconds()); - - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - server_thread_->WaitForCryptoHandshakeConfirmed(); - - // Pause the server so we can access the server's internals without races. - server_thread_->Pause(); - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - ASSERT_EQ(1u, dispatcher->session_map().size()); - const QuicSentPacketManager& client_sent_packet_manager = - client_->client()->client_session()->connection()->sent_packet_manager(); - const QuicSentPacketManager* server_sent_packet_manager = - GetSentPacketManagerFromFirstServerSession(); - - EXPECT_EQ(kInitialRTT, - client_sent_packet_manager.GetRttStats()->initial_rtt()); - EXPECT_EQ(kInitialRTT, - server_sent_packet_manager->GetRttStats()->initial_rtt()); - server_thread_->Resume(); -} - -TEST_P(EndToEndTest, MaxInitialRTT) { - // Client tries to suggest twice the server's max initial rtt and the server - // uses the max. - client_config_.SetInitialRoundTripTimeUsToSend(2 * - kMaxInitialRoundTripTimeUs); - - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - server_thread_->WaitForCryptoHandshakeConfirmed(); - - // Pause the server so we can access the server's internals without races. - server_thread_->Pause(); - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - ASSERT_EQ(1u, dispatcher->session_map().size()); - QuicSession* session = dispatcher->session_map().begin()->second.get(); - const QuicSentPacketManager& client_sent_packet_manager = - client_->client()->client_session()->connection()->sent_packet_manager(); - - // Now that acks have been exchanged, the RTT estimate has decreased on the - // server and is not infinite on the client. - EXPECT_FALSE( - client_sent_packet_manager.GetRttStats()->smoothed_rtt().IsInfinite()); - const RttStats& server_rtt_stats = - *session->connection()->sent_packet_manager().GetRttStats(); - EXPECT_EQ(static_cast<int64_t>(kMaxInitialRoundTripTimeUs), - server_rtt_stats.initial_rtt().ToMicroseconds()); - EXPECT_GE(static_cast<int64_t>(kMaxInitialRoundTripTimeUs), - server_rtt_stats.smoothed_rtt().ToMicroseconds()); - server_thread_->Resume(); -} - -TEST_P(EndToEndTest, MinInitialRTT) { - // Client tries to suggest 0 and the server uses the default. - client_config_.SetInitialRoundTripTimeUsToSend(0); - - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - server_thread_->WaitForCryptoHandshakeConfirmed(); - - // Pause the server so we can access the server's internals without races. - server_thread_->Pause(); - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - ASSERT_EQ(1u, dispatcher->session_map().size()); - QuicSession* session = dispatcher->session_map().begin()->second.get(); - const QuicSentPacketManager& client_sent_packet_manager = - client_->client()->client_session()->connection()->sent_packet_manager(); - const QuicSentPacketManager& server_sent_packet_manager = - session->connection()->sent_packet_manager(); - - // Now that acks have been exchanged, the RTT estimate has decreased on the - // server and is not infinite on the client. - EXPECT_FALSE( - client_sent_packet_manager.GetRttStats()->smoothed_rtt().IsInfinite()); - // Expect the default rtt of 100ms. - EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100), - server_sent_packet_manager.GetRttStats()->initial_rtt()); - // Ensure the bandwidth is valid. - client_sent_packet_manager.BandwidthEstimate(); - server_sent_packet_manager.BandwidthEstimate(); - server_thread_->Resume(); -} - -TEST_P(EndToEndTest, 0ByteConnectionId) { - client_config_.SetBytesForConnectionIdToSend(0); - ASSERT_TRUE(Initialize()); - - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - - QuicPacketHeader* header = QuicConnectionPeer::GetLastHeader( - client_->client()->client_session()->connection()); - EXPECT_EQ(PACKET_0BYTE_CONNECTION_ID, header->connection_id_length); -} - -TEST_P(EndToEndTestWithTls, 8ByteConnectionId) { - client_config_.SetBytesForConnectionIdToSend(8); - ASSERT_TRUE(Initialize()); - - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - QuicPacketHeader* header = QuicConnectionPeer::GetLastHeader( - client_->client()->client_session()->connection()); - EXPECT_EQ(PACKET_8BYTE_CONNECTION_ID, header->connection_id_length); -} - -TEST_P(EndToEndTestWithTls, 15ByteConnectionId) { - client_config_.SetBytesForConnectionIdToSend(15); - ASSERT_TRUE(Initialize()); - - // Our server is permissive and allows for out of bounds values. - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - QuicPacketHeader* header = QuicConnectionPeer::GetLastHeader( - client_->client()->client_session()->connection()); - EXPECT_EQ(PACKET_8BYTE_CONNECTION_ID, header->connection_id_length); -} - -TEST_P(EndToEndTestWithTls, ResetConnection) { - ASSERT_TRUE(Initialize()); - - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - client_->ResetConnection(); - EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); -} - -// TODO(fkastenholz): this test seems to cause net_unittests timeouts -// reverted from EndToEndTestWithTls to EndToEndTest -TEST_P(EndToEndTest, MaxStreamsUberTest) { - if (!BothSidesSupportStatelessRejects()) { - // Connect with lower fake packet loss than we'd like to test. Until - // b/10126687 is fixed, losing handshake packets is pretty brutal. - // TODO(jokulik): Until we support redundant SREJ packets, don't - // drop handshake packets for stateless rejects. - SetPacketLossPercentage(1); - } - ASSERT_TRUE(Initialize()); - QuicString large_body(10240, 'a'); - int max_streams = 100; - - AddToCache("/large_response", 200, large_body); - - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - SetPacketLossPercentage(10); - - for (int i = 0; i < max_streams; ++i) { - EXPECT_LT(0, client_->SendRequest("/large_response")); - } - - // WaitForEvents waits 50ms and returns true if there are outstanding - // requests. - while (client_->client()->WaitForEvents() == true) { - } -} - -TEST_P(EndToEndTestWithTls, StreamCancelErrorTest) { - ASSERT_TRUE(Initialize()); - QuicString small_body(256, 'a'); - - AddToCache("/small_response", 200, small_body); - - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - QuicSession* session = client_->client()->client_session(); - // Lose the request. - SetPacketLossPercentage(100); - EXPECT_LT(0, client_->SendRequest("/small_response")); - client_->client()->WaitForEvents(); - // Transmit the cancel, and ensure the connection is torn down properly. - SetPacketLossPercentage(0); - QuicStreamId stream_id = GetNthClientInitiatedId(0); - session->SendRstStream(stream_id, QUIC_STREAM_CANCELLED, 0); - - // WaitForEvents waits 50ms and returns true if there are outstanding - // requests. - while (client_->client()->WaitForEvents() == true) { - } - // It should be completely fine to RST a stream before any data has been - // received for that stream. - EXPECT_EQ(QUIC_NO_ERROR, client_->connection_error()); -} - -TEST_P(EndToEndTest, ConnectionMigrationClientIPChanged) { - ASSERT_TRUE(Initialize()); - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - - // Store the client IP address which was used to send the first request. - QuicIpAddress old_host = - client_->client()->network_helper()->GetLatestClientAddress().host(); - - // Migrate socket to the new IP address. - QuicIpAddress new_host = TestLoopback(2); - EXPECT_NE(old_host, new_host); - ASSERT_TRUE(client_->client()->MigrateSocket(new_host)); - - // Send a request using the new socket. - EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); -} - -TEST_P(EndToEndTest, ConnectionMigrationClientPortChanged) { - // Tests that the client's port can change during an established QUIC - // connection, and that doing so does not result in the connection being - // closed by the server. - ASSERT_TRUE(Initialize()); - - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - - // Store the client address which was used to send the first request. - QuicSocketAddress old_address = - client_->client()->network_helper()->GetLatestClientAddress(); - int old_fd = client_->client()->GetLatestFD(); - - // Create a new socket before closing the old one, which will result in a new - // ephemeral port. - QuicClientPeer::CreateUDPSocketAndBind(client_->client()); - - // Stop listening and close the old FD. - QuicClientPeer::CleanUpUDPSocket(client_->client(), old_fd); - - // The packet writer needs to be updated to use the new FD. - client_->client()->network_helper()->CreateQuicPacketWriter(); - - // Change the internal state of the client and connection to use the new port, - // this is done because in a real NAT rebinding the client wouldn't see any - // port change, and so expects no change to incoming port. - // This is kind of ugly, but needed as we are simply swapping out the client - // FD rather than any more complex NAT rebinding simulation. - int new_port = - client_->client()->network_helper()->GetLatestClientAddress().port(); - QuicClientPeer::SetClientPort(client_->client(), new_port); - QuicConnectionPeer::SetSelfAddress( - client_->client()->client_session()->connection(), - QuicSocketAddress(client_->client() - ->client_session() - ->connection() - ->self_address() - .host(), - new_port)); - - // Register the new FD for epoll events. - int new_fd = client_->client()->GetLatestFD(); - EpollServer* eps = client_->epoll_server(); - eps->RegisterFD(new_fd, client_->client()->epoll_network_helper(), - EPOLLIN | EPOLLOUT | EPOLLET); - - // Send a second request, using the new FD. - EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - - // Verify that the client's ephemeral port is different. - QuicSocketAddress new_address = - client_->client()->network_helper()->GetLatestClientAddress(); - EXPECT_EQ(old_address.host(), new_address.host()); - EXPECT_NE(old_address.port(), new_address.port()); -} - -TEST_P(EndToEndTest, NegotiatedInitialCongestionWindow) { - SetQuicReloadableFlag(quic_unified_iw_options, true); - client_extra_copts_.push_back(kIW03); - - ASSERT_TRUE(Initialize()); - - // Values are exchanged during crypto handshake, so wait for that to finish. - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - server_thread_->WaitForCryptoHandshakeConfirmed(); - server_thread_->Pause(); - - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - QuicSession* session = dispatcher->session_map().begin()->second.get(); - QuicConnection* server_connection = session->connection(); - QuicPacketCount cwnd = - server_connection->sent_packet_manager().initial_congestion_window(); - EXPECT_EQ(3u, cwnd); -} - -TEST_P(EndToEndTest, DifferentFlowControlWindows) { - // Client and server can set different initial flow control receive windows. - // These are sent in CHLO/SHLO. Tests that these values are exchanged properly - // in the crypto handshake. - const uint32_t kClientStreamIFCW = 123456; - const uint32_t kClientSessionIFCW = 234567; - set_client_initial_stream_flow_control_receive_window(kClientStreamIFCW); - set_client_initial_session_flow_control_receive_window(kClientSessionIFCW); - - uint32_t kServerStreamIFCW = 32 * 1024; - uint32_t kServerSessionIFCW = 48 * 1024; - set_server_initial_stream_flow_control_receive_window(kServerStreamIFCW); - set_server_initial_session_flow_control_receive_window(kServerSessionIFCW); - - ASSERT_TRUE(Initialize()); - - // Values are exchanged during crypto handshake, so wait for that to finish. - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - server_thread_->WaitForCryptoHandshakeConfirmed(); - - // Open a data stream to make sure the stream level flow control is updated. - QuicSpdyClientStream* stream = client_->GetOrCreateStream(); - stream->WriteOrBufferBody("hello", false, nullptr); - - // Client should have the right values for server's receive window. - EXPECT_EQ(kServerStreamIFCW, - client_->client() - ->client_session() - ->config() - ->ReceivedInitialStreamFlowControlWindowBytes()); - EXPECT_EQ(kServerSessionIFCW, - client_->client() - ->client_session() - ->config() - ->ReceivedInitialSessionFlowControlWindowBytes()); - EXPECT_EQ(kServerStreamIFCW, QuicFlowControllerPeer::SendWindowOffset( - stream->flow_controller())); - EXPECT_EQ(kServerSessionIFCW, - QuicFlowControllerPeer::SendWindowOffset( - client_->client()->client_session()->flow_controller())); - - // Server should have the right values for client's receive window. - server_thread_->Pause(); - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - QuicSession* session = dispatcher->session_map().begin()->second.get(); - EXPECT_EQ(kClientStreamIFCW, - session->config()->ReceivedInitialStreamFlowControlWindowBytes()); - EXPECT_EQ(kClientSessionIFCW, - session->config()->ReceivedInitialSessionFlowControlWindowBytes()); - EXPECT_EQ(kClientSessionIFCW, QuicFlowControllerPeer::SendWindowOffset( - session->flow_controller())); - server_thread_->Resume(); -} - -// Test negotiation of IFWA connection option. -TEST_P(EndToEndTest, NegotiatedServerInitialFlowControlWindow) { - const uint32_t kClientStreamIFCW = 123456; - const uint32_t kClientSessionIFCW = 234567; - set_client_initial_stream_flow_control_receive_window(kClientStreamIFCW); - set_client_initial_session_flow_control_receive_window(kClientSessionIFCW); - - uint32_t kServerStreamIFCW = 32 * 1024; - uint32_t kServerSessionIFCW = 48 * 1024; - set_server_initial_stream_flow_control_receive_window(kServerStreamIFCW); - set_server_initial_session_flow_control_receive_window(kServerSessionIFCW); - - // Bump the window. - const uint32_t kExpectedStreamIFCW = 1024 * 1024; - const uint32_t kExpectedSessionIFCW = 1.5 * 1024 * 1024; - client_extra_copts_.push_back(kIFWA); - - ASSERT_TRUE(Initialize()); - - // Values are exchanged during crypto handshake, so wait for that to finish. - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - server_thread_->WaitForCryptoHandshakeConfirmed(); - - // Open a data stream to make sure the stream level flow control is updated. - QuicSpdyClientStream* stream = client_->GetOrCreateStream(); - stream->WriteOrBufferBody("hello", false, nullptr); - - // Client should have the right values for server's receive window. - EXPECT_EQ(kExpectedStreamIFCW, - client_->client() - ->client_session() - ->config() - ->ReceivedInitialStreamFlowControlWindowBytes()); - EXPECT_EQ(kExpectedSessionIFCW, - client_->client() - ->client_session() - ->config() - ->ReceivedInitialSessionFlowControlWindowBytes()); - EXPECT_EQ(kExpectedStreamIFCW, QuicFlowControllerPeer::SendWindowOffset( - stream->flow_controller())); - EXPECT_EQ(kExpectedSessionIFCW, - QuicFlowControllerPeer::SendWindowOffset( - client_->client()->client_session()->flow_controller())); -} - -TEST_P(EndToEndTest, HeadersAndCryptoStreamsNoConnectionFlowControl) { - // The special headers and crypto streams should be subject to per-stream flow - // control limits, but should not be subject to connection level flow control - const uint32_t kStreamIFCW = 32 * 1024; - const uint32_t kSessionIFCW = 48 * 1024; - set_client_initial_stream_flow_control_receive_window(kStreamIFCW); - set_client_initial_session_flow_control_receive_window(kSessionIFCW); - set_server_initial_stream_flow_control_receive_window(kStreamIFCW); - set_server_initial_session_flow_control_receive_window(kSessionIFCW); - - ASSERT_TRUE(Initialize()); - - // Wait for crypto handshake to finish. This should have contributed to the - // crypto stream flow control window, but not affected the session flow - // control window. - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - server_thread_->WaitForCryptoHandshakeConfirmed(); - - QuicCryptoStream* crypto_stream = QuicSessionPeer::GetMutableCryptoStream( - client_->client()->client_session()); - EXPECT_LT( - QuicFlowControllerPeer::SendWindowSize(crypto_stream->flow_controller()), - kStreamIFCW); - EXPECT_EQ(kSessionIFCW, - QuicFlowControllerPeer::SendWindowSize( - client_->client()->client_session()->flow_controller())); - - // Send a request with no body, and verify that the connection level window - // has not been affected. - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - - QuicHeadersStream* headers_stream = QuicSpdySessionPeer::GetHeadersStream( - client_->client()->client_session()); - EXPECT_LT( - QuicFlowControllerPeer::SendWindowSize(headers_stream->flow_controller()), - kStreamIFCW); - EXPECT_EQ(kSessionIFCW, - QuicFlowControllerPeer::SendWindowSize( - client_->client()->client_session()->flow_controller())); - - // Server should be in a similar state: connection flow control window should - // not have any bytes marked as received. - server_thread_->Pause(); - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - QuicSession* session = dispatcher->session_map().begin()->second.get(); - QuicFlowController* server_connection_flow_controller = - session->flow_controller(); - EXPECT_EQ(kSessionIFCW, QuicFlowControllerPeer::ReceiveWindowSize( - server_connection_flow_controller)); - server_thread_->Resume(); -} - -TEST_P(EndToEndTest, FlowControlsSynced) { - set_smaller_flow_control_receive_window(); - - ASSERT_TRUE(Initialize()); - - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - server_thread_->WaitForCryptoHandshakeConfirmed(); - - server_thread_->Pause(); - QuicSpdySession* const client_session = client_->client()->client_session(); - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - auto* server_session = static_cast<QuicSpdySession*>( - dispatcher->session_map().begin()->second.get()); - ExpectFlowControlsSynced(client_session->flow_controller(), - server_session->flow_controller()); - ExpectFlowControlsSynced( - QuicSessionPeer::GetMutableCryptoStream(client_session) - ->flow_controller(), - QuicSessionPeer::GetMutableCryptoStream(server_session) - ->flow_controller()); - SpdyFramer spdy_framer(SpdyFramer::ENABLE_COMPRESSION); - SpdySettingsIR settings_frame; - settings_frame.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE, - kDefaultMaxUncompressedHeaderSize); - SpdySerializedFrame frame(spdy_framer.SerializeFrame(settings_frame)); - QuicFlowController* client_header_stream_flow_controller = - QuicSpdySessionPeer::GetHeadersStream(client_session)->flow_controller(); - QuicFlowController* server_header_stream_flow_controller = - QuicSpdySessionPeer::GetHeadersStream(server_session)->flow_controller(); - if (GetQuicReloadableFlag(quic_send_max_header_list_size)) { - // Both client and server are sending this SETTINGS frame, and the send - // window is consumed. But because of timing issue, the server may send or - // not send the frame, and the client may send/ not send / receive / not - // receive the frame. - // TODO(fayang): Rewrite this part because it is hacky. - QuicByteCount win_difference1 = QuicFlowControllerPeer::ReceiveWindowSize( - server_header_stream_flow_controller) - - QuicFlowControllerPeer::SendWindowSize( - client_header_stream_flow_controller); - QuicByteCount win_difference2 = QuicFlowControllerPeer::ReceiveWindowSize( - client_header_stream_flow_controller) - - QuicFlowControllerPeer::SendWindowSize( - server_header_stream_flow_controller); - EXPECT_TRUE(win_difference1 == 0 || win_difference1 == frame.size()); - EXPECT_TRUE(win_difference2 == 0 || win_difference2 == frame.size()); - } else { - ExpectFlowControlsSynced( - QuicSpdySessionPeer::GetHeadersStream(client_session) - ->flow_controller(), - QuicSpdySessionPeer::GetHeadersStream(server_session) - ->flow_controller()); - } - - if (GetQuicReloadableFlag(quic_send_max_header_list_size)) { - // Client *may* have received the SETTINGs frame. - // TODO(fayang): Rewrite this part because it is hacky. - float ratio1 = static_cast<float>(QuicFlowControllerPeer::ReceiveWindowSize( - client_session->flow_controller())) / - QuicFlowControllerPeer::ReceiveWindowSize( - QuicSpdySessionPeer::GetHeadersStream(client_session) - ->flow_controller()); - float ratio2 = static_cast<float>(QuicFlowControllerPeer::ReceiveWindowSize( - client_session->flow_controller())) / - (QuicFlowControllerPeer::ReceiveWindowSize( - QuicSpdySessionPeer::GetHeadersStream(client_session) - ->flow_controller()) + - frame.size()); - EXPECT_TRUE(ratio1 == kSessionToStreamRatio || - ratio2 == kSessionToStreamRatio); - } - - server_thread_->Resume(); -} - -TEST_P(EndToEndTestWithTls, RequestWithNoBodyWillNeverSendStreamFrameWithFIN) { - // A stream created on receipt of a simple request with no body will never get - // a stream frame with a FIN. Verify that we don't keep track of the stream in - // the locally closed streams map: it will never be removed if so. - ASSERT_TRUE(Initialize()); - - // Send a simple headers only request, and receive response. - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - - // Now verify that the server is not waiting for a final FIN or RST. - server_thread_->Pause(); - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - QuicSession* session = dispatcher->session_map().begin()->second.get(); - EXPECT_EQ( - 0u, - QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(session).size()); - server_thread_->Resume(); -} - -// A TestAckListener verifies that its OnAckNotification method has been -// called exactly once on destruction. -class TestAckListener : public QuicAckListenerInterface { - public: - explicit TestAckListener(int bytes_to_ack) : bytes_to_ack_(bytes_to_ack) {} - - void OnPacketAcked(int acked_bytes, - QuicTime::Delta /*delta_largest_observed*/) override { - ASSERT_LE(acked_bytes, bytes_to_ack_); - bytes_to_ack_ -= acked_bytes; - } - - void OnPacketRetransmitted(int /*retransmitted_bytes*/) override {} - - bool has_been_notified() const { return bytes_to_ack_ == 0; } - - protected: - // Object is ref counted. - ~TestAckListener() override { EXPECT_EQ(0, bytes_to_ack_); } - - private: - int bytes_to_ack_; -}; - -class TestResponseListener : public QuicSpdyClientBase::ResponseListener { - public: - void OnCompleteResponse(QuicStreamId id, - const SpdyHeaderBlock& response_headers, - const QuicString& response_body) override { - QUIC_DVLOG(1) << "response for stream " << id << " " - << response_headers.DebugString() << "\n" - << response_body; - } -}; - -TEST_P(EndToEndTest, AckNotifierWithPacketLossAndBlockedSocket) { - // Verify that even in the presence of packet loss and occasionally blocked - // socket, an AckNotifierDelegate will get informed that the data it is - // interested in has been ACKed. This tests end-to-end ACK notification, and - // demonstrates that retransmissions do not break this functionality. - if (!BothSidesSupportStatelessRejects()) { - // TODO(jokulik): Until we support redundant SREJ packets, don't - // drop handshake packets for stateless rejects. - SetPacketLossPercentage(5); - } - ASSERT_TRUE(Initialize()); - - // Wait for the server SHLO before upping the packet loss. - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - SetPacketLossPercentage(30); - client_writer_->set_fake_blocked_socket_percentage(10); - - // Create a POST request and send the headers only. - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - - client_->SendMessage(headers, "", /*fin=*/false); - - // Test the AckNotifier's ability to track multiple packets by making the - // request body exceed the size of a single packet. - QuicString request_string = - "a request body bigger than one packet" + QuicString(kMaxPacketSize, '.'); - - // The TestAckListener will cause a failure if not notified. - QuicReferenceCountedPointer<TestAckListener> ack_listener( - new TestAckListener(request_string.length())); - - // Send the request, and register the delegate for ACKs. - client_->SendData(request_string, true, ack_listener); - client_->WaitForResponse(); - EXPECT_EQ(kFooResponseBody, client_->response_body()); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - - // Send another request to flush out any pending ACKs on the server. - client_->SendSynchronousRequest("/bar"); - - // Make sure the delegate does get the notification it expects. - while (!ack_listener->has_been_notified()) { - // Waits for up to 50 ms. - client_->client()->WaitForEvents(); - } -} - -// Send a public reset from the server. -TEST_P(EndToEndTestWithTls, ServerSendPublicReset) { - ASSERT_TRUE(Initialize()); - - // Send the public reset. - QuicConnectionId connection_id = - client_->client()->client_session()->connection()->connection_id(); - QuicPublicResetPacket header; - header.connection_id = connection_id; - QuicFramer framer(server_supported_versions_, QuicTime::Zero(), - Perspective::IS_SERVER); - std::unique_ptr<QuicEncryptedPacket> packet( - framer.BuildPublicResetPacket(header)); - // We must pause the server's thread in order to call WritePacket without - // race conditions. - server_thread_->Pause(); - server_writer_->WritePacket( - packet->data(), packet->length(), server_address_.host(), - client_->client()->network_helper()->GetLatestClientAddress(), nullptr); - server_thread_->Resume(); - - // The request should fail. - EXPECT_EQ("", client_->SendSynchronousRequest("/foo")); - EXPECT_TRUE(client_->response_headers()->empty()); - EXPECT_EQ(QUIC_PUBLIC_RESET, client_->connection_error()); -} - -// Send a public reset from the server for a different connection ID. -// It should be ignored. -TEST_P(EndToEndTestWithTls, ServerSendPublicResetWithDifferentConnectionId) { - ASSERT_TRUE(Initialize()); - - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - // Send the public reset. - QuicConnectionId incorrect_connection_id = - client_->client()->client_session()->connection()->connection_id() + 1; - QuicPublicResetPacket header; - header.connection_id = incorrect_connection_id; - QuicFramer framer(server_supported_versions_, QuicTime::Zero(), - Perspective::IS_SERVER); - std::unique_ptr<QuicEncryptedPacket> packet( - framer.BuildPublicResetPacket(header)); - testing::NiceMock<MockQuicConnectionDebugVisitor> visitor; - client_->client()->client_session()->connection()->set_debug_visitor( - &visitor); - EXPECT_CALL(visitor, OnIncorrectConnectionId(incorrect_connection_id)) - .Times(1); - // We must pause the server's thread in order to call WritePacket without - // race conditions. - server_thread_->Pause(); - server_writer_->WritePacket( - packet->data(), packet->length(), server_address_.host(), - client_->client()->network_helper()->GetLatestClientAddress(), nullptr); - server_thread_->Resume(); - - // The connection should be unaffected. - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - - client_->client()->client_session()->connection()->set_debug_visitor(nullptr); -} - -// Send a public reset from the client for a different connection ID. -// It should be ignored. -TEST_P(EndToEndTestWithTls, ClientSendPublicResetWithDifferentConnectionId) { - ASSERT_TRUE(Initialize()); - - // Send the public reset. - QuicConnectionId incorrect_connection_id = - client_->client()->client_session()->connection()->connection_id() + 1; - QuicPublicResetPacket header; - header.connection_id = incorrect_connection_id; - QuicFramer framer(server_supported_versions_, QuicTime::Zero(), - Perspective::IS_CLIENT); - std::unique_ptr<QuicEncryptedPacket> packet( - framer.BuildPublicResetPacket(header)); - client_writer_->WritePacket( - packet->data(), packet->length(), - client_->client()->network_helper()->GetLatestClientAddress().host(), - server_address_, nullptr); - - // The connection should be unaffected. - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); -} - -// Send a version negotiation packet from the server for a different -// connection ID. It should be ignored. -TEST_P(EndToEndTestWithTls, - ServerSendVersionNegotiationWithDifferentConnectionId) { - ASSERT_TRUE(Initialize()); - - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - // Send the version negotiation packet. - QuicConnectionId incorrect_connection_id = - client_->client()->client_session()->connection()->connection_id() + 1; - std::unique_ptr<QuicEncryptedPacket> packet( - QuicFramer::BuildVersionNegotiationPacket(incorrect_connection_id, false, - server_supported_versions_)); - testing::NiceMock<MockQuicConnectionDebugVisitor> visitor; - client_->client()->client_session()->connection()->set_debug_visitor( - &visitor); - EXPECT_CALL(visitor, OnIncorrectConnectionId(incorrect_connection_id)) - .Times(1); - // We must pause the server's thread in order to call WritePacket without - // race conditions. - server_thread_->Pause(); - server_writer_->WritePacket( - packet->data(), packet->length(), server_address_.host(), - client_->client()->network_helper()->GetLatestClientAddress(), nullptr); - server_thread_->Resume(); - - // The connection should be unaffected. - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - - client_->client()->client_session()->connection()->set_debug_visitor(nullptr); -} - -// A bad header shouldn't tear down the connection, because the receiver can't -// tell the connection ID. -TEST_P(EndToEndTestWithTls, BadPacketHeaderTruncated) { - ASSERT_TRUE(Initialize()); - - // Start the connection. - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - - // Packet with invalid public flags. - char packet[] = {// public flags (8 byte connection_id) - 0x3C, - // truncated connection ID - 0x11}; - client_writer_->WritePacket( - &packet[0], sizeof(packet), - client_->client()->network_helper()->GetLatestClientAddress().host(), - server_address_, nullptr); - // Give the server time to process the packet. - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); - // Pause the server so we can access the server's internals without races. - server_thread_->Pause(); - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, - QuicDispatcherPeer::GetAndClearLastError(dispatcher)); - server_thread_->Resume(); - - // The connection should not be terminated. - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); -} - -// A bad header shouldn't tear down the connection, because the receiver can't -// tell the connection ID. -TEST_P(EndToEndTestWithTls, BadPacketHeaderFlags) { - ASSERT_TRUE(Initialize()); - - // Start the connection. - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - - // Packet with invalid public flags. - char packet[] = { - // invalid public flags - 0xFF, - // connection_id - 0x10, - 0x32, - 0x54, - 0x76, - 0x98, - 0xBA, - 0xDC, - 0xFE, - // packet sequence number - 0xBC, - 0x9A, - 0x78, - 0x56, - 0x34, - 0x12, - // private flags - 0x00, - }; - client_writer_->WritePacket( - &packet[0], sizeof(packet), - client_->client()->network_helper()->GetLatestClientAddress().host(), - server_address_, nullptr); - // Give the server time to process the packet. - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); - // Pause the server so we can access the server's internals without races. - server_thread_->Pause(); - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, - QuicDispatcherPeer::GetAndClearLastError(dispatcher)); - server_thread_->Resume(); - - // The connection should not be terminated. - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); -} - -// Send a packet from the client with bad encrypted data. The server should not -// tear down the connection. -TEST_P(EndToEndTestWithTls, BadEncryptedData) { - ASSERT_TRUE(Initialize()); - - // Start the connection. - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - - std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket( - client_->client()->client_session()->connection()->connection_id(), false, - false, 1, "At least 20 characters.", PACKET_8BYTE_CONNECTION_ID, - PACKET_4BYTE_PACKET_NUMBER)); - // Damage the encrypted data. - QuicString damaged_packet(packet->data(), packet->length()); - damaged_packet[30] ^= 0x01; - QUIC_DLOG(INFO) << "Sending bad packet."; - client_writer_->WritePacket( - damaged_packet.data(), damaged_packet.length(), - client_->client()->network_helper()->GetLatestClientAddress().host(), - server_address_, nullptr); - // Give the server time to process the packet. - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); - // This error is sent to the connection's OnError (which ignores it), so the - // dispatcher doesn't see it. - // Pause the server so we can access the server's internals without races. - server_thread_->Pause(); - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - EXPECT_EQ(QUIC_NO_ERROR, - QuicDispatcherPeer::GetAndClearLastError(dispatcher)); - server_thread_->Resume(); - - // The connection should not be terminated. - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); -} - -TEST_P(EndToEndTestWithTls, CanceledStreamDoesNotBecomeZombie) { - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - // Lose the request. - SetPacketLossPercentage(100); - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - client_->SendMessage(headers, "test_body", /*fin=*/false); - QuicSpdyClientStream* stream = client_->GetOrCreateStream(); - - // Cancel the stream. - stream->Reset(QUIC_STREAM_CANCELLED); - QuicSession* session = client_->client()->client_session(); - // Verify canceled stream does not become zombie. - EXPECT_TRUE(QuicSessionPeer::zombie_streams(session).empty()); - EXPECT_EQ(1u, QuicSessionPeer::closed_streams(session).size()); -} - -// A test stream that gives |response_body_| as an error response body. -class ServerStreamWithErrorResponseBody : public QuicSimpleServerStream { - public: - ServerStreamWithErrorResponseBody(QuicStreamId id, - QuicSpdySession* session, - QuicHttpResponseCache* response_cache, - QuicString response_body) - : QuicSimpleServerStream(id, session, response_cache), - response_body_(std::move(response_body)) {} - - ~ServerStreamWithErrorResponseBody() override = default; - - protected: - void SendErrorResponse() override { - QUIC_DLOG(INFO) << "Sending error response for stream " << id(); - SpdyHeaderBlock headers; - headers[":status"] = "500"; - headers["content-length"] = - QuicTextUtils::Uint64ToString(response_body_.size()); - // This method must call CloseReadSide to cause the test case, StopReading - // is not sufficient. - QuicStreamPeer::CloseReadSide(this); - SendHeadersAndBody(std::move(headers), response_body_); - } - - QuicString response_body_; -}; - -class StreamWithErrorFactory : public QuicTestServer::StreamFactory { - public: - explicit StreamWithErrorFactory(QuicString response_body) - : response_body_(std::move(response_body)) {} - - ~StreamWithErrorFactory() override = default; - - QuicSimpleServerStream* CreateStream( - QuicStreamId id, - QuicSpdySession* session, - QuicHttpResponseCache* response_cache) override { - return new ServerStreamWithErrorResponseBody(id, session, response_cache, - response_body_); - } - - private: - QuicString response_body_; -}; - -// A test server stream that drops all received body. -class ServerStreamThatDropsBody : public QuicSimpleServerStream { - public: - ServerStreamThatDropsBody(QuicStreamId id, - QuicSpdySession* session, - QuicHttpResponseCache* response_cache) - : QuicSimpleServerStream(id, session, response_cache) {} - - ~ServerStreamThatDropsBody() override = default; - - protected: - void OnDataAvailable() override { - while (HasBytesToRead()) { - struct iovec iov; - if (GetReadableRegions(&iov, 1) == 0) { - // No more data to read. - break; - } - QUIC_DVLOG(1) << "Processed " << iov.iov_len << " bytes for stream " - << id(); - MarkConsumed(iov.iov_len); - } - - if (!sequencer()->IsClosed()) { - sequencer()->SetUnblocked(); - return; - } - - // If the sequencer is closed, then all the body, including the fin, has - // been consumed. - OnFinRead(); - - if (write_side_closed() || fin_buffered()) { - return; - } - - SendResponse(); - } -}; - -class ServerStreamThatDropsBodyFactory : public QuicTestServer::StreamFactory { - public: - ServerStreamThatDropsBodyFactory() = default; - - ~ServerStreamThatDropsBodyFactory() override = default; - - QuicSimpleServerStream* CreateStream( - QuicStreamId id, - QuicSpdySession* session, - QuicHttpResponseCache* response_cache) override { - return new ServerStreamThatDropsBody(id, session, response_cache); - } -}; - -// A test server stream that sends response with body size greater than 4GB. -class ServerStreamThatSendsHugeResponse : public QuicSimpleServerStream { - public: - ServerStreamThatSendsHugeResponse(QuicStreamId id, - QuicSpdySession* session, - QuicHttpResponseCache* response_cache, - int64_t body_bytes) - : QuicSimpleServerStream(id, session, response_cache), - body_bytes_(body_bytes) {} - - ~ServerStreamThatSendsHugeResponse() override = default; - - protected: - void SendResponse() override { - QuicHttpResponseCache::Response response; - QuicString body(body_bytes_, 'a'); - response.set_body(body); - SendHeadersAndBodyAndTrailers(response.headers().Clone(), response.body(), - response.trailers().Clone()); - } - - private: - // Use a explicit int64_t rather than size_t to simulate a 64-bit server - // talking to a 32-bit client. - int64_t body_bytes_; -}; - -class ServerStreamThatSendsHugeResponseFactory - : public QuicTestServer::StreamFactory { - public: - explicit ServerStreamThatSendsHugeResponseFactory(int64_t body_bytes) - : body_bytes_(body_bytes) {} - - ~ServerStreamThatSendsHugeResponseFactory() override = default; - - QuicSimpleServerStream* CreateStream( - QuicStreamId id, - QuicSpdySession* session, - QuicHttpResponseCache* response_cache) override { - return new ServerStreamThatSendsHugeResponse(id, session, response_cache, - body_bytes_); - } - - int64_t body_bytes_; -}; - -// A test client stream that drops all received body. -class ClientStreamThatDropsBody : public QuicSpdyClientStream { - public: - ClientStreamThatDropsBody(QuicStreamId id, QuicSpdyClientSession* session) - : QuicSpdyClientStream(id, session) {} - ~ClientStreamThatDropsBody() override = default; - - void OnDataAvailable() override { - while (HasBytesToRead()) { - struct iovec iov; - if (GetReadableRegions(&iov, 1) == 0) { - break; - } - MarkConsumed(iov.iov_len); - } - if (sequencer()->IsClosed()) { - OnFinRead(); - } else { - sequencer()->SetUnblocked(); - } - } -}; - -class ClientSessionThatDropsBody : public QuicSpdyClientSession { - public: - ClientSessionThatDropsBody(const QuicConfig& config, - QuicConnection* connection, - const QuicServerId& server_id, - QuicCryptoClientConfig* crypto_config, - QuicClientPushPromiseIndex* push_promise_index) - : QuicSpdyClientSession(config, - connection, - server_id, - crypto_config, - push_promise_index) {} - - ~ClientSessionThatDropsBody() override = default; - - std::unique_ptr<QuicSpdyClientStream> CreateClientStream() override { - return QuicMakeUnique<ClientStreamThatDropsBody>(GetNextOutgoingStreamId(), - this); - } -}; - -class MockableQuicClientThatDropsBody : public MockableQuicClient { - public: - MockableQuicClientThatDropsBody( - QuicSocketAddress server_address, - const QuicServerId& server_id, - const QuicConfig& config, - const ParsedQuicVersionVector& supported_versions, - EpollServer* epoll_server) - : MockableQuicClient(server_address, - server_id, - config, - supported_versions, - epoll_server) {} - ~MockableQuicClientThatDropsBody() override = default; - - std::unique_ptr<QuicSession> CreateQuicClientSession( - QuicConnection* connection) override { - return QuicMakeUnique<ClientSessionThatDropsBody>( - *config(), connection, server_id(), crypto_config(), - push_promise_index()); - } -}; - -class QuicTestClientThatDropsBody : public QuicTestClient { - public: - QuicTestClientThatDropsBody(QuicSocketAddress server_address, - const QuicString& server_hostname, - const QuicConfig& config, - const ParsedQuicVersionVector& supported_versions) - : QuicTestClient(server_address, - server_hostname, - config, - supported_versions) { - set_client(new MockableQuicClientThatDropsBody( - server_address, - QuicServerId(server_hostname, server_address.port(), - PRIVACY_MODE_DISABLED), - config, supported_versions, epoll_server())); - } - ~QuicTestClientThatDropsBody() override = default; -}; - -TEST_P(EndToEndTest, EarlyResponseFinRecording) { - set_smaller_flow_control_receive_window(); - - // 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_close_streams_highest_offset_ (which will never be deleted). - // To set up the test condition, the server must do the following in order: - // start sending the response and call CloseReadSide - // receive the FIN of the request - // send the FIN of the response - - // The response body must be larger than the flow control window so the server - // must receive a window update from the client before it can finish sending - // it. - uint32_t response_body_size = - 2 * client_config_.GetInitialStreamFlowControlWindowToSend(); - QuicString response_body(response_body_size, 'a'); - - StreamWithErrorFactory stream_factory(response_body); - SetSpdyStreamFactory(&stream_factory); - - ASSERT_TRUE(Initialize()); - - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - // A POST that gets an early error response, after the headers are received - // and before the body is received, due to invalid content-length. - // Set an invalid content-length, so the request will receive an early 500 - // response. - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/garbage"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - headers["content-length"] = "-1"; - - // The body must be large enough that the FIN will be in a different packet - // than the end of the headers, but short enough to not require a flow control - // update. This allows headers processing to trigger the error response - // before the request FIN is processed but receive the request FIN before the - // response is sent completely. - const uint32_t kRequestBodySize = kMaxPacketSize + 10; - QuicString request_body(kRequestBodySize, 'a'); - - // Send the request. - client_->SendMessage(headers, request_body); - client_->WaitForResponse(); - EXPECT_EQ("500", client_->response_headers()->find(":status")->second); - - // Pause the server so we can access the server's internals without races. - server_thread_->Pause(); - - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - QuicDispatcher::SessionMap const& map = - QuicDispatcherPeer::session_map(dispatcher); - QuicDispatcher::SessionMap::const_iterator it = map.begin(); - EXPECT_TRUE(it != map.end()); - QuicSession* server_session = it->second.get(); - - // The stream is not waiting for the arrival of the peer's final offset. - EXPECT_EQ( - 0u, QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(server_session) - .size()); - - server_thread_->Resume(); -} - -TEST_P(EndToEndTestWithTls, Trailers) { - // Test sending and receiving HTTP/2 Trailers (trailing HEADERS frames). - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - // Set reordering to ensure that Trailers arriving before body is ok. - SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2)); - SetReorderPercentage(30); - - // Add a response with headers, body, and trailers. - const QuicString kBody = "body content"; - - SpdyHeaderBlock headers; - headers[":status"] = "200"; - headers[":version"] = "HTTP/1.1"; - headers["content-length"] = QuicTextUtils::Uint64ToString(kBody.size()); - - SpdyHeaderBlock trailers; - trailers["some-trailing-header"] = "trailing-header-value"; - - response_cache_.AddResponse(server_hostname_, "/trailer_url", - std::move(headers), kBody, trailers.Clone()); - - EXPECT_EQ(kBody, client_->SendSynchronousRequest("/trailer_url")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - EXPECT_EQ(trailers, client_->response_trailers()); -} - -class EndToEndTestServerPush : public EndToEndTest { - protected: - const size_t kNumMaxStreams = 10; - - EndToEndTestServerPush() : EndToEndTest() { - client_config_.SetMaxStreamsPerConnection(kNumMaxStreams, kNumMaxStreams); - client_config_.SetMaxIncomingDynamicStreamsToSend(kNumMaxStreams); - server_config_.SetMaxStreamsPerConnection(kNumMaxStreams, kNumMaxStreams); - server_config_.SetMaxIncomingDynamicStreamsToSend(kNumMaxStreams); - support_server_push_ = true; - } - - // Add a request with its response and |num_resources| push resources into - // cache. - // If |resource_size| == 0, response body of push resources use default string - // concatenating with resource url. Otherwise, generate a string of - // |resource_size| as body. - void AddRequestAndResponseWithServerPush(QuicString host, - QuicString path, - QuicString response_body, - QuicString* push_urls, - const size_t num_resources, - const size_t resource_size) { - bool use_large_response = resource_size != 0; - QuicString large_resource; - if (use_large_response) { - // Generate a response common body larger than flow control window for - // push response. - large_resource = QuicString(resource_size, 'a'); - } - std::list<QuicHttpResponseCache::ServerPushInfo> push_resources; - for (size_t i = 0; i < num_resources; ++i) { - QuicString url = push_urls[i]; - QuicUrl resource_url(url); - QuicString body = - use_large_response - ? large_resource - : QuicStrCat("This is server push response body for ", url); - SpdyHeaderBlock response_headers; - response_headers[":version"] = "HTTP/1.1"; - response_headers[":status"] = "200"; - response_headers["content-length"] = - QuicTextUtils::Uint64ToString(body.size()); - push_resources.push_back(QuicHttpResponseCache::ServerPushInfo( - resource_url, std::move(response_headers), kV3LowestPriority, body)); - } - - response_cache_.AddSimpleResponseWithServerPushResources( - host, path, 200, response_body, push_resources); - } -}; - -// Run all server push end to end tests with all supported versions. -INSTANTIATE_TEST_CASE_P(EndToEndTestsServerPush, - EndToEndTestServerPush, - ::testing::ValuesIn(GetTestParams(false))); - -TEST_P(EndToEndTestServerPush, ServerPush) { - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - // Set reordering to ensure that body arriving before PUSH_PROMISE is ok. - SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2)); - SetReorderPercentage(30); - - // Add a response with headers, body, and push resources. - const QuicString kBody = "body content"; - size_t kNumResources = 4; - QuicString push_urls[] = {"https://example.com/font.woff", - "https://example.com/script.js", - "https://fonts.example.com/font.woff", - "https://example.com/logo-hires.jpg"}; - AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody, - push_urls, kNumResources, 0); - - client_->client()->set_response_listener( - std::unique_ptr<QuicSpdyClientBase::ResponseListener>( - new TestResponseListener)); - - QUIC_DVLOG(1) << "send request for /push_example"; - EXPECT_EQ(kBody, client_->SendSynchronousRequest( - "https://example.com/push_example")); - QuicHeadersStream* headers_stream = QuicSpdySessionPeer::GetHeadersStream( - client_->client()->client_session()); - QuicStreamSequencer* sequencer = QuicStreamPeer::sequencer(headers_stream); - // Headers stream's sequencer buffer shouldn't be released because server push - // hasn't finished yet. - EXPECT_TRUE(QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer)); - - for (const QuicString& url : push_urls) { - QUIC_DVLOG(1) << "send request for pushed stream on url " << url; - QuicString expected_body = - QuicStrCat("This is server push response body for ", url); - QuicString response_body = client_->SendSynchronousRequest(url); - QUIC_DVLOG(1) << "response body " << response_body; - EXPECT_EQ(expected_body, response_body); - } - EXPECT_FALSE(QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer)); -} - -TEST_P(EndToEndTestServerPush, ServerPushUnderLimit) { - // Tests that sending a request which has 4 push resources will trigger server - // to push those 4 resources and client can handle pushed resources and match - // them with requests later. - ASSERT_TRUE(Initialize()); - - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - // Set reordering to ensure that body arriving before PUSH_PROMISE is ok. - SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2)); - SetReorderPercentage(30); - - // Add a response with headers, body, and push resources. - const QuicString kBody = "body content"; - size_t const kNumResources = 4; - QuicString push_urls[] = { - "https://example.com/font.woff", "https://example.com/script.js", - "https://fonts.example.com/font.woff", - "https://example.com/logo-hires.jpg", - }; - AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody, - push_urls, kNumResources, 0); - client_->client()->set_response_listener( - std::unique_ptr<QuicSpdyClientBase::ResponseListener>( - new TestResponseListener)); - - // Send the first request: this will trigger the server to send all the push - // resources associated with this request, and these will be cached by the - // client. - EXPECT_EQ(kBody, client_->SendSynchronousRequest( - "https://example.com/push_example")); - - for (const QuicString& url : push_urls) { - // Sending subsequent requesets will not actually send anything on the wire, - // as the responses are already in the client's cache. - QUIC_DVLOG(1) << "send request for pushed stream on url " << url; - QuicString expected_body = - QuicStrCat("This is server push response body for ", url); - QuicString response_body = client_->SendSynchronousRequest(url); - QUIC_DVLOG(1) << "response body " << response_body; - EXPECT_EQ(expected_body, response_body); - } - // Expect only original request has been sent and push responses have been - // received as normal response. - EXPECT_EQ(1u, client_->num_requests()); - EXPECT_EQ(1u + kNumResources, client_->num_responses()); -} - -TEST_P(EndToEndTestServerPush, ServerPushOverLimitNonBlocking) { - // Tests that when streams are not blocked by flow control or congestion - // control, pushing even more resources than max number of open outgoing - // streams should still work because all response streams get closed - // immediately after pushing resources. - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - // Set reordering to ensure that body arriving before PUSH_PROMISE is ok. - SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2)); - SetReorderPercentage(30); - - // Add a response with headers, body, and push resources. - const QuicString kBody = "body content"; - - // One more resource than max number of outgoing stream of this session. - const size_t kNumResources = 1 + kNumMaxStreams; // 11. - QuicString push_urls[11]; - for (size_t i = 0; i < kNumResources; ++i) { - push_urls[i] = QuicStrCat("https://example.com/push_resources", i); - } - AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody, - push_urls, kNumResources, 0); - client_->client()->set_response_listener( - std::unique_ptr<QuicSpdyClientBase::ResponseListener>( - new TestResponseListener)); - - // Send the first request: this will trigger the server to send all the push - // resources associated with this request, and these will be cached by the - // client. - EXPECT_EQ(kBody, client_->SendSynchronousRequest( - "https://example.com/push_example")); - - for (const QuicString& url : push_urls) { - // Sending subsequent requesets will not actually send anything on the wire, - // as the responses are already in the client's cache. - EXPECT_EQ(QuicStrCat("This is server push response body for ", url), - client_->SendSynchronousRequest(url)); - } - - // Only 1 request should have been sent. - EXPECT_EQ(1u, client_->num_requests()); - // The responses to the original request and all the promised resources - // should have been received. - EXPECT_EQ(12u, client_->num_responses()); -} - -TEST_P(EndToEndTestServerPush, ServerPushOverLimitWithBlocking) { - // Tests that when server tries to send more large resources(large enough to - // be blocked by flow control window or congestion control window) than max - // open outgoing streams , server can open upto max number of outgoing - // streams for them, and the rest will be queued up. - - // Reset flow control windows. - size_t kFlowControlWnd = 20 * 1024; // 20KB. - // Response body is larger than 1 flow controlblock window. - size_t kBodySize = kFlowControlWnd * 2; - set_client_initial_stream_flow_control_receive_window(kFlowControlWnd); - // Make sure conntection level flow control window is large enough not to - // block data being sent out though they will be blocked by stream level one. - set_client_initial_session_flow_control_receive_window( - kBodySize * kNumMaxStreams + 1024); - - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - - // Set reordering to ensure that body arriving before PUSH_PROMISE is ok. - SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2)); - SetReorderPercentage(30); - - // Add a response with headers, body, and push resources. - const QuicString kBody = "body content"; - - const size_t kNumResources = kNumMaxStreams + 1; - QuicString push_urls[11]; - for (size_t i = 0; i < kNumResources; ++i) { - push_urls[i] = QuicStrCat("http://example.com/push_resources", i); - } - AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody, - push_urls, kNumResources, kBodySize); - - client_->client()->set_response_listener( - std::unique_ptr<QuicSpdyClientBase::ResponseListener>( - new TestResponseListener)); - - client_->SendRequest("https://example.com/push_example"); - - // Pause after the first response arrives. - while (!client_->response_complete()) { - // Because of priority, the first response arrived should be to original - // request. - client_->WaitForResponse(); - } - - // Check server session to see if it has max number of outgoing streams opened - // though more resources need to be pushed. - server_thread_->Pause(); - QuicDispatcher* dispatcher = - QuicServerPeer::GetDispatcher(server_thread_->server()); - ASSERT_EQ(1u, dispatcher->session_map().size()); - QuicSession* session = dispatcher->session_map().begin()->second.get(); - EXPECT_EQ(kNumMaxStreams, session->GetNumOpenOutgoingStreams()); - server_thread_->Resume(); - - EXPECT_EQ(1u, client_->num_requests()); - EXPECT_EQ(1u, client_->num_responses()); - EXPECT_EQ(kBody, client_->response_body()); - - // "Send" request for a promised resources will not really send out it because - // its response is being pushed(but blocked). And the following ack and - // flow control behavior of SendSynchronousRequests() - // will unblock the stream to finish receiving response. - client_->SendSynchronousRequest(push_urls[0]); - EXPECT_EQ(1u, client_->num_requests()); - EXPECT_EQ(2u, client_->num_responses()); - - // Do same thing for the rest 10 resources. - for (size_t i = 1; i < kNumResources; ++i) { - client_->SendSynchronousRequest(push_urls[i]); - } - - // Because of server push, client gets all pushed resources without actually - // sending requests for them. - EXPECT_EQ(1u, client_->num_requests()); - // Including response to original request, 12 responses in total were - // recieved. - EXPECT_EQ(12u, client_->num_responses()); -} - -// TODO(fayang): this test seems to cause net_unittests timeouts :| -TEST_P(EndToEndTest, DISABLED_TestHugePostWithPacketLoss) { - // This test tests a huge post with introduced packet loss from client to - // server and body size greater than 4GB, making sure QUIC code does not break - // for 32-bit builds. - ServerStreamThatDropsBodyFactory stream_factory; - SetSpdyStreamFactory(&stream_factory); - ASSERT_TRUE(Initialize()); - // Set client's epoll server's time out to 0 to make this test be finished - // within a short time. - client_->epoll_server()->set_timeout_in_us(0); - - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - SetPacketLossPercentage(1); - // To avoid storing the whole request body in memory, use a loop to repeatedly - // send body size of kSizeBytes until the whole request body size is reached. - const int kSizeBytes = 128 * 1024; - // Request body size is 4G plus one more kSizeBytes. - int64_t request_body_size_bytes = pow(2, 32) + kSizeBytes; - ASSERT_LT(INT64_C(4294967296), request_body_size_bytes); - QuicString body(kSizeBytes, 'a'); - - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - headers["content-length"] = - QuicTextUtils::Uint64ToString(request_body_size_bytes); - - client_->SendMessage(headers, "", /*fin=*/false); - - for (int i = 0; i < request_body_size_bytes / kSizeBytes; ++i) { - bool fin = (i == request_body_size_bytes - 1); - client_->SendData(QuicString(body.data(), kSizeBytes), fin); - client_->client()->WaitForEvents(); - } - VerifyCleanConnection(true); -} - -// TODO(fayang): this test seems to cause net_unittests timeouts :| -TEST_P(EndToEndTest, DISABLED_TestHugeResponseWithPacketLoss) { - // This test tests a huge response with introduced loss from server to client - // and body size greater than 4GB, making sure QUIC code does not break for - // 32-bit builds. - const int kSizeBytes = 128 * 1024; - int64_t response_body_size_bytes = pow(2, 32) + kSizeBytes; - ASSERT_LT(4294967296, response_body_size_bytes); - ServerStreamThatSendsHugeResponseFactory stream_factory( - response_body_size_bytes); - SetSpdyStreamFactory(&stream_factory); - - StartServer(); - - // Use a quic client that drops received body. - QuicTestClient* client = new QuicTestClientThatDropsBody( - server_address_, server_hostname_, client_config_, - client_supported_versions_); - client->UseWriter(client_writer_); - client->Connect(); - client_.reset(client); - static EpollEvent event(EPOLLOUT); - client_writer_->Initialize( - QuicConnectionPeer::GetHelper( - client_->client()->client_session()->connection()), - QuicConnectionPeer::GetAlarmFactory( - client_->client()->client_session()->connection()), - new ClientDelegate(client_->client())); - initialized_ = true; - ASSERT_TRUE(client_->client()->connected()); - - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - SetPacketLossPercentage(1); - client_->SendRequest("/huge_response"); - client_->WaitForResponse(); - // TODO(fayang): Fix this test to work with stateless rejects. - if (!BothSidesSupportStatelessRejects()) { - VerifyCleanConnection(true); - } -} - -TEST_P(EndToEndTest, ReleaseHeadersStreamBufferWhenIdle) { - // Tests that when client side has no active request and no waiting - // PUSH_PROMISE, its headers stream's sequencer buffer should be released. - ASSERT_TRUE(Initialize()); - client_->SendSynchronousRequest("/foo"); - QuicHeadersStream* headers_stream = QuicSpdySessionPeer::GetHeadersStream( - client_->client()->client_session()); - QuicStreamSequencer* sequencer = QuicStreamPeer::sequencer(headers_stream); - EXPECT_FALSE(QuicStreamSequencerPeer::IsUnderlyingBufferAllocated(sequencer)); -} - -TEST_P(EndToEndTest, WayTooLongRequestHeaders) { - ASSERT_TRUE(Initialize()); - SpdyHeaderBlock headers; - headers[":method"] = "GET"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - headers["key"] = QuicString(64 * 1024, 'a'); - - client_->SendMessage(headers, ""); - client_->WaitForResponse(); - EXPECT_EQ(QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE, - client_->connection_error()); -} - -class WindowUpdateObserver : public QuicConnectionDebugVisitor { - public: - WindowUpdateObserver() : num_window_update_frames_(0), num_ping_frames_(0) {} - - size_t num_window_update_frames() const { return num_window_update_frames_; } - - size_t num_ping_frames() const { return num_ping_frames_; } - - void OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame, - const QuicTime& receive_time) override { - ++num_window_update_frames_; - } - - void OnPingFrame(const QuicPingFrame& frame) override { ++num_ping_frames_; } - - private: - size_t num_window_update_frames_; - size_t num_ping_frames_; -}; - -TEST_P(EndToEndTest, WindowUpdateInAck) { - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - WindowUpdateObserver observer; - QuicConnection* client_connection = - client_->client()->client_session()->connection(); - client_connection->set_debug_visitor(&observer); - QuicTransportVersion version = client_connection->transport_version(); - // 100KB body. - QuicString body(100 * 1024, 'a'); - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - - EXPECT_EQ(kFooResponseBody, - client_->SendCustomSynchronousRequest(headers, body)); - client_->Disconnect(); - if (version > QUIC_VERSION_38) { - EXPECT_LT(0u, observer.num_window_update_frames()); - if (GetQuicReloadableFlag(quic_remove_redundant_ping)) { - EXPECT_EQ(0u, observer.num_ping_frames()); - } else { - // A redundant PING frame is bundled with each WINDOW_UPDATE frame. - EXPECT_EQ(observer.num_window_update_frames(), - observer.num_ping_frames()); - } - } else { - EXPECT_EQ(0u, observer.num_window_update_frames()); - } -} - -TEST_P(EndToEndTest, SendStatelessResetTokenInShlo) { - ASSERT_TRUE(Initialize()); - EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed()); - QuicConfig* config = client_->client()->session()->config(); - EXPECT_TRUE(config->HasReceivedStatelessResetToken()); - EXPECT_EQ(1010101u, config->ReceivedStatelessResetToken()); - client_->Disconnect(); -} - -// Regression test of b/70782529. -TEST_P(EndToEndTest, DoNotCrashOnPacketWriteError) { - ASSERT_TRUE(Initialize()); - BadPacketWriter* bad_writer = - new BadPacketWriter(/*packet_causing_write_error=*/5, - /*error_code=*/90); - std::unique_ptr<QuicTestClient> client(CreateQuicClient(bad_writer)); - - // 1 MB body. - QuicString body(1024 * 1024, 'a'); - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/foo"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - - client->SendCustomSynchronousRequest(headers, body); -} - -// Regression test for b/71711996. This test sends a connectivity probing packet -// as its last sent packet, and makes sure the server's ACK of that packet does -// not cause the client to fail. -TEST_P(EndToEndTest, LastPacketSentIsConnectivityProbing) { - ASSERT_TRUE(Initialize()); - - EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); - EXPECT_EQ("200", client_->response_headers()->find(":status")->second); - - // Wait for the client's ACK (of the response) to be received by the server. - client_->WaitForDelayedAcks(); - - // We are sending a connectivity probing packet from an unchanged client - // address, so the server will not respond to us with a connectivity probing - // packet, however the server should send an ack-only packet to us. - client_->SendConnectivityProbing(); - - // Wait for the server's last ACK to be received by the client. - client_->WaitForDelayedAcks(); -} - -class EndToEndBufferedPacketsTest : public EndToEndTest { - public: - void CreateClientWithWriter() override { - QUIC_LOG(ERROR) << "create client with reorder_writer_ "; - reorder_writer_ = new PacketReorderingWriter(); - client_.reset(EndToEndTest::CreateQuicClient(reorder_writer_)); - } - - void SetUp() override { - // Don't initialize client writer in base class. - server_writer_ = new PacketDroppingTestWriter(); - } - - protected: - PacketReorderingWriter* reorder_writer_; -}; - -INSTANTIATE_TEST_CASE_P(EndToEndBufferedPacketsTests, - EndToEndBufferedPacketsTest, - testing::ValuesIn(GetTestParams(false))); - -TEST_P(EndToEndBufferedPacketsTest, Buffer0RttRequest) { - ASSERT_TRUE(Initialize()); - // Finish one request to make sure handshake established. - client_->SendSynchronousRequest("/foo"); - // Disconnect for next 0-rtt request. - client_->Disconnect(); - - // Client get valid STK now. Do a 0-rtt request. - // Buffer a CHLO till another packets sent out. - reorder_writer_->SetDelay(1); - // Only send out a CHLO. - client_->client()->Initialize(); - client_->client()->StartConnect(); - ASSERT_TRUE(client_->client()->connected()); - - // Send a request before handshake finishes. - SpdyHeaderBlock headers; - headers[":method"] = "POST"; - headers[":path"] = "/bar"; - headers[":scheme"] = "https"; - headers[":authority"] = server_hostname_; - - client_->SendMessage(headers, ""); - client_->WaitForResponse(); - EXPECT_EQ(kBarResponseBody, client_->response_body()); - QuicConnectionStats client_stats = - client_->client()->client_session()->connection()->GetStats(); - EXPECT_EQ(0u, client_stats.packets_lost); - EXPECT_EQ(1, client_->client()->GetNumSentClientHellos()); -} -} // namespace -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/platform/impl/quic_epoll_clock.cc b/chromium/net/tools/quic/platform/impl/quic_epoll_clock.cc deleted file mode 100644 index c44c9dd44fd..00000000000 --- a/chromium/net/tools/quic/platform/impl/quic_epoll_clock.cc +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/platform/impl/quic_epoll_clock.h" - -#include "net/tools/epoll_server/epoll_server.h" - -namespace net { - -QuicEpollClock::QuicEpollClock(EpollServer* epoll_server) - : epoll_server_(epoll_server) {} - -QuicEpollClock::~QuicEpollClock() = default; - -QuicTime QuicEpollClock::ApproximateNow() const { - return QuicTime::Zero() + QuicTime::Delta::FromMicroseconds( - epoll_server_->ApproximateNowInUsec()); -} - -QuicTime QuicEpollClock::Now() const { - return QuicTime::Zero() + - QuicTime::Delta::FromMicroseconds(epoll_server_->NowInUsec()); -} - -QuicWallTime QuicEpollClock::WallNow() const { - return QuicWallTime::FromUNIXMicroseconds( - epoll_server_->ApproximateNowInUsec()); -} - -QuicTime QuicEpollClock::ConvertWallTimeToQuicTime( - const QuicWallTime& walltime) const { - return QuicTime::Zero() + - QuicTime::Delta::FromMicroseconds(walltime.ToUNIXMicroseconds()); -} - -} // namespace net diff --git a/chromium/net/tools/quic/platform/impl/quic_epoll_clock.h b/chromium/net/tools/quic/platform/impl/quic_epoll_clock.h deleted file mode 100644 index 8c125bcacdc..00000000000 --- a/chromium/net/tools/quic/platform/impl/quic_epoll_clock.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_PLATFORM_IMPL_QUIC_EPOLL_CLOCK_H_ -#define NET_TOOLS_QUIC_PLATFORM_IMPL_QUIC_EPOLL_CLOCK_H_ - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "net/quic/core/quic_time.h" -#include "net/quic/platform/api/quic_clock.h" - -namespace net { - -class EpollServer; - -// Clock to efficiently retrieve an approximately accurate time from an -// EpollServer. -class QuicEpollClock : public QuicClock { - public: - explicit QuicEpollClock(EpollServer* epoll_server); - ~QuicEpollClock() override; - - // Returns the approximate current time as a QuicTime object. - QuicTime ApproximateNow() const override; - - // Returns the current time as a QuicTime object. - // Note: this uses significant resources, please use only if needed. - QuicTime Now() const override; - - // Returns the current time as a QuicWallTime object. - // Note: this uses significant resources, please use only if needed. - QuicWallTime WallNow() const override; - - // Override to do less work in this implementation. The epoll clock is - // already based on system (unix epoch) time, no conversion required. - QuicTime ConvertWallTimeToQuicTime( - const QuicWallTime& walltime) const override; - - protected: - EpollServer* epoll_server_; - - private: - DISALLOW_COPY_AND_ASSIGN(QuicEpollClock); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_PLATFORM_IMPL_QUIC_EPOLL_CLOCK_H_ diff --git a/chromium/net/tools/quic/platform/impl/quic_epoll_clock_test.cc b/chromium/net/tools/quic/platform/impl/quic_epoll_clock_test.cc deleted file mode 100644 index 52115a72c12..00000000000 --- a/chromium/net/tools/quic/platform/impl/quic_epoll_clock_test.cc +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/platform/impl/quic_epoll_clock.h" - -#include "net/quic/platform/api/quic_test.h" -#include "net/tools/quic/test_tools/mock_epoll_server.h" - -namespace net { -namespace test { - -class QuicEpollClockTest : public QuicTest {}; - -TEST_F(QuicEpollClockTest, ApproximateNowInUsec) { - MockEpollServer epoll_server; - QuicEpollClock clock(&epoll_server); - - epoll_server.set_now_in_usec(1000000); - EXPECT_EQ(1000000, - (clock.ApproximateNow() - QuicTime::Zero()).ToMicroseconds()); - EXPECT_EQ(1u, clock.WallNow().ToUNIXSeconds()); - EXPECT_EQ(1000000u, clock.WallNow().ToUNIXMicroseconds()); - - epoll_server.AdvanceBy(5); - EXPECT_EQ(1000005, - (clock.ApproximateNow() - QuicTime::Zero()).ToMicroseconds()); - EXPECT_EQ(1u, clock.WallNow().ToUNIXSeconds()); - EXPECT_EQ(1000005u, clock.WallNow().ToUNIXMicroseconds()); - - epoll_server.AdvanceBy(10 * 1000000); - EXPECT_EQ(11u, clock.WallNow().ToUNIXSeconds()); - EXPECT_EQ(11000005u, clock.WallNow().ToUNIXMicroseconds()); -} - -TEST_F(QuicEpollClockTest, NowInUsec) { - MockEpollServer epoll_server; - QuicEpollClock clock(&epoll_server); - - epoll_server.set_now_in_usec(1000000); - EXPECT_EQ(1000000, (clock.Now() - QuicTime::Zero()).ToMicroseconds()); - - epoll_server.AdvanceBy(5); - EXPECT_EQ(1000005, (clock.Now() - QuicTime::Zero()).ToMicroseconds()); -} - -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/platform/impl/quic_socket_utils.cc b/chromium/net/tools/quic/platform/impl/quic_socket_utils.cc deleted file mode 100644 index 434e96efec1..00000000000 --- a/chromium/net/tools/quic/platform/impl/quic_socket_utils.cc +++ /dev/null @@ -1,319 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/platform/impl/quic_socket_utils.h" - -#include <errno.h> -#include <linux/net_tstamp.h> -#include <netinet/in.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/uio.h> -#include <unistd.h> -#include <string> - -#include "net/quic/core/quic_packets.h" -#include "net/quic/platform/api/quic_bug_tracker.h" -#include "net/quic/platform/api/quic_flags.h" -#include "net/quic/platform/api/quic_logging.h" -#include "net/quic/platform/api/quic_socket_address.h" - -#ifndef SO_RXQ_OVFL -#define SO_RXQ_OVFL 40 -#endif - -using std::string; - -namespace net { - -// static -void QuicSocketUtils::GetAddressAndTimestampFromMsghdr( - struct msghdr* hdr, - QuicIpAddress* address, - QuicWallTime* walltimestamp) { - if (hdr->msg_controllen > 0) { - for (cmsghdr* cmsg = CMSG_FIRSTHDR(hdr); cmsg != nullptr; - cmsg = CMSG_NXTHDR(hdr, cmsg)) { - char* addr_data = nullptr; - int len = 0; - if (cmsg->cmsg_type == IPV6_PKTINFO) { - in6_pktinfo* info = reinterpret_cast<in6_pktinfo*>(CMSG_DATA(cmsg)); - addr_data = reinterpret_cast<char*>(&info->ipi6_addr); - len = sizeof(in6_addr); - address->FromPackedString(addr_data, len); - } else if (cmsg->cmsg_type == IP_PKTINFO) { - in_pktinfo* info = reinterpret_cast<in_pktinfo*>(CMSG_DATA(cmsg)); - addr_data = reinterpret_cast<char*>(&info->ipi_addr); - len = sizeof(in_addr); - address->FromPackedString(addr_data, len); - } else if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SO_TIMESTAMPING) { - LinuxTimestamping* lts = - reinterpret_cast<LinuxTimestamping*>(CMSG_DATA(cmsg)); - timespec* ts = <s->systime; - int64_t usec = (static_cast<int64_t>(ts->tv_sec) * 1000 * 1000) + - (static_cast<int64_t>(ts->tv_nsec) / 1000); - *walltimestamp = QuicWallTime::FromUNIXMicroseconds(usec); - } - } - } -} - -// static -bool QuicSocketUtils::GetOverflowFromMsghdr(struct msghdr* hdr, - QuicPacketCount* dropped_packets) { - if (hdr->msg_controllen > 0) { - struct cmsghdr* cmsg; - for (cmsg = CMSG_FIRSTHDR(hdr); cmsg != nullptr; - cmsg = CMSG_NXTHDR(hdr, cmsg)) { - if (cmsg->cmsg_type == SO_RXQ_OVFL) { - *dropped_packets = *(reinterpret_cast<uint32_t*> CMSG_DATA(cmsg)); - return true; - } - } - } - return false; -} - -// static -bool QuicSocketUtils::GetTtlFromMsghdr(struct msghdr* hdr, int* ttl) { - if (hdr->msg_controllen > 0) { - struct cmsghdr* cmsg; - for (cmsg = CMSG_FIRSTHDR(hdr); cmsg != nullptr; - cmsg = CMSG_NXTHDR(hdr, cmsg)) { - if ((cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_TTL) || - (cmsg->cmsg_level == IPPROTO_IPV6 && - cmsg->cmsg_type == IPV6_HOPLIMIT)) { - *ttl = *(reinterpret_cast<int*>(CMSG_DATA(cmsg))); - return true; - } - } - } - return false; -} - -// static -int QuicSocketUtils::SetGetAddressInfo(int fd, int address_family) { - int get_local_ip = 1; - int rc = setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_local_ip, - sizeof(get_local_ip)); - if (rc == 0 && address_family == AF_INET6) { - rc = setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_local_ip, - sizeof(get_local_ip)); - } - return rc; -} - -// static -int QuicSocketUtils::SetGetSoftwareReceiveTimestamp(int fd) { - int timestamping = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE; - return setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, ×tamping, - sizeof(timestamping)); -} - -// static -bool QuicSocketUtils::SetSendBufferSize(int fd, size_t size) { - if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) != 0) { - LOG(ERROR) << "Failed to set socket send size"; - return false; - } - return true; -} - -// static -bool QuicSocketUtils::SetReceiveBufferSize(int fd, size_t size) { - if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) != 0) { - LOG(ERROR) << "Failed to set socket recv size"; - return false; - } - return true; -} - -// static -int QuicSocketUtils::ReadPacket(int fd, - char* buffer, - size_t buf_len, - QuicPacketCount* dropped_packets, - QuicIpAddress* self_address, - QuicWallTime* walltimestamp, - QuicSocketAddress* peer_address) { - DCHECK(peer_address != nullptr); - char cbuf[kSpaceForCmsg]; - memset(cbuf, 0, arraysize(cbuf)); - - iovec iov = {buffer, buf_len}; - struct sockaddr_storage raw_address; - msghdr hdr; - - hdr.msg_name = &raw_address; - hdr.msg_namelen = sizeof(sockaddr_storage); - hdr.msg_iov = &iov; - hdr.msg_iovlen = 1; - hdr.msg_flags = 0; - - struct cmsghdr* cmsg = reinterpret_cast<struct cmsghdr*>(cbuf); - cmsg->cmsg_len = arraysize(cbuf); - hdr.msg_control = cmsg; - hdr.msg_controllen = arraysize(cbuf); - - int bytes_read = recvmsg(fd, &hdr, 0); - - // Return before setting dropped packets: if we get EAGAIN, it will - // be 0. - if (bytes_read < 0 && errno != 0) { - if (errno != EAGAIN) { - LOG(ERROR) << "Error reading " << strerror(errno); - } - return -1; - } - - if (hdr.msg_controllen >= arraysize(cbuf)) { - QUIC_BUG << "Incorrectly set control length: " << hdr.msg_controllen - << ", expected " << arraysize(cbuf); - return -1; - } - - if (dropped_packets != nullptr) { - GetOverflowFromMsghdr(&hdr, dropped_packets); - } - - QuicIpAddress stack_address; - if (self_address == nullptr) { - self_address = &stack_address; - } - - QuicWallTime stack_walltimestamp = QuicWallTime::FromUNIXMicroseconds(0); - if (walltimestamp == nullptr) { - walltimestamp = &stack_walltimestamp; - } - - GetAddressAndTimestampFromMsghdr(&hdr, self_address, walltimestamp); - - *peer_address = QuicSocketAddress(raw_address); - return bytes_read; -} - -size_t QuicSocketUtils::SetIpInfoInCmsg(const QuicIpAddress& self_address, - cmsghdr* cmsg) { - string address_string; - if (self_address.IsIPv4()) { - cmsg->cmsg_len = CMSG_LEN(sizeof(in_pktinfo)); - cmsg->cmsg_level = IPPROTO_IP; - cmsg->cmsg_type = IP_PKTINFO; - in_pktinfo* pktinfo = reinterpret_cast<in_pktinfo*>(CMSG_DATA(cmsg)); - memset(pktinfo, 0, sizeof(in_pktinfo)); - pktinfo->ipi_ifindex = 0; - address_string = self_address.ToPackedString(); - memcpy(&pktinfo->ipi_spec_dst, address_string.c_str(), - address_string.length()); - return sizeof(in_pktinfo); - } else if (self_address.IsIPv6()) { - cmsg->cmsg_len = CMSG_LEN(sizeof(in6_pktinfo)); - cmsg->cmsg_level = IPPROTO_IPV6; - cmsg->cmsg_type = IPV6_PKTINFO; - in6_pktinfo* pktinfo = reinterpret_cast<in6_pktinfo*>(CMSG_DATA(cmsg)); - memset(pktinfo, 0, sizeof(in6_pktinfo)); - address_string = self_address.ToPackedString(); - memcpy(&pktinfo->ipi6_addr, address_string.c_str(), - address_string.length()); - return sizeof(in6_pktinfo); - } else { - NOTREACHED() << "Unrecognized IPAddress"; - return 0; - } -} - -// static -WriteResult QuicSocketUtils::WritePacket( - int fd, - const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address) { - sockaddr_storage raw_address = peer_address.generic_address(); - iovec iov = {const_cast<char*>(buffer), buf_len}; - - msghdr hdr; - hdr.msg_name = &raw_address; - hdr.msg_namelen = raw_address.ss_family == AF_INET ? sizeof(sockaddr_in) - : sizeof(sockaddr_in6); - hdr.msg_iov = &iov; - hdr.msg_iovlen = 1; - hdr.msg_flags = 0; - - const int kSpaceForIpv4 = CMSG_SPACE(sizeof(in_pktinfo)); - const int kSpaceForIpv6 = CMSG_SPACE(sizeof(in6_pktinfo)); - // kSpaceForIp should be big enough to hold both IPv4 and IPv6 packet info. - const int kSpaceForIp = - (kSpaceForIpv4 < kSpaceForIpv6) ? kSpaceForIpv6 : kSpaceForIpv4; - char cbuf[kSpaceForIp]; - if (!self_address.IsInitialized()) { - hdr.msg_control = nullptr; - hdr.msg_controllen = 0; - } else { - hdr.msg_control = cbuf; - hdr.msg_controllen = kSpaceForIp; - cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr); - SetIpInfoInCmsg(self_address, cmsg); - hdr.msg_controllen = cmsg->cmsg_len; - } - - int rc; - do { - rc = sendmsg(fd, &hdr, 0); - } while (rc < 0 && errno == EINTR); - if (rc >= 0) { - return WriteResult(WRITE_STATUS_OK, rc); - } - return WriteResult((errno == EAGAIN || errno == EWOULDBLOCK) - ? WRITE_STATUS_BLOCKED - : WRITE_STATUS_ERROR, - errno); -} - -// static -int QuicSocketUtils::CreateUDPSocket(const QuicSocketAddress& address, - int32_t receive_buffer_size, - int32_t send_buffer_size, - bool* overflow_supported) { - int address_family = address.host().AddressFamilyToInt(); - int fd = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); - if (fd < 0) { - QUIC_LOG(ERROR) << "socket() failed: " << strerror(errno); - return -1; - } - - int get_overflow = 1; - int rc = setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow, - sizeof(get_overflow)); - if (rc < 0) { - QUIC_DLOG(WARNING) << "Socket overflow detection not supported"; - } else { - *overflow_supported = true; - } - - if (!SetReceiveBufferSize(fd, receive_buffer_size)) { - return -1; - } - - if (!SetSendBufferSize(fd, send_buffer_size)) { - return -1; - } - - rc = SetGetAddressInfo(fd, address_family); - if (rc < 0) { - LOG(ERROR) << "IP detection not supported" << strerror(errno); - return -1; - } - - rc = SetGetSoftwareReceiveTimestamp(fd); - if (rc < 0) { - QUIC_LOG(WARNING) << "SO_TIMESTAMPING not supported; using fallback: " - << strerror(errno); - } - - return fd; -} - -} // namespace net diff --git a/chromium/net/tools/quic/platform/impl/quic_socket_utils.h b/chromium/net/tools/quic/platform/impl/quic_socket_utils.h deleted file mode 100644 index 6db434fad5a..00000000000 --- a/chromium/net/tools/quic/platform/impl/quic_socket_utils.h +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Some socket related helper methods for quic. - -#ifndef NET_TOOLS_QUIC_PLATFORM_IMPL_QUIC_SOCKET_UTILS_H_ -#define NET_TOOLS_QUIC_PLATFORM_IMPL_QUIC_SOCKET_UTILS_H_ - -#include <netinet/in.h> -#include <stddef.h> -#include <sys/socket.h> - -#include <string> - -#include "base/macros.h" -#include "net/base/ip_address.h" -#include "net/base/ip_endpoint.h" -#include "net/quic/core/quic_bandwidth.h" -#include "net/quic/core/quic_types.h" - -namespace net { -class QuicIpAddress; -class QuicSocketAddress; - -// This is the structure that SO_TIMESTAMPING fills into the cmsg header. It is -// well-defined, but does not have a definition in a public header. See -// https://www.kernel.org/doc/Documentation/networking/timestamping.txt for more -// information. -struct LinuxTimestamping { - // The converted system time of the timestamp. - struct timespec systime; - // Deprecated; serves only as padding. - struct timespec hwtimetrans; - // The raw hardware timestamp. - struct timespec hwtimeraw; -}; - -class QuicSocketUtils { - public: - // The first integer is for overflow. The in6_pktinfo is the larger of the - // address structures present. LinuxTimestamping is present for socket - // timestamping. The subsequent int is for ttl. - // The final int is a sentinel so the msg_controllen feedback - // can be used to detect larger control messages than there is space for. - static const int kSpaceForCmsg = - CMSG_SPACE(CMSG_LEN(sizeof(int)) + CMSG_LEN(sizeof(in6_pktinfo)) + - CMSG_LEN(sizeof(LinuxTimestamping)) + - CMSG_LEN(sizeof(int)) + - CMSG_LEN(sizeof(int))); - - // Fills in |address| if |hdr| contains IP_PKTINFO or IPV6_PKTINFO. Fills in - // |timestamp| if |hdr| contains |SO_TIMESTAMPING|. |address| and |timestamp| - // must not be null. - static void GetAddressAndTimestampFromMsghdr(struct msghdr* hdr, - QuicIpAddress* address, - QuicWallTime* walltimestamp); - - // If the msghdr contains an SO_RXQ_OVFL entry, this will set dropped_packets - // to the correct value and return true. Otherwise it will return false. - static bool GetOverflowFromMsghdr(struct msghdr* hdr, - QuicPacketCount* dropped_packets); - - // If the msghdr contains an IP_TTL entry, this will set ttl to the correct - // value and return true. Otherwise it will return false. - static bool GetTtlFromMsghdr(struct msghdr* hdr, int* ttl); - - // Sets either IP_PKTINFO or IPV6_PKTINFO on the socket, based on - // address_family. Returns the return code from setsockopt. - static int SetGetAddressInfo(int fd, int address_family); - - // Sets SO_TIMESTAMPING on the socket for software receive timestamping. - // Returns the return code from setsockopt. - static int SetGetSoftwareReceiveTimestamp(int fd); - - // Sets the send buffer size to |size| and returns false if it fails. - static bool SetSendBufferSize(int fd, size_t size); - - // Sets the receive buffer size to |size| and returns false if it fails. - static bool SetReceiveBufferSize(int fd, size_t size); - - // Reads buf_len from the socket. If reading is successful, returns bytes - // read and sets peer_address to the peer address. Otherwise returns -1. - // - // If dropped_packets is non-null, it will be set to the number of packets - // dropped on the socket since the socket was created, assuming the kernel - // supports this feature. - // - // If self_address is non-null, it will be set to the address the peer sent - // packets to, assuming a packet was read. - // - // If timestamp is non-null, it will be filled with the timestamp of the - // received packet, assuming a packet was read and the platform supports - // packet receipt timestamping. If the platform does not support packet - // receipt timestamping, timestamp will not be changed. - static int ReadPacket(int fd, - char* buffer, - size_t buf_len, - QuicPacketCount* dropped_packets, - QuicIpAddress* self_address, - QuicWallTime* walltimestamp, - QuicSocketAddress* peer_address); - - // Writes buf_len to the socket. If writing is successful, sets the result's - // status to WRITE_STATUS_OK and sets bytes_written. Otherwise sets the - // result's status to WRITE_STATUS_BLOCKED or WRITE_STATUS_ERROR and sets - // error_code to errno. - static WriteResult WritePacket(int fd, - const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address); - - // A helper for WritePacket which fills in the cmsg with the supplied self - // address. - // Returns the length of the packet info structure used. - static size_t SetIpInfoInCmsg(const QuicIpAddress& self_address, - cmsghdr* cmsg); - - // Creates a UDP socket and sets appropriate socket options for QUIC. - // Returns the created FD if successful, -1 otherwise. - // |overflow_supported| is set to true if the socket supports it. - static int CreateUDPSocket(const QuicSocketAddress& address, - int32_t receive_buffer_size, - int32_t send_buffer_size, - bool* overflow_supported); - - private: - DISALLOW_COPY_AND_ASSIGN(QuicSocketUtils); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_PLATFORM_IMPL_QUIC_SOCKET_UTILS_H_ diff --git a/chromium/net/tools/quic/platform/impl/quic_socket_utils_test.cc b/chromium/net/tools/quic/platform/impl/quic_socket_utils_test.cc deleted file mode 100644 index 7d5d173b828..00000000000 --- a/chromium/net/tools/quic/platform/impl/quic_socket_utils_test.cc +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/platform/impl/quic_socket_utils.h" - -#include <fcntl.h> - -#include <array> - -#include "net/quic/platform/api/quic_logging.h" -#include "net/quic/platform/api/quic_socket_address.h" -#include "net/quic/platform/api/quic_test.h" - -namespace net { -namespace test { -namespace { - -// A test fixture is used to ensure that all sockets are closed down gracefully -// upon test completion. Also provides a convenient API to Bind not presently -// available in QuicSocketUtils. -class QuicSocketUtilsTest : public QuicTest { - protected: - ~QuicSocketUtilsTest() override { - for (int fd : open_sockets_) { - close(fd); - } - } - - int CreateUDPSocket(const QuicSocketAddress& address) { - bool overflow_supported = false; - int fd = QuicSocketUtils::CreateUDPSocket( - address, /*receive_buffer_size =*/kDefaultSocketReceiveBuffer, - /*send_buffer_size =*/kDefaultSocketReceiveBuffer, &overflow_supported); - if (fd != -1) { - open_sockets_.push_back(fd); - } - return fd; - } - - int CreateBoundUDPSocket(QuicSocketAddress* address) { - int fd = CreateUDPSocket(*address); - *address = BindSocket(fd, *address); - if (!address->IsInitialized()) { - close(fd); - fd = -1; - } - return fd; - } - - QuicSocketAddress BindSocket(int fd, const QuicSocketAddress& address) { - QuicSocketAddress bound_address; - - if (fd == -1) { - return bound_address; - } - - sockaddr_storage bind_addr_native = address.generic_address(); - socklen_t bind_addr_size = 0; - - switch (address.host().address_family()) { - case IpAddressFamily::IP_V4: - bind_addr_size = sizeof(struct sockaddr_in); - break; - case IpAddressFamily::IP_V6: - bind_addr_size = sizeof(struct sockaddr_in6); - break; - case IpAddressFamily::IP_UNSPEC: - QUIC_LOG(FATAL) << "Unspecified IP address family"; - } - - int rc = bind(fd, reinterpret_cast<sockaddr*>(&bind_addr_native), - bind_addr_size); - if (rc != 0) { - QUIC_LOG(ERROR) << "Failed to bind socket to " << address.ToString() - << ": " << strerror(errno); - return bound_address; - } - - rc = bound_address.FromSocket(fd); - if (rc != 0) { - QUIC_LOG(ERROR) << "Failed to get bound socket address from fd: " - << strerror(errno); - bound_address = QuicSocketAddress(); - } - return bound_address; - } - - private: - std::vector<int> open_sockets_; -}; - -// This test verifies that QuicSocketUtils creates a non-blocking socket -// successfully by seeing if a read blocks. -TEST_F(QuicSocketUtilsTest, NonBlockingSocket) { - std::array<char, 512> buffer; - - QuicIpAddress localhost = QuicIpAddress::Loopback4(); - QuicSocketAddress addr(localhost, 0); - - int fd = CreateUDPSocket(addr); - ASSERT_NE(-1, fd); - - int fd_flags = fcntl(fd, F_GETFL, 0); - - // Assert so that the test errors out quickly rather than blocking below and - // relying on timeouts. - ASSERT_TRUE(fd_flags & O_NONBLOCK) << "Socket not reporting as non-blocking"; - - QuicIpAddress target_server_addr; - auto walltimestamp = QuicWallTime::Zero(); - QuicSocketAddress remote_addr; - int bytes_read = QuicSocketUtils::ReadPacket(fd, buffer.data(), buffer.size(), - nullptr, &target_server_addr, - &walltimestamp, &remote_addr); - EXPECT_EQ(-1, bytes_read); -} - -// This test verifies that we can successfully WritePacket/ReadPacket between -// two localhost sockets. -TEST_F(QuicSocketUtilsTest, PacketRoundTrip) { - QuicIpAddress localhost = QuicIpAddress::Loopback4(); - QuicSocketAddress client_addr(localhost, 0); - QuicSocketAddress server_addr(localhost, 0); - - int server_fd = CreateBoundUDPSocket(&server_addr); - int client_fd = CreateUDPSocket(client_addr); - - ASSERT_NE(-1, server_fd); - ASSERT_NE(-1, client_fd); - - { - std::array<char, 512> write_buffer; - for (size_t i = 0; i < write_buffer.size(); i++) { - write_buffer[i] = static_cast<char>(i); - } - auto res = QuicSocketUtils::WritePacket(client_fd, write_buffer.data(), - write_buffer.size(), - QuicIpAddress(), server_addr); - ASSERT_EQ(WRITE_STATUS_OK, res.status) << "Failed to write with error " - << res.error_code; - EXPECT_EQ(512, res.bytes_written); - } - - fd_set read_fds; - FD_ZERO(&read_fds); - FD_SET(server_fd, &read_fds); - - timeval select_timeout; - select_timeout.tv_sec = 5; - select_timeout.tv_usec = 0; - - int select_rc = - select(1 + server_fd, &read_fds, nullptr, nullptr, &select_timeout); - EXPECT_EQ(select_rc, 1) << "server_fd didn't become read selectable: " - << errno; - - { - std::array<char, 1024> read_buffer; - QuicIpAddress target_server_addr; - auto walltimestamp = QuicWallTime::Zero(); - QuicSocketAddress remote_addr; - int bytes_read = QuicSocketUtils::ReadPacket( - server_fd, read_buffer.data(), read_buffer.size(), nullptr, - &target_server_addr, &walltimestamp, &remote_addr); - EXPECT_EQ(512, bytes_read); - for (int i = 0; i < bytes_read; i++) { - EXPECT_EQ(static_cast<char>(i), read_buffer[i]); - } - } -} - -} // namespace -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/quic_client.cc b/chromium/net/tools/quic/quic_client.cc deleted file mode 100644 index 49af6ae8a59..00000000000 --- a/chromium/net/tools/quic/quic_client.cc +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_client.h" - -#include <errno.h> -#include <netinet/in.h> -#include <string.h> -#include <sys/epoll.h> -#include <sys/socket.h> -#include <unistd.h> - -#include "base/run_loop.h" -#include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_data_reader.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/core/quic_server_id.h" -#include "net/quic/core/spdy_utils.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/tools/quic/platform/impl/quic_socket_utils.h" -#include "net/tools/quic/quic_epoll_alarm_factory.h" -#include "net/tools/quic/quic_epoll_connection_helper.h" - -#ifndef SO_RXQ_OVFL -#define SO_RXQ_OVFL 40 -#endif - -// TODO(rtenneti): Add support for MMSG_MORE. -#define MMSG_MORE 0 -using std::string; - -namespace net { - -QuicClient::QuicClient(QuicSocketAddress server_address, - const QuicServerId& server_id, - const ParsedQuicVersionVector& supported_versions, - EpollServer* epoll_server, - std::unique_ptr<ProofVerifier> proof_verifier) - : QuicClient( - server_address, - server_id, - supported_versions, - QuicConfig(), - epoll_server, - QuicWrapUnique(new QuicClientEpollNetworkHelper(epoll_server, this)), - std::move(proof_verifier)) {} - -QuicClient::QuicClient( - QuicSocketAddress server_address, - const QuicServerId& server_id, - const ParsedQuicVersionVector& supported_versions, - EpollServer* epoll_server, - std::unique_ptr<QuicClientEpollNetworkHelper> network_helper, - std::unique_ptr<ProofVerifier> proof_verifier) - : QuicClient(server_address, - server_id, - supported_versions, - QuicConfig(), - epoll_server, - std::move(network_helper), - std::move(proof_verifier)) {} - -QuicClient::QuicClient( - QuicSocketAddress server_address, - const QuicServerId& server_id, - const ParsedQuicVersionVector& supported_versions, - const QuicConfig& config, - EpollServer* epoll_server, - std::unique_ptr<QuicClientEpollNetworkHelper> network_helper, - std::unique_ptr<ProofVerifier> proof_verifier) - : QuicSpdyClientBase( - server_id, - supported_versions, - config, - new QuicEpollConnectionHelper(epoll_server, QuicAllocator::SIMPLE), - new QuicEpollAlarmFactory(epoll_server), - std::move(network_helper), - std::move(proof_verifier)) { - set_server_address(server_address); -} - -QuicClient::~QuicClient() = default; - -QuicClientEpollNetworkHelper* QuicClient::epoll_network_helper() { - return static_cast<QuicClientEpollNetworkHelper*>(network_helper()); -} - -const QuicClientEpollNetworkHelper* QuicClient::epoll_network_helper() const { - return static_cast<const QuicClientEpollNetworkHelper*>(network_helper()); -} - -} // namespace net diff --git a/chromium/net/tools/quic/quic_client.h b/chromium/net/tools/quic/quic_client.h deleted file mode 100644 index 031cdff92ea..00000000000 --- a/chromium/net/tools/quic/quic_client.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// A toy client, which connects to a specified port and sends QUIC -// request to that endpoint. - -#ifndef NET_TOOLS_QUIC_QUIC_CLIENT_H_ -#define NET_TOOLS_QUIC_QUIC_CLIENT_H_ - -#include <cstdint> -#include <memory> -#include <string> - -#include "base/command_line.h" -#include "base/macros.h" -#include "net/quic/core/quic_client_push_promise_index.h" -#include "net/quic/core/quic_config.h" -#include "net/quic/core/quic_spdy_stream.h" -#include "net/quic/platform/api/quic_containers.h" -#include "net/tools/epoll_server/epoll_server.h" -#include "net/tools/quic/quic_client_base.h" -#include "net/tools/quic/quic_client_epoll_network_helper.h" -#include "net/tools/quic/quic_packet_reader.h" -#include "net/tools/quic/quic_process_packet_interface.h" -#include "net/tools/quic/quic_spdy_client_base.h" -#include "net/tools/quic/quic_spdy_client_session.h" - -namespace net { - -class QuicServerId; - -namespace test { -class QuicClientPeer; -} // namespace test - -class QuicClient : public QuicSpdyClientBase { - public: - // This will create its own QuicClientEpollNetworkHelper. - QuicClient(QuicSocketAddress server_address, - const QuicServerId& server_id, - const ParsedQuicVersionVector& supported_versions, - EpollServer* epoll_server, - std::unique_ptr<ProofVerifier> proof_verifier); - // This will take ownership of a passed in network primitive. - QuicClient(QuicSocketAddress server_address, - const QuicServerId& server_id, - const ParsedQuicVersionVector& supported_versions, - EpollServer* epoll_server, - std::unique_ptr<QuicClientEpollNetworkHelper> network_helper, - std::unique_ptr<ProofVerifier> proof_verifier); - QuicClient(QuicSocketAddress server_address, - const QuicServerId& server_id, - const ParsedQuicVersionVector& supported_versions, - const QuicConfig& config, - EpollServer* epoll_server, - std::unique_ptr<QuicClientEpollNetworkHelper> network_helper, - std::unique_ptr<ProofVerifier> proof_verifier); - - ~QuicClient() override; - - // Exposed for the quic client test. - int GetLatestFD() const { return epoll_network_helper()->GetLatestFD(); } - - QuicClientEpollNetworkHelper* epoll_network_helper(); - const QuicClientEpollNetworkHelper* epoll_network_helper() const; - - private: - friend class test::QuicClientPeer; - - DISALLOW_COPY_AND_ASSIGN(QuicClient); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_CLIENT_H_ diff --git a/chromium/net/tools/quic/quic_client_base.cc b/chromium/net/tools/quic/quic_client_base.cc deleted file mode 100644 index c8fa05f4d48..00000000000 --- a/chromium/net/tools/quic/quic_client_base.cc +++ /dev/null @@ -1,307 +0,0 @@ -// Copyright (c) 2015 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/tools/quic/quic_client_base.h" - -#include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_server_id.h" -#include "net/quic/core/spdy_utils.h" -#include "net/quic/core/tls_client_handshaker.h" -#include "net/quic/platform/api/quic_flags.h" -#include "net/quic/platform/api/quic_logging.h" -#include "net/quic/platform/api/quic_text_utils.h" - -using base::StringToInt; -using std::string; - -namespace net { - -QuicClientBase::NetworkHelper::~NetworkHelper() = default; - -QuicClientBase::QuicClientBase( - const QuicServerId& server_id, - const ParsedQuicVersionVector& supported_versions, - const QuicConfig& config, - QuicConnectionHelperInterface* helper, - QuicAlarmFactory* alarm_factory, - std::unique_ptr<NetworkHelper> network_helper, - std::unique_ptr<ProofVerifier> proof_verifier) - : server_id_(server_id), - initialized_(false), - local_port_(0), - config_(config), - crypto_config_(std::move(proof_verifier), - TlsClientHandshaker::CreateSslCtx()), - helper_(helper), - alarm_factory_(alarm_factory), - supported_versions_(supported_versions), - initial_max_packet_length_(0), - num_stateless_rejects_received_(0), - num_sent_client_hellos_(0), - connection_error_(QUIC_NO_ERROR), - connected_or_attempting_connect_(false), - network_helper_(std::move(network_helper)) {} - -QuicClientBase::~QuicClientBase() = default; - -bool QuicClientBase::Initialize() { - num_sent_client_hellos_ = 0; - num_stateless_rejects_received_ = 0; - connection_error_ = QUIC_NO_ERROR; - connected_or_attempting_connect_ = false; - - // If an initial flow control window has not explicitly been set, then use the - // same values that Chrome uses. - const uint32_t kSessionMaxRecvWindowSize = 15 * 1024 * 1024; // 15 MB - const uint32_t kStreamMaxRecvWindowSize = 6 * 1024 * 1024; // 6 MB - if (config()->GetInitialStreamFlowControlWindowToSend() == - kMinimumFlowControlSendWindow) { - config()->SetInitialStreamFlowControlWindowToSend(kStreamMaxRecvWindowSize); - } - if (config()->GetInitialSessionFlowControlWindowToSend() == - kMinimumFlowControlSendWindow) { - config()->SetInitialSessionFlowControlWindowToSend( - kSessionMaxRecvWindowSize); - } - - if (!network_helper_->CreateUDPSocketAndBind(server_address_, - bind_to_address_, local_port_)) { - return false; - } - - initialized_ = true; - return true; -} - -bool QuicClientBase::Connect() { - // Attempt multiple connects until the maximum number of client hellos have - // been sent. - while (!connected() && - GetNumSentClientHellos() <= QuicCryptoClientStream::kMaxClientHellos) { - StartConnect(); - while (EncryptionBeingEstablished()) { - WaitForEvents(); - } - if (GetQuicReloadableFlag(enable_quic_stateless_reject_support) && - connected()) { - // Resend any previously queued data. - ResendSavedData(); - } - if (session() != nullptr && - session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { - // We've successfully created a session but we're not connected, and there - // is no stateless reject to recover from. Give up trying. - break; - } - } - if (!connected() && - GetNumSentClientHellos() > QuicCryptoClientStream::kMaxClientHellos && - session() != nullptr && - session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { - // The overall connection failed due too many stateless rejects. - set_connection_error(QUIC_CRYPTO_TOO_MANY_REJECTS); - } - return session()->connection()->connected(); -} - -void QuicClientBase::StartConnect() { - DCHECK(initialized_); - DCHECK(!connected()); - QuicPacketWriter* writer = network_helper_->CreateQuicPacketWriter(); - if (connected_or_attempting_connect()) { - // If the last error was not a stateless reject, then the queued up data - // does not need to be resent. - if (session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { - ClearDataToResend(); - } - // Before we destroy the last session and create a new one, gather its stats - // and update the stats for the overall connection. - UpdateStats(); - } - - session_ = CreateQuicClientSession(new QuicConnection( - GetNextConnectionId(), server_address(), helper(), alarm_factory(), - writer, - /* owns_writer= */ false, Perspective::IS_CLIENT, supported_versions())); - if (initial_max_packet_length_ != 0) { - session()->connection()->SetMaxPacketLength(initial_max_packet_length_); - } - // Reset |writer()| after |session()| so that the old writer outlives the old - // session. - set_writer(writer); - InitializeSession(); - set_connected_or_attempting_connect(true); -} - -void QuicClientBase::InitializeSession() { - session()->Initialize(); -} - -void QuicClientBase::Disconnect() { - DCHECK(initialized_); - - initialized_ = false; - if (connected()) { - session()->connection()->CloseConnection( - QUIC_PEER_GOING_AWAY, "Client disconnecting", - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - } - - ClearDataToResend(); - - network_helper_->CleanUpAllUDPSockets(); -} - -ProofVerifier* QuicClientBase::proof_verifier() const { - return crypto_config_.proof_verifier(); -} - -bool QuicClientBase::EncryptionBeingEstablished() { - return !session_->IsEncryptionEstablished() && - session_->connection()->connected(); -} - -bool QuicClientBase::WaitForEvents() { - DCHECK(connected()); - - network_helper_->RunEventLoop(); - - DCHECK(session() != nullptr); - if (!connected() && - session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { - DCHECK(GetQuicReloadableFlag(enable_quic_stateless_reject_support)); - QUIC_DLOG(INFO) << "Detected stateless reject while waiting for events. " - << "Attempting to reconnect."; - Connect(); - } - - return session()->num_active_requests() != 0; -} - -bool QuicClientBase::MigrateSocket(const QuicIpAddress& new_host) { - if (!connected()) { - return false; - } - - network_helper_->CleanUpAllUDPSockets(); - - set_bind_to_address(new_host); - if (!network_helper_->CreateUDPSocketAndBind(server_address_, - bind_to_address_, local_port_)) { - return false; - } - - session()->connection()->SetSelfAddress( - network_helper_->GetLatestClientAddress()); - - QuicPacketWriter* writer = network_helper_->CreateQuicPacketWriter(); - set_writer(writer); - session()->connection()->SetQuicPacketWriter(writer, false); - - return true; -} - -QuicSession* QuicClientBase::session() { - return session_.get(); -} - -QuicClientBase::NetworkHelper* QuicClientBase::network_helper() { - return network_helper_.get(); -} - -const QuicClientBase::NetworkHelper* QuicClientBase::network_helper() const { - return network_helper_.get(); -} - -void QuicClientBase::WaitForStreamToClose(QuicStreamId id) { - DCHECK(connected()); - - while (connected() && !session_->IsClosedStream(id)) { - WaitForEvents(); - } -} - -bool QuicClientBase::WaitForCryptoHandshakeConfirmed() { - DCHECK(connected()); - - while (connected() && !session_->IsCryptoHandshakeConfirmed()) { - WaitForEvents(); - } - - // If the handshake fails due to a timeout, the connection will be closed. - QUIC_LOG_IF(ERROR, !connected()) << "Handshake with server failed."; - return connected(); -} - -bool QuicClientBase::connected() const { - return session_.get() && session_->connection() && - session_->connection()->connected(); -} - -bool QuicClientBase::goaway_received() const { - return session_ != nullptr && session_->goaway_received(); -} - -int QuicClientBase::GetNumSentClientHellos() { - // If we are not actively attempting to connect, the session object - // corresponds to the previous connection and should not be used. - const int current_session_hellos = !connected_or_attempting_connect_ - ? 0 - : GetNumSentClientHellosFromSession(); - return num_sent_client_hellos_ + current_session_hellos; -} - -void QuicClientBase::UpdateStats() { - num_sent_client_hellos_ += GetNumSentClientHellosFromSession(); - if (session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) { - ++num_stateless_rejects_received_; - } -} - -int QuicClientBase::GetNumReceivedServerConfigUpdates() { - // If we are not actively attempting to connect, the session object - // corresponds to the previous connection and should not be used. - // We do not need to take stateless rejects into account, since we - // don't expect any scup messages to be sent during a - // statelessly-rejected connection. - return !connected_or_attempting_connect_ - ? 0 - : GetNumReceivedServerConfigUpdatesFromSession(); -} - -QuicErrorCode QuicClientBase::connection_error() const { - // Return the high-level error if there was one. Otherwise, return the - // connection error from the last session. - if (connection_error_ != QUIC_NO_ERROR) { - return connection_error_; - } - if (session_ == nullptr) { - return QUIC_NO_ERROR; - } - return session_->error(); -} - -QuicConnectionId QuicClientBase::GetNextConnectionId() { - QuicConnectionId server_designated_id = GetNextServerDesignatedConnectionId(); - return server_designated_id ? server_designated_id - : GenerateNewConnectionId(); -} - -QuicConnectionId QuicClientBase::GetNextServerDesignatedConnectionId() { - QuicCryptoClientConfig::CachedState* cached = - crypto_config_.LookupOrCreate(server_id_); - // If the cached state indicates that we should use a server-designated - // connection ID, then return that connection ID. - CHECK(cached != nullptr) << "QuicClientCryptoConfig::LookupOrCreate returned " - << "unexpected nullptr."; - return cached->has_server_designated_connection_id() - ? cached->GetNextServerDesignatedConnectionId() - : 0; -} - -QuicConnectionId QuicClientBase::GenerateNewConnectionId() { - return QuicRandom::GetInstance()->RandUint64(); -} - -} // namespace net diff --git a/chromium/net/tools/quic/quic_client_base.h b/chromium/net/tools/quic/quic_client_base.h deleted file mode 100644 index f3d1d5aeee2..00000000000 --- a/chromium/net/tools/quic/quic_client_base.h +++ /dev/null @@ -1,357 +0,0 @@ -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// A base class for the toy client, which connects to a specified port and sends -// QUIC request to that endpoint. - -#ifndef NET_TOOLS_QUIC_QUIC_CLIENT_BASE_H_ -#define NET_TOOLS_QUIC_QUIC_CLIENT_BASE_H_ - -#include <string> - -#include "base/macros.h" -#include "net/quic/core/crypto/crypto_handshake.h" -#include "net/quic/core/quic_client_push_promise_index.h" -#include "net/quic/core/quic_config.h" -#include "net/quic/platform/api/quic_socket_address.h" -#include "net/quic/platform/api/quic_string_piece.h" -#include "net/tools/quic/quic_spdy_client_session.h" -#include "net/tools/quic/quic_spdy_client_stream.h" - -namespace net { - -class ProofVerifier; -class QuicServerId; - -// QuicClientBase handles establishing a connection to the passed in -// server id, including ensuring that it supports the passed in versions -// and config. -// Subclasses derived from this class are responsible for creating the -// actual QuicSession instance, as well as defining functions that -// create and run the underlying network transport. -class QuicClientBase { - public: - // An interface to various network events that the QuicClient will need to - // interact with. - class NetworkHelper { - public: - virtual ~NetworkHelper(); - - // Runs one iteration of the event loop. - virtual void RunEventLoop() = 0; - - // Used during initialization: creates the UDP socket FD, sets socket - // options, and binds the socket to our address. - virtual bool CreateUDPSocketAndBind(QuicSocketAddress server_address, - QuicIpAddress bind_to_address, - int bind_to_port) = 0; - - // Unregister and close all open UDP sockets. - virtual void CleanUpAllUDPSockets() = 0; - - // If the client has at least one UDP socket, return address of the latest - // created one. Otherwise, return an empty socket address. - virtual QuicSocketAddress GetLatestClientAddress() const = 0; - - // Creates a packet writer to be used for the next connection. - virtual QuicPacketWriter* CreateQuicPacketWriter() = 0; - }; - - QuicClientBase(const QuicServerId& server_id, - const ParsedQuicVersionVector& supported_versions, - const QuicConfig& config, - QuicConnectionHelperInterface* helper, - QuicAlarmFactory* alarm_factory, - std::unique_ptr<NetworkHelper> network_helper, - std::unique_ptr<ProofVerifier> proof_verifier); - - virtual ~QuicClientBase(); - - // Initializes the client to create a connection. Should be called exactly - // once before calling StartConnect or Connect. Returns true if the - // initialization succeeds, false otherwise. - virtual bool Initialize(); - - // "Connect" to the QUIC server, including performing synchronous crypto - // handshake. - bool Connect(); - - // Start the crypto handshake. This can be done in place of the synchronous - // Connect(), but callers are responsible for making sure the crypto handshake - // completes. - void StartConnect(); - - // Calls session()->Initialize(). Subclasses may override this if any extra - // initialization needs to be done. Subclasses should expect that session() - // is non-null and valid. - virtual void InitializeSession(); - - // Disconnects from the QUIC server. - void Disconnect(); - - // Returns true if the crypto handshake has yet to establish encryption. - // Returns false if encryption is active (even if the server hasn't confirmed - // the handshake) or if the connection has been closed. - bool EncryptionBeingEstablished(); - - // Wait for events until the stream with the given ID is closed. - void WaitForStreamToClose(QuicStreamId id); - - // Wait for events until the handshake is confirmed. - // Returns true if the crypto handshake succeeds, false otherwise. - bool WaitForCryptoHandshakeConfirmed() WARN_UNUSED_RESULT; - - // Wait up to 50ms, and handle any events which occur. - // Returns true if there are any outstanding requests. - bool WaitForEvents(); - - // Migrate to a new socket during an active connection. - bool MigrateSocket(const QuicIpAddress& new_host); - - QuicSession* session(); - - bool connected() const; - bool goaway_received() const; - - const QuicServerId& server_id() const { return server_id_; } - - // This should only be set before the initial Connect() - void set_server_id(const QuicServerId& server_id) { server_id_ = server_id; } - - void SetUserAgentID(const std::string& user_agent_id) { - crypto_config_.set_user_agent_id(user_agent_id); - } - - // SetChannelIDSource sets a ChannelIDSource that will be called, when the - // server supports channel IDs, to obtain a channel ID for signing a message - // proving possession of the channel ID. This object takes ownership of - // |source|. - void SetChannelIDSource(ChannelIDSource* source) { - crypto_config_.SetChannelIDSource(source); - } - - // UseTokenBinding enables token binding negotiation in the client. This - // should only be called before the initial Connect(). The client will still - // need to check that token binding is negotiated with the server, and add - // token binding headers to requests if so. server, and add token binding - // headers to requests if so. The negotiated token binding parameters can be - // found on the QuicCryptoNegotiatedParameters object in - // token_binding_key_param. - void UseTokenBinding() { - crypto_config_.tb_key_params = QuicTagVector{kTB10}; - } - - const ParsedQuicVersionVector& supported_versions() const { - return supported_versions_; - } - - void SetSupportedVersions(const ParsedQuicVersionVector& versions) { - supported_versions_ = versions; - } - - QuicConfig* config() { return &config_; } - - QuicCryptoClientConfig* crypto_config() { return &crypto_config_; } - - // Change the initial maximum packet size of the connection. Has to be called - // before Connect()/StartConnect() in order to have any effect. - void set_initial_max_packet_length(QuicByteCount initial_max_packet_length) { - initial_max_packet_length_ = initial_max_packet_length; - } - - int num_stateless_rejects_received() const { - return num_stateless_rejects_received_; - } - - // The number of client hellos sent, taking stateless rejects into - // account. In the case of a stateless reject, the initial - // connection object may be torn down and a new one created. The - // user cannot rely upon the latest connection object to get the - // total number of client hellos sent, and should use this function - // instead. - int GetNumSentClientHellos(); - - // Gather the stats for the last session and update the stats for the overall - // connection. - void UpdateStats(); - - // The number of server config updates received. We assume no - // updates can be sent during a previously, statelessly rejected - // connection, so only the latest session is taken into account. - int GetNumReceivedServerConfigUpdates(); - - // Returns any errors that occurred at the connection-level (as - // opposed to the session-level). When a stateless reject occurs, - // the error of the last session may not reflect the overall state - // of the connection. - QuicErrorCode connection_error() const; - void set_connection_error(QuicErrorCode connection_error) { - connection_error_ = connection_error; - } - - bool connected_or_attempting_connect() const { - return connected_or_attempting_connect_; - } - void set_connected_or_attempting_connect( - bool connected_or_attempting_connect) { - connected_or_attempting_connect_ = connected_or_attempting_connect; - } - - QuicPacketWriter* writer() { return writer_.get(); } - void set_writer(QuicPacketWriter* writer) { - if (writer_.get() != writer) { - writer_.reset(writer); - } - } - void reset_writer() { writer_.reset(); } - - ProofVerifier* proof_verifier() const; - - void set_bind_to_address(QuicIpAddress address) { - bind_to_address_ = address; - } - - QuicIpAddress bind_to_address() const { return bind_to_address_; } - - void set_local_port(int local_port) { local_port_ = local_port; } - - int local_port() const { return local_port_; } - - const QuicSocketAddress& server_address() const { return server_address_; } - - void set_server_address(const QuicSocketAddress& server_address) { - server_address_ = server_address; - } - - QuicConnectionHelperInterface* helper() { return helper_.get(); } - - NetworkHelper* network_helper(); - const NetworkHelper* network_helper() const; - - bool initialized() const { return initialized_; } - - protected: - // TODO(rch): Move GetNumSentClientHellosFromSession and - // GetNumReceivedServerConfigUpdatesFromSession into a new/better - // QuicSpdyClientSession class. The current inherits dependencies from - // Spdy. When that happens this class and all its subclasses should - // work with QuicSpdyClientSession instead of QuicSession. - // That will obviate the need for the pure virtual functions below. - - // Extract the number of sent client hellos from the session. - virtual int GetNumSentClientHellosFromSession() = 0; - - // The number of server config updates received. We assume no - // updates can be sent during a previously, statelessly rejected - // connection, so only the latest session is taken into account. - virtual int GetNumReceivedServerConfigUpdatesFromSession() = 0; - - // If this client supports buffering data, resend it. - virtual void ResendSavedData() = 0; - - // If this client supports buffering data, clear it. - virtual void ClearDataToResend() = 0; - - // Takes ownership of |connection|. If you override this function, - // you probably want to call ResetSession() in your destructor. - // TODO(rch): Change the connection parameter to take in a - // std::unique_ptr<QuicConnection> instead. - virtual std::unique_ptr<QuicSession> CreateQuicClientSession( - QuicConnection* connection) = 0; - - // Generates the next ConnectionId for |server_id_|. By default, if the - // cached server config contains a server-designated ID, that ID will be - // returned. Otherwise, the next random ID will be returned. - QuicConnectionId GetNextConnectionId(); - - // Returns the next server-designated ConnectionId from the cached config for - // |server_id_|, if it exists. Otherwise, returns 0. - QuicConnectionId GetNextServerDesignatedConnectionId(); - - // Generates a new, random connection ID (as opposed to a server-designated - // connection ID). - virtual QuicConnectionId GenerateNewConnectionId(); - - QuicAlarmFactory* alarm_factory() { return alarm_factory_.get(); } - - // Subclasses may need to explicitly clear the session on destruction - // if they create it with objects that will be destroyed before this is. - // You probably want to call this if you override CreateQuicSpdyClientSession. - void ResetSession() { session_.reset(); } - - private: - // |server_id_| is a tuple (hostname, port, is_https) of the server. - QuicServerId server_id_; - - // Tracks if the client is initialized to connect. - bool initialized_; - - // Address of the server. - QuicSocketAddress server_address_; - - // If initialized, the address to bind to. - QuicIpAddress bind_to_address_; - - // Local port to bind to. Initialize to 0. - int local_port_; - - // config_ and crypto_config_ contain configuration and cached state about - // servers. - QuicConfig config_; - QuicCryptoClientConfig crypto_config_; - - // Helper to be used by created connections. Must outlive |session_|. - std::unique_ptr<QuicConnectionHelperInterface> helper_; - - // Alarm factory to be used by created connections. Must outlive |session_|. - std::unique_ptr<QuicAlarmFactory> alarm_factory_; - - // Writer used to actually send packets to the wire. Must outlive |session_|. - std::unique_ptr<QuicPacketWriter> writer_; - - // Session which manages streams. - std::unique_ptr<QuicSession> session_; - - // This vector contains QUIC versions which we currently support. - // This should be ordered such that the highest supported version is the first - // element, with subsequent elements in descending order (versions can be - // skipped as necessary). We will always pick supported_versions_[0] as the - // initial version to use. - ParsedQuicVersionVector supported_versions_; - - // The initial value of maximum packet size of the connection. If set to - // zero, the default is used. - QuicByteCount initial_max_packet_length_; - - // The number of stateless rejects received during the current/latest - // connection. - // TODO(jokulik): Consider some consistent naming scheme (or other) for member - // variables that are kept per-request, per-connection, and over the client's - // lifetime. - int num_stateless_rejects_received_; - - // The number of hellos sent during the current/latest connection. - int num_sent_client_hellos_; - - // Used to store any errors that occurred with the overall connection (as - // opposed to that associated with the last session object). - QuicErrorCode connection_error_; - - // True when the client is attempting to connect or re-connect the session (in - // the case of a stateless reject). Set to false between a call to - // Disconnect() and the subsequent call to StartConnect(). When - // connected_or_attempting_connect_ is false, the session object corresponds - // to the previous client-level connection. - bool connected_or_attempting_connect_; - - // The network helper used to create sockets and manage the event loop. - // Not owned by this class. - std::unique_ptr<NetworkHelper> network_helper_; - - DISALLOW_COPY_AND_ASSIGN(QuicClientBase); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_CLIENT_BASE_H_ diff --git a/chromium/net/tools/quic/quic_client_bin.cc b/chromium/net/tools/quic/quic_client_bin.cc deleted file mode 100644 index 7a2249b80e9..00000000000 --- a/chromium/net/tools/quic/quic_client_bin.cc +++ /dev/null @@ -1,384 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// A binary wrapper for QuicClient. -// Connects to a host using QUIC, sends a request to the provided URL, and -// displays the response. -// -// Some usage examples: -// -// TODO(rtenneti): make --host optional by getting IP Address of URL's host. -// -// Get IP address of the www.google.com -// IP=`dig www.google.com +short | head -1` -// -// Standard request/response: -// quic_client http://www.google.com --host=${IP} -// quic_client http://www.google.com --quiet --host=${IP} -// quic_client https://www.google.com --port=443 --host=${IP} -// -// Use a specific version: -// quic_client http://www.google.com --quic_version=23 --host=${IP} -// -// Send a POST instead of a GET: -// quic_client http://www.google.com --body="this is a POST body" --host=${IP} -// -// Append additional headers to the request: -// quic_client http://www.google.com --host=${IP} -// --headers="Header-A: 1234; Header-B: 5678" -// -// Connect to a host different to the URL being requested: -// Get IP address of the www.google.com -// IP=`dig www.google.com +short | head -1` -// quic_client mail.google.com --host=${IP} -// -// Try to connect to a host which does not speak QUIC: -// Get IP address of the www.example.com -// IP=`dig www.example.com +short | head -1` -// quic_client http://www.example.com --host=${IP} - -#include <iostream> - -#include "base/at_exit.h" -#include "base/command_line.h" -#include "base/message_loop/message_loop.h" -#include "base/task_scheduler/task_scheduler.h" -#include "net/base/net_errors.h" -#include "net/base/privacy_mode.h" -#include "net/cert/cert_verifier.h" -#include "net/cert/ct_known_logs.h" -#include "net/cert/ct_log_verifier.h" -#include "net/cert/multi_log_ct_verifier.h" -#include "net/http/transport_security_state.h" -#include "net/quic/chromium/crypto/proof_verifier_chromium.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/core/quic_server_id.h" -#include "net/quic/platform/api/quic_flags.h" -#include "net/quic/platform/api/quic_ptr_util.h" -#include "net/quic/platform/api/quic_socket_address.h" -#include "net/quic/platform/api/quic_str_cat.h" -#include "net/quic/platform/api/quic_string_piece.h" -#include "net/quic/platform/api/quic_text_utils.h" -#include "net/quic/platform/api/quic_url.h" -#include "net/spdy/core/spdy_header_block.h" -#include "net/tools/epoll_server/epoll_server.h" -#include "net/tools/quic/quic_client.h" -#include "net/tools/quic/synchronous_host_resolver.h" - -using net::CertVerifier; -using net::CTPolicyEnforcer; -using net::CTVerifier; -using net::MultiLogCTVerifier; -using net::ProofVerifier; -using net::ProofVerifierChromium; -using net::QuicStringPiece; -using net::QuicTextUtils; -using net::QuicUrl; -using net::SpdyHeaderBlock; -using net::TransportSecurityState; -using std::cout; -using std::cerr; -using std::endl; -using std::string; - -// The IP or hostname the quic client will connect to. -string FLAGS_host = ""; -// The port to connect to. -int32_t FLAGS_port = 0; -// If set, send a POST with this body. -string FLAGS_body = ""; -// If set, contents are converted from hex to ascii, before sending as body of -// a POST. e.g. --body_hex=\"68656c6c6f\" -string FLAGS_body_hex = ""; -// A semicolon separated list of key:value pairs to add to request headers. -string FLAGS_headers = ""; -// Set to true for a quieter output experience. -bool FLAGS_quiet = false; -// QUIC version to speak, e.g. 21. If not set, then all available versions are -// offered in the handshake. -int32_t FLAGS_quic_version = -1; -// If true, a version mismatch in the handshake is not considered a failure. -// Useful for probing a server to determine if it speaks any version of QUIC. -bool FLAGS_version_mismatch_ok = false; -// If true, an HTTP response code of 3xx is considered to be a successful -// response, otherwise a failure. -bool FLAGS_redirect_is_success = true; -// Initial MTU of the connection. -int32_t FLAGS_initial_mtu = 0; - -class FakeProofVerifier : public ProofVerifier { - public: - net::QuicAsyncStatus VerifyProof( - const string& /*hostname*/, - const uint16_t /*port*/, - const string& /*server_config*/, - net::QuicTransportVersion /*quic_version*/, - QuicStringPiece /*chlo_hash*/, - const std::vector<string>& /*certs*/, - const string& /*cert_sct*/, - const string& /*signature*/, - const net::ProofVerifyContext* /*context*/, - string* /*error_details*/, - std::unique_ptr<net::ProofVerifyDetails>* /*details*/, - std::unique_ptr<net::ProofVerifierCallback> /*callback*/) override { - return net::QUIC_SUCCESS; - } - - net::QuicAsyncStatus VerifyCertChain( - const std::string& /*hostname*/, - const std::vector<std::string>& /*certs*/, - const net::ProofVerifyContext* /*verify_context*/, - std::string* /*error_details*/, - std::unique_ptr<net::ProofVerifyDetails>* /*verify_details*/, - std::unique_ptr<net::ProofVerifierCallback> /*callback*/) override { - return net::QUIC_SUCCESS; - } -}; - -int main(int argc, char* argv[]) { - base::TaskScheduler::CreateAndStartWithDefaultParams("quic_client"); - base::CommandLine::Init(argc, argv); - base::CommandLine* line = base::CommandLine::ForCurrentProcess(); - const base::CommandLine::StringVector& urls = line->GetArgs(); - - logging::LoggingSettings settings; - settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; - CHECK(logging::InitLogging(settings)); - - if (line->HasSwitch("h") || line->HasSwitch("help") || urls.empty()) { - const char* help_str = - "Usage: quic_client [options] <url>\n" - "\n" - "<url> with scheme must be provided (e.g. http://www.google.com)\n\n" - "Options:\n" - "-h, --help show this help message and exit\n" - "--host=<host> specify the IP address of the hostname to " - "connect to\n" - "--port=<port> specify the port to connect to\n" - "--body=<body> specify the body to post\n" - "--body_hex=<body_hex> specify the body_hex to be printed out\n" - "--headers=<headers> specify a semicolon separated list of " - "key:value pairs to add to request headers\n" - "--quiet specify for a quieter output experience\n" - "--quic-version=<quic version> specify QUIC version to speak\n" - "--version_mismatch_ok if specified a version mismatch in the " - "handshake is not considered a failure\n" - "--redirect_is_success if specified an HTTP response code of 3xx " - "is considered to be a successful response, otherwise a failure\n" - "--initial_mtu=<initial_mtu> specify the initial MTU of the connection" - "\n" - "--disable-certificate-verification do not verify certificates\n"; - cout << help_str; - exit(0); - } - if (line->HasSwitch("host")) { - FLAGS_host = line->GetSwitchValueASCII("host"); - } - if (line->HasSwitch("port")) { - if (!base::StringToInt(line->GetSwitchValueASCII("port"), &FLAGS_port)) { - std::cerr << "--port must be an integer\n"; - return 1; - } - } - if (line->HasSwitch("body")) { - FLAGS_body = line->GetSwitchValueASCII("body"); - } - if (line->HasSwitch("body_hex")) { - FLAGS_body_hex = line->GetSwitchValueASCII("body_hex"); - } - if (line->HasSwitch("headers")) { - FLAGS_headers = line->GetSwitchValueASCII("headers"); - } - if (line->HasSwitch("quiet")) { - FLAGS_quiet = true; - } - if (line->HasSwitch("quic-version")) { - int quic_version; - if (base::StringToInt(line->GetSwitchValueASCII("quic-version"), - &quic_version)) { - FLAGS_quic_version = quic_version; - } - } - if (line->HasSwitch("version_mismatch_ok")) { - FLAGS_version_mismatch_ok = true; - } - if (line->HasSwitch("redirect_is_success")) { - FLAGS_redirect_is_success = true; - } - if (line->HasSwitch("initial_mtu")) { - if (!base::StringToInt(line->GetSwitchValueASCII("initial_mtu"), - &FLAGS_initial_mtu)) { - std::cerr << "--initial_mtu must be an integer\n"; - return 1; - } - } - - VLOG(1) << "server host: " << FLAGS_host << " port: " << FLAGS_port - << " body: " << FLAGS_body << " headers: " << FLAGS_headers - << " quiet: " << FLAGS_quiet - << " quic-version: " << FLAGS_quic_version - << " version_mismatch_ok: " << FLAGS_version_mismatch_ok - << " redirect_is_success: " << FLAGS_redirect_is_success - << " initial_mtu: " << FLAGS_initial_mtu; - - base::AtExitManager exit_manager; - base::MessageLoopForIO message_loop; - - // Determine IP address to connect to from supplied hostname. - net::QuicIpAddress ip_addr; - - QuicUrl url(urls[0], "https"); - string host = FLAGS_host; - if (host.empty()) { - host = url.host(); - } - int port = FLAGS_port; - if (port == 0) { - port = url.port(); - } - if (!ip_addr.FromString(host)) { - net::AddressList addresses; - int rv = net::SynchronousHostResolver::Resolve(host, &addresses); - if (rv != net::OK) { - LOG(ERROR) << "Unable to resolve '" << host - << "' : " << net::ErrorToShortString(rv); - return 1; - } - ip_addr = - net::QuicIpAddress(net::QuicIpAddressImpl(addresses[0].address())); - } - - string host_port = net::QuicStrCat(ip_addr.ToString(), ":", port); - VLOG(1) << "Resolved " << host << " to " << host_port << endl; - - // Build the client, and try to connect. - net::EpollServer epoll_server; - net::QuicServerId server_id(url.host(), url.port(), - net::PRIVACY_MODE_DISABLED); - net::ParsedQuicVersionVector versions = net::AllSupportedVersions(); - if (FLAGS_quic_version != -1) { - versions.clear(); - versions.push_back(net::ParsedQuicVersion( - net::PROTOCOL_QUIC_CRYPTO, - static_cast<net::QuicTransportVersion>(FLAGS_quic_version))); - } - // For secure QUIC we need to verify the cert chain. - std::unique_ptr<CertVerifier> cert_verifier(CertVerifier::CreateDefault()); - std::unique_ptr<TransportSecurityState> transport_security_state( - new TransportSecurityState); - std::unique_ptr<MultiLogCTVerifier> ct_verifier(new MultiLogCTVerifier()); - ct_verifier->AddLogs(net::ct::CreateLogVerifiersForKnownLogs()); - std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer(new CTPolicyEnforcer()); - std::unique_ptr<ProofVerifier> proof_verifier; - if (line->HasSwitch("disable-certificate-verification")) { - proof_verifier = net::QuicMakeUnique<FakeProofVerifier>(); - } else { - proof_verifier = net::QuicMakeUnique<ProofVerifierChromium>( - cert_verifier.get(), ct_policy_enforcer.get(), - transport_security_state.get(), ct_verifier.get()); - } - net::QuicClient client(net::QuicSocketAddress(ip_addr, port), server_id, - versions, &epoll_server, std::move(proof_verifier)); - client.set_initial_max_packet_length( - FLAGS_initial_mtu != 0 ? FLAGS_initial_mtu : net::kDefaultMaxPacketSize); - if (!client.Initialize()) { - cerr << "Failed to initialize client." << endl; - return 1; - } - if (!client.Connect()) { - net::QuicErrorCode error = client.session()->error(); - if (FLAGS_version_mismatch_ok && error == net::QUIC_INVALID_VERSION) { - cout << "Server talks QUIC, but none of the versions supported by " - << "this client: " << ParsedQuicVersionVectorToString(versions) - << endl; - // Version mismatch is not deemed a failure. - return 0; - } - cerr << "Failed to connect to " << host_port - << ". Error: " << net::QuicErrorCodeToString(error) << endl; - return 1; - } - cout << "Connected to " << host_port << endl; - - // Construct the string body from flags, if provided. - string body = FLAGS_body; - if (!FLAGS_body_hex.empty()) { - DCHECK(FLAGS_body.empty()) << "Only set one of --body and --body_hex."; - body = QuicTextUtils::HexDecode(FLAGS_body_hex); - } - - // Construct a GET or POST request for supplied URL. - SpdyHeaderBlock header_block; - header_block[":method"] = body.empty() ? "GET" : "POST"; - header_block[":scheme"] = url.scheme(); - header_block[":authority"] = url.HostPort(); - header_block[":path"] = url.PathParamsQuery(); - - // Append any additional headers supplied on the command line. - for (QuicStringPiece sp : QuicTextUtils::Split(FLAGS_headers, ';')) { - QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&sp); - if (sp.empty()) { - continue; - } - std::vector<QuicStringPiece> kv = QuicTextUtils::Split(sp, ':'); - QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[0]); - QuicTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[1]); - header_block[kv[0]] = kv[1]; - } - - // Make sure to store the response, for later output. - client.set_store_response(true); - - // Send the request. - client.SendRequestAndWaitForResponse(header_block, body, /*fin=*/true); - - // Print request and response details. - if (!FLAGS_quiet) { - cout << "Request:" << endl; - cout << "headers:" << header_block.DebugString(); - if (!FLAGS_body_hex.empty()) { - // Print the user provided hex, rather than binary body. - cout << "body:\n" - << QuicTextUtils::HexDump(QuicTextUtils::HexDecode(FLAGS_body_hex)) - << endl; - } else { - cout << "body: " << body << endl; - } - cout << endl; - - if (!client.preliminary_response_headers().empty()) { - cout << "Preliminary response headers: " - << client.preliminary_response_headers() << endl; - cout << endl; - } - - cout << "Response:" << endl; - cout << "headers: " << client.latest_response_headers() << endl; - string response_body = client.latest_response_body(); - if (!FLAGS_body_hex.empty()) { - // Assume response is binary data. - cout << "body:\n" << QuicTextUtils::HexDump(response_body) << endl; - } else { - cout << "body: " << response_body << endl; - } - cout << "trailers: " << client.latest_response_trailers() << endl; - } - - size_t response_code = client.latest_response_code(); - if (response_code >= 200 && response_code < 300) { - cout << "Request succeeded (" << response_code << ")." << endl; - return 0; - } else if (response_code >= 300 && response_code < 400) { - if (FLAGS_redirect_is_success) { - cout << "Request succeeded (redirect " << response_code << ")." << endl; - return 0; - } else { - cout << "Request failed (redirect " << response_code << ")." << endl; - return 1; - } - } else { - cerr << "Request failed (" << response_code << ")." << endl; - return 1; - } -} diff --git a/chromium/net/tools/quic/quic_client_epoll_network_helper.cc b/chromium/net/tools/quic/quic_client_epoll_network_helper.cc deleted file mode 100644 index fefaae4c654..00000000000 --- a/chromium/net/tools/quic/quic_client_epoll_network_helper.cc +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_client_epoll_network_helper.h" - -#include <errno.h> -#include <netinet/in.h> -#include <string.h> -#include <sys/epoll.h> -#include <sys/socket.h> -#include <unistd.h> - -#include "base/run_loop.h" -#include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_data_reader.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/core/quic_server_id.h" -#include "net/quic/core/spdy_utils.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/tools/quic/platform/impl/quic_socket_utils.h" -#include "net/tools/quic/quic_epoll_alarm_factory.h" -#include "net/tools/quic/quic_epoll_connection_helper.h" - -#ifndef SO_RXQ_OVFL -#define SO_RXQ_OVFL 40 -#endif - -// TODO(rtenneti): Add support for MMSG_MORE. -#define MMSG_MORE 0 -using std::string; - -namespace net { - -namespace { -const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET; -} // namespace - -QuicClientEpollNetworkHelper::QuicClientEpollNetworkHelper( - EpollServer* epoll_server, - QuicClientBase* client) - : epoll_server_(epoll_server), - packets_dropped_(0), - overflow_supported_(false), - packet_reader_(new QuicPacketReader()), - client_(client), - max_reads_per_epoll_loop_(std::numeric_limits<int>::max()) {} - -QuicClientEpollNetworkHelper::~QuicClientEpollNetworkHelper() { - if (client_->connected()) { - client_->session()->connection()->CloseConnection( - QUIC_PEER_GOING_AWAY, "Client being torn down", - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - } - - CleanUpAllUDPSockets(); -} - -bool QuicClientEpollNetworkHelper::CreateUDPSocketAndBind( - QuicSocketAddress server_address, - QuicIpAddress bind_to_address, - int bind_to_port) { - epoll_server_->set_timeout_in_us(50 * 1000); - - int fd = CreateUDPSocket(server_address, &overflow_supported_); - if (fd < 0) { - return false; - } - - QuicSocketAddress client_address; - if (bind_to_address.IsInitialized()) { - client_address = QuicSocketAddress(bind_to_address, client_->local_port()); - } else if (server_address.host().address_family() == IpAddressFamily::IP_V4) { - client_address = QuicSocketAddress(QuicIpAddress::Any4(), bind_to_port); - } else { - client_address = QuicSocketAddress(QuicIpAddress::Any6(), bind_to_port); - } - - sockaddr_storage addr = client_address.generic_address(); - int rc = bind(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)); - if (rc < 0) { - QUIC_LOG(ERROR) << "Bind failed: " << strerror(errno); - return false; - } - - if (client_address.FromSocket(fd) != 0) { - QUIC_LOG(ERROR) << "Unable to get self address. Error: " - << strerror(errno); - } - - fd_address_map_[fd] = client_address; - - epoll_server_->RegisterFD(fd, this, kEpollFlags); - return true; -} - -void QuicClientEpollNetworkHelper::CleanUpUDPSocket(int fd) { - CleanUpUDPSocketImpl(fd); - fd_address_map_.erase(fd); -} - -void QuicClientEpollNetworkHelper::CleanUpAllUDPSockets() { - for (std::pair<int, QuicSocketAddress> fd_address : fd_address_map_) { - CleanUpUDPSocketImpl(fd_address.first); - } - fd_address_map_.clear(); -} - -void QuicClientEpollNetworkHelper::CleanUpUDPSocketImpl(int fd) { - if (fd > -1) { - epoll_server_->UnregisterFD(fd); - int rc = close(fd); - DCHECK_EQ(0, rc); - } -} - -void QuicClientEpollNetworkHelper::RunEventLoop() { - base::RunLoop().RunUntilIdle(); - epoll_server_->WaitForEventsAndExecuteCallbacks(); -} - -void QuicClientEpollNetworkHelper::OnRegistration(EpollServer* eps, - int fd, - int event_mask) {} -void QuicClientEpollNetworkHelper::OnModification(int fd, int event_mask) {} -void QuicClientEpollNetworkHelper::OnUnregistration(int fd, bool replaced) {} -void QuicClientEpollNetworkHelper::OnShutdown(EpollServer* eps, int fd) {} - -void QuicClientEpollNetworkHelper::OnEvent(int fd, EpollEvent* event) { - DCHECK_EQ(fd, GetLatestFD()); - - if (event->in_events & EPOLLIN) { - DVLOG(1) << "Read packets on EPOLLIN"; - int times_to_read = max_reads_per_epoll_loop_; - bool more_to_read = true; - while (client_->connected() && more_to_read && times_to_read > 0) { - more_to_read = packet_reader_->ReadAndDispatchPackets( - GetLatestFD(), GetLatestClientAddress().port(), - *client_->helper()->GetClock(), this, - overflow_supported_ ? &packets_dropped_ : nullptr); - --times_to_read; - } - if (packets_dropped_ > 100) { - QUIC_LOG_FIRST_N(ERROR, 50) - << packets_dropped_ - << " packets droped in the socket receive buffer."; - } - if (client_->connected() && more_to_read) { - event->out_ready_mask |= EPOLLIN; - } - } - if (client_->connected() && (event->in_events & EPOLLOUT)) { - client_->writer()->SetWritable(); - client_->session()->connection()->OnCanWrite(); - } - if (event->in_events & EPOLLERR) { - QUIC_DLOG(INFO) << "Epollerr"; - } -} - -QuicPacketWriter* QuicClientEpollNetworkHelper::CreateQuicPacketWriter() { - return new QuicDefaultPacketWriter(GetLatestFD()); -} - -void QuicClientEpollNetworkHelper::SetClientPort(int port) { - fd_address_map_.back().second = - QuicSocketAddress(GetLatestClientAddress().host(), port); -} - -QuicSocketAddress QuicClientEpollNetworkHelper::GetLatestClientAddress() const { - if (fd_address_map_.empty()) { - return QuicSocketAddress(); - } - - return fd_address_map_.back().second; -} - -int QuicClientEpollNetworkHelper::GetLatestFD() const { - if (fd_address_map_.empty()) { - return -1; - } - - return fd_address_map_.back().first; -} - -void QuicClientEpollNetworkHelper::ProcessPacket( - const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - const QuicReceivedPacket& packet) { - client_->session()->ProcessUdpPacket(self_address, peer_address, packet); -} - -int QuicClientEpollNetworkHelper::CreateUDPSocket( - QuicSocketAddress server_address, - bool* overflow_supported) { - return QuicSocketUtils::CreateUDPSocket( - server_address, - /*receive_buffer_size =*/kDefaultSocketReceiveBuffer, - /*send_buffer_size =*/kDefaultSocketReceiveBuffer, overflow_supported); -} -} // namespace net diff --git a/chromium/net/tools/quic/quic_client_epoll_network_helper.h b/chromium/net/tools/quic/quic_client_epoll_network_helper.h deleted file mode 100644 index a5117fd6a20..00000000000 --- a/chromium/net/tools/quic/quic_client_epoll_network_helper.h +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// An implementation of the QuicClientBase::NetworkHelper -// that is based off the epoll server. - -#ifndef NET_TOOLS_QUIC_QUIC_CLIENT_EPOLL_NETWORK_HELPER_H_ -#define NET_TOOLS_QUIC_QUIC_CLIENT_EPOLL_NETWORK_HELPER_H_ - -#include <cstdint> -#include <memory> -#include <string> - -#include "base/command_line.h" -#include "base/macros.h" -#include "net/quic/core/quic_client_push_promise_index.h" -#include "net/quic/core/quic_config.h" -#include "net/quic/core/quic_spdy_stream.h" -#include "net/quic/platform/api/quic_containers.h" -#include "net/tools/epoll_server/epoll_server.h" -#include "net/tools/quic/quic_client_base.h" -#include "net/tools/quic/quic_packet_reader.h" -#include "net/tools/quic/quic_process_packet_interface.h" -#include "net/tools/quic/quic_spdy_client_base.h" -#include "net/tools/quic/quic_spdy_client_session.h" - -namespace net { - -namespace test { -class QuicClientPeer; -} // namespace test - -// An implementation of the QuicClientBase::NetworkHelper based off -// the epoll server. -class QuicClientEpollNetworkHelper : public QuicClientBase::NetworkHelper, - public EpollCallbackInterface, - public ProcessPacketInterface { - public: - // Create a quic client, which will have events managed by an externally owned - // EpollServer. - QuicClientEpollNetworkHelper(EpollServer* epoll_server, - QuicClientBase* client); - - ~QuicClientEpollNetworkHelper() override; - - // From EpollCallbackInterface - void OnRegistration(EpollServer* eps, int fd, int event_mask) override; - void OnModification(int fd, int event_mask) override; - void OnEvent(int fd, EpollEvent* event) override; - // |fd_| can be unregistered without the client being disconnected. This - // happens in b3m QuicProber where we unregister |fd_| to feed in events to - // the client from the SelectServer. - void OnUnregistration(int fd, bool replaced) override; - void OnShutdown(EpollServer* eps, int fd) override; - - // From ProcessPacketInterface. This will be called for each received - // packet. - void ProcessPacket(const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - const QuicReceivedPacket& packet) override; - - // From NetworkHelper. - void RunEventLoop() override; - bool CreateUDPSocketAndBind(QuicSocketAddress server_address, - QuicIpAddress bind_to_address, - int bind_to_port) override; - void CleanUpAllUDPSockets() override; - QuicSocketAddress GetLatestClientAddress() const override; - QuicPacketWriter* CreateQuicPacketWriter() override; - - // Accessors provided for convenience, not part of any interface. - - EpollServer* epoll_server() { return epoll_server_; } - - const QuicLinkedHashMap<int, QuicSocketAddress>& fd_address_map() const { - return fd_address_map_; - } - - // If the client has at least one UDP socket, return the latest created one. - // Otherwise, return -1. - int GetLatestFD() const; - - // Create socket for connection to |server_address| with default socket - // options. - // Return fd index. - virtual int CreateUDPSocket(QuicSocketAddress server_address, - bool* overflow_supported); - - QuicClientBase* client() { return client_; } - - void set_max_reads_per_epoll_loop(int num_reads) { - max_reads_per_epoll_loop_ = num_reads; - } - // If |fd| is an open UDP socket, unregister and close it. Otherwise, do - // nothing. - void CleanUpUDPSocket(int fd); - - private: - friend class test::QuicClientPeer; - - // Used for testing. - void SetClientPort(int port); - - // Actually clean up |fd|. - void CleanUpUDPSocketImpl(int fd); - - // Listens for events on the client socket. - EpollServer* epoll_server_; - - // Map mapping created UDP sockets to their addresses. By using linked hash - // map, the order of socket creation can be recorded. - QuicLinkedHashMap<int, QuicSocketAddress> fd_address_map_; - - // If overflow_supported_ is true, this will be the number of packets dropped - // during the lifetime of the server. - QuicPacketCount packets_dropped_; - - // True if the kernel supports SO_RXQ_OVFL, the number of packets dropped - // because the socket would otherwise overflow. - bool overflow_supported_; - - // Point to a QuicPacketReader object on the heap. The reader allocates more - // space than allowed on the stack. - std::unique_ptr<QuicPacketReader> packet_reader_; - - QuicClientBase* client_; - - int max_reads_per_epoll_loop_; - - DISALLOW_COPY_AND_ASSIGN(QuicClientEpollNetworkHelper); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_CLIENT_EPOLL_NETWORK_HELPER_H_ diff --git a/chromium/net/tools/quic/quic_client_message_loop_network_helper.cc b/chromium/net/tools/quic/quic_client_message_loop_network_helper.cc index b60ba04d575..0075af6293a 100644 --- a/chromium/net/tools/quic/quic_client_message_loop_network_helper.cc +++ b/chromium/net/tools/quic/quic_client_message_loop_network_helper.cc @@ -18,16 +18,16 @@ #include "net/quic/chromium/quic_chromium_connection_helper.h" #include "net/quic/chromium/quic_chromium_packet_reader.h" #include "net/quic/chromium/quic_chromium_packet_writer.h" -#include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/core/quic_server_id.h" -#include "net/quic/core/spdy_utils.h" -#include "net/quic/platform/api/quic_flags.h" -#include "net/quic/platform/api/quic_ptr_util.h" #include "net/socket/udp_client_socket.h" -#include "net/spdy/chromium/spdy_http_utils.h" -#include "net/spdy/core/spdy_header_block.h" +#include "net/spdy/spdy_http_utils.h" +#include "net/third_party/quic/core/crypto/quic_random.h" +#include "net/third_party/quic/core/quic_connection.h" +#include "net/third_party/quic/core/quic_packets.h" +#include "net/third_party/quic/core/quic_server_id.h" +#include "net/third_party/quic/core/spdy_utils.h" +#include "net/third_party/quic/platform/api/quic_flags.h" +#include "net/third_party/quic/platform/api/quic_ptr_util.h" +#include "net/third_party/spdy/core/spdy_header_block.h" using std::string; diff --git a/chromium/net/tools/quic/quic_client_message_loop_network_helper.h b/chromium/net/tools/quic/quic_client_message_loop_network_helper.h index 891f19f78f6..2a75444145d 100644 --- a/chromium/net/tools/quic/quic_client_message_loop_network_helper.h +++ b/chromium/net/tools/quic/quic_client_message_loop_network_helper.h @@ -20,10 +20,10 @@ #include "net/http/http_response_headers.h" #include "net/log/net_log.h" #include "net/quic/chromium/quic_chromium_packet_reader.h" -#include "net/quic/core/quic_config.h" -#include "net/quic/core/quic_spdy_stream.h" -#include "net/quic/platform/impl/quic_chromium_clock.h" -#include "net/tools/quic/quic_spdy_client_base.h" +#include "net/third_party/quic/core/quic_config.h" +#include "net/third_party/quic/core/quic_spdy_stream.h" +#include "net/third_party/quic/platform/impl/quic_chromium_clock.h" +#include "net/third_party/quic/tools/quic_spdy_client_base.h" namespace net { diff --git a/chromium/net/tools/quic/quic_client_test.cc b/chromium/net/tools/quic/quic_client_test.cc deleted file mode 100644 index e9b7e5d6d21..00000000000 --- a/chromium/net/tools/quic/quic_client_test.cc +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_client.h" - -#include <dirent.h> -#include <stdio.h> - -#include <memory> - -#include "base/files/file_enumerator.h" -#include "base/files/file_util.h" -#include "net/quic/platform/api/quic_test.h" -#include "net/quic/platform/api/quic_test_loopback.h" -#include "net/quic/platform/api/quic_text_utils.h" -#include "net/quic/test_tools/crypto_test_utils.h" -#include "net/quic/test_tools/quic_test_utils.h" -#include "net/tools/epoll_server/epoll_server.h" -#include "net/tools/quic/test_tools/quic_client_peer.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace net { -namespace test { -namespace { - -const char* kPathToFds = "/proc/self/fd"; - -// Counts the number of open sockets for the current process. -size_t NumOpenSocketFDs() { - base::FileEnumerator fd_entries( - base::FilePath(kPathToFds), false, - base::FileEnumerator::FILES | base::FileEnumerator::SHOW_SYM_LINKS); - - size_t socket_count = 0; - for (base::FilePath entry = fd_entries.Next(); !entry.empty(); - entry = fd_entries.Next()) { - base::FilePath fd_path; - if (!base::ReadSymbolicLink(entry, &fd_path)) { - continue; - } - if (QuicTextUtils::StartsWith(fd_path.value(), "socket:")) { - socket_count++; - } - } - - return socket_count; -} - -// Creates a new QuicClient and Initializes it. Caller is responsible for -// deletion. -QuicClient* CreateAndInitializeQuicClient(EpollServer* eps, uint16_t port) { - QuicSocketAddress server_address(QuicSocketAddress(TestLoopback(), port)); - QuicServerId server_id("hostname", server_address.port(), - PRIVACY_MODE_DISABLED); - ParsedQuicVersionVector versions = AllSupportedVersions(); - QuicClient* client = - new QuicClient(server_address, server_id, versions, eps, - crypto_test_utils::ProofVerifierForTesting()); - EXPECT_TRUE(client->Initialize()); - return client; -} - -class QuicClientTest : public QuicTest {}; - -TEST_F(QuicClientTest, DoNotLeakSocketFDs) { - // Make sure that the QuicClient doesn't leak socket FDs. Doing so could cause - // port exhaustion in long running processes which repeatedly create clients. - - // Create a ProofVerifier before counting the number of open FDs to work - // around some ASAN weirdness. - crypto_test_utils::ProofVerifierForTesting().reset(); - - // Record initial number of FDs, after creation of EpollServer. - EpollServer eps; - size_t number_of_open_fds = NumOpenSocketFDs(); - - // Create a number of clients, initialize them, and verify this has resulted - // in additional FDs being opened. - const int kNumClients = 50; - for (int i = 0; i < kNumClients; ++i) { - std::unique_ptr<QuicClient> client( - CreateAndInitializeQuicClient(&eps, net::test::kTestPort + i)); - - // Initializing the client will create a new FD. - EXPECT_LT(number_of_open_fds, NumOpenSocketFDs()); - } - - // The FDs created by the QuicClients should now be closed. - EXPECT_EQ(number_of_open_fds, NumOpenSocketFDs()); -} - -TEST_F(QuicClientTest, CreateAndCleanUpUDPSockets) { - // Create a ProofVerifier before counting the number of open FDs to work - // around some ASAN weirdness. - crypto_test_utils::ProofVerifierForTesting().reset(); - - EpollServer eps; - size_t number_of_open_fds = NumOpenSocketFDs(); - - std::unique_ptr<QuicClient> client( - CreateAndInitializeQuicClient(&eps, net::test::kTestPort)); - EXPECT_EQ(number_of_open_fds + 1, NumOpenSocketFDs()); - // Create more UDP sockets. - EXPECT_TRUE(QuicClientPeer::CreateUDPSocketAndBind(client.get())); - EXPECT_EQ(number_of_open_fds + 2, NumOpenSocketFDs()); - EXPECT_TRUE(QuicClientPeer::CreateUDPSocketAndBind(client.get())); - EXPECT_EQ(number_of_open_fds + 3, NumOpenSocketFDs()); - - // Clean up UDP sockets. - QuicClientPeer::CleanUpUDPSocket(client.get(), client->GetLatestFD()); - EXPECT_EQ(number_of_open_fds + 2, NumOpenSocketFDs()); - QuicClientPeer::CleanUpUDPSocket(client.get(), client->GetLatestFD()); - EXPECT_EQ(number_of_open_fds + 1, NumOpenSocketFDs()); -} - -} // namespace -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/quic_default_packet_writer.cc b/chromium/net/tools/quic/quic_default_packet_writer.cc deleted file mode 100644 index 34c1bab4fb6..00000000000 --- a/chromium/net/tools/quic/quic_default_packet_writer.cc +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_default_packet_writer.h" - -#include "net/tools/quic/platform/impl/quic_socket_utils.h" - -namespace net { - -QuicDefaultPacketWriter::QuicDefaultPacketWriter(int fd) - : fd_(fd), write_blocked_(false) {} - -QuicDefaultPacketWriter::~QuicDefaultPacketWriter() = default; - -WriteResult QuicDefaultPacketWriter::WritePacket( - const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address, - PerPacketOptions* options) { - DCHECK(!write_blocked_); - DCHECK(nullptr == options) - << "QuicDefaultPacketWriter does not accept any options."; - WriteResult result = QuicSocketUtils::WritePacket(fd_, buffer, buf_len, - self_address, peer_address); - if (result.status == WRITE_STATUS_BLOCKED) { - write_blocked_ = true; - } - return result; -} - -bool QuicDefaultPacketWriter::IsWriteBlockedDataBuffered() const { - return false; -} - -bool QuicDefaultPacketWriter::IsWriteBlocked() const { - return write_blocked_; -} - -void QuicDefaultPacketWriter::SetWritable() { - write_blocked_ = false; -} - -QuicByteCount QuicDefaultPacketWriter::GetMaxPacketSize( - const QuicSocketAddress& peer_address) const { - return kMaxPacketSize; -} - -void QuicDefaultPacketWriter::set_write_blocked(bool is_blocked) { - write_blocked_ = is_blocked; -} - -} // namespace net diff --git a/chromium/net/tools/quic/quic_default_packet_writer.h b/chromium/net/tools/quic/quic_default_packet_writer.h deleted file mode 100644 index 19d75d4b30d..00000000000 --- a/chromium/net/tools/quic/quic_default_packet_writer.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_QUIC_DEFAULT_PACKET_WRITER_H_ -#define NET_TOOLS_QUIC_QUIC_DEFAULT_PACKET_WRITER_H_ - -#include <stddef.h> - -#include "base/macros.h" -#include "net/quic/core/quic_packet_writer.h" -#include "net/quic/platform/api/quic_export.h" -#include "net/quic/platform/api/quic_socket_address.h" - -namespace net { - -struct WriteResult; - - -// Default packet writer which wraps QuicSocketUtils WritePacket. -class QUIC_EXPORT_PRIVATE QuicDefaultPacketWriter : public QuicPacketWriter { - public: - explicit QuicDefaultPacketWriter(int fd); - ~QuicDefaultPacketWriter() override; - - // QuicPacketWriter - WriteResult WritePacket(const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address, - PerPacketOptions* options) override; - bool IsWriteBlockedDataBuffered() const override; - bool IsWriteBlocked() const override; - void SetWritable() override; - QuicByteCount GetMaxPacketSize( - const QuicSocketAddress& peer_address) const override; - - void set_fd(int fd) { fd_ = fd; } - - protected: - void set_write_blocked(bool is_blocked); - int fd() { return fd_; } - - private: - int fd_; - bool write_blocked_; - - DISALLOW_COPY_AND_ASSIGN(QuicDefaultPacketWriter); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_DEFAULT_PACKET_WRITER_H_ diff --git a/chromium/net/tools/quic/quic_dispatcher.cc b/chromium/net/tools/quic/quic_dispatcher.cc deleted file mode 100644 index 591c45869a7..00000000000 --- a/chromium/net/tools/quic/quic_dispatcher.cc +++ /dev/null @@ -1,1107 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_dispatcher.h" - -#include <utility> - -#include "base/macros.h" -#include "net/quic/core/crypto/crypto_protocol.h" -#include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_utils.h" -#include "net/quic/platform/api/quic_bug_tracker.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" -#include "net/quic/platform/api/quic_stack_trace.h" -#include "net/quic/platform/api/quic_string.h" -#include "net/quic/platform/api/quic_string_piece.h" -#include "net/tools/quic/chlo_extractor.h" -#include "net/tools/quic/quic_per_connection_packet_writer.h" -#include "net/tools/quic/quic_simple_server_session.h" -#include "net/tools/quic/quic_time_wait_list_manager.h" -#include "net/tools/quic/stateless_rejector.h" - - -namespace net { - -typedef QuicBufferedPacketStore::BufferedPacket BufferedPacket; -typedef QuicBufferedPacketStore::BufferedPacketList BufferedPacketList; -typedef QuicBufferedPacketStore::EnqueuePacketResult EnqueuePacketResult; - -namespace { - -// An alarm that informs the QuicDispatcher to delete old sessions. -class DeleteSessionsAlarm : public QuicAlarm::Delegate { - public: - explicit DeleteSessionsAlarm(QuicDispatcher* dispatcher) - : dispatcher_(dispatcher) {} - - void OnAlarm() override { dispatcher_->DeleteSessions(); } - - private: - // Not owned. - QuicDispatcher* dispatcher_; - - DISALLOW_COPY_AND_ASSIGN(DeleteSessionsAlarm); -}; - -// Collects packets serialized by a QuicPacketCreator in order -// to be handed off to the time wait list manager. -class PacketCollector : public QuicPacketCreator::DelegateInterface, - public QuicStreamFrameDataProducer { - public: - explicit PacketCollector(QuicBufferAllocator* allocator) - : send_buffer_(allocator) {} - ~PacketCollector() override = default; - - // QuicPacketCreator::DelegateInterface methods: - void OnSerializedPacket(SerializedPacket* serialized_packet) override { - // Make a copy of the serialized packet to send later. - packets_.emplace_back( - new QuicEncryptedPacket(CopyBuffer(*serialized_packet), - serialized_packet->encrypted_length, true)); - serialized_packet->encrypted_buffer = nullptr; - DeleteFrames(&(serialized_packet->retransmittable_frames)); - serialized_packet->retransmittable_frames.clear(); - } - - void OnUnrecoverableError(QuicErrorCode error, - const QuicString& error_details, - ConnectionCloseSource source) override {} - - void SaveStatelessRejectFrameData(QuicStringPiece reject) { - struct iovec iovec; - iovec.iov_base = const_cast<char*>(reject.data()); - iovec.iov_len = reject.length(); - send_buffer_.SaveStreamData(&iovec, 1, 0, iovec.iov_len); - } - - // QuicStreamFrameDataProducer - bool WriteStreamData(QuicStreamId id, - QuicStreamOffset offset, - QuicByteCount data_length, - QuicDataWriter* writer) override { - DCHECK_EQ(kCryptoStreamId, id); - return send_buffer_.WriteStreamData(offset, data_length, writer); - } - - std::vector<std::unique_ptr<QuicEncryptedPacket>>* packets() { - return &packets_; - } - - private: - std::vector<std::unique_ptr<QuicEncryptedPacket>> packets_; - // This is only needed until the packets are encrypted. Once packets are - // encrypted, the stream data is no longer required. - QuicStreamSendBuffer send_buffer_; -}; - -// Helper for statelessly closing connections by generating the -// correct termination packets and adding the connection to the time wait -// list manager. -class StatelessConnectionTerminator { - public: - StatelessConnectionTerminator(QuicConnectionId connection_id, - QuicFramer* framer, - QuicConnectionHelperInterface* helper, - QuicTimeWaitListManager* time_wait_list_manager) - : connection_id_(connection_id), - framer_(framer), - collector_(helper->GetStreamSendBufferAllocator()), - creator_(connection_id, framer, &collector_), - time_wait_list_manager_(time_wait_list_manager) { - framer_->set_data_producer(&collector_); - } - - ~StatelessConnectionTerminator() { - // Clear framer's producer. - framer_->set_data_producer(nullptr); - } - - // Generates a packet containing a CONNECTION_CLOSE frame specifying - // |error_code| and |error_details| and add the connection to time wait. - void CloseConnection(QuicErrorCode error_code, - const std::string& error_details) { - QuicConnectionCloseFrame* frame = new QuicConnectionCloseFrame; - frame->error_code = error_code; - frame->error_details = error_details; - if (!creator_.AddSavedFrame(QuicFrame(frame))) { - QUIC_BUG << "Unable to add frame to an empty packet"; - delete frame; - return; - } - creator_.Flush(); - DCHECK_EQ(1u, collector_.packets()->size()); - time_wait_list_manager_->AddConnectionIdToTimeWait( - connection_id_, framer_->version(), framer_->last_packet_is_ietf_quic(), - /*connection_rejected_statelessly=*/false, collector_.packets()); - } - - // Generates a series of termination packets containing the crypto handshake - // message |reject|. Adds the connection to time wait list with the - // generated packets. - void RejectConnection(QuicStringPiece reject) { - QuicStreamOffset offset = 0; - collector_.SaveStatelessRejectFrameData(reject); - while (offset < reject.length()) { - QuicFrame frame; - if (!creator_.ConsumeData(kCryptoStreamId, reject.length(), offset, - offset, - /*fin=*/false, - /*needs_full_padding=*/true, &frame)) { - QUIC_BUG << "Unable to consume data into an empty packet."; - return; - } - offset += frame.stream_frame->data_length; - if (offset < reject.length()) { - DCHECK(!creator_.HasRoomForStreamFrame(kCryptoStreamId, offset)); - } - creator_.Flush(); - } - time_wait_list_manager_->AddConnectionIdToTimeWait( - connection_id_, framer_->version(), framer_->last_packet_is_ietf_quic(), - /*connection_rejected_statelessly=*/true, collector_.packets()); - DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id_)); - } - - private: - QuicConnectionId connection_id_; - QuicFramer* framer_; // Unowned. - // Set as the visitor of |creator_| to collect any generated packets. - PacketCollector collector_; - QuicPacketCreator creator_; - QuicTimeWaitListManager* time_wait_list_manager_; -}; - -// Class which extracts the ALPN from a CHLO packet. -class ChloAlpnExtractor : public ChloExtractor::Delegate { - public: - void OnChlo(QuicTransportVersion version, - QuicConnectionId connection_id, - const CryptoHandshakeMessage& chlo) override { - QuicStringPiece alpn_value; - if (chlo.GetStringPiece(kALPN, &alpn_value)) { - alpn_ = QuicString(alpn_value); - } - } - - QuicString&& ConsumeAlpn() { return std::move(alpn_); } - - private: - QuicString alpn_; -}; - -// Class which sits between the ChloExtractor and the StatelessRejector -// to give the QuicDispatcher a chance to apply policy checks to the CHLO. -class ChloValidator : public ChloAlpnExtractor { - public: - ChloValidator(QuicCryptoServerStream::Helper* helper, - QuicSocketAddress self_address, - StatelessRejector* rejector) - : helper_(helper), - self_address_(self_address), - rejector_(rejector), - can_accept_(false), - error_details_("CHLO not processed") {} - - // ChloExtractor::Delegate implementation. - void OnChlo(QuicTransportVersion version, - QuicConnectionId connection_id, - const CryptoHandshakeMessage& chlo) override { - // Extract the ALPN - ChloAlpnExtractor::OnChlo(version, connection_id, chlo); - if (helper_->CanAcceptClientHello(chlo, self_address_, &error_details_)) { - can_accept_ = true; - rejector_->OnChlo(version, connection_id, - helper_->GenerateConnectionIdForReject(connection_id), - chlo); - } - } - - bool can_accept() const { return can_accept_; } - - const QuicString& error_details() const { return error_details_; } - - private: - QuicCryptoServerStream::Helper* helper_; // Unowned. - QuicSocketAddress self_address_; - StatelessRejector* rejector_; // Unowned. - bool can_accept_; - QuicString error_details_; -}; - -} // namespace - -QuicDispatcher::QuicDispatcher( - const QuicConfig& config, - const QuicCryptoServerConfig* crypto_config, - QuicVersionManager* version_manager, - std::unique_ptr<QuicConnectionHelperInterface> helper, - std::unique_ptr<QuicCryptoServerStream::Helper> session_helper, - std::unique_ptr<QuicAlarmFactory> alarm_factory) - : config_(config), - crypto_config_(crypto_config), - compressed_certs_cache_( - QuicCompressedCertsCache::kQuicCompressedCertsCacheSize), - helper_(std::move(helper)), - session_helper_(std::move(session_helper)), - alarm_factory_(std::move(alarm_factory)), - delete_sessions_alarm_( - alarm_factory_->CreateAlarm(new DeleteSessionsAlarm(this))), - buffered_packets_(this, helper_->GetClock(), alarm_factory_.get()), - current_packet_(nullptr), - version_manager_(version_manager), - framer_(GetSupportedVersions(), - /*unused*/ QuicTime::Zero(), - Perspective::IS_SERVER), - last_error_(QUIC_NO_ERROR), - new_sessions_allowed_per_event_loop_(0u), - accept_new_connections_(true) { - framer_.set_visitor(this); -} - -QuicDispatcher::~QuicDispatcher() { - session_map_.clear(); - closed_session_list_.clear(); -} - -void QuicDispatcher::InitializeWithWriter(QuicPacketWriter* writer) { - DCHECK(writer_ == nullptr); - writer_.reset(writer); - time_wait_list_manager_.reset(CreateQuicTimeWaitListManager()); -} - -void QuicDispatcher::ProcessPacket(const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - const QuicReceivedPacket& packet) { - current_self_address_ = self_address; - current_peer_address_ = peer_address; - // GetClientAddress must be called after current_peer_address_ is set. - current_client_address_ = GetClientAddress(); - current_packet_ = &packet; - // ProcessPacket will cause the packet to be dispatched in - // OnUnauthenticatedPublicHeader, or sent to the time wait list manager - // in OnUnauthenticatedHeader. - framer_.ProcessPacket(packet); - // TODO(rjshade): Return a status describing if/why a packet was dropped, - // and log somehow. Maybe expose as a varz. - // TODO(wub): Consider invalidate the current_* variables so processing of the - // next packet does not use them incorrectly. -} - -bool QuicDispatcher::OnUnauthenticatedPublicHeader( - const QuicPacketHeader& header) { - current_connection_id_ = header.connection_id; - - // Port zero is only allowed for unidirectional UDP, so is disallowed by QUIC. - // Given that we can't even send a reply rejecting the packet, just drop the - // packet. - if (current_peer_address_.port() == 0) { - return false; - } - - // Stopgap test: The code does not construct full-length connection IDs - // correctly from truncated connection ID fields. Prevent this from causing - // the connection ID lookup to error by dropping any packet with a short - // connection ID. - if (header.connection_id_length != PACKET_8BYTE_CONNECTION_ID) { - return false; - } - - // Packets with connection IDs for active connections are processed - // immediately. - QuicConnectionId connection_id = header.connection_id; - SessionMap::iterator it = session_map_.find(connection_id); - if (it != session_map_.end()) { - DCHECK(!buffered_packets_.HasBufferedPackets(connection_id)); - it->second->ProcessUdpPacket(current_self_address_, current_peer_address_, - *current_packet_); - return false; - } - - if (buffered_packets_.HasChloForConnection(connection_id)) { - BufferEarlyPacket(connection_id, framer_.last_packet_is_ietf_quic()); - return false; - } - - // Check if we are buffering packets for this connection ID - if (temporarily_buffered_connections_.find(connection_id) != - temporarily_buffered_connections_.end()) { - // This packet was received while the a CHLO for the same connection ID was - // being processed. Buffer it. - BufferEarlyPacket(connection_id, framer_.last_packet_is_ietf_quic()); - return false; - } - - if (!OnUnauthenticatedUnknownPublicHeader(header)) { - return false; - } - - // If the packet is a public reset for a connection ID that is not active, - // there is nothing we must do or can do. - if (header.reset_flag) { - return false; - } - - if (time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)) { - // Set the framer's version based on the recorded version for this - // connection and continue processing for non-public-reset packets. - return HandlePacketForTimeWait(header); - } - - // The packet has an unknown connection ID. - - // Unless the packet provides a version, assume that we can continue - // processing using our preferred version. - ParsedQuicVersion version = GetSupportedVersions().front(); - if (header.version_flag) { - ParsedQuicVersion packet_version = header.version; - if (framer_.supported_versions() != GetSupportedVersions()) { - // Reset framer's version if version flags change in flight. - framer_.SetSupportedVersions(GetSupportedVersions()); - } - if (!framer_.IsSupportedVersion(packet_version)) { - if (ShouldCreateSessionForUnknownVersion(framer_.last_version_label())) { - return true; - } - // Since the version is not supported, send a version negotiation - // packet and stop processing the current packet. - time_wait_list_manager()->SendVersionNegotiationPacket( - connection_id, framer_.last_packet_is_ietf_quic(), - GetSupportedVersions(), current_self_address_, current_peer_address_); - return false; - } - version = packet_version; - } - // Set the framer's version and continue processing. - framer_.set_version(version); - return true; -} - -bool QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) { - QuicConnectionId connection_id = header.connection_id; - - if (time_wait_list_manager_->IsConnectionIdInTimeWait(header.connection_id)) { - // This connection ID is already in time-wait state. - time_wait_list_manager_->ProcessPacket( - current_self_address_, current_peer_address_, header.connection_id); - return false; - } - - // Packet's connection ID is unknown. Apply the validity checks. - QuicPacketFate fate = ValidityChecks(header); - if (fate == kFateProcess) { - // Execute stateless rejection logic to determine the packet fate, then - // invoke ProcessUnauthenticatedHeaderFate. - MaybeRejectStatelessly(connection_id, header.version); - } else { - // If the fate is already known, process it without executing stateless - // rejection logic. - ProcessUnauthenticatedHeaderFate(fate, connection_id); - } - - return false; -} - -void QuicDispatcher::ProcessUnauthenticatedHeaderFate( - QuicPacketFate fate, - QuicConnectionId connection_id) { - switch (fate) { - case kFateProcess: { - ProcessChlo(); - break; - } - case kFateTimeWait: - // MaybeRejectStatelessly or OnExpiredPackets might have already added the - // connection to time wait, in which case it should not be added again. - if (!GetQuicReloadableFlag(quic_use_cheap_stateless_rejects) || - !time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)) { - // Add this connection_id to the time-wait state, to safely reject - // future packets. - QUIC_DLOG(INFO) << "Adding connection ID " << connection_id - << "to time-wait list."; - time_wait_list_manager_->AddConnectionIdToTimeWait( - connection_id, framer_.version(), - framer_.last_packet_is_ietf_quic(), - /*connection_rejected_statelessly=*/false, nullptr); - } - DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); - time_wait_list_manager_->ProcessPacket( - current_self_address_, current_peer_address_, connection_id); - - // Any packets which were buffered while the stateless rejector logic was - // running should be discarded. Do not inform the time wait list manager, - // which should already have a made a decision about sending a reject - // based on the CHLO alone. - buffered_packets_.DiscardPackets(connection_id); - break; - case kFateBuffer: - // This packet is a non-CHLO packet which has arrived before the - // corresponding CHLO, *or* this packet was received while the - // corresponding CHLO was being processed. Buffer it. - BufferEarlyPacket(connection_id, framer_.last_packet_is_ietf_quic()); - break; - case kFateDrop: - // Do nothing with the packet. - break; - } -} - -QuicDispatcher::QuicPacketFate QuicDispatcher::ValidityChecks( - const QuicPacketHeader& header) { - // To have all the checks work properly without tears, insert any new check - // into the framework of this method in the section for checks that return the - // check's fate value. The sections for checks must be ordered with the - // highest priority fate first. - - // Checks that return kFateDrop. - - // Checks that return kFateTimeWait. - - // All packets within a connection sent by a client before receiving a - // response from the server are required to have the version negotiation flag - // set. Since this may be a client continuing a connection we lost track of - // via server restart, send a rejection to fast-fail the connection. - if (!header.version_flag) { - QUIC_DLOG(INFO) - << "Packet without version arrived for unknown connection ID " - << header.connection_id; - return kFateTimeWait; - } - - // initial packet number of 0 is always invalid. - const int kInvalidPacketNumber = 0; - if (header.packet_number == kInvalidPacketNumber) { - return kFateTimeWait; - } - if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) { - QUIC_FLAG_COUNT_N(quic_restart_flag_quic_enable_accept_random_ipn, 1, 2); - // Accepting Initial Packet Numbers in 1...((2^31)-1) range... check - // maximum accordingly. - if (header.packet_number > kMaxRandomInitialPacketNumber) { - return kFateTimeWait; - } - } else { - // Count those that would have been accepted if FLAGS..random_ipn - // were true -- to detect/diagnose potential issues prior to - // enabling the flag. - if ((header.packet_number > kMaxReasonableInitialPacketNumber) && - (header.packet_number <= kMaxRandomInitialPacketNumber)) { - QUIC_CODE_COUNT_N(had_possibly_random_ipn, 1, 2); - } - // Check that the sequence number is within the range that the client is - // expected to send before receiving a response from the server. - if (header.packet_number > kMaxReasonableInitialPacketNumber) { - return kFateTimeWait; - } - } - return kFateProcess; -} - -void QuicDispatcher::CleanUpSession(SessionMap::iterator it, - QuicConnection* connection, - bool should_close_statelessly) { - write_blocked_list_.erase(connection); - if (should_close_statelessly) { - DCHECK(connection->termination_packets() != nullptr && - !connection->termination_packets()->empty()); - } - time_wait_list_manager_->AddConnectionIdToTimeWait( - it->first, connection->version(), false, should_close_statelessly, - connection->termination_packets()); - session_map_.erase(it); -} - -void QuicDispatcher::StopAcceptingNewConnections() { - accept_new_connections_ = false; -} - -bool QuicDispatcher::ShouldAddToBlockedList() { - return writer_->IsWriteBlocked(); -} - -void QuicDispatcher::DeleteSessions() { - closed_session_list_.clear(); -} - -void QuicDispatcher::OnCanWrite() { - // The socket is now writable. - writer_->SetWritable(); - - // Give all the blocked writers one chance to write, until we're blocked again - // or there's no work left. - while (!write_blocked_list_.empty() && !writer_->IsWriteBlocked()) { - QuicBlockedWriterInterface* blocked_writer = - write_blocked_list_.begin()->first; - write_blocked_list_.erase(write_blocked_list_.begin()); - blocked_writer->OnBlockedWriterCanWrite(); - } -} - -bool QuicDispatcher::HasPendingWrites() const { - return !write_blocked_list_.empty(); -} - -void QuicDispatcher::Shutdown() { - while (!session_map_.empty()) { - QuicSession* session = session_map_.begin()->second.get(); - session->connection()->CloseConnection( - QUIC_PEER_GOING_AWAY, "Server shutdown imminent", - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - // Validate that the session removes itself from the session map on close. - DCHECK(session_map_.empty() || - session_map_.begin()->second.get() != session); - } - DeleteSessions(); -} - -void QuicDispatcher::OnConnectionClosed(QuicConnectionId connection_id, - QuicErrorCode error, - const QuicString& error_details) { - SessionMap::iterator it = session_map_.find(connection_id); - if (it == session_map_.end()) { - QUIC_BUG << "ConnectionId " << connection_id - << " does not exist in the session map. Error: " - << QuicErrorCodeToString(error); - QUIC_BUG << QuicStackTrace(); - return; - } - - QUIC_DLOG_IF(INFO, error != QUIC_NO_ERROR) - << "Closing connection (" << connection_id - << ") due to error: " << QuicErrorCodeToString(error) - << ", with details: " << error_details; - - QuicConnection* connection = it->second->connection(); - if (ShouldDestroySessionAsynchronously()) { - // Set up alarm to fire immediately to bring destruction of this session - // out of current call stack. - if (closed_session_list_.empty()) { - delete_sessions_alarm_->Update(helper()->GetClock()->ApproximateNow(), - QuicTime::Delta::Zero()); - } - closed_session_list_.push_back(std::move(it->second)); - } - const bool should_close_statelessly = - (error == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT); - CleanUpSession(it, connection, should_close_statelessly); -} - -void QuicDispatcher::OnWriteBlocked( - QuicBlockedWriterInterface* blocked_writer) { - if (!ShouldAddToBlockedList()) { - QUIC_BUG - << "Tried to add writer into blocked list when it shouldn't be added"; - // Return without adding the connection to the blocked list, to avoid - // infinite loops in OnCanWrite. - return; - } - write_blocked_list_.insert(std::make_pair(blocked_writer, true)); -} - -void QuicDispatcher::OnRstStreamReceived(const QuicRstStreamFrame& frame) {} - -void QuicDispatcher::OnConnectionAddedToTimeWaitList( - QuicConnectionId connection_id) { - QUIC_DLOG(INFO) << "Connection " << connection_id - << " added to time wait list."; -} - -void QuicDispatcher::OnPacket() {} - -void QuicDispatcher::OnError(QuicFramer* framer) { - QuicErrorCode error = framer->error(); - SetLastError(error); - QUIC_DLOG(INFO) << QuicErrorCodeToString(error); -} - -bool QuicDispatcher::ShouldCreateSessionForUnknownVersion( - QuicVersionLabel /*version_label*/) { - return false; -} - -bool QuicDispatcher::OnProtocolVersionMismatch( - ParsedQuicVersion /*received_version*/) { - QUIC_BUG_IF( - !time_wait_list_manager_->IsConnectionIdInTimeWait( - current_connection_id_) && - !ShouldCreateSessionForUnknownVersion(framer_.last_version_label())) - << "Unexpected version mismatch: " - << QuicVersionLabelToString(framer_.last_version_label()); - - // Keep processing after protocol mismatch - this will be dealt with by the - // time wait list or connection that we will create. - return true; -} - -void QuicDispatcher::OnPublicResetPacket( - const QuicPublicResetPacket& /*packet*/) { - DCHECK(false); -} - -void QuicDispatcher::OnVersionNegotiationPacket( - const QuicVersionNegotiationPacket& /*packet*/) { - DCHECK(false); -} - -void QuicDispatcher::OnDecryptedPacket(EncryptionLevel level) { - DCHECK(false); -} - -bool QuicDispatcher::OnPacketHeader(const QuicPacketHeader& /*header*/) { - DCHECK(false); - return false; -} - -bool QuicDispatcher::OnStreamFrame(const QuicStreamFrame& /*frame*/) { - DCHECK(false); - return false; -} - -bool QuicDispatcher::OnAckFrame(const QuicAckFrame& /*frame*/) { - DCHECK(false); - return false; -} - -bool QuicDispatcher::OnAckFrameStart(QuicPacketNumber /*largest_acked*/, - QuicTime::Delta /*ack_delay_time*/) { - DCHECK(false); - return false; -} - -bool QuicDispatcher::OnAckRange(QuicPacketNumber /*start*/, - QuicPacketNumber /*end*/, - bool /*last_range*/) { - DCHECK(false); - return false; -} - -bool QuicDispatcher::OnStopWaitingFrame(const QuicStopWaitingFrame& /*frame*/) { - DCHECK(false); - return false; -} - -bool QuicDispatcher::OnPaddingFrame(const QuicPaddingFrame& /*frame*/) { - DCHECK(false); - return false; -} - -bool QuicDispatcher::OnPingFrame(const QuicPingFrame& /*frame*/) { - DCHECK(false); - return false; -} - -bool QuicDispatcher::OnRstStreamFrame(const QuicRstStreamFrame& /*frame*/) { - DCHECK(false); - return false; -} - -bool QuicDispatcher::OnConnectionCloseFrame( - const QuicConnectionCloseFrame& /*frame*/) { - DCHECK(false); - return false; -} - -bool QuicDispatcher::OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) { - DCHECK(false); - return false; -} - -bool QuicDispatcher::OnWindowUpdateFrame( - const QuicWindowUpdateFrame& /*frame*/) { - DCHECK(false); - return false; -} - -bool QuicDispatcher::OnBlockedFrame(const QuicBlockedFrame& frame) { - DCHECK(false); - return false; -} - -void QuicDispatcher::OnPacketComplete() { - DCHECK(false); -} - -bool QuicDispatcher::IsValidStatelessResetToken(uint128 token) const { - DCHECK(false); - return false; -} - -void QuicDispatcher::OnAuthenticatedIetfStatelessResetPacket( - const QuicIetfStatelessResetPacket& packet) { - DCHECK(false); -} - -void QuicDispatcher::OnExpiredPackets( - QuicConnectionId connection_id, - BufferedPacketList early_arrived_packets) { - time_wait_list_manager_->AddConnectionIdToTimeWait( - connection_id, framer_.version(), early_arrived_packets.ietf_quic, false, - nullptr); -} - -void QuicDispatcher::ProcessBufferedChlos(size_t max_connections_to_create) { - // Reset the counter before starting creating connections. - new_sessions_allowed_per_event_loop_ = max_connections_to_create; - for (; new_sessions_allowed_per_event_loop_ > 0; - --new_sessions_allowed_per_event_loop_) { - QuicConnectionId connection_id; - BufferedPacketList packet_list = - buffered_packets_.DeliverPacketsForNextConnection(&connection_id); - const std::list<BufferedPacket>& packets = packet_list.buffered_packets; - if (packets.empty()) { - return; - } - QuicSession* session = CreateQuicSession( - connection_id, packets.front().client_address, packet_list.alpn); - QUIC_DLOG(INFO) << "Created new session for " << connection_id; - session_map_.insert(std::make_pair(connection_id, QuicWrapUnique(session))); - DeliverPacketsToSession(packets, session); - } -} - -bool QuicDispatcher::HasChlosBuffered() const { - return buffered_packets_.HasChlosBuffered(); -} - -bool QuicDispatcher::ShouldCreateOrBufferPacketForConnection( - QuicConnectionId connection_id) { - VLOG(1) << "Received packet from new connection " << connection_id; - return true; -} - -// Return true if there is any packet buffered in the store. -bool QuicDispatcher::HasBufferedPackets(QuicConnectionId connection_id) { - return buffered_packets_.HasBufferedPackets(connection_id); -} - -void QuicDispatcher::OnBufferPacketFailure(EnqueuePacketResult result, - QuicConnectionId connection_id) { - QUIC_DLOG(INFO) << "Fail to buffer packet on connection " << connection_id - << " because of " << result; -} - -void QuicDispatcher::OnConnectionRejectedStatelessly() {} - -void QuicDispatcher::OnConnectionClosedStatelessly(QuicErrorCode error) {} - -bool QuicDispatcher::ShouldAttemptCheapStatelessRejection() { - return true; -} - -QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() { - return new QuicTimeWaitListManager(writer_.get(), this, helper_.get(), - alarm_factory_.get()); -} - -void QuicDispatcher::BufferEarlyPacket(QuicConnectionId connection_id, - bool ietf_quic) { - bool is_new_connection = !buffered_packets_.HasBufferedPackets(connection_id); - if (is_new_connection && - !ShouldCreateOrBufferPacketForConnection(connection_id)) { - return; - } - EnqueuePacketResult rs = buffered_packets_.EnqueuePacket( - connection_id, ietf_quic, *current_packet_, current_self_address_, - current_peer_address_, /*is_chlo=*/false, /*alpn=*/""); - if (rs != EnqueuePacketResult::SUCCESS) { - OnBufferPacketFailure(rs, connection_id); - } -} - -void QuicDispatcher::ProcessChlo() { - if (!accept_new_connections_) { - // Don't any create new connection. - time_wait_list_manager()->AddConnectionIdToTimeWait( - current_connection_id(), framer()->version(), - framer()->last_packet_is_ietf_quic(), - /*connection_rejected_statelessly=*/false, - /*termination_packets=*/nullptr); - // This will trigger sending Public Reset packet. - time_wait_list_manager()->ProcessPacket(current_self_address(), - current_peer_address(), - current_connection_id()); - return; - } - if (!buffered_packets_.HasBufferedPackets(current_connection_id_) && - !ShouldCreateOrBufferPacketForConnection(current_connection_id_)) { - return; - } - if (FLAGS_quic_allow_chlo_buffering && - new_sessions_allowed_per_event_loop_ <= 0) { - // Can't create new session any more. Wait till next event loop. - QUIC_BUG_IF(buffered_packets_.HasChloForConnection(current_connection_id_)); - EnqueuePacketResult rs = buffered_packets_.EnqueuePacket( - current_connection_id_, framer_.last_packet_is_ietf_quic(), - *current_packet_, current_self_address_, current_peer_address_, - /*is_chlo=*/true, current_alpn_); - if (rs != EnqueuePacketResult::SUCCESS) { - OnBufferPacketFailure(rs, current_connection_id_); - } - return; - } - // Creates a new session and process all buffered packets for this connection. - QuicSession* session = CreateQuicSession( - current_connection_id_, current_peer_address_, current_alpn_); - QUIC_DLOG(INFO) << "Created new session for " << current_connection_id_; - session_map_.insert( - std::make_pair(current_connection_id_, QuicWrapUnique(session))); - std::list<BufferedPacket> packets = - buffered_packets_.DeliverPackets(current_connection_id_).buffered_packets; - - // Process CHLO at first. - session->ProcessUdpPacket(current_self_address_, current_peer_address_, - *current_packet_); - // Deliver queued-up packets in the same order as they arrived. - // Do this even when flag is off because there might be still some packets - // buffered in the store before flag is turned off. - DeliverPacketsToSession(packets, session); - --new_sessions_allowed_per_event_loop_; -} - -const QuicSocketAddress QuicDispatcher::GetClientAddress() const { - return current_peer_address_; -} - -bool QuicDispatcher::ShouldDestroySessionAsynchronously() { - return true; -} - -bool QuicDispatcher::HandlePacketForTimeWait(const QuicPacketHeader& header) { - if (header.reset_flag) { - // Public reset packets do not have packet numbers, so ignore the packet. - return false; - } - - // Switch the framer to the correct version, so that the packet number can - // be parsed correctly. - framer_.set_version(time_wait_list_manager_->GetQuicVersionFromConnectionId( - header.connection_id)); - - // Continue parsing the packet to extract the packet number. Then - // send it to the time wait manager in OnUnathenticatedHeader. - return true; -} - -QuicPacketWriter* QuicDispatcher::CreatePerConnectionWriter() { - return new QuicPerConnectionPacketWriter(writer_.get()); -} - -void QuicDispatcher::SetLastError(QuicErrorCode error) { - last_error_ = error; -} - -bool QuicDispatcher::OnUnauthenticatedUnknownPublicHeader( - const QuicPacketHeader& header) { - return true; -} - -class StatelessRejectorProcessDoneCallback - : public StatelessRejector::ProcessDoneCallback { - public: - StatelessRejectorProcessDoneCallback(QuicDispatcher* dispatcher, - ParsedQuicVersion first_version) - : dispatcher_(dispatcher), - current_client_address_(dispatcher->current_client_address_), - current_peer_address_(dispatcher->current_peer_address_), - current_self_address_(dispatcher->current_self_address_), - current_packet_( - dispatcher->current_packet_->Clone()), // Note: copies the packet - first_version_(first_version) {} - - void Run(std::unique_ptr<StatelessRejector> rejector) override { - dispatcher_->OnStatelessRejectorProcessDone( - std::move(rejector), current_client_address_, current_peer_address_, - current_self_address_, std::move(current_packet_), first_version_); - } - - private: - QuicDispatcher* dispatcher_; - QuicSocketAddress current_client_address_; - QuicSocketAddress current_peer_address_; - QuicSocketAddress current_self_address_; - std::unique_ptr<QuicReceivedPacket> current_packet_; - ParsedQuicVersion first_version_; -}; - -void QuicDispatcher::MaybeRejectStatelessly(QuicConnectionId connection_id, - ParsedQuicVersion version) { - if (version.handshake_protocol == PROTOCOL_TLS1_3) { - ProcessUnauthenticatedHeaderFate(kFateProcess, connection_id); - return; - // TODO(nharper): Support buffering non-ClientHello packets when using TLS. - } - // TODO(rch): This logic should probably live completely inside the rejector. - if (!FLAGS_quic_allow_chlo_buffering || - !GetQuicReloadableFlag(quic_use_cheap_stateless_rejects) || - !GetQuicReloadableFlag(enable_quic_stateless_reject_support) || - !ShouldAttemptCheapStatelessRejection()) { - // Not use cheap stateless reject. - ChloAlpnExtractor alpn_extractor; - if (FLAGS_quic_allow_chlo_buffering && - !ChloExtractor::Extract(*current_packet_, GetSupportedVersions(), - config_.create_session_tag_indicators(), - &alpn_extractor)) { - // Buffer non-CHLO packets. - ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id); - return; - } - current_alpn_ = alpn_extractor.ConsumeAlpn(); - ProcessUnauthenticatedHeaderFate(kFateProcess, connection_id); - return; - } - - std::unique_ptr<StatelessRejector> rejector(new StatelessRejector( - version.transport_version, GetSupportedTransportVersions(), - crypto_config_, &compressed_certs_cache_, helper()->GetClock(), - helper()->GetRandomGenerator(), current_packet_->length(), - current_client_address_, current_self_address_)); - ChloValidator validator(session_helper_.get(), current_self_address_, - rejector.get()); - if (!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(), - config_.create_session_tag_indicators(), - &validator)) { - ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id); - return; - } - current_alpn_ = validator.ConsumeAlpn(); - - if (!validator.can_accept()) { - // This CHLO is prohibited by policy. - StatelessConnectionTerminator terminator(connection_id, &framer_, helper(), - time_wait_list_manager_.get()); - terminator.CloseConnection(QUIC_HANDSHAKE_FAILED, - validator.error_details()); - OnConnectionClosedStatelessly(QUIC_HANDSHAKE_FAILED); - ProcessUnauthenticatedHeaderFate(kFateTimeWait, connection_id); - return; - } - - // If we were able to make a decision about this CHLO based purely on the - // information available in OnChlo, just invoke the done callback immediately. - if (rejector->state() != StatelessRejector::UNKNOWN) { - ProcessStatelessRejectorState(std::move(rejector), - version.transport_version); - return; - } - - // Insert into set of connection IDs to buffer - const bool ok = - temporarily_buffered_connections_.insert(connection_id).second; - QUIC_BUG_IF(!ok) - << "Processing multiple stateless rejections for connection ID " - << connection_id; - - // Continue stateless rejector processing - std::unique_ptr<StatelessRejectorProcessDoneCallback> cb( - new StatelessRejectorProcessDoneCallback(this, version)); - StatelessRejector::Process(std::move(rejector), std::move(cb)); -} - -void QuicDispatcher::OnStatelessRejectorProcessDone( - std::unique_ptr<StatelessRejector> rejector, - const QuicSocketAddress& current_client_address, - const QuicSocketAddress& current_peer_address, - const QuicSocketAddress& current_self_address, - std::unique_ptr<QuicReceivedPacket> current_packet, - ParsedQuicVersion first_version) { - // Stop buffering packets on this connection - const auto num_erased = - temporarily_buffered_connections_.erase(rejector->connection_id()); - QUIC_BUG_IF(num_erased != 1) << "Completing stateless rejection logic for " - "non-buffered connection ID " - << rejector->connection_id(); - - // If this connection has gone into time-wait during the async processing, - // don't proceed. - if (time_wait_list_manager_->IsConnectionIdInTimeWait( - rejector->connection_id())) { - time_wait_list_manager_->ProcessPacket( - current_self_address, current_peer_address, rejector->connection_id()); - return; - } - - // Reset current_* to correspond to the packet which initiated the stateless - // reject logic. - current_client_address_ = current_client_address; - current_peer_address_ = current_peer_address; - current_self_address_ = current_self_address; - current_packet_ = current_packet.get(); - current_connection_id_ = rejector->connection_id(); - framer_.set_version(first_version); - - ProcessStatelessRejectorState(std::move(rejector), - first_version.transport_version); -} - -void QuicDispatcher::ProcessStatelessRejectorState( - std::unique_ptr<StatelessRejector> rejector, - QuicTransportVersion first_version) { - QuicPacketFate fate; - switch (rejector->state()) { - case StatelessRejector::FAILED: { - // There was an error processing the client hello. - StatelessConnectionTerminator terminator(rejector->connection_id(), - &framer_, helper(), - time_wait_list_manager_.get()); - terminator.CloseConnection(rejector->error(), rejector->error_details()); - fate = kFateTimeWait; - break; - } - - case StatelessRejector::UNSUPPORTED: - // Cheap stateless rejects are not supported so process the packet. - fate = kFateProcess; - break; - - case StatelessRejector::ACCEPTED: - // Contains a valid CHLO, so process the packet and create a connection. - fate = kFateProcess; - break; - - case StatelessRejector::REJECTED: { - QUIC_BUG_IF(first_version != framer_.transport_version()) - << "SREJ: Client's version: " << QuicVersionToString(first_version) - << " is different from current dispatcher framer's version: " - << QuicVersionToString(framer_.transport_version()); - StatelessConnectionTerminator terminator(rejector->connection_id(), - &framer_, helper(), - time_wait_list_manager_.get()); - terminator.RejectConnection(rejector->reply() - .GetSerialized(Perspective::IS_SERVER) - .AsStringPiece()); - OnConnectionRejectedStatelessly(); - fate = kFateTimeWait; - break; - } - - default: - QUIC_BUG << "Rejector has invalid state " << rejector->state(); - fate = kFateDrop; - break; - } - ProcessUnauthenticatedHeaderFate(fate, rejector->connection_id()); -} - -const QuicTransportVersionVector& -QuicDispatcher::GetSupportedTransportVersions() { - return version_manager_->GetSupportedTransportVersions(); -} - -const ParsedQuicVersionVector& QuicDispatcher::GetSupportedVersions() { - return version_manager_->GetSupportedVersions(); -} - -void QuicDispatcher::DeliverPacketsToSession( - const std::list<BufferedPacket>& packets, - QuicSession* session) { - for (const BufferedPacket& packet : packets) { - session->ProcessUdpPacket(packet.server_address, packet.client_address, - *(packet.packet)); - } -} - -} // namespace net diff --git a/chromium/net/tools/quic/quic_dispatcher.h b/chromium/net/tools/quic/quic_dispatcher.h deleted file mode 100644 index 27c7c8cad6e..00000000000 --- a/chromium/net/tools/quic/quic_dispatcher.h +++ /dev/null @@ -1,438 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// A server side dispatcher which dispatches a given client's data to their -// stream. - -#ifndef NET_TOOLS_QUIC_QUIC_DISPATCHER_H_ -#define NET_TOOLS_QUIC_QUIC_DISPATCHER_H_ - -#include <memory> -#include <vector> - -#include "base/macros.h" -#include "net/quic/core/crypto/quic_compressed_certs_cache.h" -#include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_blocked_writer_interface.h" -#include "net/quic/core/quic_buffered_packet_store.h" -#include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_crypto_server_stream.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/core/quic_session.h" -#include "net/quic/core/quic_version_manager.h" -#include "net/quic/platform/api/quic_containers.h" -#include "net/quic/platform/api/quic_socket_address.h" -#include "net/quic/platform/api/quic_string.h" - -#include "net/tools/quic/quic_process_packet_interface.h" -#include "net/tools/quic/quic_time_wait_list_manager.h" -#include "net/tools/quic/stateless_rejector.h" - -namespace net { -namespace test { -class QuicDispatcherPeer; -} // namespace test - -class QuicConfig; -class QuicCryptoServerConfig; - -class QuicDispatcher : public QuicTimeWaitListManager::Visitor, - public ProcessPacketInterface, - public QuicFramerVisitorInterface, - public QuicBufferedPacketStore::VisitorInterface { - public: - // Ideally we'd have a linked_hash_set: the boolean is unused. - typedef QuicLinkedHashMap<QuicBlockedWriterInterface*, bool> WriteBlockedList; - - QuicDispatcher(const QuicConfig& config, - const QuicCryptoServerConfig* crypto_config, - QuicVersionManager* version_manager, - std::unique_ptr<QuicConnectionHelperInterface> helper, - std::unique_ptr<QuicCryptoServerStream::Helper> session_helper, - std::unique_ptr<QuicAlarmFactory> alarm_factory); - - ~QuicDispatcher() override; - - // Takes ownership of |writer|. - void InitializeWithWriter(QuicPacketWriter* writer); - - // Process the incoming packet by creating a new session, passing it to - // an existing session, or passing it to the time wait list. - void ProcessPacket(const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - const QuicReceivedPacket& packet) override; - - // Called when the socket becomes writable to allow queued writes to happen. - virtual void OnCanWrite(); - - // Returns true if there's anything in the blocked writer list. - virtual bool HasPendingWrites() const; - - // Sends ConnectionClose frames to all connected clients. - void Shutdown(); - - // QuicSession::Visitor interface implementation (via inheritance of - // QuicTimeWaitListManager::Visitor): - // Ensure that the closed connection is cleaned up asynchronously. - void OnConnectionClosed(QuicConnectionId connection_id, - QuicErrorCode error, - const QuicString& error_details) override; - - // QuicSession::Visitor interface implementation (via inheritance of - // QuicTimeWaitListManager::Visitor): - // Queues the blocked writer for later resumption. - void OnWriteBlocked(QuicBlockedWriterInterface* blocked_writer) override; - - // QuicSession::Visitor interface implementation (via inheritance of - // QuicTimeWaitListManager::Visitor): - // Collects reset error code received on streams. - void OnRstStreamReceived(const QuicRstStreamFrame& frame) override; - - // QuicTimeWaitListManager::Visitor interface implementation - // Called whenever the time wait list manager adds a new connection to the - // time-wait list. - void OnConnectionAddedToTimeWaitList(QuicConnectionId connection_id) override; - - using SessionMap = - QuicUnorderedMap<QuicConnectionId, std::unique_ptr<QuicSession>>; - - const SessionMap& session_map() const { return session_map_; } - - // Deletes all sessions on the closed session list and clears the list. - virtual void DeleteSessions(); - - // The largest packet number we expect to receive with a connection - // ID for a connection that is not established yet. The current design will - // send a handshake and then up to 50 or so data packets, and then it may - // resend the handshake packet up to 10 times. (Retransmitted packets are - // sent with unique packet numbers.) - static const QuicPacketNumber kMaxReasonableInitialPacketNumber = 100; - static_assert(kMaxReasonableInitialPacketNumber >= - kInitialCongestionWindow + 10, - "kMaxReasonableInitialPacketNumber is unreasonably small " - "relative to kInitialCongestionWindow."); - - // QuicFramerVisitorInterface implementation. Not expected to be called - // outside of this class. - void OnPacket() override; - // Called when the public header has been parsed. - bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override; - // Called when the private header has been parsed of a data packet that is - // destined for the time wait manager. - bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override; - void OnError(QuicFramer* framer) override; - bool OnProtocolVersionMismatch(ParsedQuicVersion received_version) override; - - // The following methods should never get called because - // OnUnauthenticatedPublicHeader() or OnUnauthenticatedHeader() (whichever - // was called last), will return false and prevent a subsequent invocation - // of these methods. Thus, the payload of the packet is never processed in - // the dispatcher. - void OnPublicResetPacket(const QuicPublicResetPacket& packet) override; - void OnVersionNegotiationPacket( - const QuicVersionNegotiationPacket& packet) override; - void OnDecryptedPacket(EncryptionLevel level) override; - bool OnPacketHeader(const QuicPacketHeader& header) override; - bool OnStreamFrame(const QuicStreamFrame& frame) override; - bool OnAckFrame(const QuicAckFrame& frame) override; - bool OnAckFrameStart(QuicPacketNumber largest_acked, - QuicTime::Delta ack_delay_time) override; - bool OnAckRange(QuicPacketNumber start, - QuicPacketNumber end, - bool last_range) override; - bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override; - bool OnPaddingFrame(const QuicPaddingFrame& frame) override; - bool OnPingFrame(const QuicPingFrame& frame) override; - bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override; - bool OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override; - bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override; - 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; - - // QuicBufferedPacketStore::VisitorInterface implementation. - void OnExpiredPackets(QuicConnectionId connection_id, - QuicBufferedPacketStore::BufferedPacketList - early_arrived_packets) override; - - // Create connections for previously buffered CHLOs as many as allowed. - virtual void ProcessBufferedChlos(size_t max_connections_to_create); - - // Return true if there is CHLO buffered. - virtual bool HasChlosBuffered() const; - - protected: - virtual QuicSession* CreateQuicSession(QuicConnectionId connection_id, - const QuicSocketAddress& peer_address, - QuicStringPiece alpn) = 0; - - // Called when a connection is rejected statelessly. - virtual void OnConnectionRejectedStatelessly(); - - // Called when a connection is closed statelessly. - virtual void OnConnectionClosedStatelessly(QuicErrorCode error); - - // Returns true if cheap stateless rejection should be attempted. - virtual bool ShouldAttemptCheapStatelessRejection(); - - // Values to be returned by ValidityChecks() to indicate what should be done - // with a packet. Fates with greater values are considered to be higher - // priority, in that if one validity check indicates a lower-valued fate and - // another validity check indicates a higher-valued fate, the higher-valued - // fate should be obeyed. - enum QuicPacketFate { - // Process the packet normally, which is usually to establish a connection. - kFateProcess, - // Put the connection ID into time-wait state and send a public reset. - kFateTimeWait, - // Buffer the packet. - kFateBuffer, - // Drop the packet (ignore and give no response). - kFateDrop, - }; - - // This method is called by OnUnauthenticatedHeader on packets not associated - // with a known connection ID. It applies validity checks and returns a - // QuicPacketFate to tell what should be done with the packet. - virtual QuicPacketFate ValidityChecks(const QuicPacketHeader& header); - - // Create and return the time wait list manager for this dispatcher, which - // will be owned by the dispatcher as time_wait_list_manager_ - virtual QuicTimeWaitListManager* CreateQuicTimeWaitListManager(); - - // Called when |connection_id| doesn't have an open connection yet, to buffer - // |current_packet_| until it can be delivered to the connection. - void BufferEarlyPacket(QuicConnectionId connection_id, bool ietf_quic); - - // Called when |current_packet_| is a CHLO packet. Creates a new connection - // and delivers any buffered packets for that connection id. - void ProcessChlo(); - - // Returns the actual client address of the current packet. - // This function should only be called once per packet at the very beginning - // of ProcessPacket(), its result is saved to |current_client_address_|, which - // is guaranteed to be valid even in the stateless rejector's callback(i.e. - // OnStatelessRejectorProcessDone). - // By default, this function returns |current_peer_address_|, subclasses have - // the option to override this function to return a different address. - virtual const QuicSocketAddress GetClientAddress() const; - - // Return true if dispatcher wants to destroy session outside of - // OnConnectionClosed() call stack. - virtual bool ShouldDestroySessionAsynchronously(); - - QuicTimeWaitListManager* time_wait_list_manager() { - return time_wait_list_manager_.get(); - } - - const QuicTransportVersionVector& GetSupportedTransportVersions(); - - const ParsedQuicVersionVector& GetSupportedVersions(); - - QuicConnectionId current_connection_id() const { - return current_connection_id_; - } - const QuicSocketAddress& current_self_address() const { - return current_self_address_; - } - const QuicSocketAddress& current_peer_address() const { - return current_peer_address_; - } - const QuicSocketAddress& current_client_address() const { - return current_client_address_; - } - const QuicReceivedPacket& current_packet() const { return *current_packet_; } - - const QuicConfig& config() const { return config_; } - - const QuicCryptoServerConfig* crypto_config() const { return crypto_config_; } - - QuicCompressedCertsCache* compressed_certs_cache() { - return &compressed_certs_cache_; - } - - QuicFramer* framer() { return &framer_; } - - QuicConnectionHelperInterface* helper() { return helper_.get(); } - - QuicCryptoServerStream::Helper* session_helper() { - return session_helper_.get(); - } - - QuicAlarmFactory* alarm_factory() { return alarm_factory_.get(); } - - QuicPacketWriter* writer() { return writer_.get(); } - - // Creates per-connection packet writers out of the QuicDispatcher's shared - // QuicPacketWriter. The per-connection writers' IsWriteBlocked() state must - // always be the same as the shared writer's IsWriteBlocked(), or else the - // QuicDispatcher::OnCanWrite logic will not work. (This will hopefully be - // cleaned up for bug 16950226.) - virtual QuicPacketWriter* CreatePerConnectionWriter(); - - // Returns true if a session should be created for a connection with an - // unknown version identified by |version_label|. - virtual bool ShouldCreateSessionForUnknownVersion( - QuicVersionLabel version_label); - - void SetLastError(QuicErrorCode error); - - // Called when the public header has been parsed and the session has been - // looked up, and the session was not found in the active list of sessions. - // Returns false if processing should stop after this call. - virtual bool OnUnauthenticatedUnknownPublicHeader( - const QuicPacketHeader& header); - - // Called when a new connection starts to be handled by this dispatcher. - // Either this connection is created or its packets is buffered while waiting - // for CHLO. Returns true if a new connection should be created or its packets - // should be buffered, false otherwise. - virtual bool ShouldCreateOrBufferPacketForConnection( - QuicConnectionId connection_id); - - bool HasBufferedPackets(QuicConnectionId connection_id); - - // Called when BufferEarlyPacket() fail to buffer the packet. - virtual void OnBufferPacketFailure( - QuicBufferedPacketStore::EnqueuePacketResult result, - QuicConnectionId connection_id); - - // Removes the session from the session map and write blocked list, and adds - // the ConnectionId to the time-wait list. If |session_closed_statelessly| is - // true, any future packets for the ConnectionId will be black-holed. - virtual void CleanUpSession(SessionMap::iterator it, - QuicConnection* connection, - bool session_closed_statelessly); - - void StopAcceptingNewConnections(); - - // Return true if the blocked writer should be added to blocked list. - virtual bool ShouldAddToBlockedList(); - - private: - friend class test::QuicDispatcherPeer; - friend class StatelessRejectorProcessDoneCallback; - - typedef QuicUnorderedSet<QuicConnectionId> QuicConnectionIdSet; - - bool HandlePacketForTimeWait(const QuicPacketHeader& header); - - // Attempts to reject the connection statelessly, if stateless rejects are - // possible and if the current packet contains a CHLO message. Determines a - // fate which describes what subsequent processing should be performed on the - // packets, like ValidityChecks, and invokes ProcessUnauthenticatedHeaderFate. - void MaybeRejectStatelessly(QuicConnectionId connection_id, - ParsedQuicVersion version); - - // Deliver |packets| to |session| for further processing. - void DeliverPacketsToSession( - const std::list<QuicBufferedPacketStore::BufferedPacket>& packets, - QuicSession* session); - - // Perform the appropriate actions on the current packet based on |fate| - - // either process, buffer, or drop it. - void ProcessUnauthenticatedHeaderFate(QuicPacketFate fate, - QuicConnectionId connection_id); - - // Invoked when StatelessRejector::Process completes. |first_version| is the - // version of the packet which initiated the stateless reject. - // WARNING: This function can be called when a async proof returns, i.e. not - // from a stack traceable to ProcessPacket(). - void OnStatelessRejectorProcessDone( - std::unique_ptr<StatelessRejector> rejector, - const QuicSocketAddress& current_client_address, - const QuicSocketAddress& current_peer_address, - const QuicSocketAddress& current_self_address, - std::unique_ptr<QuicReceivedPacket> current_packet, - ParsedQuicVersion first_version); - - // Examine the state of the rejector and decide what to do with the current - // packet. - void ProcessStatelessRejectorState( - std::unique_ptr<StatelessRejector> rejector, - QuicTransportVersion first_version); - - void set_new_sessions_allowed_per_event_loop( - int16_t new_sessions_allowed_per_event_loop) { - new_sessions_allowed_per_event_loop_ = new_sessions_allowed_per_event_loop; - } - - const QuicConfig& config_; - - const QuicCryptoServerConfig* crypto_config_; - - // The cache for most recently compressed certs. - QuicCompressedCertsCache compressed_certs_cache_; - - // The list of connections waiting to write. - WriteBlockedList write_blocked_list_; - - SessionMap session_map_; - - // Entity that manages connection_ids in time wait state. - std::unique_ptr<QuicTimeWaitListManager> time_wait_list_manager_; - - // The list of closed but not-yet-deleted sessions. - std::vector<std::unique_ptr<QuicSession>> closed_session_list_; - - // The helper used for all connections. - std::unique_ptr<QuicConnectionHelperInterface> helper_; - - // The helper used for all sessions. - std::unique_ptr<QuicCryptoServerStream::Helper> session_helper_; - - // Creates alarms. - std::unique_ptr<QuicAlarmFactory> alarm_factory_; - - // An alarm which deletes closed sessions. - std::unique_ptr<QuicAlarm> delete_sessions_alarm_; - - // The writer to write to the socket with. - std::unique_ptr<QuicPacketWriter> writer_; - - // Packets which are buffered until a connection can be created to handle - // them. - QuicBufferedPacketStore buffered_packets_; - - // Set of connection IDs for which asynchronous CHLO processing is in - // progress, making it necessary to buffer any other packets which arrive on - // that connection until CHLO processing is complete. - QuicConnectionIdSet temporarily_buffered_connections_; - - // Information about the packet currently being handled. - - // Used for stateless rejector to generate and validate source address token. - QuicSocketAddress current_client_address_; - QuicSocketAddress current_peer_address_; - QuicSocketAddress current_self_address_; - const QuicReceivedPacket* current_packet_; - // If |current_packet_| is a CHLO packet, the extracted alpn. - QuicString current_alpn_; - QuicConnectionId current_connection_id_; - - // Used to get the supported versions based on flag. Does not own. - QuicVersionManager* version_manager_; - - QuicFramer framer_; - - // The last error set by SetLastError(), which is called by - // framer_visitor_->OnError(). - QuicErrorCode last_error_; - - // A backward counter of how many new sessions can be create within current - // event loop. When reaches 0, it means can't create sessions for now. - int16_t new_sessions_allowed_per_event_loop_; - - // True if this dispatcher is not draining. - bool accept_new_connections_; - - DISALLOW_COPY_AND_ASSIGN(QuicDispatcher); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_DISPATCHER_H_ diff --git a/chromium/net/tools/quic/quic_dispatcher_test.cc b/chromium/net/tools/quic/quic_dispatcher_test.cc deleted file mode 100644 index 1f118e14f62..00000000000 --- a/chromium/net/tools/quic/quic_dispatcher_test.cc +++ /dev/null @@ -1,2421 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_dispatcher.h" - -#include <memory> -#include <ostream> - -#include "base/callback.h" -#include "base/macros.h" -#include "net/quic/core/crypto/crypto_handshake.h" -#include "net/quic/core/crypto/crypto_protocol.h" -#include "net/quic/core/crypto/quic_crypto_server_config.h" -#include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_crypto_stream.h" -#include "net/quic/core/quic_utils.h" -#include "net/quic/core/tls_server_handshaker.h" -#include "net/quic/platform/api/quic_arraysize.h" -#include "net/quic/platform/api/quic_flags.h" -#include "net/quic/platform/api/quic_logging.h" -#include "net/quic/platform/api/quic_str_cat.h" -#include "net/quic/platform/api/quic_string.h" -#include "net/quic/platform/api/quic_test.h" -#include "net/quic/test_tools/crypto_test_utils.h" -#include "net/quic/test_tools/fake_proof_source.h" -#include "net/quic/test_tools/quic_buffered_packet_store_peer.h" -#include "net/quic/test_tools/quic_crypto_server_config_peer.h" -#include "net/quic/test_tools/quic_test_utils.h" -#include "net/quic/test_tools/quic_time_wait_list_manager_peer.h" -#include "net/test/gtest_util.h" -#include "net/tools/epoll_server/epoll_server.h" -#include "net/tools/quic/chlo_extractor.h" -#include "net/tools/quic/quic_epoll_alarm_factory.h" -#include "net/tools/quic/quic_epoll_connection_helper.h" -#include "net/tools/quic/quic_packet_writer_wrapper.h" -#include "net/tools/quic/quic_simple_crypto_server_stream_helper.h" -#include "net/tools/quic/quic_time_wait_list_manager.h" -#include "net/tools/quic/stateless_rejector.h" -#include "net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h" -#include "net/tools/quic/test_tools/quic_dispatcher_peer.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gmock_mutant.h" -#include "testing/gtest/include/gtest/gtest.h" - -using std::string; -using testing::_; -using testing::InSequence; -using testing::Invoke; -using testing::Return; -using testing::WithArg; -using testing::WithoutArgs; - -static const size_t kDefaultMaxConnectionsInStore = 100; -static const size_t kMaxConnectionsWithoutCHLO = - kDefaultMaxConnectionsInStore / 2; -static const int16_t kMaxNumSessionsToCreate = 16; - -namespace net { -namespace test { -namespace { - -class TestQuicSpdyServerSession : public QuicServerSessionBase { - public: - TestQuicSpdyServerSession(const QuicConfig& config, - QuicConnection* connection, - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache) - : QuicServerSessionBase(config, - connection, - nullptr, - nullptr, - crypto_config, - compressed_certs_cache), - crypto_stream_(QuicServerSessionBase::GetMutableCryptoStream()) {} - - ~TestQuicSpdyServerSession() override { delete connection(); }; - - MOCK_METHOD3(OnConnectionClosed, - void(QuicErrorCode error, - const QuicString& error_details, - ConnectionCloseSource source)); - MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id)); - MOCK_METHOD0(CreateOutgoingDynamicStream, QuicSpdyStream*()); - - QuicCryptoServerStreamBase* CreateQuicCryptoServerStream( - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache) override { - return new QuicCryptoServerStream( - crypto_config, compressed_certs_cache, - GetQuicReloadableFlag(enable_quic_stateless_reject_support), this, - stream_helper()); - } - - void SetCryptoStream(QuicCryptoServerStream* crypto_stream) { - crypto_stream_ = crypto_stream; - } - - QuicCryptoServerStreamBase* GetMutableCryptoStream() override { - return crypto_stream_; - } - - const QuicCryptoServerStreamBase* GetCryptoStream() const override { - return crypto_stream_; - } - - QuicCryptoServerStream::Helper* stream_helper() { - return QuicServerSessionBase::stream_helper(); - } - - private: - QuicCryptoServerStreamBase* crypto_stream_; - - DISALLOW_COPY_AND_ASSIGN(TestQuicSpdyServerSession); -}; - -class TestDispatcher : public QuicDispatcher { - public: - TestDispatcher(const QuicConfig& config, - const QuicCryptoServerConfig* crypto_config, - QuicVersionManager* version_manager, - EpollServer* eps) - : QuicDispatcher( - config, - crypto_config, - version_manager, - std::unique_ptr<QuicEpollConnectionHelper>( - new QuicEpollConnectionHelper(eps, QuicAllocator::BUFFER_POOL)), - std::unique_ptr<QuicCryptoServerStream::Helper>( - new QuicSimpleCryptoServerStreamHelper( - QuicRandom::GetInstance())), - std::unique_ptr<QuicEpollAlarmFactory>( - new QuicEpollAlarmFactory(eps))) {} - - MOCK_METHOD3(CreateQuicSession, - QuicServerSessionBase*(QuicConnectionId connection_id, - const QuicSocketAddress& peer_address, - QuicStringPiece alpn)); - - MOCK_METHOD1(ShouldCreateOrBufferPacketForConnection, - bool(QuicConnectionId connection_id)); - - using QuicDispatcher::current_client_address; - using QuicDispatcher::current_peer_address; - using QuicDispatcher::current_self_address; -}; - -// A Connection class which unregisters the session from the dispatcher when -// sending connection close. -// It'd be slightly more realistic to do this from the Session but it would -// involve a lot more mocking. -class MockServerConnection : public MockQuicConnection { - public: - MockServerConnection(QuicConnectionId connection_id, - MockQuicConnectionHelper* helper, - MockAlarmFactory* alarm_factory, - QuicDispatcher* dispatcher) - : MockQuicConnection(connection_id, - helper, - alarm_factory, - Perspective::IS_SERVER), - dispatcher_(dispatcher) {} - - void UnregisterOnConnectionClosed() { - QUIC_LOG(ERROR) << "Unregistering " << connection_id(); - dispatcher_->OnConnectionClosed(connection_id(), QUIC_NO_ERROR, - "Unregistering."); - } - - private: - QuicDispatcher* dispatcher_; -}; - -class QuicDispatcherTest : public QuicTest { - public: - QuicDispatcherTest() - : QuicDispatcherTest(crypto_test_utils::ProofSourceForTesting()) {} - - ParsedQuicVersionVector AllSupportedVersionsIncludingTls() { - SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true); - return AllSupportedVersions(); - } - - explicit QuicDispatcherTest(std::unique_ptr<ProofSource> proof_source) - : helper_(&eps_, QuicAllocator::BUFFER_POOL), - alarm_factory_(&eps_), - version_manager_(AllSupportedVersionsIncludingTls()), - crypto_config_(QuicCryptoServerConfig::TESTING, - QuicRandom::GetInstance(), - std::move(proof_source), - TlsServerHandshaker::CreateSslCtx()), - dispatcher_(new TestDispatcher(config_, - &crypto_config_, - &version_manager_, - &eps_)), - time_wait_list_manager_(nullptr), - session1_(nullptr), - session2_(nullptr), - store_(nullptr) {} - - void SetUp() override { - dispatcher_->InitializeWithWriter(new QuicDefaultPacketWriter(1)); - // Set the counter to some value to start with. - QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop( - dispatcher_.get(), kMaxNumSessionsToCreate); - ON_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(_)) - .WillByDefault(Return(true)); - } - - ~QuicDispatcherTest() override = default; - - MockQuicConnection* connection1() { - return reinterpret_cast<MockQuicConnection*>(session1_->connection()); - } - - MockQuicConnection* connection2() { - return reinterpret_cast<MockQuicConnection*>(session2_->connection()); - } - - // Process a packet with an 8 byte connection id, - // 6 byte packet number, default path id, and packet number 1, - // using the first supported version. - void ProcessPacket(QuicSocketAddress peer_address, - QuicConnectionId connection_id, - bool has_version_flag, - const QuicString& data) { - ProcessPacket(peer_address, connection_id, has_version_flag, data, - PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER); - } - - // Process a packet with a default path id, and packet number 1, - // using the first supported version. - void ProcessPacket(QuicSocketAddress peer_address, - QuicConnectionId connection_id, - bool has_version_flag, - const QuicString& data, - QuicConnectionIdLength connection_id_length, - QuicPacketNumberLength packet_number_length) { - ProcessPacket(peer_address, connection_id, has_version_flag, data, - connection_id_length, packet_number_length, 1); - } - - // Process a packet using the first supported version. - void ProcessPacket(QuicSocketAddress peer_address, - QuicConnectionId connection_id, - bool has_version_flag, - const QuicString& data, - QuicConnectionIdLength connection_id_length, - QuicPacketNumberLength packet_number_length, - QuicPacketNumber packet_number) { - ProcessPacket(peer_address, connection_id, has_version_flag, - CurrentSupportedVersions().front(), data, - connection_id_length, packet_number_length, packet_number); - } - - // Processes a packet. - void ProcessPacket(QuicSocketAddress peer_address, - QuicConnectionId connection_id, - bool has_version_flag, - ParsedQuicVersion version, - const QuicString& data, - QuicConnectionIdLength connection_id_length, - QuicPacketNumberLength packet_number_length, - QuicPacketNumber packet_number) { - ParsedQuicVersionVector versions(SupportedVersions(version)); - std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket( - connection_id, has_version_flag, false, packet_number, data, - connection_id_length, packet_number_length, &versions)); - std::unique_ptr<QuicReceivedPacket> received_packet( - ConstructReceivedPacket(*packet, helper_.GetClock()->Now())); - - if (ChloExtractor::Extract(*packet, versions, {}, nullptr)) { - // Add CHLO packet to the beginning to be verified first, because it is - // also processed first by new session. - data_connection_map_[connection_id].push_front( - QuicString(packet->data(), packet->length())); - } else { - // For non-CHLO, always append to last. - data_connection_map_[connection_id].push_back( - QuicString(packet->data(), packet->length())); - } - dispatcher_->ProcessPacket(server_address_, peer_address, *received_packet); - } - - void ValidatePacket(QuicConnectionId conn_id, - const QuicEncryptedPacket& packet) { - EXPECT_EQ(data_connection_map_[conn_id].front().length(), - packet.AsStringPiece().length()); - EXPECT_EQ(data_connection_map_[conn_id].front(), packet.AsStringPiece()); - data_connection_map_[conn_id].pop_front(); - } - - QuicServerSessionBase* CreateSession( - QuicDispatcher* dispatcher, - const QuicConfig& config, - QuicConnectionId connection_id, - const QuicSocketAddress& peer_address, - MockQuicConnectionHelper* helper, - MockAlarmFactory* alarm_factory, - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache, - TestQuicSpdyServerSession** session) { - MockServerConnection* connection = new MockServerConnection( - connection_id, helper, alarm_factory, dispatcher); - *session = new TestQuicSpdyServerSession(config, connection, crypto_config, - compressed_certs_cache); - connection->set_visitor(*session); - ON_CALL(*connection, CloseConnection(_, _, _)) - .WillByDefault(WithoutArgs(Invoke( - connection, &MockServerConnection::UnregisterOnConnectionClosed))); - return *session; - } - - void CreateTimeWaitListManager() { - time_wait_list_manager_ = new MockTimeWaitListManager( - QuicDispatcherPeer::GetWriter(dispatcher_.get()), dispatcher_.get(), - &helper_, &alarm_factory_); - // dispatcher_ takes the ownership of time_wait_list_manager_. - QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(), - time_wait_list_manager_); - } - - QuicString SerializeCHLO() { - CryptoHandshakeMessage client_hello; - client_hello.set_tag(kCHLO); - client_hello.SetStringPiece(kALPN, "hq"); - return string( - client_hello.GetSerialized(Perspective::IS_CLIENT).AsStringPiece()); - } - - QuicString SerializeTlsClientHello() { return ""; } - - EpollServer eps_; - QuicEpollConnectionHelper helper_; - MockQuicConnectionHelper mock_helper_; - QuicEpollAlarmFactory alarm_factory_; - MockAlarmFactory mock_alarm_factory_; - QuicConfig config_; - QuicVersionManager version_manager_; - QuicCryptoServerConfig crypto_config_; - QuicSocketAddress server_address_; - std::unique_ptr<TestDispatcher> dispatcher_; - MockTimeWaitListManager* time_wait_list_manager_; - TestQuicSpdyServerSession* session1_; - TestQuicSpdyServerSession* session2_; - std::map<QuicConnectionId, std::list<QuicString>> data_connection_map_; - QuicBufferedPacketStore* store_; -}; - -TEST_F(QuicDispatcherTest, TlsClientHelloCreatesSession) { - FLAGS_quic_supports_tls_handshake = true; - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5); - - EXPECT_CALL(*dispatcher_, - CreateQuicSession(1, client_address, QuicStringPiece(""))) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, 1, client_address, &mock_helper_, - &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) { - ValidatePacket(1, packet); - }))); - EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(1)); - ProcessPacket( - client_address, 1, true, - ParsedQuicVersion(PROTOCOL_TLS1_3, - CurrentSupportedVersions().front().transport_version), - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, - 1); - EXPECT_EQ(client_address, dispatcher_->current_peer_address()); - EXPECT_EQ(server_address_, dispatcher_->current_self_address()); -} - -TEST_F(QuicDispatcherTest, ProcessPackets) { - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5); - - EXPECT_CALL(*dispatcher_, - CreateQuicSession(1, client_address, QuicStringPiece("hq"))) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, 1, client_address, &mock_helper_, - &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) { - ValidatePacket(1, packet); - }))); - EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(1)); - ProcessPacket(client_address, 1, true, SerializeCHLO()); - EXPECT_EQ(client_address, dispatcher_->current_peer_address()); - EXPECT_EQ(server_address_, dispatcher_->current_self_address()); - - EXPECT_CALL(*dispatcher_, - CreateQuicSession(2, client_address, QuicStringPiece("hq"))) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, 2, client_address, &mock_helper_, - &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) { - ValidatePacket(2, packet); - }))); - EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(2)); - ProcessPacket(client_address, 2, true, SerializeCHLO()); - - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .Times(1) - .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) { - ValidatePacket(1, packet); - }))); - ProcessPacket(client_address, 1, false, "data"); -} - -TEST_F(QuicDispatcherTest, StatelessVersionNegotiation) { - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5); - - EXPECT_CALL(*dispatcher_, - CreateQuicSession(1, client_address, QuicStringPiece("hq"))) - .Times(0); - QuicTransportVersion version = - static_cast<QuicTransportVersion>(QuicTransportVersionMin() - 1); - ParsedQuicVersion parsed_version(PROTOCOL_QUIC_CRYPTO, version); - ProcessPacket(client_address, 1, true, parsed_version, SerializeCHLO(), - PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, 1); -} - -TEST_F(QuicDispatcherTest, Shutdown) { - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - - EXPECT_CALL(*dispatcher_, - CreateQuicSession(_, client_address, QuicStringPiece("hq"))) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, 1, client_address, &mock_helper_, - &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) { - ValidatePacket(1, packet); - }))); - - EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(1)); - ProcessPacket(client_address, 1, true, SerializeCHLO()); - - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - CloseConnection(QUIC_PEER_GOING_AWAY, _, _)); - - dispatcher_->Shutdown(); -} - -TEST_F(QuicDispatcherTest, TimeWaitListManager) { - CreateTimeWaitListManager(); - - // Create a new session. - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - QuicConnectionId connection_id = 1; - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address, - QuicStringPiece("hq"))) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, connection_id, client_address, - &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) { - ValidatePacket(1, packet); - }))); - - EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(1)); - ProcessPacket(client_address, connection_id, true, SerializeCHLO()); - - // Close the connection by sending public reset packet. - QuicPublicResetPacket packet; - packet.connection_id = connection_id; - packet.nonce_proof = 132232; - std::unique_ptr<QuicEncryptedPacket> encrypted( - QuicFramer::BuildPublicResetPacket(packet)); - std::unique_ptr<QuicReceivedPacket> received(ConstructReceivedPacket( - *encrypted, session1_->connection()->clock()->Now())); - EXPECT_CALL(*session1_, OnConnectionClosed(QUIC_PUBLIC_RESET, _, - ConnectionCloseSource::FROM_PEER)) - .Times(1) - .WillOnce(WithoutArgs(Invoke( - reinterpret_cast<MockServerConnection*>(session1_->connection()), - &MockServerConnection::UnregisterOnConnectionClosed))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce( - Invoke(reinterpret_cast<MockQuicConnection*>(session1_->connection()), - &MockQuicConnection::ReallyProcessUdpPacket)); - dispatcher_->ProcessPacket(QuicSocketAddress(), client_address, *received); - EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); - - // Dispatcher forwards subsequent packets for this connection_id to the time - // wait list manager. - EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, connection_id)) - .Times(1); - EXPECT_CALL(*time_wait_list_manager_, - AddConnectionIdToTimeWait(_, _, _, _, _)) - .Times(0); - ProcessPacket(client_address, connection_id, true, "data"); -} - -TEST_F(QuicDispatcherTest, NoVersionPacketToTimeWaitListManager) { - CreateTimeWaitListManager(); - - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - QuicConnectionId connection_id = 1; - // Dispatcher forwards all packets for this connection_id to the time wait - // list manager. - EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, QuicStringPiece("hq"))) - .Times(0); - EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, connection_id)) - .Times(1); - EXPECT_CALL(*time_wait_list_manager_, - AddConnectionIdToTimeWait(_, _, _, _, _)) - .Times(1); - ProcessPacket(client_address, connection_id, false, SerializeCHLO()); -} - -TEST_F(QuicDispatcherTest, ProcessPacketWithZeroPort) { - CreateTimeWaitListManager(); - - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 0); - server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5); - - // dispatcher_ should drop this packet. - EXPECT_CALL(*dispatcher_, - CreateQuicSession(1, client_address, QuicStringPiece("hq"))) - .Times(0); - EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _)).Times(0); - EXPECT_CALL(*time_wait_list_manager_, - AddConnectionIdToTimeWait(_, _, _, _, _)) - .Times(0); - ProcessPacket(client_address, 1, true, SerializeCHLO()); -} - -TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) { - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - QuicConnectionId connection_id = 1; - server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5); - - EXPECT_CALL(*dispatcher_, - CreateQuicSession(1, client_address, QuicStringPiece("hq"))) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, 1, client_address, &mock_helper_, - &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) { - ValidatePacket(1, packet); - }))); - - // A packet whose packet number is the largest that is allowed to start a - // connection. - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection(connection_id)); - ProcessPacket(client_address, connection_id, true, SerializeCHLO(), - PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, - QuicDispatcher::kMaxReasonableInitialPacketNumber); - EXPECT_EQ(client_address, dispatcher_->current_peer_address()); - EXPECT_EQ(server_address_, dispatcher_->current_self_address()); -} - -TEST_F(QuicDispatcherTest, TooBigSeqNoPacketToTimeWaitListManager) { - CreateTimeWaitListManager(); - SetQuicRestartFlag(quic_enable_accept_random_ipn, false); - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - QuicConnectionId connection_id = 1; - - // Dispatcher forwards this packet for this connection_id to the time wait - // list manager. - EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, QuicStringPiece("hq"))) - .Times(0); - EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, 1)).Times(1); - EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, 2)).Times(1); - EXPECT_CALL(*time_wait_list_manager_, - AddConnectionIdToTimeWait(_, _, _, _, _)) - .Times(2); - // A packet whose packet number is one to large to be allowed to start a - // connection. - ProcessPacket(client_address, connection_id, true, SerializeCHLO(), - PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, - QuicDispatcher::kMaxReasonableInitialPacketNumber + 1); - connection_id = 2; - SetQuicRestartFlag(quic_enable_accept_random_ipn, true); - ProcessPacket(client_address, connection_id, true, SerializeCHLO(), - PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, - kMaxRandomInitialPacketNumber + - QuicDispatcher::kMaxReasonableInitialPacketNumber + 1); -} - -TEST_F(QuicDispatcherTest, SupportedTransportVersionsChangeInFlight) { - static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u, - "Supported versions out of sync"); - SetQuicReloadableFlag(quic_disable_version_37, false); - SetQuicReloadableFlag(quic_disable_version_38, false); - SetQuicReloadableFlag(quic_disable_version_41, false); - SetQuicReloadableFlag(quic_enable_version_42_2, true); - SetQuicReloadableFlag(quic_enable_version_43, true); - SetQuicFlag(&FLAGS_quic_enable_version_99, true); - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5); - QuicConnectionId connection_id = 1; - - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address, - QuicStringPiece("hq"))) - .Times(0); - ParsedQuicVersion version( - PROTOCOL_QUIC_CRYPTO, - static_cast<QuicTransportVersion>(QuicTransportVersionMin() - 1)); - ProcessPacket(client_address, connection_id, true, version, SerializeCHLO(), - PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, 1); - ++connection_id; - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address, - QuicStringPiece("hq"))) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, connection_id, client_address, - &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, connection_id](const QuicEncryptedPacket& packet) { - ValidatePacket(connection_id, packet); - }))); - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection(connection_id)); - ProcessPacket(client_address, connection_id, true, - ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, - QuicVersionMin().transport_version), - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, - PACKET_4BYTE_PACKET_NUMBER, 1); - ++connection_id; - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address, - QuicStringPiece("hq"))) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, connection_id, client_address, - &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, connection_id](const QuicEncryptedPacket& packet) { - ValidatePacket(connection_id, packet); - }))); - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection(connection_id)); - ProcessPacket(client_address, connection_id, true, QuicVersionMax(), - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, - PACKET_4BYTE_PACKET_NUMBER, 1); - - // Turn off version 43. - SetQuicReloadableFlag(quic_enable_version_43, false); - ++connection_id; - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address, - QuicStringPiece("hq"))) - .Times(0); - ProcessPacket(client_address, connection_id, true, - ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43), - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, - PACKET_4BYTE_PACKET_NUMBER, 1); - - // Turn on version 43. - SetQuicReloadableFlag(quic_enable_version_43, true); - ++connection_id; - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address, - QuicStringPiece("hq"))) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, connection_id, client_address, - &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, connection_id](const QuicEncryptedPacket& packet) { - ValidatePacket(connection_id, packet); - }))); - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection(connection_id)); - ProcessPacket(client_address, connection_id, true, - ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43), - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, - PACKET_4BYTE_PACKET_NUMBER, 1); - - // Turn off version 42. - SetQuicReloadableFlag(quic_enable_version_42_2, false); - ++connection_id; - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address, - QuicStringPiece("hq"))) - .Times(0); - ProcessPacket(client_address, connection_id, true, - ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_42), - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, - PACKET_4BYTE_PACKET_NUMBER, 1); - - // Turn on version 42. - SetQuicReloadableFlag(quic_enable_version_42_2, true); - ++connection_id; - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address, - QuicStringPiece("hq"))) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, connection_id, client_address, - &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, connection_id](const QuicEncryptedPacket& packet) { - ValidatePacket(connection_id, packet); - }))); - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection(connection_id)); - ProcessPacket(client_address, connection_id, true, - ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_42), - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, - PACKET_4BYTE_PACKET_NUMBER, 1); - - // Turn off version 41. - SetQuicReloadableFlag(quic_disable_version_41, true); - ++connection_id; - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address, - QuicStringPiece("hq"))) - .Times(0); - ProcessPacket(client_address, connection_id, true, - ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_41), - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, - PACKET_4BYTE_PACKET_NUMBER, 1); - - // Turn on version 41. - SetQuicReloadableFlag(quic_disable_version_41, false); - ++connection_id; - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address, - QuicStringPiece("hq"))) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, connection_id, client_address, - &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, connection_id](const QuicEncryptedPacket& packet) { - ValidatePacket(connection_id, packet); - }))); - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection(connection_id)); - ProcessPacket(client_address, connection_id, true, - ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_41), - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, - PACKET_4BYTE_PACKET_NUMBER, 1); - - // Turn off version 38. - SetQuicReloadableFlag(quic_disable_version_38, true); - ++connection_id; - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address, - QuicStringPiece("hq"))) - .Times(0); - ProcessPacket(client_address, connection_id, true, - ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_38), - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, - PACKET_4BYTE_PACKET_NUMBER, 1); - - // Turn on version 38. - SetQuicReloadableFlag(quic_disable_version_38, false); - ++connection_id; - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address, - QuicStringPiece("hq"))) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, connection_id, client_address, - &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, connection_id](const QuicEncryptedPacket& packet) { - ValidatePacket(connection_id, packet); - }))); - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection(connection_id)); - ProcessPacket(client_address, connection_id, true, - ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_38), - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, - PACKET_4BYTE_PACKET_NUMBER, 1); - - // Turn off version 37. - SetQuicReloadableFlag(quic_disable_version_37, true); - ++connection_id; - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address, - QuicStringPiece("hq"))) - .Times(0); - ProcessPacket(client_address, connection_id, true, - ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_37), - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, - PACKET_4BYTE_PACKET_NUMBER, 1); - - // Turn on version 37. - SetQuicReloadableFlag(quic_disable_version_37, false); - ++connection_id; - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address, - QuicStringPiece("hq"))) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, connection_id, client_address, - &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, connection_id](const QuicEncryptedPacket& packet) { - ValidatePacket(connection_id, packet); - }))); - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection(connection_id)); - ProcessPacket(client_address, connection_id, true, - ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_37), - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, - PACKET_4BYTE_PACKET_NUMBER, 1); -} - -// Enables mocking of the handshake-confirmation for stateless rejects. -class MockQuicCryptoServerStream : public QuicCryptoServerStream { - public: - MockQuicCryptoServerStream(const QuicCryptoServerConfig& crypto_config, - QuicCompressedCertsCache* compressed_certs_cache, - QuicServerSessionBase* session, - QuicCryptoServerStream::Helper* helper) - : QuicCryptoServerStream( - &crypto_config, - compressed_certs_cache, - GetQuicReloadableFlag(enable_quic_stateless_reject_support), - session, - helper), - handshake_confirmed_(false) {} - - void set_handshake_confirmed_for_testing(bool handshake_confirmed) { - handshake_confirmed_ = handshake_confirmed; - } - - bool handshake_confirmed() const override { return handshake_confirmed_; } - - private: - bool handshake_confirmed_; - DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStream); -}; - -struct StatelessRejectTestParams { - StatelessRejectTestParams(bool enable_stateless_rejects_via_flag, - bool client_supports_statelesss_rejects, - bool crypto_handshake_successful) - : enable_stateless_rejects_via_flag(enable_stateless_rejects_via_flag), - client_supports_statelesss_rejects(client_supports_statelesss_rejects), - crypto_handshake_successful(crypto_handshake_successful) {} - - friend std::ostream& operator<<(std::ostream& os, - const StatelessRejectTestParams& p) { - os << "{ enable_stateless_rejects_via_flag: " - << p.enable_stateless_rejects_via_flag << std::endl; - os << " client_supports_statelesss_rejects: " - << p.client_supports_statelesss_rejects << std::endl; - os << " crypto_handshake_successful: " << p.crypto_handshake_successful - << " }"; - return os; - } - - // This only enables the stateless reject feature via the feature-flag. - // This should be a no-op if the peer does not support them. - bool enable_stateless_rejects_via_flag; - // Whether or not the client supports stateless rejects. - bool client_supports_statelesss_rejects; - // Should the initial crypto handshake succeed or not. - bool crypto_handshake_successful; -}; - -// Constructs various test permutations for stateless rejects. -std::vector<StatelessRejectTestParams> GetStatelessRejectTestParams() { - std::vector<StatelessRejectTestParams> params; - for (bool enable_stateless_rejects_via_flag : {true, false}) { - for (bool client_supports_statelesss_rejects : {true, false}) { - for (bool crypto_handshake_successful : {true, false}) { - params.push_back(StatelessRejectTestParams( - enable_stateless_rejects_via_flag, - client_supports_statelesss_rejects, crypto_handshake_successful)); - } - } - } - return params; -} - -class QuicDispatcherStatelessRejectTest - : public QuicDispatcherTest, - public testing::WithParamInterface<StatelessRejectTestParams> { - public: - QuicDispatcherStatelessRejectTest() - : QuicDispatcherTest(), crypto_stream1_(nullptr) {} - - ~QuicDispatcherStatelessRejectTest() override { - if (crypto_stream1_) { - delete crypto_stream1_; - } - } - - // This test setup assumes that all testing will be done using - // crypto_stream1_. - void SetUp() override { - QuicDispatcherTest::SetUp(); - SetQuicReloadableFlag(enable_quic_stateless_reject_support, - GetParam().enable_stateless_rejects_via_flag); - } - - // Returns true or false, depending on whether the server will emit - // a stateless reject, depending upon the parameters of the test. - bool ExpectStatelessReject() { - return GetParam().enable_stateless_rejects_via_flag && - !GetParam().crypto_handshake_successful && - GetParam().client_supports_statelesss_rejects; - } - - // Sets up dispatcher_, session1_, and crypto_stream1_ based on - // the test parameters. - QuicServerSessionBase* CreateSessionBasedOnTestParams( - QuicConnectionId connection_id, - const QuicSocketAddress& client_address) { - CreateSession(dispatcher_.get(), config_, connection_id, client_address, - &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_); - - crypto_stream1_ = new MockQuicCryptoServerStream( - crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()), - session1_, session1_->stream_helper()); - session1_->SetCryptoStream(crypto_stream1_); - crypto_stream1_->set_handshake_confirmed_for_testing( - GetParam().crypto_handshake_successful); - crypto_stream1_->SetPeerSupportsStatelessRejects( - GetParam().client_supports_statelesss_rejects); - return session1_; - } - - MockQuicCryptoServerStream* crypto_stream1_; -}; - -// Parameterized test for stateless rejects. Should test all -// combinations of enabling/disabling, reject/no-reject for stateless -// rejects. -INSTANTIATE_TEST_CASE_P(QuicDispatcherStatelessRejectTests, - QuicDispatcherStatelessRejectTest, - ::testing::ValuesIn(GetStatelessRejectTestParams())); - -TEST_P(QuicDispatcherStatelessRejectTest, ParameterizedBasicTest) { - CreateTimeWaitListManager(); - - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - QuicConnectionId connection_id = 1; - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address, - QuicStringPiece("hq"))) - .WillOnce(testing::Return( - CreateSessionBasedOnTestParams(connection_id, client_address))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, connection_id](const QuicEncryptedPacket& packet) { - ValidatePacket(connection_id, packet); - }))); - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection(connection_id)) - .Times(1); - - // Process the first packet for the connection. - ProcessPacket(client_address, connection_id, true, SerializeCHLO()); - if (ExpectStatelessReject()) { - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - CloseConnection(QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, _, _)); - // If this is a stateless reject, the crypto stream will close the - // connection. - session1_->connection()->CloseConnection( - QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, "stateless reject", - ConnectionCloseBehavior::SILENT_CLOSE); - } - - // Send a second packet and check the results. If this is a stateless reject, - // the existing connection_id will go on the time-wait list. - EXPECT_EQ(ExpectStatelessReject(), - time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); - if (ExpectStatelessReject()) { - // The second packet will be processed on the time-wait list. - EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, connection_id)) - .Times(1); - } else { - // The second packet will trigger a packet-validation - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .Times(1) - .WillOnce(WithArg<2>( - Invoke([this, connection_id](const QuicEncryptedPacket& packet) { - ValidatePacket(connection_id, packet); - }))); - } - ProcessPacket(client_address, connection_id, true, "data"); -} - -TEST_P(QuicDispatcherStatelessRejectTest, CheapRejects) { - SetQuicReloadableFlag(quic_use_cheap_stateless_rejects, true); - CreateTimeWaitListManager(); - - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - QuicConnectionId connection_id = 1; - if (GetParam().enable_stateless_rejects_via_flag) { - EXPECT_CALL(*dispatcher_, - CreateQuicSession(connection_id, client_address, _)) - .Times(0); - } else { - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address, - QuicStringPiece("h2"))) - .WillOnce(testing::Return( - CreateSessionBasedOnTestParams(connection_id, client_address))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) { - ValidatePacket(1, packet); - }))); - } - - QUIC_LOG(INFO) << "ExpectStatelessReject: " << ExpectStatelessReject(); - QUIC_LOG(INFO) << "Params: " << GetParam(); - // Process the first packet for the connection. - CryptoHandshakeMessage client_hello = - crypto_test_utils::CreateCHLO({{"AEAD", "AESG"}, - {"KEXS", "C255"}, - {"COPT", "SREJ"}, - {"NONC", "1234567890123456789012"}, - {"ALPN", "h2"}, - {"VER\0", "Q025"}}, - kClientHelloMinimumSize); - - if (GetParam().enable_stateless_rejects_via_flag) { - EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, connection_id)) - .Times(1); - } else { - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection(connection_id)) - .Times(1); - } - ProcessPacket( - client_address, connection_id, true, - string( - client_hello.GetSerialized(Perspective::IS_CLIENT).AsStringPiece())); - - if (GetParam().enable_stateless_rejects_via_flag) { - EXPECT_EQ(true, - time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); - } -} - -TEST_P(QuicDispatcherStatelessRejectTest, BufferNonChlo) { - SetQuicReloadableFlag(quic_use_cheap_stateless_rejects, true); - CreateTimeWaitListManager(); - - const QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - const QuicConnectionId connection_id = 1; - - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection(connection_id)) - .Times(1); - ProcessPacket(client_address, connection_id, true, "NOT DATA FOR A CHLO"); - - // Process the first packet for the connection. - CryptoHandshakeMessage client_hello = - crypto_test_utils::CreateCHLO({{"AEAD", "AESG"}, - {"KEXS", "C255"}, - {"NONC", "1234567890123456789012"}, - {"ALPN", "h3"}, - {"VER\0", "Q025"}}, - kClientHelloMinimumSize); - - // If stateless rejects are enabled then a connection will be created now - // and the buffered packet will be processed - EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address, - QuicStringPiece("h3"))) - .WillOnce(testing::Return( - CreateSessionBasedOnTestParams(connection_id, client_address))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, client_address, _)) - .WillOnce(WithArg<2>( - Invoke([this, connection_id](const QuicEncryptedPacket& packet) { - ValidatePacket(connection_id, packet); - }))); - // Expect both packets to be passed to ProcessUdpPacket(). And one of them - // is already expected in CreateSessionBasedOnTestParams(). - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, client_address, _)) - .WillOnce(WithArg<2>( - Invoke([this, connection_id](const QuicEncryptedPacket& packet) { - ValidatePacket(connection_id, packet); - }))) - .RetiresOnSaturation(); - ProcessPacket( - client_address, connection_id, true, - string( - client_hello.GetSerialized(Perspective::IS_CLIENT).AsStringPiece())); - EXPECT_FALSE( - time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); -} - -// Verify the stopgap test: Packets with truncated connection IDs should be -// dropped. -class QuicDispatcherTestStrayPacketConnectionId : public QuicDispatcherTest {}; - -// Packets with truncated connection IDs should be dropped. -TEST_F(QuicDispatcherTestStrayPacketConnectionId, - StrayPacketTruncatedConnectionId) { - CreateTimeWaitListManager(); - - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - QuicConnectionId connection_id = 1; - // Dispatcher drops this packet. - EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, QuicStringPiece("hq"))) - .Times(0); - EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, connection_id)) - .Times(0); - EXPECT_CALL(*time_wait_list_manager_, - AddConnectionIdToTimeWait(_, _, _, _, _)) - .Times(0); - ProcessPacket(client_address, connection_id, true, "data", - PACKET_0BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER); -} - -class BlockingWriter : public QuicPacketWriterWrapper { - public: - BlockingWriter() : write_blocked_(false) {} - - bool IsWriteBlocked() const override { return write_blocked_; } - void SetWritable() override { write_blocked_ = false; } - - WriteResult WritePacket(const char* buffer, - size_t buf_len, - const QuicIpAddress& self_client_address, - const QuicSocketAddress& peer_client_address, - PerPacketOptions* options) override { - // It would be quite possible to actually implement this method here with - // the fake blocked status, but it would be significantly more work in - // Chromium, and since it's not called anyway, don't bother. - QUIC_LOG(DFATAL) << "Not supported"; - return WriteResult(); - } - - bool write_blocked_; -}; - -class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest { - public: - void SetUp() override { - QuicDispatcherTest::SetUp(); - writer_ = new BlockingWriter; - QuicDispatcherPeer::UseWriter(dispatcher_.get(), writer_); - - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - - EXPECT_CALL(*dispatcher_, - CreateQuicSession(_, client_address, QuicStringPiece("hq"))) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, 1, client_address, &helper_, - &alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) { - ValidatePacket(1, packet); - }))); - EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(1)); - ProcessPacket(client_address, 1, true, SerializeCHLO()); - - EXPECT_CALL(*dispatcher_, - CreateQuicSession(_, client_address, QuicStringPiece("hq"))) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, 2, client_address, &helper_, - &alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) { - ValidatePacket(2, packet); - }))); - EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(2)); - ProcessPacket(client_address, 2, true, SerializeCHLO()); - - blocked_list_ = QuicDispatcherPeer::GetWriteBlockedList(dispatcher_.get()); - } - - void TearDown() override { - EXPECT_CALL(*connection1(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _)); - EXPECT_CALL(*connection2(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _)); - dispatcher_->Shutdown(); - } - - void SetBlocked() { writer_->write_blocked_ = true; } - - void BlockConnection2() { - writer_->write_blocked_ = true; - dispatcher_->OnWriteBlocked(connection2()); - } - - protected: - MockQuicConnectionHelper helper_; - MockAlarmFactory alarm_factory_; - BlockingWriter* writer_; - QuicDispatcher::WriteBlockedList* blocked_list_; -}; - -TEST_F(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) { - // No OnCanWrite calls because no connections are blocked. - dispatcher_->OnCanWrite(); - - // Register connection 1 for events, and make sure it's notified. - SetBlocked(); - dispatcher_->OnWriteBlocked(connection1()); - EXPECT_CALL(*connection1(), OnCanWrite()); - dispatcher_->OnCanWrite(); - - // It should get only one notification. - EXPECT_CALL(*connection1(), OnCanWrite()).Times(0); - dispatcher_->OnCanWrite(); - EXPECT_FALSE(dispatcher_->HasPendingWrites()); -} - -TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) { - // Make sure we handle events in order. - InSequence s; - SetBlocked(); - dispatcher_->OnWriteBlocked(connection1()); - dispatcher_->OnWriteBlocked(connection2()); - EXPECT_CALL(*connection1(), OnCanWrite()); - EXPECT_CALL(*connection2(), OnCanWrite()); - dispatcher_->OnCanWrite(); - - // Check the other ordering. - SetBlocked(); - dispatcher_->OnWriteBlocked(connection2()); - dispatcher_->OnWriteBlocked(connection1()); - EXPECT_CALL(*connection2(), OnCanWrite()); - EXPECT_CALL(*connection1(), OnCanWrite()); - dispatcher_->OnCanWrite(); -} - -TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) { - // Add and remove one connction. - SetBlocked(); - dispatcher_->OnWriteBlocked(connection1()); - blocked_list_->erase(connection1()); - EXPECT_CALL(*connection1(), OnCanWrite()).Times(0); - dispatcher_->OnCanWrite(); - - // Add and remove one connction and make sure it doesn't affect others. - SetBlocked(); - dispatcher_->OnWriteBlocked(connection1()); - dispatcher_->OnWriteBlocked(connection2()); - blocked_list_->erase(connection1()); - EXPECT_CALL(*connection2(), OnCanWrite()); - dispatcher_->OnCanWrite(); - - // Add it, remove it, and add it back and make sure things are OK. - SetBlocked(); - dispatcher_->OnWriteBlocked(connection1()); - blocked_list_->erase(connection1()); - dispatcher_->OnWriteBlocked(connection1()); - EXPECT_CALL(*connection1(), OnCanWrite()).Times(1); - dispatcher_->OnCanWrite(); -} - -TEST_F(QuicDispatcherWriteBlockedListTest, DoubleAdd) { - // Make sure a double add does not necessitate a double remove. - SetBlocked(); - dispatcher_->OnWriteBlocked(connection1()); - dispatcher_->OnWriteBlocked(connection1()); - blocked_list_->erase(connection1()); - EXPECT_CALL(*connection1(), OnCanWrite()).Times(0); - dispatcher_->OnCanWrite(); - - // Make sure a double add does not result in two OnCanWrite calls. - SetBlocked(); - dispatcher_->OnWriteBlocked(connection1()); - dispatcher_->OnWriteBlocked(connection1()); - EXPECT_CALL(*connection1(), OnCanWrite()).Times(1); - dispatcher_->OnCanWrite(); -} - -TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlock) { - // Finally make sure if we write block on a write call, we stop calling. - InSequence s; - SetBlocked(); - dispatcher_->OnWriteBlocked(connection1()); - dispatcher_->OnWriteBlocked(connection2()); - EXPECT_CALL(*connection1(), OnCanWrite()) - .WillOnce(Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked)); - EXPECT_CALL(*connection2(), OnCanWrite()).Times(0); - dispatcher_->OnCanWrite(); - - // And we'll resume where we left off when we get another call. - EXPECT_CALL(*connection2(), OnCanWrite()); - dispatcher_->OnCanWrite(); -} - -TEST_F(QuicDispatcherWriteBlockedListTest, LimitedWrites) { - // Make sure we call both writers. The first will register for more writing - // but should not be immediately called due to limits. - InSequence s; - SetBlocked(); - dispatcher_->OnWriteBlocked(connection1()); - dispatcher_->OnWriteBlocked(connection2()); - EXPECT_CALL(*connection1(), OnCanWrite()); - EXPECT_CALL(*connection2(), OnCanWrite()) - .WillOnce( - Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2)); - dispatcher_->OnCanWrite(); - EXPECT_TRUE(dispatcher_->HasPendingWrites()); - - // Now call OnCanWrite again, and connection1 should get its second chance - EXPECT_CALL(*connection2(), OnCanWrite()); - dispatcher_->OnCanWrite(); - EXPECT_FALSE(dispatcher_->HasPendingWrites()); -} - -TEST_F(QuicDispatcherWriteBlockedListTest, TestWriteLimits) { - // Finally make sure if we write block on a write call, we stop calling. - InSequence s; - SetBlocked(); - dispatcher_->OnWriteBlocked(connection1()); - dispatcher_->OnWriteBlocked(connection2()); - EXPECT_CALL(*connection1(), OnCanWrite()) - .WillOnce(Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked)); - EXPECT_CALL(*connection2(), OnCanWrite()).Times(0); - dispatcher_->OnCanWrite(); - EXPECT_TRUE(dispatcher_->HasPendingWrites()); - - // And we'll resume where we left off when we get another call. - EXPECT_CALL(*connection2(), OnCanWrite()); - dispatcher_->OnCanWrite(); - EXPECT_FALSE(dispatcher_->HasPendingWrites()); -} - -// Tests that bufferring packets works in stateful reject, expensive stateless -// reject and cheap stateless reject. -struct BufferedPacketStoreTestParams { - BufferedPacketStoreTestParams(bool enable_stateless_rejects_via_flag, - bool support_cheap_stateless_reject) - : enable_stateless_rejects_via_flag(enable_stateless_rejects_via_flag), - support_cheap_stateless_reject(support_cheap_stateless_reject) {} - - friend std::ostream& operator<<(std::ostream& os, - const BufferedPacketStoreTestParams& p) { - os << "{ enable_stateless_rejects_via_flag: " - << p.enable_stateless_rejects_via_flag << std::endl; - os << " support_cheap_stateless_reject: " - << p.support_cheap_stateless_reject << " }"; - return os; - } - - // This only enables the stateless reject feature via the feature-flag. - // This should be a no-op if the peer does not support them. - bool enable_stateless_rejects_via_flag; - // Whether to do cheap stateless or not. - bool support_cheap_stateless_reject; -}; - -std::vector<BufferedPacketStoreTestParams> GetBufferedPacketStoreTestParams() { - std::vector<BufferedPacketStoreTestParams> params; - for (bool enable_stateless_rejects_via_flag : {true, false}) { - for (bool support_cheap_stateless_reject : {true, false}) { - params.push_back(BufferedPacketStoreTestParams( - enable_stateless_rejects_via_flag, support_cheap_stateless_reject)); - } - } - return params; -} - -// A dispatcher whose stateless rejector will always ACCEPTs CHLO. -class BufferedPacketStoreTest - : public QuicDispatcherTest, - public testing::WithParamInterface<BufferedPacketStoreTestParams> { - public: - BufferedPacketStoreTest() - : QuicDispatcherTest(), - client_addr_(QuicIpAddress::Loopback4(), 1234), - signed_config_(new QuicSignedServerConfig) { - SetQuicReloadableFlag(quic_use_cheap_stateless_rejects, - GetParam().support_cheap_stateless_reject); - SetQuicReloadableFlag(enable_quic_stateless_reject_support, - GetParam().enable_stateless_rejects_via_flag); - } - - void SetUp() override { - QuicDispatcherTest::SetUp(); - clock_ = QuicDispatcherPeer::GetHelper(dispatcher_.get())->GetClock(); - - QuicTransportVersion version = AllSupportedTransportVersions().front(); - CryptoHandshakeMessage chlo = - crypto_test_utils::GenerateDefaultInchoateCHLO(clock_, version, - &crypto_config_); - chlo.SetVector(net::kCOPT, net::QuicTagVector{net::kSREJ}); - // Pass an inchoate CHLO. - crypto_test_utils::GenerateFullCHLO( - chlo, &crypto_config_, server_addr_, client_addr_, version, clock_, - signed_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()), - &full_chlo_); - } - - QuicString SerializeFullCHLO() { - return string( - full_chlo_.GetSerialized(Perspective::IS_CLIENT).AsStringPiece()); - } - - protected: - QuicSocketAddress server_addr_; - QuicSocketAddress client_addr_; - QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_; - const QuicClock* clock_; - CryptoHandshakeMessage full_chlo_; -}; - -INSTANTIATE_TEST_CASE_P( - BufferedPacketStoreTests, - BufferedPacketStoreTest, - ::testing::ValuesIn(GetBufferedPacketStoreTestParams())); - -TEST_P(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) { - InSequence s; - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5); - QuicConnectionId conn_id = 1; - // A bunch of non-CHLO should be buffered upon arrival, and the first one - // should trigger ShouldCreateOrBufferPacketForConnection(). - EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id)) - .Times(1); - for (size_t i = 1; i <= kDefaultMaxUndecryptablePackets + 1; ++i) { - ProcessPacket(client_address, conn_id, true, - QuicStrCat("data packet ", i + 1), PACKET_8BYTE_CONNECTION_ID, - PACKET_4BYTE_PACKET_NUMBER, /*packet_number=*/i + 1); - } - EXPECT_EQ(0u, dispatcher_->session_map().size()) - << "No session should be created before CHLO arrives."; - - // Pop out the last packet as it is also be dropped by the store. - data_connection_map_[conn_id].pop_back(); - // When CHLO arrives, a new session should be created, and all packets - // buffered should be delivered to the session. - EXPECT_CALL(*dispatcher_, - CreateQuicSession(conn_id, client_address, QuicStringPiece())) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, conn_id, client_address, &mock_helper_, - &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - - // Only |kDefaultMaxUndecryptablePackets| packets were buffered, and they - // should be delivered in arrival order. - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .Times(kDefaultMaxUndecryptablePackets + 1) // + 1 for CHLO. - .WillOnce( - WithArg<2>(Invoke([this, conn_id](const QuicEncryptedPacket& packet) { - ValidatePacket(conn_id, packet); - }))); - ProcessPacket(client_address, conn_id, true, SerializeFullCHLO()); -} - -TEST_P(BufferedPacketStoreTest, - ProcessNonChloPacketsForDifferentConnectionsUptoLimit) { - InSequence s; - server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5); - // A bunch of non-CHLO should be buffered upon arrival. - size_t kNumConnections = kMaxConnectionsWithoutCHLO + 1; - for (size_t i = 1; i <= kNumConnections; ++i) { - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), i); - QuicConnectionId conn_id = i; - EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id)); - ProcessPacket(client_address, conn_id, true, - QuicStrCat("data packet on connection ", i), - PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, - /*packet_number=*/2); - } - - // Pop out the packet on last connection as it shouldn't be enqueued in store - // as well. - data_connection_map_[kNumConnections].pop_front(); - - // Reset session creation counter to ensure processing CHLO can always - // create session. - QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(dispatcher_.get(), - kNumConnections); - // Process CHLOs to create session for these connections. - for (size_t i = 1; i <= kNumConnections; ++i) { - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), i); - QuicConnectionId conn_id = i; - if (conn_id == kNumConnections) { - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection(conn_id)); - } - EXPECT_CALL(*dispatcher_, - CreateQuicSession(conn_id, client_address, QuicStringPiece())) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, conn_id, client_address, &mock_helper_, - &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - // First |kNumConnections| - 1 connections should have buffered - // a packet in store. The rest should have been dropped. - size_t num_packet_to_process = i <= kMaxConnectionsWithoutCHLO ? 2u : 1u; - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, client_address, _)) - .Times(num_packet_to_process) - .WillOnce(WithArg<2>( - Invoke([this, conn_id](const QuicEncryptedPacket& packet) { - ValidatePacket(conn_id, packet); - }))); - - ProcessPacket(client_address, conn_id, true, SerializeFullCHLO()); - } -} - -// Tests that store delivers empty packet list if CHLO arrives firstly. -TEST_P(BufferedPacketStoreTest, DeliverEmptyPackets) { - QuicConnectionId conn_id = 1; - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id)); - EXPECT_CALL(*dispatcher_, - CreateQuicSession(conn_id, client_address, QuicStringPiece())) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, conn_id, client_address, &mock_helper_, - &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - ProcessPacket(client_address, conn_id, true, SerializeFullCHLO()); -} - -// Tests that a retransmitted CHLO arrives after a connection for the -// CHLO has been created. -TEST_P(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) { - InSequence s; - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5); - QuicConnectionId conn_id = 1; - ProcessPacket(client_address, conn_id, true, QuicStrCat("data packet ", 2), - PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, - /*packet_number=*/2); - - // When CHLO arrives, a new session should be created, and all packets - // buffered should be delivered to the session. - EXPECT_CALL(*dispatcher_, - CreateQuicSession(conn_id, client_address, QuicStringPiece())) - .Times(1) // Only triggered by 1st CHLO. - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, conn_id, client_address, &mock_helper_, - &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .Times(3) // Triggered by 1 data packet and 2 CHLOs. - .WillOnce( - WithArg<2>(Invoke([this, conn_id](const QuicEncryptedPacket& packet) { - ValidatePacket(conn_id, packet); - }))); - ProcessPacket(client_address, conn_id, true, SerializeFullCHLO()); - - ProcessPacket(client_address, conn_id, true, SerializeFullCHLO()); -} - -// Tests that expiration of a connection add connection id to time wait list. -TEST_P(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) { - InSequence s; - CreateTimeWaitListManager(); - QuicBufferedPacketStore* store = - QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get()); - QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock()); - - QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1); - server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5); - QuicConnectionId conn_id = 1; - ProcessPacket(client_address, conn_id, true, QuicStrCat("data packet ", 2), - PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, - /*packet_number=*/2); - - mock_helper_.AdvanceTime( - QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs)); - QuicAlarm* alarm = QuicBufferedPacketStorePeer::expiration_alarm(store); - // Cancel alarm as if it had been fired. - alarm->Cancel(); - store->OnExpirationTimeout(); - // New arrived CHLO will be dropped because this connection is in time wait - // list. - ASSERT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id)); - EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, conn_id)); - ProcessPacket(client_address, conn_id, true, SerializeFullCHLO()); -} - -TEST_P(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) { - // Process more than (|kMaxNumSessionsToCreate| + - // |kDefaultMaxConnectionsInStore|) CHLOs, - // the first |kMaxNumSessionsToCreate| should create connections immediately, - // the next |kDefaultMaxConnectionsInStore| should be buffered, - // the rest should be dropped. - QuicBufferedPacketStore* store = - QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get()); - const size_t kNumCHLOs = - kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore + 1; - for (size_t conn_id = 1; conn_id <= kNumCHLOs; ++conn_id) { - EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id)); - if (conn_id <= kMaxNumSessionsToCreate) { - EXPECT_CALL(*dispatcher_, - CreateQuicSession(conn_id, client_addr_, QuicStringPiece())) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, conn_id, client_addr_, &mock_helper_, - &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL( - *reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, conn_id](const QuicEncryptedPacket& packet) { - ValidatePacket(conn_id, packet); - }))); - } - ProcessPacket(client_addr_, conn_id, true, SerializeFullCHLO()); - if (conn_id <= kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore && - conn_id > kMaxNumSessionsToCreate) { - EXPECT_TRUE(store->HasChloForConnection(conn_id)); - } else { - // First |kMaxNumSessionsToCreate| CHLOs should be passed to new - // connections immediately, and the last CHLO should be dropped as the - // store is full. - EXPECT_FALSE(store->HasChloForConnection(conn_id)); - } - } - - // Graduately consume buffered CHLOs. The buffered connections should be - // created but the dropped one shouldn't. - for (size_t conn_id = kMaxNumSessionsToCreate + 1; - conn_id <= kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore; - ++conn_id) { - EXPECT_CALL(*dispatcher_, - CreateQuicSession(conn_id, client_addr_, QuicStringPiece())) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, conn_id, client_addr_, &mock_helper_, - &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, conn_id](const QuicEncryptedPacket& packet) { - ValidatePacket(conn_id, packet); - }))); - } - EXPECT_CALL(*dispatcher_, - CreateQuicSession(kNumCHLOs, client_addr_, QuicStringPiece())) - .Times(0); - - while (store->HasChlosBuffered()) { - dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate); - } - - EXPECT_EQ(static_cast<size_t>(kMaxNumSessionsToCreate) + - kDefaultMaxConnectionsInStore, - session1_->connection_id()); -} - -// Duplicated CHLO shouldn't be buffered. -TEST_P(BufferedPacketStoreTest, BufferDuplicatedCHLO) { - for (QuicConnectionId conn_id = 1; conn_id <= kMaxNumSessionsToCreate + 1; - ++conn_id) { - // Last CHLO will be buffered. Others will create connection right away. - if (conn_id <= kMaxNumSessionsToCreate) { - EXPECT_CALL(*dispatcher_, - CreateQuicSession(conn_id, client_addr_, QuicStringPiece())) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, conn_id, client_addr_, &mock_helper_, - &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL( - *reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, conn_id](const QuicEncryptedPacket& packet) { - ValidatePacket(conn_id, packet); - }))); - } - ProcessPacket(client_addr_, conn_id, true, SerializeFullCHLO()); - } - // Retransmit CHLO on last connection should be dropped. - QuicConnectionId last_connection = kMaxNumSessionsToCreate + 1; - ProcessPacket(client_addr_, last_connection, true, SerializeFullCHLO()); - - size_t packets_buffered = 2; - - // Reset counter and process buffered CHLO. - EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection, client_addr_, - QuicStringPiece())) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, last_connection, client_addr_, - &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - // Only one packet(CHLO) should be process. - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .Times(packets_buffered) - .WillOnce(WithArg<2>( - Invoke([this, last_connection](const QuicEncryptedPacket& packet) { - ValidatePacket(last_connection, packet); - }))); - dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate); -} - -TEST_P(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) { - QuicConnectionId last_connection_id = kMaxNumSessionsToCreate + 1; - for (QuicConnectionId conn_id = 1; conn_id <= last_connection_id; ++conn_id) { - // Last CHLO will be buffered. Others will create connection right away. - if (conn_id <= kMaxNumSessionsToCreate) { - EXPECT_CALL(*dispatcher_, - CreateQuicSession(conn_id, client_addr_, QuicStringPiece())) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, conn_id, client_addr_, &mock_helper_, - &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL( - *reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, conn_id](const QuicEncryptedPacket& packet) { - ValidatePacket(conn_id, packet); - }))); - } - ProcessPacket(client_addr_, conn_id, true, SerializeFullCHLO()); - } - - // Process another |kDefaultMaxUndecryptablePackets| + 1 data packets. The - // last one should be dropped. - for (QuicPacketNumber packet_number = 2; - packet_number <= kDefaultMaxUndecryptablePackets + 2; ++packet_number) { - ProcessPacket(client_addr_, last_connection_id, true, "data packet"); - } - - // Reset counter and process buffered CHLO. - EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection_id, client_addr_, - QuicStringPiece())) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, last_connection_id, client_addr_, - &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - // Only CHLO and following |kDefaultMaxUndecryptablePackets| data packets - // should be process. - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .Times(kDefaultMaxUndecryptablePackets + 1) - .WillOnce(WithArg<2>( - Invoke([this, last_connection_id](const QuicEncryptedPacket& packet) { - ValidatePacket(last_connection_id, packet); - }))); - dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate); -} - -// Tests that when dispatcher's packet buffer is full, a CHLO on connection -// which doesn't have buffered CHLO should be buffered. -TEST_P(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) { - QuicBufferedPacketStore* store = - QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get()); - - QuicConnectionId conn_id = 1; - ProcessPacket(client_addr_, conn_id, true, "data packet", - PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, - /*packet_number=*/1); - // Fill packet buffer to full with CHLOs on other connections. Need to feed - // extra CHLOs because the first |kMaxNumSessionsToCreate| are going to create - // session directly. - for (conn_id = 2; - conn_id <= kDefaultMaxConnectionsInStore + kMaxNumSessionsToCreate; - ++conn_id) { - if (conn_id <= kMaxNumSessionsToCreate + 1) { - EXPECT_CALL(*dispatcher_, - CreateQuicSession(conn_id, client_addr_, QuicStringPiece())) - .WillOnce(testing::Return(CreateSession( - dispatcher_.get(), config_, conn_id, client_addr_, &mock_helper_, - &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); - EXPECT_CALL( - *reinterpret_cast<MockQuicConnection*>(session1_->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, conn_id](const QuicEncryptedPacket& packet) { - ValidatePacket(conn_id, packet); - }))); - } - ProcessPacket(client_addr_, conn_id, true, SerializeFullCHLO()); - } - EXPECT_FALSE(store->HasChloForConnection(/*connection_id=*/1)); - - // CHLO on connection 1 should still be buffered. - ProcessPacket(client_addr_, /*connection_id=*/1, true, SerializeFullCHLO()); - EXPECT_TRUE(store->HasChloForConnection(/*connection_id=*/1)); -} - -// Test which exercises the async GetProof codepaths, especially in the context -// of stateless rejection. -class AsyncGetProofTest : public QuicDispatcherTest { - public: - AsyncGetProofTest() - : QuicDispatcherTest( - std::unique_ptr<FakeProofSource>(new FakeProofSource())), - client_addr_(QuicIpAddress::Loopback4(), 1234), - client_addr_2_(QuicIpAddress::Loopback4(), 1357), - crypto_config_peer_(&crypto_config_), - signed_config_(new QuicSignedServerConfig) { - SetQuicReloadableFlag(enable_quic_stateless_reject_support, true); - SetQuicReloadableFlag(quic_use_cheap_stateless_rejects, true); - } - - void SetUp() override { - QuicDispatcherTest::SetUp(); - - clock_ = QuicDispatcherPeer::GetHelper(dispatcher_.get())->GetClock(); - QuicTransportVersion version = AllSupportedTransportVersions().front(); - chlo_ = crypto_test_utils::GenerateDefaultInchoateCHLO(clock_, version, - &crypto_config_); - chlo_.SetVector(net::kCOPT, net::QuicTagVector{net::kSREJ}); - chlo_.SetStringPiece(kALPN, "HTTP/1"); - // Pass an inchoate CHLO. - crypto_test_utils::GenerateFullCHLO( - chlo_, &crypto_config_, server_addr_, client_addr_, version, clock_, - signed_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()), - &full_chlo_); - - crypto_test_utils::GenerateFullCHLO( - chlo_, &crypto_config_, server_addr_, client_addr_2_, version, clock_, - signed_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()), - &full_chlo_2_); - - GetFakeProofSource()->Activate(); - } - - FakeProofSource* GetFakeProofSource() const { - return static_cast<FakeProofSource*>(crypto_config_peer_.GetProofSource()); - } - - QuicString SerializeFullCHLO() { - return QuicString( - full_chlo_.GetSerialized(Perspective::IS_CLIENT).AsStringPiece()); - } - - QuicString SerializeFullCHLOForClient2() { - return QuicString( - full_chlo_2_.GetSerialized(Perspective::IS_CLIENT).AsStringPiece()); - } - - QuicString SerializeCHLO() { - return string(chlo_.GetSerialized(Perspective::IS_CLIENT).AsStringPiece()); - } - - // Sets up a session, and crypto stream based on the test parameters. - QuicServerSessionBase* GetSession(QuicConnectionId connection_id, - QuicSocketAddress client_address) { - auto it = sessions_.find(connection_id); - if (it != sessions_.end()) { - return it->second.session; - } - - TestQuicSpdyServerSession* session; - CreateSession(dispatcher_.get(), config_, connection_id, client_address, - &mock_helper_, &mock_alarm_factory_, &crypto_config_, - QuicDispatcherPeer::GetCache(dispatcher_.get()), &session); - - std::unique_ptr<MockQuicCryptoServerStream> crypto_stream( - new MockQuicCryptoServerStream( - crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()), - session, session->stream_helper())); - session->SetCryptoStream(crypto_stream.get()); - crypto_stream->SetPeerSupportsStatelessRejects(true); - const bool ok = - sessions_ - .insert(std::make_pair( - connection_id, SessionInfo{session, std::move(crypto_stream)})) - .second; - CHECK(ok); - return session; - } - - protected: - const QuicSocketAddress client_addr_; - const QuicSocketAddress client_addr_2_; - - private: - QuicCryptoServerConfigPeer crypto_config_peer_; - QuicSocketAddress server_addr_; - QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_; - const QuicClock* clock_; - CryptoHandshakeMessage chlo_; - CryptoHandshakeMessage full_chlo_; // CHLO for client_addr_ - CryptoHandshakeMessage full_chlo_2_; // CHLO for client_addr_2_ - - struct SessionInfo { - TestQuicSpdyServerSession* session; - std::unique_ptr<MockQuicCryptoServerStream> crypto_stream; - }; - std::map<QuicConnectionId, SessionInfo> sessions_; -}; - -// Test a simple situation of connections which the StatelessRejector will -// accept. -TEST_F(AsyncGetProofTest, BasicAccept) { - QuicConnectionId conn_id = 1; - - testing::MockFunction<void(int check_point)> check; - { - InSequence s; - - EXPECT_CALL(check, Call(1)); - EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id)); - EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_addr_, - QuicStringPiece("HTTP/1"))) - .WillOnce(testing::Return(GetSession(conn_id, client_addr_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>( - GetSession(conn_id, client_addr_)->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, conn_id](const QuicEncryptedPacket& packet) { - ValidatePacket(conn_id, packet); - }))); - - EXPECT_CALL(check, Call(2)); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>( - GetSession(conn_id, client_addr_)->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, conn_id](const QuicEncryptedPacket& packet) { - ValidatePacket(conn_id, packet); - }))); - } - - // Send a CHLO that the StatelessRejector will accept. - ProcessPacket(client_addr_, conn_id, true, SerializeFullCHLO()); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); - - check.Call(1); - // Complete the ProofSource::GetProof call and verify that a session is - // created. - GetFakeProofSource()->InvokePendingCallback(0); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0); - - check.Call(2); - // Verify that a data packet gets processed immediately. - ProcessPacket(client_addr_, conn_id, true, "My name is Data"); -} - -TEST_F(AsyncGetProofTest, RestorePacketContext) { - QuicConnectionId conn_id_1 = 1; - QuicConnectionId conn_id_2 = 2; - - testing::MockFunction<void(int check_point)> check; - { - InSequence s; - EXPECT_CALL(check, Call(1)); - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection(conn_id_1)); - - EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_1, client_addr_, - QuicStringPiece("HTTP/1"))) - .WillOnce(testing::Return(GetSession(conn_id_1, client_addr_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>( - GetSession(conn_id_1, client_addr_)->connection()), - ProcessUdpPacket(_, _, _)) - .WillRepeatedly(WithArg<2>( - Invoke([this, conn_id_1](const QuicEncryptedPacket& packet) { - ValidatePacket(conn_id_1, packet); - }))); - - EXPECT_CALL(check, Call(2)); - - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection(conn_id_2)); - EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_2, client_addr_2_, - QuicStringPiece("HTTP/1"))) - .WillOnce(testing::Return(GetSession(conn_id_2, client_addr_2_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>( - GetSession(conn_id_2, client_addr_2_)->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, conn_id_2](const QuicEncryptedPacket& packet) { - ValidatePacket(conn_id_2, packet); - }))); - } - - // Send a CHLO that the StatelessRejector will accept. - ProcessPacket(client_addr_, conn_id_1, true, SerializeFullCHLO()); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); - - // Send another CHLO that the StatelessRejector will accept. - ProcessPacket(client_addr_2_, conn_id_2, true, SerializeFullCHLOForClient2()); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2); - - // Complete the first ProofSource::GetProof call and verify that a session is - // created. - check.Call(1); - - EXPECT_EQ(client_addr_2_, dispatcher_->current_client_address()); - EXPECT_EQ(client_addr_2_, dispatcher_->current_peer_address()); - - // Runs the async proof callback for conn_id_1 from client_addr_. - GetFakeProofSource()->InvokePendingCallback(0); - - EXPECT_EQ(client_addr_, dispatcher_->current_client_address()); - EXPECT_EQ(client_addr_, dispatcher_->current_peer_address()); - - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); - - // Complete the second ProofSource::GetProof call and verify that a session is - // created. - check.Call(2); - - EXPECT_EQ(client_addr_, dispatcher_->current_client_address()); - EXPECT_EQ(client_addr_, dispatcher_->current_peer_address()); - - // Runs the async proof callback for conn_id_2 from client_addr_2_. - GetFakeProofSource()->InvokePendingCallback(0); - - EXPECT_EQ(client_addr_2_, dispatcher_->current_client_address()); - EXPECT_EQ(client_addr_2_, dispatcher_->current_peer_address()); - - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0); -} - -// Test a simple situation of connections which the StatelessRejector will -// reject. -TEST_F(AsyncGetProofTest, BasicReject) { - CreateTimeWaitListManager(); - - QuicConnectionId conn_id = 1; - - testing::MockFunction<void(int check_point)> check; - { - InSequence s; - EXPECT_CALL(check, Call(1)); - EXPECT_CALL(*time_wait_list_manager_, - AddConnectionIdToTimeWait(conn_id, _, _, true, _)); - EXPECT_CALL(*time_wait_list_manager_, - ProcessPacket(_, client_addr_, conn_id)); - - EXPECT_CALL(check, Call(2)); - EXPECT_CALL(*dispatcher_, - CreateQuicSession(conn_id, client_addr_, QuicStringPiece("hq"))) - .Times(0); - EXPECT_CALL(*time_wait_list_manager_, - ProcessPacket(_, client_addr_, conn_id)); - } - - // Send a CHLO that the StatelessRejector will reject. - ProcessPacket(client_addr_, conn_id, true, SerializeCHLO()); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); - - // Complete the ProofSource::GetProof call and verify that the connection and - // packet are processed by the time wait list manager. - check.Call(1); - GetFakeProofSource()->InvokePendingCallback(0); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0); - - // Verify that a data packet is passed to the time wait list manager. - check.Call(2); - ProcessPacket(client_addr_, conn_id, true, "My name is Data"); -} - -// Test a situation with multiple interleaved connections which the -// StatelessRejector will accept. -TEST_F(AsyncGetProofTest, MultipleAccept) { - QuicConnectionId conn_id_1 = 1; - QuicConnectionId conn_id_2 = 2; - QuicBufferedPacketStore* store = - QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get()); - - testing::MockFunction<void(int check_point)> check; - { - InSequence s; - EXPECT_CALL(check, Call(1)); - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection(conn_id_2)); - EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_2, client_addr_, - QuicStringPiece("HTTP/1"))) - .WillOnce(testing::Return(GetSession(conn_id_2, client_addr_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>( - GetSession(conn_id_2, client_addr_)->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, conn_id_2](const QuicEncryptedPacket& packet) { - ValidatePacket(conn_id_2, packet); - }))); - - EXPECT_CALL(check, Call(2)); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>( - GetSession(conn_id_2, client_addr_)->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, conn_id_2](const QuicEncryptedPacket& packet) { - ValidatePacket(conn_id_2, packet); - }))); - - EXPECT_CALL(check, Call(3)); - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection(conn_id_1)); - - EXPECT_CALL(check, Call(4)); - EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_1, client_addr_, - QuicStringPiece("HTTP/1"))) - .WillOnce(testing::Return(GetSession(conn_id_1, client_addr_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>( - GetSession(conn_id_1, client_addr_)->connection()), - ProcessUdpPacket(_, _, _)) - .WillRepeatedly(WithArg<2>( - Invoke([this, conn_id_1](const QuicEncryptedPacket& packet) { - ValidatePacket(conn_id_1, packet); - }))); - } - - // Send a CHLO that the StatelessRejector will accept. - ProcessPacket(client_addr_, conn_id_1, true, SerializeFullCHLO()); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); - - // Send another CHLO that the StatelessRejector will accept. - ProcessPacket(client_addr_, conn_id_2, true, SerializeFullCHLO()); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2); - - // Complete the second ProofSource::GetProof call and verify that a session is - // created. - check.Call(1); - GetFakeProofSource()->InvokePendingCallback(1); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); - - // Verify that a data packet on that connection gets processed immediately. - check.Call(2); - ProcessPacket(client_addr_, conn_id_2, true, "My name is Data"); - - // Verify that a data packet on the other connection does not get processed - // yet. - check.Call(3); - ProcessPacket(client_addr_, conn_id_1, true, "My name is Data"); - EXPECT_TRUE(store->HasBufferedPackets(conn_id_1)); - EXPECT_FALSE(store->HasBufferedPackets(conn_id_2)); - - // Complete the first ProofSource::GetProof call and verify that a session is - // created and the buffered packet is processed. - check.Call(4); - GetFakeProofSource()->InvokePendingCallback(0); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0); -} - -// Test a situation with multiple interleaved connections which the -// StatelessRejector will reject. -TEST_F(AsyncGetProofTest, MultipleReject) { - CreateTimeWaitListManager(); - - QuicConnectionId conn_id_1 = 1; - QuicConnectionId conn_id_2 = 2; - QuicBufferedPacketStore* store = - QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get()); - - testing::MockFunction<void(int check_point)> check; - { - InSequence s; - - EXPECT_CALL(check, Call(1)); - EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_2, client_addr_, _)) - .Times(0); - EXPECT_CALL(*time_wait_list_manager_, - AddConnectionIdToTimeWait(conn_id_2, _, _, true, _)); - EXPECT_CALL(*time_wait_list_manager_, - ProcessPacket(_, client_addr_, conn_id_2)); - - EXPECT_CALL(check, Call(2)); - EXPECT_CALL(*time_wait_list_manager_, - ProcessPacket(_, client_addr_, conn_id_2)); - - EXPECT_CALL(check, Call(3)); - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection(conn_id_1)); - - EXPECT_CALL(check, Call(4)); - EXPECT_CALL(*time_wait_list_manager_, - AddConnectionIdToTimeWait(conn_id_1, _, _, true, _)); - EXPECT_CALL(*time_wait_list_manager_, - ProcessPacket(_, client_addr_, conn_id_1)); - } - - // Send a CHLO that the StatelessRejector will reject. - ProcessPacket(client_addr_, conn_id_1, true, SerializeCHLO()); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); - - // Send another CHLO that the StatelessRejector will reject. - ProcessPacket(client_addr_, conn_id_2, true, SerializeCHLO()); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2); - - // Complete the second ProofSource::GetProof call and verify that the - // connection and packet are processed by the time wait manager. - check.Call(1); - GetFakeProofSource()->InvokePendingCallback(1); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); - - // Verify that a data packet on that connection gets processed immediately by - // the time wait manager. - check.Call(2); - ProcessPacket(client_addr_, conn_id_2, true, "My name is Data"); - - // Verify that a data packet on the first connection gets buffered. - check.Call(3); - ProcessPacket(client_addr_, conn_id_1, true, "My name is Data"); - EXPECT_TRUE(store->HasBufferedPackets(conn_id_1)); - EXPECT_FALSE(store->HasBufferedPackets(conn_id_2)); - - // Complete the first ProofSource::GetProof call and verify that the CHLO is - // processed by the time wait manager and the remaining packets are discarded. - check.Call(4); - GetFakeProofSource()->InvokePendingCallback(0); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0); - EXPECT_FALSE(store->HasBufferedPackets(conn_id_1)); - EXPECT_FALSE(store->HasBufferedPackets(conn_id_2)); -} - -// Test a situation with multiple identical CHLOs which the StatelessRejector -// will reject. -TEST_F(AsyncGetProofTest, MultipleIdenticalReject) { - CreateTimeWaitListManager(); - - QuicConnectionId conn_id_1 = 1; - QuicBufferedPacketStore* store = - QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get()); - - testing::MockFunction<void(int check_point)> check; - { - InSequence s; - EXPECT_CALL(check, Call(1)); - EXPECT_CALL(*dispatcher_, - ShouldCreateOrBufferPacketForConnection(conn_id_1)); - - EXPECT_CALL(check, Call(2)); - EXPECT_CALL(*dispatcher_, - CreateQuicSession(conn_id_1, client_addr_, QuicStringPiece())) - .Times(0); - EXPECT_CALL(*time_wait_list_manager_, - AddConnectionIdToTimeWait(conn_id_1, _, _, true, _)); - EXPECT_CALL(*time_wait_list_manager_, - ProcessPacket(_, client_addr_, conn_id_1)); - } - - // Send a CHLO that the StatelessRejector will reject. - ProcessPacket(client_addr_, conn_id_1, true, SerializeCHLO()); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); - EXPECT_FALSE(store->HasBufferedPackets(conn_id_1)); - - // Send an identical CHLO which should get buffered. - check.Call(1); - ProcessPacket(client_addr_, conn_id_1, true, SerializeCHLO()); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); - EXPECT_TRUE(store->HasBufferedPackets(conn_id_1)); - - // Complete the ProofSource::GetProof call and verify that the CHLO is - // rejected and the copy is discarded. - check.Call(2); - GetFakeProofSource()->InvokePendingCallback(0); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0); - EXPECT_FALSE(store->HasBufferedPackets(conn_id_1)); -} - -// Test dispatcher behavior when packets time out of the buffer while CHLO -// validation is still pending. -TEST_F(AsyncGetProofTest, BufferTimeout) { - CreateTimeWaitListManager(); - - QuicConnectionId conn_id = 1; - QuicBufferedPacketStore* store = - QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get()); - QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock()); - - testing::MockFunction<void(int check_point)> check; - { - InSequence s; - EXPECT_CALL(check, Call(1)); - EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id)); - - EXPECT_CALL(check, Call(2)); - EXPECT_CALL(*time_wait_list_manager_, - ProcessPacket(_, client_addr_, conn_id)); - EXPECT_CALL(*dispatcher_, - CreateQuicSession(conn_id, client_addr_, QuicStringPiece())) - .Times(0); - } - - // Send a CHLO that the StatelessRejector will accept. - ProcessPacket(client_addr_, conn_id, true, SerializeFullCHLO()); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); - EXPECT_FALSE(store->HasBufferedPackets(conn_id)); - - // Send a data packet that will get buffered - check.Call(1); - ProcessPacket(client_addr_, conn_id, true, "My name is Data"); - EXPECT_TRUE(store->HasBufferedPackets(conn_id)); - - // Pretend that enough time has gone by for the packets to get expired out of - // the buffer - mock_helper_.AdvanceTime( - QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs)); - QuicBufferedPacketStorePeer::expiration_alarm(store)->Cancel(); - store->OnExpirationTimeout(); - EXPECT_FALSE(store->HasBufferedPackets(conn_id)); - EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id)); - - // Now allow the CHLO validation to complete, and verify that no connection - // gets created. - check.Call(2); - GetFakeProofSource()->InvokePendingCallback(0); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0); - EXPECT_FALSE(store->HasBufferedPackets(conn_id)); - EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id)); -} - -// Test behavior when packets time out of the buffer *and* the connection times -// out of the time wait manager while CHLO validation is still pending. This -// *should* be impossible, but anything can happen with timing conditions. -TEST_F(AsyncGetProofTest, TimeWaitTimeout) { - QuicConnectionId conn_id = 1; - QuicBufferedPacketStore* store = - QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get()); - QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock()); - CreateTimeWaitListManager(); - QuicTimeWaitListManagerPeer::set_clock(time_wait_list_manager_, - mock_helper_.GetClock()); - - testing::MockFunction<void(int check_point)> check; - { - InSequence s; - EXPECT_CALL(check, Call(1)); - EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id)); - - EXPECT_CALL(check, Call(2)); - EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id)); - EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_addr_, - QuicStringPiece("HTTP/1"))) - .WillOnce(testing::Return(GetSession(conn_id, client_addr_))); - EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>( - GetSession(conn_id, client_addr_)->connection()), - ProcessUdpPacket(_, _, _)) - .WillOnce(WithArg<2>( - Invoke([this, conn_id](const QuicEncryptedPacket& packet) { - ValidatePacket(conn_id, packet); - }))); - } - - // Send a CHLO that the StatelessRejector will accept. - ProcessPacket(client_addr_, conn_id, true, SerializeFullCHLO()); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); - EXPECT_FALSE(store->HasBufferedPackets(conn_id)); - - // Send a data packet that will get buffered - check.Call(1); - ProcessPacket(client_addr_, conn_id, true, "My name is Data"); - EXPECT_TRUE(store->HasBufferedPackets(conn_id)); - - // Pretend that enough time has gone by for the packets to get expired out of - // the buffer - mock_helper_.AdvanceTime( - QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs)); - QuicBufferedPacketStorePeer::expiration_alarm(store)->Cancel(); - store->OnExpirationTimeout(); - EXPECT_FALSE(store->HasBufferedPackets(conn_id)); - EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id)); - - // Pretend that enough time has gone by for the connection ID to be removed - // from the time wait manager - mock_helper_.AdvanceTime( - QuicTimeWaitListManagerPeer::time_wait_period(time_wait_list_manager_)); - QuicTimeWaitListManagerPeer::expiration_alarm(time_wait_list_manager_) - ->Cancel(); - time_wait_list_manager_->CleanUpOldConnectionIds(); - EXPECT_FALSE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id)); - - // Now allow the CHLO validation to complete. Expect that a connection is - // indeed created, since QUIC has forgotten that this connection ever existed. - // This is a miniscule corner case which should never happen in the wild, so - // really we are just verifying that the dispatcher does not explode in this - // situation. - check.Call(2); - GetFakeProofSource()->InvokePendingCallback(0); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0); - EXPECT_FALSE(store->HasBufferedPackets(conn_id)); - EXPECT_FALSE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id)); -} - -// Regression test for -// https://bugs.chromium.org/p/chromium/issues/detail?id=748289 -TEST_F(AsyncGetProofTest, DispatcherFailedToPickUpVersionForAsyncProof) { - // This test mimics the scenario that dispatcher's framer can have different - // version when async proof returns. - // When dispatcher sends SREJ, the SREJ frame can be serialized in - // different endianness which causes the client to close the connection - // because of QUIC_INVALID_STREAM_DATA. - - // Send a CHLO with v39. Dispatcher framer's version is set to v39. - ProcessPacket(client_addr_, 1, true, - ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39), - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, - PACKET_4BYTE_PACKET_NUMBER, 1); - - // Send another CHLO with v35. Dispatcher framer's version is set to v35. - ProcessPacket(client_addr_, 2, true, - ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_35), - SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, - PACKET_4BYTE_PACKET_NUMBER, 1); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2); - - // Complete the ProofSource::GetProof call for v39. This would cause the - // version mismatch between the CHLO packet and the dispatcher. - GetFakeProofSource()->InvokePendingCallback(0); - ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); -} - -} // namespace -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/quic_epoll_alarm_factory.cc b/chromium/net/tools/quic/quic_epoll_alarm_factory.cc deleted file mode 100644 index deb95597459..00000000000 --- a/chromium/net/tools/quic/quic_epoll_alarm_factory.cc +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_epoll_alarm_factory.h" - -#include "net/tools/epoll_server/epoll_server.h" - -namespace net { - -namespace { - -class QuicEpollAlarm : public QuicAlarm { - public: - QuicEpollAlarm(EpollServer* epoll_server, - QuicArenaScopedPtr<Delegate> delegate) - : QuicAlarm(std::move(delegate)), - epoll_server_(epoll_server), - epoll_alarm_impl_(this) {} - - protected: - void SetImpl() override { - DCHECK(deadline().IsInitialized()); - epoll_server_->RegisterAlarm( - (deadline() - QuicTime::Zero()).ToMicroseconds(), &epoll_alarm_impl_); - } - - void CancelImpl() override { - DCHECK(!deadline().IsInitialized()); - epoll_alarm_impl_.UnregisterIfRegistered(); - } - - private: - class EpollAlarmImpl : public EpollAlarm { - public: - explicit EpollAlarmImpl(QuicEpollAlarm* alarm) : alarm_(alarm) {} - - int64_t OnAlarm() override { - EpollAlarm::OnAlarm(); - alarm_->Fire(); - // Fire will take care of registering the alarm, if needed. - return 0; - } - - private: - QuicEpollAlarm* alarm_; - }; - - EpollServer* epoll_server_; - EpollAlarmImpl epoll_alarm_impl_; -}; - -} // namespace - -QuicEpollAlarmFactory::QuicEpollAlarmFactory(EpollServer* epoll_server) - : epoll_server_(epoll_server) {} - -QuicEpollAlarmFactory::~QuicEpollAlarmFactory() = default; - -QuicAlarm* QuicEpollAlarmFactory::CreateAlarm(QuicAlarm::Delegate* delegate) { - return new QuicEpollAlarm(epoll_server_, - QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate)); -} - -QuicArenaScopedPtr<QuicAlarm> QuicEpollAlarmFactory::CreateAlarm( - QuicArenaScopedPtr<QuicAlarm::Delegate> delegate, - QuicConnectionArena* arena) { - if (arena != nullptr) { - return arena->New<QuicEpollAlarm>(epoll_server_, std::move(delegate)); - } else { - return QuicArenaScopedPtr<QuicAlarm>( - new QuicEpollAlarm(epoll_server_, std::move(delegate))); - } -} - -} // namespace net diff --git a/chromium/net/tools/quic/quic_epoll_alarm_factory.h b/chromium/net/tools/quic/quic_epoll_alarm_factory.h deleted file mode 100644 index 9c47f56dc7b..00000000000 --- a/chromium/net/tools/quic/quic_epoll_alarm_factory.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2015 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_TOOLS_QUIC_QUIC_EPOLL_ALARM_FACTORY_H_ -#define NET_TOOLS_QUIC_QUIC_EPOLL_ALARM_FACTORY_H_ - -#include "net/quic/core/quic_alarm.h" -#include "net/quic/core/quic_alarm_factory.h" - -namespace net { - -class EpollServer; - -// Creates alarms that use the supplied EpollServer for timing and firing. -class QuicEpollAlarmFactory : public QuicAlarmFactory { - public: - explicit QuicEpollAlarmFactory(EpollServer* epoll_server); - ~QuicEpollAlarmFactory() override; - - // QuicAlarmFactory interface. - QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override; - QuicArenaScopedPtr<QuicAlarm> CreateAlarm( - QuicArenaScopedPtr<QuicAlarm::Delegate> delegate, - QuicConnectionArena* arena) override; - - private: - EpollServer* epoll_server_; // Not owned. - - DISALLOW_COPY_AND_ASSIGN(QuicEpollAlarmFactory); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_EPOLL_ALARM_FACTORY_H_ diff --git a/chromium/net/tools/quic/quic_epoll_alarm_factory_test.cc b/chromium/net/tools/quic/quic_epoll_alarm_factory_test.cc deleted file mode 100644 index 2e0f743a4a6..00000000000 --- a/chromium/net/tools/quic/quic_epoll_alarm_factory_test.cc +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2015 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/tools/quic/quic_epoll_alarm_factory.h" - -#include "net/quic/platform/api/quic_test.h" -#include "net/tools/quic/platform/impl/quic_epoll_clock.h" -#include "net/tools/quic/test_tools/mock_epoll_server.h" - -namespace net { -namespace test { -namespace { - -class TestDelegate : public QuicAlarm::Delegate { - public: - TestDelegate() : fired_(false) {} - - void OnAlarm() override { fired_ = true; } - - bool fired() const { return fired_; } - - private: - bool fired_; -}; - -// The boolean parameter denotes whether or not to use an arena. -class QuicEpollAlarmFactoryTest : public QuicTestWithParam<bool> { - protected: - QuicEpollAlarmFactoryTest() - : clock_(&epoll_server_), alarm_factory_(&epoll_server_) {} - - QuicConnectionArena* GetArenaParam() { - return GetParam() ? &arena_ : nullptr; - } - - const QuicEpollClock clock_; - QuicEpollAlarmFactory alarm_factory_; - test::MockEpollServer epoll_server_; - QuicConnectionArena arena_; -}; - -INSTANTIATE_TEST_CASE_P(UseArena, - QuicEpollAlarmFactoryTest, - ::testing::ValuesIn({true, false})); - -TEST_P(QuicEpollAlarmFactoryTest, CreateAlarm) { - QuicArenaScopedPtr<TestDelegate> delegate = - QuicArenaScopedPtr<TestDelegate>(new TestDelegate()); - QuicArenaScopedPtr<QuicAlarm> alarm( - alarm_factory_.CreateAlarm(std::move(delegate), GetArenaParam())); - - QuicTime start = clock_.Now(); - QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1); - alarm->Set(start + delta); - - epoll_server_.AdvanceByAndWaitForEventsAndExecuteCallbacks( - delta.ToMicroseconds()); - EXPECT_EQ(start + delta, clock_.Now()); -} - -TEST_P(QuicEpollAlarmFactoryTest, CreateAlarmAndCancel) { - QuicArenaScopedPtr<TestDelegate> delegate = - QuicArenaScopedPtr<TestDelegate>(new TestDelegate()); - TestDelegate* unowned_delegate = delegate.get(); - QuicArenaScopedPtr<QuicAlarm> alarm( - alarm_factory_.CreateAlarm(std::move(delegate), GetArenaParam())); - - QuicTime start = clock_.Now(); - QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1); - alarm->Set(start + delta); - alarm->Cancel(); - - epoll_server_.AdvanceByExactlyAndCallCallbacks(delta.ToMicroseconds()); - EXPECT_EQ(start + delta, clock_.Now()); - EXPECT_FALSE(unowned_delegate->fired()); -} - -TEST_P(QuicEpollAlarmFactoryTest, CreateAlarmAndReset) { - QuicArenaScopedPtr<TestDelegate> delegate = - QuicArenaScopedPtr<TestDelegate>(new TestDelegate()); - TestDelegate* unowned_delegate = delegate.get(); - QuicArenaScopedPtr<QuicAlarm> alarm( - alarm_factory_.CreateAlarm(std::move(delegate), GetArenaParam())); - - QuicTime start = clock_.Now(); - QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1); - alarm->Set(clock_.Now() + delta); - alarm->Cancel(); - QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(3); - alarm->Set(clock_.Now() + new_delta); - - epoll_server_.AdvanceByExactlyAndCallCallbacks(delta.ToMicroseconds()); - EXPECT_EQ(start + delta, clock_.Now()); - EXPECT_FALSE(unowned_delegate->fired()); - - epoll_server_.AdvanceByExactlyAndCallCallbacks( - (new_delta - delta).ToMicroseconds()); - EXPECT_EQ(start + new_delta, clock_.Now()); - EXPECT_TRUE(unowned_delegate->fired()); -} - -TEST_P(QuicEpollAlarmFactoryTest, CreateAlarmAndUpdate) { - QuicArenaScopedPtr<TestDelegate> delegate = - QuicArenaScopedPtr<TestDelegate>(new TestDelegate()); - TestDelegate* unowned_delegate = delegate.get(); - QuicArenaScopedPtr<QuicAlarm> alarm( - alarm_factory_.CreateAlarm(std::move(delegate), GetArenaParam())); - - QuicTime start = clock_.Now(); - QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1); - alarm->Set(clock_.Now() + delta); - QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(3); - alarm->Update(clock_.Now() + new_delta, QuicTime::Delta::FromMicroseconds(1)); - - epoll_server_.AdvanceByExactlyAndCallCallbacks(delta.ToMicroseconds()); - EXPECT_EQ(start + delta, clock_.Now()); - EXPECT_FALSE(unowned_delegate->fired()); - - // Move the alarm forward 1us and ensure it doesn't move forward. - alarm->Update(clock_.Now() + new_delta, QuicTime::Delta::FromMicroseconds(2)); - - epoll_server_.AdvanceByExactlyAndCallCallbacks( - (new_delta - delta).ToMicroseconds()); - EXPECT_EQ(start + new_delta, clock_.Now()); - EXPECT_TRUE(unowned_delegate->fired()); - - // Set the alarm via an update call. - new_delta = QuicTime::Delta::FromMicroseconds(5); - alarm->Update(clock_.Now() + new_delta, QuicTime::Delta::FromMicroseconds(1)); - EXPECT_TRUE(alarm->IsSet()); - - // Update it with an uninitialized time and ensure it's cancelled. - alarm->Update(QuicTime::Zero(), QuicTime::Delta::FromMicroseconds(1)); - EXPECT_FALSE(alarm->IsSet()); -} - -} // namespace -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/quic_epoll_connection_helper.cc b/chromium/net/tools/quic/quic_epoll_connection_helper.cc deleted file mode 100644 index 2c7f9537b77..00000000000 --- a/chromium/net/tools/quic/quic_epoll_connection_helper.cc +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_epoll_connection_helper.h" - -#include <errno.h> -#include <sys/socket.h> - -#include "net/quic/core/crypto/quic_random.h" -#include "net/tools/epoll_server/epoll_server.h" -#include "net/tools/quic/platform/impl/quic_socket_utils.h" - -namespace net { - -QuicEpollConnectionHelper::QuicEpollConnectionHelper(EpollServer* epoll_server, - QuicAllocator type) - : clock_(epoll_server), - random_generator_(QuicRandom::GetInstance()), - allocator_type_(type) {} - -QuicEpollConnectionHelper::~QuicEpollConnectionHelper() = default; - -const QuicClock* QuicEpollConnectionHelper::GetClock() const { - return &clock_; -} - -QuicRandom* QuicEpollConnectionHelper::GetRandomGenerator() { - return random_generator_; -} - -QuicBufferAllocator* QuicEpollConnectionHelper::GetStreamSendBufferAllocator() { - if (allocator_type_ == QuicAllocator::BUFFER_POOL) { - return &stream_buffer_allocator_; - } else { - DCHECK(allocator_type_ == QuicAllocator::SIMPLE); - return &simple_buffer_allocator_; - } -} - -} // namespace net diff --git a/chromium/net/tools/quic/quic_epoll_connection_helper.h b/chromium/net/tools/quic/quic_epoll_connection_helper.h deleted file mode 100644 index 90545689f22..00000000000 --- a/chromium/net/tools/quic/quic_epoll_connection_helper.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// The Google-specific helper for QuicConnection which uses -// EpollAlarm for alarms, and used an int fd_ for writing data. - -#ifndef NET_TOOLS_QUIC_QUIC_EPOLL_CONNECTION_HELPER_H_ -#define NET_TOOLS_QUIC_QUIC_EPOLL_CONNECTION_HELPER_H_ - -#include <sys/types.h> -#include <set> - -#include "base/macros.h" -#include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_packet_writer.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/core/quic_simple_buffer_allocator.h" -#include "net/quic/core/quic_time.h" -#include "net/tools/quic/platform/impl/quic_epoll_clock.h" -#include "net/tools/quic/quic_default_packet_writer.h" - -namespace net { - -class EpollServer; -class QuicRandom; - -using QuicStreamBufferAllocator = SimpleBufferAllocator; - -enum class QuicAllocator { SIMPLE, BUFFER_POOL }; - -class QuicEpollConnectionHelper : public QuicConnectionHelperInterface { - public: - QuicEpollConnectionHelper(EpollServer* eps, QuicAllocator allocator); - ~QuicEpollConnectionHelper() override; - - // QuicEpollConnectionHelperInterface - const QuicClock* GetClock() const override; - QuicRandom* GetRandomGenerator() override; - QuicBufferAllocator* GetStreamSendBufferAllocator() override; - - private: - friend class QuicConnectionPeer; - - const QuicEpollClock clock_; - QuicRandom* random_generator_; - // Set up allocators. They take up minimal memory before use. - // Allocator for stream send buffers. - QuicStreamBufferAllocator stream_buffer_allocator_; - SimpleBufferAllocator simple_buffer_allocator_; - QuicAllocator allocator_type_; - - DISALLOW_COPY_AND_ASSIGN(QuicEpollConnectionHelper); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_EPOLL_CONNECTION_HELPER_H_ diff --git a/chromium/net/tools/quic/quic_epoll_connection_helper_test.cc b/chromium/net/tools/quic/quic_epoll_connection_helper_test.cc deleted file mode 100644 index c31dcebcb09..00000000000 --- a/chromium/net/tools/quic/quic_epoll_connection_helper_test.cc +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_epoll_connection_helper.h" - -#include "net/quic/core/crypto/quic_random.h" -#include "net/quic/platform/api/quic_test.h" -#include "net/tools/quic/test_tools/mock_epoll_server.h" - -namespace net { -namespace test { -namespace { - -class QuicEpollConnectionHelperTest : public QuicTest { - protected: - QuicEpollConnectionHelperTest() - : helper_(&epoll_server_, QuicAllocator::BUFFER_POOL) {} - - MockEpollServer epoll_server_; - QuicEpollConnectionHelper helper_; -}; - -TEST_F(QuicEpollConnectionHelperTest, GetClock) { - const QuicClock* clock = helper_.GetClock(); - QuicTime start = clock->Now(); - - QuicTime::Delta delta = QuicTime::Delta::FromMilliseconds(5); - epoll_server_.AdvanceBy(delta.ToMicroseconds()); - - EXPECT_EQ(start + delta, clock->Now()); -} - -TEST_F(QuicEpollConnectionHelperTest, GetRandomGenerator) { - QuicRandom* random = helper_.GetRandomGenerator(); - EXPECT_EQ(QuicRandom::GetInstance(), random); -} - -} // namespace -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/quic_http_response_cache.cc b/chromium/net/tools/quic/quic_http_response_cache.cc deleted file mode 100644 index 39ae552c513..00000000000 --- a/chromium/net/tools/quic/quic_http_response_cache.cc +++ /dev/null @@ -1,396 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_http_response_cache.h" - -#include <utility> - -#include "base/files/file_enumerator.h" -#include "base/files/file_util.h" -#include "net/http/http_util.h" -#include "net/quic/platform/api/quic_bug_tracker.h" -#include "net/quic/platform/api/quic_logging.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_text_utils.h" -#include "net/spdy/chromium/spdy_http_utils.h" - -using base::FilePath; -using base::IntToString; -using std::string; - -namespace net { - -QuicHttpResponseCache::ServerPushInfo::ServerPushInfo(QuicUrl request_url, - SpdyHeaderBlock headers, - SpdyPriority priority, - string body) - : request_url(request_url), - headers(std::move(headers)), - priority(priority), - body(body) {} - -QuicHttpResponseCache::ServerPushInfo::ServerPushInfo( - const ServerPushInfo& other) - : request_url(other.request_url), - headers(other.headers.Clone()), - priority(other.priority), - body(other.body) {} - -QuicHttpResponseCache::Response::Response() - : response_type_(REGULAR_RESPONSE) {} - -QuicHttpResponseCache::Response::~Response() = default; - -QuicHttpResponseCache::ResourceFile::ResourceFile( - const base::FilePath& file_name) - : file_name_(file_name), file_name_string_(file_name.AsUTF8Unsafe()) {} - -QuicHttpResponseCache::ResourceFile::~ResourceFile() = default; - -void QuicHttpResponseCache::ResourceFile::Read() { - base::ReadFileToString(FilePath(file_name_), &file_contents_); - - // First read the headers. - size_t start = 0; - while (start < file_contents_.length()) { - size_t pos = file_contents_.find("\n", start); - if (pos == string::npos) { - QUIC_LOG(DFATAL) << "Headers invalid or empty, ignoring: " - << file_name_.value(); - return; - } - size_t len = pos - start; - // Support both dos and unix line endings for convenience. - if (file_contents_[pos - 1] == '\r') { - len -= 1; - } - QuicStringPiece line(file_contents_.data() + start, len); - start = pos + 1; - // Headers end with an empty line. - if (line.empty()) { - break; - } - // Extract the status from the HTTP first line. - if (line.substr(0, 4) == "HTTP") { - pos = line.find(" "); - if (pos == string::npos) { - QUIC_LOG(DFATAL) << "Headers invalid or empty, ignoring: " - << file_name_.value(); - return; - } - spdy_headers_[":status"] = line.substr(pos + 1, 3); - continue; - } - // Headers are "key: value". - pos = line.find(": "); - if (pos == string::npos) { - QUIC_LOG(DFATAL) << "Headers invalid or empty, ignoring: " - << file_name_.value(); - return; - } - spdy_headers_.AppendValueOrAddHeader( - QuicTextUtils::ToLower(line.substr(0, pos)), line.substr(pos + 2)); - } - - // The connection header is prohibited in HTTP/2. - spdy_headers_.erase("connection"); - - // Override the URL with the X-Original-Url header, if present. - auto it = spdy_headers_.find("x-original-url"); - if (it != spdy_headers_.end()) { - x_original_url_ = it->second; - HandleXOriginalUrl(); - } - - // X-Push-URL header is a relatively quick way to support sever push - // in the toy server. A production server should use link=preload - // stuff as described in https://w3c.github.io/preload/. - it = spdy_headers_.find("x-push-url"); - if (it != spdy_headers_.end()) { - QuicStringPiece push_urls = it->second; - size_t start = 0; - while (start < push_urls.length()) { - size_t pos = push_urls.find('\0', start); - if (pos == string::npos) { - push_urls_.push_back(QuicStringPiece(push_urls.data() + start, - push_urls.length() - start)); - break; - } - push_urls_.push_back(QuicStringPiece(push_urls.data() + start, pos)); - start += pos + 1; - } - } - - body_ = QuicStringPiece(file_contents_.data() + start, - file_contents_.size() - start); -} - -void QuicHttpResponseCache::ResourceFile::SetHostPathFromBase( - QuicStringPiece base) { - size_t path_start = base.find_first_of('/'); - DCHECK_LT(0UL, path_start); - host_ = base.substr(0, path_start); - size_t query_start = base.find_first_of(','); - if (query_start > 0) { - path_ = base.substr(path_start, query_start - 1); - } else { - path_ = base.substr(path_start); - } -} - -QuicStringPiece QuicHttpResponseCache::ResourceFile::RemoveScheme( - QuicStringPiece url) { - if (QuicTextUtils::StartsWith(url, "https://")) { - url.remove_prefix(8); - } else if (QuicTextUtils::StartsWith(url, "http://")) { - url.remove_prefix(7); - } - return url; -} - -void QuicHttpResponseCache::ResourceFile::HandleXOriginalUrl() { - QuicStringPiece url(x_original_url_); - // Remove the protocol so we can add it below. - url = RemoveScheme(url); - SetHostPathFromBase(url); -} - -const QuicHttpResponseCache::Response* QuicHttpResponseCache::GetResponse( - QuicStringPiece host, - QuicStringPiece path) const { - QuicWriterMutexLock lock(&response_mutex_); - - auto it = responses_.find(GetKey(host, path)); - if (it == responses_.end()) { - DVLOG(1) << "Get response for resource failed: host " << host << " path " - << path; - if (default_response_) { - return default_response_.get(); - } - return nullptr; - } - return it->second.get(); -} - -typedef QuicHttpResponseCache::ServerPushInfo ServerPushInfo; - -void QuicHttpResponseCache::AddSimpleResponse(QuicStringPiece host, - QuicStringPiece path, - int response_code, - QuicStringPiece body) { - SpdyHeaderBlock response_headers; - response_headers[":status"] = QuicTextUtils::Uint64ToString(response_code); - response_headers["content-length"] = - QuicTextUtils::Uint64ToString(body.length()); - AddResponse(host, path, std::move(response_headers), body); -} - -void QuicHttpResponseCache::AddSimpleResponseWithServerPushResources( - QuicStringPiece host, - QuicStringPiece path, - int response_code, - QuicStringPiece body, - std::list<ServerPushInfo> push_resources) { - AddSimpleResponse(host, path, response_code, body); - MaybeAddServerPushResources(host, path, push_resources); -} - -void QuicHttpResponseCache::AddDefaultResponse(Response* response) { - QuicWriterMutexLock lock(&response_mutex_); - default_response_.reset(response); -} - -void QuicHttpResponseCache::AddResponse(QuicStringPiece host, - QuicStringPiece path, - SpdyHeaderBlock response_headers, - QuicStringPiece response_body) { - AddResponseImpl(host, path, REGULAR_RESPONSE, std::move(response_headers), - response_body, SpdyHeaderBlock()); -} - -void QuicHttpResponseCache::AddResponse(QuicStringPiece host, - QuicStringPiece path, - SpdyHeaderBlock response_headers, - QuicStringPiece response_body, - SpdyHeaderBlock response_trailers) { - AddResponseImpl(host, path, REGULAR_RESPONSE, std::move(response_headers), - response_body, std::move(response_trailers)); -} - -void QuicHttpResponseCache::AddSpecialResponse( - QuicStringPiece host, - QuicStringPiece path, - SpecialResponseType response_type) { - AddResponseImpl(host, path, response_type, SpdyHeaderBlock(), "", - SpdyHeaderBlock()); -} - -QuicHttpResponseCache::QuicHttpResponseCache() = default; - -void QuicHttpResponseCache::InitializeFromDirectory( - const string& cache_directory) { - if (cache_directory.empty()) { - QUIC_BUG << "cache_directory must not be empty."; - return; - } - QUIC_LOG(INFO) - << "Attempting to initialize QuicHttpResponseCache from directory: " - << cache_directory; - FilePath directory(FilePath::FromUTF8Unsafe(cache_directory)); - base::FileEnumerator file_list(directory, true, base::FileEnumerator::FILES); - std::list<std::unique_ptr<ResourceFile>> resource_files; - for (FilePath file_iter = file_list.Next(); !file_iter.empty(); - file_iter = file_list.Next()) { - // Need to skip files in .svn directories - if (file_iter.value().find(FILE_PATH_LITERAL("/.svn/")) != string::npos) { - continue; - } - - std::unique_ptr<ResourceFile> resource_file(new ResourceFile(file_iter)); - - // Tease apart filename into host and path. - QuicStringPiece base(resource_file->file_name()); - base.remove_prefix(cache_directory.length()); - if (base[0] == '/') { - base.remove_prefix(1); - } - - resource_file->SetHostPathFromBase(base); - resource_file->Read(); - - AddResponse(resource_file->host(), resource_file->path(), - resource_file->spdy_headers().Clone(), resource_file->body()); - - resource_files.push_back(std::move(resource_file)); - } - - for (const auto& resource_file : resource_files) { - std::list<ServerPushInfo> push_resources; - for (const auto& push_url : resource_file->push_urls()) { - QuicUrl url(push_url); - const Response* response = GetResponse(url.host(), url.path()); - if (!response) { - QUIC_BUG << "Push URL '" << push_url << "' not found."; - return; - } - push_resources.push_back(ServerPushInfo(url, response->headers().Clone(), - kV3LowestPriority, - (string(response->body())))); - } - MaybeAddServerPushResources(resource_file->host(), resource_file->path(), - push_resources); - } -} - -std::list<ServerPushInfo> QuicHttpResponseCache::GetServerPushResources( - string request_url) { - QuicWriterMutexLock lock(&response_mutex_); - - std::list<ServerPushInfo> resources; - auto resource_range = server_push_resources_.equal_range(request_url); - for (auto it = resource_range.first; it != resource_range.second; ++it) { - resources.push_back(it->second); - } - QUIC_DVLOG(1) << "Found " << resources.size() << " push resources for " - << request_url; - return resources; -} - -QuicHttpResponseCache::~QuicHttpResponseCache() { - { - QuicWriterMutexLock lock(&response_mutex_); - responses_.clear(); - } -} - -void QuicHttpResponseCache::AddResponseImpl(QuicStringPiece host, - QuicStringPiece path, - SpecialResponseType response_type, - SpdyHeaderBlock response_headers, - QuicStringPiece response_body, - SpdyHeaderBlock response_trailers) { - QuicWriterMutexLock lock(&response_mutex_); - - DCHECK(!host.empty()) << "Host must be populated, e.g. \"www.google.com\""; - string key = GetKey(host, path); - if (QuicContainsKey(responses_, key)) { - QUIC_BUG << "Response for '" << key << "' already exists!"; - return; - } - auto new_response = QuicMakeUnique<Response>(); - new_response->set_response_type(response_type); - new_response->set_headers(std::move(response_headers)); - new_response->set_body(response_body); - new_response->set_trailers(std::move(response_trailers)); - QUIC_DVLOG(1) << "Add response with key " << key; - responses_[key] = std::move(new_response); -} - -string QuicHttpResponseCache::GetKey(QuicStringPiece host, - QuicStringPiece path) const { - string host_string = string(host); - size_t port = host_string.find(':'); - if (port != string::npos) - host_string = string(host_string.c_str(), port); - return host_string + string(path); -} - -void QuicHttpResponseCache::MaybeAddServerPushResources( - QuicStringPiece request_host, - QuicStringPiece request_path, - std::list<ServerPushInfo> push_resources) { - string request_url = GetKey(request_host, request_path); - - for (const auto& push_resource : push_resources) { - if (PushResourceExistsInCache(request_url, push_resource)) { - continue; - } - - QUIC_DVLOG(1) << "Add request-resource association: request url " - << request_url << " push url " - << push_resource.request_url.ToString() - << " response headers " - << push_resource.headers.DebugString(); - { - QuicWriterMutexLock lock(&response_mutex_); - server_push_resources_.insert(std::make_pair(request_url, push_resource)); - } - string host = push_resource.request_url.host(); - if (host.empty()) { - host = string(request_host); - } - string path = push_resource.request_url.path(); - bool found_existing_response = false; - { - QuicWriterMutexLock lock(&response_mutex_); - found_existing_response = QuicContainsKey(responses_, GetKey(host, path)); - } - if (!found_existing_response) { - // Add a server push response to responses map, if it is not in the map. - QuicStringPiece body = push_resource.body; - QUIC_DVLOG(1) << "Add response for push resource: host " << host - << " path " << path; - AddResponse(host, path, push_resource.headers.Clone(), body); - } - } -} - -bool QuicHttpResponseCache::PushResourceExistsInCache( - string original_request_url, - ServerPushInfo resource) { - QuicWriterMutexLock lock(&response_mutex_); - auto resource_range = - server_push_resources_.equal_range(original_request_url); - for (auto it = resource_range.first; it != resource_range.second; ++it) { - ServerPushInfo push_resource = it->second; - if (push_resource.request_url.ToString() == - resource.request_url.ToString()) { - return true; - } - } - return false; -} - -} // namespace net diff --git a/chromium/net/tools/quic/quic_http_response_cache.h b/chromium/net/tools/quic/quic_http_response_cache.h deleted file mode 100644 index ea840feaa6e..00000000000 --- a/chromium/net/tools/quic/quic_http_response_cache.h +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_QUIC_HTTP_RESPONSE_CACHE_H_ -#define NET_TOOLS_QUIC_QUIC_HTTP_RESPONSE_CACHE_H_ - -#include <list> -#include <map> -#include <memory> -#include <string> -#include <vector> - -#include "base/files/file_path.h" -#include "base/macros.h" -#include "net/quic/core/spdy_utils.h" -#include "net/quic/platform/api/quic_containers.h" -#include "net/quic/platform/api/quic_mutex.h" -#include "net/quic/platform/api/quic_string_piece.h" -#include "net/quic/platform/api/quic_url.h" -#include "net/spdy/core/spdy_framer.h" - -namespace net { - -// In-memory cache for HTTP responses. -// Reads from disk cache generated by: -// `wget -p --save_headers <url>` -class QuicHttpResponseCache { - public: - // A ServerPushInfo contains path of the push request and everything needed in - // comprising a response for the push request. - struct ServerPushInfo { - ServerPushInfo(QuicUrl request_url, - SpdyHeaderBlock headers, - SpdyPriority priority, - std::string body); - ServerPushInfo(const ServerPushInfo& other); - QuicUrl request_url; - SpdyHeaderBlock headers; - SpdyPriority priority; - std::string body; - }; - - enum SpecialResponseType { - REGULAR_RESPONSE, // Send the headers and body like a server should. - CLOSE_CONNECTION, // Close the connection (sending the close packet). - IGNORE_REQUEST, // Do nothing, expect the client to time out. - }; - - // Container for response header/body pairs. - class Response { - public: - Response(); - ~Response(); - - SpecialResponseType response_type() const { return response_type_; } - const SpdyHeaderBlock& headers() const { return headers_; } - const SpdyHeaderBlock& trailers() const { return trailers_; } - const QuicStringPiece body() const { return QuicStringPiece(body_); } - - void set_response_type(SpecialResponseType response_type) { - response_type_ = response_type; - } - void set_headers(SpdyHeaderBlock headers) { headers_ = std::move(headers); } - void set_trailers(SpdyHeaderBlock trailers) { - trailers_ = std::move(trailers); - } - void set_body(QuicStringPiece body) { - body_.assign(body.data(), body.size()); - } - - private: - SpecialResponseType response_type_; - SpdyHeaderBlock headers_; - SpdyHeaderBlock trailers_; - std::string body_; - - DISALLOW_COPY_AND_ASSIGN(Response); - }; - - // Class to manage loading a resource file into memory. There are - // two uses: called by InitializeFromDirectory to load resources - // from files, and recursively called when said resources specify - // server push associations. - class ResourceFile { - public: - explicit ResourceFile(const base::FilePath& file_name); - virtual ~ResourceFile(); - - void Read(); - - // |base| is |file_name_| with |cache_directory| prefix stripped. - void SetHostPathFromBase(QuicStringPiece base); - - const std::string& file_name() { return file_name_string_; } - - QuicStringPiece host() { return host_; } - - QuicStringPiece path() { return path_; } - - const SpdyHeaderBlock& spdy_headers() { return spdy_headers_; } - - QuicStringPiece body() { return body_; } - - const std::vector<QuicStringPiece>& push_urls() { return push_urls_; } - - protected: - void HandleXOriginalUrl(); - void HandlePushUrls(const std::vector<QuicStringPiece>& push_urls); - QuicStringPiece RemoveScheme(QuicStringPiece url); - - const std::string cache_directory_; - const base::FilePath file_name_; - const std::string file_name_string_; - std::string file_contents_; - QuicStringPiece body_; - SpdyHeaderBlock spdy_headers_; - QuicStringPiece x_original_url_; - std::vector<QuicStringPiece> push_urls_; - - private: - QuicStringPiece host_; - QuicStringPiece path_; - QuicHttpResponseCache* cache_; - - DISALLOW_COPY_AND_ASSIGN(ResourceFile); - }; - - QuicHttpResponseCache(); - ~QuicHttpResponseCache(); - - // Retrieve a response from this cache for a given host and path.. - // If no appropriate response exists, nullptr is returned. - const Response* GetResponse(QuicStringPiece host, QuicStringPiece path) const; - - // Adds a simple response to the cache. The response headers will - // only contain the "content-length" header with the length of |body|. - void AddSimpleResponse(QuicStringPiece host, - QuicStringPiece path, - int response_code, - QuicStringPiece body); - - // Add a simple response to the cache as AddSimpleResponse() does, and add - // some server push resources(resource path, corresponding response status and - // path) associated with it. - // Push resource implicitly come from the same host. - void AddSimpleResponseWithServerPushResources( - QuicStringPiece host, - QuicStringPiece path, - int response_code, - QuicStringPiece body, - std::list<ServerPushInfo> push_resources); - - // Add a response to the cache. - void AddResponse(QuicStringPiece host, - QuicStringPiece path, - SpdyHeaderBlock response_headers, - QuicStringPiece response_body); - - // Add a response, with trailers, to the cache. - void AddResponse(QuicStringPiece host, - QuicStringPiece path, - SpdyHeaderBlock response_headers, - QuicStringPiece response_body, - SpdyHeaderBlock response_trailers); - - // Simulate a special behavior at a particular path. - void AddSpecialResponse(QuicStringPiece host, - QuicStringPiece path, - SpecialResponseType response_type); - - // Sets a default response in case of cache misses. Takes ownership of - // 'response'. - void AddDefaultResponse(Response* response); - - // |cache_cirectory| can be generated using `wget -p --save-headers <url>`. - void InitializeFromDirectory(const std::string& cache_directory); - - // Find all the server push resources associated with |request_url|. - std::list<ServerPushInfo> GetServerPushResources(std::string request_url); - - private: - void AddResponseImpl(QuicStringPiece host, - QuicStringPiece path, - SpecialResponseType response_type, - SpdyHeaderBlock response_headers, - QuicStringPiece response_body, - SpdyHeaderBlock response_trailers); - - std::string GetKey(QuicStringPiece host, QuicStringPiece path) const; - - // Add some server push urls with given responses for specified - // request if these push resources are not associated with this request yet. - void MaybeAddServerPushResources(QuicStringPiece request_host, - QuicStringPiece request_path, - std::list<ServerPushInfo> push_resources); - - // Check if push resource(push_host/push_path) associated with given request - // url already exists in server push map. - bool PushResourceExistsInCache(std::string original_request_url, - ServerPushInfo resource); - - // Cached responses. - QuicUnorderedMap<std::string, std::unique_ptr<Response>> responses_ - GUARDED_BY(response_mutex_); - - // The default response for cache misses, if set. - std::unique_ptr<Response> default_response_ GUARDED_BY(response_mutex_); - - // A map from request URL to associated server push responses (if any). - std::multimap<std::string, ServerPushInfo> server_push_resources_ - GUARDED_BY(response_mutex_); - - // Protects against concurrent access from test threads setting responses, and - // server threads accessing those responses. - mutable QuicMutex response_mutex_; - - DISALLOW_COPY_AND_ASSIGN(QuicHttpResponseCache); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_HTTP_RESPONSE_CACHE_H_ diff --git a/chromium/net/tools/quic/quic_http_response_cache_test.cc b/chromium/net/tools/quic/quic_http_response_cache_test.cc deleted file mode 100644 index 60ea65fa53d..00000000000 --- a/chromium/net/tools/quic/quic_http_response_cache_test.cc +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_http_response_cache.h" - -#include "base/files/file_path.h" -#include "base/path_service.h" -#include "net/quic/platform/api/quic_map_util.h" -#include "net/quic/platform/api/quic_str_cat.h" -#include "net/quic/platform/api/quic_test.h" -#include "net/quic/platform/api/quic_text_utils.h" - -using std::string; - -namespace net { -namespace test { - -namespace { -typedef QuicHttpResponseCache::Response Response; -typedef QuicHttpResponseCache::ServerPushInfo ServerPushInfo; -}; // namespace - -class QuicHttpResponseCacheTest : public QuicTest { - protected: - void CreateRequest(string host, string path, SpdyHeaderBlock* headers) { - (*headers)[":method"] = "GET"; - (*headers)[":path"] = path; - (*headers)[":authority"] = host; - (*headers)[":scheme"] = "https"; - } - - string CacheDirectory() { - base::FilePath path; - PathService::Get(base::DIR_SOURCE_ROOT, &path); - path = path.AppendASCII("net").AppendASCII("data").AppendASCII( - "quic_http_response_cache_data"); - // The file path is known to be an ascii string. - return path.MaybeAsASCII(); - } - - QuicHttpResponseCache cache_; -}; - -TEST_F(QuicHttpResponseCacheTest, GetResponseNoMatch) { - const QuicHttpResponseCache::Response* response = - cache_.GetResponse("mail.google.com", "/index.html"); - ASSERT_FALSE(response); -} - -TEST_F(QuicHttpResponseCacheTest, AddSimpleResponseGetResponse) { - string response_body("hello response"); - cache_.AddSimpleResponse("www.google.com", "/", 200, response_body); - - SpdyHeaderBlock request_headers; - CreateRequest("www.google.com", "/", &request_headers); - const QuicHttpResponseCache::Response* response = - cache_.GetResponse("www.google.com", "/"); - ASSERT_TRUE(response); - ASSERT_TRUE(QuicContainsKey(response->headers(), ":status")); - EXPECT_EQ("200", response->headers().find(":status")->second); - EXPECT_EQ(response_body.size(), response->body().length()); -} - -TEST_F(QuicHttpResponseCacheTest, AddResponse) { - const string kRequestHost = "www.foo.com"; - const string kRequestPath = "/"; - const string kResponseBody("hello response"); - - SpdyHeaderBlock response_headers; - response_headers[":version"] = "HTTP/1.1"; - response_headers[":status"] = "200"; - response_headers["content-length"] = - QuicTextUtils::Uint64ToString(kResponseBody.size()); - - SpdyHeaderBlock response_trailers; - response_trailers["key-1"] = "value-1"; - response_trailers["key-2"] = "value-2"; - response_trailers["key-3"] = "value-3"; - - cache_.AddResponse(kRequestHost, "/", response_headers.Clone(), kResponseBody, - response_trailers.Clone()); - - const QuicHttpResponseCache::Response* response = - cache_.GetResponse(kRequestHost, kRequestPath); - EXPECT_EQ(response->headers(), response_headers); - EXPECT_EQ(response->body(), kResponseBody); - EXPECT_EQ(response->trailers(), response_trailers); -} - -TEST_F(QuicHttpResponseCacheTest, ReadsCacheDir) { - cache_.InitializeFromDirectory(CacheDirectory()); - const QuicHttpResponseCache::Response* response = - cache_.GetResponse("test.example.com", "/index.html"); - ASSERT_TRUE(response); - ASSERT_TRUE(QuicContainsKey(response->headers(), ":status")); - EXPECT_EQ("200", response->headers().find(":status")->second); - // Connection headers are not valid in HTTP/2. - EXPECT_FALSE(QuicContainsKey(response->headers(), "connection")); - EXPECT_LT(0U, response->body().length()); -} - -TEST_F(QuicHttpResponseCacheTest, ReadsCacheDirWithServerPushResource) { - cache_.InitializeFromDirectory(CacheDirectory() + "_with_push"); - std::list<ServerPushInfo> resources = - cache_.GetServerPushResources("test.example.com/"); - ASSERT_EQ(1UL, resources.size()); -} - -TEST_F(QuicHttpResponseCacheTest, ReadsCacheDirWithServerPushResources) { - cache_.InitializeFromDirectory(CacheDirectory() + "_with_push"); - std::list<ServerPushInfo> resources = - cache_.GetServerPushResources("test.example.com/index2.html"); - ASSERT_EQ(2UL, resources.size()); -} - -TEST_F(QuicHttpResponseCacheTest, UsesOriginalUrl) { - cache_.InitializeFromDirectory(CacheDirectory()); - const QuicHttpResponseCache::Response* response = - cache_.GetResponse("test.example.com", "/site_map.html"); - ASSERT_TRUE(response); - ASSERT_TRUE(QuicContainsKey(response->headers(), ":status")); - EXPECT_EQ("200", response->headers().find(":status")->second); - // Connection headers are not valid in HTTP/2. - EXPECT_FALSE(QuicContainsKey(response->headers(), "connection")); - EXPECT_LT(0U, response->body().length()); -} - -TEST_F(QuicHttpResponseCacheTest, DefaultResponse) { - // Verify GetResponse returns nullptr when no default is set. - const QuicHttpResponseCache::Response* response = - cache_.GetResponse("www.google.com", "/"); - ASSERT_FALSE(response); - - // Add a default response. - SpdyHeaderBlock response_headers; - response_headers[":version"] = "HTTP/1.1"; - response_headers[":status"] = "200"; - response_headers["content-length"] = "0"; - QuicHttpResponseCache::Response* default_response = - new QuicHttpResponseCache::Response; - default_response->set_headers(std::move(response_headers)); - cache_.AddDefaultResponse(default_response); - - // Now we should get the default response for the original request. - response = cache_.GetResponse("www.google.com", "/"); - ASSERT_TRUE(response); - ASSERT_TRUE(QuicContainsKey(response->headers(), ":status")); - EXPECT_EQ("200", response->headers().find(":status")->second); - - // Now add a set response for / and make sure it is returned - cache_.AddSimpleResponse("www.google.com", "/", 302, ""); - response = cache_.GetResponse("www.google.com", "/"); - ASSERT_TRUE(response); - ASSERT_TRUE(QuicContainsKey(response->headers(), ":status")); - EXPECT_EQ("302", response->headers().find(":status")->second); - - // We should get the default response for other requests. - response = cache_.GetResponse("www.google.com", "/asd"); - ASSERT_TRUE(response); - ASSERT_TRUE(QuicContainsKey(response->headers(), ":status")); - EXPECT_EQ("200", response->headers().find(":status")->second); -} - -TEST_F(QuicHttpResponseCacheTest, AddSimpleResponseWithServerPushResources) { - string request_host = "www.foo.com"; - string response_body("hello response"); - const size_t kNumResources = 5; - int NumResources = 5; - std::list<QuicHttpResponseCache::ServerPushInfo> push_resources; - string scheme = "http"; - for (int i = 0; i < NumResources; ++i) { - string path = "/server_push_src" + QuicTextUtils::Uint64ToString(i); - string url = scheme + "://" + request_host + path; - QuicUrl resource_url(url); - string body = QuicStrCat("This is server push response body for ", path); - SpdyHeaderBlock response_headers; - response_headers[":version"] = "HTTP/1.1"; - response_headers[":status"] = "200"; - response_headers["content-length"] = - QuicTextUtils::Uint64ToString(body.size()); - push_resources.push_back( - ServerPushInfo(resource_url, response_headers.Clone(), i, body)); - } - - cache_.AddSimpleResponseWithServerPushResources( - request_host, "/", 200, response_body, push_resources); - - string request_url = request_host + "/"; - std::list<ServerPushInfo> resources = - cache_.GetServerPushResources(request_url); - ASSERT_EQ(kNumResources, resources.size()); - for (const auto& push_resource : push_resources) { - ServerPushInfo resource = resources.front(); - EXPECT_EQ(resource.request_url.ToString(), - push_resource.request_url.ToString()); - EXPECT_EQ(resource.priority, push_resource.priority); - resources.pop_front(); - } -} - -TEST_F(QuicHttpResponseCacheTest, GetServerPushResourcesAndPushResponses) { - string request_host = "www.foo.com"; - string response_body("hello response"); - const size_t kNumResources = 4; - int NumResources = 4; - string scheme = "http"; - string push_response_status[kNumResources] = {"200", "200", "301", "404"}; - std::list<QuicHttpResponseCache::ServerPushInfo> push_resources; - for (int i = 0; i < NumResources; ++i) { - string path = "/server_push_src" + QuicTextUtils::Uint64ToString(i); - string url = scheme + "://" + request_host + path; - QuicUrl resource_url(url); - string body = "This is server push response body for " + path; - SpdyHeaderBlock response_headers; - response_headers[":version"] = "HTTP/1.1"; - response_headers[":status"] = push_response_status[i]; - response_headers["content-length"] = - QuicTextUtils::Uint64ToString(body.size()); - push_resources.push_back( - ServerPushInfo(resource_url, response_headers.Clone(), i, body)); - } - cache_.AddSimpleResponseWithServerPushResources( - request_host, "/", 200, response_body, push_resources); - string request_url = request_host + "/"; - std::list<ServerPushInfo> resources = - cache_.GetServerPushResources(request_url); - ASSERT_EQ(kNumResources, resources.size()); - int i = 0; - for (const auto& push_resource : push_resources) { - QuicUrl url = resources.front().request_url; - string host = url.host(); - string path = url.path(); - const QuicHttpResponseCache::Response* response = - cache_.GetResponse(host, path); - ASSERT_TRUE(response); - ASSERT_TRUE(QuicContainsKey(response->headers(), ":status")); - EXPECT_EQ(push_response_status[i++], - response->headers().find(":status")->second); - EXPECT_EQ(push_resource.body, response->body()); - resources.pop_front(); - } -} - -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/quic_packet_printer_bin.cc b/chromium/net/tools/quic/quic_packet_printer_bin.cc deleted file mode 100644 index 59750bbfaa7..00000000000 --- a/chromium/net/tools/quic/quic_packet_printer_bin.cc +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// clang-format off - -// Dumps out the decryptable contents of a QUIC packet in a human-readable way. -// If the packet is null encrypted, this will dump full packet contents. -// Otherwise it will dump the header, and fail with an error that the -// packet is undecryptable. -// -// Usage: quic_packet_printer server|client <hex dump of packet> -// -// Example input: -// quic_packet_printer server 0c6b810308320f24c004a939a38a2e3fd6ca589917f200400 -// 201b80b0100501c0700060003023d0000001c00556e656e637279707465642073747265616d2 -// 064617461207365656e -// -// Example output: -// OnPacket -// OnUnauthenticatedPublicHeader -// OnUnauthenticatedHeader: { connection_id: 13845207862000976235, -// connection_id_length:8, packet_number_length:1, multipath_flag: 0, -// reset_flag: 0, version_flag: 0, path_id: , packet_number: 4} -// OnDecryptedPacket -// OnPacketHeader -// OnAckFrame: largest_observed: 1 ack_delay_time: 3000 -// missing_packets: [ ] is_truncated: 0 received_packets: [ 1 at 466016 ] -// OnStopWaitingFrame -// OnConnectionCloseFrame: error_code { 61 } error_details { Unencrypted stream -// data seen } - -// clang-format on - -#include <iostream> -#include <string> - -#include "base/command_line.h" -#include "base/strings/utf_string_conversions.h" -#include "net/quic/core/quic_framer.h" -#include "net/quic/core/quic_utils.h" -#include "net/quic/platform/api/quic_text_utils.h" - -using std::string; - -// If set, specify the QUIC version to use. -string FLAGS_quic_version = ""; - -namespace { - -string ArgToString(base::CommandLine::StringType arg) { -#if defined(OS_WIN) - return base::UTF16ToASCII(arg); -#else - return arg; -#endif -} -} - -namespace net { - -class QuicPacketPrinter : public QuicFramerVisitorInterface { - public: - explicit QuicPacketPrinter(QuicFramer* framer) : framer_(framer) {} - - void OnError(QuicFramer* framer) override { - std::cerr << "OnError: " << QuicErrorCodeToString(framer->error()) - << " detail: " << framer->detailed_error() << "\n"; - } - bool OnProtocolVersionMismatch(ParsedQuicVersion received_version) override { - framer_->set_version(received_version); - std::cerr << "OnProtocolVersionMismatch: " - << ParsedQuicVersionToString(received_version) << "\n"; - return true; - } - void OnPacket() override { std::cerr << "OnPacket\n"; } - void OnPublicResetPacket(const QuicPublicResetPacket& packet) override { - std::cerr << "OnPublicResetPacket\n"; - } - void OnVersionNegotiationPacket( - const QuicVersionNegotiationPacket& packet) override { - std::cerr << "OnVersionNegotiationPacket\n"; - } - bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override { - std::cerr << "OnUnauthenticatedPublicHeader\n"; - return true; - } - bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override { - std::cerr << "OnUnauthenticatedHeader: " << header; - return true; - } - void OnDecryptedPacket(EncryptionLevel level) override { - // This only currently supports "decrypting" null encrypted packets. - DCHECK_EQ(ENCRYPTION_NONE, level); - std::cerr << "OnDecryptedPacket\n"; - } - bool OnPacketHeader(const QuicPacketHeader& header) override { - std::cerr << "OnPacketHeader\n"; - return true; - } - bool OnStreamFrame(const QuicStreamFrame& frame) override { - std::cerr << "OnStreamFrame: " << frame; - std::cerr << " data: { " - << QuicTextUtils::HexEncode(frame.data_buffer, frame.data_length) - << " }\n"; - return true; - } - bool OnAckFrame(const QuicAckFrame& frame) override { - std::cerr << "OnAckFrame: " << frame; - return true; - } - bool OnAckFrameStart(QuicPacketNumber largest_acked, - QuicTime::Delta /*ack_delay_time*/) override { - std::cerr << "OnAckFrameStart, largest_acked: " << largest_acked; - return true; - } - bool OnAckRange(QuicPacketNumber start, - QuicPacketNumber end, - bool last_range) override { - std::cerr << "OnAckRange: [" << start << ", " << end - << "), last_range: " << last_range; - return true; - } - bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override { - std::cerr << "OnStopWaitingFrame: " << frame; - return true; - } - bool OnPaddingFrame(const QuicPaddingFrame& frame) override { - std::cerr << "OnPaddingFrame: " << frame; - return true; - } - bool OnPingFrame(const QuicPingFrame& frame) override { - std::cerr << "OnPingFrame\n"; - return true; - } - bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override { - std::cerr << "OnRstStreamFrame: " << frame; - return true; - } - bool OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override { - std::cerr << "OnConnectionCloseFrame: " << frame; - return true; - } - bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override { - std::cerr << "OnGoAwayFrame: " << frame; - return true; - } - bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override { - std::cerr << "OnWindowUpdateFrame: " << frame; - return true; - } - bool OnBlockedFrame(const QuicBlockedFrame& frame) override { - std::cerr << "OnBlockedFrame: " << frame; - return true; - } - void OnPacketComplete() override { std::cerr << "OnPacketComplete\n"; } - bool IsValidStatelessResetToken(uint128 token) const override { - std::cerr << "IsValidStatelessResetToken\n"; - return false; - } - void OnAuthenticatedIetfStatelessResetPacket( - const QuicIetfStatelessResetPacket& packet) override { - std::cerr << "OnAuthenticatedIetfStatelessResetPacket\n"; - } - - private: - QuicFramer* framer_; // Unowned. -}; - -} // namespace net - -int main(int argc, char* argv[]) { - base::CommandLine::Init(argc, argv); - base::CommandLine* line = base::CommandLine::ForCurrentProcess(); - const base::CommandLine::StringVector& args = line->GetArgs(); - - if (args.size() != 3) { - std::cerr << "Missing argument " << argc << ". (Usage: " << argv[0] - << " client|server <hex>\n"; - return 1; - } - - if (line->HasSwitch("quic_version")) { - FLAGS_quic_version = line->GetSwitchValueASCII("quic_version"); - } - - string perspective_string = ArgToString(args[0]); - net::Perspective perspective; - if (perspective_string == "client") { - perspective = net::Perspective::IS_CLIENT; - } else if (perspective_string == "server") { - perspective = net::Perspective::IS_SERVER; - } else { - std::cerr << "Invalid perspective. " << perspective_string - << " Usage: " << args[0] << " client|server <hex>\n"; - return 1; - } - string hex = net::QuicTextUtils::HexDecode(argv[2]); - net::ParsedQuicVersionVector versions = net::AllSupportedVersions(); - // Fake a time since we're not actually generating acks. - net::QuicTime start(net::QuicTime::Zero()); - net::QuicFramer framer(versions, start, perspective); - if (!FLAGS_quic_version.empty()) { - for (net::ParsedQuicVersion version : versions) { - if (net::QuicVersionToString(version.transport_version) == - FLAGS_quic_version) { - framer.set_version(version); - } - } - } - net::QuicPacketPrinter visitor(&framer); - framer.set_visitor(&visitor); - net::QuicEncryptedPacket encrypted(hex.c_str(), hex.length()); - return framer.ProcessPacket(encrypted); -} diff --git a/chromium/net/tools/quic/quic_packet_reader.cc b/chromium/net/tools/quic/quic_packet_reader.cc deleted file mode 100644 index 76de5b2956b..00000000000 --- a/chromium/net/tools/quic/quic_packet_reader.cc +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright 2015 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/tools/quic/quic_packet_reader.h" - -#include <errno.h> -#ifndef __APPLE__ -// This is a GNU header that is not present in /usr/include on MacOS -#include <features.h> -#endif -#include <string.h> - -#include "net/quic/platform/api/quic_bug_tracker.h" -#include "net/quic/platform/api/quic_flags.h" -#include "net/quic/platform/api/quic_logging.h" -#include "net/quic/platform/api/quic_socket_address.h" -#include "net/tools/quic/platform/impl/quic_socket_utils.h" -#include "net/tools/quic/quic_dispatcher.h" -#include "net/tools/quic/quic_process_packet_interface.h" - -#ifndef SO_RXQ_OVFL -#define SO_RXQ_OVFL 40 -#endif - -namespace net { - - -QuicPacketReader::QuicPacketReader() { - Initialize(); -} - -void QuicPacketReader::Initialize() { -#if MMSG_MORE - // Zero initialize uninitialized memory. - memset(mmsg_hdr_, 0, sizeof(mmsg_hdr_)); - - for (int i = 0; i < kNumPacketsPerReadMmsgCall; ++i) { - packets_[i].iov.iov_base = packets_[i].buf; - packets_[i].iov.iov_len = kMaxPacketSize; - memset(&packets_[i].raw_address, 0, sizeof(packets_[i].raw_address)); - memset(packets_[i].cbuf, 0, sizeof(packets_[i].cbuf)); - memset(packets_[i].buf, 0, sizeof(packets_[i].buf)); - - msghdr* hdr = &mmsg_hdr_[i].msg_hdr; - hdr->msg_name = &packets_[i].raw_address; - hdr->msg_namelen = sizeof(sockaddr_storage); - hdr->msg_iov = &packets_[i].iov; - hdr->msg_iovlen = 1; - - hdr->msg_control = packets_[i].cbuf; - hdr->msg_controllen = QuicSocketUtils::kSpaceForCmsg; - } -#endif -} - -QuicPacketReader::~QuicPacketReader() = default; - -bool QuicPacketReader::ReadAndDispatchPackets( - int fd, - int port, - const QuicClock& clock, - ProcessPacketInterface* processor, - QuicPacketCount* packets_dropped) { -#if MMSG_MORE - return ReadAndDispatchManyPackets(fd, port, clock, processor, - packets_dropped); -#else - return ReadAndDispatchSinglePacket(fd, port, clock, processor, - packets_dropped); -#endif -} - -bool QuicPacketReader::ReadAndDispatchManyPackets( - int fd, - int port, - const QuicClock& clock, - ProcessPacketInterface* processor, - QuicPacketCount* packets_dropped) { -#if MMSG_MORE - // Re-set the length fields in case recvmmsg has changed them. - for (int i = 0; i < kNumPacketsPerReadMmsgCall; ++i) { - DCHECK_EQ(kMaxPacketSize, packets_[i].iov.iov_len); - msghdr* hdr = &mmsg_hdr_[i].msg_hdr; - hdr->msg_namelen = sizeof(sockaddr_storage); - DCHECK_EQ(1, hdr->msg_iovlen); - hdr->msg_controllen = QuicSocketUtils::kSpaceForCmsg; - } - - int packets_read = - recvmmsg(fd, mmsg_hdr_, kNumPacketsPerReadMmsgCall, 0, nullptr); - - if (packets_read <= 0) { - return false; // recvmmsg failed. - } - - QuicWallTime fallback_walltimestamp = QuicWallTime::Zero(); - for (int i = 0; i < packets_read; ++i) { - if (mmsg_hdr_[i].msg_len == 0) { - continue; - } - - if (mmsg_hdr_[i].msg_hdr.msg_controllen >= QuicSocketUtils::kSpaceForCmsg) { - QUIC_BUG << "Incorrectly set control length: " - << mmsg_hdr_[i].msg_hdr.msg_controllen << ", expected " - << QuicSocketUtils::kSpaceForCmsg; - continue; - } - - QuicSocketAddress client_address = - QuicSocketAddress(packets_[i].raw_address); - QuicIpAddress server_ip; - QuicWallTime packet_walltimestamp = QuicWallTime::Zero(); - QuicSocketUtils::GetAddressAndTimestampFromMsghdr( - &mmsg_hdr_[i].msg_hdr, &server_ip, &packet_walltimestamp); - if (!server_ip.IsInitialized()) { - QUIC_BUG << "Unable to get server address."; - continue; - } - - // This isn't particularly desirable, but not all platforms support socket - // timestamping. - if (packet_walltimestamp.IsZero()) { - if (fallback_walltimestamp.IsZero()) { - fallback_walltimestamp = clock.WallNow(); - } - packet_walltimestamp = fallback_walltimestamp; - } - QuicTime timestamp = clock.ConvertWallTimeToQuicTime(packet_walltimestamp); - int ttl = 0; - bool has_ttl = - QuicSocketUtils::GetTtlFromMsghdr(&mmsg_hdr_[i].msg_hdr, &ttl); - QuicReceivedPacket packet(reinterpret_cast<char*>(packets_[i].iov.iov_base), - mmsg_hdr_[i].msg_len, timestamp, false, ttl, - has_ttl); - QuicSocketAddress server_address(server_ip, port); - processor->ProcessPacket(server_address, client_address, packet); - } - - if (packets_dropped != nullptr) { - QuicSocketUtils::GetOverflowFromMsghdr(&mmsg_hdr_[0].msg_hdr, - packets_dropped); - } - - // We may not have read all of the packets available on the socket. - return packets_read == kNumPacketsPerReadMmsgCall; -#else - QUIC_LOG(FATAL) << "Unsupported"; - return false; -#endif -} - -/* static */ -bool QuicPacketReader::ReadAndDispatchSinglePacket( - int fd, - int port, - const QuicClock& clock, - ProcessPacketInterface* processor, - QuicPacketCount* packets_dropped) { - char buf[kMaxPacketSize]; - - QuicSocketAddress client_address; - QuicIpAddress server_ip; - QuicWallTime walltimestamp = QuicWallTime::Zero(); - int bytes_read = - QuicSocketUtils::ReadPacket(fd, buf, arraysize(buf), packets_dropped, - &server_ip, &walltimestamp, &client_address); - if (bytes_read < 0) { - return false; // ReadPacket failed. - } - - if (!server_ip.IsInitialized()) { - QUIC_BUG << "Unable to get server address."; - return false; - } - // This isn't particularly desirable, but not all platforms support socket - // timestamping. - if (walltimestamp.IsZero()) { - walltimestamp = clock.WallNow(); - } - QuicTime timestamp = clock.ConvertWallTimeToQuicTime(walltimestamp); - - QuicReceivedPacket packet(buf, bytes_read, timestamp, false); - QuicSocketAddress server_address(server_ip, port); - processor->ProcessPacket(server_address, client_address, packet); - - // The socket read was successful, so return true even if packet dispatch - // failed. - return true; -} - - -} // namespace net diff --git a/chromium/net/tools/quic/quic_packet_reader.h b/chromium/net/tools/quic/quic_packet_reader.h deleted file mode 100644 index 13a8ccc89a0..00000000000 --- a/chromium/net/tools/quic/quic_packet_reader.h +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// A class to read incoming QUIC packets from the UDP socket. - -#ifndef NET_TOOLS_QUIC_QUIC_PACKET_READER_H_ -#define NET_TOOLS_QUIC_QUIC_PACKET_READER_H_ - -#include <netinet/in.h> -// Include here to guarantee this header gets included (for MSG_WAITFORONE) -// regardless of how the below transitive header include set may change. -#include <sys/socket.h> - -#include "base/macros.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/platform/api/quic_clock.h" -#include "net/quic/platform/api/quic_socket_address.h" -#include "net/tools/quic/platform/impl/quic_socket_utils.h" -#include "net/tools/quic/quic_process_packet_interface.h" - -#define MMSG_MORE 0 - -namespace net { - -#if MMSG_MORE -// Read in larger batches to minimize recvmmsg overhead. -const int kNumPacketsPerReadMmsgCall = 16; -#endif - -class QuicPacketReader { - public: - QuicPacketReader(); - - virtual ~QuicPacketReader(); - - // Reads a number of packets from the given fd, and then passes them off to - // 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. - // If the socket has timestamping enabled, the per packet timestamps will be - // passed to the processor. Otherwise, |clock| will be used. - virtual bool ReadAndDispatchPackets(int fd, - int port, - const QuicClock& clock, - ProcessPacketInterface* processor, - QuicPacketCount* packets_dropped); - - private: - // Initialize the internal state of the reader. - void Initialize(); - - // Reads and dispatches many packets using recvmmsg. - bool ReadAndDispatchManyPackets(int fd, - int port, - const QuicClock& clock, - ProcessPacketInterface* processor, - QuicPacketCount* packets_dropped); - - // Reads and dispatches a single packet using recvmsg. - static bool ReadAndDispatchSinglePacket(int fd, - int port, - const QuicClock& clock, - ProcessPacketInterface* processor, - QuicPacketCount* packets_dropped); - - // Storage only used when recvmmsg is available. - -#if MMSG_MORE - // TODO(danzh): change it to be a pointer to avoid the allocation on the stack - // from exceeding maximum allowed frame size. - // packets_ and mmsg_hdr_ are used to supply cbuf and buf to the recvmmsg - // call. - - struct PacketData { - iovec iov; - // raw_address is used for address information provided by the recvmmsg - // call on the packets. - struct sockaddr_storage raw_address; - // cbuf is used for ancillary data from the kernel on recvmmsg. - char cbuf[QuicSocketUtils::kSpaceForCmsg]; - // buf is used for the data read from the kernel on recvmmsg. - char buf[kMaxPacketSize]; - }; - PacketData packets_[kNumPacketsPerReadMmsgCall]; - mmsghdr mmsg_hdr_[kNumPacketsPerReadMmsgCall]; -#endif - - DISALLOW_COPY_AND_ASSIGN(QuicPacketReader); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_PACKET_READER_H_ diff --git a/chromium/net/tools/quic/quic_packet_writer_wrapper.cc b/chromium/net/tools/quic/quic_packet_writer_wrapper.cc deleted file mode 100644 index 42f7d0a1ee3..00000000000 --- a/chromium/net/tools/quic/quic_packet_writer_wrapper.cc +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_packet_writer_wrapper.h" - -#include "net/quic/core/quic_types.h" - -namespace net { - -QuicPacketWriterWrapper::QuicPacketWriterWrapper() = default; - -QuicPacketWriterWrapper::~QuicPacketWriterWrapper() = default; - -WriteResult QuicPacketWriterWrapper::WritePacket( - const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address, - PerPacketOptions* options) { - return writer_->WritePacket(buffer, buf_len, self_address, peer_address, - options); -} - -bool QuicPacketWriterWrapper::IsWriteBlockedDataBuffered() const { - return writer_->IsWriteBlockedDataBuffered(); -} - -bool QuicPacketWriterWrapper::IsWriteBlocked() const { - return writer_->IsWriteBlocked(); -} - -void QuicPacketWriterWrapper::SetWritable() { - writer_->SetWritable(); -} - -QuicByteCount QuicPacketWriterWrapper::GetMaxPacketSize( - const QuicSocketAddress& peer_address) const { - return writer_->GetMaxPacketSize(peer_address); -} - -void QuicPacketWriterWrapper::set_writer(QuicPacketWriter* writer) { - writer_.reset(writer); -} - -} // namespace net diff --git a/chromium/net/tools/quic/quic_packet_writer_wrapper.h b/chromium/net/tools/quic/quic_packet_writer_wrapper.h deleted file mode 100644 index 72273181fcb..00000000000 --- a/chromium/net/tools/quic/quic_packet_writer_wrapper.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_QUIC_PACKET_WRITER_WRAPPER_H_ -#define NET_TOOLS_QUIC_QUIC_PACKET_WRITER_WRAPPER_H_ - -#include <stddef.h> - -#include <memory> - -#include "base/macros.h" -#include "net/quic/core/quic_packet_writer.h" - -namespace net { - -// Wraps a writer object to allow dynamically extending functionality. Use -// cases: replace writer while dispatcher and connections hold on to the -// wrapper; mix in monitoring; mix in mocks in unit tests. -class QuicPacketWriterWrapper : public QuicPacketWriter { - public: - QuicPacketWriterWrapper(); - ~QuicPacketWriterWrapper() override; - - // Default implementation of the QuicPacketWriter interface. Passes everything - // to |writer_|. - WriteResult WritePacket(const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address, - PerPacketOptions* options) override; - bool IsWriteBlockedDataBuffered() const override; - bool IsWriteBlocked() const override; - void SetWritable() override; - QuicByteCount GetMaxPacketSize( - const QuicSocketAddress& peer_address) const override; - - // Takes ownership of |writer|. - void set_writer(QuicPacketWriter* writer); - - virtual void set_peer_address(const QuicSocketAddress& peer_address) {} - - QuicPacketWriter* writer() { return writer_.get(); } - - private: - std::unique_ptr<QuicPacketWriter> writer_; - - DISALLOW_COPY_AND_ASSIGN(QuicPacketWriterWrapper); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_PACKET_WRITER_WRAPPER_H_ diff --git a/chromium/net/tools/quic/quic_per_connection_packet_writer.cc b/chromium/net/tools/quic/quic_per_connection_packet_writer.cc deleted file mode 100644 index c9d3b514c3c..00000000000 --- a/chromium/net/tools/quic/quic_per_connection_packet_writer.cc +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_per_connection_packet_writer.h" - -namespace net { - -QuicPerConnectionPacketWriter::QuicPerConnectionPacketWriter( - QuicPacketWriter* shared_writer) - : shared_writer_(shared_writer) {} - -QuicPerConnectionPacketWriter::~QuicPerConnectionPacketWriter() = default; - -WriteResult QuicPerConnectionPacketWriter::WritePacket( - const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address, - PerPacketOptions* options) { - return shared_writer_->WritePacket(buffer, buf_len, self_address, - peer_address, options); -} - -bool QuicPerConnectionPacketWriter::IsWriteBlockedDataBuffered() const { - return shared_writer_->IsWriteBlockedDataBuffered(); -} - -bool QuicPerConnectionPacketWriter::IsWriteBlocked() const { - return shared_writer_->IsWriteBlocked(); -} - -void QuicPerConnectionPacketWriter::SetWritable() { - shared_writer_->SetWritable(); -} - -QuicByteCount QuicPerConnectionPacketWriter::GetMaxPacketSize( - const QuicSocketAddress& peer_address) const { - return shared_writer_->GetMaxPacketSize(peer_address); -} - -} // namespace net diff --git a/chromium/net/tools/quic/quic_per_connection_packet_writer.h b/chromium/net/tools/quic/quic_per_connection_packet_writer.h deleted file mode 100644 index 35e9131460e..00000000000 --- a/chromium/net/tools/quic/quic_per_connection_packet_writer.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_QUIC_PER_CONNECTION_PACKET_WRITER_H_ -#define NET_TOOLS_QUIC_QUIC_PER_CONNECTION_PACKET_WRITER_H_ - -#include <stddef.h> - -#include "base/macros.h" -#include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_packet_writer.h" - -namespace net { - -// A connection-specific packet writer that wraps a shared writer. -class QuicPerConnectionPacketWriter : public QuicPacketWriter { - public: - // Does not take ownership of |shared_writer|. - explicit QuicPerConnectionPacketWriter(QuicPacketWriter* shared_writer); - ~QuicPerConnectionPacketWriter() override; - - // Default implementation of the QuicPacketWriter interface: Passes everything - // to |shared_writer_|. - WriteResult WritePacket(const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address, - PerPacketOptions* options) override; - bool IsWriteBlockedDataBuffered() const override; - bool IsWriteBlocked() const override; - void SetWritable() override; - QuicByteCount GetMaxPacketSize( - const QuicSocketAddress& peer_address) const override; - - private: - QuicPacketWriter* shared_writer_; // Not owned. - - DISALLOW_COPY_AND_ASSIGN(QuicPerConnectionPacketWriter); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_PER_CONNECTION_PACKET_WRITER_H_ diff --git a/chromium/net/tools/quic/quic_process_packet_interface.h b/chromium/net/tools/quic/quic_process_packet_interface.h deleted file mode 100644 index e960788d4c2..00000000000 --- a/chromium/net/tools/quic/quic_process_packet_interface.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2015 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_TOOLS_QUIC_QUIC_PROCESS_PACKET_INTERFACE_H_ -#define NET_TOOLS_QUIC_QUIC_PROCESS_PACKET_INTERFACE_H_ - -#include "base/macros.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/platform/api/quic_socket_address.h" - -namespace net { - -// A class to process each incoming packet. -class ProcessPacketInterface { - public: - virtual ~ProcessPacketInterface() {} - virtual void ProcessPacket(const QuicSocketAddress& server_address, - const QuicSocketAddress& client_address, - const QuicReceivedPacket& packet) = 0; -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_PROCESS_PACKET_INTERFACE_H_ diff --git a/chromium/net/tools/quic/quic_reject_reason_decoder_bin.cc b/chromium/net/tools/quic/quic_reject_reason_decoder_bin.cc deleted file mode 100644 index 96d63e6656f..00000000000 --- a/chromium/net/tools/quic/quic_reject_reason_decoder_bin.cc +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Decodes the packet HandshakeFailureReason from the chromium histogram -// Net.QuicClientHelloRejectReasons - -#include <iostream> - -#include "base/command_line.h" -#include "base/strings/string_number_conversions.h" -#include "net/quic/core/crypto/crypto_handshake.h" -#include "net/quic/core/crypto/crypto_utils.h" - -using base::CommandLine; -using net::HandshakeFailureReason; -using net::CryptoUtils; -using net::MAX_FAILURE_REASON; - -int main(int argc, char* argv[]) { - CommandLine::Init(argc, argv); - CommandLine* line = CommandLine::ForCurrentProcess(); - const CommandLine::StringVector& args = line->GetArgs(); - - if (args.size() != 1) { - std::cerr << "Missing argument (Usage: " << argv[0] << " <packed_reason>\n"; - return 1; - } - - uint32_t packed_error = 0; - if (!base::StringToUint(args[0], &packed_error)) { - std::cerr << "Unable to parse: " << args[0] << "\n"; - return 2; - } - - for (int i = 1; i < MAX_FAILURE_REASON; ++i) { - if ((packed_error & (1 << (i - 1))) == 0) { - continue; - } - HandshakeFailureReason reason = static_cast<HandshakeFailureReason>(i); - std::cout << CryptoUtils::HandshakeFailureReasonToString(reason) << "\n"; - } - return 0; -} diff --git a/chromium/net/tools/quic/quic_server.cc b/chromium/net/tools/quic/quic_server.cc deleted file mode 100644 index 45269bdd489..00000000000 --- a/chromium/net/tools/quic/quic_server.cc +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_server.h" - -#include <errno.h> -#include <features.h> -#include <netinet/in.h> -#include <string.h> -#include <sys/epoll.h> -#include <sys/socket.h> - -#include <memory> - -#include "net/quic/core/crypto/crypto_handshake.h" -#include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_crypto_stream.h" -#include "net/quic/core/quic_data_reader.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/core/tls_server_handshaker.h" -#include "net/quic/platform/api/quic_clock.h" -#include "net/quic/platform/api/quic_flags.h" -#include "net/quic/platform/api/quic_logging.h" -#include "net/tools/quic/platform/impl/quic_epoll_clock.h" -#include "net/tools/quic/platform/impl/quic_socket_utils.h" -#include "net/tools/quic/quic_dispatcher.h" -#include "net/tools/quic/quic_epoll_alarm_factory.h" -#include "net/tools/quic/quic_epoll_connection_helper.h" -#include "net/tools/quic/quic_http_response_cache.h" -#include "net/tools/quic/quic_packet_reader.h" -#include "net/tools/quic/quic_simple_crypto_server_stream_helper.h" -#include "net/tools/quic/quic_simple_dispatcher.h" - -#ifndef SO_RXQ_OVFL -#define SO_RXQ_OVFL 40 -#endif - -namespace net { - -namespace { - -// Specifies the directory used during QuicHttpResponseCache -// construction to seed the cache. Cache directory can be -// generated using `wget -p --save-headers <url>` -std::string FLAGS_quic_response_cache_dir = ""; - -const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET; -const char kSourceAddressTokenSecret[] = "secret"; - -} // namespace - -const size_t kNumSessionsToCreatePerSocketEvent = 16; - -QuicServer::QuicServer(std::unique_ptr<ProofSource> proof_source, - QuicHttpResponseCache* response_cache) - : QuicServer(std::move(proof_source), - QuicConfig(), - QuicCryptoServerConfig::ConfigOptions(), - AllSupportedVersions(), - response_cache) {} - -QuicServer::QuicServer( - std::unique_ptr<ProofSource> proof_source, - const QuicConfig& config, - const QuicCryptoServerConfig::ConfigOptions& crypto_config_options, - const ParsedQuicVersionVector& supported_versions, - QuicHttpResponseCache* response_cache) - : port_(0), - fd_(-1), - packets_dropped_(0), - overflow_supported_(false), - silent_close_(false), - config_(config), - crypto_config_(kSourceAddressTokenSecret, - QuicRandom::GetInstance(), - std::move(proof_source), - TlsServerHandshaker::CreateSslCtx()), - crypto_config_options_(crypto_config_options), - version_manager_(supported_versions), - packet_reader_(new QuicPacketReader()), - response_cache_(response_cache) { - Initialize(); -} - -void QuicServer::Initialize() { - // If an initial flow control window has not explicitly been set, then use a - // sensible value for a server: 1 MB for session, 64 KB for each stream. - const uint32_t kInitialSessionFlowControlWindow = 1 * 1024 * 1024; // 1 MB - const uint32_t kInitialStreamFlowControlWindow = 64 * 1024; // 64 KB - if (config_.GetInitialStreamFlowControlWindowToSend() == - kMinimumFlowControlSendWindow) { - config_.SetInitialStreamFlowControlWindowToSend( - kInitialStreamFlowControlWindow); - } - if (config_.GetInitialSessionFlowControlWindowToSend() == - kMinimumFlowControlSendWindow) { - config_.SetInitialSessionFlowControlWindowToSend( - kInitialSessionFlowControlWindow); - } - - epoll_server_.set_timeout_in_us(50 * 1000); - - if (!FLAGS_quic_response_cache_dir.empty()) { - response_cache_->InitializeFromDirectory(FLAGS_quic_response_cache_dir); - } - - QuicEpollClock clock(&epoll_server_); - - std::unique_ptr<CryptoHandshakeMessage> scfg(crypto_config_.AddDefaultConfig( - QuicRandom::GetInstance(), &clock, crypto_config_options_)); -} - -QuicServer::~QuicServer() = default; - -bool QuicServer::CreateUDPSocketAndListen(const QuicSocketAddress& address) { - fd_ = QuicSocketUtils::CreateUDPSocket( - address, - /*receive_buffer_size =*/kDefaultSocketReceiveBuffer, - /*send_buffer_size =*/kDefaultSocketReceiveBuffer, &overflow_supported_); - if (fd_ < 0) { - QUIC_LOG(ERROR) << "CreateSocket() failed: " << strerror(errno); - return false; - } - - sockaddr_storage addr = address.generic_address(); - int rc = bind(fd_, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)); - if (rc < 0) { - QUIC_LOG(ERROR) << "Bind failed: " << strerror(errno); - return false; - } - QUIC_LOG(INFO) << "Listening on " << address.ToString(); - port_ = address.port(); - if (port_ == 0) { - QuicSocketAddress address; - if (address.FromSocket(fd_) != 0) { - QUIC_LOG(ERROR) << "Unable to get self address. Error: " - << strerror(errno); - } - port_ = address.port(); - } - - epoll_server_.RegisterFD(fd_, this, kEpollFlags); - dispatcher_.reset(CreateQuicDispatcher()); - dispatcher_->InitializeWithWriter(CreateWriter(fd_)); - - return true; -} - -QuicDefaultPacketWriter* QuicServer::CreateWriter(int fd) { - return new QuicDefaultPacketWriter(fd); -} - -QuicDispatcher* QuicServer::CreateQuicDispatcher() { - QuicEpollAlarmFactory alarm_factory(&epoll_server_); - return new QuicSimpleDispatcher( - config_, &crypto_config_, &version_manager_, - std::unique_ptr<QuicEpollConnectionHelper>(new QuicEpollConnectionHelper( - &epoll_server_, QuicAllocator::BUFFER_POOL)), - std::unique_ptr<QuicCryptoServerStream::Helper>( - new QuicSimpleCryptoServerStreamHelper(QuicRandom::GetInstance())), - std::unique_ptr<QuicEpollAlarmFactory>( - new QuicEpollAlarmFactory(&epoll_server_)), - response_cache_); -} - -void QuicServer::WaitForEvents() { - epoll_server_.WaitForEventsAndExecuteCallbacks(); -} - -void QuicServer::Shutdown() { - if (!silent_close_) { - // Before we shut down the epoll server, give all active sessions a chance - // to notify clients that they're closing. - dispatcher_->Shutdown(); - } - - close(fd_); - fd_ = -1; -} - -void QuicServer::OnEvent(int fd, EpollEvent* event) { - DCHECK_EQ(fd, fd_); - event->out_ready_mask = 0; - - if (event->in_events & EPOLLIN) { - QUIC_DVLOG(1) << "EPOLLIN"; - - dispatcher_->ProcessBufferedChlos(kNumSessionsToCreatePerSocketEvent); - - bool more_to_read = true; - while (more_to_read) { - more_to_read = packet_reader_->ReadAndDispatchPackets( - fd_, port_, QuicEpollClock(&epoll_server_), dispatcher_.get(), - overflow_supported_ ? &packets_dropped_ : nullptr); - } - - if (dispatcher_->HasChlosBuffered()) { - // Register EPOLLIN event to consume buffered CHLO(s). - event->out_ready_mask |= EPOLLIN; - } - } - if (event->in_events & EPOLLOUT) { - dispatcher_->OnCanWrite(); - if (dispatcher_->HasPendingWrites()) { - event->out_ready_mask |= EPOLLOUT; - } - } - if (event->in_events & EPOLLERR) { - } -} - -} // namespace net diff --git a/chromium/net/tools/quic/quic_server.h b/chromium/net/tools/quic/quic_server.h deleted file mode 100644 index e284941dc4d..00000000000 --- a/chromium/net/tools/quic/quic_server.h +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// A toy server, which listens on a specified address for QUIC traffic and -// handles incoming responses. -// -// Note that this server is intended to verify correctness of the client and is -// in no way expected to be performant. - -#ifndef NET_TOOLS_QUIC_QUIC_SERVER_H_ -#define NET_TOOLS_QUIC_QUIC_SERVER_H_ - -#include <memory> - -#include "base/macros.h" -#include "net/quic/chromium/quic_chromium_connection_helper.h" -#include "net/quic/core/crypto/quic_crypto_server_config.h" -#include "net/quic/core/quic_config.h" -#include "net/quic/core/quic_framer.h" -#include "net/quic/core/quic_version_manager.h" -#include "net/quic/platform/api/quic_socket_address.h" -#include "net/tools/epoll_server/epoll_server.h" -#include "net/tools/quic/quic_default_packet_writer.h" -#include "net/tools/quic/quic_http_response_cache.h" - -namespace net { - -namespace test { -class QuicServerPeer; -} // namespace test - -class QuicDispatcher; -class QuicPacketReader; - -class QuicServer : public EpollCallbackInterface { - public: - QuicServer(std::unique_ptr<ProofSource> proof_source, - QuicHttpResponseCache* response_cache); - QuicServer(std::unique_ptr<ProofSource> proof_source, - const QuicConfig& config, - const QuicCryptoServerConfig::ConfigOptions& server_config_options, - const ParsedQuicVersionVector& supported_versions, - QuicHttpResponseCache* response_cache); - - ~QuicServer() override; - - // Start listening on the specified address. - bool CreateUDPSocketAndListen(const QuicSocketAddress& address); - - // Wait up to 50ms, and handle any events which occur. - void WaitForEvents(); - - // Server deletion is imminent. Start cleaning up the epoll server. - virtual void Shutdown(); - - // From EpollCallbackInterface - void OnRegistration(EpollServer* eps, int fd, int event_mask) override {} - void OnModification(int fd, int event_mask) override {} - void OnEvent(int fd, EpollEvent* event) override; - void OnUnregistration(int fd, bool replaced) override {} - - void OnShutdown(EpollServer* eps, int fd) override {} - - void SetChloMultiplier(size_t multiplier) { - crypto_config_.set_chlo_multiplier(multiplier); - } - - bool overflow_supported() { return overflow_supported_; } - - QuicPacketCount packets_dropped() { return packets_dropped_; } - - int port() { return port_; } - - protected: - virtual QuicDefaultPacketWriter* CreateWriter(int fd); - - virtual QuicDispatcher* CreateQuicDispatcher(); - - const QuicConfig& config() const { return config_; } - const QuicCryptoServerConfig& crypto_config() const { return crypto_config_; } - EpollServer* epoll_server() { return &epoll_server_; } - - QuicDispatcher* dispatcher() { return dispatcher_.get(); } - - QuicVersionManager* version_manager() { return &version_manager_; } - - QuicHttpResponseCache* response_cache() { return response_cache_; } - - void set_silent_close(bool value) { silent_close_ = value; } - - private: - friend class net::test::QuicServerPeer; - - // Initialize the internal state of the server. - void Initialize(); - - // Accepts data from the framer and demuxes clients to sessions. - std::unique_ptr<QuicDispatcher> dispatcher_; - // Frames incoming packets and hands them to the dispatcher. - EpollServer epoll_server_; - - // The port the server is listening on. - int port_; - - // Listening connection. Also used for outbound client communication. - int fd_; - - // If overflow_supported_ is true this will be the number of packets dropped - // during the lifetime of the server. This may overflow if enough packets - // are dropped. - QuicPacketCount packets_dropped_; - - // True if the kernel supports SO_RXQ_OVFL, the number of packets dropped - // because the socket would otherwise overflow. - bool overflow_supported_; - - // If true, do not call Shutdown on the dispatcher. Connections will close - // without sending a final connection close. - bool silent_close_; - - // config_ contains non-crypto parameters that are negotiated in the crypto - // handshake. - QuicConfig config_; - // crypto_config_ contains crypto parameters for the handshake. - QuicCryptoServerConfig crypto_config_; - // crypto_config_options_ contains crypto parameters for the handshake. - QuicCryptoServerConfig::ConfigOptions crypto_config_options_; - - // Used to generate current supported versions. - QuicVersionManager version_manager_; - - // Point to a QuicPacketReader object on the heap. The reader allocates more - // space than allowed on the stack. - std::unique_ptr<QuicPacketReader> packet_reader_; - - QuicHttpResponseCache* response_cache_; // unowned. - - DISALLOW_COPY_AND_ASSIGN(QuicServer); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_SERVER_H_ diff --git a/chromium/net/tools/quic/quic_server_bin.cc b/chromium/net/tools/quic/quic_server_bin.cc deleted file mode 100644 index c3d2291b9cb..00000000000 --- a/chromium/net/tools/quic/quic_server_bin.cc +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// A binary wrapper for QuicServer. It listens forever on --port -// (default 6121) until it's killed or ctrl-cd to death. - -#include <iostream> - -#include "base/at_exit.h" -#include "base/command_line.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/strings/string_number_conversions.h" -#include "base/task_scheduler/task_scheduler.h" -#include "net/quic/chromium/crypto/proof_source_chromium.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/platform/api/quic_socket_address.h" -#include "net/tools/quic/quic_http_response_cache.h" -#include "net/tools/quic/quic_server.h" - -// The port the quic server will listen on. -int32_t FLAGS_port = 6121; - -std::unique_ptr<net::ProofSource> CreateProofSource( - const base::FilePath& cert_path, - const base::FilePath& key_path) { - std::unique_ptr<net::ProofSourceChromium> proof_source( - new net::ProofSourceChromium()); - CHECK(proof_source->Initialize(cert_path, key_path, base::FilePath())); - return std::move(proof_source); -} - -int main(int argc, char* argv[]) { - base::AtExitManager exit_manager; - base::CommandLine::Init(argc, argv); - base::CommandLine* line = base::CommandLine::ForCurrentProcess(); - - base::MessageLoopForIO message_loop; - base::TaskScheduler::CreateAndStartWithDefaultParams("quic_server"); - - logging::LoggingSettings settings; - settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; - CHECK(logging::InitLogging(settings)); - - if (line->HasSwitch("h") || line->HasSwitch("help")) { - const char* help_str = - "Usage: quic_server [options]\n" - "\n" - "Options:\n" - "-h, --help show this help message and exit\n" - "--port=<port> specify the port to listen on\n" - "--quic_response_cache_dir directory containing response data\n" - " to load\n" - "--certificate_file=<file> path to the certificate chain\n" - "--key_file=<file> path to the pkcs8 private key\n"; - std::cout << help_str; - exit(0); - } - - net::QuicHttpResponseCache response_cache; - if (line->HasSwitch("quic_response_cache_dir")) { - response_cache.InitializeFromDirectory( - line->GetSwitchValueASCII("quic_response_cache_dir")); - } - - if (line->HasSwitch("port")) { - if (!base::StringToInt(line->GetSwitchValueASCII("port"), &FLAGS_port)) { - LOG(ERROR) << "--port must be an integer\n"; - return 1; - } - } - - if (!line->HasSwitch("certificate_file")) { - LOG(ERROR) << "missing --certificate_file"; - return 1; - } - - if (!line->HasSwitch("key_file")) { - LOG(ERROR) << "missing --key_file"; - return 1; - } - - net::QuicConfig config; - net::QuicServer server( - CreateProofSource(line->GetSwitchValuePath("certificate_file"), - line->GetSwitchValuePath("key_file")), - config, net::QuicCryptoServerConfig::ConfigOptions(), - net::AllSupportedVersions(), &response_cache); - - int rc = server.CreateUDPSocketAndListen( - net::QuicSocketAddress(net::QuicIpAddress::Any6(), FLAGS_port)); - if (rc < 0) { - return 1; - } - - while (true) { - server.WaitForEvents(); - } -} diff --git a/chromium/net/tools/quic/quic_server_test.cc b/chromium/net/tools/quic/quic_server_test.cc deleted file mode 100644 index df80fa7d7b4..00000000000 --- a/chromium/net/tools/quic/quic_server_test.cc +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_server.h" - -#include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_utils.h" -#include "net/quic/core/tls_server_handshaker.h" -#include "net/quic/platform/api/quic_arraysize.h" -#include "net/quic/platform/api/quic_flags.h" -#include "net/quic/platform/api/quic_logging.h" -#include "net/quic/platform/api/quic_socket_address.h" -#include "net/quic/platform/api/quic_test.h" -#include "net/quic/platform/api/quic_test_loopback.h" -#include "net/quic/test_tools/crypto_test_utils.h" -#include "net/quic/test_tools/mock_quic_dispatcher.h" -#include "net/tools/quic/quic_epoll_alarm_factory.h" -#include "net/tools/quic/quic_epoll_connection_helper.h" -#include "net/tools/quic/quic_simple_crypto_server_stream_helper.h" -#include "net/tools/quic/test_tools/quic_server_peer.h" - -using ::testing::_; - -namespace net { -namespace test { - -namespace { - -class MockQuicSimpleDispatcher : public QuicSimpleDispatcher { - public: - MockQuicSimpleDispatcher( - const QuicConfig& config, - const QuicCryptoServerConfig* crypto_config, - QuicVersionManager* version_manager, - std::unique_ptr<QuicConnectionHelperInterface> helper, - std::unique_ptr<QuicCryptoServerStream::Helper> session_helper, - std::unique_ptr<QuicAlarmFactory> alarm_factory, - QuicHttpResponseCache* response_cache) - : QuicSimpleDispatcher(config, - crypto_config, - version_manager, - std::move(helper), - std::move(session_helper), - std::move(alarm_factory), - response_cache) {} - ~MockQuicSimpleDispatcher() override = default; - - MOCK_METHOD0(OnCanWrite, void()); - MOCK_CONST_METHOD0(HasPendingWrites, bool()); - MOCK_CONST_METHOD0(HasChlosBuffered, bool()); - MOCK_METHOD1(ProcessBufferedChlos, void(size_t)); -}; - -class TestQuicServer : public QuicServer { - public: - TestQuicServer() - : QuicServer(crypto_test_utils::ProofSourceForTesting(), - &response_cache_) {} - - ~TestQuicServer() override = default; - - MockQuicSimpleDispatcher* mock_dispatcher() { return mock_dispatcher_; } - - protected: - QuicDispatcher* CreateQuicDispatcher() override { - mock_dispatcher_ = new MockQuicSimpleDispatcher( - config(), &crypto_config(), version_manager(), - std::unique_ptr<QuicEpollConnectionHelper>( - new QuicEpollConnectionHelper(epoll_server(), - QuicAllocator::BUFFER_POOL)), - std::unique_ptr<QuicCryptoServerStream::Helper>( - new QuicSimpleCryptoServerStreamHelper(QuicRandom::GetInstance())), - std::unique_ptr<QuicEpollAlarmFactory>( - new QuicEpollAlarmFactory(epoll_server())), - &response_cache_); - return mock_dispatcher_; - } - - MockQuicSimpleDispatcher* mock_dispatcher_ = nullptr; - QuicHttpResponseCache response_cache_; -}; - -class QuicServerEpollInTest : public QuicTest { - public: - QuicServerEpollInTest() - : port_(net::test::kTestPort), - server_address_(QuicIpAddress::Loopback4(), port_) {} - - void StartListening() { - server_.CreateUDPSocketAndListen(server_address_); - ASSERT_TRUE(QuicServerPeer::SetSmallSocket(&server_)); - - if (!server_.overflow_supported()) { - QUIC_LOG(WARNING) << "Overflow not supported. Not testing."; - return; - } - } - - protected: - int port_; - QuicSocketAddress server_address_; - TestQuicServer server_; -}; - -// Tests that if dispatcher has CHLOs waiting for connection creation, EPOLLIN -// event should try to create connections for them. And set epoll mask with -// EPOLLIN if there are still CHLOs remaining at the end of epoll event. -TEST_F(QuicServerEpollInTest, ProcessBufferedCHLOsOnEpollin) { - // Given an EPOLLIN event, try to create session for buffered CHLOs. In first - // event, dispatcher can't create session for all of CHLOs. So listener should - // register another EPOLLIN event by itself. Even without new packet arrival, - // the rest CHLOs should be process in next epoll event. - StartListening(); - bool more_chlos = true; - MockQuicSimpleDispatcher* dispatcher_ = server_.mock_dispatcher(); - DCHECK(dispatcher_ != nullptr); - EXPECT_CALL(*dispatcher_, OnCanWrite()).Times(testing::AnyNumber()); - EXPECT_CALL(*dispatcher_, ProcessBufferedChlos(_)).Times(2); - EXPECT_CALL(*dispatcher_, HasPendingWrites()).Times(testing::AnyNumber()); - // Expect there are still CHLOs buffered after 1st event. But not any more - // after 2nd event. - EXPECT_CALL(*dispatcher_, HasChlosBuffered()) - .WillOnce(testing::Return(true)) - .WillOnce( - DoAll(testing::Assign(&more_chlos, false), testing::Return(false))); - - // Send a packet to trigger epoll event. - int fd = socket( - AddressFamilyUnderTest() == IpAddressFamily::IP_V4 ? AF_INET : AF_INET6, - SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); - ASSERT_LT(0, fd); - - char buf[1024]; - memset(buf, 0, QUIC_ARRAYSIZE(buf)); - sockaddr_storage storage = server_address_.generic_address(); - int rc = sendto(fd, buf, QUIC_ARRAYSIZE(buf), 0, - reinterpret_cast<sockaddr*>(&storage), sizeof(storage)); - if (rc < 0) { - QUIC_DLOG(INFO) << errno << " " << strerror(errno); - } - - while (more_chlos) { - server_.WaitForEvents(); - } -} - -class QuicServerDispatchPacketTest : public QuicTest { - public: - QuicServerDispatchPacketTest() - : crypto_config_("blah", - QuicRandom::GetInstance(), - crypto_test_utils::ProofSourceForTesting(), - TlsServerHandshaker::CreateSslCtx()), - version_manager_(AllSupportedVersions()), - dispatcher_( - config_, - &crypto_config_, - &version_manager_, - std::unique_ptr<QuicEpollConnectionHelper>( - new QuicEpollConnectionHelper(&eps_, - QuicAllocator::BUFFER_POOL)), - std::unique_ptr<QuicCryptoServerStream::Helper>( - new QuicSimpleCryptoServerStreamHelper( - QuicRandom::GetInstance())), - std::unique_ptr<QuicEpollAlarmFactory>( - new QuicEpollAlarmFactory(&eps_)), - &response_cache_) { - dispatcher_.InitializeWithWriter(new QuicDefaultPacketWriter(1234)); - } - - void DispatchPacket(const QuicReceivedPacket& packet) { - QuicSocketAddress client_addr, server_addr; - dispatcher_.ProcessPacket(server_addr, client_addr, packet); - } - - protected: - QuicConfig config_; - QuicCryptoServerConfig crypto_config_; - QuicVersionManager version_manager_; - EpollServer eps_; - QuicHttpResponseCache response_cache_; - MockQuicDispatcher dispatcher_; -}; - -TEST_F(QuicServerDispatchPacketTest, DispatchPacket) { - // clang-format off - unsigned char valid_packet[] = { - // public flags (8 byte connection_id) - 0x3C, - // connection_id - 0x10, 0x32, 0x54, 0x76, - 0x98, 0xBA, 0xDC, 0xFE, - // packet number - 0xBC, 0x9A, 0x78, 0x56, - 0x34, 0x12, - // private flags - 0x00 - }; - // clang-format on - QuicReceivedPacket encrypted_valid_packet( - reinterpret_cast<char*>(valid_packet), QUIC_ARRAYSIZE(valid_packet), - QuicTime::Zero(), false); - - EXPECT_CALL(dispatcher_, ProcessPacket(_, _, _)).Times(1); - DispatchPacket(encrypted_valid_packet); -} - -} // namespace -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/quic_simple_client.cc b/chromium/net/tools/quic/quic_simple_client.cc index 1273c1bed19..dbd6fff4b4a 100644 --- a/chromium/net/tools/quic/quic_simple_client.cc +++ b/chromium/net/tools/quic/quic_simple_client.cc @@ -18,16 +18,16 @@ #include "net/quic/chromium/quic_chromium_connection_helper.h" #include "net/quic/chromium/quic_chromium_packet_reader.h" #include "net/quic/chromium/quic_chromium_packet_writer.h" -#include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/core/quic_server_id.h" -#include "net/quic/core/spdy_utils.h" -#include "net/quic/platform/api/quic_flags.h" -#include "net/quic/platform/api/quic_ptr_util.h" #include "net/socket/udp_client_socket.h" -#include "net/spdy/chromium/spdy_http_utils.h" -#include "net/spdy/core/spdy_header_block.h" +#include "net/spdy/spdy_http_utils.h" +#include "net/third_party/quic/core/crypto/quic_random.h" +#include "net/third_party/quic/core/quic_connection.h" +#include "net/third_party/quic/core/quic_packets.h" +#include "net/third_party/quic/core/quic_server_id.h" +#include "net/third_party/quic/core/spdy_utils.h" +#include "net/third_party/quic/platform/api/quic_flags.h" +#include "net/third_party/quic/platform/api/quic_ptr_util.h" +#include "net/third_party/spdy/core/spdy_header_block.h" using std::string; diff --git a/chromium/net/tools/quic/quic_simple_client.h b/chromium/net/tools/quic/quic_simple_client.h index 8f17f68a1d9..d3329f6598d 100644 --- a/chromium/net/tools/quic/quic_simple_client.h +++ b/chromium/net/tools/quic/quic_simple_client.h @@ -20,11 +20,11 @@ #include "net/http/http_response_headers.h" #include "net/log/net_log.h" #include "net/quic/chromium/quic_chromium_packet_reader.h" -#include "net/quic/core/quic_config.h" -#include "net/quic/core/quic_spdy_stream.h" -#include "net/quic/platform/impl/quic_chromium_clock.h" +#include "net/third_party/quic/core/quic_config.h" +#include "net/third_party/quic/core/quic_spdy_stream.h" +#include "net/third_party/quic/platform/impl/quic_chromium_clock.h" +#include "net/third_party/quic/tools/quic_spdy_client_base.h" #include "net/tools/quic/quic_client_message_loop_network_helper.h" -#include "net/tools/quic/quic_spdy_client_base.h" namespace net { diff --git a/chromium/net/tools/quic/quic_simple_client_bin.cc b/chromium/net/tools/quic/quic_simple_client_bin.cc index f14f2aacf34..f21ef04445c 100644 --- a/chromium/net/tools/quic/quic_simple_client_bin.cc +++ b/chromium/net/tools/quic/quic_simple_client_bin.cc @@ -48,34 +48,33 @@ #include "net/base/net_errors.h" #include "net/base/privacy_mode.h" #include "net/cert/cert_verifier.h" -#include "net/cert/ct_known_logs.h" #include "net/cert/ct_log_verifier.h" +#include "net/cert/ct_policy_enforcer.h" #include "net/cert/multi_log_ct_verifier.h" #include "net/http/transport_security_state.h" #include "net/quic/chromium/crypto/proof_verifier_chromium.h" -#include "net/quic/core/quic_error_codes.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/core/quic_server_id.h" -#include "net/quic/platform/api/quic_socket_address.h" -#include "net/quic/platform/api/quic_str_cat.h" -#include "net/quic/platform/api/quic_string_piece.h" -#include "net/quic/platform/api/quic_text_utils.h" -#include "net/spdy/chromium/spdy_http_utils.h" -#include "net/spdy/core/spdy_header_block.h" +#include "net/spdy/spdy_http_utils.h" +#include "net/third_party/quic/core/quic_error_codes.h" +#include "net/third_party/quic/core/quic_packets.h" +#include "net/third_party/quic/core/quic_server_id.h" +#include "net/third_party/quic/platform/api/quic_socket_address.h" +#include "net/third_party/quic/platform/api/quic_str_cat.h" +#include "net/third_party/quic/platform/api/quic_string_piece.h" +#include "net/third_party/quic/platform/api/quic_text_utils.h" +#include "net/third_party/spdy/core/spdy_header_block.h" #include "net/tools/quic/quic_simple_client.h" #include "net/tools/quic/synchronous_host_resolver.h" #include "url/gurl.h" using net::CertVerifier; -using net::CTPolicyEnforcer; using net::CTVerifier; using net::MultiLogCTVerifier; using net::ProofVerifier; using net::ProofVerifierChromium; using net::QuicStringPiece; using net::QuicTextUtils; -using net::SpdyHeaderBlock; using net::TransportSecurityState; +using spdy::SpdyHeaderBlock; using std::cout; using std::cerr; using std::endl; @@ -266,8 +265,8 @@ int main(int argc, char* argv[]) { std::unique_ptr<TransportSecurityState> transport_security_state( new TransportSecurityState); std::unique_ptr<MultiLogCTVerifier> ct_verifier(new MultiLogCTVerifier()); - ct_verifier->AddLogs(net::ct::CreateLogVerifiersForKnownLogs()); - std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer(new CTPolicyEnforcer()); + std::unique_ptr<net::CTPolicyEnforcer> ct_policy_enforcer( + new net::DefaultCTPolicyEnforcer()); std::unique_ptr<ProofVerifier> proof_verifier; if (line->HasSwitch("disable-certificate-verification")) { proof_verifier.reset(new FakeProofVerifier()); diff --git a/chromium/net/tools/quic/quic_simple_client_test.cc b/chromium/net/tools/quic/quic_simple_client_test.cc index 16ff1bfa337..39ccbe63625 100644 --- a/chromium/net/tools/quic/quic_simple_client_test.cc +++ b/chromium/net/tools/quic/quic_simple_client_test.cc @@ -5,14 +5,16 @@ #include "net/tools/quic/quic_simple_client.h" #include "base/strings/string_util.h" -#include "net/quic/test_tools/crypto_test_utils.h" -#include "net/quic/test_tools/quic_test_utils.h" +#include "base/test/scoped_task_environment.h" +#include "net/third_party/quic/test_tools/crypto_test_utils.h" +#include "net/third_party/quic/test_tools/quic_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { namespace test { TEST(QuicSimpleClientTest, Initialize) { + base::test::ScopedTaskEnvironment scoped_task_environment; QuicSocketAddress server_address(QuicIpAddress::Loopback4(), 80); QuicServerId server_id("hostname", server_address.port(), PRIVACY_MODE_DISABLED); diff --git a/chromium/net/tools/quic/quic_simple_crypto_server_stream_helper.cc b/chromium/net/tools/quic/quic_simple_crypto_server_stream_helper.cc deleted file mode 100644 index 56afbf82dd4..00000000000 --- a/chromium/net/tools/quic/quic_simple_crypto_server_stream_helper.cc +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_simple_crypto_server_stream_helper.h" - -namespace net { - -QuicSimpleCryptoServerStreamHelper::QuicSimpleCryptoServerStreamHelper( - QuicRandom* random) - : random_(random) {} - -QuicSimpleCryptoServerStreamHelper::~QuicSimpleCryptoServerStreamHelper() = - default; - -QuicConnectionId -QuicSimpleCryptoServerStreamHelper::GenerateConnectionIdForReject( - QuicConnectionId /*connection_id*/) const { - return random_->RandUint64(); -} - -bool QuicSimpleCryptoServerStreamHelper::CanAcceptClientHello( - const CryptoHandshakeMessage& message, - const QuicSocketAddress& self_address, - std::string* error_details) const { - return true; -} - -} // namespace net diff --git a/chromium/net/tools/quic/quic_simple_crypto_server_stream_helper.h b/chromium/net/tools/quic/quic_simple_crypto_server_stream_helper.h deleted file mode 100644 index 31c257df395..00000000000 --- a/chromium/net/tools/quic/quic_simple_crypto_server_stream_helper.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_QUIC_SIMPLE_CRYPTO_SERVER_STREAM_HELPER_H_ -#define NET_TOOLS_QUIC_QUIC_SIMPLE_CRYPTO_SERVER_STREAM_HELPER_H_ - -#include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_crypto_server_stream.h" - -namespace net { - -// Simple helper for server crypto streams which generates a new random -// connection ID for stateless rejects. -class QuicSimpleCryptoServerStreamHelper - : public QuicCryptoServerStream::Helper { - public: - explicit QuicSimpleCryptoServerStreamHelper(QuicRandom* random); - - ~QuicSimpleCryptoServerStreamHelper() override; - - QuicConnectionId GenerateConnectionIdForReject( - QuicConnectionId /*connection_id*/) const override; - - bool CanAcceptClientHello(const CryptoHandshakeMessage& message, - const QuicSocketAddress& self_address, - std::string* error_details) const override; - - private: - QuicRandom* random_; // Unowned. -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_SIMPLE_CRYPTO_SERVER_STREAM_HELPER_H_ diff --git a/chromium/net/tools/quic/quic_simple_dispatcher.cc b/chromium/net/tools/quic/quic_simple_dispatcher.cc deleted file mode 100644 index 1f64cb5d6f4..00000000000 --- a/chromium/net/tools/quic/quic_simple_dispatcher.cc +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_simple_dispatcher.h" - -#include "net/tools/quic/quic_simple_server_session.h" - -namespace net { - -QuicSimpleDispatcher::QuicSimpleDispatcher( - const QuicConfig& config, - const QuicCryptoServerConfig* crypto_config, - QuicVersionManager* version_manager, - std::unique_ptr<QuicConnectionHelperInterface> helper, - std::unique_ptr<QuicCryptoServerStream::Helper> session_helper, - std::unique_ptr<QuicAlarmFactory> alarm_factory, - QuicHttpResponseCache* response_cache) - : QuicDispatcher(config, - crypto_config, - version_manager, - std::move(helper), - std::move(session_helper), - std::move(alarm_factory)), - response_cache_(response_cache) {} - -QuicSimpleDispatcher::~QuicSimpleDispatcher() = default; - -int QuicSimpleDispatcher::GetRstErrorCount( - QuicRstStreamErrorCode error_code) const { - auto it = rst_error_map_.find(error_code); - if (it == rst_error_map_.end()) { - return 0; - } else { - return it->second; - } -} - -void QuicSimpleDispatcher::OnRstStreamReceived( - const QuicRstStreamFrame& frame) { - auto it = rst_error_map_.find(frame.error_code); - if (it == rst_error_map_.end()) { - rst_error_map_.insert(std::make_pair(frame.error_code, 1)); - } else { - it->second++; - } -} - -QuicServerSessionBase* QuicSimpleDispatcher::CreateQuicSession( - QuicConnectionId connection_id, - const QuicSocketAddress& client_address, - QuicStringPiece /*alpn*/) { - // The QuicServerSessionBase takes ownership of |connection| below. - QuicConnection* connection = new QuicConnection( - connection_id, client_address, helper(), alarm_factory(), - CreatePerConnectionWriter(), - /* owns_writer= */ true, Perspective::IS_SERVER, GetSupportedVersions()); - - QuicServerSessionBase* session = new QuicSimpleServerSession( - config(), connection, this, session_helper(), crypto_config(), - compressed_certs_cache(), response_cache_); - session->Initialize(); - return session; -} - -} // namespace net diff --git a/chromium/net/tools/quic/quic_simple_dispatcher.h b/chromium/net/tools/quic/quic_simple_dispatcher.h deleted file mode 100644 index 04e1252684b..00000000000 --- a/chromium/net/tools/quic/quic_simple_dispatcher.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_QUIC_SIMPLE_DISPATCHER_H_ -#define NET_TOOLS_QUIC_QUIC_SIMPLE_DISPATCHER_H_ - -#include "net/quic/core/quic_server_session_base.h" -#include "net/tools/quic/quic_dispatcher.h" -#include "net/tools/quic/quic_http_response_cache.h" - -namespace net { - -class QuicSimpleDispatcher : public QuicDispatcher { - public: - QuicSimpleDispatcher( - const QuicConfig& config, - const QuicCryptoServerConfig* crypto_config, - QuicVersionManager* version_manager, - std::unique_ptr<QuicConnectionHelperInterface> helper, - std::unique_ptr<QuicCryptoServerStream::Helper> session_helper, - std::unique_ptr<QuicAlarmFactory> alarm_factory, - QuicHttpResponseCache* response_cache); - - ~QuicSimpleDispatcher() override; - - int GetRstErrorCount(QuicRstStreamErrorCode rst_error_code) const; - - void OnRstStreamReceived(const QuicRstStreamFrame& frame) override; - - protected: - QuicServerSessionBase* CreateQuicSession( - QuicConnectionId connection_id, - const QuicSocketAddress& client_address, - QuicStringPiece alpn) override; - - QuicHttpResponseCache* response_cache() { return response_cache_; } - - private: - QuicHttpResponseCache* response_cache_; // Unowned. - - // The map of the reset error code with its counter. - std::map<QuicRstStreamErrorCode, int> rst_error_map_; -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_SIMPLE_DISPATCHER_H_ diff --git a/chromium/net/tools/quic/quic_simple_per_connection_packet_writer.h b/chromium/net/tools/quic/quic_simple_per_connection_packet_writer.h index 4c6710ce2c2..7e5132e59b5 100644 --- a/chromium/net/tools/quic/quic_simple_per_connection_packet_writer.h +++ b/chromium/net/tools/quic/quic_simple_per_connection_packet_writer.h @@ -9,8 +9,8 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_packet_writer.h" +#include "net/third_party/quic/core/quic_connection.h" +#include "net/third_party/quic/core/quic_packet_writer.h" namespace net { diff --git a/chromium/net/tools/quic/quic_simple_server.cc b/chromium/net/tools/quic/quic_simple_server.cc index 6526e6ce6bb..1e990db9af1 100644 --- a/chromium/net/tools/quic/quic_simple_server.cc +++ b/chromium/net/tools/quic/quic_simple_server.cc @@ -12,14 +12,14 @@ #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/log/net_log_source.h" -#include "net/quic/core/crypto/crypto_handshake.h" -#include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_crypto_stream.h" -#include "net/quic/core/quic_data_reader.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/core/tls_server_handshaker.h" #include "net/socket/udp_server_socket.h" -#include "net/tools/quic/quic_simple_dispatcher.h" +#include "net/third_party/quic/core/crypto/crypto_handshake.h" +#include "net/third_party/quic/core/crypto/quic_random.h" +#include "net/third_party/quic/core/quic_crypto_stream.h" +#include "net/third_party/quic/core/quic_data_reader.h" +#include "net/third_party/quic/core/quic_packets.h" +#include "net/third_party/quic/core/tls_server_handshaker.h" +#include "net/third_party/quic/tools/quic_simple_dispatcher.h" #include "net/tools/quic/quic_simple_per_connection_packet_writer.h" #include "net/tools/quic/quic_simple_server_packet_writer.h" #include "net/tools/quic/quic_simple_server_session_helper.h" @@ -42,7 +42,7 @@ QuicSimpleServer::QuicSimpleServer( const QuicConfig& config, const QuicCryptoServerConfig::ConfigOptions& crypto_config_options, const ParsedQuicVersionVector& supported_versions, - QuicHttpResponseCache* response_cache) + QuicSimpleServerBackend* quic_simple_server_backend) : version_manager_(supported_versions), helper_( new QuicChromiumConnectionHelper(&clock_, QuicRandom::GetInstance())), @@ -58,7 +58,7 @@ QuicSimpleServer::QuicSimpleServer( read_pending_(false), synchronous_read_count_(0), read_buffer_(new IOBufferWithSize(kReadBufferSize)), - response_cache_(response_cache), + quic_simple_server_backend_(quic_simple_server_backend), weak_factory_(this) { Initialize(); } @@ -133,7 +133,8 @@ int QuicSimpleServer::Listen(const IPEndPoint& address) { std::unique_ptr<QuicConnectionHelperInterface>(helper_), std::unique_ptr<QuicCryptoServerStream::Helper>( new QuicSimpleServerSessionHelper(QuicRandom::GetInstance())), - std::unique_ptr<QuicAlarmFactory>(alarm_factory_), response_cache_)); + std::unique_ptr<QuicAlarmFactory>(alarm_factory_), + quic_simple_server_backend_)); QuicSimpleServerPacketWriter* writer = new QuicSimpleServerPacketWriter(socket_.get(), dispatcher_.get()); dispatcher_->InitializeWithWriter(writer); diff --git a/chromium/net/tools/quic/quic_simple_server.h b/chromium/net/tools/quic/quic_simple_server.h index b72d967e8da..faae4fb4f75 100644 --- a/chromium/net/tools/quic/quic_simple_server.h +++ b/chromium/net/tools/quic/quic_simple_server.h @@ -16,11 +16,11 @@ #include "net/log/net_log.h" #include "net/quic/chromium/quic_chromium_alarm_factory.h" #include "net/quic/chromium/quic_chromium_connection_helper.h" -#include "net/quic/core/crypto/quic_crypto_server_config.h" -#include "net/quic/core/quic_config.h" -#include "net/quic/core/quic_version_manager.h" -#include "net/quic/platform/impl/quic_chromium_clock.h" -#include "net/tools/quic/quic_http_response_cache.h" +#include "net/third_party/quic/core/crypto/quic_crypto_server_config.h" +#include "net/third_party/quic/core/quic_config.h" +#include "net/third_party/quic/core/quic_version_manager.h" +#include "net/third_party/quic/platform/impl/quic_chromium_clock.h" +#include "net/third_party/quic/tools/quic_simple_server_backend.h" namespace net { @@ -40,7 +40,7 @@ class QuicSimpleServer { const QuicConfig& config, const QuicCryptoServerConfig::ConfigOptions& crypto_config_options, const ParsedQuicVersionVector& supported_versions, - QuicHttpResponseCache* response_cache); + QuicSimpleServerBackend* quic_simple_server_backend); virtual ~QuicSimpleServer(); @@ -114,7 +114,7 @@ class QuicSimpleServer { // The log to use for the socket. NetLog net_log_; - QuicHttpResponseCache* response_cache_; + QuicSimpleServerBackend* quic_simple_server_backend_; base::WeakPtrFactory<QuicSimpleServer> weak_factory_; diff --git a/chromium/net/tools/quic/quic_simple_server_bin.cc b/chromium/net/tools/quic/quic_simple_server_bin.cc index e7c44d2553c..57c4f1a9c7a 100644 --- a/chromium/net/tools/quic/quic_simple_server_bin.cc +++ b/chromium/net/tools/quic/quic_simple_server_bin.cc @@ -17,12 +17,18 @@ #include "net/base/ip_address.h" #include "net/base/ip_endpoint.h" #include "net/quic/chromium/crypto/proof_source_chromium.h" -#include "net/quic/core/quic_packets.h" -#include "net/tools/quic/quic_http_response_cache.h" +#include "net/third_party/quic/core/quic_packets.h" +#include "net/third_party/quic/tools/quic_memory_cache_backend.h" #include "net/tools/quic/quic_simple_server.h" // The port the quic server will listen on. int32_t FLAGS_port = 6121; +// Mode of operations: currently only support in-memory cache +std::string FLAGS_quic_mode = "cache"; +// Specifies the directory used during QuicHttpResponseCache +// construction to seed the cache. Cache directory can be +// generated using `wget -p --save-headers <url>` +std::string FLAGS_quic_response_cache_dir = ""; std::unique_ptr<net::ProofSource> CreateProofSource( const base::FilePath& cert_path, @@ -52,18 +58,37 @@ int main(int argc, char* argv[]) { "Options:\n" "-h, --help show this help message and exit\n" "--port=<port> specify the port to listen on\n" - "--quic_response_cache_dir directory containing response data\n" - " to load\n" + "--mode=<cache> Default: cache\n" + " Specify mode of operation: Cache will " + "serve it " + "from a cache dir\n" + "--quic_response_cache_dir=<directory>\n" + " The directory containing cached response " + "data to load\n" "--certificate_file=<file> path to the certificate chain\n" "--key_file=<file> path to the pkcs8 private key\n"; std::cout << help_str; exit(0); } - net::QuicHttpResponseCache response_cache; - if (line->HasSwitch("quic_response_cache_dir")) { - response_cache.InitializeFromDirectory( - line->GetSwitchValueASCII("quic_response_cache_dir")); + net::QuicMemoryCacheBackend memory_cache_backend; + if (line->HasSwitch("mode")) { + FLAGS_quic_mode = line->GetSwitchValueASCII("mode"); + } + if (FLAGS_quic_mode.compare("cache") == 0) { + if (line->HasSwitch("quic_response_cache_dir")) { + FLAGS_quic_response_cache_dir = + line->GetSwitchValueASCII("quic_response_cache_dir"); + if (FLAGS_quic_response_cache_dir.empty() || + memory_cache_backend.InitializeBackend( + FLAGS_quic_response_cache_dir) != true) { + LOG(ERROR) << "--quic_response_cache_dir is not valid !"; + return 1; + } + } + } else { + LOG(ERROR) << "unknown --mode. cache is a valid mode of operation"; + return 1; } if (line->HasSwitch("port")) { @@ -90,7 +115,7 @@ int main(int argc, char* argv[]) { CreateProofSource(line->GetSwitchValuePath("certificate_file"), line->GetSwitchValuePath("key_file")), config, net::QuicCryptoServerConfig::ConfigOptions(), - net::AllSupportedVersions(), &response_cache); + net::AllSupportedVersions(), &memory_cache_backend); int rc = server.Listen(net::IPEndPoint(ip, FLAGS_port)); if (rc < 0) { diff --git a/chromium/net/tools/quic/quic_simple_server_packet_writer.cc b/chromium/net/tools/quic/quic_simple_server_packet_writer.cc index 15b24ca664f..c20b835bb0f 100644 --- a/chromium/net/tools/quic/quic_simple_server_packet_writer.cc +++ b/chromium/net/tools/quic/quic_simple_server_packet_writer.cc @@ -11,7 +11,7 @@ #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/socket/udp_server_socket.h" -#include "net/tools/quic/quic_dispatcher.h" +#include "net/third_party/quic/core/quic_dispatcher.h" namespace net { diff --git a/chromium/net/tools/quic/quic_simple_server_packet_writer.h b/chromium/net/tools/quic/quic_simple_server_packet_writer.h index b3bf6dbb785..5b266aa6914 100644 --- a/chromium/net/tools/quic/quic_simple_server_packet_writer.h +++ b/chromium/net/tools/quic/quic_simple_server_packet_writer.h @@ -10,9 +10,9 @@ #include "base/callback.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_packet_writer.h" -#include "net/quic/core/quic_packets.h" +#include "net/third_party/quic/core/quic_connection.h" +#include "net/third_party/quic/core/quic_packet_writer.h" +#include "net/third_party/quic/core/quic_packets.h" namespace net { diff --git a/chromium/net/tools/quic/quic_simple_server_session.cc b/chromium/net/tools/quic/quic_simple_server_session.cc deleted file mode 100644 index bc9ae358280..00000000000 --- a/chromium/net/tools/quic/quic_simple_server_session.cc +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_simple_server_session.h" - -#include <utility> - -#include "net/quic/core/quic_connection.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" -#include "net/tools/quic/quic_simple_server_stream.h" - -using std::string; - -namespace net { - -QuicSimpleServerSession::QuicSimpleServerSession( - const QuicConfig& config, - QuicConnection* connection, - QuicSession::Visitor* visitor, - QuicCryptoServerStream::Helper* helper, - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache, - QuicHttpResponseCache* response_cache) - : QuicServerSessionBase(config, - connection, - visitor, - helper, - crypto_config, - compressed_certs_cache), - highest_promised_stream_id_(0), - response_cache_(response_cache) {} - -QuicSimpleServerSession::~QuicSimpleServerSession() { - delete connection(); -} - -QuicCryptoServerStreamBase* -QuicSimpleServerSession::CreateQuicCryptoServerStream( - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache) { - return new QuicCryptoServerStream( - crypto_config, compressed_certs_cache, - GetQuicReloadableFlag(enable_quic_stateless_reject_support), this, - stream_helper()); -} - -void QuicSimpleServerSession::StreamDraining(QuicStreamId id) { - QuicSpdySession::StreamDraining(id); - if (!IsIncomingStream(id)) { - HandlePromisedPushRequests(); - } -} - -void QuicSimpleServerSession::OnStreamFrame(const QuicStreamFrame& frame) { - if (!IsIncomingStream(frame.stream_id)) { - QUIC_LOG(WARNING) << "Client shouldn't send data on server push stream"; - connection()->CloseConnection( - QUIC_INVALID_STREAM_ID, "Client sent data on server push stream", - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - return; - } - QuicSpdySession::OnStreamFrame(frame); -} - -void QuicSimpleServerSession::PromisePushResources( - const string& request_url, - const std::list<QuicHttpResponseCache::ServerPushInfo>& resources, - QuicStreamId original_stream_id, - const SpdyHeaderBlock& original_request_headers) { - if (!server_push_enabled()) { - return; - } - - for (QuicHttpResponseCache::ServerPushInfo resource : resources) { - SpdyHeaderBlock headers = SynthesizePushRequestHeaders( - request_url, resource, original_request_headers); - highest_promised_stream_id_ += 2; - SendPushPromise(original_stream_id, highest_promised_stream_id_, - headers.Clone()); - promised_streams_.push_back(PromisedStreamInfo( - std::move(headers), highest_promised_stream_id_, resource.priority)); - } - - // Procese promised push request as many as possible. - HandlePromisedPushRequests(); -} - -QuicSpdyStream* QuicSimpleServerSession::CreateIncomingDynamicStream( - QuicStreamId id) { - if (!ShouldCreateIncomingDynamicStream(id)) { - return nullptr; - } - - QuicSpdyStream* stream = - new QuicSimpleServerStream(id, this, response_cache_); - ActivateStream(QuicWrapUnique(stream)); - return stream; -} - -QuicSimpleServerStream* QuicSimpleServerSession::CreateOutgoingDynamicStream() { - if (!ShouldCreateOutgoingDynamicStream()) { - return nullptr; - } - - QuicSimpleServerStream* stream = new QuicSimpleServerStream( - GetNextOutgoingStreamId(), this, response_cache_); - ActivateStream(QuicWrapUnique(stream)); - return stream; -} - -void QuicSimpleServerSession::CloseStreamInner(QuicStreamId stream_id, - bool locally_reset) { - QuicSpdySession::CloseStreamInner(stream_id, locally_reset); - HandlePromisedPushRequests(); -} - -void QuicSimpleServerSession::HandleFrameOnNonexistentOutgoingStream( - QuicStreamId stream_id) { - // If this stream is a promised but not created stream (stream_id within the - // range of next_outgoing_stream_id_ and highes_promised_stream_id_), - // connection shouldn't be closed. - // Otherwise behave in the same way as base class. - if (stream_id > highest_promised_stream_id_) { - QuicSession::HandleFrameOnNonexistentOutgoingStream(stream_id); - } -} - -void QuicSimpleServerSession::HandleRstOnValidNonexistentStream( - const QuicRstStreamFrame& frame) { - QuicSession::HandleRstOnValidNonexistentStream(frame); - if (!IsClosedStream(frame.stream_id)) { - // If a nonexistent stream is not a closed stream and still valid, it must - // be a locally preserved stream. Resetting this kind of stream means - // cancelling the promised server push. - // Since PromisedStreamInfo are queued in sequence, the corresponding - // index for it in promised_streams_ can be calculated. - DCHECK(frame.stream_id >= next_outgoing_stream_id()); - size_t index = (frame.stream_id - next_outgoing_stream_id()) / 2; - DCHECK(index <= promised_streams_.size()); - promised_streams_[index].is_cancelled = true; - control_frame_manager().WriteOrBufferRstStream(frame.stream_id, - QUIC_RST_ACKNOWLEDGEMENT, 0); - connection()->OnStreamReset(frame.stream_id, QUIC_RST_ACKNOWLEDGEMENT); - } -} - -SpdyHeaderBlock QuicSimpleServerSession::SynthesizePushRequestHeaders( - string request_url, - QuicHttpResponseCache::ServerPushInfo resource, - const SpdyHeaderBlock& original_request_headers) { - QuicUrl push_request_url = resource.request_url; - - SpdyHeaderBlock spdy_headers = original_request_headers.Clone(); - // :authority could be different from original request. - spdy_headers[":authority"] = push_request_url.host(); - spdy_headers[":path"] = push_request_url.path(); - ; - // Push request always use GET. - spdy_headers[":method"] = "GET"; - spdy_headers["referer"] = request_url; - spdy_headers[":scheme"] = push_request_url.scheme(); - // It is not possible to push a response to a request that includes a request - // body. - spdy_headers["content-length"] = "0"; - // Remove "host" field as push request is a directly generated HTTP2 request - // which should use ":authority" instead of "host". - spdy_headers.erase("host"); - return spdy_headers; -} - -void QuicSimpleServerSession::SendPushPromise(QuicStreamId original_stream_id, - QuicStreamId promised_stream_id, - SpdyHeaderBlock headers) { - QUIC_DLOG(INFO) << "stream " << original_stream_id - << " send PUSH_PROMISE for promised stream " - << promised_stream_id; - WritePushPromise(original_stream_id, promised_stream_id, std::move(headers)); -} - -void QuicSimpleServerSession::HandlePromisedPushRequests() { - while (!promised_streams_.empty() && ShouldCreateOutgoingDynamicStream()) { - PromisedStreamInfo& promised_info = promised_streams_.front(); - DCHECK_EQ(next_outgoing_stream_id(), promised_info.stream_id); - - if (promised_info.is_cancelled) { - // This stream has been reset by client. Skip this stream id. - promised_streams_.pop_front(); - GetNextOutgoingStreamId(); - return; - } - - QuicSimpleServerStream* promised_stream = - static_cast<QuicSimpleServerStream*>(CreateOutgoingDynamicStream()); - DCHECK_NE(promised_stream, nullptr); - DCHECK_EQ(promised_info.stream_id, promised_stream->id()); - QUIC_DLOG(INFO) << "created server push stream " << promised_stream->id(); - - promised_stream->SetPriority(promised_info.priority); - - SpdyHeaderBlock request_headers(std::move(promised_info.request_headers)); - - promised_streams_.pop_front(); - promised_stream->PushResponse(std::move(request_headers)); - } -} - -} // namespace net diff --git a/chromium/net/tools/quic/quic_simple_server_session.h b/chromium/net/tools/quic/quic_simple_server_session.h deleted file mode 100644 index f40dc0d184f..00000000000 --- a/chromium/net/tools/quic/quic_simple_server_session.h +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// A toy server specific QuicSession subclass. - -#ifndef NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_SESSION_H_ -#define NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_SESSION_H_ - -#include <stdint.h> - -#include <list> -#include <memory> -#include <set> -#include <string> -#include <utility> -#include <vector> - -#include "base/macros.h" -#include "net/quic/core/quic_crypto_server_stream.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/core/quic_server_session_base.h" -#include "net/quic/core/quic_spdy_session.h" -#include "net/quic/platform/api/quic_containers.h" -#include "net/tools/quic/quic_http_response_cache.h" -#include "net/tools/quic/quic_simple_server_stream.h" - -namespace net { - -namespace test { -class QuicSimpleServerSessionPeer; -} // namespace test - -class QuicSimpleServerSession : public QuicServerSessionBase { - public: - // A PromisedStreamInfo is an element of the queue to store promised - // stream which hasn't been created yet. It keeps a mapping between promised - // stream id with its priority and the headers sent out in PUSH_PROMISE. - struct PromisedStreamInfo { - public: - PromisedStreamInfo(SpdyHeaderBlock request_headers, - QuicStreamId stream_id, - SpdyPriority priority) - : request_headers(std::move(request_headers)), - stream_id(stream_id), - priority(priority), - is_cancelled(false) {} - SpdyHeaderBlock request_headers; - QuicStreamId stream_id; - SpdyPriority priority; - bool is_cancelled; - }; - - // Takes ownership of |connection|. - QuicSimpleServerSession(const QuicConfig& config, - QuicConnection* connection, - QuicSession::Visitor* visitor, - QuicCryptoServerStream::Helper* helper, - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache, - QuicHttpResponseCache* response_cache); - - ~QuicSimpleServerSession() override; - - // When a stream is marked draining, it will decrease the number of open - // streams. If it is an outgoing stream, try to open a new stream to send - // remaing push responses. - void StreamDraining(QuicStreamId id) override; - - // Override base class to detact client sending data on server push stream. - void OnStreamFrame(const QuicStreamFrame& frame) override; - - // Send out PUSH_PROMISE for all |resources| promised stream id in each frame - // will increase by 2 for each item in |resources|. - // And enqueue HEADERS block in those PUSH_PROMISED for sending push response - // later. - virtual void PromisePushResources( - const std::string& request_url, - const std::list<QuicHttpResponseCache::ServerPushInfo>& resources, - QuicStreamId original_stream_id, - const SpdyHeaderBlock& original_request_headers); - - protected: - // QuicSession methods: - QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override; - QuicSimpleServerStream* CreateOutgoingDynamicStream() override; - // Closing an outgoing stream can reduce open outgoing stream count, try - // to handle queued promised streams right now. - void CloseStreamInner(QuicStreamId stream_id, bool locally_reset) override; - // Override to return true for locally preserved server push stream. - void HandleFrameOnNonexistentOutgoingStream(QuicStreamId stream_id) override; - // Override to handle reseting locally preserved streams. - void HandleRstOnValidNonexistentStream( - const QuicRstStreamFrame& frame) override; - - // QuicServerSessionBaseMethod: - QuicCryptoServerStreamBase* CreateQuicCryptoServerStream( - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache) override; - - QuicHttpResponseCache* response_cache() { return response_cache_; } - - private: - friend class test::QuicSimpleServerSessionPeer; - - // Create a server push headers block by copying request's headers block. - // But replace or add these pseudo-headers as they are specific to each - // request: - // :authority, :path, :method, :scheme, referer. - // Copying the rest headers ensures they are the same as the original - // request, especially cookies. - SpdyHeaderBlock SynthesizePushRequestHeaders( - std::string request_url, - QuicHttpResponseCache::ServerPushInfo resource, - const SpdyHeaderBlock& original_request_headers); - - // Send PUSH_PROMISE frame on headers stream. - void SendPushPromise(QuicStreamId original_stream_id, - QuicStreamId promised_stream_id, - SpdyHeaderBlock headers); - - // Fetch response from cache for request headers enqueued into - // promised_headers_and_streams_ and send them on dedicated stream until - // reaches max_open_stream_ limit. - // Called when return value of GetNumOpenOutgoingStreams() changes: - // CloseStreamInner(); - // StreamDraining(); - // Note that updateFlowControlOnFinalReceivedByteOffset() won't change the - // return value becasue all push streams are impossible to become locally - // closed. Since a locally preserved stream becomes remotely closed after - // HandlePromisedPushRequests() starts to process it, and if it is reset - // locally afterwards, it will be immediately become closed and never get into - // locally_closed_stream_highest_offset_. So all the streams in this map - // are not outgoing streams. - void HandlePromisedPushRequests(); - - // Keep track of the highest stream id which has been sent in PUSH_PROMISE. - QuicStreamId highest_promised_stream_id_; - - // Promised streams which hasn't been created yet because of max_open_stream_ - // limit. New element is added to the end of the queue. - // Since outgoing stream is created in sequence, stream_id of each element in - // the queue also increases by 2 from previous one's. The front element's - // stream_id is always next_outgoing_stream_id_, and the last one is always - // highest_promised_stream_id_. - QuicDeque<PromisedStreamInfo> promised_streams_; - - QuicHttpResponseCache* response_cache_; // Not owned. - - DISALLOW_COPY_AND_ASSIGN(QuicSimpleServerSession); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_SESSION_H_ diff --git a/chromium/net/tools/quic/quic_simple_server_session_helper.cc b/chromium/net/tools/quic/quic_simple_server_session_helper.cc index 819553aeb4c..21a7977cd17 100644 --- a/chromium/net/tools/quic/quic_simple_server_session_helper.cc +++ b/chromium/net/tools/quic/quic_simple_server_session_helper.cc @@ -18,6 +18,8 @@ QuicConnectionId QuicSimpleServerSessionHelper::GenerateConnectionIdForReject( bool QuicSimpleServerSessionHelper::CanAcceptClientHello( const CryptoHandshakeMessage& message, + const QuicSocketAddress& client_address, + const QuicSocketAddress& peer_address, const QuicSocketAddress& self_address, std::string* error_details) const { return true; diff --git a/chromium/net/tools/quic/quic_simple_server_session_helper.h b/chromium/net/tools/quic/quic_simple_server_session_helper.h index 00a3bf9c8bb..6ddd5d96dfd 100644 --- a/chromium/net/tools/quic/quic_simple_server_session_helper.h +++ b/chromium/net/tools/quic/quic_simple_server_session_helper.h @@ -5,8 +5,8 @@ #ifndef NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_SESSION_HELPER_H_ #define NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_SESSION_HELPER_H_ -#include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_server_session_base.h" +#include "net/third_party/quic/core/crypto/quic_random.h" +#include "net/third_party/quic/core/quic_server_session_base.h" namespace net { @@ -22,6 +22,8 @@ class QuicSimpleServerSessionHelper : public QuicCryptoServerStream::Helper { QuicConnectionId /*connection_id*/) const override; bool CanAcceptClientHello(const CryptoHandshakeMessage& message, + const QuicSocketAddress& client_address, + const QuicSocketAddress& peer_address, const QuicSocketAddress& self_address, std::string* error_details) const override; diff --git a/chromium/net/tools/quic/quic_simple_server_session_helper_test.cc b/chromium/net/tools/quic/quic_simple_server_session_helper_test.cc index c25c60e54a8..b2bd7a922a0 100644 --- a/chromium/net/tools/quic/quic_simple_server_session_helper_test.cc +++ b/chromium/net/tools/quic/quic_simple_server_session_helper_test.cc @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/quic/test_tools/mock_random.h" -#include "net/tools/quic/quic_simple_crypto_server_stream_helper.h" +#include "net/third_party/quic/test_tools/mock_random.h" +#include "net/third_party/quic/tools/quic_simple_crypto_server_stream_helper.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chromium/net/tools/quic/quic_simple_server_session_test.cc b/chromium/net/tools/quic/quic_simple_server_session_test.cc deleted file mode 100644 index 124ff389a2b..00000000000 --- a/chromium/net/tools/quic/quic_simple_server_session_test.cc +++ /dev/null @@ -1,658 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_simple_server_session.h" - -#include <algorithm> -#include <memory> - -#include "base/macros.h" -#include "net/quic/core/crypto/quic_crypto_server_config.h" -#include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/proto/cached_network_parameters.pb.h" -#include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_crypto_server_stream.h" -#include "net/quic/core/quic_utils.h" -#include "net/quic/core/tls_server_handshaker.h" -#include "net/quic/platform/api/quic_containers.h" -#include "net/quic/platform/api/quic_flags.h" -#include "net/quic/platform/api/quic_ptr_util.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_test.h" -#include "net/quic/platform/api/quic_text_utils.h" -#include "net/quic/test_tools/crypto_test_utils.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_sent_packet_manager_peer.h" -#include "net/quic/test_tools/quic_session_peer.h" -#include "net/quic/test_tools/quic_spdy_session_peer.h" -#include "net/quic/test_tools/quic_spdy_stream_peer.h" -#include "net/quic/test_tools/quic_stream_peer.h" -#include "net/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h" -#include "net/quic/test_tools/quic_test_utils.h" -#include "net/test/gtest_util.h" -#include "net/tools/quic/quic_simple_server_stream.h" -#include "net/tools/quic/test_tools/mock_quic_session_visitor.h" - -using std::string; -using testing::_; -using testing::AtLeast; -using testing::InSequence; -using testing::Return; -using testing::StrictMock; - -namespace net { -namespace test { -namespace { -typedef QuicSimpleServerSession::PromisedStreamInfo PromisedStreamInfo; -} // namespace - -class QuicSimpleServerSessionPeer { - public: - static void SetCryptoStream(QuicSimpleServerSession* s, - QuicCryptoServerStream* crypto_stream) { - s->crypto_stream_.reset(crypto_stream); - s->static_streams()[kCryptoStreamId] = crypto_stream; - } - - static QuicSpdyStream* CreateIncomingDynamicStream(QuicSimpleServerSession* s, - QuicStreamId id) { - return s->CreateIncomingDynamicStream(id); - } - - static QuicSimpleServerStream* CreateOutgoingDynamicStream( - QuicSimpleServerSession* s) { - return s->CreateOutgoingDynamicStream(); - } -}; - -namespace { - -const size_t kMaxStreamsForTest = 10; - -class MockQuicCryptoServerStream : public QuicCryptoServerStream { - public: - explicit MockQuicCryptoServerStream( - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache, - QuicServerSessionBase* session, - QuicCryptoServerStream::Helper* helper) - : QuicCryptoServerStream( - crypto_config, - compressed_certs_cache, - GetQuicReloadableFlag( - enable_quic_stateless_reject_support), // NOLINT - session, - helper) {} - ~MockQuicCryptoServerStream() override = default; - - MOCK_METHOD1(SendServerConfigUpdate, - void(const CachedNetworkParameters* cached_network_parameters)); - - void set_encryption_established(bool has_established) { - encryption_established_override_ = has_established; - } - - bool encryption_established() const override { - return QuicCryptoServerStream::encryption_established() || - encryption_established_override_; - } - - private: - bool encryption_established_override_ = false; - - DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStream); -}; - -class MockQuicConnectionWithSendStreamData : public MockQuicConnection { - public: - MockQuicConnectionWithSendStreamData( - MockQuicConnectionHelper* helper, - MockAlarmFactory* alarm_factory, - Perspective perspective, - const ParsedQuicVersionVector& supported_versions) - : MockQuicConnection(helper, - alarm_factory, - perspective, - supported_versions) {} - - MOCK_METHOD4(SendStreamData, - QuicConsumedData(QuicStreamId id, - size_t write_length, - QuicStreamOffset offset, - StreamSendingState state)); -}; - -class MockQuicSimpleServerSession : public QuicSimpleServerSession { - public: - MockQuicSimpleServerSession(const QuicConfig& config, - QuicConnection* connection, - QuicSession::Visitor* visitor, - QuicCryptoServerStream::Helper* helper, - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache, - QuicHttpResponseCache* response_cache) - : QuicSimpleServerSession(config, - connection, - visitor, - helper, - crypto_config, - compressed_certs_cache, - response_cache) {} - // Methods taking non-copyable types like SpdyHeaderBlock by value cannot be - // mocked directly. - size_t WritePushPromise(QuicStreamId original_stream_id, - QuicStreamId promised_stream_id, - SpdyHeaderBlock headers) override { - return WritePushPromiseMock(original_stream_id, promised_stream_id, - headers); - } - MOCK_METHOD3(WritePushPromiseMock, - size_t(QuicStreamId original_stream_id, - QuicStreamId promised_stream_id, - const SpdyHeaderBlock& headers)); - - size_t WriteHeaders(QuicStreamId stream_id, - SpdyHeaderBlock headers, - bool fin, - SpdyPriority priority, - QuicReferenceCountedPointer<QuicAckListenerInterface> - ack_listener) override { - return WriteHeadersMock(stream_id, headers, fin, priority, ack_listener); - } - MOCK_METHOD5( - WriteHeadersMock, - size_t(QuicStreamId stream_id, - const SpdyHeaderBlock& headers, - bool fin, - SpdyPriority priority, - const QuicReferenceCountedPointer<QuicAckListenerInterface>& - ack_listener)); - MOCK_METHOD1(SendBlocked, void(QuicStreamId)); -}; - -class QuicSimpleServerSessionTest - : public QuicTestWithParam<ParsedQuicVersion> { - public: - bool ClearControlFrame(const QuicFrame& frame) { - DeleteFrame(&const_cast<QuicFrame&>(frame)); - return true; - } - - protected: - QuicSimpleServerSessionTest() - : crypto_config_(QuicCryptoServerConfig::TESTING, - QuicRandom::GetInstance(), - crypto_test_utils::ProofSourceForTesting(), - TlsServerHandshaker::CreateSslCtx()), - compressed_certs_cache_( - QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) { - config_.SetMaxStreamsPerConnection(kMaxStreamsForTest, kMaxStreamsForTest); - config_.SetMaxIncomingDynamicStreamsToSend(kMaxStreamsForTest); - QuicConfigPeer::SetReceivedMaxIncomingDynamicStreams(&config_, - kMaxStreamsForTest); - config_.SetInitialStreamFlowControlWindowToSend( - kInitialStreamFlowControlWindowForTest); - config_.SetInitialSessionFlowControlWindowToSend( - kInitialSessionFlowControlWindowForTest); - - ParsedQuicVersionVector supported_versions = SupportedVersions(GetParam()); - connection_ = new StrictMock<MockQuicConnectionWithSendStreamData>( - &helper_, &alarm_factory_, Perspective::IS_SERVER, supported_versions); - session_ = QuicMakeUnique<MockQuicSimpleServerSession>( - config_, connection_, &owner_, &stream_helper_, &crypto_config_, - &compressed_certs_cache_, &response_cache_); - MockClock clock; - handshake_message_.reset(crypto_config_.AddDefaultConfig( - QuicRandom::GetInstance(), &clock, - QuicCryptoServerConfig::ConfigOptions())); - session_->Initialize(); - QuicSessionPeer::GetMutableCryptoStream(session_.get()) - ->OnSuccessfulVersionNegotiation(supported_versions.front()); - visitor_ = QuicConnectionPeer::GetVisitor(connection_); - - session_->OnConfigNegotiated(); - } - - QuicStreamId GetNthClientInitiatedId(int n) { - return QuicSpdySessionPeer::GetNthClientInitiatedStreamId(*session_, n); - } - - QuicStreamId GetNthServerInitiatedId(int n) { - return QuicSpdySessionPeer::GetNthServerInitiatedStreamId(*session_, n); - } - - StrictMock<MockQuicSessionVisitor> owner_; - StrictMock<MockQuicCryptoServerStreamHelper> stream_helper_; - MockQuicConnectionHelper helper_; - MockAlarmFactory alarm_factory_; - StrictMock<MockQuicConnectionWithSendStreamData>* connection_; - QuicConfig config_; - QuicCryptoServerConfig crypto_config_; - QuicCompressedCertsCache compressed_certs_cache_; - QuicHttpResponseCache response_cache_; - std::unique_ptr<MockQuicSimpleServerSession> session_; - std::unique_ptr<CryptoHandshakeMessage> handshake_message_; - QuicConnectionVisitorInterface* visitor_; -}; - -INSTANTIATE_TEST_CASE_P(Tests, - QuicSimpleServerSessionTest, - ::testing::ValuesIn(AllSupportedVersions())); - -TEST_P(QuicSimpleServerSessionTest, CloseStreamDueToReset) { - // Open a stream, then reset it. - // Send two bytes of payload to open it. - QuicStreamFrame data1(GetNthClientInitiatedId(0), false, 0, - QuicStringPiece("HT")); - session_->OnStreamFrame(data1); - EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams()); - - // Receive a reset (and send a RST in response). - QuicRstStreamFrame rst1(kInvalidControlFrameId, GetNthClientInitiatedId(0), - QUIC_ERROR_PROCESSING_STREAM, 0); - EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); - EXPECT_CALL(*connection_, SendControlFrame(_)); - EXPECT_CALL(*connection_, OnStreamReset(GetNthClientInitiatedId(0), - QUIC_RST_ACKNOWLEDGEMENT)); - visitor_->OnRstStream(rst1); - EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); - - // Send the same two bytes of payload in a new packet. - visitor_->OnStreamFrame(data1); - - // The stream should not be re-opened. - EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); - EXPECT_TRUE(connection_->connected()); -} - -TEST_P(QuicSimpleServerSessionTest, NeverOpenStreamDueToReset) { - // Send a reset (and expect the peer to send a RST in response). - QuicRstStreamFrame rst1(kInvalidControlFrameId, GetNthClientInitiatedId(0), - QUIC_ERROR_PROCESSING_STREAM, 0); - EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); - EXPECT_CALL(*connection_, SendControlFrame(_)); - EXPECT_CALL(*connection_, OnStreamReset(GetNthClientInitiatedId(0), - QUIC_RST_ACKNOWLEDGEMENT)); - visitor_->OnRstStream(rst1); - EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); - - // Send two bytes of payload. - QuicStreamFrame data1(GetNthClientInitiatedId(0), false, 0, - QuicStringPiece("HT")); - visitor_->OnStreamFrame(data1); - - // The stream should never be opened, now that the reset is received. - EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); - EXPECT_TRUE(connection_->connected()); -} - -TEST_P(QuicSimpleServerSessionTest, AcceptClosedStream) { - // Send (empty) compressed headers followed by two bytes of data. - QuicStreamFrame frame1(GetNthClientInitiatedId(0), false, 0, - QuicStringPiece("\1\0\0\0\0\0\0\0HT")); - QuicStreamFrame frame2(GetNthClientInitiatedId(1), false, 0, - QuicStringPiece("\2\0\0\0\0\0\0\0HT")); - visitor_->OnStreamFrame(frame1); - visitor_->OnStreamFrame(frame2); - EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams()); - - // Send a reset (and expect the peer to send a RST in response). - QuicRstStreamFrame rst(kInvalidControlFrameId, GetNthClientInitiatedId(0), - QUIC_ERROR_PROCESSING_STREAM, 0); - EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); - 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 - // past the reset point of stream 3. As it's a closed stream we just drop the - // data on the floor, but accept the packet because it has data for stream 5. - QuicStreamFrame frame3(GetNthClientInitiatedId(0), false, 2, - QuicStringPiece("TP")); - QuicStreamFrame frame4(GetNthClientInitiatedId(1), false, 2, - QuicStringPiece("TP")); - visitor_->OnStreamFrame(frame3); - visitor_->OnStreamFrame(frame4); - // The stream should never be opened, now that the reset is received. - EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams()); - EXPECT_TRUE(connection_->connected()); -} - -TEST_P(QuicSimpleServerSessionTest, CreateIncomingDynamicStreamDisconnected) { - // Tests that incoming stream creation fails when connection is not connected. - size_t initial_num_open_stream = session_->GetNumOpenIncomingStreams(); - QuicConnectionPeer::TearDownLocalConnectionState(connection_); - EXPECT_QUIC_BUG(QuicSimpleServerSessionPeer::CreateIncomingDynamicStream( - session_.get(), GetNthClientInitiatedId(0)), - "ShouldCreateIncomingDynamicStream called when disconnected"); - EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenIncomingStreams()); -} - -TEST_P(QuicSimpleServerSessionTest, CreateEvenIncomingDynamicStream) { - // Tests that incoming stream creation fails when given stream id is even. - size_t initial_num_open_stream = session_->GetNumOpenIncomingStreams(); - EXPECT_CALL(*connection_, - CloseConnection(QUIC_INVALID_STREAM_ID, - "Client created even numbered stream", _)); - QuicSimpleServerSessionPeer::CreateIncomingDynamicStream(session_.get(), 2); - EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenIncomingStreams()); -} - -TEST_P(QuicSimpleServerSessionTest, CreateIncomingDynamicStream) { - QuicSpdyStream* stream = - QuicSimpleServerSessionPeer::CreateIncomingDynamicStream( - session_.get(), GetNthClientInitiatedId(0)); - EXPECT_NE(nullptr, stream); - EXPECT_EQ(GetNthClientInitiatedId(0), stream->id()); -} - -TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamDisconnected) { - // Tests that outgoing stream creation fails when connection is not connected. - size_t initial_num_open_stream = session_->GetNumOpenOutgoingStreams(); - QuicConnectionPeer::TearDownLocalConnectionState(connection_); - EXPECT_QUIC_BUG( - QuicSimpleServerSessionPeer::CreateOutgoingDynamicStream(session_.get()), - "ShouldCreateOutgoingDynamicStream called when disconnected"); - - EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenOutgoingStreams()); -} - -TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUnencrypted) { - // Tests that outgoing stream creation fails when encryption has not yet been - // established. - size_t initial_num_open_stream = session_->GetNumOpenOutgoingStreams(); - EXPECT_QUIC_BUG( - QuicSimpleServerSessionPeer::CreateOutgoingDynamicStream(session_.get()), - "Encryption not established so no outgoing stream created."); - EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenOutgoingStreams()); -} - -TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUptoLimit) { - // Tests that outgoing stream creation should not be affected by existing - // incoming stream and vice-versa. But when reaching the limit of max outgoing - // stream allowed, creation should fail. - - // Receive some data to initiate a incoming stream which should not effect - // creating outgoing streams. - QuicStreamFrame data1(GetNthClientInitiatedId(0), false, 0, - QuicStringPiece("HT")); - session_->OnStreamFrame(data1); - EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams()); - EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams()); - - if (GetQuicReloadableFlag(quic_register_streams_early2) && - GetQuicReloadableFlag(quic_register_static_streams)) { - session_->UnregisterStreamPriority(kHeadersStreamId, /*is_static=*/true); - } - // Assume encryption already established. - QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), nullptr); - MockQuicCryptoServerStream* crypto_stream = - new MockQuicCryptoServerStream(&crypto_config_, &compressed_certs_cache_, - session_.get(), &stream_helper_); - crypto_stream->set_encryption_established(true); - QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream); - if (GetQuicReloadableFlag(quic_register_streams_early2) && - GetQuicReloadableFlag(quic_register_static_streams)) { - session_->RegisterStreamPriority(kHeadersStreamId, /*is_static=*/true, - QuicStream::kDefaultPriority); - } - - // Create push streams till reaching the upper limit of allowed open streams. - for (size_t i = 0; i < kMaxStreamsForTest; ++i) { - QuicSpdyStream* created_stream = - QuicSimpleServerSessionPeer::CreateOutgoingDynamicStream( - session_.get()); - EXPECT_EQ(GetNthServerInitiatedId(i), created_stream->id()); - EXPECT_EQ(i + 1, session_->GetNumOpenOutgoingStreams()); - } - - // Continuing creating push stream would fail. - EXPECT_EQ(nullptr, QuicSimpleServerSessionPeer::CreateOutgoingDynamicStream( - session_.get())); - EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams()); - - // Create peer initiated stream should have no problem. - QuicStreamFrame data2(GetNthClientInitiatedId(1), false, 0, - QuicStringPiece("HT")); - session_->OnStreamFrame(data2); - EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams()); -} - -TEST_P(QuicSimpleServerSessionTest, OnStreamFrameWithEvenStreamId) { - QuicStreamFrame frame(2, false, 0, QuicStringPiece()); - EXPECT_CALL(*connection_, - CloseConnection(QUIC_INVALID_STREAM_ID, - "Client sent data on server push stream", _)); - session_->OnStreamFrame(frame); -} - -TEST_P(QuicSimpleServerSessionTest, GetEvenIncomingError) { - // Tests that calling GetOrCreateDynamicStream() on an outgoing stream not - // promised yet should result close connection. - EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, - "Data for nonexistent stream", _)); - EXPECT_EQ(nullptr, - QuicSessionPeer::GetOrCreateDynamicStream(session_.get(), 4)); -} - -// In order to test the case where server push stream creation goes beyond -// limit, server push streams need to be hanging there instead of -// immediately closing after sending back response. -// To achieve this goal, this class resets flow control windows so that large -// responses will not be sent fully in order to prevent push streams from being -// closed immediately. -// Also adjust connection-level flow control window to ensure a large response -// can cause stream-level flow control blocked but not connection-level. -class QuicSimpleServerSessionServerPushTest - : public QuicSimpleServerSessionTest { - protected: - const size_t kStreamFlowControlWindowSize = 32 * 1024; // 32KB. - - QuicSimpleServerSessionServerPushTest() : QuicSimpleServerSessionTest() { - config_.SetMaxStreamsPerConnection(kMaxStreamsForTest, kMaxStreamsForTest); - - // Reset stream level flow control window to be 32KB. - QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow( - &config_, kStreamFlowControlWindowSize); - // Reset connection level flow control window to be 1.5 MB which is large - // enough that it won't block any stream to write before stream level flow - // control blocks it. - QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow( - &config_, kInitialSessionFlowControlWindowForTest); - // Enable server push. - QuicTagVector copt; - copt.push_back(kSPSH); - QuicConfigPeer::SetReceivedConnectionOptions(&config_, copt); - - ParsedQuicVersionVector supported_versions = SupportedVersions(GetParam()); - connection_ = new StrictMock<MockQuicConnectionWithSendStreamData>( - &helper_, &alarm_factory_, Perspective::IS_SERVER, supported_versions); - session_ = QuicMakeUnique<MockQuicSimpleServerSession>( - config_, connection_, &owner_, &stream_helper_, &crypto_config_, - &compressed_certs_cache_, &response_cache_); - session_->Initialize(); - QuicSessionPeer::GetMutableCryptoStream(session_.get()) - ->OnSuccessfulVersionNegotiation(supported_versions.front()); - // Needed to make new session flow control window and server push work. - session_->OnConfigNegotiated(); - - visitor_ = QuicConnectionPeer::GetVisitor(connection_); - - if (GetQuicReloadableFlag(quic_register_streams_early2) && - GetQuicReloadableFlag(quic_register_static_streams)) { - session_->UnregisterStreamPriority(kHeadersStreamId, /*is_static=*/true); - } - QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), nullptr); - // Assume encryption already established. - MockQuicCryptoServerStream* crypto_stream = new MockQuicCryptoServerStream( - &crypto_config_, &compressed_certs_cache_, session_.get(), - &stream_helper_); - - crypto_stream->set_encryption_established(true); - QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream); - if (GetQuicReloadableFlag(quic_register_streams_early2) && - GetQuicReloadableFlag(quic_register_static_streams)) { - session_->RegisterStreamPriority(kHeadersStreamId, /*is_static=*/true, - QuicStream::kDefaultPriority); - } - } - - // Given |num_resources|, create this number of fake push resources and push - // them by sending PUSH_PROMISE for all and sending push responses for as much - // as possible(limited by kMaxStreamsForTest). - // If |num_resources| > kMaxStreamsForTest, the left over will be queued. - void PromisePushResources(size_t num_resources) { - // To prevent push streams from being closed the response need to be larger - // than stream flow control window so stream won't send the full body. - size_t body_size = 2 * kStreamFlowControlWindowSize; // 64KB. - - config_.SetMaxStreamsPerConnection(kMaxStreamsForTest, kMaxStreamsForTest); - - string request_url = "mail.google.com/"; - SpdyHeaderBlock request_headers; - string resource_host = "www.google.com"; - string partial_push_resource_path = "/server_push_src"; - std::list<QuicHttpResponseCache::ServerPushInfo> push_resources; - string scheme = "http"; - for (unsigned int i = 1; i <= num_resources; ++i) { - QuicStreamId stream_id = GetNthServerInitiatedId(i - 1); - string path = - partial_push_resource_path + QuicTextUtils::Uint64ToString(i); - string url = scheme + "://" + resource_host + path; - QuicUrl resource_url = QuicUrl(url); - string body(body_size, 'a'); - response_cache_.AddSimpleResponse(resource_host, path, 200, body); - push_resources.push_back(QuicHttpResponseCache::ServerPushInfo( - resource_url, SpdyHeaderBlock(), QuicStream::kDefaultPriority, body)); - // PUSH_PROMISED are sent for all the resources. - EXPECT_CALL(*session_, WritePushPromiseMock(GetNthClientInitiatedId(0), - stream_id, _)); - if (i <= kMaxStreamsForTest) { - // |kMaxStreamsForTest| promised responses should be sent. - EXPECT_CALL(*session_, - WriteHeadersMock(stream_id, _, false, - QuicStream::kDefaultPriority, _)); - // Since flow control window is smaller than response body, not the - // whole body will be sent. - EXPECT_CALL(*connection_, SendStreamData(stream_id, _, 0, NO_FIN)) - .WillOnce( - Return(QuicConsumedData(kStreamFlowControlWindowSize, false))); - EXPECT_CALL(*session_, SendBlocked(stream_id)); - } - } - session_->PromisePushResources(request_url, push_resources, - GetNthClientInitiatedId(0), request_headers); - } -}; - -INSTANTIATE_TEST_CASE_P(Tests, - QuicSimpleServerSessionServerPushTest, - ::testing::ValuesIn(AllSupportedVersions())); - -TEST_P(QuicSimpleServerSessionServerPushTest, TestPromisePushResources) { - // Tests that given more than kMaxOpenStreamForTest resources, all their - // PUSH_PROMISE's will be sent out and only |kMaxOpenStreamForTest| streams - // will be opened and send push response. - - size_t num_resources = kMaxStreamsForTest + 5; - PromisePushResources(num_resources); - EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams()); -} - -TEST_P(QuicSimpleServerSessionServerPushTest, - HandlePromisedPushRequestsAfterStreamDraining) { - // Tests that after promised stream queued up, when an opened stream is marked - // draining, a queued promised stream will become open and send push response. - size_t num_resources = kMaxStreamsForTest + 1; - PromisePushResources(num_resources); - QuicStreamId next_out_going_stream_id = - GetNthServerInitiatedId(kMaxStreamsForTest); - - // After an open stream is marked draining, a new stream is expected to be - // created and a response sent on the stream. - EXPECT_CALL(*session_, WriteHeadersMock(next_out_going_stream_id, _, false, - QuicStream::kDefaultPriority, _)); - EXPECT_CALL(*connection_, - SendStreamData(next_out_going_stream_id, _, 0, NO_FIN)) - .WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false))); - EXPECT_CALL(*session_, SendBlocked(next_out_going_stream_id)); - session_->StreamDraining(2); - // Number of open outgoing streams should still be the same, because a new - // stream is opened. And the queue should be empty. - EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams()); -} - -TEST_P(QuicSimpleServerSessionServerPushTest, - ResetPromisedStreamToCancelServerPush) { - // Tests that after all resources are promised, a RST frame from client can - // prevent a promised resource to be send out. - - // Having two extra resources to be send later. One of them will be reset, so - // when opened stream become close, only one will become open. - size_t num_resources = kMaxStreamsForTest + 2; - PromisePushResources(num_resources); - - // Reset the last stream in the queue. It should be marked cancelled. - QuicStreamId stream_got_reset = - GetNthServerInitiatedId(kMaxStreamsForTest + 1); - QuicRstStreamFrame rst(kInvalidControlFrameId, stream_got_reset, - QUIC_STREAM_CANCELLED, 0); - EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); - EXPECT_CALL(*connection_, SendControlFrame(_)) - .WillOnce(Invoke( - this, &QuicSimpleServerSessionServerPushTest::ClearControlFrame)); - EXPECT_CALL(*connection_, - OnStreamReset(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT)); - visitor_->OnRstStream(rst); - - // When the first 2 streams becomes draining, the two queued up stream could - // be created. But since one of them was marked cancelled due to RST frame, - // only one queued resource will be sent out. - QuicStreamId stream_not_reset = GetNthServerInitiatedId(kMaxStreamsForTest); - InSequence s; - EXPECT_CALL(*session_, WriteHeadersMock(stream_not_reset, _, false, - QuicStream::kDefaultPriority, _)); - EXPECT_CALL(*connection_, SendStreamData(stream_not_reset, _, 0, NO_FIN)) - .WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false))); - EXPECT_CALL(*session_, SendBlocked(stream_not_reset)); - EXPECT_CALL(*session_, WriteHeadersMock(stream_got_reset, _, false, - QuicStream::kDefaultPriority, _)) - .Times(0); - - session_->StreamDraining(GetNthServerInitiatedId(0)); - session_->StreamDraining(GetNthServerInitiatedId(1)); -} - -TEST_P(QuicSimpleServerSessionServerPushTest, - CloseStreamToHandleMorePromisedStream) { - // Tests that closing a open outgoing stream can trigger a promised resource - // in the queue to be send out. - size_t num_resources = kMaxStreamsForTest + 1; - PromisePushResources(num_resources); - QuicStreamId stream_to_open = GetNthServerInitiatedId(kMaxStreamsForTest); - - // Resetting 1st open stream will close the stream and give space for extra - // stream to be opened. - QuicStreamId stream_got_reset = GetNthServerInitiatedId(0); - EXPECT_CALL(*connection_, SendControlFrame(_)); - EXPECT_CALL(*connection_, - OnStreamReset(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT)); - EXPECT_CALL(*session_, WriteHeadersMock(stream_to_open, _, false, - QuicStream::kDefaultPriority, _)); - EXPECT_CALL(*connection_, SendStreamData(stream_to_open, _, 0, NO_FIN)) - .WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false))); - - EXPECT_CALL(*session_, SendBlocked(stream_to_open)); - EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); - QuicRstStreamFrame rst(kInvalidControlFrameId, stream_got_reset, - QUIC_STREAM_CANCELLED, 0); - visitor_->OnRstStream(rst); -} - -} // namespace -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/quic_simple_server_stream.cc b/chromium/net/tools/quic/quic_simple_server_stream.cc deleted file mode 100644 index c0ee02d3079..00000000000 --- a/chromium/net/tools/quic/quic_simple_server_stream.cc +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_simple_server_stream.h" - -#include <list> -#include <utility> - -#include "net/quic/core/quic_spdy_stream.h" -#include "net/quic/core/spdy_utils.h" -#include "net/quic/platform/api/quic_bug_tracker.h" -#include "net/quic/platform/api/quic_flags.h" -#include "net/quic/platform/api/quic_logging.h" -#include "net/quic/platform/api/quic_map_util.h" -#include "net/quic/platform/api/quic_text_utils.h" -#include "net/spdy/core/spdy_protocol.h" -#include "net/tools/quic/quic_http_response_cache.h" -#include "net/tools/quic/quic_simple_server_session.h" - -using std::string; - -namespace net { - -QuicSimpleServerStream::QuicSimpleServerStream( - QuicStreamId id, - QuicSpdySession* session, - QuicHttpResponseCache* response_cache) - : QuicSpdyServerStreamBase(id, session), - content_length_(-1), - response_cache_(response_cache) {} - -QuicSimpleServerStream::~QuicSimpleServerStream() = default; - -void QuicSimpleServerStream::OnInitialHeadersComplete( - bool fin, - size_t frame_len, - const QuicHeaderList& header_list) { - QuicSpdyStream::OnInitialHeadersComplete(fin, frame_len, header_list); - if (!SpdyUtils::CopyAndValidateHeaders(header_list, &content_length_, - &request_headers_)) { - QUIC_DVLOG(1) << "Invalid headers"; - SendErrorResponse(); - } - ConsumeHeaderList(); -} - -void QuicSimpleServerStream::OnTrailingHeadersComplete( - bool fin, - size_t frame_len, - const QuicHeaderList& header_list) { - QUIC_BUG << "Server does not support receiving Trailers."; - SendErrorResponse(); -} - -void QuicSimpleServerStream::OnDataAvailable() { - while (HasBytesToRead()) { - struct iovec iov; - if (GetReadableRegions(&iov, 1) == 0) { - // No more data to read. - break; - } - QUIC_DVLOG(1) << "Stream " << id() << " processed " << iov.iov_len - << " bytes."; - body_.append(static_cast<char*>(iov.iov_base), iov.iov_len); - - if (content_length_ >= 0 && - body_.size() > static_cast<uint64_t>(content_length_)) { - QUIC_DVLOG(1) << "Body size (" << body_.size() << ") > content length (" - << content_length_ << ")."; - SendErrorResponse(); - return; - } - MarkConsumed(iov.iov_len); - } - if (!sequencer()->IsClosed()) { - sequencer()->SetUnblocked(); - return; - } - - // If the sequencer is closed, then all the body, including the fin, has been - // consumed. - OnFinRead(); - - if (write_side_closed() || fin_buffered()) { - return; - } - - SendResponse(); -} - -void QuicSimpleServerStream::PushResponse( - SpdyHeaderBlock push_request_headers) { - if (id() % 2 != 0) { - QUIC_BUG << "Client initiated stream shouldn't be used as promised stream."; - return; - } - // Change the stream state to emulate a client request. - request_headers_ = std::move(push_request_headers); - content_length_ = 0; - QUIC_DVLOG(1) << "Stream " << id() - << " ready to receive server push response."; - - // Set as if stream decompresed the headers and received fin. - QuicSpdyStream::OnInitialHeadersComplete(/*fin=*/true, 0, QuicHeaderList()); -} - -void QuicSimpleServerStream::SendResponse() { - if (request_headers_.empty()) { - QUIC_DVLOG(1) << "Request headers empty."; - SendErrorResponse(); - return; - } - - if (content_length_ > 0 && - static_cast<uint64_t>(content_length_) != body_.size()) { - QUIC_DVLOG(1) << "Content length (" << content_length_ << ") != body size (" - << body_.size() << ")."; - SendErrorResponse(); - return; - } - - if (!QuicContainsKey(request_headers_, ":authority") || - !QuicContainsKey(request_headers_, ":path")) { - QUIC_DVLOG(1) << "Request headers do not contain :authority or :path."; - SendErrorResponse(); - return; - } - - // Find response in cache. If not found, send error response. - const QuicHttpResponseCache::Response* response = nullptr; - auto authority = request_headers_.find(":authority"); - auto path = request_headers_.find(":path"); - if (authority != request_headers_.end() && path != request_headers_.end()) { - response = response_cache_->GetResponse(authority->second, path->second); - } - if (response == nullptr) { - QUIC_DVLOG(1) << "Response not found in cache."; - SendNotFoundResponse(); - return; - } - - if (response->response_type() == QuicHttpResponseCache::CLOSE_CONNECTION) { - QUIC_DVLOG(1) << "Special response: closing connection."; - CloseConnectionWithDetails(QUIC_NO_ERROR, "Toy server forcing close"); - return; - } - - if (response->response_type() == QuicHttpResponseCache::IGNORE_REQUEST) { - QUIC_DVLOG(1) << "Special response: ignoring request."; - return; - } - - // Examing response status, if it was not pure integer as typical h2 - // response status, send error response. Notice that - // QuicHttpResponseCache push urls are strictly authority + path only, - // scheme is not included (see |QuicHttpResponseCache::GetKey()|). - string request_url = request_headers_[":authority"].as_string() + - request_headers_[":path"].as_string(); - int response_code; - const SpdyHeaderBlock& response_headers = response->headers(); - if (!ParseHeaderStatusCode(response_headers, &response_code)) { - auto status = response_headers.find(":status"); - if (status == response_headers.end()) { - QUIC_LOG(WARNING) - << ":status not present in response from cache for request " - << request_url; - } else { - QUIC_LOG(WARNING) << "Illegal (non-integer) response :status from cache: " - << status->second << " for request " << request_url; - } - SendErrorResponse(); - return; - } - - if (id() % 2 == 0) { - // A server initiated stream is only used for a server push response, - // and only 200 and 30X response codes are supported for server push. - // This behavior mirrors the HTTP/2 implementation. - bool is_redirection = response_code / 100 == 3; - if (response_code != 200 && !is_redirection) { - QUIC_LOG(WARNING) << "Response to server push request " << request_url - << " result in response code " << response_code; - Reset(QUIC_STREAM_CANCELLED); - return; - } - } - std::list<QuicHttpResponseCache::ServerPushInfo> resources = - response_cache_->GetServerPushResources(request_url); - QUIC_DVLOG(1) << "Stream " << id() << " found " << resources.size() - << " push resources."; - - if (!resources.empty()) { - QuicSimpleServerSession* session = - static_cast<QuicSimpleServerSession*>(spdy_session()); - session->PromisePushResources(request_url, resources, id(), - request_headers_); - } - - QUIC_DVLOG(1) << "Stream " << id() << " sending response."; - SendHeadersAndBodyAndTrailers(response->headers().Clone(), response->body(), - response->trailers().Clone()); -} - -void QuicSimpleServerStream::SendNotFoundResponse() { - QUIC_DVLOG(1) << "Stream " << id() << " sending not found response."; - SpdyHeaderBlock headers; - headers[":status"] = "404"; - headers["content-length"] = - QuicTextUtils::Uint64ToString(strlen(kNotFoundResponseBody)); - SendHeadersAndBody(std::move(headers), kNotFoundResponseBody); -} - -void QuicSimpleServerStream::SendErrorResponse() { - QUIC_DVLOG(1) << "Stream " << id() << " sending error response."; - SpdyHeaderBlock headers; - headers[":status"] = "500"; - headers["content-length"] = - QuicTextUtils::Uint64ToString(strlen(kErrorResponseBody)); - SendHeadersAndBody(std::move(headers), kErrorResponseBody); -} - -void QuicSimpleServerStream::SendHeadersAndBody( - SpdyHeaderBlock response_headers, - QuicStringPiece body) { - SendHeadersAndBodyAndTrailers(std::move(response_headers), body, - SpdyHeaderBlock()); -} - -void QuicSimpleServerStream::SendHeadersAndBodyAndTrailers( - SpdyHeaderBlock response_headers, - QuicStringPiece body, - SpdyHeaderBlock response_trailers) { - // Send the headers, with a FIN if there's nothing else to send. - bool send_fin = (body.empty() && response_trailers.empty()); - QUIC_DLOG(INFO) << "Stream " << id() << " writing headers (fin = " << send_fin - << ") : " << response_headers.DebugString(); - WriteHeaders(std::move(response_headers), send_fin, nullptr); - if (send_fin) { - // Nothing else to send. - return; - } - - // Send the body, with a FIN if there's no trailers to send. - send_fin = response_trailers.empty(); - QUIC_DLOG(INFO) << "Stream " << id() << " writing body (fin = " << send_fin - << ") with size: " << body.size(); - if (!body.empty() || send_fin) { - WriteOrBufferData(body, send_fin, nullptr); - } - if (send_fin) { - // Nothing else to send. - return; - } - - // Send the trailers. A FIN is always sent with trailers. - QUIC_DLOG(INFO) << "Stream " << id() << " writing trailers (fin = true): " - << response_trailers.DebugString(); - WriteTrailers(std::move(response_trailers), nullptr); -} - -const char* const QuicSimpleServerStream::kErrorResponseBody = "bad"; -const char* const QuicSimpleServerStream::kNotFoundResponseBody = - "file not found"; - -} // namespace net diff --git a/chromium/net/tools/quic/quic_simple_server_stream.h b/chromium/net/tools/quic/quic_simple_server_stream.h deleted file mode 100644 index c792af1352c..00000000000 --- a/chromium/net/tools/quic/quic_simple_server_stream.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// // Use of this source code is governed by a BSD-style license that can be -// // found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_STREAM_H_ -#define NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_STREAM_H_ - -#include <string> - -#include "base/macros.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/core/quic_spdy_stream.h" -#include "net/quic/platform/api/quic_string_piece.h" -#include "net/spdy/core/spdy_framer.h" -#include "net/tools/quic/quic_http_response_cache.h" -#include "net/tools/quic/quic_spdy_server_stream_base.h" - -namespace net { - -namespace test { -class QuicSimpleServerStreamPeer; -} // namespace test - -// All this does right now is aggregate data, and on fin, send an HTTP -// response. -class QuicSimpleServerStream : public QuicSpdyServerStreamBase { - public: - QuicSimpleServerStream(QuicStreamId id, - QuicSpdySession* session, - QuicHttpResponseCache* response_cache); - ~QuicSimpleServerStream() override; - - // QuicSpdyStream - void OnInitialHeadersComplete(bool fin, - size_t frame_len, - const QuicHeaderList& header_list) override; - void OnTrailingHeadersComplete(bool fin, - size_t frame_len, - const QuicHeaderList& header_list) override; - - // QuicStream implementation called by the sequencer when there is - // data (or a FIN) to be read. - void OnDataAvailable() override; - - // Make this stream start from as if it just finished parsing an incoming - // request whose headers are equivalent to |push_request_headers|. - // Doing so will trigger this toy stream to fetch response and send it back. - virtual void PushResponse(SpdyHeaderBlock push_request_headers); - - // The response body of error responses. - static const char* const kErrorResponseBody; - static const char* const kNotFoundResponseBody; - - protected: - // Sends a basic 200 response using SendHeaders for the headers and WriteData - // for the body. - virtual void SendResponse(); - - // Sends a basic 500 response using SendHeaders for the headers and WriteData - // for the body. - virtual void SendErrorResponse(); - - // Sends a basic 404 response using SendHeaders for the headers and WriteData - // for the body. - void SendNotFoundResponse(); - - void SendHeadersAndBody(SpdyHeaderBlock response_headers, - QuicStringPiece body); - void SendHeadersAndBodyAndTrailers(SpdyHeaderBlock response_headers, - QuicStringPiece body, - SpdyHeaderBlock response_trailers); - - SpdyHeaderBlock* request_headers() { return &request_headers_; } - - const std::string& body() { return body_; } - - private: - friend class test::QuicSimpleServerStreamPeer; - - // The parsed headers received from the client. - SpdyHeaderBlock request_headers_; - int64_t content_length_; - std::string body_; - - QuicHttpResponseCache* response_cache_; // Not owned. - - DISALLOW_COPY_AND_ASSIGN(QuicSimpleServerStream); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_STREAM_H_ diff --git a/chromium/net/tools/quic/quic_simple_server_stream_test.cc b/chromium/net/tools/quic/quic_simple_server_stream_test.cc deleted file mode 100644 index 5163c42f66c..00000000000 --- a/chromium/net/tools/quic/quic_simple_server_stream_test.cc +++ /dev/null @@ -1,618 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_simple_server_stream.h" - -#include <list> -#include <memory> -#include <utility> - -#include "net/quic/core/quic_utils.h" -#include "net/quic/core/spdy_utils.h" -#include "net/quic/core/tls_server_handshaker.h" -#include "net/quic/platform/api/quic_arraysize.h" -#include "net/quic/platform/api/quic_ptr_util.h" -#include "net/quic/platform/api/quic_socket_address.h" -#include "net/quic/platform/api/quic_test.h" -#include "net/quic/test_tools/crypto_test_utils.h" -#include "net/quic/test_tools/quic_spdy_session_peer.h" -#include "net/quic/test_tools/quic_stream_peer.h" -#include "net/quic/test_tools/quic_test_utils.h" -#include "net/test/gtest_util.h" -#include "net/tools/quic/quic_http_response_cache.h" -#include "net/tools/quic/quic_simple_server_session.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using std::string; -using testing::_; -using testing::AnyNumber; -using testing::InSequence; -using testing::Invoke; -using testing::Return; -using testing::StrictMock; - -namespace net { -namespace test { - -size_t kFakeFrameLen = 60; - -class QuicSimpleServerStreamPeer : public QuicSimpleServerStream { - public: - QuicSimpleServerStreamPeer(QuicStreamId stream_id, - QuicSpdySession* session, - QuicHttpResponseCache* response_cache) - : QuicSimpleServerStream(stream_id, session, response_cache) {} - - ~QuicSimpleServerStreamPeer() override = default; - - using QuicSimpleServerStream::SendErrorResponse; - using QuicSimpleServerStream::SendResponse; - - SpdyHeaderBlock* mutable_headers() { return &request_headers_; } - - static void SendResponse(QuicSimpleServerStream* stream) { - stream->SendResponse(); - } - - static void SendErrorResponse(QuicSimpleServerStream* stream) { - stream->SendErrorResponse(); - } - - static const string& body(QuicSimpleServerStream* stream) { - return stream->body_; - } - - static int content_length(QuicSimpleServerStream* stream) { - return stream->content_length_; - } - - static SpdyHeaderBlock& headers(QuicSimpleServerStream* stream) { - return stream->request_headers_; - } -}; - -namespace { - -class MockQuicSimpleServerSession : public QuicSimpleServerSession { - public: - const size_t kMaxStreamsForTest = 100; - - explicit MockQuicSimpleServerSession( - QuicConnection* connection, - MockQuicSessionVisitor* owner, - MockQuicCryptoServerStreamHelper* helper, - QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache, - QuicHttpResponseCache* response_cache) - : QuicSimpleServerSession(DefaultQuicConfig(), - connection, - owner, - helper, - crypto_config, - compressed_certs_cache, - response_cache) { - set_max_open_incoming_streams(kMaxStreamsForTest); - set_max_open_outgoing_streams(kMaxStreamsForTest); - ON_CALL(*this, WritevData(_, _, _, _, _)) - .WillByDefault(testing::Return(QuicConsumedData(0, false))); - } - - ~MockQuicSimpleServerSession() override = default; - - MOCK_METHOD3(OnConnectionClosed, - void(QuicErrorCode error, - const string& error_details, - ConnectionCloseSource source)); - MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id)); - MOCK_METHOD5(WritevData, - QuicConsumedData(QuicStream* stream, - QuicStreamId id, - size_t write_length, - QuicStreamOffset offset, - StreamSendingState state)); - MOCK_METHOD4(OnStreamHeaderList, - void(QuicStreamId stream_id, - bool fin, - size_t frame_len, - const QuicHeaderList& header_list)); - MOCK_METHOD2(OnStreamHeadersPriority, - void(QuicStreamId stream_id, SpdyPriority priority)); - // Methods taking non-copyable types like SpdyHeaderBlock by value cannot be - // mocked directly. - size_t WriteHeaders(QuicStreamId id, - SpdyHeaderBlock headers, - bool fin, - SpdyPriority priority, - QuicReferenceCountedPointer<QuicAckListenerInterface> - ack_listener) override { - return WriteHeadersMock(id, headers, fin, priority, ack_listener); - } - MOCK_METHOD5( - WriteHeadersMock, - size_t(QuicStreamId id, - const SpdyHeaderBlock& headers, - bool fin, - SpdyPriority priority, - const QuicReferenceCountedPointer<QuicAckListenerInterface>& - ack_listener)); - MOCK_METHOD3(SendRstStream, - void(QuicStreamId stream_id, - QuicRstStreamErrorCode error, - QuicStreamOffset bytes_written)); - MOCK_METHOD1(OnHeadersHeadOfLineBlocking, void(QuicTime::Delta delta)); - // Matchers cannot be used on non-copyable types like SpdyHeaderBlock. - void PromisePushResources( - const string& request_url, - const std::list<QuicHttpResponseCache::ServerPushInfo>& resources, - QuicStreamId original_stream_id, - const SpdyHeaderBlock& original_request_headers) override { - original_request_headers_ = original_request_headers.Clone(); - PromisePushResourcesMock(request_url, resources, original_stream_id, - original_request_headers); - } - MOCK_METHOD4(PromisePushResourcesMock, - void(const string&, - const std::list<QuicHttpResponseCache::ServerPushInfo>&, - QuicStreamId, - const SpdyHeaderBlock&)); - - using QuicSession::ActivateStream; - - SpdyHeaderBlock original_request_headers_; - - private: - DISALLOW_COPY_AND_ASSIGN(MockQuicSimpleServerSession); -}; - -class QuicSimpleServerStreamTest : public QuicTestWithParam<ParsedQuicVersion> { - public: - QuicSimpleServerStreamTest() - : connection_( - new StrictMock<MockQuicConnection>(&helper_, - &alarm_factory_, - Perspective::IS_SERVER, - SupportedVersions(GetParam()))), - crypto_config_(new QuicCryptoServerConfig( - QuicCryptoServerConfig::TESTING, - QuicRandom::GetInstance(), - crypto_test_utils::ProofSourceForTesting(), - TlsServerHandshaker::CreateSslCtx())), - compressed_certs_cache_( - QuicCompressedCertsCache::kQuicCompressedCertsCacheSize), - session_(connection_, - &session_owner_, - &session_helper_, - crypto_config_.get(), - &compressed_certs_cache_, - &response_cache_), - body_("hello world") { - header_list_.OnHeaderBlockStart(); - header_list_.OnHeader(":authority", "www.google.com"); - header_list_.OnHeader(":path", "/"); - header_list_.OnHeader(":method", "POST"); - header_list_.OnHeader(":version", "HTTP/1.1"); - header_list_.OnHeader("content-length", "11"); - header_list_.OnHeaderBlockEnd(128, 128); - - // New streams rely on having the peer's flow control receive window - // negotiated in the config. - session_.config()->SetInitialStreamFlowControlWindowToSend( - kInitialStreamFlowControlWindowForTest); - session_.config()->SetInitialSessionFlowControlWindowToSend( - kInitialSessionFlowControlWindowForTest); - stream_ = new QuicSimpleServerStreamPeer( - QuicSpdySessionPeer::GetNthClientInitiatedStreamId(session_, 0), - &session_, &response_cache_); - // Register stream_ in dynamic_stream_map_ and pass ownership to session_. - session_.ActivateStream(QuicWrapUnique(stream_)); - } - - const string& StreamBody() { - return QuicSimpleServerStreamPeer::body(stream_); - } - - string StreamHeadersValue(const string& key) { - return (*stream_->mutable_headers())[key].as_string(); - } - - SpdyHeaderBlock response_headers_; - MockQuicConnectionHelper helper_; - MockAlarmFactory alarm_factory_; - StrictMock<MockQuicConnection>* connection_; - StrictMock<MockQuicSessionVisitor> session_owner_; - StrictMock<MockQuicCryptoServerStreamHelper> session_helper_; - std::unique_ptr<QuicCryptoServerConfig> crypto_config_; - QuicCompressedCertsCache compressed_certs_cache_; - QuicHttpResponseCache response_cache_; - StrictMock<MockQuicSimpleServerSession> session_; - QuicSimpleServerStreamPeer* stream_; // Owned by session_. - string body_; - QuicHeaderList header_list_; -}; - -INSTANTIATE_TEST_CASE_P(Tests, - QuicSimpleServerStreamTest, - ::testing::ValuesIn(AllSupportedVersions())); - -TEST_P(QuicSimpleServerStreamTest, TestFraming) { - EXPECT_CALL(session_, WritevData(_, _, _, _, _)) - .Times(AnyNumber()) - .WillRepeatedly(Invoke(MockQuicSession::ConsumeData)); - stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_); - stream_->OnStreamFrame( - QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_)); - EXPECT_EQ("11", StreamHeadersValue("content-length")); - EXPECT_EQ("/", StreamHeadersValue(":path")); - EXPECT_EQ("POST", StreamHeadersValue(":method")); - EXPECT_EQ(body_, StreamBody()); -} - -TEST_P(QuicSimpleServerStreamTest, TestFramingOnePacket) { - EXPECT_CALL(session_, WritevData(_, _, _, _, _)) - .Times(AnyNumber()) - .WillRepeatedly(Invoke(MockQuicSession::ConsumeData)); - - stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_); - stream_->OnStreamFrame( - QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_)); - EXPECT_EQ("11", StreamHeadersValue("content-length")); - EXPECT_EQ("/", StreamHeadersValue(":path")); - EXPECT_EQ("POST", StreamHeadersValue(":method")); - EXPECT_EQ(body_, StreamBody()); -} - -TEST_P(QuicSimpleServerStreamTest, SendQuicRstStreamNoErrorInStopReading) { - EXPECT_CALL(session_, WritevData(_, _, _, _, _)) - .Times(AnyNumber()) - .WillRepeatedly(Invoke(MockQuicSession::ConsumeData)); - - EXPECT_FALSE(stream_->fin_received()); - EXPECT_FALSE(stream_->rst_received()); - - stream_->set_fin_sent(true); - stream_->CloseWriteSide(); - - EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(1); - stream_->StopReading(); -} - -TEST_P(QuicSimpleServerStreamTest, TestFramingExtraData) { - string large_body = "hello world!!!!!!"; - - // We'll automatically write out an error (headers + body) - EXPECT_CALL(session_, WriteHeadersMock(_, _, _, _, _)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _)) - .WillOnce(Invoke(MockQuicSession::ConsumeData)); - EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0); - - stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_); - stream_->OnStreamFrame( - QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_)); - // Content length is still 11. This will register as an error and we won't - // accept the bytes. - stream_->OnStreamFrame( - QuicStreamFrame(stream_->id(), /*fin=*/true, body_.size(), large_body)); - EXPECT_EQ("11", StreamHeadersValue("content-length")); - EXPECT_EQ("/", StreamHeadersValue(":path")); - EXPECT_EQ("POST", StreamHeadersValue(":method")); -} - -TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus) { - // Send an illegal response with response status not supported by HTTP/2. - SpdyHeaderBlock* request_headers = stream_->mutable_headers(); - (*request_headers)[":path"] = "/bar"; - (*request_headers)[":authority"] = "www.google.com"; - (*request_headers)[":version"] = "HTTP/1.1"; - (*request_headers)[":method"] = "GET"; - - response_headers_[":version"] = "HTTP/1.1"; - // HTTP/2 only supports integer responsecode, so "200 OK" is illegal. - response_headers_[":status"] = "200 OK"; - response_headers_["content-length"] = "5"; - string body = "Yummm"; - response_cache_.AddResponse("www.google.com", "/bar", - std::move(response_headers_), body); - - stream_->set_fin_received(true); - - InSequence s; - EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _)) - .Times(1) - .WillOnce(Return(QuicConsumedData( - strlen(QuicSimpleServerStream::kErrorResponseBody), true))); - - QuicSimpleServerStreamPeer::SendResponse(stream_); - EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_)); - EXPECT_TRUE(stream_->write_side_closed()); -} - -TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus2) { - // Send an illegal response with response status not supported by HTTP/2. - SpdyHeaderBlock* request_headers = stream_->mutable_headers(); - (*request_headers)[":path"] = "/bar"; - (*request_headers)[":authority"] = "www.google.com"; - (*request_headers)[":version"] = "HTTP/1.1"; - (*request_headers)[":method"] = "GET"; - - response_headers_[":version"] = "HTTP/1.1"; - // HTTP/2 only supports 3-digit-integer, so "+200" is illegal. - response_headers_[":status"] = "+200"; - response_headers_["content-length"] = "5"; - string body = "Yummm"; - response_cache_.AddResponse("www.google.com", "/bar", - std::move(response_headers_), body); - - stream_->set_fin_received(true); - - InSequence s; - EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _)) - .Times(1) - .WillOnce(Return(QuicConsumedData( - strlen(QuicSimpleServerStream::kErrorResponseBody), true))); - - QuicSimpleServerStreamPeer::SendResponse(stream_); - EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_)); - EXPECT_TRUE(stream_->write_side_closed()); -} - -TEST_P(QuicSimpleServerStreamTest, SendPushResponseWith404Response) { - // Create a new promised stream with even id(). - QuicSimpleServerStreamPeer* promised_stream = - new QuicSimpleServerStreamPeer(2, &session_, &response_cache_); - session_.ActivateStream(QuicWrapUnique(promised_stream)); - - // Send a push response with response status 404, which will be regarded as - // invalid server push response. - SpdyHeaderBlock* request_headers = promised_stream->mutable_headers(); - (*request_headers)[":path"] = "/bar"; - (*request_headers)[":authority"] = "www.google.com"; - (*request_headers)[":version"] = "HTTP/1.1"; - (*request_headers)[":method"] = "GET"; - - response_headers_[":version"] = "HTTP/1.1"; - response_headers_[":status"] = "404"; - response_headers_["content-length"] = "8"; - string body = "NotFound"; - response_cache_.AddResponse("www.google.com", "/bar", - std::move(response_headers_), body); - - InSequence s; - EXPECT_CALL(session_, - SendRstStream(promised_stream->id(), QUIC_STREAM_CANCELLED, 0)); - - QuicSimpleServerStreamPeer::SendResponse(promised_stream); -} - -TEST_P(QuicSimpleServerStreamTest, SendResponseWithValidHeaders) { - // Add a request and response with valid headers. - SpdyHeaderBlock* request_headers = stream_->mutable_headers(); - (*request_headers)[":path"] = "/bar"; - (*request_headers)[":authority"] = "www.google.com"; - (*request_headers)[":version"] = "HTTP/1.1"; - (*request_headers)[":method"] = "GET"; - - response_headers_[":version"] = "HTTP/1.1"; - response_headers_[":status"] = "200"; - response_headers_["content-length"] = "5"; - string body = "Yummm"; - response_cache_.AddResponse("www.google.com", "/bar", - std::move(response_headers_), body); - stream_->set_fin_received(true); - - InSequence s; - EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _)) - .Times(1) - .WillOnce(Return(QuicConsumedData(body.length(), true))); - - QuicSimpleServerStreamPeer::SendResponse(stream_); - EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_)); - EXPECT_TRUE(stream_->write_side_closed()); -} - -TEST_P(QuicSimpleServerStreamTest, SendReponseWithPushResources) { - // Tests that if a reponse has push resources to be send, SendResponse() will - // call PromisePushResources() to handle these resources. - - // Add a request and response with valid headers into cache. - string host = "www.google.com"; - string request_path = "/foo"; - string body = "Yummm"; - QuicHttpResponseCache::ServerPushInfo push_info( - QuicUrl(host, "/bar"), SpdyHeaderBlock(), QuicStream::kDefaultPriority, - "Push body"); - std::list<QuicHttpResponseCache::ServerPushInfo> push_resources; - push_resources.push_back(push_info); - response_cache_.AddSimpleResponseWithServerPushResources( - host, request_path, 200, body, push_resources); - - SpdyHeaderBlock* request_headers = stream_->mutable_headers(); - (*request_headers)[":path"] = request_path; - (*request_headers)[":authority"] = host; - (*request_headers)[":version"] = "HTTP/1.1"; - (*request_headers)[":method"] = "GET"; - - stream_->set_fin_received(true); - InSequence s; - EXPECT_CALL( - session_, - PromisePushResourcesMock( - host + request_path, _, - QuicSpdySessionPeer::GetNthClientInitiatedStreamId(session_, 0), _)); - EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _)) - .Times(1) - .WillOnce(Return(QuicConsumedData(body.length(), true))); - QuicSimpleServerStreamPeer::SendResponse(stream_); - EXPECT_EQ(*request_headers, session_.original_request_headers_); -} - -TEST_P(QuicSimpleServerStreamTest, PushResponseOnClientInitiatedStream) { - // Calling PushResponse() on a client initialted stream is never supposed to - // happen. - EXPECT_QUIC_BUG(stream_->PushResponse(SpdyHeaderBlock()), - "Client initiated stream" - " shouldn't be used as promised stream."); -} - -TEST_P(QuicSimpleServerStreamTest, PushResponseOnServerInitiatedStream) { - // Tests that PushResponse() should take the given headers as request headers - // and fetch response from cache, and send it out. - - // Create a stream with even stream id and test against this stream. - const QuicStreamId kServerInitiatedStreamId = 2; - // Create a server initiated stream and pass it to session_. - QuicSimpleServerStreamPeer* server_initiated_stream = - new QuicSimpleServerStreamPeer(kServerInitiatedStreamId, &session_, - &response_cache_); - session_.ActivateStream(QuicWrapUnique(server_initiated_stream)); - - const string kHost = "www.foo.com"; - const string kPath = "/bar"; - SpdyHeaderBlock headers; - headers[":path"] = kPath; - headers[":authority"] = kHost; - headers[":version"] = "HTTP/1.1"; - headers[":method"] = "GET"; - - response_headers_[":version"] = "HTTP/1.1"; - response_headers_[":status"] = "200"; - response_headers_["content-length"] = "5"; - const string kBody = "Hello"; - response_cache_.AddResponse(kHost, kPath, std::move(response_headers_), - kBody); - - // Call PushResponse() should trigger stream to fetch response from cache - // and send it back. - EXPECT_CALL(session_, - WriteHeadersMock(kServerInitiatedStreamId, _, false, - server_initiated_stream->priority(), _)); - EXPECT_CALL(session_, WritevData(_, kServerInitiatedStreamId, _, _, _)) - .Times(1) - .WillOnce(Return(QuicConsumedData(kBody.size(), true))); - server_initiated_stream->PushResponse(std::move(headers)); - EXPECT_EQ(kPath, QuicSimpleServerStreamPeer::headers( - server_initiated_stream)[":path"] - .as_string()); - EXPECT_EQ("GET", QuicSimpleServerStreamPeer::headers( - server_initiated_stream)[":method"] - .as_string()); -} - -TEST_P(QuicSimpleServerStreamTest, TestSendErrorResponse) { - EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0); - - stream_->set_fin_received(true); - - InSequence s; - EXPECT_CALL(session_, WriteHeadersMock(_, _, _, _, _)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _)) - .Times(1) - .WillOnce(Return(QuicConsumedData(3, true))); - - QuicSimpleServerStreamPeer::SendErrorResponse(stream_); - EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_)); - EXPECT_TRUE(stream_->write_side_closed()); -} - -TEST_P(QuicSimpleServerStreamTest, InvalidMultipleContentLength) { - EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0); - - SpdyHeaderBlock request_headers; - // \000 is a way to write the null byte when followed by a literal digit. - header_list_.OnHeader("content-length", QuicStringPiece("11\00012", 5)); - - EXPECT_CALL(session_, WriteHeadersMock(_, _, _, _, _)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _)) - .Times(AnyNumber()) - .WillRepeatedly(Invoke(MockQuicSession::ConsumeData)); - stream_->OnStreamHeaderList(true, kFakeFrameLen, header_list_); - - EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream_)); - EXPECT_TRUE(stream_->reading_stopped()); - EXPECT_TRUE(stream_->write_side_closed()); -} - -TEST_P(QuicSimpleServerStreamTest, InvalidLeadingNullContentLength) { - EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0); - - SpdyHeaderBlock request_headers; - // \000 is a way to write the null byte when followed by a literal digit. - header_list_.OnHeader("content-length", QuicStringPiece("\00012", 3)); - - EXPECT_CALL(session_, WriteHeadersMock(_, _, _, _, _)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _)) - .Times(AnyNumber()) - .WillRepeatedly(Invoke(MockQuicSession::ConsumeData)); - stream_->OnStreamHeaderList(true, kFakeFrameLen, header_list_); - - EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream_)); - EXPECT_TRUE(stream_->reading_stopped()); - EXPECT_TRUE(stream_->write_side_closed()); -} - -TEST_P(QuicSimpleServerStreamTest, ValidMultipleContentLength) { - SpdyHeaderBlock request_headers; - // \000 is a way to write the null byte when followed by a literal digit. - header_list_.OnHeader("content-length", QuicStringPiece("11\00011", 5)); - - stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_); - - EXPECT_EQ(11, QuicSimpleServerStreamPeer::content_length(stream_)); - EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_)); - EXPECT_FALSE(stream_->reading_stopped()); - EXPECT_FALSE(stream_->write_side_closed()); -} - -TEST_P(QuicSimpleServerStreamTest, - DoNotSendQuicRstStreamNoErrorWithRstReceived) { - InSequence s; - EXPECT_FALSE(stream_->reading_stopped()); - - EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0); - EXPECT_CALL(session_, SendRstStream(_, QUIC_RST_ACKNOWLEDGEMENT, _)).Times(1); - QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(), - QUIC_STREAM_CANCELLED, 1234); - stream_->OnStreamReset(rst_frame); - - EXPECT_TRUE(stream_->reading_stopped()); - EXPECT_TRUE(stream_->write_side_closed()); -} - -TEST_P(QuicSimpleServerStreamTest, InvalidHeadersWithFin) { - char arr[] = { - 0x3a, 0x68, 0x6f, 0x73, // :hos - 0x74, 0x00, 0x00, 0x00, // t... - 0x00, 0x00, 0x00, 0x00, // .... - 0x07, 0x3a, 0x6d, 0x65, // .:me - 0x74, 0x68, 0x6f, 0x64, // thod - 0x00, 0x00, 0x00, 0x03, // .... - 0x47, 0x45, 0x54, 0x00, // GET. - 0x00, 0x00, 0x05, 0x3a, // ...: - 0x70, 0x61, 0x74, 0x68, // path - 0x00, 0x00, 0x00, 0x04, // .... - 0x2f, 0x66, 0x6f, 0x6f, // /foo - 0x00, 0x00, 0x00, 0x07, // .... - 0x3a, 0x73, 0x63, 0x68, // :sch - 0x65, 0x6d, 0x65, 0x00, // eme. - 0x00, 0x00, 0x00, 0x00, // .... - 0x00, 0x00, 0x08, 0x3a, // ...: - 0x76, 0x65, 0x72, 0x73, // vers - 0x96, 0x6f, 0x6e, 0x00, // <i(69)>on. - 0x00, 0x00, 0x08, 0x48, // ...H - 0x54, 0x54, 0x50, 0x2f, // TTP/ - 0x31, 0x2e, 0x31, // 1.1 - }; - QuicStringPiece data(arr, QUIC_ARRAYSIZE(arr)); - QuicStreamFrame frame(stream_->id(), true, 0, data); - // Verify that we don't crash when we get a invalid headers in stream frame. - stream_->OnStreamFrame(frame); -} - -} // namespace -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/quic_simple_server_test.cc b/chromium/net/tools/quic/quic_simple_server_test.cc index 66bbd33774b..2b99b65b99a 100644 --- a/chromium/net/tools/quic/quic_simple_server_test.cc +++ b/chromium/net/tools/quic/quic_simple_server_test.cc @@ -4,14 +4,15 @@ #include "net/tools/quic/quic_simple_server.h" -#include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_crypto_stream.h" -#include "net/quic/core/quic_utils.h" -#include "net/quic/core/tls_server_handshaker.h" -#include "net/quic/platform/api/quic_test.h" -#include "net/quic/test_tools/crypto_test_utils.h" -#include "net/quic/test_tools/mock_quic_dispatcher.h" -#include "net/quic/test_tools/quic_test_utils.h" +#include "net/third_party/quic/core/crypto/quic_random.h" +#include "net/third_party/quic/core/quic_crypto_stream.h" +#include "net/third_party/quic/core/quic_utils.h" +#include "net/third_party/quic/core/tls_server_handshaker.h" +#include "net/third_party/quic/platform/api/quic_test.h" +#include "net/third_party/quic/test_tools/crypto_test_utils.h" +#include "net/third_party/quic/test_tools/mock_quic_dispatcher.h" +#include "net/third_party/quic/test_tools/quic_test_utils.h" +#include "net/third_party/quic/tools/quic_memory_cache_backend.h" #include "net/tools/quic/quic_simple_server_session_helper.h" #include "testing/gtest/include/gtest/gtest.h" @@ -38,7 +39,7 @@ class QuicChromeServerDispatchPacketTest : public QuicTest { std::unique_ptr<QuicCryptoServerStream::Helper>( new QuicSimpleServerSessionHelper(QuicRandom::GetInstance())), std::unique_ptr<MockAlarmFactory>(new net::test::MockAlarmFactory), - &response_cache_) { + &memory_cache_backend_) { dispatcher_.InitializeWithWriter(nullptr); } @@ -54,7 +55,7 @@ class QuicChromeServerDispatchPacketTest : public QuicTest { QuicCryptoServerConfig crypto_config_; QuicVersionManager version_manager_; net::test::MockQuicDispatcher dispatcher_; - QuicHttpResponseCache response_cache_; + QuicMemoryCacheBackend memory_cache_backend_; }; TEST_F(QuicChromeServerDispatchPacketTest, DispatchPacket) { diff --git a/chromium/net/tools/quic/quic_spdy_client_base.cc b/chromium/net/tools/quic/quic_spdy_client_base.cc deleted file mode 100644 index b7bf7c3f053..00000000000 --- a/chromium/net/tools/quic/quic_spdy_client_base.cc +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright (c) 2015 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/tools/quic/quic_spdy_client_base.h" - -#include "net/quic/core/crypto/quic_random.h" -#include "net/quic/core/quic_server_id.h" -#include "net/quic/core/spdy_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" -#include "net/quic/platform/api/quic_text_utils.h" - -using base::StringToInt; -using std::string; - -namespace net { - -void QuicSpdyClientBase::ClientQuicDataToResend::Resend() { - client_->SendRequest(*headers_, body_, fin_); - headers_ = nullptr; -} - -QuicSpdyClientBase::QuicDataToResend::QuicDataToResend( - std::unique_ptr<SpdyHeaderBlock> headers, - QuicStringPiece body, - bool fin) - : headers_(std::move(headers)), body_(body), fin_(fin) {} - -QuicSpdyClientBase::QuicDataToResend::~QuicDataToResend() = default; - -QuicSpdyClientBase::QuicSpdyClientBase( - const QuicServerId& server_id, - const ParsedQuicVersionVector& supported_versions, - const QuicConfig& config, - QuicConnectionHelperInterface* helper, - QuicAlarmFactory* alarm_factory, - std::unique_ptr<NetworkHelper> network_helper, - std::unique_ptr<ProofVerifier> proof_verifier) - : QuicClientBase(server_id, - supported_versions, - config, - helper, - alarm_factory, - std::move(network_helper), - std::move(proof_verifier)), - store_response_(false), - latest_response_code_(-1) {} - -QuicSpdyClientBase::~QuicSpdyClientBase() { - // We own the push promise index. We need to explicitly kill - // the session before the push promise index goes out of scope. - ResetSession(); -} - -QuicSpdyClientSession* QuicSpdyClientBase::client_session() { - return static_cast<QuicSpdyClientSession*>(QuicClientBase::session()); -} - -void QuicSpdyClientBase::InitializeSession() { - client_session()->Initialize(); - client_session()->CryptoConnect(); -} - -void QuicSpdyClientBase::OnClose(QuicSpdyStream* stream) { - DCHECK(stream != nullptr); - QuicSpdyClientStream* client_stream = - static_cast<QuicSpdyClientStream*>(stream); - - const SpdyHeaderBlock& response_headers = client_stream->response_headers(); - if (response_listener_ != nullptr) { - response_listener_->OnCompleteResponse(stream->id(), response_headers, - client_stream->data()); - } - - // Store response headers and body. - if (store_response_) { - auto status = response_headers.find(":status"); - if (status == response_headers.end() || - !QuicTextUtils::StringToInt(status->second, &latest_response_code_)) { - QUIC_LOG(ERROR) << "Invalid response headers"; - } - latest_response_headers_ = response_headers.DebugString(); - preliminary_response_headers_ = - client_stream->preliminary_headers().DebugString(); - latest_response_header_block_ = response_headers.Clone(); - latest_response_body_ = client_stream->data(); - latest_response_trailers_ = - client_stream->received_trailers().DebugString(); - } -} - -std::unique_ptr<QuicSession> QuicSpdyClientBase::CreateQuicClientSession( - QuicConnection* connection) { - return QuicMakeUnique<QuicSpdyClientSession>(*config(), connection, - server_id(), crypto_config(), - &push_promise_index_); -} - -void QuicSpdyClientBase::SendRequest(const SpdyHeaderBlock& headers, - QuicStringPiece body, - bool fin) { - QuicClientPushPromiseIndex::TryHandle* handle; - QuicAsyncStatus rv = push_promise_index()->Try(headers, this, &handle); - if (rv == QUIC_SUCCESS) - return; - - if (rv == QUIC_PENDING) { - // May need to retry request if asynchronous rendezvous fails. - AddPromiseDataToResend(headers, body, fin); - return; - } - - QuicSpdyClientStream* stream = CreateClientStream(); - if (stream == nullptr) { - QUIC_BUG << "stream creation failed!"; - return; - } - stream->SendRequest(headers.Clone(), body, fin); - // Record this in case we need to resend. - MaybeAddDataToResend(headers, body, fin); -} - -void QuicSpdyClientBase::SendRequestAndWaitForResponse( - const SpdyHeaderBlock& headers, - QuicStringPiece body, - bool fin) { - SendRequest(headers, body, fin); - while (WaitForEvents()) { - } -} - -void QuicSpdyClientBase::SendRequestsAndWaitForResponse( - const std::vector<string>& url_list) { - for (size_t i = 0; i < url_list.size(); ++i) { - SpdyHeaderBlock headers; - if (!SpdyUtils::PopulateHeaderBlockFromUrl(url_list[i], &headers)) { - QUIC_BUG << "Unable to create request"; - continue; - } - SendRequest(headers, "", true); - } - while (WaitForEvents()) { - } -} - -QuicSpdyClientStream* QuicSpdyClientBase::CreateClientStream() { - if (!connected()) { - return nullptr; - } - - auto* stream = static_cast<QuicSpdyClientStream*>( - client_session()->CreateOutgoingDynamicStream()); - if (stream) { - stream->SetPriority(QuicStream::kDefaultPriority); - stream->set_visitor(this); - } - return stream; -} - -int QuicSpdyClientBase::GetNumSentClientHellosFromSession() { - return client_session()->GetNumSentClientHellos(); -} - -int QuicSpdyClientBase::GetNumReceivedServerConfigUpdatesFromSession() { - return client_session()->GetNumReceivedServerConfigUpdates(); -} - -void QuicSpdyClientBase::MaybeAddDataToResend(const SpdyHeaderBlock& headers, - QuicStringPiece body, - bool fin) { - if (!GetQuicReloadableFlag(enable_quic_stateless_reject_support)) { - return; - } - - if (client_session()->IsCryptoHandshakeConfirmed()) { - // The handshake is confirmed. No need to continue saving requests to - // resend. - data_to_resend_on_connect_.clear(); - return; - } - - // The handshake is not confirmed. Push the data onto the queue of data to - // resend if statelessly rejected. - std::unique_ptr<SpdyHeaderBlock> new_headers( - new SpdyHeaderBlock(headers.Clone())); - std::unique_ptr<QuicDataToResend> data_to_resend( - new ClientQuicDataToResend(std::move(new_headers), body, fin, this)); - MaybeAddQuicDataToResend(std::move(data_to_resend)); -} - -void QuicSpdyClientBase::MaybeAddQuicDataToResend( - std::unique_ptr<QuicDataToResend> data_to_resend) { - data_to_resend_on_connect_.push_back(std::move(data_to_resend)); -} - -void QuicSpdyClientBase::ClearDataToResend() { - data_to_resend_on_connect_.clear(); -} - -void QuicSpdyClientBase::ResendSavedData() { - // Calling Resend will re-enqueue the data, so swap out - // data_to_resend_on_connect_ before iterating. - std::vector<std::unique_ptr<QuicDataToResend>> old_data; - old_data.swap(data_to_resend_on_connect_); - for (const auto& data : old_data) { - data->Resend(); - } -} - -void QuicSpdyClientBase::AddPromiseDataToResend(const SpdyHeaderBlock& headers, - QuicStringPiece body, - bool fin) { - std::unique_ptr<SpdyHeaderBlock> new_headers( - new SpdyHeaderBlock(headers.Clone())); - push_promise_data_to_resend_.reset( - new ClientQuicDataToResend(std::move(new_headers), body, fin, this)); -} - -bool QuicSpdyClientBase::CheckVary(const SpdyHeaderBlock& client_request, - const SpdyHeaderBlock& promise_request, - const SpdyHeaderBlock& promise_response) { - return true; -} - -void QuicSpdyClientBase::OnRendezvousResult(QuicSpdyStream* stream) { - std::unique_ptr<ClientQuicDataToResend> data_to_resend = - std::move(push_promise_data_to_resend_); - if (stream) { - stream->set_visitor(this); - stream->OnDataAvailable(); - } else if (data_to_resend) { - data_to_resend->Resend(); - } -} - -size_t QuicSpdyClientBase::latest_response_code() const { - QUIC_BUG_IF(!store_response_) << "Response not stored!"; - return latest_response_code_; -} - -const string& QuicSpdyClientBase::latest_response_headers() const { - QUIC_BUG_IF(!store_response_) << "Response not stored!"; - return latest_response_headers_; -} - -const string& QuicSpdyClientBase::preliminary_response_headers() const { - QUIC_BUG_IF(!store_response_) << "Response not stored!"; - return preliminary_response_headers_; -} - -const SpdyHeaderBlock& QuicSpdyClientBase::latest_response_header_block() - const { - QUIC_BUG_IF(!store_response_) << "Response not stored!"; - return latest_response_header_block_; -} - -const string& QuicSpdyClientBase::latest_response_body() const { - QUIC_BUG_IF(!store_response_) << "Response not stored!"; - return latest_response_body_; -} - -const string& QuicSpdyClientBase::latest_response_trailers() const { - QUIC_BUG_IF(!store_response_) << "Response not stored!"; - return latest_response_trailers_; -} - -} // namespace net diff --git a/chromium/net/tools/quic/quic_spdy_client_base.h b/chromium/net/tools/quic/quic_spdy_client_base.h deleted file mode 100644 index 468e712c1de..00000000000 --- a/chromium/net/tools/quic/quic_spdy_client_base.h +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// A base class for the toy client, which connects to a specified port and sends -// QUIC request to that endpoint. - -#ifndef NET_TOOLS_QUIC_QUIC_SPDY_CLIENT_BASE_H_ -#define NET_TOOLS_QUIC_QUIC_SPDY_CLIENT_BASE_H_ - -#include <string> - -#include "base/macros.h" -#include "net/quic/core/crypto/crypto_handshake.h" -#include "net/quic/core/quic_client_push_promise_index.h" -#include "net/quic/core/quic_config.h" -#include "net/quic/platform/api/quic_socket_address.h" -#include "net/quic/platform/api/quic_string_piece.h" -#include "net/tools/quic/quic_client_base.h" -#include "net/tools/quic/quic_spdy_client_session.h" -#include "net/tools/quic/quic_spdy_client_stream.h" - -namespace net { - -class ProofVerifier; -class QuicServerId; - -class QuicSpdyClientBase : public QuicClientBase, - public QuicClientPushPromiseIndex::Delegate, - public QuicSpdyStream::Visitor { - public: - // A ResponseListener is notified when a complete response is received. - class ResponseListener { - public: - ResponseListener() {} - virtual ~ResponseListener() {} - virtual void OnCompleteResponse(QuicStreamId id, - const SpdyHeaderBlock& response_headers, - const std::string& response_body) = 0; - }; - - // The client uses these objects to keep track of any data to resend upon - // receipt of a stateless reject. Recall that the client API allows callers - // to optimistically send data to the server prior to handshake-confirmation. - // If the client subsequently receives a stateless reject, it must tear down - // its existing session, create a new session, and resend all previously sent - // data. It uses these objects to keep track of all the sent data, and to - // resend the data upon a subsequent connection. - class QuicDataToResend { - public: - // |headers| may be null, since it's possible to send data without headers. - QuicDataToResend(std::unique_ptr<SpdyHeaderBlock> headers, - QuicStringPiece body, - bool fin); - - virtual ~QuicDataToResend(); - - // Must be overridden by specific classes with the actual method for - // re-sending data. - virtual void Resend() = 0; - - protected: - std::unique_ptr<SpdyHeaderBlock> headers_; - QuicStringPiece body_; - bool fin_; - - private: - DISALLOW_COPY_AND_ASSIGN(QuicDataToResend); - }; - - QuicSpdyClientBase(const QuicServerId& server_id, - const ParsedQuicVersionVector& supported_versions, - const QuicConfig& config, - QuicConnectionHelperInterface* helper, - QuicAlarmFactory* alarm_factory, - std::unique_ptr<NetworkHelper> network_helper, - std::unique_ptr<ProofVerifier> proof_verifier); - - ~QuicSpdyClientBase() override; - - // QuicSpdyStream::Visitor - void OnClose(QuicSpdyStream* stream) override; - - // A spdy session has to call CryptoConnect on top of the regular - // initialization. - void InitializeSession() override; - - // Sends an HTTP request and does not wait for response before returning. - void SendRequest(const SpdyHeaderBlock& headers, - QuicStringPiece body, - bool fin); - - // Sends an HTTP request and waits for response before returning. - void SendRequestAndWaitForResponse(const SpdyHeaderBlock& headers, - QuicStringPiece body, - bool fin); - - // Sends a request simple GET for each URL in |url_list|, and then waits for - // each to complete. - void SendRequestsAndWaitForResponse(const std::vector<std::string>& url_list); - - // Returns a newly created QuicSpdyClientStream. - QuicSpdyClientStream* CreateClientStream(); - - // Returns a the session used for this client downcasted to a - // QuicSpdyClientSession. - QuicSpdyClientSession* client_session(); - - QuicClientPushPromiseIndex* push_promise_index() { - return &push_promise_index_; - } - - bool CheckVary(const SpdyHeaderBlock& client_request, - const SpdyHeaderBlock& promise_request, - const SpdyHeaderBlock& promise_response) override; - void OnRendezvousResult(QuicSpdyStream*) override; - - // If the crypto handshake has not yet been confirmed, adds the data to the - // queue of data to resend if the client receives a stateless reject. - // Otherwise, deletes the data. - void MaybeAddQuicDataToResend( - std::unique_ptr<QuicDataToResend> data_to_resend); - - void set_store_response(bool val) { store_response_ = val; } - - size_t latest_response_code() const; - const std::string& latest_response_headers() const; - const std::string& preliminary_response_headers() const; - const SpdyHeaderBlock& latest_response_header_block() const; - const std::string& latest_response_body() const; - const std::string& latest_response_trailers() const; - - void set_response_listener(std::unique_ptr<ResponseListener> listener) { - response_listener_ = std::move(listener); - } - - protected: - int GetNumSentClientHellosFromSession() override; - int GetNumReceivedServerConfigUpdatesFromSession() override; - - // Takes ownership of |connection|. - std::unique_ptr<QuicSession> CreateQuicClientSession( - QuicConnection* connection) override; - - // If the crypto handshake has not yet been confirmed, adds the data to the - // queue of data to resend if the client receives a stateless reject. - // Otherwise, deletes the data. - void MaybeAddDataToResend(const SpdyHeaderBlock& headers, - QuicStringPiece body, - bool fin); - - void ClearDataToResend() override; - - void ResendSavedData() override; - - void AddPromiseDataToResend(const SpdyHeaderBlock& headers, - QuicStringPiece body, - bool fin); - - private: - // Specific QuicClient class for storing data to resend. - class ClientQuicDataToResend : public QuicDataToResend { - public: - ClientQuicDataToResend(std::unique_ptr<SpdyHeaderBlock> headers, - QuicStringPiece body, - bool fin, - QuicSpdyClientBase* client) - : QuicDataToResend(std::move(headers), body, fin), client_(client) { - DCHECK(headers_); - DCHECK(client); - } - - ~ClientQuicDataToResend() override {} - - void Resend() override; - - private: - QuicSpdyClientBase* client_; - - DISALLOW_COPY_AND_ASSIGN(ClientQuicDataToResend); - }; - - // Index of pending promised streams. Must outlive |session_|. - QuicClientPushPromiseIndex push_promise_index_; - - // If true, store the latest response code, headers, and body. - bool store_response_; - // HTTP response code from most recent response. - int latest_response_code_; - // HTTP/2 headers from most recent response. - std::string latest_response_headers_; - // preliminary 100 Continue HTTP/2 headers from most recent response, if any. - std::string preliminary_response_headers_; - // HTTP/2 headers from most recent response. - SpdyHeaderBlock latest_response_header_block_; - // Body of most recent response. - std::string latest_response_body_; - // HTTP/2 trailers from most recent response. - std::string latest_response_trailers_; - - // Listens for full responses. - std::unique_ptr<ResponseListener> response_listener_; - - // Keeps track of any data that must be resent upon a subsequent successful - // connection, in case the client receives a stateless reject. - std::vector<std::unique_ptr<QuicDataToResend>> data_to_resend_on_connect_; - - std::unique_ptr<ClientQuicDataToResend> push_promise_data_to_resend_; - - DISALLOW_COPY_AND_ASSIGN(QuicSpdyClientBase); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_SPDY_CLIENT_BASE_H_ diff --git a/chromium/net/tools/quic/quic_spdy_client_session.cc b/chromium/net/tools/quic/quic_spdy_client_session.cc deleted file mode 100644 index c178cccb2e9..00000000000 --- a/chromium/net/tools/quic/quic_spdy_client_session.cc +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_spdy_client_session.h" - -#include "net/log/net_log_with_source.h" -#include "net/quic/chromium/crypto/proof_verifier_chromium.h" -#include "net/quic/core/crypto/crypto_protocol.h" -#include "net/quic/core/quic_server_id.h" -#include "net/quic/core/spdy_utils.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" - -namespace net { - -QuicSpdyClientSession::QuicSpdyClientSession( - const QuicConfig& config, - QuicConnection* connection, - const QuicServerId& server_id, - QuicCryptoClientConfig* crypto_config, - QuicClientPushPromiseIndex* push_promise_index) - : QuicSpdyClientSessionBase(connection, push_promise_index, config), - server_id_(server_id), - crypto_config_(crypto_config), - respect_goaway_(true) {} - -QuicSpdyClientSession::~QuicSpdyClientSession() = default; - -void QuicSpdyClientSession::Initialize() { - crypto_stream_ = CreateQuicCryptoStream(); - QuicSpdyClientSessionBase::Initialize(); -} - -void QuicSpdyClientSession::OnProofValid( - const QuicCryptoClientConfig::CachedState& /*cached*/) {} - -void QuicSpdyClientSession::OnProofVerifyDetailsAvailable( - const ProofVerifyDetails& /*verify_details*/) {} - -bool QuicSpdyClientSession::ShouldCreateOutgoingDynamicStream() { - if (!crypto_stream_->encryption_established()) { - QUIC_DLOG(INFO) << "Encryption not active so no outgoing stream created."; - return false; - } - if (GetNumOpenOutgoingStreams() >= max_open_outgoing_streams()) { - QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. " - << "Already " << GetNumOpenOutgoingStreams() << " open."; - return false; - } - if (goaway_received() && respect_goaway_) { - QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. " - << "Already received goaway."; - return false; - } - return true; -} - -QuicSpdyClientStream* QuicSpdyClientSession::CreateOutgoingDynamicStream() { - if (!ShouldCreateOutgoingDynamicStream()) { - return nullptr; - } - std::unique_ptr<QuicSpdyClientStream> stream = CreateClientStream(); - QuicSpdyClientStream* stream_ptr = stream.get(); - ActivateStream(std::move(stream)); - return stream_ptr; -} - -std::unique_ptr<QuicSpdyClientStream> -QuicSpdyClientSession::CreateClientStream() { - return QuicMakeUnique<QuicSpdyClientStream>(GetNextOutgoingStreamId(), this); -} - -QuicCryptoClientStreamBase* QuicSpdyClientSession::GetMutableCryptoStream() { - return crypto_stream_.get(); -} - -const QuicCryptoClientStreamBase* QuicSpdyClientSession::GetCryptoStream() - const { - return crypto_stream_.get(); -} - -void QuicSpdyClientSession::CryptoConnect() { - DCHECK(flow_controller()); - crypto_stream_->CryptoConnect(); -} - -int QuicSpdyClientSession::GetNumSentClientHellos() const { - return crypto_stream_->num_sent_client_hellos(); -} - -int QuicSpdyClientSession::GetNumReceivedServerConfigUpdates() const { - return crypto_stream_->num_scup_messages_received(); -} - -bool QuicSpdyClientSession::ShouldCreateIncomingDynamicStream(QuicStreamId id) { - if (!connection()->connected()) { - QUIC_BUG << "ShouldCreateIncomingDynamicStream called when disconnected"; - return false; - } - if (goaway_received() && respect_goaway_) { - QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. " - << "Already received goaway."; - return false; - } - if (id % 2 != 0) { - QUIC_LOG(WARNING) << "Received invalid push stream id " << id; - connection()->CloseConnection( - QUIC_INVALID_STREAM_ID, "Server created odd numbered stream", - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - return false; - } - return true; -} - -QuicSpdyStream* QuicSpdyClientSession::CreateIncomingDynamicStream( - QuicStreamId id) { - if (!ShouldCreateIncomingDynamicStream(id)) { - return nullptr; - } - QuicSpdyStream* stream = new QuicSpdyClientStream(id, this); - stream->CloseWriteSide(); - ActivateStream(QuicWrapUnique(stream)); - return stream; -} - -std::unique_ptr<QuicCryptoClientStreamBase> -QuicSpdyClientSession::CreateQuicCryptoStream() { - return QuicMakeUnique<QuicCryptoClientStream>( - server_id_, this, new ProofVerifyContextChromium(0, NetLogWithSource()), - crypto_config_, this); -} - -bool QuicSpdyClientSession::IsAuthorized(const QuicString& authority) { - return true; -} - -} // namespace net diff --git a/chromium/net/tools/quic/quic_spdy_client_session.h b/chromium/net/tools/quic/quic_spdy_client_session.h deleted file mode 100644 index a5a0cbf14fb..00000000000 --- a/chromium/net/tools/quic/quic_spdy_client_session.h +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// A client specific QuicSession subclass. - -#ifndef NET_TOOLS_QUIC_QUIC_SPDY_CLIENT_SESSION_H_ -#define NET_TOOLS_QUIC_QUIC_SPDY_CLIENT_SESSION_H_ - -#include <memory> - -#include "base/macros.h" -#include "net/quic/core/quic_crypto_client_stream.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/core/quic_spdy_client_session_base.h" -#include "net/quic/platform/api/quic_string.h" -#include "net/tools/quic/quic_spdy_client_stream.h" - -namespace net { - -class QuicConnection; -class QuicServerId; - -class QuicSpdyClientSession : public QuicSpdyClientSessionBase { - public: - // Takes ownership of |connection|. Caller retains ownership of - // |promised_by_url|. - QuicSpdyClientSession(const QuicConfig& config, - QuicConnection* connection, - const QuicServerId& server_id, - QuicCryptoClientConfig* crypto_config, - QuicClientPushPromiseIndex* push_promise_index); - ~QuicSpdyClientSession() override; - // Set up the QuicSpdyClientSession. Must be called prior to use. - void Initialize() override; - - // QuicSession methods: - QuicSpdyClientStream* CreateOutgoingDynamicStream() override; - QuicCryptoClientStreamBase* GetMutableCryptoStream() override; - const QuicCryptoClientStreamBase* GetCryptoStream() const override; - - bool IsAuthorized(const QuicString& authority) override; - - // QuicSpdyClientSessionBase methods: - void OnProofValid(const QuicCryptoClientConfig::CachedState& cached) override; - void OnProofVerifyDetailsAvailable( - const ProofVerifyDetails& verify_details) override; - - // Performs a crypto handshake with the server. - virtual void CryptoConnect(); - - // Returns the number of client hello messages that have been sent on the - // crypto stream. If the handshake has completed then this is one greater - // than the number of round-trips needed for the handshake. - int GetNumSentClientHellos() const; - - int GetNumReceivedServerConfigUpdates() const; - - void set_respect_goaway(bool respect_goaway) { - respect_goaway_ = respect_goaway; - } - - protected: - // QuicSession methods: - QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override; - // If an outgoing stream can be created, return true. - bool ShouldCreateOutgoingDynamicStream() override; - - // If an incoming stream can be created, return true. - bool ShouldCreateIncomingDynamicStream(QuicStreamId id) override; - - // Create the crypto stream. Called by Initialize(). - virtual std::unique_ptr<QuicCryptoClientStreamBase> CreateQuicCryptoStream(); - - // Unlike CreateOutgoingDynamicStream, which applies a bunch of sanity checks, - // this simply returns a new QuicSpdyClientStream. This may be used by - // subclasses which want to use a subclass of QuicSpdyClientStream for streams - // but wish to use the sanity checks in CreateOutgoingDynamicStream. - virtual std::unique_ptr<QuicSpdyClientStream> CreateClientStream(); - - const QuicServerId& server_id() { return server_id_; } - QuicCryptoClientConfig* crypto_config() { return crypto_config_; } - - private: - std::unique_ptr<QuicCryptoClientStreamBase> crypto_stream_; - QuicServerId server_id_; - QuicCryptoClientConfig* crypto_config_; - - // If this is set to false, the client will ignore server GOAWAYs and allow - // the creation of streams regardless of the high chance they will fail. - bool respect_goaway_; - - DISALLOW_COPY_AND_ASSIGN(QuicSpdyClientSession); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_SPDY_CLIENT_SESSION_H_ diff --git a/chromium/net/tools/quic/quic_spdy_client_session_test.cc b/chromium/net/tools/quic/quic_spdy_client_session_test.cc deleted file mode 100644 index b805d89e93f..00000000000 --- a/chromium/net/tools/quic/quic_spdy_client_session_test.cc +++ /dev/null @@ -1,611 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_spdy_client_session.h" - -#include <vector> - -#include "net/quic/core/crypto/aes_128_gcm_12_encrypter.h" -#include "net/quic/core/spdy_utils.h" -#include "net/quic/core/tls_client_handshaker.h" -#include "net/quic/platform/api/quic_flags.h" -#include "net/quic/platform/api/quic_ptr_util.h" -#include "net/quic/platform/api/quic_socket_address.h" -#include "net/quic/platform/api/quic_str_cat.h" -#include "net/quic/platform/api/quic_string.h" -#include "net/quic/platform/api/quic_test.h" -#include "net/quic/test_tools/crypto_test_utils.h" -#include "net/quic/test_tools/mock_quic_spdy_client_stream.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_packet_creator_peer.h" -#include "net/quic/test_tools/quic_spdy_session_peer.h" -#include "net/quic/test_tools/quic_test_utils.h" -#include "net/tools/quic/quic_spdy_client_stream.h" - -using google::protobuf::implicit_cast; -using testing::_; -using testing::AnyNumber; -using testing::Invoke; -using testing::Truly; - -namespace net { -namespace test { -namespace { - -const char kServerHostname[] = "test.example.com"; -const uint16_t kPort = 443; - -class TestQuicSpdyClientSession : public QuicSpdyClientSession { - public: - explicit TestQuicSpdyClientSession( - const QuicConfig& config, - QuicConnection* connection, - const QuicServerId& server_id, - QuicCryptoClientConfig* crypto_config, - QuicClientPushPromiseIndex* push_promise_index) - : QuicSpdyClientSession(config, - connection, - server_id, - crypto_config, - push_promise_index) {} - - std::unique_ptr<QuicSpdyClientStream> CreateClientStream() override { - return QuicMakeUnique<MockQuicSpdyClientStream>(GetNextOutgoingStreamId(), - this); - } - - MockQuicSpdyClientStream* CreateIncomingDynamicStream( - QuicStreamId id) override { - MockQuicSpdyClientStream* stream = new MockQuicSpdyClientStream(id, this); - ActivateStream(QuicWrapUnique(stream)); - return stream; - } -}; - -class QuicSpdyClientSessionTest : public QuicTestWithParam<ParsedQuicVersion> { - protected: - QuicSpdyClientSessionTest() - : crypto_config_(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()), - promised_stream_id_(kInvalidStreamId), - associated_stream_id_(kInvalidStreamId) { - Initialize(); - // Advance the time, because timers do not like uninitialized times. - connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1)); - } - - ~QuicSpdyClientSessionTest() override { - // Session must be destroyed before promised_by_url_ - session_.reset(nullptr); - } - - void Initialize() { - session_.reset(); - connection_ = new PacketSavingConnection(&helper_, &alarm_factory_, - Perspective::IS_CLIENT, - SupportedVersions(GetParam())); - session_ = QuicMakeUnique<TestQuicSpdyClientSession>( - DefaultQuicConfig(), connection_, - QuicServerId(kServerHostname, kPort, PRIVACY_MODE_DISABLED), - &crypto_config_, &push_promise_index_); - session_->Initialize(); - push_promise_[":path"] = "/bar"; - push_promise_[":authority"] = "www.google.com"; - push_promise_[":version"] = "HTTP/1.1"; - push_promise_[":method"] = "GET"; - push_promise_[":scheme"] = "https"; - promise_url_ = SpdyUtils::GetPromisedUrlFromHeaders(push_promise_); - promised_stream_id_ = - QuicSpdySessionPeer::GetNthServerInitiatedStreamId(*session_, 0); - associated_stream_id_ = - QuicSpdySessionPeer::GetNthClientInitiatedStreamId(*session_, 0); - } - - void CompleteCryptoHandshake() { - CompleteCryptoHandshake(kDefaultMaxStreamsPerConnection); - } - - void CompleteCryptoHandshake(uint32_t server_max_incoming_streams) { - session_->CryptoConnect(); - QuicCryptoClientStream* stream = static_cast<QuicCryptoClientStream*>( - session_->GetMutableCryptoStream()); - crypto_test_utils::FakeServerOptions options; - QuicConfig config = DefaultQuicConfig(); - config.SetMaxIncomingDynamicStreamsToSend(server_max_incoming_streams); - crypto_test_utils::HandshakeWithFakeServer( - &config, &helper_, &alarm_factory_, connection_, stream, options); - } - - QuicCryptoClientConfig crypto_config_; - MockQuicConnectionHelper helper_; - MockAlarmFactory alarm_factory_; - PacketSavingConnection* connection_; - std::unique_ptr<TestQuicSpdyClientSession> session_; - QuicClientPushPromiseIndex push_promise_index_; - SpdyHeaderBlock push_promise_; - QuicString promise_url_; - QuicStreamId promised_stream_id_; - QuicStreamId associated_stream_id_; -}; - -INSTANTIATE_TEST_CASE_P(Tests, - QuicSpdyClientSessionTest, - ::testing::ValuesIn(AllSupportedVersions())); - -TEST_P(QuicSpdyClientSessionTest, CryptoConnect) { - CompleteCryptoHandshake(); -} - -TEST_P(QuicSpdyClientSessionTest, NoEncryptionAfterInitialEncryption) { - // Complete a handshake in order to prime the crypto config for 0-RTT. - CompleteCryptoHandshake(); - - // Now create a second session using the same crypto config. - Initialize(); - - EXPECT_CALL(*connection_, OnCanWrite()); - // Starting the handshake should move immediately to encryption - // established and will allow streams to be created. - session_->CryptoConnect(); - EXPECT_TRUE(session_->IsEncryptionEstablished()); - QuicSpdyClientStream* stream = session_->CreateOutgoingDynamicStream(); - ASSERT_TRUE(stream != nullptr); - EXPECT_NE(kCryptoStreamId, stream->id()); - - // Process an "inchoate" REJ from the server which will cause - // an inchoate CHLO to be sent and will leave the encryption level - // at NONE. - CryptoHandshakeMessage rej; - crypto_test_utils::FillInDummyReject(&rej, /* stateless */ false); - EXPECT_TRUE(session_->IsEncryptionEstablished()); - crypto_test_utils::SendHandshakeMessageToStream( - session_->GetMutableCryptoStream(), rej, Perspective::IS_CLIENT); - EXPECT_FALSE(session_->IsEncryptionEstablished()); - EXPECT_EQ(ENCRYPTION_NONE, - QuicPacketCreatorPeer::GetEncryptionLevel( - QuicConnectionPeer::GetPacketCreator(connection_))); - // Verify that no new streams may be created. - EXPECT_TRUE(session_->CreateOutgoingDynamicStream() == nullptr); - // Verify that no data may be send on existing streams. - char data[] = "hello world"; - QuicConsumedData consumed = - session_->WritevData(stream, stream->id(), arraysize(data), 0, NO_FIN); - EXPECT_FALSE(consumed.fin_consumed); - EXPECT_EQ(0u, consumed.bytes_consumed); -} - -TEST_P(QuicSpdyClientSessionTest, MaxNumStreamsWithNoFinOrRst) { - EXPECT_CALL(*connection_, SendControlFrame(_)).Times(AnyNumber()); - EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(AnyNumber()); - - const uint32_t kServerMaxIncomingStreams = 1; - CompleteCryptoHandshake(kServerMaxIncomingStreams); - - QuicSpdyClientStream* stream = session_->CreateOutgoingDynamicStream(); - ASSERT_TRUE(stream); - EXPECT_FALSE(session_->CreateOutgoingDynamicStream()); - - // Close the stream, but without having received a FIN or a RST_STREAM - // and check that a new one can not be created. - session_->CloseStream(stream->id()); - EXPECT_EQ(1u, session_->GetNumOpenOutgoingStreams()); - - stream = session_->CreateOutgoingDynamicStream(); - EXPECT_FALSE(stream); -} - -TEST_P(QuicSpdyClientSessionTest, MaxNumStreamsWithRst) { - EXPECT_CALL(*connection_, SendControlFrame(_)).Times(AnyNumber()); - EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(AnyNumber()); - - const uint32_t kServerMaxIncomingStreams = 1; - CompleteCryptoHandshake(kServerMaxIncomingStreams); - - QuicSpdyClientStream* stream = session_->CreateOutgoingDynamicStream(); - ASSERT_NE(nullptr, stream); - EXPECT_EQ(nullptr, session_->CreateOutgoingDynamicStream()); - - // Close the stream and receive an RST frame to remove the unfinished stream - session_->CloseStream(stream->id()); - session_->OnRstStream(QuicRstStreamFrame(kInvalidControlFrameId, stream->id(), - QUIC_RST_ACKNOWLEDGEMENT, 0)); - // Check that a new one can be created. - EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams()); - stream = session_->CreateOutgoingDynamicStream(); - EXPECT_NE(nullptr, stream); -} - -TEST_P(QuicSpdyClientSessionTest, ResetAndTrailers) { - // Tests the situation in which the client sends a RST at the same time that - // the server sends trailing headers (trailers). Receipt of the trailers by - // the client should result in all outstanding stream state being tidied up - // (including flow control, and number of available outgoing streams). - const uint32_t kServerMaxIncomingStreams = 1; - CompleteCryptoHandshake(kServerMaxIncomingStreams); - - QuicSpdyClientStream* stream = session_->CreateOutgoingDynamicStream(); - ASSERT_NE(nullptr, stream); - EXPECT_FALSE(session_->CreateOutgoingDynamicStream()); - - QuicStreamId stream_id = stream->id(); - EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1); - EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(1); - session_->SendRstStream(stream_id, QUIC_STREAM_PEER_GOING_AWAY, 0); - - // A new stream cannot be created as the reset stream still counts as an open - // outgoing stream until closed by the server. - EXPECT_EQ(1u, session_->GetNumOpenOutgoingStreams()); - stream = session_->CreateOutgoingDynamicStream(); - EXPECT_EQ(nullptr, stream); - - // The stream receives trailers with final byte offset: this is one of three - // ways that a peer can signal the end of a stream (the others being RST, - // stream data + FIN). - QuicHeaderList trailers; - trailers.OnHeaderBlockStart(); - trailers.OnHeader(kFinalOffsetHeaderKey, "0"); - trailers.OnHeaderBlockEnd(0, 0); - session_->OnStreamHeaderList(stream_id, /*fin=*/false, 0, trailers); - - // The stream is now complete from the client's perspective, and it should - // be able to create a new outgoing stream. - EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams()); - stream = session_->CreateOutgoingDynamicStream(); - EXPECT_NE(nullptr, stream); -} - -TEST_P(QuicSpdyClientSessionTest, ReceivedMalformedTrailersAfterSendingRst) { - // Tests the situation where the client has sent a RST to the server, and has - // received trailing headers with a malformed final byte offset value. - CompleteCryptoHandshake(); - - QuicSpdyClientStream* stream = session_->CreateOutgoingDynamicStream(); - ASSERT_NE(nullptr, stream); - - // Send the RST, which results in the stream being closed locally (but some - // state remains while the client waits for a response from the server). - QuicStreamId stream_id = stream->id(); - EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1); - EXPECT_CALL(*connection_, OnStreamReset(_, _)).Times(1); - session_->SendRstStream(stream_id, QUIC_STREAM_PEER_GOING_AWAY, 0); - - // The stream receives trailers with final byte offset, but the header value - // is non-numeric and should be treated as malformed. - QuicHeaderList trailers; - trailers.OnHeaderBlockStart(); - trailers.OnHeader(kFinalOffsetHeaderKey, "invalid non-numeric value"); - trailers.OnHeaderBlockEnd(0, 0); - - EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(1); - session_->OnStreamHeaderList(stream_id, /*fin=*/false, 0, trailers); -} - -TEST_P(QuicSpdyClientSessionTest, GoAwayReceived) { - CompleteCryptoHandshake(); - - // After receiving a GoAway, I should no longer be able to create outgoing - // streams. - session_->connection()->OnGoAwayFrame(QuicGoAwayFrame( - kInvalidControlFrameId, QUIC_PEER_GOING_AWAY, 1u, "Going away.")); - EXPECT_EQ(nullptr, session_->CreateOutgoingDynamicStream()); -} - -static bool CheckForDecryptionError(QuicFramer* framer) { - return framer->error() == QUIC_DECRYPTION_FAILURE; -} - -// Various sorts of invalid packets that should not cause a connection -// to be closed. -TEST_P(QuicSpdyClientSessionTest, InvalidPacketReceived) { - QuicSocketAddress server_address(TestPeerIPAddress(), kTestPort); - QuicSocketAddress client_address(TestPeerIPAddress(), kTestPort); - - EXPECT_CALL(*connection_, ProcessUdpPacket(server_address, client_address, _)) - .WillRepeatedly(Invoke(static_cast<MockQuicConnection*>(connection_), - &MockQuicConnection::ReallyProcessUdpPacket)); - EXPECT_CALL(*connection_, OnCanWrite()).Times(AnyNumber()); - EXPECT_CALL(*connection_, OnError(_)).Times(1); - - // Verify that empty packets don't close the connection. - QuicReceivedPacket zero_length_packet(nullptr, 0, QuicTime::Zero(), false); - EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0); - session_->ProcessUdpPacket(client_address, server_address, - zero_length_packet); - - // Verifiy that small, invalid packets don't close the connection. - char buf[2] = {0x00, 0x01}; - QuicReceivedPacket valid_packet(buf, 2, QuicTime::Zero(), false); - // Close connection shouldn't be called. - EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0); - session_->ProcessUdpPacket(client_address, server_address, valid_packet); - - // Verify that a non-decryptable packet doesn't close the connection. - QuicConnectionId connection_id = session_->connection()->connection_id(); - std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket( - connection_id, false, false, 100, "data", PACKET_8BYTE_CONNECTION_ID, - PACKET_4BYTE_PACKET_NUMBER, nullptr, Perspective::IS_SERVER)); - std::unique_ptr<QuicReceivedPacket> received( - ConstructReceivedPacket(*packet, QuicTime::Zero())); - // Change the last byte of the encrypted data. - *(const_cast<char*>(received->data() + received->length() - 1)) += 1; - EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0); - EXPECT_CALL(*connection_, OnError(Truly(CheckForDecryptionError))).Times(1); - session_->ProcessUdpPacket(client_address, server_address, *received); -} - -// A packet with invalid framing should cause a connection to be closed. -TEST_P(QuicSpdyClientSessionTest, InvalidFramedPacketReceived) { - QuicSocketAddress server_address(TestPeerIPAddress(), kTestPort); - QuicSocketAddress client_address(TestPeerIPAddress(), kTestPort); - - EXPECT_CALL(*connection_, ProcessUdpPacket(server_address, client_address, _)) - .WillRepeatedly(Invoke(static_cast<MockQuicConnection*>(connection_), - &MockQuicConnection::ReallyProcessUdpPacket)); - EXPECT_CALL(*connection_, OnError(_)).Times(1); - - // Verify that a decryptable packet with bad frames does close the connection. - QuicConnectionId connection_id = session_->connection()->connection_id(); - ParsedQuicVersionVector versions = {GetParam()}; - std::unique_ptr<QuicEncryptedPacket> packet(ConstructMisFramedEncryptedPacket( - connection_id, false, false, 100, "data", PACKET_8BYTE_CONNECTION_ID, - PACKET_4BYTE_PACKET_NUMBER, &versions, Perspective::IS_SERVER)); - std::unique_ptr<QuicReceivedPacket> received( - ConstructReceivedPacket(*packet, QuicTime::Zero())); - EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(1); - session_->ProcessUdpPacket(client_address, server_address, *received); -} - -TEST_P(QuicSpdyClientSessionTest, PushPromiseOnPromiseHeaders) { - // Initialize crypto before the client session will create a stream. - CompleteCryptoHandshake(); - - MockQuicSpdyClientStream* stream = static_cast<MockQuicSpdyClientStream*>( - session_->CreateOutgoingDynamicStream()); - - EXPECT_CALL(*stream, OnPromiseHeaderList(_, _, _)); - session_->OnPromiseHeaderList(associated_stream_id_, promised_stream_id_, 0, - QuicHeaderList()); -} - -TEST_P(QuicSpdyClientSessionTest, PushPromiseOnPromiseHeadersAlreadyClosed) { - // Initialize crypto before the client session will create a stream. - CompleteCryptoHandshake(); - - session_->CreateOutgoingDynamicStream(); - - EXPECT_CALL(*connection_, SendControlFrame(_)); - EXPECT_CALL(*connection_, - OnStreamReset(associated_stream_id_, QUIC_REFUSED_STREAM)); - session_->ResetPromised(associated_stream_id_, QUIC_REFUSED_STREAM); - - session_->OnPromiseHeaderList(associated_stream_id_, promised_stream_id_, 0, - QuicHeaderList()); -} - -TEST_P(QuicSpdyClientSessionTest, PushPromiseOutOfOrder) { - // Initialize crypto before the client session will create a stream. - CompleteCryptoHandshake(); - - MockQuicSpdyClientStream* stream = static_cast<MockQuicSpdyClientStream*>( - session_->CreateOutgoingDynamicStream()); - - EXPECT_CALL(*stream, OnPromiseHeaderList(promised_stream_id_, _, _)); - session_->OnPromiseHeaderList(associated_stream_id_, promised_stream_id_, 0, - QuicHeaderList()); - associated_stream_id_ += 2; - EXPECT_CALL(*connection_, - CloseConnection(QUIC_INVALID_STREAM_ID, - "Received push stream id lesser or equal to the" - " last accepted before", - _)); - session_->OnPromiseHeaderList(associated_stream_id_, promised_stream_id_, 0, - QuicHeaderList()); -} - -TEST_P(QuicSpdyClientSessionTest, PushPromiseHandlePromise) { - // Initialize crypto before the client session will create a stream. - CompleteCryptoHandshake(); - - session_->CreateOutgoingDynamicStream(); - - EXPECT_TRUE(session_->HandlePromised(associated_stream_id_, - promised_stream_id_, push_promise_)); - - EXPECT_NE(session_->GetPromisedById(promised_stream_id_), nullptr); - EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr); -} - -TEST_P(QuicSpdyClientSessionTest, PushPromiseAlreadyClosed) { - // Initialize crypto before the client session will create a stream. - CompleteCryptoHandshake(); - - session_->CreateOutgoingDynamicStream(); - session_->GetOrCreateStream(promised_stream_id_); - - EXPECT_CALL(*connection_, SendControlFrame(_)); - EXPECT_CALL(*connection_, - OnStreamReset(promised_stream_id_, QUIC_REFUSED_STREAM)); - - session_->ResetPromised(promised_stream_id_, QUIC_REFUSED_STREAM); - SpdyHeaderBlock promise_headers; - EXPECT_FALSE(session_->HandlePromised(associated_stream_id_, - promised_stream_id_, promise_headers)); - - // Verify that the promise was not created. - EXPECT_EQ(session_->GetPromisedById(promised_stream_id_), nullptr); - EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr); -} - -TEST_P(QuicSpdyClientSessionTest, PushPromiseDuplicateUrl) { - // Initialize crypto before the client session will create a stream. - CompleteCryptoHandshake(); - - session_->CreateOutgoingDynamicStream(); - - EXPECT_TRUE(session_->HandlePromised(associated_stream_id_, - promised_stream_id_, push_promise_)); - - EXPECT_NE(session_->GetPromisedById(promised_stream_id_), nullptr); - EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr); - - promised_stream_id_ += 2; - EXPECT_CALL(*connection_, SendControlFrame(_)); - EXPECT_CALL(*connection_, - OnStreamReset(promised_stream_id_, QUIC_DUPLICATE_PROMISE_URL)); - - EXPECT_FALSE(session_->HandlePromised(associated_stream_id_, - promised_stream_id_, push_promise_)); - - // Verify that the promise was not created. - EXPECT_EQ(session_->GetPromisedById(promised_stream_id_), nullptr); -} - -TEST_P(QuicSpdyClientSessionTest, ReceivingPromiseEnhanceYourCalm) { - for (size_t i = 0u; i < session_->get_max_promises(); i++) { - push_promise_[":path"] = QuicStringPrintf("/bar%zu", i); - - QuicStreamId id = promised_stream_id_ + i * 2; - - EXPECT_TRUE( - session_->HandlePromised(associated_stream_id_, id, push_promise_)); - - // Verify that the promise is in the unclaimed streams map. - QuicString promise_url(SpdyUtils::GetPromisedUrlFromHeaders(push_promise_)); - EXPECT_NE(session_->GetPromisedByUrl(promise_url), nullptr); - EXPECT_NE(session_->GetPromisedById(id), nullptr); - } - - // One more promise, this should be refused. - int i = session_->get_max_promises(); - push_promise_[":path"] = QuicStringPrintf("/bar%d", i); - - QuicStreamId id = promised_stream_id_ + i * 2; - EXPECT_CALL(*connection_, SendControlFrame(_)); - EXPECT_CALL(*connection_, OnStreamReset(id, QUIC_REFUSED_STREAM)); - EXPECT_FALSE( - session_->HandlePromised(associated_stream_id_, id, push_promise_)); - - // Verify that the promise was not created. - QuicString promise_url(SpdyUtils::GetPromisedUrlFromHeaders(push_promise_)); - EXPECT_EQ(session_->GetPromisedById(id), nullptr); - EXPECT_EQ(session_->GetPromisedByUrl(promise_url), nullptr); -} - -TEST_P(QuicSpdyClientSessionTest, IsClosedTrueAfterResetPromisedAlreadyOpen) { - // Initialize crypto before the client session will create a stream. - CompleteCryptoHandshake(); - - session_->GetOrCreateStream(promised_stream_id_); - EXPECT_CALL(*connection_, SendControlFrame(_)); - EXPECT_CALL(*connection_, - OnStreamReset(promised_stream_id_, QUIC_REFUSED_STREAM)); - session_->ResetPromised(promised_stream_id_, QUIC_REFUSED_STREAM); - EXPECT_TRUE(session_->IsClosedStream(promised_stream_id_)); -} - -TEST_P(QuicSpdyClientSessionTest, IsClosedTrueAfterResetPromisedNonexistant) { - // Initialize crypto before the client session will create a stream. - CompleteCryptoHandshake(); - - EXPECT_CALL(*connection_, SendControlFrame(_)); - EXPECT_CALL(*connection_, - OnStreamReset(promised_stream_id_, QUIC_REFUSED_STREAM)); - session_->ResetPromised(promised_stream_id_, QUIC_REFUSED_STREAM); - EXPECT_TRUE(session_->IsClosedStream(promised_stream_id_)); -} - -TEST_P(QuicSpdyClientSessionTest, OnInitialHeadersCompleteIsPush) { - // Initialize crypto before the client session will create a stream. - CompleteCryptoHandshake(); - session_->GetOrCreateStream(promised_stream_id_); - EXPECT_TRUE(session_->HandlePromised(associated_stream_id_, - promised_stream_id_, push_promise_)); - EXPECT_NE(session_->GetPromisedById(promised_stream_id_), nullptr); - EXPECT_NE(session_->GetPromisedStream(promised_stream_id_), nullptr); - EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr); - - session_->OnInitialHeadersComplete(promised_stream_id_, SpdyHeaderBlock()); -} - -TEST_P(QuicSpdyClientSessionTest, OnInitialHeadersCompleteIsNotPush) { - // Initialize crypto before the client session will create a stream. - CompleteCryptoHandshake(); - session_->CreateOutgoingDynamicStream(); - session_->OnInitialHeadersComplete(promised_stream_id_, SpdyHeaderBlock()); -} - -TEST_P(QuicSpdyClientSessionTest, DeletePromised) { - // Initialize crypto before the client session will create a stream. - CompleteCryptoHandshake(); - session_->GetOrCreateStream(promised_stream_id_); - EXPECT_TRUE(session_->HandlePromised(associated_stream_id_, - promised_stream_id_, push_promise_)); - QuicClientPromisedInfo* promised = - session_->GetPromisedById(promised_stream_id_); - EXPECT_NE(promised, nullptr); - EXPECT_NE(session_->GetPromisedStream(promised_stream_id_), nullptr); - EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr); - - session_->DeletePromised(promised); - EXPECT_EQ(session_->GetPromisedById(promised_stream_id_), nullptr); - EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr); -} - -TEST_P(QuicSpdyClientSessionTest, ResetPromised) { - // Initialize crypto before the client session will create a stream. - CompleteCryptoHandshake(); - session_->GetOrCreateStream(promised_stream_id_); - EXPECT_TRUE(session_->HandlePromised(associated_stream_id_, - promised_stream_id_, push_promise_)); - EXPECT_CALL(*connection_, SendControlFrame(_)); - EXPECT_CALL(*connection_, - OnStreamReset(promised_stream_id_, QUIC_STREAM_PEER_GOING_AWAY)); - session_->SendRstStream(promised_stream_id_, QUIC_STREAM_PEER_GOING_AWAY, 0); - QuicClientPromisedInfo* promised = - session_->GetPromisedById(promised_stream_id_); - EXPECT_NE(promised, nullptr); - EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr); - EXPECT_EQ(session_->GetPromisedStream(promised_stream_id_), nullptr); -} - -TEST_P(QuicSpdyClientSessionTest, PushPromiseInvalidMethod) { - // Initialize crypto before the client session will create a stream. - CompleteCryptoHandshake(); - - session_->CreateOutgoingDynamicStream(); - - EXPECT_CALL(*connection_, SendControlFrame(_)); - EXPECT_CALL(*connection_, - OnStreamReset(promised_stream_id_, QUIC_INVALID_PROMISE_METHOD)); - - push_promise_[":method"] = "POST"; - EXPECT_FALSE(session_->HandlePromised(associated_stream_id_, - promised_stream_id_, push_promise_)); - - EXPECT_EQ(session_->GetPromisedById(promised_stream_id_), nullptr); - EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr); -} - -TEST_P(QuicSpdyClientSessionTest, PushPromiseInvalidHost) { - // Initialize crypto before the client session will create a stream. - CompleteCryptoHandshake(); - - session_->CreateOutgoingDynamicStream(); - - EXPECT_CALL(*connection_, SendControlFrame(_)); - EXPECT_CALL(*connection_, - OnStreamReset(promised_stream_id_, QUIC_INVALID_PROMISE_URL)); - - push_promise_[":authority"] = ""; - EXPECT_FALSE(session_->HandlePromised(associated_stream_id_, - promised_stream_id_, push_promise_)); - - EXPECT_EQ(session_->GetPromisedById(promised_stream_id_), nullptr); - EXPECT_EQ(session_->GetPromisedByUrl(promise_url_), nullptr); -} - -} // namespace -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/quic_spdy_client_stream.cc b/chromium/net/tools/quic/quic_spdy_client_stream.cc deleted file mode 100644 index ac0ff0d9f0b..00000000000 --- a/chromium/net/tools/quic/quic_spdy_client_stream.cc +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_spdy_client_stream.h" - -#include <utility> - -#include "net/quic/core/quic_alarm.h" -#include "net/quic/core/quic_client_promised_info.h" -#include "net/quic/core/spdy_utils.h" -#include "net/quic/platform/api/quic_logging.h" -#include "net/spdy/core/spdy_protocol.h" -#include "net/tools/quic/quic_spdy_client_session.h" - -using std::string; - -namespace net { - -QuicSpdyClientStream::QuicSpdyClientStream(QuicStreamId id, - QuicSpdyClientSession* session) - : QuicSpdyStream(id, session), - content_length_(-1), - response_code_(0), - header_bytes_read_(0), - header_bytes_written_(0), - session_(session), - has_preliminary_headers_(false) {} - -QuicSpdyClientStream::~QuicSpdyClientStream() = default; - -void QuicSpdyClientStream::OnInitialHeadersComplete( - bool fin, - size_t frame_len, - const QuicHeaderList& header_list) { - QuicSpdyStream::OnInitialHeadersComplete(fin, frame_len, header_list); - - DCHECK(headers_decompressed()); - header_bytes_read_ += frame_len; - if (!SpdyUtils::CopyAndValidateHeaders(header_list, &content_length_, - &response_headers_)) { - QUIC_DLOG(ERROR) << "Failed to parse header list: " - << header_list.DebugString(); - Reset(QUIC_BAD_APPLICATION_PAYLOAD); - return; - } - - if (!ParseHeaderStatusCode(response_headers_, &response_code_)) { - QUIC_DLOG(ERROR) << "Received invalid response code: " - << response_headers_[":status"].as_string(); - Reset(QUIC_BAD_APPLICATION_PAYLOAD); - return; - } - - if (response_code_ == 100 && !has_preliminary_headers_) { - // These are preliminary 100 Continue headers, not the actual response - // headers. - set_headers_decompressed(false); - has_preliminary_headers_ = true; - preliminary_headers_ = std::move(response_headers_); - } - - ConsumeHeaderList(); - QUIC_DVLOG(1) << "headers complete for stream " << id(); - - session_->OnInitialHeadersComplete(id(), response_headers_); -} - -void QuicSpdyClientStream::OnTrailingHeadersComplete( - bool fin, - size_t frame_len, - const QuicHeaderList& header_list) { - QuicSpdyStream::OnTrailingHeadersComplete(fin, frame_len, header_list); - MarkTrailersConsumed(); -} - -void QuicSpdyClientStream::OnPromiseHeaderList( - QuicStreamId promised_id, - size_t frame_len, - const QuicHeaderList& header_list) { - header_bytes_read_ += frame_len; - int64_t content_length = -1; - SpdyHeaderBlock promise_headers; - if (!SpdyUtils::CopyAndValidateHeaders(header_list, &content_length, - &promise_headers)) { - QUIC_DLOG(ERROR) << "Failed to parse promise headers: " - << header_list.DebugString(); - Reset(QUIC_BAD_APPLICATION_PAYLOAD); - return; - } - - session_->HandlePromised(id(), promised_id, promise_headers); - if (visitor() != nullptr) { - visitor()->OnPromiseHeadersComplete(promised_id, frame_len); - } -} - -void QuicSpdyClientStream::OnDataAvailable() { - // For push streams, visitor will not be set until the rendezvous - // between server promise and client request is complete. - if (visitor() == nullptr) - return; - - while (HasBytesToRead()) { - struct iovec iov; - if (GetReadableRegions(&iov, 1) == 0) { - // No more data to read. - break; - } - QUIC_DVLOG(1) << "Client processed " << iov.iov_len << " bytes for stream " - << id(); - data_.append(static_cast<char*>(iov.iov_base), iov.iov_len); - - if (content_length_ >= 0 && - data_.size() > static_cast<uint64_t>(content_length_)) { - QUIC_DLOG(ERROR) << "Invalid content length (" << content_length_ - << ") with data of size " << data_.size(); - Reset(QUIC_BAD_APPLICATION_PAYLOAD); - return; - } - MarkConsumed(iov.iov_len); - } - if (sequencer()->IsClosed()) { - OnFinRead(); - } else { - sequencer()->SetUnblocked(); - } -} - -size_t QuicSpdyClientStream::SendRequest(SpdyHeaderBlock headers, - QuicStringPiece body, - bool fin) { - QuicConnection::ScopedPacketFlusher flusher( - session_->connection(), QuicConnection::SEND_ACK_IF_QUEUED); - bool send_fin_with_headers = fin && body.empty(); - size_t bytes_sent = body.size(); - header_bytes_written_ = - WriteHeaders(std::move(headers), send_fin_with_headers, nullptr); - bytes_sent += header_bytes_written_; - - if (!body.empty()) { - WriteOrBufferData(body, fin, nullptr); - } - - return bytes_sent; -} - -} // namespace net diff --git a/chromium/net/tools/quic/quic_spdy_client_stream.h b/chromium/net/tools/quic/quic_spdy_client_stream.h deleted file mode 100644 index e138f01485d..00000000000 --- a/chromium/net/tools/quic/quic_spdy_client_stream.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_QUIC_SPDY_CLIENT_STREAM_H_ -#define NET_TOOLS_QUIC_QUIC_SPDY_CLIENT_STREAM_H_ - -#include <stddef.h> -#include <sys/types.h> - -#include "base/macros.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/core/quic_spdy_stream.h" -#include "net/quic/platform/api/quic_string.h" -#include "net/quic/platform/api/quic_string_piece.h" -#include "net/spdy/core/spdy_framer.h" - -namespace net { - -class QuicSpdyClientSession; - -// All this does right now is send an SPDY request, and aggregate the -// SPDY response. -class QuicSpdyClientStream : public QuicSpdyStream { - public: - QuicSpdyClientStream(QuicStreamId id, QuicSpdyClientSession* session); - ~QuicSpdyClientStream() override; - - // Override the base class to parse and store headers. - void OnInitialHeadersComplete(bool fin, - size_t frame_len, - const QuicHeaderList& header_list) override; - - // Override the base class to parse and store trailers. - void OnTrailingHeadersComplete(bool fin, - size_t frame_len, - const QuicHeaderList& header_list) override; - - // Override the base class to handle creation of the push stream. - void OnPromiseHeaderList(QuicStreamId promised_id, - size_t frame_len, - const QuicHeaderList& header_list) override; - - // QuicStream implementation called by the session when there's data for us. - void OnDataAvailable() override; - - // Serializes the headers and body, sends it to the server, and - // returns the number of bytes sent. - size_t SendRequest(SpdyHeaderBlock headers, QuicStringPiece body, bool fin); - - // Returns the response data. - const QuicString& data() { return data_; } - - // Returns whatever headers have been received for this stream. - const SpdyHeaderBlock& response_headers() { return response_headers_; } - - const SpdyHeaderBlock& preliminary_headers() { return preliminary_headers_; } - - size_t header_bytes_read() const { return header_bytes_read_; } - - size_t header_bytes_written() const { return header_bytes_written_; } - - int response_code() const { return response_code_; } - - // While the server's SetPriority shouldn't be called externally, the creator - // of client-side streams should be able to set the priority. - using QuicSpdyStream::SetPriority; - - private: - // The parsed headers received from the server. - SpdyHeaderBlock response_headers_; - - // The parsed content-length, or -1 if none is specified. - int64_t content_length_; - int response_code_; - QuicString data_; - size_t header_bytes_read_; - size_t header_bytes_written_; - - QuicSpdyClientSession* session_; - - // These preliminary headers are used for the 100 Continue headers - // that may arrive before the response headers when the request has - // Expect: 100-continue. - bool has_preliminary_headers_; - SpdyHeaderBlock preliminary_headers_; - - DISALLOW_COPY_AND_ASSIGN(QuicSpdyClientStream); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_SPDY_CLIENT_STREAM_H_ diff --git a/chromium/net/tools/quic/quic_spdy_client_stream_test.cc b/chromium/net/tools/quic/quic_spdy_client_stream_test.cc deleted file mode 100644 index 46d060c7a82..00000000000 --- a/chromium/net/tools/quic/quic_spdy_client_stream_test.cc +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_spdy_client_stream.h" - -#include <memory> - -#include "base/macros.h" -#include "net/quic/core/quic_utils.h" -#include "net/quic/core/spdy_utils.h" -#include "net/quic/core/tls_client_handshaker.h" -#include "net/quic/platform/api/quic_logging.h" -#include "net/quic/platform/api/quic_ptr_util.h" -#include "net/quic/platform/api/quic_socket_address.h" -#include "net/quic/platform/api/quic_string.h" -#include "net/quic/platform/api/quic_test.h" -#include "net/quic/platform/api/quic_text_utils.h" -#include "net/quic/test_tools/crypto_test_utils.h" -#include "net/quic/test_tools/quic_spdy_session_peer.h" -#include "net/quic/test_tools/quic_test_utils.h" -#include "net/tools/quic/quic_spdy_client_session.h" - -using base::IntToString; -using testing::_; -using testing::StrictMock; - -namespace net { -namespace test { - -namespace { - -class MockQuicSpdyClientSession : public QuicSpdyClientSession { - public: - explicit MockQuicSpdyClientSession( - QuicConnection* connection, - QuicClientPushPromiseIndex* push_promise_index) - : QuicSpdyClientSession( - DefaultQuicConfig(), - connection, - QuicServerId("example.com", 443, PRIVACY_MODE_DISABLED), - &crypto_config_, - push_promise_index), - crypto_config_(crypto_test_utils::ProofVerifierForTesting(), - TlsClientHandshaker::CreateSslCtx()) {} - ~MockQuicSpdyClientSession() override = default; - - MOCK_METHOD1(CloseStream, void(QuicStreamId stream_id)); - - private: - QuicCryptoClientConfig crypto_config_; - - DISALLOW_COPY_AND_ASSIGN(MockQuicSpdyClientSession); -}; - -class QuicSpdyClientStreamTest : public QuicTest { - public: - class StreamVisitor; - - QuicSpdyClientStreamTest() - : connection_(new StrictMock<MockQuicConnection>(&helper_, - &alarm_factory_, - Perspective::IS_CLIENT)), - session_(connection_, &push_promise_index_), - body_("hello world") { - session_.Initialize(); - - headers_[":status"] = "200"; - headers_["content-length"] = "11"; - - stream_ = QuicMakeUnique<QuicSpdyClientStream>( - QuicSpdySessionPeer::GetNthClientInitiatedStreamId(session_, 0), - &session_); - stream_visitor_ = QuicMakeUnique<StreamVisitor>(); - stream_->set_visitor(stream_visitor_.get()); - } - - class StreamVisitor : public QuicSpdyClientStream::Visitor { - void OnClose(QuicSpdyStream* stream) override { - QUIC_DVLOG(1) << "stream " << stream->id(); - } - }; - - MockQuicConnectionHelper helper_; - MockAlarmFactory alarm_factory_; - StrictMock<MockQuicConnection>* connection_; - QuicClientPushPromiseIndex push_promise_index_; - - MockQuicSpdyClientSession session_; - std::unique_ptr<QuicSpdyClientStream> stream_; - std::unique_ptr<StreamVisitor> stream_visitor_; - SpdyHeaderBlock headers_; - QuicString body_; -}; - -TEST_F(QuicSpdyClientStreamTest, TestReceivingIllegalResponseStatusCode) { - headers_[":status"] = "200 ok"; - - EXPECT_CALL(*connection_, SendControlFrame(_)); - EXPECT_CALL(*connection_, - OnStreamReset(stream_->id(), QUIC_BAD_APPLICATION_PAYLOAD)); - auto headers = AsHeaderList(headers_); - stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(), - headers); - EXPECT_EQ(QUIC_BAD_APPLICATION_PAYLOAD, stream_->stream_error()); -} - -TEST_F(QuicSpdyClientStreamTest, TestFraming) { - auto headers = AsHeaderList(headers_); - stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(), - headers); - stream_->OnStreamFrame( - QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_)); - EXPECT_EQ("200", stream_->response_headers().find(":status")->second); - EXPECT_EQ(200, stream_->response_code()); - EXPECT_EQ(body_, stream_->data()); -} - -TEST_F(QuicSpdyClientStreamTest, TestFraming100Continue) { - headers_[":status"] = "100"; - auto headers = AsHeaderList(headers_); - stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(), - headers); - stream_->OnStreamFrame( - QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_)); - EXPECT_EQ("100", stream_->preliminary_headers().find(":status")->second); - EXPECT_EQ(0u, stream_->response_headers().size()); - EXPECT_EQ(100, stream_->response_code()); - EXPECT_EQ("", stream_->data()); -} - -TEST_F(QuicSpdyClientStreamTest, TestFramingOnePacket) { - auto headers = AsHeaderList(headers_); - stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(), - headers); - stream_->OnStreamFrame( - QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_)); - EXPECT_EQ("200", stream_->response_headers().find(":status")->second); - EXPECT_EQ(200, stream_->response_code()); - EXPECT_EQ(body_, stream_->data()); -} - -TEST_F(QuicSpdyClientStreamTest, DISABLED_TestFramingExtraData) { - QuicString large_body = "hello world!!!!!!"; - - auto headers = AsHeaderList(headers_); - stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(), - headers); - // The headers should parse successfully. - EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error()); - EXPECT_EQ("200", stream_->response_headers().find(":status")->second); - EXPECT_EQ(200, stream_->response_code()); - - EXPECT_CALL(*connection_, SendControlFrame(_)); - EXPECT_CALL(*connection_, - OnStreamReset(stream_->id(), QUIC_BAD_APPLICATION_PAYLOAD)); - stream_->OnStreamFrame( - QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, large_body)); - - EXPECT_NE(QUIC_STREAM_NO_ERROR, stream_->stream_error()); -} - -TEST_F(QuicSpdyClientStreamTest, ReceivingTrailers) { - // Test that receiving trailing headers, containing a final offset, results in - // the stream being closed at that byte offset. - // Send headers as usual. - auto headers = AsHeaderList(headers_); - stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(), - headers); - - // Send trailers before sending the body. Even though a FIN has been received - // the stream should not be closed, as it does not yet have all the data bytes - // promised by the final offset field. - SpdyHeaderBlock trailer_block; - trailer_block["trailer key"] = "trailer value"; - trailer_block[kFinalOffsetHeaderKey] = - QuicTextUtils::Uint64ToString(body_.size()); - auto trailers = AsHeaderList(trailer_block); - stream_->OnStreamHeaderList(true, trailers.uncompressed_header_bytes(), - trailers); - - // Now send the body, which should close the stream as the FIN has been - // received, as well as all data. - stream_->OnStreamFrame( - QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_)); - EXPECT_TRUE(stream_->reading_stopped()); -} - -} // namespace -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/quic_spdy_server_stream_base.cc b/chromium/net/tools/quic/quic_spdy_server_stream_base.cc deleted file mode 100644 index f7af8734b51..00000000000 --- a/chromium/net/tools/quic/quic_spdy_server_stream_base.cc +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_spdy_server_stream_base.h" - -#include "net/quic/core/quic_error_codes.h" -#include "net/quic/platform/api/quic_logging.h" - -namespace net { - -QuicSpdyServerStreamBase::QuicSpdyServerStreamBase(QuicStreamId id, - QuicSpdySession* session) - : QuicSpdyStream(id, session) {} - -void QuicSpdyServerStreamBase::CloseWriteSide() { - if (!fin_received() && !rst_received() && sequencer()->ignore_read_data() && - !rst_sent()) { - // Early cancel the stream if it has stopped reading before receiving FIN - // or RST. - DCHECK(fin_sent()); - // Tell the peer to stop sending further data. - QUIC_DVLOG(1) << " Server: Send QUIC_STREAM_NO_ERROR on stream " << id(); - Reset(QUIC_STREAM_NO_ERROR); - } - - QuicSpdyStream::CloseWriteSide(); -} - -void QuicSpdyServerStreamBase::StopReading() { - if (!fin_received() && !rst_received() && write_side_closed() && - !rst_sent()) { - DCHECK(fin_sent()); - // Tell the peer to stop sending further data. - QUIC_DVLOG(1) << " Server: Send QUIC_STREAM_NO_ERROR on stream " << id(); - Reset(QUIC_STREAM_NO_ERROR); - } - QuicSpdyStream::StopReading(); -} - -} // namespace net diff --git a/chromium/net/tools/quic/quic_spdy_server_stream_base.h b/chromium/net/tools/quic/quic_spdy_server_stream_base.h deleted file mode 100644 index 46462a16b83..00000000000 --- a/chromium/net/tools/quic/quic_spdy_server_stream_base.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_QUIC_SPDY_SERVER_STREAM_BASE_H_ -#define NET_TOOLS_QUIC_QUIC_SPDY_SERVER_STREAM_BASE_H_ - -#include "net/quic/core/quic_spdy_stream.h" - -namespace net { - -class QuicSpdyServerStreamBase : public QuicSpdyStream { - public: - QuicSpdyServerStreamBase(QuicStreamId id, QuicSpdySession* session); - - // Override the base class to send QUIC_STREAM_NO_ERROR to the peer - // when the stream has not received all the data. - void CloseWriteSide() override; - void StopReading() override; - - private: - DISALLOW_COPY_AND_ASSIGN(QuicSpdyServerStreamBase); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_SPDY_SERVER_STREAM_BASE_H_ diff --git a/chromium/net/tools/quic/quic_spdy_server_stream_base_test.cc b/chromium/net/tools/quic/quic_spdy_server_stream_base_test.cc deleted file mode 100644 index 869ca74c428..00000000000 --- a/chromium/net/tools/quic/quic_spdy_server_stream_base_test.cc +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_spdy_server_stream_base.h" - -#include "net/quic/platform/api/quic_ptr_util.h" -#include "net/quic/platform/api/quic_test.h" -#include "net/quic/test_tools/quic_spdy_session_peer.h" -#include "net/quic/test_tools/quic_test_utils.h" - -using testing::_; - -namespace net { -namespace test { -namespace { - -class TestQuicSpdyServerStream : public QuicSpdyServerStreamBase { - public: - TestQuicSpdyServerStream(QuicStreamId id, QuicSpdySession* session) - : QuicSpdyServerStreamBase(id, session) {} - - void OnDataAvailable() override {} -}; - -class QuicSpdyServerStreamBaseTest : public QuicTest { - protected: - QuicSpdyServerStreamBaseTest() - : session_(new MockQuicConnection(&helper_, - &alarm_factory_, - Perspective::IS_SERVER)) { - stream_ = new TestQuicSpdyServerStream( - QuicSpdySessionPeer::GetNthClientInitiatedStreamId(session_, 0), - &session_); - session_.ActivateStream(QuicWrapUnique(stream_)); - } - - QuicSpdyServerStreamBase* stream_ = nullptr; - MockQuicConnectionHelper helper_; - MockAlarmFactory alarm_factory_; - MockQuicSpdySession session_; -}; - -TEST_F(QuicSpdyServerStreamBaseTest, - SendQuicRstStreamNoErrorWithEarlyResponse) { - stream_->StopReading(); - EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(1); - stream_->set_fin_sent(true); - stream_->CloseWriteSide(); -} - -TEST_F(QuicSpdyServerStreamBaseTest, - DoNotSendQuicRstStreamNoErrorWithRstReceived) { - EXPECT_FALSE(stream_->reading_stopped()); - - EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0); - EXPECT_CALL(session_, SendRstStream(_, QUIC_RST_ACKNOWLEDGEMENT, _)).Times(1); - QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(), - QUIC_STREAM_CANCELLED, 1234); - stream_->OnStreamReset(rst_frame); - - EXPECT_TRUE(stream_->reading_stopped()); - EXPECT_TRUE(stream_->write_side_closed()); -} - -} // namespace -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/quic_time_wait_list_manager.cc b/chromium/net/tools/quic/quic_time_wait_list_manager.cc deleted file mode 100644 index cdc8d632072..00000000000 --- a/chromium/net/tools/quic/quic_time_wait_list_manager.cc +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_time_wait_list_manager.h" - -#include <errno.h> - -#include <memory> - -#include "base/macros.h" -#include "net/quic/core/crypto/crypto_protocol.h" -#include "net/quic/core/crypto/quic_decrypter.h" -#include "net/quic/core/crypto/quic_encrypter.h" -#include "net/quic/core/quic_framer.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/core/quic_utils.h" -#include "net/quic/platform/api/quic_clock.h" -#include "net/quic/platform/api/quic_flags.h" -#include "net/quic/platform/api/quic_logging.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_socket_address.h" - -namespace net { - -// A very simple alarm that just informs the QuicTimeWaitListManager to clean -// up old connection_ids. This alarm should be cancelled and deleted before -// the QuicTimeWaitListManager is deleted. -class ConnectionIdCleanUpAlarm : public QuicAlarm::Delegate { - public: - explicit ConnectionIdCleanUpAlarm( - QuicTimeWaitListManager* time_wait_list_manager) - : time_wait_list_manager_(time_wait_list_manager) {} - - void OnAlarm() override { - time_wait_list_manager_->CleanUpOldConnectionIds(); - } - - private: - // Not owned. - QuicTimeWaitListManager* time_wait_list_manager_; - - DISALLOW_COPY_AND_ASSIGN(ConnectionIdCleanUpAlarm); -}; - -// This class stores pending public reset packets to be sent to clients. -// server_address - server address on which a packet what was received for -// a connection_id in time wait state. -// client_address - address of the client that sent that packet. Needed to send -// the public reset packet back to the client. -// packet - the pending public reset packet that is to be sent to the client. -// created instance takes the ownership of this packet. -class QuicTimeWaitListManager::QueuedPacket { - public: - QueuedPacket(const QuicSocketAddress& server_address, - const QuicSocketAddress& client_address, - std::unique_ptr<QuicEncryptedPacket> packet) - : server_address_(server_address), - client_address_(client_address), - packet_(std::move(packet)) {} - - const QuicSocketAddress& server_address() const { return server_address_; } - const QuicSocketAddress& client_address() const { return client_address_; } - QuicEncryptedPacket* packet() { return packet_.get(); } - - private: - const QuicSocketAddress server_address_; - const QuicSocketAddress client_address_; - std::unique_ptr<QuicEncryptedPacket> packet_; - - DISALLOW_COPY_AND_ASSIGN(QueuedPacket); -}; - -QuicTimeWaitListManager::QuicTimeWaitListManager( - QuicPacketWriter* writer, - Visitor* visitor, - QuicConnectionHelperInterface* helper, - QuicAlarmFactory* alarm_factory) - : time_wait_period_( - QuicTime::Delta::FromSeconds(FLAGS_quic_time_wait_list_seconds)), - connection_id_clean_up_alarm_( - alarm_factory->CreateAlarm(new ConnectionIdCleanUpAlarm(this))), - clock_(helper->GetClock()), - writer_(writer), - visitor_(visitor) { - SetConnectionIdCleanUpAlarm(); -} - -QuicTimeWaitListManager::~QuicTimeWaitListManager() { - connection_id_clean_up_alarm_->Cancel(); -} - -void QuicTimeWaitListManager::AddConnectionIdToTimeWait( - QuicConnectionId connection_id, - ParsedQuicVersion version, - bool ietf_quic, - bool connection_rejected_statelessly, - std::vector<std::unique_ptr<QuicEncryptedPacket>>* termination_packets) { - if (connection_rejected_statelessly) { - DCHECK(termination_packets != nullptr && !termination_packets->empty()) - << "Connections that were rejected statelessly must " - << "have a close packet. connection_id = " << connection_id; - } - int num_packets = 0; - ConnectionIdMap::iterator it = connection_id_map_.find(connection_id); - const bool new_connection_id = it == connection_id_map_.end(); - if (!new_connection_id) { // Replace record if it is reinserted. - num_packets = it->second.num_packets; - connection_id_map_.erase(it); - } - TrimTimeWaitListIfNeeded(); - DCHECK_LT(num_connections(), - static_cast<size_t>(FLAGS_quic_time_wait_list_max_connections)); - ConnectionIdData data(num_packets, version, ietf_quic, - clock_->ApproximateNow(), - connection_rejected_statelessly); - if (termination_packets != nullptr) { - data.termination_packets.swap(*termination_packets); - } - connection_id_map_.emplace(std::make_pair(connection_id, std::move(data))); - if (new_connection_id) { - visitor_->OnConnectionAddedToTimeWaitList(connection_id); - } -} - -bool QuicTimeWaitListManager::IsConnectionIdInTimeWait( - QuicConnectionId connection_id) const { - return QuicContainsKey(connection_id_map_, connection_id); -} - -ParsedQuicVersion QuicTimeWaitListManager::GetQuicVersionFromConnectionId( - QuicConnectionId connection_id) { - ConnectionIdMap::iterator it = connection_id_map_.find(connection_id); - DCHECK(it != connection_id_map_.end()); - return (it->second).version; -} - -void QuicTimeWaitListManager::OnBlockedWriterCanWrite() { - while (!pending_packets_queue_.empty()) { - QueuedPacket* queued_packet = pending_packets_queue_.front().get(); - if (!WriteToWire(queued_packet)) { - return; - } - pending_packets_queue_.pop_front(); - } -} - -void QuicTimeWaitListManager::ProcessPacket( - const QuicSocketAddress& server_address, - const QuicSocketAddress& client_address, - QuicConnectionId connection_id) { - DCHECK(IsConnectionIdInTimeWait(connection_id)); - QUIC_DLOG(INFO) << "Processing " << connection_id << " in time wait state."; - // TODO(satyamshekhar): Think about handling packets from different client - // addresses. - ConnectionIdMap::iterator it = connection_id_map_.find(connection_id); - DCHECK(it != connection_id_map_.end()); - // Increment the received packet count. - ConnectionIdData* connection_data = &it->second; - ++(connection_data->num_packets); - - if (!ShouldSendResponse(connection_data->num_packets)) { - return; - } - - if (!connection_data->termination_packets.empty()) { - if (connection_data->connection_rejected_statelessly) { - QUIC_DVLOG(3) - << "Time wait list sending previous stateless reject response " - << "for connection " << connection_id; - } - for (const auto& packet : connection_data->termination_packets) { - SendOrQueuePacket(QuicMakeUnique<QueuedPacket>( - server_address, client_address, packet->Clone())); - } - return; - } - - SendPublicReset(server_address, client_address, connection_id); -} - -void QuicTimeWaitListManager::SendVersionNegotiationPacket( - QuicConnectionId connection_id, - bool ietf_quic, - const ParsedQuicVersionVector& supported_versions, - const QuicSocketAddress& server_address, - const QuicSocketAddress& client_address) { - SendOrQueuePacket(QuicMakeUnique<QueuedPacket>( - server_address, client_address, - QuicFramer::BuildVersionNegotiationPacket(connection_id, ietf_quic, - supported_versions))); -} - -// Returns true if the number of packets received for this connection_id is a -// power of 2 to throttle the number of public reset packets we send to a -// client. -bool QuicTimeWaitListManager::ShouldSendResponse(int received_packet_count) { - return (received_packet_count & (received_packet_count - 1)) == 0; -} - -void QuicTimeWaitListManager::SendPublicReset( - const QuicSocketAddress& server_address, - const QuicSocketAddress& client_address, - QuicConnectionId connection_id) { - QuicPublicResetPacket packet; - packet.connection_id = connection_id; - // TODO(satyamshekhar): generate a valid nonce for this connection_id. - packet.nonce_proof = 1010101; - packet.client_address = client_address; - // Takes ownership of the packet. - SendOrQueuePacket(QuicMakeUnique<QueuedPacket>(server_address, client_address, - BuildPublicReset(packet))); -} - -std::unique_ptr<QuicEncryptedPacket> QuicTimeWaitListManager::BuildPublicReset( - const QuicPublicResetPacket& packet) { - return QuicFramer::BuildPublicResetPacket(packet); -} - -// Either sends the packet and deletes it or makes pending queue the -// owner of the packet. -void QuicTimeWaitListManager::SendOrQueuePacket( - std::unique_ptr<QueuedPacket> packet) { - if (WriteToWire(packet.get())) { - // Allow the packet to be deleted upon leaving this function. - return; - } - pending_packets_queue_.push_back(std::move(packet)); -} - -bool QuicTimeWaitListManager::WriteToWire(QueuedPacket* queued_packet) { - if (writer_->IsWriteBlocked()) { - visitor_->OnWriteBlocked(this); - return false; - } - WriteResult result = writer_->WritePacket( - queued_packet->packet()->data(), queued_packet->packet()->length(), - queued_packet->server_address().host(), queued_packet->client_address(), - nullptr); - if (result.status == WRITE_STATUS_BLOCKED) { - // If blocked and unbuffered, return false to retry sending. - DCHECK(writer_->IsWriteBlocked()); - visitor_->OnWriteBlocked(this); - return writer_->IsWriteBlockedDataBuffered(); - } else if (IsWriteError(result.status)) { - QUIC_LOG_FIRST_N(WARNING, 1) - << "Received unknown error while sending reset packet to " - << queued_packet->client_address().ToString() << ": " - << strerror(result.error_code); - } - return true; -} - -void QuicTimeWaitListManager::SetConnectionIdCleanUpAlarm() { - QuicTime::Delta next_alarm_interval = QuicTime::Delta::Zero(); - if (!connection_id_map_.empty()) { - QuicTime oldest_connection_id = - connection_id_map_.begin()->second.time_added; - QuicTime now = clock_->ApproximateNow(); - if (now - oldest_connection_id < time_wait_period_) { - next_alarm_interval = oldest_connection_id + time_wait_period_ - now; - } else { - QUIC_LOG(ERROR) - << "ConnectionId lingered for longer than time_wait_period_"; - } - } else { - // No connection_ids added so none will expire before time_wait_period_. - next_alarm_interval = time_wait_period_; - } - - connection_id_clean_up_alarm_->Update( - clock_->ApproximateNow() + next_alarm_interval, QuicTime::Delta::Zero()); -} - -bool QuicTimeWaitListManager::MaybeExpireOldestConnection( - QuicTime expiration_time) { - if (connection_id_map_.empty()) { - return false; - } - ConnectionIdMap::iterator it = connection_id_map_.begin(); - QuicTime oldest_connection_id_time = it->second.time_added; - if (oldest_connection_id_time > expiration_time) { - // Too recent, don't retire. - return false; - } - // This connection_id has lived its age, retire it now. - connection_id_map_.erase(it); - return true; -} - -void QuicTimeWaitListManager::CleanUpOldConnectionIds() { - QuicTime now = clock_->ApproximateNow(); - QuicTime expiration = now - time_wait_period_; - - while (MaybeExpireOldestConnection(expiration)) { - } - - SetConnectionIdCleanUpAlarm(); -} - -void QuicTimeWaitListManager::TrimTimeWaitListIfNeeded() { - if (FLAGS_quic_time_wait_list_max_connections < 0) { - return; - } - while (num_connections() >= - static_cast<size_t>(FLAGS_quic_time_wait_list_max_connections)) { - MaybeExpireOldestConnection(QuicTime::Infinite()); - } -} - -QuicTimeWaitListManager::ConnectionIdData::ConnectionIdData( - int num_packets, - ParsedQuicVersion version, - bool ietf_quic, - QuicTime time_added, - bool connection_rejected_statelessly) - : num_packets(num_packets), - version(version), - ietf_quic(ietf_quic), - time_added(time_added), - connection_rejected_statelessly(connection_rejected_statelessly) {} - -QuicTimeWaitListManager::ConnectionIdData::ConnectionIdData( - ConnectionIdData&& other) = default; - -QuicTimeWaitListManager::ConnectionIdData::~ConnectionIdData() = default; - -} // namespace net diff --git a/chromium/net/tools/quic/quic_time_wait_list_manager.h b/chromium/net/tools/quic/quic_time_wait_list_manager.h deleted file mode 100644 index e5ab534b860..00000000000 --- a/chromium/net/tools/quic/quic_time_wait_list_manager.h +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Handles packets for connection_ids in time wait state by discarding the -// packet and sending the clients a public reset packet with exponential -// backoff. - -#ifndef NET_TOOLS_QUIC_QUIC_TIME_WAIT_LIST_MANAGER_H_ -#define NET_TOOLS_QUIC_QUIC_TIME_WAIT_LIST_MANAGER_H_ - -#include <stddef.h> - -#include <memory> - -#include "base/macros.h" -#include "net/quic/core/quic_blocked_writer_interface.h" -#include "net/quic/core/quic_connection.h" -#include "net/quic/core/quic_framer.h" -#include "net/quic/core/quic_packet_writer.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/core/quic_session.h" -#include "net/quic/platform/api/quic_containers.h" -#include "net/quic/platform/api/quic_flags.h" - -namespace net { - -namespace test { -class QuicDispatcherPeer; -class QuicTimeWaitListManagerPeer; -} // namespace test - -// Maintains a list of all connection_ids that have been recently closed. A -// connection_id lives in this state for time_wait_period_. All packets received -// for connection_ids in this state are handed over to the -// QuicTimeWaitListManager by the QuicDispatcher. Decides whether to send a -// public reset packet, a copy of the previously sent connection close packet, -// or nothing to the client which sent a packet with the connection_id in time -// wait state. After the connection_id expires its time wait period, a new -// connection/session will be created if a packet is received for this -// connection_id. -class QuicTimeWaitListManager : public QuicBlockedWriterInterface { - public: - class Visitor : public QuicSession::Visitor { - public: - // Called after the given connection is added to the time-wait std::list. - virtual void OnConnectionAddedToTimeWaitList( - QuicConnectionId connection_id) = 0; - }; - - // writer - the entity that writes to the socket. (Owned by the dispatcher) - // visitor - the entity that manages blocked writers. (The dispatcher) - // helper - provides a clock (Owned by the dispatcher) - // alarm_factory - used to run clean up alarms. (Owned by the dispatcher) - QuicTimeWaitListManager(QuicPacketWriter* writer, - Visitor* visitor, - QuicConnectionHelperInterface* helper, - QuicAlarmFactory* alarm_factory); - ~QuicTimeWaitListManager() override; - - // Adds the given connection_id to time wait state for time_wait_period_. - // If |termination_packets| are provided, copies of these packets will be sent - // when a packet with this connection ID is processed. If no termination - // packets are provided, then a PUBLIC_RESET will be sent with the specified - // |version|. Any termination packets will be move from |termination_packets| - // and will become owned by the manager. If |connection_rejected_statelessly| - // is true, it means that the connection was closed due to a stateless reject, - // and termination packets are expected. - virtual void AddConnectionIdToTimeWait( - QuicConnectionId connection_id, - ParsedQuicVersion version, - bool ietf_quic, - bool connection_rejected_statelessly, - std::vector<std::unique_ptr<QuicEncryptedPacket>>* termination_packets); - - // Returns true if the connection_id is in time wait state, false otherwise. - // Packets received for this connection_id should not lead to creation of new - // QuicSessions. - bool IsConnectionIdInTimeWait(QuicConnectionId connection_id) const; - - // Called when a packet is received for a connection_id that is in time wait - // state. Sends a public reset packet to the client which sent this - // connection_id. Sending of the public reset packet is throttled by using - // exponential back off. DCHECKs for the connection_id to be in time wait - // state. virtual to override in tests. - virtual void ProcessPacket(const QuicSocketAddress& server_address, - const QuicSocketAddress& client_address, - QuicConnectionId connection_id); - - // Called by the dispatcher when the underlying socket becomes writable again, - // since we might need to send pending public reset packets which we didn't - // send because the underlying socket was write blocked. - void OnBlockedWriterCanWrite() override; - - // Used to delete connection_id entries that have outlived their time wait - // period. - void CleanUpOldConnectionIds(); - - // If necessary, trims the oldest connections from the time-wait list until - // the size is under the configured maximum. - void TrimTimeWaitListIfNeeded(); - - // Given a ConnectionId that exists in the time wait list, returns the - // ParsedQuicVersion associated with it. - ParsedQuicVersion GetQuicVersionFromConnectionId( - QuicConnectionId connection_id); - - // The number of connections on the time-wait list. - size_t num_connections() const { return connection_id_map_.size(); } - - // Sends a version negotiation packet for |connection_id| announcing support - // for |supported_versions| to |client_address| from |server_address|. - virtual void SendVersionNegotiationPacket( - QuicConnectionId connection_id, - bool ietf_quic, - const ParsedQuicVersionVector& supported_versions, - const QuicSocketAddress& server_address, - const QuicSocketAddress& client_address); - - protected: - virtual std::unique_ptr<QuicEncryptedPacket> BuildPublicReset( - const QuicPublicResetPacket& packet); - - // Creates a public reset packet and sends it or queues it to be sent later. - virtual void SendPublicReset(const QuicSocketAddress& server_address, - const QuicSocketAddress& client_address, - QuicConnectionId connection_id); - - private: - friend class test::QuicDispatcherPeer; - friend class test::QuicTimeWaitListManagerPeer; - - // Internal structure to store pending public reset packets. - class QueuedPacket; - - // Decides if a packet should be sent for this connection_id based on the - // number of received packets. - bool ShouldSendResponse(int received_packet_count); - - // Either sends the packet and deletes it or makes pending_packets_queue_ the - // owner of the packet. - void SendOrQueuePacket(std::unique_ptr<QueuedPacket> packet); - - // Sends the packet out. Returns true if the packet was successfully consumed. - // If the writer got blocked and did not buffer the packet, we'll need to keep - // the packet and retry sending. In case of all other errors we drop the - // packet. - bool WriteToWire(QueuedPacket* packet); - - // Register the alarm server to wake up at appropriate time. - void SetConnectionIdCleanUpAlarm(); - - // Removes the oldest connection from the time-wait list if it was added prior - // to "expiration_time". To unconditionally remove the oldest connection, use - // a QuicTime::Delta:Infinity(). This function modifies the - // connection_id_map_. If you plan to call this function in a loop, any - // iterators that you hold before the call to this function may be invalid - // afterward. Returns true if the oldest connection was expired. Returns - // false if the map is empty or the oldest connection has not expired. - bool MaybeExpireOldestConnection(QuicTime expiration_time); - - // A map from a recently closed connection_id to the number of packets - // received after the termination of the connection bound to the - // connection_id. - struct ConnectionIdData { - ConnectionIdData(int num_packets, - ParsedQuicVersion version, - bool ietf_quic, - QuicTime time_added, - bool connection_rejected_statelessly); - - ConnectionIdData(const ConnectionIdData& other) = delete; - ConnectionIdData(ConnectionIdData&& other); - - ~ConnectionIdData(); - - int num_packets; - ParsedQuicVersion version; - bool ietf_quic; - QuicTime time_added; - // These packets may contain CONNECTION_CLOSE frames, or SREJ messages. - std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets; - bool connection_rejected_statelessly; - }; - - // QuicLinkedHashMap allows lookup by ConnectionId and traversal in add order. - typedef QuicLinkedHashMap<QuicConnectionId, ConnectionIdData> ConnectionIdMap; - ConnectionIdMap connection_id_map_; - - // Pending public reset packets that need to be sent out to the client - // when we are given a chance to write by the dispatcher. - QuicDeque<std::unique_ptr<QueuedPacket>> pending_packets_queue_; - - // Time period for which connection_ids should remain in time wait state. - const QuicTime::Delta time_wait_period_; - - // Alarm to clean up connection_ids that have out lived their duration in - // time wait state. - std::unique_ptr<QuicAlarm> connection_id_clean_up_alarm_; - - // Clock to efficiently measure approximate time. - const QuicClock* clock_; - - // Interface that writes given buffer to the socket. - QuicPacketWriter* writer_; - - // Interface that manages blocked writers. - Visitor* visitor_; - - DISALLOW_COPY_AND_ASSIGN(QuicTimeWaitListManager); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_QUIC_TIME_WAIT_LIST_MANAGER_H_ diff --git a/chromium/net/tools/quic/quic_time_wait_list_manager_test.cc b/chromium/net/tools/quic/quic_time_wait_list_manager_test.cc deleted file mode 100644 index 225471f9115..00000000000 --- a/chromium/net/tools/quic/quic_time_wait_list_manager_test.cc +++ /dev/null @@ -1,501 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/quic_time_wait_list_manager.h" - -#include <errno.h> -#include <memory> -#include <ostream> - -#include "net/quic/core/crypto/crypto_protocol.h" -#include "net/quic/core/crypto/null_encrypter.h" -#include "net/quic/core/crypto/quic_decrypter.h" -#include "net/quic/core/crypto/quic_encrypter.h" -#include "net/quic/core/quic_data_reader.h" -#include "net/quic/core/quic_framer.h" -#include "net/quic/core/quic_packet_writer.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/core/quic_utils.h" -#include "net/quic/platform/api/quic_flags.h" -#include "net/quic/platform/api/quic_test.h" -#include "net/quic/test_tools/quic_test_utils.h" -#include "net/quic/test_tools/quic_time_wait_list_manager_peer.h" -#include "net/tools/quic/quic_epoll_alarm_factory.h" -#include "net/tools/quic/quic_epoll_connection_helper.h" -#include "net/tools/quic/test_tools/mock_epoll_server.h" -#include "net/tools/quic/test_tools/mock_quic_session_visitor.h" - -using testing::_; -using testing::Args; -using testing::Assign; -using testing::DoAll; -using testing::Matcher; -using testing::NiceMock; -using testing::Return; -using testing::ReturnPointee; -using testing::StrictMock; -using testing::Truly; - -namespace net { -namespace test { -namespace { - -class FramerVisitorCapturingPublicReset : public NoOpFramerVisitor { - public: - FramerVisitorCapturingPublicReset() = default; - ~FramerVisitorCapturingPublicReset() override = default; - - void OnPublicResetPacket(const QuicPublicResetPacket& public_reset) override { - public_reset_packet_ = public_reset; - } - - const QuicPublicResetPacket public_reset_packet() { - return public_reset_packet_; - } - - private: - QuicPublicResetPacket public_reset_packet_; -}; - -class MockFakeTimeEpollServer : public FakeTimeEpollServer { - public: - MOCK_METHOD2(RegisterAlarm, - void(int64_t timeout_in_us, EpollAlarmCallbackInterface* alarm)); -}; - -class QuicTimeWaitListManagerTest : public QuicTest { - protected: - QuicTimeWaitListManagerTest() - : helper_(&epoll_server_, QuicAllocator::BUFFER_POOL), - alarm_factory_(&epoll_server_), - time_wait_list_manager_(&writer_, &visitor_, &helper_, &alarm_factory_), - connection_id_(45), - client_address_(TestPeerIPAddress(), kTestPort), - writer_is_blocked_(false) {} - - ~QuicTimeWaitListManagerTest() override = default; - - void SetUp() override { - EXPECT_CALL(writer_, IsWriteBlocked()) - .WillRepeatedly(ReturnPointee(&writer_is_blocked_)); - EXPECT_CALL(writer_, IsWriteBlockedDataBuffered()) - .WillRepeatedly(Return(false)); - } - - void AddConnectionId(QuicConnectionId connection_id) { - AddConnectionId(connection_id, QuicVersionMax(), - /*connection_rejected_statelessly=*/false, nullptr); - } - - void AddStatelessConnectionId(QuicConnectionId connection_id) { - std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets; - termination_packets.push_back(std::unique_ptr<QuicEncryptedPacket>( - new QuicEncryptedPacket(nullptr, 0, false))); - time_wait_list_manager_.AddConnectionIdToTimeWait( - connection_id, QuicVersionMax(), false, - /*connection_rejected_statelessly=*/true, &termination_packets); - } - - void AddConnectionId( - QuicConnectionId connection_id, - ParsedQuicVersion version, - bool connection_rejected_statelessly, - std::vector<std::unique_ptr<QuicEncryptedPacket>>* packets) { - time_wait_list_manager_.AddConnectionIdToTimeWait( - connection_id, version, false, connection_rejected_statelessly, - packets); - } - - bool IsConnectionIdInTimeWait(QuicConnectionId connection_id) { - return time_wait_list_manager_.IsConnectionIdInTimeWait(connection_id); - } - - void ProcessPacket(QuicConnectionId connection_id) { - time_wait_list_manager_.ProcessPacket(server_address_, client_address_, - connection_id); - } - - QuicEncryptedPacket* ConstructEncryptedPacket( - QuicConnectionId connection_id, - QuicPacketNumber packet_number) { - return net::test::ConstructEncryptedPacket(connection_id, false, false, - packet_number, "data"); - } - - NiceMock<MockFakeTimeEpollServer> epoll_server_; - QuicEpollConnectionHelper helper_; - QuicEpollAlarmFactory alarm_factory_; - StrictMock<MockPacketWriter> writer_; - StrictMock<MockQuicSessionVisitor> visitor_; - QuicTimeWaitListManager time_wait_list_manager_; - QuicConnectionId connection_id_; - QuicSocketAddress server_address_; - QuicSocketAddress client_address_; - bool writer_is_blocked_; -}; - -bool ValidPublicResetPacketPredicate( - QuicConnectionId expected_connection_id, - const testing::tuple<const char*, int>& packet_buffer) { - FramerVisitorCapturingPublicReset visitor; - QuicFramer framer(AllSupportedVersions(), QuicTime::Zero(), - Perspective::IS_CLIENT); - framer.set_visitor(&visitor); - QuicEncryptedPacket encrypted(testing::get<0>(packet_buffer), - testing::get<1>(packet_buffer)); - framer.ProcessPacket(encrypted); - QuicPublicResetPacket packet = visitor.public_reset_packet(); - return expected_connection_id == packet.connection_id && - TestPeerIPAddress() == packet.client_address.host() && - kTestPort == packet.client_address.port(); -} - -Matcher<const testing::tuple<const char*, int>> PublicResetPacketEq( - QuicConnectionId connection_id) { - return Truly( - [connection_id](const testing::tuple<const char*, int> packet_buffer) { - return ValidPublicResetPacketPredicate(connection_id, packet_buffer); - }); -} - -TEST_F(QuicTimeWaitListManagerTest, CheckConnectionIdInTimeWait) { - EXPECT_FALSE(IsConnectionIdInTimeWait(connection_id_)); - EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); - AddConnectionId(connection_id_); - EXPECT_EQ(1u, time_wait_list_manager_.num_connections()); - EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_)); -} - -TEST_F(QuicTimeWaitListManagerTest, CheckStatelessConnectionIdInTimeWait) { - EXPECT_FALSE(IsConnectionIdInTimeWait(connection_id_)); - EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); - AddStatelessConnectionId(connection_id_); - EXPECT_EQ(1u, time_wait_list_manager_.num_connections()); - EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_)); -} - -TEST_F(QuicTimeWaitListManagerTest, SendVersionNegotiationPacket) { - std::unique_ptr<QuicEncryptedPacket> packet( - QuicFramer::BuildVersionNegotiationPacket(connection_id_, false, - AllSupportedVersions())); - EXPECT_CALL(writer_, WritePacket(_, packet->length(), server_address_.host(), - client_address_, _)) - .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1))); - - time_wait_list_manager_.SendVersionNegotiationPacket( - connection_id_, false, AllSupportedVersions(), server_address_, - client_address_); - EXPECT_EQ(0u, time_wait_list_manager_.num_connections()); -} - -TEST_F(QuicTimeWaitListManagerTest, SendConnectionClose) { - const size_t kConnectionCloseLength = 100; - EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); - std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets; - termination_packets.push_back( - std::unique_ptr<QuicEncryptedPacket>(new QuicEncryptedPacket( - new char[kConnectionCloseLength], kConnectionCloseLength, true))); - AddConnectionId(connection_id_, QuicVersionMax(), - /*connection_rejected_statelessly=*/false, - &termination_packets); - EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength, - server_address_.host(), client_address_, _)) - .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1))); - - ProcessPacket(connection_id_); -} - -TEST_F(QuicTimeWaitListManagerTest, SendTwoConnectionCloses) { - const size_t kConnectionCloseLength = 100; - EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); - std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets; - termination_packets.push_back( - std::unique_ptr<QuicEncryptedPacket>(new QuicEncryptedPacket( - new char[kConnectionCloseLength], kConnectionCloseLength, true))); - termination_packets.push_back( - std::unique_ptr<QuicEncryptedPacket>(new QuicEncryptedPacket( - new char[kConnectionCloseLength], kConnectionCloseLength, true))); - AddConnectionId(connection_id_, QuicVersionMax(), - /*connection_rejected_statelessly=*/false, - &termination_packets); - EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength, - server_address_.host(), client_address_, _)) - .Times(2) - .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1))); - - ProcessPacket(connection_id_); -} - -TEST_F(QuicTimeWaitListManagerTest, SendPublicReset) { - EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); - AddConnectionId(connection_id_); - EXPECT_CALL(writer_, - WritePacket(_, _, server_address_.host(), client_address_, _)) - .With(Args<0, 1>(PublicResetPacketEq(connection_id_))) - .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0))); - - ProcessPacket(connection_id_); -} - -TEST_F(QuicTimeWaitListManagerTest, SendPublicResetWithExponentialBackOff) { - EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); - AddConnectionId(connection_id_); - EXPECT_EQ(1u, time_wait_list_manager_.num_connections()); - for (int packet_number = 1; packet_number < 101; ++packet_number) { - if ((packet_number & (packet_number - 1)) == 0) { - EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)) - .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1))); - } - ProcessPacket(connection_id_); - // Send public reset with exponential back off. - if ((packet_number & (packet_number - 1)) == 0) { - EXPECT_TRUE(QuicTimeWaitListManagerPeer::ShouldSendResponse( - &time_wait_list_manager_, packet_number)); - } else { - EXPECT_FALSE(QuicTimeWaitListManagerPeer::ShouldSendResponse( - &time_wait_list_manager_, packet_number)); - } - } -} - -TEST_F(QuicTimeWaitListManagerTest, NoPublicResetForStatelessConnections) { - EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); - AddStatelessConnectionId(connection_id_); - - EXPECT_CALL(writer_, - WritePacket(_, _, server_address_.host(), client_address_, _)) - .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1))); - - ProcessPacket(connection_id_); -} - -TEST_F(QuicTimeWaitListManagerTest, CleanUpOldConnectionIds) { - const size_t kConnectionIdCount = 100; - const size_t kOldConnectionIdCount = 31; - - // Add connection_ids such that their expiry time is time_wait_period_. - epoll_server_.set_now_in_usec(0); - for (size_t connection_id = 1; connection_id <= kOldConnectionIdCount; - ++connection_id) { - EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id)); - AddConnectionId(connection_id); - } - EXPECT_EQ(kOldConnectionIdCount, time_wait_list_manager_.num_connections()); - - // Add remaining connection_ids such that their add time is - // 2 * time_wait_period_. - const QuicTime::Delta time_wait_period = - QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_); - epoll_server_.set_now_in_usec(time_wait_period.ToMicroseconds()); - for (size_t connection_id = kOldConnectionIdCount + 1; - connection_id <= kConnectionIdCount; ++connection_id) { - EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id)); - AddConnectionId(connection_id); - } - EXPECT_EQ(kConnectionIdCount, time_wait_list_manager_.num_connections()); - - QuicTime::Delta offset = QuicTime::Delta::FromMicroseconds(39); - // Now set the current time as time_wait_period + offset usecs. - epoll_server_.set_now_in_usec((time_wait_period + offset).ToMicroseconds()); - // After all the old connection_ids are cleaned up, check the next alarm - // interval. - int64_t next_alarm_time = epoll_server_.ApproximateNowInUsec() + - (time_wait_period - offset).ToMicroseconds(); - EXPECT_CALL(epoll_server_, RegisterAlarm(next_alarm_time, _)); - - time_wait_list_manager_.CleanUpOldConnectionIds(); - for (size_t connection_id = 1; connection_id <= kConnectionIdCount; - ++connection_id) { - EXPECT_EQ(connection_id > kOldConnectionIdCount, - IsConnectionIdInTimeWait(connection_id)) - << "kOldConnectionIdCount: " << kOldConnectionIdCount - << " connection_id: " << connection_id; - } - EXPECT_EQ(kConnectionIdCount - kOldConnectionIdCount, - time_wait_list_manager_.num_connections()); -} - -TEST_F(QuicTimeWaitListManagerTest, SendQueuedPackets) { - QuicConnectionId connection_id = 1; - EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id)); - AddConnectionId(connection_id); - QuicPacketNumber packet_number = 234; - std::unique_ptr<QuicEncryptedPacket> packet( - ConstructEncryptedPacket(connection_id, packet_number)); - // Let first write through. - EXPECT_CALL(writer_, - WritePacket(_, _, server_address_.host(), client_address_, _)) - .With(Args<0, 1>(PublicResetPacketEq(connection_id))) - .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length()))); - ProcessPacket(connection_id); - - // write block for the next packet. - EXPECT_CALL(writer_, - WritePacket(_, _, server_address_.host(), client_address_, _)) - .With(Args<0, 1>(PublicResetPacketEq(connection_id))) - .WillOnce(DoAll(Assign(&writer_is_blocked_, true), - Return(WriteResult(WRITE_STATUS_BLOCKED, EAGAIN)))); - EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_)); - ProcessPacket(connection_id); - // 3rd packet. No public reset should be sent; - ProcessPacket(connection_id); - - // write packet should not be called since we are write blocked but the - // should be queued. - QuicConnectionId other_connection_id = 2; - EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(other_connection_id)); - AddConnectionId(other_connection_id); - QuicPacketNumber other_packet_number = 23423; - std::unique_ptr<QuicEncryptedPacket> other_packet( - ConstructEncryptedPacket(other_connection_id, other_packet_number)); - EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)).Times(0); - EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_)); - ProcessPacket(other_connection_id); - EXPECT_EQ(2u, time_wait_list_manager_.num_connections()); - - // Now expect all the write blocked public reset packets to be sent again. - writer_is_blocked_ = false; - EXPECT_CALL(writer_, - WritePacket(_, _, server_address_.host(), client_address_, _)) - .With(Args<0, 1>(PublicResetPacketEq(connection_id))) - .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length()))); - EXPECT_CALL(writer_, - WritePacket(_, _, server_address_.host(), client_address_, _)) - .With(Args<0, 1>(PublicResetPacketEq(other_connection_id))) - .WillOnce(Return(WriteResult(WRITE_STATUS_OK, other_packet->length()))); - time_wait_list_manager_.OnBlockedWriterCanWrite(); -} - -TEST_F(QuicTimeWaitListManagerTest, GetQuicVersionFromMap) { - const int kConnectionId1 = 123; - const int kConnectionId2 = 456; - const int kConnectionId3 = 789; - - EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(kConnectionId1)); - EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(kConnectionId2)); - EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(kConnectionId3)); - AddConnectionId(kConnectionId1, QuicVersionMin(), - /*connection_rejected_statelessly=*/false, nullptr); - AddConnectionId(kConnectionId2, QuicVersionMax(), - /*connection_rejected_statelessly=*/false, nullptr); - AddConnectionId(kConnectionId3, QuicVersionMax(), - /*connection_rejected_statelessly=*/false, nullptr); - - EXPECT_EQ(QuicTransportVersionMin(), - QuicTimeWaitListManagerPeer::GetQuicVersionFromConnectionId( - &time_wait_list_manager_, kConnectionId1)); - EXPECT_EQ(QuicTransportVersionMax(), - QuicTimeWaitListManagerPeer::GetQuicVersionFromConnectionId( - &time_wait_list_manager_, kConnectionId2)); - EXPECT_EQ(QuicTransportVersionMax(), - QuicTimeWaitListManagerPeer::GetQuicVersionFromConnectionId( - &time_wait_list_manager_, kConnectionId3)); -} - -TEST_F(QuicTimeWaitListManagerTest, AddConnectionIdTwice) { - // Add connection_ids such that their expiry time is time_wait_period_. - epoll_server_.set_now_in_usec(0); - EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id_)); - AddConnectionId(connection_id_); - EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_)); - const size_t kConnectionCloseLength = 100; - std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets; - termination_packets.push_back( - std::unique_ptr<QuicEncryptedPacket>(new QuicEncryptedPacket( - new char[kConnectionCloseLength], kConnectionCloseLength, true))); - AddConnectionId(connection_id_, QuicVersionMax(), - /*connection_rejected_statelessly=*/false, - &termination_packets); - EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id_)); - EXPECT_EQ(1u, time_wait_list_manager_.num_connections()); - - EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength, - server_address_.host(), client_address_, _)) - .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1))); - - ProcessPacket(connection_id_); - - const QuicTime::Delta time_wait_period = - QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_); - - QuicTime::Delta offset = QuicTime::Delta::FromMicroseconds(39); - // Now set the current time as time_wait_period + offset usecs. - epoll_server_.set_now_in_usec((time_wait_period + offset).ToMicroseconds()); - // After the connection_ids are cleaned up, check the next alarm interval. - int64_t next_alarm_time = - epoll_server_.ApproximateNowInUsec() + time_wait_period.ToMicroseconds(); - - EXPECT_CALL(epoll_server_, RegisterAlarm(next_alarm_time, _)); - time_wait_list_manager_.CleanUpOldConnectionIds(); - EXPECT_FALSE(IsConnectionIdInTimeWait(connection_id_)); - EXPECT_EQ(0u, time_wait_list_manager_.num_connections()); -} - -TEST_F(QuicTimeWaitListManagerTest, ConnectionIdsOrderedByTime) { - // Simple randomization: the values of connection_ids are randomly swapped. - // If the container is broken, the test will be 50% flaky. - const QuicConnectionId connection_id1 = - QuicRandom::GetInstance()->RandUint64() % 2; - const QuicConnectionId connection_id2 = 1 - connection_id1; - - // 1 will hash lower than 2, but we add it later. They should come out in the - // add order, not hash order. - epoll_server_.set_now_in_usec(0); - EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id1)); - AddConnectionId(connection_id1); - epoll_server_.set_now_in_usec(10); - EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id2)); - AddConnectionId(connection_id2); - EXPECT_EQ(2u, time_wait_list_manager_.num_connections()); - - const QuicTime::Delta time_wait_period = - QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_); - epoll_server_.set_now_in_usec(time_wait_period.ToMicroseconds() + 1); - - EXPECT_CALL(epoll_server_, RegisterAlarm(_, _)); - - time_wait_list_manager_.CleanUpOldConnectionIds(); - EXPECT_FALSE(IsConnectionIdInTimeWait(connection_id1)); - EXPECT_TRUE(IsConnectionIdInTimeWait(connection_id2)); - EXPECT_EQ(1u, time_wait_list_manager_.num_connections()); -} - -TEST_F(QuicTimeWaitListManagerTest, MaxConnectionsTest) { - // Basically, shut off time-based eviction. - FLAGS_quic_time_wait_list_seconds = 10000000000; - FLAGS_quic_time_wait_list_max_connections = 5; - - QuicConnectionId current_connection_id = 0; - // Add exactly the maximum number of connections - for (int64_t i = 0; i < FLAGS_quic_time_wait_list_max_connections; ++i) { - ++current_connection_id; - EXPECT_FALSE(IsConnectionIdInTimeWait(current_connection_id)); - EXPECT_CALL(visitor_, - OnConnectionAddedToTimeWaitList(current_connection_id)); - AddConnectionId(current_connection_id); - EXPECT_EQ(current_connection_id, time_wait_list_manager_.num_connections()); - EXPECT_TRUE(IsConnectionIdInTimeWait(current_connection_id)); - } - - // Now keep adding. Since we're already at the max, every new connection-id - // will evict the oldest one. - for (int64_t i = 0; i < FLAGS_quic_time_wait_list_max_connections; ++i) { - ++current_connection_id; - const QuicConnectionId id_to_evict = - current_connection_id - FLAGS_quic_time_wait_list_max_connections; - EXPECT_TRUE(IsConnectionIdInTimeWait(id_to_evict)); - EXPECT_FALSE(IsConnectionIdInTimeWait(current_connection_id)); - EXPECT_CALL(visitor_, - OnConnectionAddedToTimeWaitList(current_connection_id)); - AddConnectionId(current_connection_id); - EXPECT_EQ(static_cast<size_t>(FLAGS_quic_time_wait_list_max_connections), - time_wait_list_manager_.num_connections()); - EXPECT_FALSE(IsConnectionIdInTimeWait(id_to_evict)); - EXPECT_TRUE(IsConnectionIdInTimeWait(current_connection_id)); - } -} - -} // namespace -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/stateless_rejector.cc b/chromium/net/tools/quic/stateless_rejector.cc deleted file mode 100644 index 8ae3e851494..00000000000 --- a/chromium/net/tools/quic/stateless_rejector.cc +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/stateless_rejector.h" - -#include "net/quic/core/quic_crypto_server_stream.h" -#include "net/quic/platform/api/quic_bug_tracker.h" -#include "net/quic/platform/api/quic_flags.h" -#include "net/quic/platform/api/quic_string.h" - -namespace net { - -class StatelessRejector::ValidateCallback - : public ValidateClientHelloResultCallback { - public: - explicit ValidateCallback( - std::unique_ptr<StatelessRejector> rejector, - std::unique_ptr<StatelessRejector::ProcessDoneCallback> cb) - : rejector_(std::move(rejector)), cb_(std::move(cb)) {} - - ~ValidateCallback() override = default; - - void Run(QuicReferenceCountedPointer<Result> result, - std::unique_ptr<ProofSource::Details> /* proof_source_details */) - override { - StatelessRejector* rejector_ptr = rejector_.get(); - rejector_ptr->ProcessClientHello(std::move(result), std::move(rejector_), - std::move(cb_)); - } - - private: - std::unique_ptr<StatelessRejector> rejector_; - std::unique_ptr<StatelessRejector::ProcessDoneCallback> cb_; -}; - -StatelessRejector::StatelessRejector( - QuicTransportVersion version, - const QuicTransportVersionVector& versions, - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache, - const QuicClock* clock, - QuicRandom* random, - QuicByteCount chlo_packet_size, - const QuicSocketAddress& client_address, - const QuicSocketAddress& server_address) - : state_(UNKNOWN), - error_(QUIC_INTERNAL_ERROR), - version_(version), - versions_(versions), - connection_id_(0), - chlo_packet_size_(chlo_packet_size), - client_address_(client_address), - server_address_(server_address), - clock_(clock), - random_(random), - crypto_config_(crypto_config), - compressed_certs_cache_(compressed_certs_cache), - signed_config_(new QuicSignedServerConfig), - params_(new QuicCryptoNegotiatedParameters) {} - -StatelessRejector::~StatelessRejector() = default; - -void StatelessRejector::OnChlo(QuicTransportVersion version, - QuicConnectionId connection_id, - QuicConnectionId server_designated_connection_id, - const CryptoHandshakeMessage& message) { - DCHECK_EQ(kCHLO, message.tag()); - DCHECK_NE(connection_id, server_designated_connection_id); - DCHECK_EQ(state_, UNKNOWN); - - if (!GetQuicReloadableFlag(enable_quic_stateless_reject_support) || - !GetQuicReloadableFlag(quic_use_cheap_stateless_rejects) || - !QuicCryptoServerStream::DoesPeerSupportStatelessRejects(message)) { - state_ = UNSUPPORTED; - return; - } - - connection_id_ = connection_id; - server_designated_connection_id_ = server_designated_connection_id; - chlo_ = message; // Note: copies the message -} - -void StatelessRejector::Process(std::unique_ptr<StatelessRejector> rejector, - std::unique_ptr<ProcessDoneCallback> done_cb) { - QUIC_BUG_IF(rejector->state() != UNKNOWN) << "StatelessRejector::Process " - "called for a rejector which " - "has already made a decision"; - StatelessRejector* rejector_ptr = rejector.get(); - rejector_ptr->crypto_config_->ValidateClientHello( - rejector_ptr->chlo_, rejector_ptr->client_address_.host(), - rejector_ptr->server_address_, rejector_ptr->version_, - rejector_ptr->clock_, rejector_ptr->signed_config_, - std::unique_ptr<ValidateCallback>( - new ValidateCallback(std::move(rejector), std::move(done_cb)))); -} - -class StatelessRejector::ProcessClientHelloCallback - : public ProcessClientHelloResultCallback { - public: - ProcessClientHelloCallback( - std::unique_ptr<StatelessRejector> rejector, - std::unique_ptr<StatelessRejector::ProcessDoneCallback> done_cb) - : rejector_(std::move(rejector)), done_cb_(std::move(done_cb)) {} - - void Run(QuicErrorCode error, - const QuicString& error_details, - std::unique_ptr<CryptoHandshakeMessage> message, - std::unique_ptr<DiversificationNonce> diversification_nonce, - std::unique_ptr<ProofSource::Details> /* proof_source_details */) - override { - StatelessRejector* rejector_ptr = rejector_.get(); - rejector_ptr->ProcessClientHelloDone( - error, error_details, std::move(message), std::move(rejector_), - std::move(done_cb_)); - } - - private: - std::unique_ptr<StatelessRejector> rejector_; - std::unique_ptr<StatelessRejector::ProcessDoneCallback> done_cb_; -}; - -void StatelessRejector::ProcessClientHello( - QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result> - result, - std::unique_ptr<StatelessRejector> rejector, - std::unique_ptr<StatelessRejector::ProcessDoneCallback> done_cb) { - std::unique_ptr<ProcessClientHelloCallback> cb( - new ProcessClientHelloCallback(std::move(rejector), std::move(done_cb))); - crypto_config_->ProcessClientHello( - result, - /*reject_only=*/true, connection_id_, server_address_, client_address_, - version_, versions_, - /*use_stateless_rejects=*/true, server_designated_connection_id_, clock_, - random_, compressed_certs_cache_, params_, signed_config_, - QuicCryptoStream::CryptoMessageFramingOverhead(version_), - chlo_packet_size_, std::move(cb)); -} - -void StatelessRejector::ProcessClientHelloDone( - QuicErrorCode error, - const QuicString& error_details, - std::unique_ptr<CryptoHandshakeMessage> message, - std::unique_ptr<StatelessRejector> rejector, - std::unique_ptr<StatelessRejector::ProcessDoneCallback> done_cb) { - reply_ = std::move(message); - - if (error != QUIC_NO_ERROR) { - error_ = error; - error_details_ = error_details; - state_ = FAILED; - } else if (reply_->tag() == kSREJ) { - state_ = REJECTED; - } else { - state_ = ACCEPTED; - } - done_cb->Run(std::move(rejector)); -} - -} // namespace net diff --git a/chromium/net/tools/quic/stateless_rejector.h b/chromium/net/tools/quic/stateless_rejector.h deleted file mode 100644 index ac04e402665..00000000000 --- a/chromium/net/tools/quic/stateless_rejector.h +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_STATELESS_REJECTOR_H_ -#define NET_TOOLS_QUIC_STATELESS_REJECTOR_H_ - -#include "net/quic/core/crypto/crypto_framer.h" -#include "net/quic/core/crypto/quic_crypto_server_config.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/platform/api/quic_string.h" - -namespace net { - -// The StatelessRejector receives CHLO messages and generates an SREJ -// message in response, if the CHLO can be statelessly rejected. -class StatelessRejector { - public: - enum State { - UNKNOWN, // State has not yet been determined - UNSUPPORTED, // Stateless rejects are not supported - FAILED, // There was an error processing the CHLO. - ACCEPTED, // The CHLO was accepted - REJECTED, // The CHLO was rejected. - }; - - StatelessRejector(QuicTransportVersion version, - const QuicTransportVersionVector& versions, - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache, - const QuicClock* clock, - QuicRandom* random, - QuicByteCount chlo_packet_size, - const QuicSocketAddress& client_address, - const QuicSocketAddress& server_address); - - ~StatelessRejector(); - - // Called when |chlo| is received for |connection_id|. - void OnChlo(QuicTransportVersion version, - QuicConnectionId connection_id, - QuicConnectionId server_designated_connection_id, - const CryptoHandshakeMessage& chlo); - - class ProcessDoneCallback { - public: - virtual ~ProcessDoneCallback() = default; - virtual void Run(std::unique_ptr<StatelessRejector> rejector) = 0; - }; - - // Perform processing to determine whether the CHLO received in OnChlo should - // be statelessly rejected, and invoke the callback once a decision has been - // made. - static void Process(std::unique_ptr<StatelessRejector> rejector, - std::unique_ptr<ProcessDoneCallback> done_cb); - - // Returns the state of the rejector after OnChlo() has been called. - State state() const { return state_; } - - // Returns the error code when state() returns FAILED. - QuicErrorCode error() const { return error_; } - - // Returns the error details when state() returns FAILED. - QuicString error_details() const { return error_details_; } - - // Returns the connection ID. - QuicConnectionId connection_id() const { return connection_id_; } - - // Returns the SREJ message when state() returns REJECTED. - const CryptoHandshakeMessage& reply() const { return *reply_; } - - private: - // Helper class which is passed in to - // QuicCryptoServerConfig::ValidateClientHello. - class ValidateCallback; - friend class ValidateCallback; - - class ProcessClientHelloCallback; - friend class ProcessClientHelloCallback; - - void ProcessClientHello( - QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result> - result, - std::unique_ptr<StatelessRejector> rejector, - std::unique_ptr<StatelessRejector::ProcessDoneCallback> done_cb); - - void ProcessClientHelloDone( - QuicErrorCode error, - const QuicString& error_details, - std::unique_ptr<CryptoHandshakeMessage> message, - std::unique_ptr<StatelessRejector> rejector, - std::unique_ptr<StatelessRejector::ProcessDoneCallback> done_cb); - - State state_; - QuicErrorCode error_; - QuicString error_details_; - QuicTransportVersion version_; - QuicTransportVersionVector versions_; - QuicConnectionId connection_id_; - QuicConnectionId server_designated_connection_id_; - QuicByteCount chlo_packet_size_; - QuicSocketAddress client_address_; - QuicSocketAddress server_address_; - const QuicClock* clock_; - QuicRandom* random_; - const QuicCryptoServerConfig* crypto_config_; - QuicCompressedCertsCache* compressed_certs_cache_; - CryptoHandshakeMessage chlo_; - std::unique_ptr<CryptoHandshakeMessage> reply_; - CryptoFramer crypto_framer_; - QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_; - QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_; - - DISALLOW_COPY_AND_ASSIGN(StatelessRejector); -}; - -} // namespace net - -#endif // NET_TOOLS_QUIC_STATELESS_REJECTOR_H_ diff --git a/chromium/net/tools/quic/stateless_rejector_test.cc b/chromium/net/tools/quic/stateless_rejector_test.cc deleted file mode 100644 index 62e741b7a8b..00000000000 --- a/chromium/net/tools/quic/stateless_rejector_test.cc +++ /dev/null @@ -1,291 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/stateless_rejector.h" - -#include <memory> -#include <vector> - -#include "net/quic/core/crypto/crypto_handshake_message.h" -#include "net/quic/core/crypto/proof_source.h" -#include "net/quic/core/quic_utils.h" -#include "net/quic/core/tls_server_handshaker.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" -#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/platform/api/quic_text_utils.h" -#include "net/quic/test_tools/crypto_test_utils.h" -#include "net/quic/test_tools/quic_crypto_server_config_peer.h" -#include "net/quic/test_tools/quic_test_utils.h" - - -namespace net { -namespace test { -namespace { - -const QuicConnectionId kConnectionId = 42; -const QuicConnectionId kServerDesignateConnectionId = 24; - -// All four combinations of the two flags involved. -enum FlagsMode { ENABLED, STATELESS_DISABLED, CHEAP_DISABLED, BOTH_DISABLED }; - -const char* FlagsModeToString(FlagsMode mode) { - switch (mode) { - case ENABLED: - return "ENABLED"; - case STATELESS_DISABLED: - return "STATELESS_DISABLED"; - case CHEAP_DISABLED: - return "CHEAP_DISABLED"; - case BOTH_DISABLED: - return "BOTH_DISABLED"; - default: - QUIC_DLOG(FATAL) << "Unexpected FlagsMode"; - return nullptr; - } -} - -// Test various combinations of QUIC version and flag state. -struct TestParams { - QuicTransportVersion version; - FlagsMode flags; -}; - -QuicString TestParamToString(const testing::TestParamInfo<TestParams>& params) { - return QuicStrCat("v", params.param.version, "_", - FlagsModeToString(params.param.flags)); -} - -std::vector<TestParams> GetTestParams() { - std::vector<TestParams> params; - for (FlagsMode flags : - {ENABLED, STATELESS_DISABLED, CHEAP_DISABLED, BOTH_DISABLED}) { - for (QuicTransportVersion version : AllSupportedTransportVersions()) { - TestParams param; - param.version = version; - param.flags = flags; - params.push_back(param); - } - } - return params; -} - -class StatelessRejectorTest : public QuicTestWithParam<TestParams> { - public: - StatelessRejectorTest() - : proof_source_(crypto_test_utils::ProofSourceForTesting()), - config_(QuicCryptoServerConfig::TESTING, - QuicRandom::GetInstance(), - crypto_test_utils::ProofSourceForTesting(), - TlsServerHandshaker::CreateSslCtx()), - config_peer_(&config_), - compressed_certs_cache_( - QuicCompressedCertsCache::kQuicCompressedCertsCacheSize), - rejector_(QuicMakeUnique<StatelessRejector>( - GetParam().version, - AllSupportedTransportVersions(), - &config_, - &compressed_certs_cache_, - &clock_, - QuicRandom::GetInstance(), - kDefaultMaxPacketSize, - QuicSocketAddress(QuicIpAddress::Loopback4(), 12345), - QuicSocketAddress(QuicIpAddress::Loopback4(), 443))) { - SetQuicReloadableFlag( - enable_quic_stateless_reject_support, - GetParam().flags == ENABLED || GetParam().flags == CHEAP_DISABLED); - SetQuicReloadableFlag( - quic_use_cheap_stateless_rejects, - GetParam().flags == ENABLED || GetParam().flags == STATELESS_DISABLED); - - // Add a new primary config. - std::unique_ptr<CryptoHandshakeMessage> msg(config_.AddDefaultConfig( - QuicRandom::GetInstance(), &clock_, config_options_)); - - // Save the server config. - scid_hex_ = - "#" + QuicTextUtils::HexEncode(config_peer_.GetPrimaryConfig()->id); - - // Encode the QUIC version. - ver_hex_ = QuicVersionLabelToString( - QuicVersionToQuicVersionLabel(GetParam().version)); - - // Generate a public value. - char public_value[32]; - memset(public_value, 42, sizeof(public_value)); - pubs_hex_ = - "#" + QuicTextUtils::HexEncode(public_value, sizeof(public_value)); - - // Generate a client nonce. - QuicString nonce; - CryptoUtils::GenerateNonce( - clock_.WallNow(), QuicRandom::GetInstance(), - QuicStringPiece( - reinterpret_cast<char*>(config_peer_.GetPrimaryConfig()->orbit), - kOrbitSize), - &nonce); - nonc_hex_ = "#" + QuicTextUtils::HexEncode(nonce); - - // Generate a source address token. - SourceAddressTokens previous_tokens; - QuicIpAddress ip = QuicIpAddress::Loopback4(); - MockRandom rand; - QuicString stk = config_peer_.NewSourceAddressToken( - config_peer_.GetPrimaryConfig()->id, previous_tokens, ip, &rand, - clock_.WallNow(), nullptr); - stk_hex_ = "#" + QuicTextUtils::HexEncode(stk); - } - - protected: - class ProcessDoneCallback : public StatelessRejector::ProcessDoneCallback { - public: - explicit ProcessDoneCallback(StatelessRejectorTest* test) : test_(test) {} - void Run(std::unique_ptr<StatelessRejector> rejector) override { - test_->rejector_ = std::move(rejector); - } - - private: - StatelessRejectorTest* test_; - }; - - std::unique_ptr<ProofSource> proof_source_; - MockClock clock_; - QuicCryptoServerConfig config_; - QuicCryptoServerConfigPeer config_peer_; - QuicCompressedCertsCache compressed_certs_cache_; - QuicCryptoServerConfig::ConfigOptions config_options_; - std::unique_ptr<StatelessRejector> rejector_; - - // Values used in CHLO messages - QuicString scid_hex_; - QuicString nonc_hex_; - QuicString pubs_hex_; - QuicString ver_hex_; - QuicString stk_hex_; -}; - -INSTANTIATE_TEST_CASE_P(Flags, - StatelessRejectorTest, - ::testing::ValuesIn(GetTestParams()), - TestParamToString); - -TEST_P(StatelessRejectorTest, InvalidChlo) { - // clang-format off - const CryptoHandshakeMessage client_hello = crypto_test_utils::CreateCHLO( - {{"PDMD", "X509"}, - {"COPT", "SREJ"}}); - // clang-format on - rejector_->OnChlo(GetParam().version, kConnectionId, - kServerDesignateConnectionId, client_hello); - - if (GetParam().flags != ENABLED) { - EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_->state()); - return; - } - - // The StatelessRejector is undecided - proceed with async processing - ASSERT_EQ(StatelessRejector::UNKNOWN, rejector_->state()); - StatelessRejector::Process(std::move(rejector_), - QuicMakeUnique<ProcessDoneCallback>(this)); - - EXPECT_EQ(StatelessRejector::FAILED, rejector_->state()); - EXPECT_EQ(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, rejector_->error()); -} - -TEST_P(StatelessRejectorTest, ValidChloWithoutSrejSupport) { - // clang-format off - const CryptoHandshakeMessage client_hello = crypto_test_utils::CreateCHLO( - {{"PDMD", "X509"}, - {"AEAD", "AESG"}, - {"KEXS", "C255"}, - {"PUBS", pubs_hex_}, - {"NONC", nonc_hex_}, - {"VER\0", ver_hex_}}, - kClientHelloMinimumSize); - // clang-format on - - rejector_->OnChlo(GetParam().version, kConnectionId, - kServerDesignateConnectionId, client_hello); - EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_->state()); -} - -TEST_P(StatelessRejectorTest, RejectChlo) { - // clang-format off - const CryptoHandshakeMessage client_hello = crypto_test_utils::CreateCHLO( - {{"PDMD", "X509"}, - {"AEAD", "AESG"}, - {"KEXS", "C255"}, - {"COPT", "SREJ"}, - {"SCID", scid_hex_}, - {"PUBS", pubs_hex_}, - {"NONC", nonc_hex_}, - {"#004b5453", stk_hex_}, - {"VER\0", ver_hex_}}, - kClientHelloMinimumSize); - // clang-format on - - rejector_->OnChlo(GetParam().version, kConnectionId, - kServerDesignateConnectionId, client_hello); - if (GetParam().flags != ENABLED) { - EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_->state()); - return; - } - - // The StatelessRejector is undecided - proceed with async processing - ASSERT_EQ(StatelessRejector::UNKNOWN, rejector_->state()); - StatelessRejector::Process(std::move(rejector_), - QuicMakeUnique<ProcessDoneCallback>(this)); - - ASSERT_EQ(StatelessRejector::REJECTED, rejector_->state()); - const CryptoHandshakeMessage& reply = rejector_->reply(); - EXPECT_EQ(kSREJ, reply.tag()); - QuicTagVector reject_reasons; - EXPECT_EQ(QUIC_NO_ERROR, reply.GetTaglist(kRREJ, &reject_reasons)); - EXPECT_EQ(1u, reject_reasons.size()); - EXPECT_EQ(INVALID_EXPECTED_LEAF_CERTIFICATE, - static_cast<HandshakeFailureReason>(reject_reasons[0])); -} - -TEST_P(StatelessRejectorTest, AcceptChlo) { - const uint64_t xlct = crypto_test_utils::LeafCertHashForTesting(); - const QuicString xlct_hex = - "#" + QuicTextUtils::HexEncode(reinterpret_cast<const char*>(&xlct), - sizeof(xlct)); - // clang-format off - const CryptoHandshakeMessage client_hello = crypto_test_utils::CreateCHLO( - {{"PDMD", "X509"}, - {"AEAD", "AESG"}, - {"KEXS", "C255"}, - {"COPT", "SREJ"}, - {"SCID", scid_hex_}, - {"PUBS", pubs_hex_}, - {"NONC", nonc_hex_}, - {"#004b5453", stk_hex_}, - {"VER\0", ver_hex_}, - {"XLCT", xlct_hex}}, - kClientHelloMinimumSize); - // clang-format on - - rejector_->OnChlo(GetParam().version, kConnectionId, - kServerDesignateConnectionId, client_hello); - if (GetParam().flags != ENABLED) { - EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_->state()); - return; - } - - // The StatelessRejector is undecided - proceed with async processing - ASSERT_EQ(StatelessRejector::UNKNOWN, rejector_->state()); - StatelessRejector::Process(std::move(rejector_), - QuicMakeUnique<ProcessDoneCallback>(this)); - - EXPECT_EQ(StatelessRejector::ACCEPTED, rejector_->state()); -} - -} // namespace -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/synchronous_host_resolver.cc b/chromium/net/tools/quic/synchronous_host_resolver.cc index e9423a25ea9..bcb2b7617b3 100644 --- a/chromium/net/tools/quic/synchronous_host_resolver.cc +++ b/chromium/net/tools/quic/synchronous_host_resolver.cc @@ -91,7 +91,7 @@ int ResolverThread::Resolve(const std::string& host, AddressList* addresses) { void ResolverThread::OnResolutionComplete(int rv) { rv_ = rv; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); + FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated()); } } // namespace diff --git a/chromium/net/tools/quic/test_tools/bad_packet_writer.cc b/chromium/net/tools/quic/test_tools/bad_packet_writer.cc deleted file mode 100644 index 91d5fe50bca..00000000000 --- a/chromium/net/tools/quic/test_tools/bad_packet_writer.cc +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/test_tools/bad_packet_writer.h" - -namespace net { -namespace test { - -BadPacketWriter::BadPacketWriter(size_t packet_causing_write_error, - int error_code) - : packet_causing_write_error_(packet_causing_write_error), - error_code_(error_code) {} - -BadPacketWriter::~BadPacketWriter() {} - -WriteResult BadPacketWriter::WritePacket(const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address, - PerPacketOptions* options) { - if (error_code_ == 0 || packet_causing_write_error_ > 0) { - if (packet_causing_write_error_ > 0) { - --packet_causing_write_error_; - } - return QuicPacketWriterWrapper::WritePacket(buffer, buf_len, self_address, - peer_address, options); - } - // It's time to cause write error. - int error_code = error_code_; - error_code_ = 0; - return WriteResult(WRITE_STATUS_ERROR, error_code); -} - -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/test_tools/bad_packet_writer.h b/chromium/net/tools/quic/test_tools/bad_packet_writer.h deleted file mode 100644 index e8d6d4ead06..00000000000 --- a/chromium/net/tools/quic/test_tools/bad_packet_writer.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_TEST_TOOLS_BAD_PACKET_WRITER_H_ -#define NET_TOOLS_QUIC_TEST_TOOLS_BAD_PACKET_WRITER_H_ - -#include "net/tools/quic/quic_packet_writer_wrapper.h" - -namespace net { - -namespace test { -// This packet writer allows causing packet write error with specified error -// code when writing a particular packet. -class BadPacketWriter : public QuicPacketWriterWrapper { - public: - BadPacketWriter(size_t packet_causing_write_error, int error_code); - - ~BadPacketWriter() override; - - WriteResult WritePacket(const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address, - PerPacketOptions* options) override; - - private: - size_t packet_causing_write_error_; - int error_code_; -}; - -} // namespace test - -} // namespace net - -#endif // NET_TOOLS_QUIC_TEST_TOOLS_BAD_PACKET_WRITER_H_ diff --git a/chromium/net/tools/quic/test_tools/limited_mtu_test_writer.cc b/chromium/net/tools/quic/test_tools/limited_mtu_test_writer.cc deleted file mode 100644 index f37ace74feb..00000000000 --- a/chromium/net/tools/quic/test_tools/limited_mtu_test_writer.cc +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2015 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/tools/quic/test_tools/limited_mtu_test_writer.h" - -namespace net { -namespace test { - -LimitedMtuTestWriter::LimitedMtuTestWriter(QuicByteCount mtu) : mtu_(mtu) {} - -LimitedMtuTestWriter::~LimitedMtuTestWriter() = default; - -WriteResult LimitedMtuTestWriter::WritePacket( - const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address, - PerPacketOptions* options) { - if (buf_len > mtu_) { - // Drop the packet. - return WriteResult(WRITE_STATUS_OK, buf_len); - } - - return QuicPacketWriterWrapper::WritePacket(buffer, buf_len, self_address, - peer_address, options); -} - -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/test_tools/limited_mtu_test_writer.h b/chromium/net/tools/quic/test_tools/limited_mtu_test_writer.h deleted file mode 100644 index 3d2e2fd8f40..00000000000 --- a/chromium/net/tools/quic/test_tools/limited_mtu_test_writer.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2015 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_TOOLS_QUIC_TEST_TOOLS_LIMITED_MTU_TEST_WRITER_H_ -#define NET_TOOLS_QUIC_TEST_TOOLS_LIMITED_MTU_TEST_WRITER_H_ - -#include "base/macros.h" -#include "net/quic/core/quic_packets.h" -#include "net/tools/quic/quic_packet_writer_wrapper.h" - -namespace net { -namespace test { - -// Simulates a connection over a link with fixed MTU. Drops packets which -// exceed the MTU and passes the rest of them as-is. -class LimitedMtuTestWriter : public QuicPacketWriterWrapper { - public: - explicit LimitedMtuTestWriter(QuicByteCount mtu); - ~LimitedMtuTestWriter() override; - - // Inherited from QuicPacketWriterWrapper. - WriteResult WritePacket(const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address, - PerPacketOptions* options) override; - - private: - QuicByteCount mtu_; - - DISALLOW_COPY_AND_ASSIGN(LimitedMtuTestWriter); -}; - -} // namespace test -} // namespace net - -#endif // NET_TOOLS_QUIC_TEST_TOOLS_LIMITED_MTU_TEST_WRITER_H_ diff --git a/chromium/net/tools/quic/test_tools/mock_epoll_server.cc b/chromium/net/tools/quic/test_tools/mock_epoll_server.cc deleted file mode 100644 index ffca8d98d9a..00000000000 --- a/chromium/net/tools/quic/test_tools/mock_epoll_server.cc +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/test_tools/mock_epoll_server.h" - -namespace net { -namespace test { - -FakeTimeEpollServer::FakeTimeEpollServer() : now_in_usec_(0) {} - -FakeTimeEpollServer::~FakeTimeEpollServer() = default; - -int64_t FakeTimeEpollServer::NowInUsec() const { - return now_in_usec_; -} - -MockEpollServer::MockEpollServer() : until_in_usec_(-1) {} - -MockEpollServer::~MockEpollServer() = default; - -int MockEpollServer::epoll_wait_impl(int epfd, - struct epoll_event* events, - int max_events, - int timeout_in_ms) { - int num_events = 0; - while (!event_queue_.empty() && num_events < max_events && - event_queue_.begin()->first <= NowInUsec() && - ((until_in_usec_ == -1) || - (event_queue_.begin()->first < until_in_usec_))) { - int64_t event_time_in_usec = event_queue_.begin()->first; - events[num_events] = event_queue_.begin()->second; - if (event_time_in_usec > NowInUsec()) { - set_now_in_usec(event_time_in_usec); - } - event_queue_.erase(event_queue_.begin()); - ++num_events; - } - if (num_events == 0) { // then we'd have waited 'till the timeout. - if (until_in_usec_ < 0) { // then we don't care what the final time is. - if (timeout_in_ms > 0) { - AdvanceBy(timeout_in_ms * 1000); - } - } else { // except we assume that we don't wait for the timeout - // period if until_in_usec_ is a positive number. - set_now_in_usec(until_in_usec_); - // And reset until_in_usec_ to signal no waiting (as - // the AdvanceByExactly* stuff is meant to be one-shot, - // as are all similar EpollServer functions) - until_in_usec_ = -1; - } - } - if (until_in_usec_ >= 0) { - CHECK(until_in_usec_ >= NowInUsec()); - } - return num_events; -} - -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/test_tools/mock_epoll_server.h b/chromium/net/tools/quic/test_tools/mock_epoll_server.h deleted file mode 100644 index 9eac59403bc..00000000000 --- a/chromium/net/tools/quic/test_tools/mock_epoll_server.h +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_TEST_TOOLS_MOCK_EPOLL_SERVER_H_ -#define NET_TOOLS_QUIC_TEST_TOOLS_MOCK_EPOLL_SERVER_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <unordered_map> -#include <unordered_set> - -#include "base/logging.h" -#include "base/macros.h" -#include "net/tools/epoll_server/epoll_server.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace net { -namespace test { - -// Unlike the full MockEpollServer, this only lies about the time but lets -// fd events operate normally. Usefully when interacting with real backends -// but wanting to skip forward in time to trigger timeouts. -class FakeTimeEpollServer : public EpollServer { - public: - FakeTimeEpollServer(); - ~FakeTimeEpollServer() override; - - // Replaces the EpollServer NowInUsec. - int64_t NowInUsec() const override; - - void set_now_in_usec(int64_t nius) { now_in_usec_ = nius; } - - // Advances the virtual 'now' by advancement_usec. - void AdvanceBy(int64_t advancement_usec) { - set_now_in_usec(NowInUsec() + advancement_usec); - } - - // Advances the virtual 'now' by advancement_usec, and - // calls WaitForEventAndExecteCallbacks. - // Note that the WaitForEventsAndExecuteCallbacks invocation - // may cause NowInUs to advance beyond what was specified here. - // If that is not desired, use the AdvanceByExactly calls. - void AdvanceByAndWaitForEventsAndExecuteCallbacks(int64_t advancement_usec) { - AdvanceBy(advancement_usec); - WaitForEventsAndExecuteCallbacks(); - } - - private: - int64_t now_in_usec_; - - DISALLOW_COPY_AND_ASSIGN(FakeTimeEpollServer); -}; - -class MockEpollServer : public FakeTimeEpollServer { - public: // type definitions - using EventQueue = std::unordered_multimap<int64_t, struct epoll_event>; - - MockEpollServer(); - ~MockEpollServer() override; - - // time_in_usec is the time at which the event specified - // by 'ee' will be delivered. Note that it -is- possible - // to add an event for a time which has already been passed.. - // .. upon the next time that the callbacks are invoked, - // all events which are in the 'past' will be delivered. - void AddEvent(int64_t time_in_usec, const struct epoll_event& ee) { - event_queue_.insert(std::make_pair(time_in_usec, ee)); - } - - // Advances the virtual 'now' by advancement_usec, - // and ensure that the next invocation of - // WaitForEventsAndExecuteCallbacks goes no farther than - // advancement_usec from the current time. - void AdvanceByExactly(int64_t advancement_usec) { - until_in_usec_ = NowInUsec() + advancement_usec; - set_now_in_usec(NowInUsec() + advancement_usec); - } - - // As above, except calls WaitForEventsAndExecuteCallbacks. - void AdvanceByExactlyAndCallCallbacks(int64_t advancement_usec) { - AdvanceByExactly(advancement_usec); - WaitForEventsAndExecuteCallbacks(); - } - - std::unordered_set<AlarmCB*>::size_type NumberOfAlarms() const { - return all_alarms_.size(); - } - - protected: // functions - // These functions do nothing here, as we're not actually - // using the epoll_* syscalls. - void DelFD(int fd) const override {} - void AddFD(int fd, int event_mask) const override {} - void ModFD(int fd, int event_mask) const override {} - - // Replaces the epoll_server's epoll_wait_impl. - int epoll_wait_impl(int epfd, - struct epoll_event* events, - int max_events, - int timeout_in_ms) override; - void SetNonblocking(int fd) override {} - - private: // members - EventQueue event_queue_; - int64_t until_in_usec_; - - DISALLOW_COPY_AND_ASSIGN(MockEpollServer); -}; - -} // namespace test -} // namespace net - -#endif // NET_TOOLS_QUIC_TEST_TOOLS_MOCK_EPOLL_SERVER_H_ diff --git a/chromium/net/tools/quic/test_tools/mock_quic_session_visitor.cc b/chromium/net/tools/quic/test_tools/mock_quic_session_visitor.cc deleted file mode 100644 index 8bca2752da5..00000000000 --- a/chromium/net/tools/quic/test_tools/mock_quic_session_visitor.cc +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/test_tools/mock_quic_session_visitor.h" - -namespace net { -namespace test { - -MockQuicSessionVisitor::MockQuicSessionVisitor() = default; - -MockQuicSessionVisitor::~MockQuicSessionVisitor() = default; - -MockQuicCryptoServerStreamHelper::MockQuicCryptoServerStreamHelper() = default; - -MockQuicCryptoServerStreamHelper::~MockQuicCryptoServerStreamHelper() = default; - -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/test_tools/mock_quic_session_visitor.h b/chromium/net/tools/quic/test_tools/mock_quic_session_visitor.h deleted file mode 100644 index 793be8d42dd..00000000000 --- a/chromium/net/tools/quic/test_tools/mock_quic_session_visitor.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_TEST_TOOLS_MOCK_QUIC_SESSION_VISITOR_H_ -#define NET_TOOLS_QUIC_TEST_TOOLS_MOCK_QUIC_SESSION_VISITOR_H_ - -#include "base/macros.h" -#include "net/quic/core/quic_crypto_server_stream.h" -#include "net/tools/quic/quic_time_wait_list_manager.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace net { -namespace test { - -class MockQuicSessionVisitor : public QuicTimeWaitListManager::Visitor { - public: - MockQuicSessionVisitor(); - ~MockQuicSessionVisitor() override; - MOCK_METHOD3(OnConnectionClosed, - void(QuicConnectionId connection_id, - QuicErrorCode error, - const std::string& error_details)); - MOCK_METHOD1(OnWriteBlocked, - void(QuicBlockedWriterInterface* blocked_writer)); - MOCK_METHOD1(OnRstStreamReceived, void(const QuicRstStreamFrame& frame)); - MOCK_METHOD1(OnConnectionAddedToTimeWaitList, - void(QuicConnectionId connection_id)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockQuicSessionVisitor); -}; - -class MockQuicCryptoServerStreamHelper : public QuicCryptoServerStream::Helper { - public: - MockQuicCryptoServerStreamHelper(); - ~MockQuicCryptoServerStreamHelper() override; - MOCK_CONST_METHOD1(GenerateConnectionIdForReject, - QuicConnectionId(QuicConnectionId connection_id)); - MOCK_CONST_METHOD3(CanAcceptClientHello, - bool(const CryptoHandshakeMessage& message, - const QuicSocketAddress& self_address, - std::string* error_details)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStreamHelper); -}; - -} // namespace test -} // namespace net - -#endif // NET_TOOLS_QUIC_TEST_TOOLS_MOCK_QUIC_SESSION_VISITOR_H_ diff --git a/chromium/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.cc b/chromium/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.cc deleted file mode 100644 index 451d7ac9450..00000000000 --- a/chromium/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.cc +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h" - -using testing::_; -using testing::Invoke; - -namespace net { -namespace test { - -MockTimeWaitListManager::MockTimeWaitListManager( - QuicPacketWriter* writer, - Visitor* visitor, - QuicConnectionHelperInterface* helper, - QuicAlarmFactory* alarm_factory) - : QuicTimeWaitListManager(writer, visitor, helper, alarm_factory) { - // Though AddConnectionIdToTimeWait is mocked, we want to retain its - // functionality. - EXPECT_CALL(*this, AddConnectionIdToTimeWait(_, _, _, _, _)) - .Times(testing::AnyNumber()); - ON_CALL(*this, AddConnectionIdToTimeWait(_, _, _, _, _)) - .WillByDefault( - Invoke(this, &MockTimeWaitListManager:: - QuicTimeWaitListManager_AddConnectionIdToTimeWait)); -} - -MockTimeWaitListManager::~MockTimeWaitListManager() = default; - -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h b/chromium/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h deleted file mode 100644 index e893b0f9736..00000000000 --- a/chromium/net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_TEST_TOOLS_MOCK_QUIC_TIME_WAIT_LIST_MANAGER_H_ -#define NET_TOOLS_QUIC_TEST_TOOLS_MOCK_QUIC_TIME_WAIT_LIST_MANAGER_H_ - -#include "net/tools/quic/quic_time_wait_list_manager.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace net { -namespace test { - -class MockTimeWaitListManager : public QuicTimeWaitListManager { - public: - MockTimeWaitListManager(QuicPacketWriter* writer, - Visitor* visitor, - QuicConnectionHelperInterface* helper, - QuicAlarmFactory* alarm_factory); - ~MockTimeWaitListManager() override; - - MOCK_METHOD5(AddConnectionIdToTimeWait, - void(QuicConnectionId connection_id, - ParsedQuicVersion version, - bool ietf_quic, - bool connection_rejected_statelessly, - std::vector<std::unique_ptr<QuicEncryptedPacket>>* - termination_packets)); - - void QuicTimeWaitListManager_AddConnectionIdToTimeWait( - QuicConnectionId connection_id, - ParsedQuicVersion version, - bool ietf_quic, - bool connection_rejected_statelessly, - std::vector<std::unique_ptr<QuicEncryptedPacket>>* termination_packets) { - QuicTimeWaitListManager::AddConnectionIdToTimeWait( - connection_id, version, ietf_quic, connection_rejected_statelessly, - termination_packets); - } - - MOCK_METHOD3(ProcessPacket, - void(const QuicSocketAddress& server_address, - const QuicSocketAddress& client_address, - QuicConnectionId connection_id)); - - MOCK_METHOD5(SendVersionNegotiationPacket, - void(QuicConnectionId connection_id, - bool ietf_quic, - const ParsedQuicVersionVector& supported_versions, - const QuicSocketAddress& server_address, - const QuicSocketAddress& client_address)); -}; - -} // namespace test -} // namespace net - -#endif // NET_TOOLS_QUIC_TEST_TOOLS_MOCK_QUIC_TIME_WAIT_LIST_MANAGER_H_ diff --git a/chromium/net/tools/quic/test_tools/packet_dropping_test_writer.cc b/chromium/net/tools/quic/test_tools/packet_dropping_test_writer.cc deleted file mode 100644 index a5c2a1ded7b..00000000000 --- a/chromium/net/tools/quic/test_tools/packet_dropping_test_writer.cc +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/test_tools/packet_dropping_test_writer.h" - -#include <limits> - -#include "base/rand_util.h" -#include "net/quic/platform/api/quic_logging.h" -#include "net/tools/quic/platform/impl/quic_socket_utils.h" -#include "net/tools/quic/quic_epoll_connection_helper.h" - -namespace net { -namespace test { - -// An alarm that is scheduled if a blocked socket is simulated to indicate -// it's writable again. -class WriteUnblockedAlarm : public QuicAlarm::Delegate { - public: - explicit WriteUnblockedAlarm(PacketDroppingTestWriter* writer) - : writer_(writer) {} - - void OnAlarm() override { - QUIC_DLOG(INFO) << "Unblocking socket."; - writer_->OnCanWrite(); - } - - private: - PacketDroppingTestWriter* writer_; -}; - -// An alarm that is scheduled every time a new packet is to be written at a -// later point. -class DelayAlarm : public QuicAlarm::Delegate { - public: - explicit DelayAlarm(PacketDroppingTestWriter* writer) : writer_(writer) {} - - void OnAlarm() override { - QuicTime new_deadline = writer_->ReleaseOldPackets(); - if (new_deadline.IsInitialized()) { - writer_->SetDelayAlarm(new_deadline); - } - } - - private: - PacketDroppingTestWriter* writer_; -}; - -PacketDroppingTestWriter::PacketDroppingTestWriter() - : clock_(nullptr), - cur_buffer_size_(0), - num_calls_to_write_(0), - config_mutex_(), - fake_packet_loss_percentage_(0), - fake_drop_first_n_packets_(0), - fake_blocked_socket_percentage_(0), - fake_packet_reorder_percentage_(0), - fake_packet_delay_(QuicTime::Delta::Zero()), - fake_bandwidth_(QuicBandwidth::Zero()), - buffer_size_(0) { - uint32_t seed = base::RandInt(0, std::numeric_limits<int32_t>::max()); - QUIC_LOG(INFO) << "Seeding packet loss with " << seed; - simple_random_.set_seed(seed); -} - -PacketDroppingTestWriter::~PacketDroppingTestWriter() = default; - -void PacketDroppingTestWriter::Initialize(QuicConnectionHelperInterface* helper, - QuicAlarmFactory* alarm_factory, - Delegate* on_can_write) { - clock_ = helper->GetClock(); - write_unblocked_alarm_.reset( - alarm_factory->CreateAlarm(new WriteUnblockedAlarm(this))); - delay_alarm_.reset(alarm_factory->CreateAlarm(new DelayAlarm(this))); - on_can_write_.reset(on_can_write); -} - -WriteResult PacketDroppingTestWriter::WritePacket( - const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address, - PerPacketOptions* options) { - ++num_calls_to_write_; - ReleaseOldPackets(); - - QuicReaderMutexLock lock(&config_mutex_); - if (fake_drop_first_n_packets_ > 0 && - num_calls_to_write_ <= - static_cast<uint64_t>(fake_drop_first_n_packets_)) { - QUIC_DVLOG(1) << "Dropping first " << fake_drop_first_n_packets_ - << " packets (packet number " << num_calls_to_write_ << ")"; - return WriteResult(WRITE_STATUS_OK, buf_len); - } - if (fake_packet_loss_percentage_ > 0 && - simple_random_.RandUint64() % 100 < - static_cast<uint64_t>(fake_packet_loss_percentage_)) { - QUIC_DVLOG(1) << "Dropping packet."; - return WriteResult(WRITE_STATUS_OK, buf_len); - } - if (fake_blocked_socket_percentage_ > 0 && - simple_random_.RandUint64() % 100 < - static_cast<uint64_t>(fake_blocked_socket_percentage_)) { - CHECK(on_can_write_ != nullptr); - QUIC_DVLOG(1) << "Blocking socket."; - if (!write_unblocked_alarm_->IsSet()) { - // Set the alarm to fire immediately. - write_unblocked_alarm_->Set(clock_->ApproximateNow()); - } - return WriteResult(WRITE_STATUS_BLOCKED, EAGAIN); - } - - if (!fake_packet_delay_.IsZero() || !fake_bandwidth_.IsZero()) { - if (buffer_size_ > 0 && buf_len + cur_buffer_size_ > buffer_size_) { - // Drop packets which do not fit into the buffer. - QUIC_DVLOG(1) << "Dropping packet because the buffer is full."; - return WriteResult(WRITE_STATUS_OK, buf_len); - } - - // Queue it to be sent. - QuicTime send_time = clock_->ApproximateNow() + fake_packet_delay_; - if (!fake_bandwidth_.IsZero()) { - // Calculate a time the bandwidth limit would impose. - QuicTime::Delta bandwidth_delay = QuicTime::Delta::FromMicroseconds( - (buf_len * kNumMicrosPerSecond) / fake_bandwidth_.ToBytesPerSecond()); - send_time = delayed_packets_.empty() - ? send_time + bandwidth_delay - : delayed_packets_.back().send_time + bandwidth_delay; - } - std::unique_ptr<PerPacketOptions> delayed_options; - if (options != nullptr) { - delayed_options.reset(options->Clone()); - } - delayed_packets_.push_back( - DelayedWrite(buffer, buf_len, self_address, peer_address, - std::move(delayed_options), send_time)); - cur_buffer_size_ += buf_len; - - // Set the alarm if it's not yet set. - if (!delay_alarm_->IsSet()) { - delay_alarm_->Set(send_time); - } - - return WriteResult(WRITE_STATUS_OK, buf_len); - } - - return QuicPacketWriterWrapper::WritePacket(buffer, buf_len, self_address, - peer_address, options); -} - -bool PacketDroppingTestWriter::IsWriteBlocked() const { - if (write_unblocked_alarm_ != nullptr && write_unblocked_alarm_->IsSet()) { - return true; - } - return QuicPacketWriterWrapper::IsWriteBlocked(); -} - -void PacketDroppingTestWriter::SetWritable() { - if (write_unblocked_alarm_ != nullptr && write_unblocked_alarm_->IsSet()) { - write_unblocked_alarm_->Cancel(); - } - QuicPacketWriterWrapper::SetWritable(); -} - -QuicTime PacketDroppingTestWriter::ReleaseNextPacket() { - if (delayed_packets_.empty()) { - return QuicTime::Zero(); - } - QuicReaderMutexLock lock(&config_mutex_); - DelayedPacketList::iterator iter = delayed_packets_.begin(); - // Determine if we should re-order. - if (delayed_packets_.size() > 1 && fake_packet_reorder_percentage_ > 0 && - simple_random_.RandUint64() % 100 < - static_cast<uint64_t>(fake_packet_reorder_percentage_)) { - QUIC_DLOG(INFO) << "Reordering packets."; - ++iter; - // Swap the send times when re-ordering packets. - delayed_packets_.begin()->send_time = iter->send_time; - } - - QUIC_DVLOG(1) << "Releasing packet. " << (delayed_packets_.size() - 1) - << " remaining."; - // Grab the next one off the queue and send it. - QuicPacketWriterWrapper::WritePacket( - iter->buffer.data(), iter->buffer.length(), iter->self_address, - iter->peer_address, iter->options.get()); - DCHECK_GE(cur_buffer_size_, iter->buffer.length()); - cur_buffer_size_ -= iter->buffer.length(); - delayed_packets_.erase(iter); - - // If there are others, find the time for the next to be sent. - if (delayed_packets_.empty()) { - return QuicTime::Zero(); - } - return delayed_packets_.begin()->send_time; -} - -QuicTime PacketDroppingTestWriter::ReleaseOldPackets() { - while (!delayed_packets_.empty()) { - QuicTime next_send_time = delayed_packets_.front().send_time; - if (next_send_time > clock_->Now()) { - return next_send_time; - } - ReleaseNextPacket(); - } - return QuicTime::Zero(); -} - -void PacketDroppingTestWriter::SetDelayAlarm(QuicTime new_deadline) { - delay_alarm_->Set(new_deadline); -} - -void PacketDroppingTestWriter::OnCanWrite() { - on_can_write_->OnCanWrite(); -} - -PacketDroppingTestWriter::DelayedWrite::DelayedWrite( - const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address, - std::unique_ptr<PerPacketOptions> options, - QuicTime send_time) - : buffer(buffer, buf_len), - self_address(self_address), - peer_address(peer_address), - options(std::move(options)), - send_time(send_time) {} - -// TODO(rtenneti): on windows RValue reference gives errors. -PacketDroppingTestWriter::DelayedWrite::DelayedWrite( - PacketDroppingTestWriter::DelayedWrite&& other) = default; - -// TODO(rtenneti): on windows RValue reference gives errors. -// IPAddress has no move assignment operator. -// -// PacketDroppingTestWriter::DelayedWrite& -// PacketDroppingTestWriter::DelayedWrite::operator=( -// PacketDroppingTestWriter::DelayedWrite&& other) = default; - -PacketDroppingTestWriter::DelayedWrite::~DelayedWrite() = default; - -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/test_tools/packet_dropping_test_writer.h b/chromium/net/tools/quic/test_tools/packet_dropping_test_writer.h deleted file mode 100644 index c4c28b6f1ba..00000000000 --- a/chromium/net/tools/quic/test_tools/packet_dropping_test_writer.h +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_ -#define NET_TOOLS_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <list> -#include <memory> -#include <string> - -#include "base/logging.h" -#include "base/macros.h" -#include "base/synchronization/lock.h" -#include "net/base/ip_address.h" -#include "net/quic/core/quic_alarm.h" -#include "net/quic/test_tools/quic_test_utils.h" -#include "net/tools/quic/platform/impl/quic_epoll_clock.h" -#include "net/tools/quic/quic_packet_writer_wrapper.h" -#include "net/tools/quic/test_tools/quic_test_client.h" - -namespace net { -namespace test { - -// Simulates a connection that drops packets a configured percentage of the time -// and has a blocked socket a configured percentage of the time. Also provides -// the options to delay packets and reorder packets if delay is enabled. -class PacketDroppingTestWriter : public QuicPacketWriterWrapper { - public: - class Delegate { - public: - virtual ~Delegate() {} - virtual void OnCanWrite() = 0; - }; - - PacketDroppingTestWriter(); - - ~PacketDroppingTestWriter() override; - - // Must be called before blocking, reordering or delaying (loss is OK). May be - // called after connecting if the helper is not available before. - // |on_can_write| will be triggered when fake-unblocking; ownership will be - // assumed. - void Initialize(QuicConnectionHelperInterface* helper, - QuicAlarmFactory* alarm_factory, - Delegate* on_can_write); - - // QuicPacketWriter methods: - WriteResult WritePacket(const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address, - PerPacketOptions* options) override; - - bool IsWriteBlocked() const override; - - void SetWritable() override; - - // Writes out any packet which should have been sent by now - // to the contained writer and returns the time - // for the next delayed packet to be written. - QuicTime ReleaseOldPackets(); - - // Sets |delay_alarm_| to fire at |new_deadline|. - void SetDelayAlarm(QuicTime new_deadline); - - void OnCanWrite(); - - // The percent of time a packet is simulated as being lost. - void set_fake_packet_loss_percentage(int32_t fake_packet_loss_percentage) { - QuicWriterMutexLock lock(&config_mutex_); - fake_packet_loss_percentage_ = fake_packet_loss_percentage; - } - - // Simulate dropping the first n packets unconditionally. - // Subsequent packets will be lost at fake_packet_loss_percentage_ if set. - void set_fake_drop_first_n_packets(int32_t fake_drop_first_n_packets) { - QuicWriterMutexLock lock(&config_mutex_); - fake_drop_first_n_packets_ = fake_drop_first_n_packets; - } - - // The percent of time WritePacket will block and set WriteResult's status - // to WRITE_STATUS_BLOCKED. - void set_fake_blocked_socket_percentage( - int32_t fake_blocked_socket_percentage) { - DCHECK(clock_); - QuicWriterMutexLock lock(&config_mutex_); - fake_blocked_socket_percentage_ = fake_blocked_socket_percentage; - } - - // The percent of time a packet is simulated as being reordered. - void set_fake_reorder_percentage(int32_t fake_packet_reorder_percentage) { - DCHECK(clock_); - QuicWriterMutexLock lock(&config_mutex_); - DCHECK(!fake_packet_delay_.IsZero()); - fake_packet_reorder_percentage_ = fake_packet_reorder_percentage; - } - - // The delay before writing this packet. - void set_fake_packet_delay(QuicTime::Delta fake_packet_delay) { - DCHECK(clock_); - QuicWriterMutexLock lock(&config_mutex_); - fake_packet_delay_ = fake_packet_delay; - } - - // The maximum bandwidth and buffer size of the connection. When these are - // set, packets will be delayed until a connection with that bandwidth would - // transmit it. Once the |buffer_size| is reached, all new packets are - // dropped. - void set_max_bandwidth_and_buffer_size(QuicBandwidth fake_bandwidth, - QuicByteCount buffer_size) { - DCHECK(clock_); - QuicWriterMutexLock lock(&config_mutex_); - fake_bandwidth_ = fake_bandwidth; - buffer_size_ = buffer_size; - } - - // Useful for reproducing very flaky issues. - void set_seed(uint64_t seed) { simple_random_.set_seed(seed); } - - private: - // Writes out the next packet to the contained writer and returns the time - // for the next delayed packet to be written. - QuicTime ReleaseNextPacket(); - - // A single packet which will be sent at the supplied send_time. - struct DelayedWrite { - public: - DelayedWrite(const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address, - std::unique_ptr<PerPacketOptions> options, - QuicTime send_time); - // TODO(rtenneti): on windows RValue reference gives errors. - DelayedWrite(DelayedWrite&& other); - // TODO(rtenneti): on windows RValue reference gives errors. - // DelayedWrite& operator=(DelayedWrite&& other); - ~DelayedWrite(); - - std::string buffer; - const QuicIpAddress self_address; - const QuicSocketAddress peer_address; - std::unique_ptr<PerPacketOptions> options; - QuicTime send_time; - - private: - DISALLOW_COPY_AND_ASSIGN(DelayedWrite); - }; - - typedef std::list<DelayedWrite> DelayedPacketList; - - const QuicClock* clock_; - std::unique_ptr<QuicAlarm> write_unblocked_alarm_; - std::unique_ptr<QuicAlarm> delay_alarm_; - std::unique_ptr<Delegate> on_can_write_; - net::test::SimpleRandom simple_random_; - // Stored packets delayed by fake packet delay or bandwidth restrictions. - DelayedPacketList delayed_packets_; - QuicByteCount cur_buffer_size_; - uint64_t num_calls_to_write_; - - QuicMutex config_mutex_; - int32_t fake_packet_loss_percentage_ GUARDED_BY(config_mutex_); - int32_t fake_drop_first_n_packets_ GUARDED_BY(config_mutex_); - int32_t fake_blocked_socket_percentage_ GUARDED_BY(config_mutex_); - int32_t fake_packet_reorder_percentage_ GUARDED_BY(config_mutex_); - QuicTime::Delta fake_packet_delay_ GUARDED_BY(config_mutex_); - QuicBandwidth fake_bandwidth_ GUARDED_BY(config_mutex_); - QuicByteCount buffer_size_ GUARDED_BY(config_mutex_); - - DISALLOW_COPY_AND_ASSIGN(PacketDroppingTestWriter); -}; - -} // namespace test -} // namespace net - -#endif // NET_TOOLS_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_ diff --git a/chromium/net/tools/quic/test_tools/packet_reordering_writer.cc b/chromium/net/tools/quic/test_tools/packet_reordering_writer.cc deleted file mode 100644 index 992b9eb07f5..00000000000 --- a/chromium/net/tools/quic/test_tools/packet_reordering_writer.cc +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/test_tools/packet_reordering_writer.h" - -namespace net { -namespace test { - -PacketReorderingWriter::PacketReorderingWriter() = default; - -PacketReorderingWriter::~PacketReorderingWriter() = default; - -WriteResult PacketReorderingWriter::WritePacket( - const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address, - PerPacketOptions* options) { - if (!delay_next_) { - VLOG(2) << "Writing a non-delayed packet"; - WriteResult wr = QuicPacketWriterWrapper::WritePacket( - buffer, buf_len, self_address, peer_address, options); - --num_packets_to_wait_; - if (num_packets_to_wait_ == 0) { - VLOG(2) << "Writing a delayed packet"; - // It's time to write the delayed packet. - QuicPacketWriterWrapper::WritePacket( - delayed_data_.data(), delayed_data_.length(), delayed_self_address_, - delayed_peer_address_, delayed_options_.get()); - } - return wr; - } - // Still have packet to wait. - DCHECK_LT(0u, num_packets_to_wait_) << "Only allow one packet to be delayed"; - delayed_data_ = std::string(buffer, buf_len); - delayed_self_address_ = self_address; - delayed_peer_address_ = peer_address; - if (options != nullptr) { - delayed_options_.reset(options->Clone()); - } - delay_next_ = false; - return WriteResult(WRITE_STATUS_OK, buf_len); -} - -void PacketReorderingWriter::SetDelay(size_t num_packets_to_wait) { - DCHECK_GT(num_packets_to_wait, 0u); - num_packets_to_wait_ = num_packets_to_wait; - delay_next_ = true; -} - -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/test_tools/packet_reordering_writer.h b/chromium/net/tools/quic/test_tools/packet_reordering_writer.h deleted file mode 100644 index 2ac8c35be7d..00000000000 --- a/chromium/net/tools/quic/test_tools/packet_reordering_writer.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_TEST_TOOLS_PACKET_REORDERING_WRITER_H_ -#define NET_TOOLS_QUIC_TEST_TOOLS_PACKET_REORDERING_WRITER_H_ - -#include "net/tools/quic/quic_packet_writer_wrapper.h" - -namespace net { - -namespace test { - -// This packet writer allows delaying writing the next packet after -// SetDelay(num_packets_to_wait) -// is called and buffer this packet and write it after it writes next -// |num_packets_to_wait| packets. It doesn't support delaying a packet while -// there is already a packet delayed. -class PacketReorderingWriter : public QuicPacketWriterWrapper { - public: - PacketReorderingWriter(); - - ~PacketReorderingWriter() override; - - WriteResult WritePacket(const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address, - PerPacketOptions* options) override; - - void SetDelay(size_t num_packets_to_wait); - - private: - bool delay_next_ = false; - size_t num_packets_to_wait_ = 0; - std::string delayed_data_; - QuicIpAddress delayed_self_address_; - QuicSocketAddress delayed_peer_address_; - std::unique_ptr<PerPacketOptions> delayed_options_; -}; - -} // namespace test -} // namespace net - -#endif // NET_TOOLS_QUIC_TEST_TOOLS_PACKET_REORDERING_WRITER_H_ diff --git a/chromium/net/tools/quic/test_tools/quic_client_peer.cc b/chromium/net/tools/quic/test_tools/quic_client_peer.cc deleted file mode 100644 index 14627bf24ac..00000000000 --- a/chromium/net/tools/quic/test_tools/quic_client_peer.cc +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/test_tools/quic_client_peer.h" - -#include "net/tools/quic/quic_client.h" - -namespace net { -namespace test { - -// static -bool QuicClientPeer::CreateUDPSocketAndBind(QuicClient* client) { - return client->network_helper()->CreateUDPSocketAndBind( - client->server_address(), client->bind_to_address(), - client->local_port()); -} - -// static -void QuicClientPeer::CleanUpUDPSocket(QuicClient* client, int fd) { - client->epoll_network_helper()->CleanUpUDPSocket(fd); -} - -// static -void QuicClientPeer::SetClientPort(QuicClient* client, int port) { - client->epoll_network_helper()->SetClientPort(port); -} - -// static -void QuicClientPeer::SetWriter(QuicClient* client, QuicPacketWriter* writer) { - client->set_writer(writer); -} - -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/test_tools/quic_client_peer.h b/chromium/net/tools/quic/test_tools/quic_client_peer.h deleted file mode 100644 index 47c918eeeab..00000000000 --- a/chromium/net/tools/quic/test_tools/quic_client_peer.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_TEST_TOOLS_QUIC_CLIENT_PEER_H_ -#define NET_TOOLS_QUIC_TEST_TOOLS_QUIC_CLIENT_PEER_H_ - -#include "base/macros.h" - -namespace net { - -class QuicClient; -class QuicPacketWriter; - -namespace test { - -class QuicClientPeer { - public: - static bool CreateUDPSocketAndBind(QuicClient* client); - static void CleanUpUDPSocket(QuicClient* client, int fd); - static void SetClientPort(QuicClient* client, int port); - static void SetWriter(QuicClient* client, QuicPacketWriter* writer); - - private: - DISALLOW_COPY_AND_ASSIGN(QuicClientPeer); -}; - -} // namespace test -} // namespace net - -#endif // NET_TOOLS_QUIC_TEST_TOOLS_QUIC_CLIENT_PEER_H_ diff --git a/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.cc b/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.cc deleted file mode 100644 index 7f693c6d525..00000000000 --- a/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.cc +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/test_tools/quic_dispatcher_peer.h" - -#include "net/tools/quic/quic_dispatcher.h" -#include "net/tools/quic/quic_packet_writer_wrapper.h" - -namespace net { -namespace test { - -// static -void QuicDispatcherPeer::SetTimeWaitListManager( - QuicDispatcher* dispatcher, - QuicTimeWaitListManager* time_wait_list_manager) { - dispatcher->time_wait_list_manager_.reset(time_wait_list_manager); -} - -// static -void QuicDispatcherPeer::UseWriter(QuicDispatcher* dispatcher, - QuicPacketWriterWrapper* writer) { - writer->set_writer(dispatcher->writer_.release()); - dispatcher->writer_.reset(writer); -} - -// static -QuicPacketWriter* QuicDispatcherPeer::GetWriter(QuicDispatcher* dispatcher) { - return dispatcher->writer_.get(); -} - -// static -QuicCompressedCertsCache* QuicDispatcherPeer::GetCache( - QuicDispatcher* dispatcher) { - return dispatcher->compressed_certs_cache(); -} - -// static -QuicConnectionHelperInterface* QuicDispatcherPeer::GetHelper( - QuicDispatcher* dispatcher) { - return dispatcher->helper_.get(); -} - -// static -QuicAlarmFactory* QuicDispatcherPeer::GetAlarmFactory( - QuicDispatcher* dispatcher) { - return dispatcher->alarm_factory_.get(); -} - -// static -QuicDispatcher::WriteBlockedList* QuicDispatcherPeer::GetWriteBlockedList( - QuicDispatcher* dispatcher) { - return &dispatcher->write_blocked_list_; -} - -// static -QuicErrorCode QuicDispatcherPeer::GetAndClearLastError( - QuicDispatcher* dispatcher) { - QuicErrorCode ret = dispatcher->last_error_; - dispatcher->last_error_ = QUIC_NO_ERROR; - return ret; -} - -// static -QuicBufferedPacketStore* QuicDispatcherPeer::GetBufferedPackets( - QuicDispatcher* dispatcher) { - return &(dispatcher->buffered_packets_); -} - -// static -const QuicDispatcher::SessionMap& QuicDispatcherPeer::session_map( - QuicDispatcher* dispatcher) { - return dispatcher->session_map(); -} - -// static -void QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop( - QuicDispatcher* dispatcher, - size_t num_session_allowed) { - return dispatcher->set_new_sessions_allowed_per_event_loop( - num_session_allowed); -} - -// static -void QuicDispatcherPeer::SendPublicReset( - QuicDispatcher* dispatcher, - const QuicSocketAddress& server_address, - const QuicSocketAddress& client_address, - QuicConnectionId connection_id) { - dispatcher->time_wait_list_manager()->SendPublicReset( - server_address, client_address, connection_id); -} - -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.h b/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.h deleted file mode 100644 index 9353a60aaa5..00000000000 --- a/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_TEST_TOOLS_QUIC_DISPATCHER_PEER_H_ -#define NET_TOOLS_QUIC_TEST_TOOLS_QUIC_DISPATCHER_PEER_H_ - -#include "base/macros.h" -#include "net/tools/quic/quic_dispatcher.h" - -namespace net { - -class QuicPacketWriterWrapper; - -namespace test { - -class QuicDispatcherPeer { - public: - static void SetTimeWaitListManager( - QuicDispatcher* dispatcher, - QuicTimeWaitListManager* time_wait_list_manager); - - // Injects |writer| into |dispatcher| as the shared writer. - static void UseWriter(QuicDispatcher* dispatcher, - QuicPacketWriterWrapper* writer); - - static QuicPacketWriter* GetWriter(QuicDispatcher* dispatcher); - - static QuicCompressedCertsCache* GetCache(QuicDispatcher* dispatcher); - - static QuicConnectionHelperInterface* GetHelper(QuicDispatcher* dispatcher); - - static QuicAlarmFactory* GetAlarmFactory(QuicDispatcher* dispatcher); - - static QuicDispatcher::WriteBlockedList* GetWriteBlockedList( - QuicDispatcher* dispatcher); - - // Get the dispatcher's record of the last error reported to its framer - // visitor's OnError() method. Then set that record to QUIC_NO_ERROR. - static QuicErrorCode GetAndClearLastError(QuicDispatcher* dispatcher); - - static QuicBufferedPacketStore* GetBufferedPackets( - QuicDispatcher* dispatcher); - - static const QuicDispatcher::SessionMap& session_map( - QuicDispatcher* dispatcher); - - static void set_new_sessions_allowed_per_event_loop( - QuicDispatcher* dispatcher, - size_t num_session_allowed); - - static void SendPublicReset(QuicDispatcher* dispatcher, - const QuicSocketAddress& server_address, - const QuicSocketAddress& client_address, - QuicConnectionId connection_id); - - private: - DISALLOW_COPY_AND_ASSIGN(QuicDispatcherPeer); -}; - -} // namespace test -} // namespace net - -#endif // NET_TOOLS_QUIC_TEST_TOOLS_QUIC_DISPATCHER_PEER_H_ diff --git a/chromium/net/tools/quic/test_tools/quic_server_peer.cc b/chromium/net/tools/quic/test_tools/quic_server_peer.cc deleted file mode 100644 index 892c6922785..00000000000 --- a/chromium/net/tools/quic/test_tools/quic_server_peer.cc +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/test_tools/quic_server_peer.h" - -#include "net/tools/quic/quic_dispatcher.h" -#include "net/tools/quic/quic_packet_reader.h" -#include "net/tools/quic/quic_server.h" - -namespace net { -namespace test { - -// static -bool QuicServerPeer::SetSmallSocket(QuicServer* server) { - int size = 1024 * 10; - return setsockopt(server->fd_, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) != - -1; -} - -// static -QuicDispatcher* QuicServerPeer::GetDispatcher(QuicServer* server) { - return server->dispatcher_.get(); -} - -// static -void QuicServerPeer::SetReader(QuicServer* server, QuicPacketReader* reader) { - server->packet_reader_.reset(reader); -} - -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/test_tools/quic_server_peer.h b/chromium/net/tools/quic/test_tools/quic_server_peer.h deleted file mode 100644 index e3d5d1e4a3b..00000000000 --- a/chromium/net/tools/quic/test_tools/quic_server_peer.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_TEST_TOOLS_QUIC_SERVER_PEER_H_ -#define NET_TOOLS_QUIC_TEST_TOOLS_QUIC_SERVER_PEER_H_ - -#include "base/macros.h" - -namespace net { - -class QuicDispatcher; -class QuicServer; -class QuicPacketReader; - -namespace test { - -class QuicServerPeer { - public: - static bool SetSmallSocket(QuicServer* server); - static QuicDispatcher* GetDispatcher(QuicServer* server); - static void SetReader(QuicServer* server, QuicPacketReader* reader); - - private: - DISALLOW_COPY_AND_ASSIGN(QuicServerPeer); -}; - -} // namespace test -} // namespace net - -#endif // NET_TOOLS_QUIC_TEST_TOOLS_QUIC_SERVER_PEER_H_ diff --git a/chromium/net/tools/quic/test_tools/quic_test_client.cc b/chromium/net/tools/quic/test_tools/quic_test_client.cc deleted file mode 100644 index e44ccc39820..00000000000 --- a/chromium/net/tools/quic/test_tools/quic_test_client.cc +++ /dev/null @@ -1,876 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/test_tools/quic_test_client.h" - -#include <memory> -#include <utility> -#include <vector> - -#include "net/quic/core/crypto/proof_verifier.h" -#include "net/quic/core/quic_server_id.h" -#include "net/quic/core/quic_utils.h" -#include "net/quic/core/spdy_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" -#include "net/quic/platform/api/quic_stack_trace.h" -#include "net/quic/platform/api/quic_text_utils.h" -#include "net/quic/platform/api/quic_url.h" -#include "net/quic/test_tools/crypto_test_utils.h" -#include "net/quic/test_tools/quic_connection_peer.h" -#include "net/quic/test_tools/quic_spdy_session_peer.h" -#include "net/quic/test_tools/quic_stream_peer.h" -#include "net/quic/test_tools/quic_test_utils.h" -#include "net/tools/quic/quic_epoll_connection_helper.h" -#include "net/tools/quic/quic_packet_writer_wrapper.h" -#include "net/tools/quic/quic_spdy_client_stream.h" -#include "net/tools/quic/test_tools/quic_client_peer.h" - -using std::string; - -namespace net { -namespace test { -namespace { - -// RecordingProofVerifier accepts any certificate chain and records the common -// name of the leaf and then delegates the actual verfication to an actual -// verifier. If no optional verifier is provided, then VerifyProof will return -// success. -class RecordingProofVerifier : public ProofVerifier { - public: - explicit RecordingProofVerifier(std::unique_ptr<ProofVerifier> verifier) - : verifier_(std::move(verifier)) {} - - // ProofVerifier interface. - QuicAsyncStatus VerifyProof( - const string& hostname, - const uint16_t port, - const string& server_config, - QuicTransportVersion transport_version, - QuicStringPiece chlo_hash, - const std::vector<string>& certs, - const string& cert_sct, - const string& signature, - const ProofVerifyContext* context, - string* error_details, - std::unique_ptr<ProofVerifyDetails>* details, - std::unique_ptr<ProofVerifierCallback> callback) override { - common_name_.clear(); - if (certs.empty()) { - return QUIC_FAILURE; - } - - // Convert certs to X509Certificate. - std::vector<QuicStringPiece> cert_pieces(certs.size()); - for (unsigned i = 0; i < certs.size(); i++) { - cert_pieces[i] = QuicStringPiece(certs[i]); - } - // TODO(rtenneti): Fix after adding support for real certs. Currently, - // cert_pieces are "leaf" and "intermediate" and CreateFromDERCertChain - // fails to return cert from these cert_pieces. - // bssl::UniquePtr<X509> cert(d2i_X509(nullptr, &data, certs[0].size())); - // if (!cert.get()) { - // return QUIC_FAILURE; - // } - // - // common_name_ = cert->subject().GetDisplayName(); - cert_sct_ = cert_sct; - - if (!verifier_) { - return QUIC_SUCCESS; - } - - return verifier_->VerifyProof(hostname, port, server_config, - transport_version, chlo_hash, certs, cert_sct, - signature, context, error_details, details, - std::move(callback)); - } - - QuicAsyncStatus VerifyCertChain( - const std::string& hostname, - const std::vector<std::string>& certs, - const ProofVerifyContext* context, - std::string* error_details, - std::unique_ptr<ProofVerifyDetails>* details, - std::unique_ptr<ProofVerifierCallback> callback) override { - return QUIC_SUCCESS; - } - - const string& common_name() const { return common_name_; } - - const string& cert_sct() const { return cert_sct_; } - - private: - std::unique_ptr<ProofVerifier> verifier_; - string common_name_; - string cert_sct_; -}; -} // namespace - -class MockableQuicClientEpollNetworkHelper - : public QuicClientEpollNetworkHelper { - public: - using QuicClientEpollNetworkHelper::QuicClientEpollNetworkHelper; - ~MockableQuicClientEpollNetworkHelper() override = default; - - void ProcessPacket(const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - const QuicReceivedPacket& packet) override { - QuicClientEpollNetworkHelper::ProcessPacket(self_address, peer_address, - packet); - if (track_last_incoming_packet_) { - last_incoming_packet_ = packet.Clone(); - } - } - - QuicPacketWriter* CreateQuicPacketWriter() override { - QuicPacketWriter* writer = - QuicClientEpollNetworkHelper::CreateQuicPacketWriter(); - if (!test_writer_) { - return writer; - } - test_writer_->set_writer(writer); - return test_writer_; - } - - const QuicReceivedPacket* last_incoming_packet() { - return last_incoming_packet_.get(); - } - - void set_track_last_incoming_packet(bool track) { - track_last_incoming_packet_ = track; - } - - void UseWriter(QuicPacketWriterWrapper* writer) { - CHECK(test_writer_ == nullptr); - test_writer_ = writer; - } - - void set_peer_address(const QuicSocketAddress& address) { - CHECK(test_writer_ != nullptr); - test_writer_->set_peer_address(address); - } - - private: - QuicPacketWriterWrapper* test_writer_ = nullptr; - // The last incoming packet, iff |track_last_incoming_packet_| is true. - std::unique_ptr<QuicReceivedPacket> last_incoming_packet_; - // If true, copy each packet from ProcessPacket into |last_incoming_packet_| - bool track_last_incoming_packet_ = false; -}; - -MockableQuicClient::MockableQuicClient( - QuicSocketAddress server_address, - const QuicServerId& server_id, - const ParsedQuicVersionVector& supported_versions, - EpollServer* epoll_server) - : MockableQuicClient(server_address, - server_id, - QuicConfig(), - supported_versions, - epoll_server) {} - -MockableQuicClient::MockableQuicClient( - QuicSocketAddress server_address, - const QuicServerId& server_id, - const QuicConfig& config, - const ParsedQuicVersionVector& supported_versions, - EpollServer* epoll_server) - : MockableQuicClient(server_address, - server_id, - config, - supported_versions, - epoll_server, - nullptr) {} - -MockableQuicClient::MockableQuicClient( - QuicSocketAddress server_address, - const QuicServerId& server_id, - const QuicConfig& config, - const ParsedQuicVersionVector& supported_versions, - EpollServer* epoll_server, - std::unique_ptr<ProofVerifier> proof_verifier) - : QuicClient( - server_address, - server_id, - supported_versions, - config, - epoll_server, - QuicMakeUnique<MockableQuicClientEpollNetworkHelper>(epoll_server, - this), - QuicWrapUnique( - new RecordingProofVerifier(std::move(proof_verifier)))), - override_connection_id_(0) {} - -MockableQuicClient::~MockableQuicClient() { - if (connected()) { - Disconnect(); - } -} - -MockableQuicClientEpollNetworkHelper* -MockableQuicClient::mockable_network_helper() { - return static_cast<MockableQuicClientEpollNetworkHelper*>( - epoll_network_helper()); -} - -const MockableQuicClientEpollNetworkHelper* -MockableQuicClient::mockable_network_helper() const { - return static_cast<const MockableQuicClientEpollNetworkHelper*>( - epoll_network_helper()); -} - -QuicConnectionId MockableQuicClient::GenerateNewConnectionId() { - return override_connection_id_ ? override_connection_id_ - : QuicClient::GenerateNewConnectionId(); -} - -void MockableQuicClient::UseConnectionId(QuicConnectionId connection_id) { - override_connection_id_ = connection_id; -} - -void MockableQuicClient::UseWriter(QuicPacketWriterWrapper* writer) { - mockable_network_helper()->UseWriter(writer); -} - -void MockableQuicClient::set_peer_address(const QuicSocketAddress& address) { - mockable_network_helper()->set_peer_address(address); -} - -const QuicReceivedPacket* MockableQuicClient::last_incoming_packet() { - return mockable_network_helper()->last_incoming_packet(); -} - -void MockableQuicClient::set_track_last_incoming_packet(bool track) { - mockable_network_helper()->set_track_last_incoming_packet(track); -} - -QuicTestClient::QuicTestClient( - QuicSocketAddress server_address, - const string& server_hostname, - const ParsedQuicVersionVector& supported_versions) - : QuicTestClient(server_address, - server_hostname, - QuicConfig(), - supported_versions) {} - -QuicTestClient::QuicTestClient( - QuicSocketAddress server_address, - const string& server_hostname, - const QuicConfig& config, - const ParsedQuicVersionVector& supported_versions) - : client_(new MockableQuicClient(server_address, - QuicServerId(server_hostname, - server_address.port(), - PRIVACY_MODE_DISABLED), - config, - supported_versions, - &epoll_server_)) { - Initialize(); -} - -QuicTestClient::QuicTestClient( - QuicSocketAddress server_address, - const string& server_hostname, - const QuicConfig& config, - const ParsedQuicVersionVector& supported_versions, - std::unique_ptr<ProofVerifier> proof_verifier) - : client_(new MockableQuicClient(server_address, - QuicServerId(server_hostname, - server_address.port(), - PRIVACY_MODE_DISABLED), - config, - supported_versions, - &epoll_server_, - std::move(proof_verifier))) { - Initialize(); -} - -QuicTestClient::QuicTestClient() = default; - -QuicTestClient::~QuicTestClient() { - for (std::pair<QuicStreamId, QuicSpdyClientStream*> stream : open_streams_) { - stream.second->set_visitor(nullptr); - } -} - -void QuicTestClient::Initialize() { - priority_ = 3; - connect_attempted_ = false; - auto_reconnect_ = false; - buffer_body_ = true; - num_requests_ = 0; - num_responses_ = 0; - ClearPerConnectionState(); - // As chrome will generally do this, we want it to be the default when it's - // not overridden. - if (!client_->config()->HasSetBytesForConnectionIdToSend()) { - client_->config()->SetBytesForConnectionIdToSend(0); - } -} - -void QuicTestClient::SetUserAgentID(const string& user_agent_id) { - client_->SetUserAgentID(user_agent_id); -} - -ssize_t QuicTestClient::SendRequest(const string& uri) { - SpdyHeaderBlock headers; - if (!PopulateHeaderBlockFromUrl(uri, &headers)) { - return 0; - } - return SendMessage(headers, ""); -} - -void QuicTestClient::SendRequestsAndWaitForResponses( - const std::vector<string>& url_list) { - for (const string& url : url_list) { - SendRequest(url); - } - while (client()->WaitForEvents()) { - } -} - -ssize_t QuicTestClient::GetOrCreateStreamAndSendRequest( - const SpdyHeaderBlock* headers, - QuicStringPiece body, - bool fin, - QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { - if (headers) { - QuicClientPushPromiseIndex::TryHandle* handle; - QuicAsyncStatus rv = - client()->push_promise_index()->Try(*headers, this, &handle); - if (rv == QUIC_SUCCESS) - return 1; - if (rv == QUIC_PENDING) { - // May need to retry request if asynchronous rendezvous fails. - std::unique_ptr<SpdyHeaderBlock> new_headers( - new SpdyHeaderBlock(headers->Clone())); - push_promise_data_to_resend_ = QuicMakeUnique<TestClientDataToResend>( - std::move(new_headers), body, fin, this, std::move(ack_listener)); - return 1; - } - } - - // Maybe it's better just to overload this. it's just that we need - // for the GetOrCreateStream function to call something else...which - // is icky and complicated, but maybe not worse than this. - QuicSpdyClientStream* stream = GetOrCreateStream(); - if (stream == nullptr) { - return 0; - } - QuicStreamPeer::set_ack_listener(stream, ack_listener); - - ssize_t ret = 0; - if (headers != nullptr) { - SpdyHeaderBlock spdy_headers(headers->Clone()); - if (spdy_headers[":authority"].as_string().empty()) { - spdy_headers[":authority"] = client_->server_id().host(); - } - ret = stream->SendRequest(std::move(spdy_headers), body, fin); - ++num_requests_; - } else { - stream->WriteOrBufferBody(string(body), fin, ack_listener); - ret = body.length(); - } - if (GetQuicReloadableFlag(enable_quic_stateless_reject_support)) { - std::unique_ptr<SpdyHeaderBlock> new_headers; - if (headers) { - new_headers = QuicMakeUnique<SpdyHeaderBlock>(headers->Clone()); - } - std::unique_ptr<QuicSpdyClientBase::QuicDataToResend> data_to_resend( - new TestClientDataToResend(std::move(new_headers), body, fin, this, - ack_listener)); - client()->MaybeAddQuicDataToResend(std::move(data_to_resend)); - } - return ret; -} - -ssize_t QuicTestClient::SendMessage(const SpdyHeaderBlock& headers, - QuicStringPiece body) { - return SendMessage(headers, body, /*fin=*/true); -} - -ssize_t QuicTestClient::SendMessage(const SpdyHeaderBlock& headers, - QuicStringPiece body, - bool fin) { - // Always force creation of a stream for SendMessage. - latest_created_stream_ = nullptr; - - ssize_t ret = GetOrCreateStreamAndSendRequest(&headers, body, fin, nullptr); - WaitForWriteToFlush(); - return ret; -} - -ssize_t QuicTestClient::SendData(const string& data, bool last_data) { - return SendData(data, last_data, nullptr); -} - -ssize_t QuicTestClient::SendData( - const string& data, - bool last_data, - QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { - return GetOrCreateStreamAndSendRequest(nullptr, QuicStringPiece(data), - last_data, std::move(ack_listener)); -} - -bool QuicTestClient::response_complete() const { - return response_complete_; -} - -int64_t QuicTestClient::response_body_size() const { - return response_body_size_; -} - -bool QuicTestClient::buffer_body() const { - return buffer_body_; -} - -void QuicTestClient::set_buffer_body(bool buffer_body) { - buffer_body_ = buffer_body; -} - -const string& QuicTestClient::response_body() const { - return response_; -} - -string QuicTestClient::SendCustomSynchronousRequest( - const SpdyHeaderBlock& headers, - const string& body) { - // Clear connection state here and only track this synchronous request. - ClearPerConnectionState(); - if (SendMessage(headers, body) == 0) { - QUIC_DLOG(ERROR) << "Failed the request for: " << headers.DebugString(); - // Set the response_ explicitly. Otherwise response_ will contain the - // response from the previously successful request. - response_ = ""; - } else { - WaitForResponse(); - } - return response_; -} - -string QuicTestClient::SendSynchronousRequest(const string& uri) { - SpdyHeaderBlock headers; - if (!PopulateHeaderBlockFromUrl(uri, &headers)) { - return ""; - } - return SendCustomSynchronousRequest(headers, ""); -} - -void QuicTestClient::SendConnectivityProbing() { - QuicConnection* connection = client()->client_session()->connection(); - connection->SendConnectivityProbingPacket(connection->writer(), - connection->peer_address()); -} - -void QuicTestClient::SetLatestCreatedStream(QuicSpdyClientStream* stream) { - latest_created_stream_ = stream; - if (latest_created_stream_ != nullptr) { - open_streams_[stream->id()] = stream; - stream->set_visitor(this); - } -} - -QuicSpdyClientStream* QuicTestClient::GetOrCreateStream() { - if (!connect_attempted_ || auto_reconnect_) { - if (!connected()) { - Connect(); - } - if (!connected()) { - return nullptr; - } - } - if (open_streams_.empty()) { - ClearPerConnectionState(); - } - if (!latest_created_stream_) { - SetLatestCreatedStream(client_->CreateClientStream()); - if (latest_created_stream_) { - latest_created_stream_->SetPriority(priority_); - } - } - - return latest_created_stream_; -} - -QuicErrorCode QuicTestClient::connection_error() { - return client()->connection_error(); -} - -MockableQuicClient* QuicTestClient::client() { - return client_.get(); -} - -const string& QuicTestClient::cert_common_name() const { - return reinterpret_cast<RecordingProofVerifier*>(client_->proof_verifier()) - ->common_name(); -} - -const string& QuicTestClient::cert_sct() const { - return reinterpret_cast<RecordingProofVerifier*>(client_->proof_verifier()) - ->cert_sct(); -} - -QuicTagValueMap QuicTestClient::GetServerConfig() const { - QuicCryptoClientConfig* config = client_->crypto_config(); - QuicCryptoClientConfig::CachedState* state = - config->LookupOrCreate(client_->server_id()); - const CryptoHandshakeMessage* handshake_msg = state->GetServerConfig(); - if (handshake_msg != nullptr) { - return handshake_msg->tag_value_map(); - } else { - return QuicTagValueMap(); - } -} - -bool QuicTestClient::connected() const { - return client_->connected(); -} - -void QuicTestClient::Connect() { - DCHECK(!connected()); - if (!connect_attempted_) { - client_->Initialize(); - } - - // If we've been asked to override SNI, set it now - if (override_sni_set_) { - client_->set_server_id( - QuicServerId(override_sni_, address().port(), PRIVACY_MODE_DISABLED)); - } - - client_->Connect(); - connect_attempted_ = true; -} - -void QuicTestClient::ResetConnection() { - Disconnect(); - Connect(); -} - -void QuicTestClient::Disconnect() { - ClearPerConnectionState(); - client_->Disconnect(); - connect_attempted_ = false; -} - -QuicSocketAddress QuicTestClient::local_address() const { - return client_->network_helper()->GetLatestClientAddress(); -} - -void QuicTestClient::ClearPerRequestState() { - stream_error_ = QUIC_STREAM_NO_ERROR; - response_ = ""; - response_complete_ = false; - response_headers_complete_ = false; - preliminary_headers_.clear(); - response_headers_.clear(); - response_trailers_.clear(); - bytes_read_ = 0; - bytes_written_ = 0; - response_body_size_ = 0; -} - -bool QuicTestClient::HaveActiveStream() { - return push_promise_data_to_resend_.get() || !open_streams_.empty(); -} - -bool QuicTestClient::WaitUntil(int timeout_ms, std::function<bool()> trigger) { - int64_t timeout_us = timeout_ms * base::Time::kMicrosecondsPerMillisecond; - int64_t old_timeout_us = epoll_server()->timeout_in_us(); - if (timeout_us > 0) { - epoll_server()->set_timeout_in_us(timeout_us); - } - const QuicClock* clock = - QuicConnectionPeer::GetHelper(client()->session()->connection()) - ->GetClock(); - QuicTime end_waiting_time = - clock->Now() + QuicTime::Delta::FromMicroseconds(timeout_us); - while (HaveActiveStream() && !(trigger && trigger()) && - (timeout_us < 0 || clock->Now() < end_waiting_time)) { - client_->WaitForEvents(); - } - ReadNextResponse(); - if (timeout_us > 0) { - epoll_server()->set_timeout_in_us(old_timeout_us); - } - if (trigger && !trigger()) { - VLOG(1) << "Client WaitUntil returning with trigger returning false." - << QuicStackTrace(); - return false; - } - return true; -} - -ssize_t QuicTestClient::Send(const void* buffer, size_t size) { - return SendData(string(static_cast<const char*>(buffer), size), false); -} - -bool QuicTestClient::response_headers_complete() const { - for (std::pair<QuicStreamId, QuicSpdyClientStream*> stream : open_streams_) { - if (stream.second->headers_decompressed()) { - return true; - } - } - return response_headers_complete_; -} - -const SpdyHeaderBlock* QuicTestClient::response_headers() const { - for (std::pair<QuicStreamId, QuicSpdyClientStream*> stream : open_streams_) { - size_t bytes_read = - stream.second->stream_bytes_read() + stream.second->header_bytes_read(); - if (bytes_read > 0) { - response_headers_ = stream.second->response_headers().Clone(); - break; - } - } - return &response_headers_; -} - -const SpdyHeaderBlock* QuicTestClient::preliminary_headers() const { - for (std::pair<QuicStreamId, QuicSpdyClientStream*> stream : open_streams_) { - size_t bytes_read = - stream.second->stream_bytes_read() + stream.second->header_bytes_read(); - if (bytes_read > 0) { - preliminary_headers_ = stream.second->preliminary_headers().Clone(); - break; - } - } - return &preliminary_headers_; -} - -const SpdyHeaderBlock& QuicTestClient::response_trailers() const { - return response_trailers_; -} - -int64_t QuicTestClient::response_size() const { - return bytes_read(); -} - -size_t QuicTestClient::bytes_read() const { - for (std::pair<QuicStreamId, QuicSpdyClientStream*> stream : open_streams_) { - size_t bytes_read = - stream.second->stream_bytes_read() + stream.second->header_bytes_read(); - if (bytes_read > 0) { - return bytes_read; - } - } - return bytes_read_; -} - -size_t QuicTestClient::bytes_written() const { - for (std::pair<QuicStreamId, QuicSpdyClientStream*> stream : open_streams_) { - size_t bytes_written = stream.second->stream_bytes_written() + - stream.second->header_bytes_written(); - if (bytes_written > 0) { - return bytes_written; - } - } - return bytes_written_; -} - -void QuicTestClient::OnClose(QuicSpdyStream* stream) { - if (stream == nullptr) { - return; - } - // Always close the stream, regardless of whether it was the last stream - // written. - client()->OnClose(stream); - ++num_responses_; - if (!QuicContainsKey(open_streams_, stream->id())) { - return; - } - if (latest_created_stream_ == stream) { - latest_created_stream_ = nullptr; - } - QuicSpdyClientStream* client_stream = - static_cast<QuicSpdyClientStream*>(stream); - QuicStreamId id = client_stream->id(); - closed_stream_states_.insert(std::make_pair( - id, - PerStreamState( - client_stream->stream_error(), true, - client_stream->headers_decompressed(), - client_stream->response_headers(), - client_stream->preliminary_headers(), - (buffer_body() ? client_stream->data() : ""), - client_stream->received_trailers(), - // Use NumBytesConsumed to avoid counting retransmitted stream frames. - QuicStreamPeer::sequencer(client_stream)->NumBytesConsumed() + - client_stream->header_bytes_read(), - client_stream->stream_bytes_written() + - client_stream->header_bytes_written(), - client_stream->data().size()))); - open_streams_.erase(id); -} - -bool QuicTestClient::CheckVary(const SpdyHeaderBlock& client_request, - const SpdyHeaderBlock& promise_request, - const SpdyHeaderBlock& promise_response) { - return true; -} - -void QuicTestClient::OnRendezvousResult(QuicSpdyStream* stream) { - std::unique_ptr<TestClientDataToResend> data_to_resend = - std::move(push_promise_data_to_resend_); - SetLatestCreatedStream(static_cast<QuicSpdyClientStream*>(stream)); - if (stream) { - stream->OnDataAvailable(); - } else if (data_to_resend) { - data_to_resend->Resend(); - } -} - -void QuicTestClient::UseWriter(QuicPacketWriterWrapper* writer) { - client_->UseWriter(writer); -} - -void QuicTestClient::UseConnectionId(QuicConnectionId connection_id) { - DCHECK(!connected()); - client_->UseConnectionId(connection_id); -} - -bool QuicTestClient::MigrateSocket(const QuicIpAddress& new_host) { - return client_->MigrateSocket(new_host); -} - -bool QuicTestClient::MigrateSocketWithSpecifiedPort( - const QuicIpAddress& new_host, - int port) { - client_->set_local_port(port); - return client_->MigrateSocket(new_host); -} - -QuicIpAddress QuicTestClient::bind_to_address() const { - return client_->bind_to_address(); -} - -void QuicTestClient::set_bind_to_address(QuicIpAddress address) { - client_->set_bind_to_address(address); -} - -const QuicSocketAddress& QuicTestClient::address() const { - return client_->server_address(); -} - -void QuicTestClient::WaitForWriteToFlush() { - while (connected() && client()->session()->HasDataToWrite()) { - client_->WaitForEvents(); - } -} - -QuicTestClient::TestClientDataToResend::TestClientDataToResend( - std::unique_ptr<SpdyHeaderBlock> headers, - QuicStringPiece body, - bool fin, - QuicTestClient* test_client, - QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) - : QuicClient::QuicDataToResend(std::move(headers), body, fin), - test_client_(test_client), - ack_listener_(std::move(ack_listener)) {} - -QuicTestClient::TestClientDataToResend::~TestClientDataToResend() = default; - -void QuicTestClient::TestClientDataToResend::Resend() { - test_client_->GetOrCreateStreamAndSendRequest(headers_.get(), body_, fin_, - ack_listener_); - headers_.reset(); -} - -QuicTestClient::PerStreamState::PerStreamState(const PerStreamState& other) - : stream_error(other.stream_error), - response_complete(other.response_complete), - response_headers_complete(other.response_headers_complete), - response_headers(other.response_headers.Clone()), - preliminary_headers(other.preliminary_headers.Clone()), - response(other.response), - response_trailers(other.response_trailers.Clone()), - bytes_read(other.bytes_read), - bytes_written(other.bytes_written), - response_body_size(other.response_body_size) {} - -QuicTestClient::PerStreamState::PerStreamState( - QuicRstStreamErrorCode stream_error, - bool response_complete, - bool response_headers_complete, - const SpdyHeaderBlock& response_headers, - const SpdyHeaderBlock& preliminary_headers, - const string& response, - const SpdyHeaderBlock& response_trailers, - uint64_t bytes_read, - uint64_t bytes_written, - int64_t response_body_size) - : stream_error(stream_error), - response_complete(response_complete), - response_headers_complete(response_headers_complete), - response_headers(response_headers.Clone()), - preliminary_headers(preliminary_headers.Clone()), - response(response), - response_trailers(response_trailers.Clone()), - bytes_read(bytes_read), - bytes_written(bytes_written), - response_body_size(response_body_size) {} - -QuicTestClient::PerStreamState::~PerStreamState() = default; - -bool QuicTestClient::PopulateHeaderBlockFromUrl(const string& uri, - SpdyHeaderBlock* headers) { - string url; - if (QuicTextUtils::StartsWith(uri, "https://") || - QuicTextUtils::StartsWith(uri, "http://")) { - url = uri; - } else if (uri[0] == '/') { - url = "https://" + client_->server_id().host() + uri; - } else { - url = "https://" + uri; - } - return SpdyUtils::PopulateHeaderBlockFromUrl(url, headers); -} - -void QuicTestClient::ReadNextResponse() { - if (closed_stream_states_.empty()) { - return; - } - - PerStreamState state(closed_stream_states_.front().second); - - stream_error_ = state.stream_error; - response_ = state.response; - response_complete_ = state.response_complete; - response_headers_complete_ = state.response_headers_complete; - preliminary_headers_ = state.preliminary_headers.Clone(); - response_headers_ = state.response_headers.Clone(); - response_trailers_ = state.response_trailers.Clone(); - bytes_read_ = state.bytes_read; - bytes_written_ = state.bytes_written; - response_body_size_ = state.response_body_size; - - closed_stream_states_.pop_front(); -} - -void QuicTestClient::ClearPerConnectionState() { - ClearPerRequestState(); - open_streams_.clear(); - closed_stream_states_.clear(); - latest_created_stream_ = nullptr; -} - -void QuicTestClient::WaitForDelayedAcks() { - // kWaitDuration is a period of time that is long enough for all delayed - // acks to be sent and received on the other end. - const QuicTime::Delta kWaitDuration = - 4 * QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); - - const QuicClock* clock = client()->client_session()->connection()->clock(); - - QuicTime wait_until = clock->ApproximateNow() + kWaitDuration; - while (clock->ApproximateNow() < wait_until) { - // This waits for up to 50 ms. - client()->WaitForEvents(); - } -} - -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/test_tools/quic_test_client.h b/chromium/net/tools/quic/test_tools/quic_test_client.h deleted file mode 100644 index 99a78f13421..00000000000 --- a/chromium/net/tools/quic/test_tools/quic_test_client.h +++ /dev/null @@ -1,396 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_TEST_TOOLS_QUIC_TEST_CLIENT_H_ -#define NET_TOOLS_QUIC_TEST_TOOLS_QUIC_TEST_CLIENT_H_ - -#include <cstdint> -#include <memory> -#include <string> - -#include "base/macros.h" -#include "net/quic/core/proto/cached_network_parameters.pb.h" -#include "net/quic/core/quic_framer.h" -#include "net/quic/core/quic_packet_creator.h" -#include "net/quic/core/quic_packets.h" -#include "net/quic/platform/api/quic_containers.h" -#include "net/quic/platform/api/quic_map_util.h" -#include "net/quic/platform/api/quic_string_piece.h" -#include "net/tools/quic/quic_client.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace net { - -class ProofVerifier; -class QuicPacketWriterWrapper; - -namespace test { - -class MockableQuicClientEpollNetworkHelper; - -// A quic client which allows mocking out reads and writes. -class MockableQuicClient : public QuicClient { - public: - MockableQuicClient(QuicSocketAddress server_address, - const QuicServerId& server_id, - const ParsedQuicVersionVector& supported_versions, - EpollServer* epoll_server); - - MockableQuicClient(QuicSocketAddress server_address, - const QuicServerId& server_id, - const QuicConfig& config, - const ParsedQuicVersionVector& supported_versions, - EpollServer* epoll_server); - - MockableQuicClient(QuicSocketAddress server_address, - const QuicServerId& server_id, - const QuicConfig& config, - const ParsedQuicVersionVector& supported_versions, - EpollServer* epoll_server, - std::unique_ptr<ProofVerifier> proof_verifier); - - ~MockableQuicClient() override; - - QuicConnectionId GenerateNewConnectionId() override; - void UseConnectionId(QuicConnectionId connection_id); - - void UseWriter(QuicPacketWriterWrapper* writer); - void set_peer_address(const QuicSocketAddress& address); - // The last incoming packet, iff |track_last_incoming_packet| is true. - const QuicReceivedPacket* last_incoming_packet(); - // If true, copy each packet from ProcessPacket into |last_incoming_packet| - void set_track_last_incoming_packet(bool track); - - // Casts the network helper to a MockableQuicClientEpollNetworkHelper. - MockableQuicClientEpollNetworkHelper* mockable_network_helper(); - const MockableQuicClientEpollNetworkHelper* mockable_network_helper() const; - - private: - QuicConnectionId override_connection_id_; // ConnectionId to use, if nonzero - CachedNetworkParameters cached_network_paramaters_; - - DISALLOW_COPY_AND_ASSIGN(MockableQuicClient); -}; - -// A toy QUIC client used for testing. -class QuicTestClient : public QuicSpdyStream::Visitor, - public QuicClientPushPromiseIndex::Delegate { - public: - QuicTestClient(QuicSocketAddress server_address, - const std::string& server_hostname, - const ParsedQuicVersionVector& supported_versions); - QuicTestClient(QuicSocketAddress server_address, - const std::string& server_hostname, - const QuicConfig& config, - const ParsedQuicVersionVector& supported_versions); - QuicTestClient(QuicSocketAddress server_address, - const std::string& server_hostname, - const QuicConfig& config, - const ParsedQuicVersionVector& supported_versions, - std::unique_ptr<ProofVerifier> proof_verifier); - - ~QuicTestClient() override; - - // Sets the |user_agent_id| of the |client_|. - void SetUserAgentID(const std::string& user_agent_id); - - // Wraps data in a quic packet and sends it. - ssize_t SendData(const std::string& data, bool last_data); - // As above, but |delegate| will be notified when |data| is ACKed. - ssize_t SendData( - const std::string& data, - bool last_data, - QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener); - - // Clears any outstanding state and sends a simple GET of 'uri' to the - // server. Returns 0 if the request failed and no bytes were written. - ssize_t SendRequest(const std::string& uri); - // Sends requests for all the urls and waits for the responses. To process - // the individual responses as they are returned, the caller should use the - // set the response_listener on the client(). - void SendRequestsAndWaitForResponses( - const std::vector<std::string>& url_list); - // Sends a request containing |headers| and |body| and returns the number of - // bytes sent (the size of the serialized request headers and body). - ssize_t SendMessage(const SpdyHeaderBlock& headers, QuicStringPiece body); - // Sends a request containing |headers| and |body| with the fin bit set to - // |fin| and returns the number of bytes sent (the size of the serialized - // request headers and body). - ssize_t SendMessage(const SpdyHeaderBlock& headers, - QuicStringPiece body, - bool fin); - // Sends a request containing |headers| and |body|, waits for the response, - // and returns the response body. - std::string SendCustomSynchronousRequest(const SpdyHeaderBlock& headers, - const std::string& body); - // Sends a GET request for |uri|, waits for the response, and returns the - // response body. - std::string SendSynchronousRequest(const std::string& uri); - void SendConnectivityProbing(); - void Connect(); - void ResetConnection(); - void Disconnect(); - QuicSocketAddress local_address() const; - void ClearPerRequestState(); - bool WaitUntil(int timeout_ms, std::function<bool()> trigger); - ssize_t Send(const void* buffer, size_t size); - bool connected() const; - bool buffer_body() const; - void set_buffer_body(bool buffer_body); - - // Getters for stream state. Please note, these getters are divided into two - // groups. 1) returns state which only get updated once a complete response - // is received. 2) returns state of the oldest active stream which have - // received partial response (if any). - // Group 1. - const SpdyHeaderBlock& response_trailers() const; - bool response_complete() const; - int64_t response_body_size() const; - const std::string& response_body() const; - // Group 2. - bool response_headers_complete() const; - const SpdyHeaderBlock* response_headers() const; - const SpdyHeaderBlock* preliminary_headers() const; - int64_t response_size() const; - size_t bytes_read() const; - size_t bytes_written() const; - - // Returns once at least one complete response or a connection close has been - // received from the server. If responses are received for multiple (say 2) - // streams, next WaitForResponse will return immediately. - void WaitForResponse() { WaitForResponseForMs(-1); } - - // Returns once some data is received on any open streams or at least one - // complete response is received from the server. - void WaitForInitialResponse() { WaitForInitialResponseForMs(-1); } - - // Returns once at least one complete response or a connection close has been - // received from the server, or once the timeout expires. -1 means no timeout. - // If responses are received for multiple (say 2) streams, next - // WaitForResponseForMs will return immediately. - void WaitForResponseForMs(int timeout_ms) { - WaitUntil(timeout_ms, [this]() { return !closed_stream_states_.empty(); }); - if (response_complete()) { - VLOG(1) << "Client received response:" - << response_headers()->DebugString() << response_body(); - } - } - - // Returns once some data is received on any open streams or at least one - // complete response is received from the server, or once the timeout - // expires. -1 means no timeout. - void WaitForInitialResponseForMs(int timeout_ms) { - WaitUntil(timeout_ms, [this]() { return response_size() != 0; }); - } - - // Migrate local address to <|new_host|, a random port>. - // Return whether the migration succeeded. - bool MigrateSocket(const QuicIpAddress& new_host); - // Migrate local address to <|new_host|, |port|>. - // Return whether the migration succeeded. - bool MigrateSocketWithSpecifiedPort(const QuicIpAddress& new_host, int port); - QuicIpAddress bind_to_address() const; - void set_bind_to_address(QuicIpAddress address); - const QuicSocketAddress& address() const; - - // From QuicSpdyStream::Visitor - void OnClose(QuicSpdyStream* stream) override; - - // From QuicClientPushPromiseIndex::Delegate - bool CheckVary(const SpdyHeaderBlock& client_request, - const SpdyHeaderBlock& promise_request, - const SpdyHeaderBlock& promise_response) override; - void OnRendezvousResult(QuicSpdyStream*) override; - - // Configures client_ to take ownership of and use the writer. - // Must be called before initial connect. - void UseWriter(QuicPacketWriterWrapper* writer); - // If the given ConnectionId is nonzero, configures client_ to use a specific - // ConnectionId instead of a random one. - void UseConnectionId(QuicConnectionId connection_id); - - // Returns nullptr if the maximum number of streams have already been created. - QuicSpdyClientStream* GetOrCreateStream(); - - // Calls GetOrCreateStream(), sends the request on the stream, and - // stores the request in case it needs to be resent. If |headers| is - // null, only the body will be sent on the stream. - ssize_t GetOrCreateStreamAndSendRequest( - const SpdyHeaderBlock* headers, - QuicStringPiece body, - bool fin, - QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener); - - QuicRstStreamErrorCode stream_error() { return stream_error_; } - QuicErrorCode connection_error(); - - MockableQuicClient* client(); - - // cert_common_name returns the common name value of the server's certificate, - // or the empty string if no certificate was presented. - const std::string& cert_common_name() const; - - // cert_sct returns the signed timestamp of the server's certificate, - // or the empty string if no signed timestamp was presented. - const std::string& cert_sct() const; - - // Get the server config map. - QuicTagValueMap GetServerConfig() const; - - void set_auto_reconnect(bool reconnect) { auto_reconnect_ = reconnect; } - - void set_priority(SpdyPriority priority) { priority_ = priority; } - - void WaitForWriteToFlush(); - - EpollServer* epoll_server() { return &epoll_server_; } - - size_t num_requests() const { return num_requests_; } - - size_t num_responses() const { return num_responses_; } - - void set_server_address(const QuicSocketAddress& server_address) { - client_->set_server_address(server_address); - } - - void set_peer_address(const QuicSocketAddress& address) { - client_->set_peer_address(address); - } - - // Explicitly set the SNI value for this client, overriding the default - // behavior which extracts the SNI value from the request URL. - void OverrideSni(const std::string& sni) { - override_sni_set_ = true; - override_sni_ = sni; - } - - void Initialize(); - - void set_client(MockableQuicClient* client) { client_.reset(client); } - - // PerStreamState of a stream is updated when it is closed. - struct PerStreamState { - PerStreamState(const PerStreamState& other); - PerStreamState(QuicRstStreamErrorCode stream_error, - bool response_complete, - bool response_headers_complete, - const SpdyHeaderBlock& response_headers, - const SpdyHeaderBlock& preliminary_headers, - const std::string& response, - const SpdyHeaderBlock& response_trailers, - uint64_t bytes_read, - uint64_t bytes_written, - int64_t response_body_size); - ~PerStreamState(); - - QuicRstStreamErrorCode stream_error; - bool response_complete; - bool response_headers_complete; - SpdyHeaderBlock response_headers; - SpdyHeaderBlock preliminary_headers; - std::string response; - SpdyHeaderBlock response_trailers; - uint64_t bytes_read; - uint64_t bytes_written; - int64_t response_body_size; - }; - - // Given |uri|, populates the fields in |headers| for a simple GET - // request. If |uri| is a relative URL, the QuicServerId will be - // use to specify the authority. - bool PopulateHeaderBlockFromUrl(const std::string& uri, - SpdyHeaderBlock* headers); - - // Waits for a period of time that is long enough to receive all delayed acks - // sent by peer. - void WaitForDelayedAcks(); - - protected: - QuicTestClient(); - - private: - class TestClientDataToResend : public QuicClient::QuicDataToResend { - public: - TestClientDataToResend( - std::unique_ptr<SpdyHeaderBlock> headers, - QuicStringPiece body, - bool fin, - QuicTestClient* test_client, - QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener); - - ~TestClientDataToResend() override; - - void Resend() override; - - protected: - QuicTestClient* test_client_; - QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener_; - }; - - bool HaveActiveStream(); - - // Read oldest received response and remove it from closed_stream_states_. - void ReadNextResponse(); - - // Clear open_streams_, closed_stream_states_ and reset - // latest_created_stream_. - void ClearPerConnectionState(); - - // Update latest_created_stream_, add |stream| to open_streams_ and starts - // tracking its state. - void SetLatestCreatedStream(QuicSpdyClientStream* stream); - - EpollServer epoll_server_; - std::unique_ptr<MockableQuicClient> client_; // The actual client - QuicSpdyClientStream* latest_created_stream_; - std::map<QuicStreamId, QuicSpdyClientStream*> open_streams_; - // Received responses of closed streams. - QuicLinkedHashMap<QuicStreamId, PerStreamState> closed_stream_states_; - - QuicRstStreamErrorCode stream_error_; - - bool response_complete_; - bool response_headers_complete_; - mutable SpdyHeaderBlock preliminary_headers_; - mutable SpdyHeaderBlock response_headers_; - - // Parsed response trailers (if present), copied from the stream in OnClose. - SpdyHeaderBlock response_trailers_; - - SpdyPriority priority_; - std::string response_; - // bytes_read_ and bytes_written_ are updated only when stream_ is released; - // prefer bytes_read() and bytes_written() member functions. - uint64_t bytes_read_; - uint64_t bytes_written_; - // The number of HTTP body bytes received. - int64_t response_body_size_; - // True if we tried to connect already since the last call to Disconnect(). - bool connect_attempted_; - // The client will auto-connect exactly once before sending data. If - // something causes a connection reset, it will not automatically reconnect - // unless auto_reconnect_ is true. - bool auto_reconnect_; - // Should we buffer the response body? Defaults to true. - bool buffer_body_; - // For async push promise rendezvous, validation may fail in which - // case the request should be retried. - std::unique_ptr<TestClientDataToResend> push_promise_data_to_resend_; - // Number of requests/responses this client has sent/received. - size_t num_requests_; - size_t num_responses_; - - // If set, this value is used for the connection SNI, overriding the usual - // logic which extracts the SNI from the request URL. - bool override_sni_set_ = false; - std::string override_sni_; - - DISALLOW_COPY_AND_ASSIGN(QuicTestClient); -}; - -} // namespace test - -} // namespace net - -#endif // NET_TOOLS_QUIC_TEST_TOOLS_QUIC_TEST_CLIENT_H_ diff --git a/chromium/net/tools/quic/test_tools/quic_test_server.cc b/chromium/net/tools/quic/test_tools/quic_test_server.cc deleted file mode 100644 index ac90e7f39d5..00000000000 --- a/chromium/net/tools/quic/test_tools/quic_test_server.cc +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright (c) 2015 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/tools/quic/test_tools/quic_test_server.h" - -#include "net/quic/platform/api/quic_ptr_util.h" -#include "net/tools/quic/quic_epoll_alarm_factory.h" -#include "net/tools/quic/quic_epoll_connection_helper.h" -#include "net/tools/quic/quic_simple_crypto_server_stream_helper.h" -#include "net/tools/quic/quic_simple_dispatcher.h" -#include "net/tools/quic/quic_simple_server_session.h" - -namespace net { - -namespace test { - -class CustomStreamSession : public QuicSimpleServerSession { - public: - CustomStreamSession( - const QuicConfig& config, - QuicConnection* connection, - QuicSession::Visitor* visitor, - QuicCryptoServerStream::Helper* helper, - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache, - QuicTestServer::StreamFactory* stream_factory, - QuicTestServer::CryptoStreamFactory* crypto_stream_factory, - QuicHttpResponseCache* response_cache) - : QuicSimpleServerSession(config, - connection, - visitor, - helper, - crypto_config, - compressed_certs_cache, - response_cache), - stream_factory_(stream_factory), - crypto_stream_factory_(crypto_stream_factory) {} - - QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override { - if (!ShouldCreateIncomingDynamicStream(id)) { - return nullptr; - } - if (stream_factory_) { - QuicSpdyStream* stream = - stream_factory_->CreateStream(id, this, response_cache()); - ActivateStream(QuicWrapUnique(stream)); - return stream; - } - return QuicSimpleServerSession::CreateIncomingDynamicStream(id); - } - - QuicCryptoServerStreamBase* CreateQuicCryptoServerStream( - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache) override { - if (crypto_stream_factory_) { - return crypto_stream_factory_->CreateCryptoStream(crypto_config, this); - } - return QuicSimpleServerSession::CreateQuicCryptoServerStream( - crypto_config, compressed_certs_cache); - } - - private: - QuicTestServer::StreamFactory* stream_factory_; // Not owned. - QuicTestServer::CryptoStreamFactory* crypto_stream_factory_; // Not owned. -}; - -class QuicTestDispatcher : public QuicSimpleDispatcher { - public: - QuicTestDispatcher( - const QuicConfig& config, - const QuicCryptoServerConfig* crypto_config, - QuicVersionManager* version_manager, - std::unique_ptr<QuicConnectionHelperInterface> helper, - std::unique_ptr<QuicCryptoServerStream::Helper> session_helper, - std::unique_ptr<QuicAlarmFactory> alarm_factory, - QuicHttpResponseCache* response_cache) - : QuicSimpleDispatcher(config, - crypto_config, - version_manager, - std::move(helper), - std::move(session_helper), - std::move(alarm_factory), - response_cache), - session_factory_(nullptr), - stream_factory_(nullptr), - crypto_stream_factory_(nullptr) {} - - QuicServerSessionBase* CreateQuicSession(QuicConnectionId id, - const QuicSocketAddress& client, - QuicStringPiece alpn) override { - QuicReaderMutexLock lock(&factory_lock_); - if (session_factory_ == nullptr && stream_factory_ == nullptr && - crypto_stream_factory_ == nullptr) { - return QuicSimpleDispatcher::CreateQuicSession(id, client, alpn); - } - QuicConnection* connection = new QuicConnection( - id, client, helper(), alarm_factory(), CreatePerConnectionWriter(), - /* owns_writer= */ true, Perspective::IS_SERVER, - GetSupportedVersions()); - - QuicServerSessionBase* session = nullptr; - if (stream_factory_ != nullptr || crypto_stream_factory_ != nullptr) { - session = new CustomStreamSession( - config(), connection, this, session_helper(), crypto_config(), - compressed_certs_cache(), stream_factory_, crypto_stream_factory_, - response_cache()); - } else { - session = session_factory_->CreateSession( - config(), connection, this, session_helper(), crypto_config(), - compressed_certs_cache(), response_cache()); - } - session->Initialize(); - return session; - } - - void SetSessionFactory(QuicTestServer::SessionFactory* factory) { - QuicWriterMutexLock lock(&factory_lock_); - DCHECK(session_factory_ == nullptr); - DCHECK(stream_factory_ == nullptr); - DCHECK(crypto_stream_factory_ == nullptr); - session_factory_ = factory; - } - - void SetStreamFactory(QuicTestServer::StreamFactory* factory) { - QuicWriterMutexLock lock(&factory_lock_); - DCHECK(session_factory_ == nullptr); - DCHECK(stream_factory_ == nullptr); - stream_factory_ = factory; - } - - void SetCryptoStreamFactory(QuicTestServer::CryptoStreamFactory* factory) { - QuicWriterMutexLock lock(&factory_lock_); - DCHECK(session_factory_ == nullptr); - DCHECK(crypto_stream_factory_ == nullptr); - crypto_stream_factory_ = factory; - } - - private: - QuicMutex factory_lock_; - QuicTestServer::SessionFactory* session_factory_; // Not owned. - QuicTestServer::StreamFactory* stream_factory_; // Not owned. - QuicTestServer::CryptoStreamFactory* crypto_stream_factory_; // Not owned. -}; - -QuicTestServer::QuicTestServer(std::unique_ptr<ProofSource> proof_source, - QuicHttpResponseCache* response_cache) - : QuicServer(std::move(proof_source), response_cache) {} - -QuicTestServer::QuicTestServer( - std::unique_ptr<ProofSource> proof_source, - const QuicConfig& config, - const ParsedQuicVersionVector& supported_versions, - QuicHttpResponseCache* response_cache) - : QuicServer(std::move(proof_source), - config, - QuicCryptoServerConfig::ConfigOptions(), - supported_versions, - response_cache) {} - -QuicDispatcher* QuicTestServer::CreateQuicDispatcher() { - return new QuicTestDispatcher( - config(), &crypto_config(), version_manager(), - QuicMakeUnique<QuicEpollConnectionHelper>(epoll_server(), - QuicAllocator::BUFFER_POOL), - std::unique_ptr<QuicCryptoServerStream::Helper>( - new QuicSimpleCryptoServerStreamHelper(QuicRandom::GetInstance())), - QuicMakeUnique<QuicEpollAlarmFactory>(epoll_server()), response_cache()); -} - -void QuicTestServer::SetSessionFactory(SessionFactory* factory) { - DCHECK(dispatcher()); - static_cast<QuicTestDispatcher*>(dispatcher())->SetSessionFactory(factory); -} - -void QuicTestServer::SetSpdyStreamFactory(StreamFactory* factory) { - static_cast<QuicTestDispatcher*>(dispatcher())->SetStreamFactory(factory); -} - -void QuicTestServer::SetCryptoStreamFactory(CryptoStreamFactory* factory) { - static_cast<QuicTestDispatcher*>(dispatcher()) - ->SetCryptoStreamFactory(factory); -} - -/////////////////////////// TEST SESSIONS /////////////////////////////// - -ImmediateGoAwaySession::ImmediateGoAwaySession( - const QuicConfig& config, - QuicConnection* connection, - QuicSession::Visitor* visitor, - QuicCryptoServerStream::Helper* helper, - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache, - QuicHttpResponseCache* response_cache) - : QuicSimpleServerSession(config, - connection, - visitor, - helper, - crypto_config, - compressed_certs_cache, - response_cache) {} - -void ImmediateGoAwaySession::OnStreamFrame(const QuicStreamFrame& frame) { - SendGoAway(QUIC_PEER_GOING_AWAY, ""); - QuicSimpleServerSession::OnStreamFrame(frame); -} - -} // namespace test - -} // namespace net diff --git a/chromium/net/tools/quic/test_tools/quic_test_server.h b/chromium/net/tools/quic/test_tools/quic_test_server.h deleted file mode 100644 index 13ffc4ca6a0..00000000000 --- a/chromium/net/tools/quic/test_tools/quic_test_server.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2015 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_TOOLS_QUIC_TEST_TOOLS_QUIC_TEST_SERVER_H_ -#define NET_TOOLS_QUIC_TEST_TOOLS_QUIC_TEST_SERVER_H_ - -#include "net/quic/core/quic_session.h" -#include "net/tools/quic/quic_dispatcher.h" -#include "net/tools/quic/quic_server.h" -#include "net/tools/quic/quic_simple_server_session.h" -#include "net/tools/quic/quic_simple_server_stream.h" - -namespace net { - -namespace test { - -// A test server which enables easy creation of custom QuicServerSessions -// -// Eventually this may be extended to allow custom QuicConnections etc. -class QuicTestServer : public QuicServer { - public: - // Factory for creating QuicServerSessions. - class SessionFactory { - public: - virtual ~SessionFactory() {} - - // Returns a new session owned by the caller. - virtual QuicServerSessionBase* CreateSession( - const QuicConfig& config, - QuicConnection* connection, - QuicSession::Visitor* visitor, - QuicCryptoServerStream::Helper* helper, - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache, - QuicHttpResponseCache* response_cache) = 0; - }; - - // Factory for creating QuicSimpleServerStreams. - class StreamFactory { - public: - virtual ~StreamFactory() {} - - // Returns a new stream owned by the caller. - virtual QuicSimpleServerStream* CreateStream( - QuicStreamId id, - QuicSpdySession* session, - QuicHttpResponseCache* response_cache) = 0; - }; - - class CryptoStreamFactory { - public: - virtual ~CryptoStreamFactory() {} - - // Returns a new QuicCryptoServerStreamBase owned by the caller - virtual QuicCryptoServerStreamBase* CreateCryptoStream( - const QuicCryptoServerConfig* crypto_config, - QuicServerSessionBase* session) = 0; - }; - - QuicTestServer(std::unique_ptr<ProofSource> proof_source, - QuicHttpResponseCache* response_cache); - QuicTestServer(std::unique_ptr<ProofSource> proof_source, - const QuicConfig& config, - const ParsedQuicVersionVector& supported_versions, - QuicHttpResponseCache* response_cache); - - // Create a custom dispatcher which creates custom sessions. - QuicDispatcher* CreateQuicDispatcher() override; - - // Sets a custom session factory, owned by the caller, for easy custom - // session logic. This is incompatible with setting a stream factory or a - // crypto stream factory. - void SetSessionFactory(SessionFactory* factory); - - // Sets a custom stream factory, owned by the caller, for easy custom - // stream logic. This is incompatible with setting a session factory. - void SetSpdyStreamFactory(StreamFactory* factory); - - // Sets a custom crypto stream factory, owned by the caller, for easy custom - // crypto logic. This is incompatible with setting a session factory. - void SetCryptoStreamFactory(CryptoStreamFactory* factory); -}; - -// Useful test sessions for the QuicTestServer. - -// Test session which sends a GOAWAY immedaitely on creation, before crypto -// credentials have even been established. -class ImmediateGoAwaySession : public QuicSimpleServerSession { - public: - ImmediateGoAwaySession(const QuicConfig& config, - QuicConnection* connection, - QuicSession::Visitor* visitor, - QuicCryptoServerStream::Helper* helper, - const QuicCryptoServerConfig* crypto_config, - QuicCompressedCertsCache* compressed_certs_cache, - QuicHttpResponseCache* response_cache); - - // Override to send GoAway. - void OnStreamFrame(const QuicStreamFrame& frame) override; -}; - -} // namespace test - -} // namespace net - -#endif // NET_TOOLS_QUIC_TEST_TOOLS_QUIC_TEST_SERVER_H_ diff --git a/chromium/net/tools/quic/test_tools/run_all_unittests.cc b/chromium/net/tools/quic/test_tools/run_all_unittests.cc deleted file mode 100644 index 6d42d33eb8f..00000000000 --- a/chromium/net/tools/quic/test_tools/run_all_unittests.cc +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/test/test_suite.h" - -int main(int argc, char** argv) { - base::TestSuite test_suite(argc, argv); - - return test_suite.Run(); -} diff --git a/chromium/net/tools/quic/test_tools/server_thread.cc b/chromium/net/tools/quic/test_tools/server_thread.cc deleted file mode 100644 index 641c5fc88d6..00000000000 --- a/chromium/net/tools/quic/test_tools/server_thread.cc +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/tools/quic/test_tools/server_thread.h" - -#include "net/quic/platform/api/quic_containers.h" -#include "net/quic/test_tools/crypto_test_utils.h" -#include "net/tools/quic/quic_dispatcher.h" -#include "net/tools/quic/test_tools/quic_server_peer.h" - -namespace net { -namespace test { - -ServerThread::ServerThread(QuicServer* server, const QuicSocketAddress& address) - : SimpleThread("server_thread"), - confirmed_(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED), - pause_(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED), - paused_(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED), - resume_(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED), - quit_(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED), - server_(server), - address_(address), - port_(0), - initialized_(false) {} - -ServerThread::~ServerThread() = default; - -void ServerThread::Initialize() { - if (initialized_) { - return; - } - - server_->CreateUDPSocketAndListen(address_); - - QuicWriterMutexLock lock(&port_lock_); - port_ = server_->port(); - - initialized_ = true; -} - -void ServerThread::Run() { - if (!initialized_) { - Initialize(); - } - - while (!quit_.IsSignaled()) { - if (pause_.IsSignaled() && !resume_.IsSignaled()) { - paused_.Signal(); - resume_.Wait(); - } - server_->WaitForEvents(); - ExecuteScheduledActions(); - MaybeNotifyOfHandshakeConfirmation(); - } - - server_->Shutdown(); -} - -int ServerThread::GetPort() { - QuicReaderMutexLock lock(&port_lock_); - int rc = port_; - return rc; -} - -void ServerThread::Schedule(std::function<void()> action) { - DCHECK(!quit_.IsSignaled()); - QuicWriterMutexLock lock(&scheduled_actions_lock_); - scheduled_actions_.push_back(std::move(action)); -} - -void ServerThread::WaitForCryptoHandshakeConfirmed() { - confirmed_.Wait(); -} - -void ServerThread::Pause() { - DCHECK(!pause_.IsSignaled()); - pause_.Signal(); - paused_.Wait(); -} - -void ServerThread::Resume() { - DCHECK(!resume_.IsSignaled()); - DCHECK(pause_.IsSignaled()); - resume_.Signal(); -} - -void ServerThread::Quit() { - if (pause_.IsSignaled() && !resume_.IsSignaled()) { - resume_.Signal(); - } - quit_.Signal(); -} - -void ServerThread::MaybeNotifyOfHandshakeConfirmation() { - if (confirmed_.IsSignaled()) { - // Only notify once. - return; - } - QuicDispatcher* dispatcher = QuicServerPeer::GetDispatcher(server()); - if (dispatcher->session_map().empty()) { - // Wait for a session to be created. - return; - } - QuicSession* session = dispatcher->session_map().begin()->second.get(); - if (session->IsCryptoHandshakeConfirmed()) { - confirmed_.Signal(); - } -} - -void ServerThread::ExecuteScheduledActions() { - QuicDeque<std::function<void()>> actions; - { - QuicWriterMutexLock lock(&scheduled_actions_lock_); - actions.swap(scheduled_actions_); - } - while (!actions.empty()) { - actions.front()(); - actions.pop_front(); - } -} - -} // namespace test -} // namespace net diff --git a/chromium/net/tools/quic/test_tools/server_thread.h b/chromium/net/tools/quic/test_tools/server_thread.h deleted file mode 100644 index 7ebb5f5992d..00000000000 --- a/chromium/net/tools/quic/test_tools/server_thread.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_TOOLS_QUIC_TEST_TOOLS_SERVER_THREAD_H_ -#define NET_TOOLS_QUIC_TEST_TOOLS_SERVER_THREAD_H_ - -#include <memory> - -#include "base/macros.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/simple_thread.h" -#include "net/quic/core/quic_config.h" -#include "net/quic/platform/api/quic_containers.h" -#include "net/quic/platform/api/quic_mutex.h" -#include "net/quic/platform/api/quic_socket_address.h" -#include "net/tools/quic/quic_server.h" - -namespace net { -namespace test { - -// Simple wrapper class to run QuicServer in a dedicated thread. -class ServerThread : public base::SimpleThread { - public: - ServerThread(QuicServer* server, const QuicSocketAddress& address); - - ~ServerThread() override; - - // Prepares the server, but does not start accepting connections. Useful for - // injecting mocks. - void Initialize(); - - // Runs the event loop. Will initialize if necessary. - void Run() override; - - // Schedules the given action for execution in the event loop. - void Schedule(std::function<void()> action); - - // Waits for the handshake to be confirmed for the first session created. - void WaitForCryptoHandshakeConfirmed(); - - // Pauses execution of the server until Resume() is called. May only be - // called once. - void Pause(); - - // Resumes execution of the server after Pause() has been called. May only - // be called once. - void Resume(); - - // Stops the server from executing and shuts it down, destroying all - // server objects. - void Quit(); - - // Returns the underlying server. Care must be taken to avoid data races - // when accessing the server. It is always safe to access the server - // after calling Pause() and before calling Resume(). - QuicServer* server() { return server_.get(); } - - // Returns the port that the server is listening on. - int GetPort(); - - private: - void MaybeNotifyOfHandshakeConfirmation(); - void ExecuteScheduledActions(); - - base::WaitableEvent - confirmed_; // Notified when the first handshake is confirmed. - base::WaitableEvent pause_; // Notified when the server should pause. - base::WaitableEvent paused_; // Notitied when the server has paused - base::WaitableEvent resume_; // Notified when the server should resume. - base::WaitableEvent quit_; // Notified when the server should quit. - - std::unique_ptr<QuicServer> server_; - QuicSocketAddress address_; - mutable QuicMutex port_lock_; - int port_ GUARDED_BY(port_lock_); - - bool initialized_; - - QuicMutex scheduled_actions_lock_; - QuicDeque<std::function<void()>> scheduled_actions_ - GUARDED_BY(scheduled_actions_lock_); - - DISALLOW_COPY_AND_ASSIGN(ServerThread); -}; - -} // namespace test -} // namespace net - -#endif // NET_TOOLS_QUIC_TEST_TOOLS_SERVER_THREAD_H_ |