Home | History | Annotate | Download | only in quic
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/tools/quic/quic_dispatcher.h"
      6 
      7 #include <string>
      8 
      9 #include "base/strings/string_piece.h"
     10 #include "net/quic/crypto/crypto_handshake.h"
     11 #include "net/quic/crypto/quic_crypto_server_config.h"
     12 #include "net/quic/crypto/quic_random.h"
     13 #include "net/quic/quic_crypto_stream.h"
     14 #include "net/quic/quic_flags.h"
     15 #include "net/quic/quic_utils.h"
     16 #include "net/quic/test_tools/quic_test_utils.h"
     17 #include "net/tools/epoll_server/epoll_server.h"
     18 #include "net/tools/quic/quic_packet_writer_wrapper.h"
     19 #include "net/tools/quic/quic_time_wait_list_manager.h"
     20 #include "net/tools/quic/test_tools/quic_dispatcher_peer.h"
     21 #include "net/tools/quic/test_tools/quic_test_utils.h"
     22 #include "testing/gmock/include/gmock/gmock.h"
     23 #include "testing/gtest/include/gtest/gtest.h"
     24 
     25 using base::StringPiece;
     26 using net::EpollServer;
     27 using net::test::ConstructEncryptedPacket;
     28 using net::test::MockSession;
     29 using net::test::ValueRestore;
     30 using net::tools::test::MockConnection;
     31 using std::make_pair;
     32 using testing::DoAll;
     33 using testing::InSequence;
     34 using testing::Invoke;
     35 using testing::WithoutArgs;
     36 using testing::_;
     37 
     38 namespace net {
     39 namespace tools {
     40 namespace test {
     41 namespace {
     42 
     43 class TestDispatcher : public QuicDispatcher {
     44  public:
     45   explicit TestDispatcher(const QuicConfig& config,
     46                           const QuicCryptoServerConfig& crypto_config,
     47                           EpollServer* eps)
     48       : QuicDispatcher(config,
     49                        crypto_config,
     50                        QuicSupportedVersions(),
     51                        eps) {
     52   }
     53 
     54   MOCK_METHOD3(CreateQuicSession, QuicSession*(
     55       QuicConnectionId connection_id,
     56       const IPEndPoint& server_address,
     57       const IPEndPoint& client_address));
     58   using QuicDispatcher::write_blocked_list;
     59 
     60   using QuicDispatcher::current_server_address;
     61   using QuicDispatcher::current_client_address;
     62 };
     63 
     64 // A Connection class which unregisters the session from the dispatcher
     65 // when sending connection close.
     66 // It'd be slightly more realistic to do this from the Session but it would
     67 // involve a lot more mocking.
     68 class MockServerConnection : public MockConnection {
     69  public:
     70   MockServerConnection(QuicConnectionId connection_id,
     71                        QuicDispatcher* dispatcher)
     72       : MockConnection(connection_id, true),
     73         dispatcher_(dispatcher) {}
     74 
     75   void UnregisterOnConnectionClosed() {
     76     LOG(ERROR) << "Unregistering " << connection_id();
     77     dispatcher_->OnConnectionClosed(connection_id(), QUIC_NO_ERROR);
     78   }
     79  private:
     80   QuicDispatcher* dispatcher_;
     81 };
     82 
     83 QuicSession* CreateSession(QuicDispatcher* dispatcher,
     84                            QuicConnectionId connection_id,
     85                            const IPEndPoint& client_address,
     86                            MockSession** session) {
     87   MockServerConnection* connection =
     88       new MockServerConnection(connection_id, dispatcher);
     89   *session = new MockSession(connection);
     90   ON_CALL(*connection, SendConnectionClose(_)).WillByDefault(
     91       WithoutArgs(Invoke(
     92           connection, &MockServerConnection::UnregisterOnConnectionClosed)));
     93   EXPECT_CALL(*reinterpret_cast<MockConnection*>((*session)->connection()),
     94               ProcessUdpPacket(_, client_address, _));
     95 
     96   return *session;
     97 }
     98 
     99 class QuicDispatcherTest : public ::testing::Test {
    100  public:
    101   QuicDispatcherTest()
    102       : crypto_config_(QuicCryptoServerConfig::TESTING,
    103                        QuicRandom::GetInstance()),
    104         dispatcher_(config_, crypto_config_, &eps_),
    105         session1_(NULL),
    106         session2_(NULL) {
    107     dispatcher_.Initialize(1);
    108   }
    109 
    110   virtual ~QuicDispatcherTest() {}
    111 
    112   MockConnection* connection1() {
    113     return reinterpret_cast<MockConnection*>(session1_->connection());
    114   }
    115 
    116   MockConnection* connection2() {
    117     return reinterpret_cast<MockConnection*>(session2_->connection());
    118   }
    119 
    120   void ProcessPacket(IPEndPoint client_address,
    121                      QuicConnectionId connection_id,
    122                      bool has_version_flag,
    123                      const string& data) {
    124     scoped_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
    125         connection_id, has_version_flag, false, 1, data));
    126     data_ = string(packet->data(), packet->length());
    127     dispatcher_.ProcessPacket(server_address_, client_address, *packet);
    128   }
    129 
    130   void ValidatePacket(const QuicEncryptedPacket& packet) {
    131     EXPECT_EQ(data_.length(), packet.AsStringPiece().length());
    132     EXPECT_EQ(data_, packet.AsStringPiece());
    133   }
    134 
    135   EpollServer eps_;
    136   QuicConfig config_;
    137   QuicCryptoServerConfig crypto_config_;
    138   IPEndPoint server_address_;
    139   TestDispatcher dispatcher_;
    140   MockSession* session1_;
    141   MockSession* session2_;
    142   string data_;
    143 };
    144 
    145 TEST_F(QuicDispatcherTest, ProcessPackets) {
    146   IPEndPoint client_address(net::test::Loopback4(), 1);
    147   IPAddressNumber any4;
    148   CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &any4));
    149   server_address_ = IPEndPoint(any4, 5);
    150 
    151   EXPECT_CALL(dispatcher_, CreateQuicSession(1, _, client_address))
    152       .WillOnce(testing::Return(CreateSession(
    153           &dispatcher_, 1, client_address, &session1_)));
    154   ProcessPacket(client_address, 1, true, "foo");
    155   EXPECT_EQ(client_address, dispatcher_.current_client_address());
    156   EXPECT_EQ(server_address_, dispatcher_.current_server_address());
    157 
    158 
    159   EXPECT_CALL(dispatcher_, CreateQuicSession(2, _, client_address))
    160       .WillOnce(testing::Return(CreateSession(
    161                     &dispatcher_, 2, client_address, &session2_)));
    162   ProcessPacket(client_address, 2, true, "bar");
    163 
    164   EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
    165               ProcessUdpPacket(_, _, _)).Times(1).
    166       WillOnce(testing::WithArgs<2>(Invoke(
    167           this, &QuicDispatcherTest::ValidatePacket)));
    168   ProcessPacket(client_address, 1, false, "eep");
    169 }
    170 
    171 TEST_F(QuicDispatcherTest, Shutdown) {
    172   IPEndPoint client_address(net::test::Loopback4(), 1);
    173 
    174   EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, client_address))
    175       .WillOnce(testing::Return(CreateSession(
    176                     &dispatcher_, 1, client_address, &session1_)));
    177 
    178   ProcessPacket(client_address, 1, true, "foo");
    179 
    180   EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
    181               SendConnectionClose(QUIC_PEER_GOING_AWAY));
    182 
    183   dispatcher_.Shutdown();
    184 }
    185 
    186 class MockTimeWaitListManager : public QuicTimeWaitListManager {
    187  public:
    188   MockTimeWaitListManager(QuicPacketWriter* writer,
    189                           QuicServerSessionVisitor* visitor,
    190                           EpollServer* eps)
    191       : QuicTimeWaitListManager(writer, visitor, eps, QuicSupportedVersions()) {
    192   }
    193 
    194   MOCK_METHOD5(ProcessPacket, void(const IPEndPoint& server_address,
    195                                    const IPEndPoint& client_address,
    196                                    QuicConnectionId connection_id,
    197                                    QuicPacketSequenceNumber sequence_number,
    198                                    const QuicEncryptedPacket& packet));
    199 };
    200 
    201 TEST_F(QuicDispatcherTest, TimeWaitListManager) {
    202   MockTimeWaitListManager* time_wait_list_manager =
    203       new MockTimeWaitListManager(
    204           QuicDispatcherPeer::GetWriter(&dispatcher_), &dispatcher_, &eps_);
    205   // dispatcher takes the ownership of time_wait_list_manager.
    206   QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
    207                                              time_wait_list_manager);
    208   // Create a new session.
    209   IPEndPoint client_address(net::test::Loopback4(), 1);
    210   QuicConnectionId connection_id = 1;
    211   EXPECT_CALL(dispatcher_, CreateQuicSession(connection_id, _, client_address))
    212       .WillOnce(testing::Return(CreateSession(
    213                     &dispatcher_, connection_id, client_address, &session1_)));
    214   ProcessPacket(client_address, connection_id, true, "foo");
    215 
    216   // Close the connection by sending public reset packet.
    217   QuicPublicResetPacket packet;
    218   packet.public_header.connection_id = connection_id;
    219   packet.public_header.reset_flag = true;
    220   packet.public_header.version_flag = false;
    221   packet.rejected_sequence_number = 19191;
    222   packet.nonce_proof = 132232;
    223   scoped_ptr<QuicEncryptedPacket> encrypted(
    224       QuicFramer::BuildPublicResetPacket(packet));
    225   EXPECT_CALL(*session1_, OnConnectionClosed(QUIC_PUBLIC_RESET, true)).Times(1)
    226       .WillOnce(WithoutArgs(Invoke(
    227           reinterpret_cast<MockServerConnection*>(session1_->connection()),
    228           &MockServerConnection::UnregisterOnConnectionClosed)));
    229   EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
    230               ProcessUdpPacket(_, _, _))
    231       .WillOnce(Invoke(
    232           reinterpret_cast<MockConnection*>(session1_->connection()),
    233           &MockConnection::ReallyProcessUdpPacket));
    234   dispatcher_.ProcessPacket(IPEndPoint(), client_address, *encrypted);
    235   EXPECT_TRUE(time_wait_list_manager->IsConnectionIdInTimeWait(connection_id));
    236 
    237   // Dispatcher forwards subsequent packets for this connection_id to the time
    238   // wait list manager.
    239   EXPECT_CALL(*time_wait_list_manager,
    240               ProcessPacket(_, _, connection_id, _, _)).Times(1);
    241   ProcessPacket(client_address, connection_id, true, "foo");
    242 }
    243 
    244 TEST_F(QuicDispatcherTest, StrayPacketToTimeWaitListManager) {
    245   MockTimeWaitListManager* time_wait_list_manager =
    246       new MockTimeWaitListManager(
    247           QuicDispatcherPeer::GetWriter(&dispatcher_), &dispatcher_, &eps_);
    248   // dispatcher takes the ownership of time_wait_list_manager.
    249   QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
    250                                              time_wait_list_manager);
    251 
    252   IPEndPoint client_address(net::test::Loopback4(), 1);
    253   QuicConnectionId connection_id = 1;
    254   // Dispatcher forwards all packets for this connection_id to the time wait
    255   // list manager.
    256   EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, _)).Times(0);
    257   EXPECT_CALL(*time_wait_list_manager,
    258               ProcessPacket(_, _, connection_id, _, _)).Times(1);
    259   string data = "foo";
    260   ProcessPacket(client_address, connection_id, false, "foo");
    261 }
    262 
    263 TEST(QuicDispatcherFlowControlTest, NoNewVersion17ConnectionsIfFlagDisabled) {
    264   // If FLAGS_enable_quic_stream_flow_control_2 is disabled
    265   // then the dispatcher should stop creating connections that support
    266   // QUIC_VERSION_17 (existing connections will stay alive).
    267   // TODO(rjshade): Remove once
    268   // FLAGS_enable_quic_stream_flow_control_2 is removed.
    269 
    270   EpollServer eps;
    271   QuicConfig config;
    272   QuicCryptoServerConfig server_config(QuicCryptoServerConfig::TESTING,
    273                                        QuicRandom::GetInstance());
    274   IPEndPoint client(net::test::Loopback4(), 1);
    275   IPEndPoint server(net::test::Loopback4(), 1);
    276   QuicConnectionId kCID = 1234;
    277 
    278   QuicVersion kTestQuicVersions[] = {QUIC_VERSION_17,
    279                                      QUIC_VERSION_16,
    280                                      QUIC_VERSION_15};
    281   QuicVersionVector kTestVersions;
    282   for (size_t i = 0; i < arraysize(kTestQuicVersions); ++i) {
    283     kTestVersions.push_back(kTestQuicVersions[i]);
    284   }
    285 
    286   QuicDispatcher dispatcher(config, server_config, kTestVersions, &eps);
    287   dispatcher.Initialize(0);
    288 
    289   // When flag is enabled, new connections should support QUIC_VERSION_17.
    290   ValueRestore<bool> old_flag(&FLAGS_enable_quic_stream_flow_control_2, true);
    291   scoped_ptr<QuicConnection> connection_1(
    292       QuicDispatcherPeer::CreateQuicConnection(&dispatcher, kCID, client,
    293                                                server));
    294   EXPECT_EQ(QUIC_VERSION_17, connection_1->version());
    295 
    296 
    297   // When flag is disabled, new connections should not support QUIC_VERSION_17.
    298   FLAGS_enable_quic_stream_flow_control_2 = false;
    299   scoped_ptr<QuicConnection> connection_2(
    300       QuicDispatcherPeer::CreateQuicConnection(&dispatcher, kCID, client,
    301                                                server));
    302   EXPECT_EQ(QUIC_VERSION_16, connection_2->version());
    303 }
    304 
    305 class BlockingWriter : public QuicPacketWriterWrapper {
    306  public:
    307   BlockingWriter() : write_blocked_(false) {}
    308 
    309   virtual bool IsWriteBlocked() const OVERRIDE { return write_blocked_; }
    310   virtual void SetWritable() OVERRIDE { write_blocked_ = false; }
    311 
    312   virtual WriteResult WritePacket(
    313       const char* buffer,
    314       size_t buf_len,
    315       const IPAddressNumber& self_client_address,
    316       const IPEndPoint& peer_client_address) OVERRIDE {
    317     if (write_blocked_) {
    318       return WriteResult(WRITE_STATUS_BLOCKED, EAGAIN);
    319     } else {
    320       return QuicPacketWriterWrapper::WritePacket(
    321           buffer, buf_len, self_client_address, peer_client_address);
    322     }
    323   }
    324 
    325   bool write_blocked_;
    326 };
    327 
    328 class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
    329  public:
    330   virtual void SetUp() {
    331     writer_ = new BlockingWriter;
    332     QuicDispatcherPeer::UseWriter(&dispatcher_, writer_);
    333 
    334     IPEndPoint client_address(net::test::Loopback4(), 1);
    335 
    336     EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, client_address))
    337         .WillOnce(testing::Return(CreateSession(
    338                       &dispatcher_, 1, client_address, &session1_)));
    339     ProcessPacket(client_address, 1, true, "foo");
    340 
    341     EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, client_address))
    342         .WillOnce(testing::Return(CreateSession(
    343                       &dispatcher_, 2, client_address, &session2_)));
    344     ProcessPacket(client_address, 2, true, "bar");
    345 
    346     blocked_list_ = dispatcher_.write_blocked_list();
    347   }
    348 
    349   virtual void TearDown() {
    350     EXPECT_CALL(*connection1(), SendConnectionClose(QUIC_PEER_GOING_AWAY));
    351     EXPECT_CALL(*connection2(), SendConnectionClose(QUIC_PEER_GOING_AWAY));
    352     dispatcher_.Shutdown();
    353   }
    354 
    355   void SetBlocked() {
    356     writer_->write_blocked_ = true;
    357   }
    358 
    359   void BlockConnection2() {
    360     writer_->write_blocked_ = true;
    361     dispatcher_.OnWriteBlocked(connection2());
    362   }
    363 
    364  protected:
    365   BlockingWriter* writer_;
    366   QuicDispatcher::WriteBlockedList* blocked_list_;
    367 };
    368 
    369 TEST_F(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) {
    370   // No OnCanWrite calls because no connections are blocked.
    371   dispatcher_.OnCanWrite();
    372 
    373   // Register connection 1 for events, and make sure it's notified.
    374   SetBlocked();
    375   dispatcher_.OnWriteBlocked(connection1());
    376   EXPECT_CALL(*connection1(), OnCanWrite());
    377   dispatcher_.OnCanWrite();
    378 
    379   // It should get only one notification.
    380   EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
    381   dispatcher_.OnCanWrite();
    382   EXPECT_FALSE(dispatcher_.HasPendingWrites());
    383 }
    384 
    385 TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) {
    386   // Make sure we handle events in order.
    387   InSequence s;
    388   SetBlocked();
    389   dispatcher_.OnWriteBlocked(connection1());
    390   dispatcher_.OnWriteBlocked(connection2());
    391   EXPECT_CALL(*connection1(), OnCanWrite());
    392   EXPECT_CALL(*connection2(), OnCanWrite());
    393   dispatcher_.OnCanWrite();
    394 
    395   // Check the other ordering.
    396   SetBlocked();
    397   dispatcher_.OnWriteBlocked(connection2());
    398   dispatcher_.OnWriteBlocked(connection1());
    399   EXPECT_CALL(*connection2(), OnCanWrite());
    400   EXPECT_CALL(*connection1(), OnCanWrite());
    401   dispatcher_.OnCanWrite();
    402 }
    403 
    404 TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) {
    405   // Add and remove one connction.
    406   SetBlocked();
    407   dispatcher_.OnWriteBlocked(connection1());
    408   blocked_list_->erase(connection1());
    409   EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
    410   dispatcher_.OnCanWrite();
    411 
    412   // Add and remove one connction and make sure it doesn't affect others.
    413   SetBlocked();
    414   dispatcher_.OnWriteBlocked(connection1());
    415   dispatcher_.OnWriteBlocked(connection2());
    416   blocked_list_->erase(connection1());
    417   EXPECT_CALL(*connection2(), OnCanWrite());
    418   dispatcher_.OnCanWrite();
    419 
    420   // Add it, remove it, and add it back and make sure things are OK.
    421   SetBlocked();
    422   dispatcher_.OnWriteBlocked(connection1());
    423   blocked_list_->erase(connection1());
    424   dispatcher_.OnWriteBlocked(connection1());
    425   EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
    426   dispatcher_.OnCanWrite();
    427 }
    428 
    429 TEST_F(QuicDispatcherWriteBlockedListTest, DoubleAdd) {
    430   // Make sure a double add does not necessitate a double remove.
    431   SetBlocked();
    432   dispatcher_.OnWriteBlocked(connection1());
    433   dispatcher_.OnWriteBlocked(connection1());
    434   blocked_list_->erase(connection1());
    435   EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
    436   dispatcher_.OnCanWrite();
    437 
    438   // Make sure a double add does not result in two OnCanWrite calls.
    439   SetBlocked();
    440   dispatcher_.OnWriteBlocked(connection1());
    441   dispatcher_.OnWriteBlocked(connection1());
    442   EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
    443   dispatcher_.OnCanWrite();
    444 }
    445 
    446 TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlock) {
    447   // Finally make sure if we write block on a write call, we stop calling.
    448   InSequence s;
    449   SetBlocked();
    450   dispatcher_.OnWriteBlocked(connection1());
    451   dispatcher_.OnWriteBlocked(connection2());
    452   EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
    453       Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked));
    454   EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
    455   dispatcher_.OnCanWrite();
    456 
    457   // And we'll resume where we left off when we get another call.
    458   EXPECT_CALL(*connection2(), OnCanWrite());
    459   dispatcher_.OnCanWrite();
    460 }
    461 
    462 TEST_F(QuicDispatcherWriteBlockedListTest, LimitedWrites) {
    463   // Make sure we call both writers.  The first will register for more writing
    464   // but should not be immediately called due to limits.
    465   InSequence s;
    466   SetBlocked();
    467   dispatcher_.OnWriteBlocked(connection1());
    468   dispatcher_.OnWriteBlocked(connection2());
    469   EXPECT_CALL(*connection1(), OnCanWrite());
    470   EXPECT_CALL(*connection2(), OnCanWrite()).WillOnce(
    471       Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2));
    472   dispatcher_.OnCanWrite();
    473   EXPECT_TRUE(dispatcher_.HasPendingWrites());
    474 
    475   // Now call OnCanWrite again, and connection1 should get its second chance
    476   EXPECT_CALL(*connection2(), OnCanWrite());
    477   dispatcher_.OnCanWrite();
    478   EXPECT_FALSE(dispatcher_.HasPendingWrites());
    479 }
    480 
    481 TEST_F(QuicDispatcherWriteBlockedListTest, TestWriteLimits) {
    482   // Finally make sure if we write block on a write call, we stop calling.
    483   InSequence s;
    484   SetBlocked();
    485   dispatcher_.OnWriteBlocked(connection1());
    486   dispatcher_.OnWriteBlocked(connection2());
    487   EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
    488       Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked));
    489   EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
    490   dispatcher_.OnCanWrite();
    491   EXPECT_TRUE(dispatcher_.HasPendingWrites());
    492 
    493   // And we'll resume where we left off when we get another call.
    494   EXPECT_CALL(*connection2(), OnCanWrite());
    495   dispatcher_.OnCanWrite();
    496   EXPECT_FALSE(dispatcher_.HasPendingWrites());
    497 }
    498 
    499 }  // namespace
    500 }  // namespace test
    501 }  // namespace tools
    502 }  // namespace net
    503