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/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
, 1, eps
) {}
46 MOCK_METHOD4(CreateQuicSession
, QuicSession
*(
48 const IPEndPoint
& client_address
,
51 using QuicDispatcher::write_blocked_list
;
54 // A Connection class which unregisters the session from the dispatcher
55 // when sending connection close.
56 // It'd be slightly more realistic to do this from the Session but it would
57 // involve a lot more mocking.
58 class MockServerConnection
: public MockConnection
{
60 MockServerConnection(QuicGuid guid
,
64 QuicDispatcher
* dispatcher
)
65 : MockConnection(guid
, address
, fd
, eps
, true),
66 dispatcher_(dispatcher
) {
68 void UnregisterOnConnectionClose() {
69 LOG(ERROR
) << "Unregistering " << guid();
70 dispatcher_
->OnConnectionClose(guid(), QUIC_NO_ERROR
);
73 QuicDispatcher
* dispatcher_
;
76 QuicSession
* CreateSession(QuicDispatcher
* dispatcher
,
78 const IPEndPoint
& addr
,
79 MockSession
** session
,
81 MockServerConnection
* connection
=
82 new MockServerConnection(guid
, addr
, 0, eps
, dispatcher
);
83 *session
= new MockSession(connection
, true);
84 ON_CALL(*connection
, SendConnectionClose(_
)).WillByDefault(
86 connection
, &MockServerConnection::UnregisterOnConnectionClose
)));
87 EXPECT_CALL(*reinterpret_cast<MockConnection
*>((*session
)->connection()),
88 ProcessUdpPacket(_
, addr
, _
));
93 class QuicDispatcherTest
: public ::testing::Test
{
96 : crypto_config_(QuicCryptoServerConfig::TESTING
,
97 QuicRandom::GetInstance()),
98 dispatcher_(config_
, crypto_config_
, &eps_
),
103 virtual ~QuicDispatcherTest() {}
105 MockConnection
* connection1() {
106 return reinterpret_cast<MockConnection
*>(session1_
->connection());
109 MockConnection
* connection2() {
110 return reinterpret_cast<MockConnection
*>(session2_
->connection());
113 void ProcessPacket(IPEndPoint addr
,
115 const string
& data
) {
116 QuicEncryptedPacket
packet(data
.data(), data
.length());
117 dispatcher_
.ProcessPacket(IPEndPoint(), addr
, guid
, packet
);
120 void ValidatePacket(const QuicEncryptedPacket
& packet
) {
121 EXPECT_TRUE(packet
.AsStringPiece().find(data_
) != StringPiece::npos
);
124 IPAddressNumber
Loopback4() {
125 net::IPAddressNumber addr
;
126 CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &addr
));
132 QuicCryptoServerConfig crypto_config_
;
133 TestDispatcher dispatcher_
;
134 MockSession
* session1_
;
135 MockSession
* session2_
;
139 TEST_F(QuicDispatcherTest
, ProcessPackets
) {
140 IPEndPoint
addr(Loopback4(), 1);
142 EXPECT_CALL(dispatcher_
, CreateQuicSession(1, addr
, _
, &eps_
))
143 .WillOnce(testing::Return(CreateSession(
144 &dispatcher_
, 1, addr
, &session1_
, &eps_
)));
145 ProcessPacket(addr
, 1, "foo");
147 EXPECT_CALL(dispatcher_
, CreateQuicSession(2, addr
, _
, &eps_
))
148 .WillOnce(testing::Return(CreateSession(
149 &dispatcher_
, 2, addr
, &session2_
, &eps_
)));
150 ProcessPacket(addr
, 2, "bar");
153 EXPECT_CALL(*reinterpret_cast<MockConnection
*>(session1_
->connection()),
154 ProcessUdpPacket(_
, _
, _
)).Times(1).
155 WillOnce(testing::WithArgs
<2>(Invoke(
156 this, &QuicDispatcherTest::ValidatePacket
)));
157 ProcessPacket(addr
, 1, "eep");
160 TEST_F(QuicDispatcherTest
, Shutdown
) {
161 IPEndPoint
addr(Loopback4(), 1);
163 EXPECT_CALL(dispatcher_
, CreateQuicSession(_
, addr
, _
, &eps_
))
164 .WillOnce(testing::Return(CreateSession(
165 &dispatcher_
, 1, addr
, &session1_
, &eps_
)));
167 ProcessPacket(addr
, 1, "foo");
169 EXPECT_CALL(*reinterpret_cast<MockConnection
*>(session1_
->connection()),
170 SendConnectionClose(QUIC_PEER_GOING_AWAY
));
172 dispatcher_
.Shutdown();
175 class MockTimeWaitListManager
: public QuicTimeWaitListManager
{
177 MockTimeWaitListManager(QuicPacketWriter
* writer
,
179 : QuicTimeWaitListManager(writer
, eps
) {
182 MOCK_METHOD4(ProcessPacket
, void(const IPEndPoint
& server_address
,
183 const IPEndPoint
& client_address
,
185 const QuicEncryptedPacket
& packet
));
188 TEST_F(QuicDispatcherTest
, TimeWaitListManager
) {
189 MockTimeWaitListManager
* time_wait_list_manager
=
190 new MockTimeWaitListManager(
191 QuicDispatcherPeer::GetWriter(&dispatcher_
), &eps_
);
192 // dispatcher takes the ownership of time_wait_list_manager.
193 QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_
,
194 time_wait_list_manager
);
195 // Create a new session.
196 IPEndPoint
addr(Loopback4(), 1);
198 EXPECT_CALL(dispatcher_
, CreateQuicSession(guid
, addr
, _
, &eps_
))
199 .WillOnce(testing::Return(CreateSession(
200 &dispatcher_
, guid
, addr
, &session1_
, &eps_
)));
201 ProcessPacket(addr
, guid
, "foo");
203 // Close the connection by sending public reset packet.
204 QuicPublicResetPacket packet
;
205 packet
.public_header
.guid
= guid
;
206 packet
.public_header
.reset_flag
= true;
207 packet
.public_header
.version_flag
= false;
208 packet
.rejected_sequence_number
= 19191;
209 packet
.nonce_proof
= 132232;
210 scoped_ptr
<QuicEncryptedPacket
> encrypted(
211 QuicFramer::BuildPublicResetPacket(packet
));
212 EXPECT_CALL(*session1_
, ConnectionClose(QUIC_PUBLIC_RESET
, true)).Times(1)
213 .WillOnce(WithoutArgs(Invoke(
214 reinterpret_cast<MockServerConnection
*>(session1_
->connection()),
215 &MockServerConnection::UnregisterOnConnectionClose
)));
216 EXPECT_CALL(*reinterpret_cast<MockConnection
*>(session1_
->connection()),
217 ProcessUdpPacket(_
, _
, _
))
219 reinterpret_cast<MockConnection
*>(session1_
->connection()),
220 &MockConnection::ReallyProcessUdpPacket
));
221 dispatcher_
.ProcessPacket(IPEndPoint(), addr
, guid
, *encrypted
);
222 EXPECT_TRUE(time_wait_list_manager
->IsGuidInTimeWait(guid
));
224 // Dispatcher forwards subsequent packets for this guid to the time wait list
226 EXPECT_CALL(*time_wait_list_manager
, ProcessPacket(_
, _
, guid
, _
)).Times(1);
227 ProcessPacket(addr
, guid
, "foo");
230 class QuicWriteBlockedListTest
: public QuicDispatcherTest
{
232 virtual void SetUp() {
233 IPEndPoint
addr(Loopback4(), 1);
235 EXPECT_CALL(dispatcher_
, CreateQuicSession(_
, addr
, _
, &eps_
))
236 .WillOnce(testing::Return(CreateSession(
237 &dispatcher_
, 1, addr
, &session1_
, &eps_
)));
238 ProcessPacket(addr
, 1, "foo");
240 EXPECT_CALL(dispatcher_
, CreateQuicSession(_
, addr
, _
, &eps_
))
241 .WillOnce(testing::Return(CreateSession(
242 &dispatcher_
, 2, addr
, &session2_
, &eps_
)));
243 ProcessPacket(addr
, 2, "bar");
245 blocked_list_
= dispatcher_
.write_blocked_list();
248 virtual void TearDown() {
249 EXPECT_CALL(*connection1(), SendConnectionClose(QUIC_PEER_GOING_AWAY
));
250 EXPECT_CALL(*connection2(), SendConnectionClose(QUIC_PEER_GOING_AWAY
));
251 dispatcher_
.Shutdown();
255 QuicDispatcherPeer::SetWriteBlocked(&dispatcher_
);
260 QuicDispatcher::WriteBlockedList
* blocked_list_
;
263 TEST_F(QuicWriteBlockedListTest
, BasicOnCanWrite
) {
264 // No OnCanWrite calls because no connections are blocked.
265 dispatcher_
.OnCanWrite();
267 // Register connection 1 for events, and make sure it's nofitied.
268 blocked_list_
->insert(make_pair(connection1(), true));
269 EXPECT_CALL(*connection1(), OnCanWrite());
270 dispatcher_
.OnCanWrite();
272 // It should get only one notification.
273 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
274 EXPECT_FALSE(dispatcher_
.OnCanWrite());
277 TEST_F(QuicWriteBlockedListTest
, OnCanWriteOrder
) {
278 // Make sure we handle events in order.
280 blocked_list_
->insert(make_pair(connection1(), true));
281 blocked_list_
->insert(make_pair(connection2(), true));
282 EXPECT_CALL(*connection1(), OnCanWrite());
283 EXPECT_CALL(*connection2(), OnCanWrite());
284 dispatcher_
.OnCanWrite();
286 // Check the other ordering.
287 blocked_list_
->insert(make_pair(connection2(), true));
288 blocked_list_
->insert(make_pair(connection1(), true));
289 EXPECT_CALL(*connection2(), OnCanWrite());
290 EXPECT_CALL(*connection1(), OnCanWrite());
291 dispatcher_
.OnCanWrite();
294 TEST_F(QuicWriteBlockedListTest
, OnCanWriteRemove
) {
295 // Add and remove one connction.
296 blocked_list_
->insert(make_pair(connection1(), true));
297 blocked_list_
->erase(connection1());
298 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
299 dispatcher_
.OnCanWrite();
301 // Add and remove one connction and make sure it doesn't affect others.
302 blocked_list_
->insert(make_pair(connection1(), true));
303 blocked_list_
->insert(make_pair(connection2(), true));
304 blocked_list_
->erase(connection1());
305 EXPECT_CALL(*connection2(), OnCanWrite());
306 dispatcher_
.OnCanWrite();
308 // Add it, remove it, and add it back and make sure things are OK.
309 blocked_list_
->insert(make_pair(connection1(), true));
310 blocked_list_
->erase(connection1());
311 blocked_list_
->insert(make_pair(connection1(), true));
312 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
313 dispatcher_
.OnCanWrite();
316 TEST_F(QuicWriteBlockedListTest
, DoubleAdd
) {
317 // Make sure a double add does not necessitate a double remove.
318 blocked_list_
->insert(make_pair(connection1(), true));
319 blocked_list_
->insert(make_pair(connection1(), true));
320 blocked_list_
->erase(connection1());
321 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
322 dispatcher_
.OnCanWrite();
324 // Make sure a double add does not result in two OnCanWrite calls.
325 blocked_list_
->insert(make_pair(connection1(), true));
326 blocked_list_
->insert(make_pair(connection1(), true));
327 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
328 dispatcher_
.OnCanWrite();
331 TEST_F(QuicWriteBlockedListTest
, OnCanWriteHandleBlock
) {
332 // Finally make sure if we write block on a write call, we stop calling.
334 blocked_list_
->insert(make_pair(connection1(), true));
335 blocked_list_
->insert(make_pair(connection2(), true));
336 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
337 Invoke(this, &QuicWriteBlockedListTest::SetBlocked
));
338 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
339 dispatcher_
.OnCanWrite();
341 // And we'll resume where we left off when we get another call.
342 EXPECT_CALL(*connection2(), OnCanWrite());
343 dispatcher_
.OnCanWrite();
346 TEST_F(QuicWriteBlockedListTest
, LimitedWrites
) {
347 // Make sure we call both writers. The first will register for more writing
348 // but should not be immediately called due to limits.
350 blocked_list_
->insert(make_pair(connection1(), true));
351 blocked_list_
->insert(make_pair(connection2(), true));
352 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(Return(true));
353 EXPECT_CALL(*connection2(), OnCanWrite()).WillOnce(Return(false));
354 dispatcher_
.OnCanWrite();
356 // Now call OnCanWrite again, and connection1 should get its second chance
357 EXPECT_CALL(*connection1(), OnCanWrite());
358 dispatcher_
.OnCanWrite();
361 TEST_F(QuicWriteBlockedListTest
, TestWriteLimits
) {
362 // Finally make sure if we write block on a write call, we stop calling.
364 blocked_list_
->insert(make_pair(connection1(), true));
365 blocked_list_
->insert(make_pair(connection2(), true));
366 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
367 Invoke(this, &QuicWriteBlockedListTest::SetBlocked
));
368 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
369 dispatcher_
.OnCanWrite();
371 // And we'll resume where we left off when we get another call.
372 EXPECT_CALL(*connection2(), OnCanWrite());
373 dispatcher_
.OnCanWrite();