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/crypto_server_config.h" 12 #include "net/quic/crypto/quic_random.h" 13 #include "net/quic/quic_crypto_stream.h" 14 #include "net/quic/test_tools/quic_test_utils.h" 15 #include "net/tools/flip_server/epoll_server.h" 16 #include "net/tools/quic/quic_time_wait_list_manager.h" 17 #include "net/tools/quic/test_tools/quic_test_utils.h" 18 #include "testing/gmock/include/gmock/gmock.h" 19 #include "testing/gtest/include/gtest/gtest.h" 20 21 using base::StringPiece; 22 using net::EpollServer; 23 using net::test::MockSession; 24 using net::tools::test::MockConnection; 25 using testing::_; 26 using testing::DoAll; 27 using testing::Invoke; 28 using testing::InSequence; 29 using testing::Return; 30 using testing::WithoutArgs; 31 32 namespace net { 33 namespace tools { 34 namespace test { 35 class QuicDispatcherPeer { 36 public: 37 static void SetTimeWaitListManager( 38 QuicDispatcher* dispatcher, 39 QuicTimeWaitListManager* time_wait_list_manager) { 40 dispatcher->time_wait_list_manager_.reset(time_wait_list_manager); 41 } 42 43 static void SetWriteBlocked(QuicDispatcher* dispatcher) { 44 dispatcher->write_blocked_ = true; 45 } 46 }; 47 48 namespace { 49 50 class TestDispatcher : public QuicDispatcher { 51 public: 52 explicit TestDispatcher(const QuicConfig& config, 53 const QuicCryptoServerConfig& crypto_config, 54 EpollServer* eps) 55 : QuicDispatcher(config, crypto_config, 1, eps) {} 56 57 MOCK_METHOD4(CreateQuicSession, QuicSession*( 58 QuicGuid guid, 59 const IPEndPoint& client_address, 60 int fd, 61 EpollServer* eps)); 62 using QuicDispatcher::write_blocked_list; 63 }; 64 65 // A Connection class which unregisters the session from the dispatcher 66 // when sending connection close. 67 // It'd be slightly more realistic to do this from the Session but it would 68 // involve a lot more mocking. 69 class MockServerConnection : public MockConnection { 70 public: 71 MockServerConnection(QuicGuid guid, 72 IPEndPoint address, 73 int fd, 74 EpollServer* eps, 75 QuicDispatcher* dispatcher) 76 : MockConnection(guid, address, fd, eps, true), 77 dispatcher_(dispatcher) { 78 } 79 void UnregisterOnConnectionClose() { 80 LOG(ERROR) << "Unregistering " << guid(); 81 dispatcher_->OnConnectionClose(guid(), QUIC_NO_ERROR); 82 } 83 private: 84 QuicDispatcher* dispatcher_; 85 }; 86 87 QuicSession* CreateSession(QuicDispatcher* dispatcher, 88 QuicGuid guid, 89 const IPEndPoint& addr, 90 MockSession** session, 91 EpollServer* eps) { 92 MockServerConnection* connection = 93 new MockServerConnection(guid, addr, 0, eps, dispatcher); 94 *session = new MockSession(connection, true); 95 ON_CALL(*connection, SendConnectionClose(_)).WillByDefault( 96 WithoutArgs(Invoke( 97 connection, &MockServerConnection::UnregisterOnConnectionClose))); 98 EXPECT_CALL(*reinterpret_cast<MockConnection*>((*session)->connection()), 99 ProcessUdpPacket(_, addr, _)); 100 101 return *session; 102 } 103 104 class QuicDispatcherTest : public ::testing::Test { 105 public: 106 QuicDispatcherTest() 107 : crypto_config_(QuicCryptoServerConfig::TESTING, 108 QuicRandom::GetInstance()), 109 dispatcher_(config_, crypto_config_, &eps_), 110 session1_(NULL), 111 session2_(NULL) { 112 } 113 114 virtual ~QuicDispatcherTest() {} 115 116 MockConnection* connection1() { 117 return reinterpret_cast<MockConnection*>(session1_->connection()); 118 } 119 120 MockConnection* connection2() { 121 return reinterpret_cast<MockConnection*>(session2_->connection()); 122 } 123 124 void ProcessPacket(IPEndPoint addr, 125 QuicGuid guid, 126 const string& data) { 127 QuicEncryptedPacket packet(data.data(), data.length()); 128 dispatcher_.ProcessPacket(IPEndPoint(), addr, guid, packet); 129 } 130 131 void ValidatePacket(const QuicEncryptedPacket& packet) { 132 EXPECT_TRUE(packet.AsStringPiece().find(data_) != StringPiece::npos); 133 } 134 135 IPAddressNumber Loopback4() { 136 net::IPAddressNumber addr; 137 CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &addr)); 138 return addr; 139 } 140 141 EpollServer eps_; 142 QuicConfig config_; 143 QuicCryptoServerConfig crypto_config_; 144 TestDispatcher dispatcher_; 145 MockSession* session1_; 146 MockSession* session2_; 147 string data_; 148 }; 149 150 TEST_F(QuicDispatcherTest, ProcessPackets) { 151 IPEndPoint addr(Loopback4(), 1); 152 153 EXPECT_CALL(dispatcher_, CreateQuicSession(1, addr, _, &eps_)) 154 .WillOnce(testing::Return(CreateSession( 155 &dispatcher_, 1, addr, &session1_, &eps_))); 156 ProcessPacket(addr, 1, "foo"); 157 158 EXPECT_CALL(dispatcher_, CreateQuicSession(2, addr, _, &eps_)) 159 .WillOnce(testing::Return(CreateSession( 160 &dispatcher_, 2, addr, &session2_, &eps_))); 161 ProcessPacket(addr, 2, "bar"); 162 163 data_ = "eep"; 164 EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()), 165 ProcessUdpPacket(_, _, _)).Times(1). 166 WillOnce(testing::WithArgs<2>(Invoke( 167 this, &QuicDispatcherTest::ValidatePacket))); 168 ProcessPacket(addr, 1, "eep"); 169 } 170 171 TEST_F(QuicDispatcherTest, Shutdown) { 172 IPEndPoint addr(Loopback4(), 1); 173 174 EXPECT_CALL(dispatcher_, CreateQuicSession(_, addr, _, &eps_)) 175 .WillOnce(testing::Return(CreateSession( 176 &dispatcher_, 1, addr, &session1_, &eps_))); 177 178 ProcessPacket(addr, 1, "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 EpollServer* eps) 190 : QuicTimeWaitListManager(writer, eps) { 191 } 192 193 MOCK_METHOD4(ProcessPacket, void(const IPEndPoint& server_address, 194 const IPEndPoint& client_address, 195 QuicGuid guid, 196 const QuicEncryptedPacket& packet)); 197 }; 198 199 TEST_F(QuicDispatcherTest, TimeWaitListManager) { 200 MockTimeWaitListManager* time_wait_list_manager = 201 new MockTimeWaitListManager(&dispatcher_, &eps_); 202 // dispatcher takes the ownership of time_wait_list_manager. 203 QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_, 204 time_wait_list_manager); 205 // Create a new session. 206 IPEndPoint addr(Loopback4(), 1); 207 QuicGuid guid = 1; 208 EXPECT_CALL(dispatcher_, CreateQuicSession(guid, addr, _, &eps_)) 209 .WillOnce(testing::Return(CreateSession( 210 &dispatcher_, guid, addr, &session1_, &eps_))); 211 ProcessPacket(addr, guid, "foo"); 212 213 // Close the connection by sending public reset packet. 214 QuicPublicResetPacket packet; 215 packet.public_header.guid = guid; 216 packet.public_header.reset_flag = true; 217 packet.public_header.version_flag = false; 218 packet.rejected_sequence_number = 19191; 219 packet.nonce_proof = 132232; 220 scoped_ptr<QuicEncryptedPacket> encrypted( 221 QuicFramer::BuildPublicResetPacket(packet)); 222 EXPECT_CALL(*session1_, ConnectionClose(QUIC_PUBLIC_RESET, true)).Times(1) 223 .WillOnce(WithoutArgs(Invoke( 224 reinterpret_cast<MockServerConnection*>(session1_->connection()), 225 &MockServerConnection::UnregisterOnConnectionClose))); 226 EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()), 227 ProcessUdpPacket(_, _, _)) 228 .WillOnce(Invoke( 229 reinterpret_cast<MockConnection*>(session1_->connection()), 230 &MockConnection::ReallyProcessUdpPacket)); 231 dispatcher_.ProcessPacket(IPEndPoint(), addr, guid, *encrypted); 232 EXPECT_TRUE(time_wait_list_manager->IsGuidInTimeWait(guid)); 233 234 // Dispatcher forwards subsequent packets for this guid to the time wait list 235 // manager. 236 EXPECT_CALL(*time_wait_list_manager, ProcessPacket(_, _, guid, _)).Times(1); 237 ProcessPacket(addr, guid, "foo"); 238 } 239 240 class WriteBlockedListTest : public QuicDispatcherTest { 241 public: 242 virtual void SetUp() { 243 IPEndPoint addr(Loopback4(), 1); 244 245 EXPECT_CALL(dispatcher_, CreateQuicSession(_, addr, _, &eps_)) 246 .WillOnce(testing::Return(CreateSession( 247 &dispatcher_, 1, addr, &session1_, &eps_))); 248 ProcessPacket(addr, 1, "foo"); 249 250 EXPECT_CALL(dispatcher_, CreateQuicSession(_, addr, _, &eps_)) 251 .WillOnce(testing::Return(CreateSession( 252 &dispatcher_, 2, addr, &session2_, &eps_))); 253 ProcessPacket(addr, 2, "bar"); 254 255 blocked_list_ = dispatcher_.write_blocked_list(); 256 } 257 258 virtual void TearDown() { 259 EXPECT_CALL(*connection1(), SendConnectionClose(QUIC_PEER_GOING_AWAY)); 260 EXPECT_CALL(*connection2(), SendConnectionClose(QUIC_PEER_GOING_AWAY)); 261 dispatcher_.Shutdown(); 262 } 263 264 bool SetBlocked() { 265 QuicDispatcherPeer::SetWriteBlocked(&dispatcher_); 266 return true; 267 } 268 269 protected: 270 QuicDispatcher::WriteBlockedList* blocked_list_; 271 }; 272 273 TEST_F(WriteBlockedListTest, BasicOnCanWrite) { 274 // No OnCanWrite calls because no connections are blocked. 275 dispatcher_.OnCanWrite(); 276 277 // Register connection 1 for events, and make sure it's nofitied. 278 blocked_list_->AddBlockedObject(connection1()); 279 EXPECT_CALL(*connection1(), OnCanWrite()); 280 dispatcher_.OnCanWrite(); 281 282 // It should get only one notification. 283 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0); 284 EXPECT_FALSE(dispatcher_.OnCanWrite()); 285 } 286 287 TEST_F(WriteBlockedListTest, OnCanWriteOrder) { 288 // Make sure we handle events in order. 289 InSequence s; 290 blocked_list_->AddBlockedObject(connection1()); 291 blocked_list_->AddBlockedObject(connection2()); 292 EXPECT_CALL(*connection1(), OnCanWrite()); 293 EXPECT_CALL(*connection2(), OnCanWrite()); 294 dispatcher_.OnCanWrite(); 295 296 // Check the other ordering. 297 blocked_list_->AddBlockedObject(connection2()); 298 blocked_list_->AddBlockedObject(connection1()); 299 EXPECT_CALL(*connection2(), OnCanWrite()); 300 EXPECT_CALL(*connection1(), OnCanWrite()); 301 dispatcher_.OnCanWrite(); 302 } 303 304 TEST_F(WriteBlockedListTest, OnCanWriteRemove) { 305 // Add and remove one connction. 306 blocked_list_->AddBlockedObject(connection1()); 307 blocked_list_->RemoveBlockedObject(connection1()); 308 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0); 309 dispatcher_.OnCanWrite(); 310 311 // Add and remove one connction and make sure it doesn't affect others. 312 blocked_list_->AddBlockedObject(connection1()); 313 blocked_list_->AddBlockedObject(connection2()); 314 blocked_list_->RemoveBlockedObject(connection1()); 315 EXPECT_CALL(*connection2(), OnCanWrite()); 316 dispatcher_.OnCanWrite(); 317 318 // Add it, remove it, and add it back and make sure things are OK. 319 blocked_list_->AddBlockedObject(connection1()); 320 blocked_list_->RemoveBlockedObject(connection1()); 321 blocked_list_->AddBlockedObject(connection1()); 322 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1); 323 dispatcher_.OnCanWrite(); 324 } 325 326 TEST_F(WriteBlockedListTest, DoubleAdd) { 327 // Make sure a double add does not necessitate a double remove. 328 blocked_list_->AddBlockedObject(connection1()); 329 blocked_list_->AddBlockedObject(connection1()); 330 blocked_list_->RemoveBlockedObject(connection1()); 331 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0); 332 dispatcher_.OnCanWrite(); 333 334 // Make sure a double add does not result in two OnCanWrite calls. 335 blocked_list_->AddBlockedObject(connection1()); 336 blocked_list_->AddBlockedObject(connection1()); 337 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1); 338 dispatcher_.OnCanWrite(); 339 } 340 341 TEST_F(WriteBlockedListTest, OnCanWriteHandleBlock) { 342 // Finally make sure if we write block on a write call, we stop calling. 343 InSequence s; 344 blocked_list_->AddBlockedObject(connection1()); 345 blocked_list_->AddBlockedObject(connection2()); 346 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce( 347 Invoke(this, &WriteBlockedListTest::SetBlocked)); 348 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0); 349 dispatcher_.OnCanWrite(); 350 351 // And we'll resume where we left off when we get another call. 352 EXPECT_CALL(*connection2(), OnCanWrite()); 353 dispatcher_.OnCanWrite(); 354 } 355 356 TEST_F(WriteBlockedListTest, LimitedWrites) { 357 // Make sure we call both writers. The first will register for more writing 358 // but should not be immediately called due to limits. 359 InSequence s; 360 blocked_list_->AddBlockedObject(connection1()); 361 blocked_list_->AddBlockedObject(connection2()); 362 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(Return(true)); 363 EXPECT_CALL(*connection2(), OnCanWrite()).WillOnce(Return(false)); 364 dispatcher_.OnCanWrite(); 365 366 // Now call OnCanWrite again, and connection1 should get its second chance 367 EXPECT_CALL(*connection1(), OnCanWrite()); 368 dispatcher_.OnCanWrite(); 369 } 370 371 TEST_F(WriteBlockedListTest, TestWriteLimits) { 372 // Finally make sure if we write block on a write call, we stop calling. 373 InSequence s; 374 blocked_list_->AddBlockedObject(connection1()); 375 blocked_list_->AddBlockedObject(connection2()); 376 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce( 377 Invoke(this, &WriteBlockedListTest::SetBlocked)); 378 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0); 379 dispatcher_.OnCanWrite(); 380 381 // And we'll resume where we left off when we get another call. 382 EXPECT_CALL(*connection2(), OnCanWrite()); 383 dispatcher_.OnCanWrite(); 384 } 385 386 387 } // namespace 388 } // namespace test 389 } // namespace tools 390 } // namespace net 391