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.
5 #include "net/tools/quic/quic_dispatcher.h"
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/test_tools/quic_test_utils.h"
15 #include "net/tools/epoll_server/epoll_server.h"
16 #include "net/tools/quic/quic_time_wait_list_manager.h"
17 #include "net/tools/quic/test_tools/quic_dispatcher_peer.h"
18 #include "net/tools/quic/test_tools/quic_test_utils.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 using base::StringPiece;
23 using net::EpollServer;
24 using net::test::MockSession;
25 using net::tools::test::MockConnection;
29 using testing::Invoke;
30 using testing::InSequence;
31 using testing::Return;
32 using testing::WithoutArgs;
39 class TestDispatcher : public QuicDispatcher {
41 explicit TestDispatcher(const QuicConfig& config,
42 const QuicCryptoServerConfig& crypto_config,
44 : QuicDispatcher(config, crypto_config, QuicSupportedVersions(), 1, eps) {
47 MOCK_METHOD2(CreateQuicSession, QuicSession*(
49 const IPEndPoint& client_address));
50 using QuicDispatcher::write_blocked_list;
53 // A Connection class which unregisters the session from the dispatcher
54 // when sending connection close.
55 // It'd be slightly more realistic to do this from the Session but it would
56 // involve a lot more mocking.
57 class MockServerConnection : public MockConnection {
59 MockServerConnection(QuicGuid guid,
63 QuicDispatcher* dispatcher)
64 : MockConnection(guid, address, fd, eps, true),
65 dispatcher_(dispatcher) {
67 void UnregisterOnConnectionClosed() {
68 LOG(ERROR) << "Unregistering " << guid();
69 dispatcher_->OnConnectionClosed(guid(), QUIC_NO_ERROR);
72 QuicDispatcher* dispatcher_;
75 QuicSession* CreateSession(QuicDispatcher* dispatcher,
77 const IPEndPoint& addr,
78 MockSession** session,
80 MockServerConnection* connection =
81 new MockServerConnection(guid, addr, 0, eps, dispatcher);
82 *session = new MockSession(connection, true);
83 ON_CALL(*connection, SendConnectionClose(_)).WillByDefault(
85 connection, &MockServerConnection::UnregisterOnConnectionClosed)));
86 EXPECT_CALL(*reinterpret_cast<MockConnection*>((*session)->connection()),
87 ProcessUdpPacket(_, addr, _));
92 class QuicDispatcherTest : public ::testing::Test {
95 : crypto_config_(QuicCryptoServerConfig::TESTING,
96 QuicRandom::GetInstance()),
97 dispatcher_(config_, crypto_config_, &eps_),
102 virtual ~QuicDispatcherTest() {}
104 MockConnection* connection1() {
105 return reinterpret_cast<MockConnection*>(session1_->connection());
108 MockConnection* connection2() {
109 return reinterpret_cast<MockConnection*>(session2_->connection());
112 void ProcessPacket(IPEndPoint addr,
114 const string& data) {
115 QuicEncryptedPacket packet(data.data(), data.length());
116 dispatcher_.ProcessPacket(IPEndPoint(), addr, guid, packet);
119 void ValidatePacket(const QuicEncryptedPacket& packet) {
120 EXPECT_TRUE(packet.AsStringPiece().find(data_) != StringPiece::npos);
123 IPAddressNumber Loopback4() {
124 net::IPAddressNumber addr;
125 CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &addr));
131 QuicCryptoServerConfig crypto_config_;
132 TestDispatcher dispatcher_;
133 MockSession* session1_;
134 MockSession* session2_;
138 TEST_F(QuicDispatcherTest, ProcessPackets) {
139 IPEndPoint addr(Loopback4(), 1);
141 EXPECT_CALL(dispatcher_, CreateQuicSession(1, addr))
142 .WillOnce(testing::Return(CreateSession(
143 &dispatcher_, 1, addr, &session1_, &eps_)));
144 ProcessPacket(addr, 1, "foo");
146 EXPECT_CALL(dispatcher_, CreateQuicSession(2, addr))
147 .WillOnce(testing::Return(CreateSession(
148 &dispatcher_, 2, addr, &session2_, &eps_)));
149 ProcessPacket(addr, 2, "bar");
152 EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
153 ProcessUdpPacket(_, _, _)).Times(1).
154 WillOnce(testing::WithArgs<2>(Invoke(
155 this, &QuicDispatcherTest::ValidatePacket)));
156 ProcessPacket(addr, 1, "eep");
159 TEST_F(QuicDispatcherTest, Shutdown) {
160 IPEndPoint addr(Loopback4(), 1);
162 EXPECT_CALL(dispatcher_, CreateQuicSession(_, addr))
163 .WillOnce(testing::Return(CreateSession(
164 &dispatcher_, 1, addr, &session1_, &eps_)));
166 ProcessPacket(addr, 1, "foo");
168 EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
169 SendConnectionClose(QUIC_PEER_GOING_AWAY));
171 dispatcher_.Shutdown();
174 class MockTimeWaitListManager : public QuicTimeWaitListManager {
176 MockTimeWaitListManager(QuicPacketWriter* writer,
178 : QuicTimeWaitListManager(writer, eps, QuicSupportedVersions()) {
181 MOCK_METHOD4(ProcessPacket, void(const IPEndPoint& server_address,
182 const IPEndPoint& client_address,
184 const QuicEncryptedPacket& packet));
187 TEST_F(QuicDispatcherTest, TimeWaitListManager) {
188 MockTimeWaitListManager* time_wait_list_manager =
189 new MockTimeWaitListManager(
190 QuicDispatcherPeer::GetWriter(&dispatcher_), &eps_);
191 // dispatcher takes the ownership of time_wait_list_manager.
192 QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
193 time_wait_list_manager);
194 // Create a new session.
195 IPEndPoint addr(Loopback4(), 1);
197 EXPECT_CALL(dispatcher_, CreateQuicSession(guid, addr))
198 .WillOnce(testing::Return(CreateSession(
199 &dispatcher_, guid, addr, &session1_, &eps_)));
200 ProcessPacket(addr, guid, "foo");
202 // Close the connection by sending public reset packet.
203 QuicPublicResetPacket packet;
204 packet.public_header.guid = guid;
205 packet.public_header.reset_flag = true;
206 packet.public_header.version_flag = false;
207 packet.rejected_sequence_number = 19191;
208 packet.nonce_proof = 132232;
209 scoped_ptr<QuicEncryptedPacket> encrypted(
210 QuicFramer::BuildPublicResetPacket(packet));
211 EXPECT_CALL(*session1_, OnConnectionClosed(QUIC_PUBLIC_RESET, true)).Times(1)
212 .WillOnce(WithoutArgs(Invoke(
213 reinterpret_cast<MockServerConnection*>(session1_->connection()),
214 &MockServerConnection::UnregisterOnConnectionClosed)));
215 EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
216 ProcessUdpPacket(_, _, _))
218 reinterpret_cast<MockConnection*>(session1_->connection()),
219 &MockConnection::ReallyProcessUdpPacket));
220 dispatcher_.ProcessPacket(IPEndPoint(), addr, guid, *encrypted);
221 EXPECT_TRUE(time_wait_list_manager->IsGuidInTimeWait(guid));
223 // Dispatcher forwards subsequent packets for this guid to the time wait list
225 EXPECT_CALL(*time_wait_list_manager, ProcessPacket(_, _, guid, _)).Times(1);
226 ProcessPacket(addr, guid, "foo");
229 class QuicWriteBlockedListTest : public QuicDispatcherTest {
231 virtual void SetUp() {
232 IPEndPoint addr(Loopback4(), 1);
234 EXPECT_CALL(dispatcher_, CreateQuicSession(_, addr))
235 .WillOnce(testing::Return(CreateSession(
236 &dispatcher_, 1, addr, &session1_, &eps_)));
237 ProcessPacket(addr, 1, "foo");
239 EXPECT_CALL(dispatcher_, CreateQuicSession(_, addr))
240 .WillOnce(testing::Return(CreateSession(
241 &dispatcher_, 2, addr, &session2_, &eps_)));
242 ProcessPacket(addr, 2, "bar");
244 blocked_list_ = dispatcher_.write_blocked_list();
247 virtual void TearDown() {
248 EXPECT_CALL(*connection1(), SendConnectionClose(QUIC_PEER_GOING_AWAY));
249 EXPECT_CALL(*connection2(), SendConnectionClose(QUIC_PEER_GOING_AWAY));
250 dispatcher_.Shutdown();
254 QuicDispatcherPeer::SetWriteBlocked(&dispatcher_);
259 QuicDispatcher::WriteBlockedList* blocked_list_;
262 TEST_F(QuicWriteBlockedListTest, BasicOnCanWrite) {
263 // No OnCanWrite calls because no connections are blocked.
264 dispatcher_.OnCanWrite();
266 // Register connection 1 for events, and make sure it's nofitied.
267 blocked_list_->insert(make_pair(connection1(), true));
268 EXPECT_CALL(*connection1(), OnCanWrite());
269 dispatcher_.OnCanWrite();
271 // It should get only one notification.
272 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
273 EXPECT_FALSE(dispatcher_.OnCanWrite());
276 TEST_F(QuicWriteBlockedListTest, OnCanWriteOrder) {
277 // Make sure we handle events in order.
279 blocked_list_->insert(make_pair(connection1(), true));
280 blocked_list_->insert(make_pair(connection2(), true));
281 EXPECT_CALL(*connection1(), OnCanWrite());
282 EXPECT_CALL(*connection2(), OnCanWrite());
283 dispatcher_.OnCanWrite();
285 // Check the other ordering.
286 blocked_list_->insert(make_pair(connection2(), true));
287 blocked_list_->insert(make_pair(connection1(), true));
288 EXPECT_CALL(*connection2(), OnCanWrite());
289 EXPECT_CALL(*connection1(), OnCanWrite());
290 dispatcher_.OnCanWrite();
293 TEST_F(QuicWriteBlockedListTest, OnCanWriteRemove) {
294 // Add and remove one connction.
295 blocked_list_->insert(make_pair(connection1(), true));
296 blocked_list_->erase(connection1());
297 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
298 dispatcher_.OnCanWrite();
300 // Add and remove one connction and make sure it doesn't affect others.
301 blocked_list_->insert(make_pair(connection1(), true));
302 blocked_list_->insert(make_pair(connection2(), true));
303 blocked_list_->erase(connection1());
304 EXPECT_CALL(*connection2(), OnCanWrite());
305 dispatcher_.OnCanWrite();
307 // Add it, remove it, and add it back and make sure things are OK.
308 blocked_list_->insert(make_pair(connection1(), true));
309 blocked_list_->erase(connection1());
310 blocked_list_->insert(make_pair(connection1(), true));
311 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
312 dispatcher_.OnCanWrite();
315 TEST_F(QuicWriteBlockedListTest, DoubleAdd) {
316 // Make sure a double add does not necessitate a double remove.
317 blocked_list_->insert(make_pair(connection1(), true));
318 blocked_list_->insert(make_pair(connection1(), true));
319 blocked_list_->erase(connection1());
320 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
321 dispatcher_.OnCanWrite();
323 // Make sure a double add does not result in two OnCanWrite calls.
324 blocked_list_->insert(make_pair(connection1(), true));
325 blocked_list_->insert(make_pair(connection1(), true));
326 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
327 dispatcher_.OnCanWrite();
330 TEST_F(QuicWriteBlockedListTest, OnCanWriteHandleBlock) {
331 // Finally make sure if we write block on a write call, we stop calling.
333 blocked_list_->insert(make_pair(connection1(), true));
334 blocked_list_->insert(make_pair(connection2(), true));
335 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
336 Invoke(this, &QuicWriteBlockedListTest::SetBlocked));
337 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
338 dispatcher_.OnCanWrite();
340 // And we'll resume where we left off when we get another call.
341 EXPECT_CALL(*connection2(), OnCanWrite());
342 dispatcher_.OnCanWrite();
345 TEST_F(QuicWriteBlockedListTest, LimitedWrites) {
346 // Make sure we call both writers. The first will register for more writing
347 // but should not be immediately called due to limits.
349 blocked_list_->insert(make_pair(connection1(), true));
350 blocked_list_->insert(make_pair(connection2(), true));
351 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(Return(true));
352 EXPECT_CALL(*connection2(), OnCanWrite()).WillOnce(Return(false));
353 dispatcher_.OnCanWrite();
355 // Now call OnCanWrite again, and connection1 should get its second chance
356 EXPECT_CALL(*connection1(), OnCanWrite());
357 dispatcher_.OnCanWrite();
360 TEST_F(QuicWriteBlockedListTest, TestWriteLimits) {
361 // Finally make sure if we write block on a write call, we stop calling.
363 blocked_list_->insert(make_pair(connection1(), true));
364 blocked_list_->insert(make_pair(connection2(), true));
365 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
366 Invoke(this, &QuicWriteBlockedListTest::SetBlocked));
367 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
368 dispatcher_.OnCanWrite();
370 // And we'll resume where we left off when we get another call.
371 EXPECT_CALL(*connection2(), OnCanWrite());
372 dispatcher_.OnCanWrite();