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/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"
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
;
34 using testing::InSequence
;
35 using testing::Invoke
;
36 using testing::WithoutArgs
;
44 class TestDispatcher
: public QuicDispatcher
{
46 explicit TestDispatcher(const QuicConfig
& config
,
47 const QuicCryptoServerConfig
& crypto_config
,
49 : QuicDispatcher(config
,
51 QuicSupportedVersions(),
52 new QuicDispatcher::DefaultPacketWriterFactory(),
56 MOCK_METHOD3(CreateQuicSession
, QuicSession
*(
57 QuicConnectionId connection_id
,
58 const IPEndPoint
& server_address
,
59 const IPEndPoint
& client_address
));
61 using QuicDispatcher::current_server_address
;
62 using QuicDispatcher::current_client_address
;
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
{
71 MockServerConnection(QuicConnectionId connection_id
,
72 QuicDispatcher
* dispatcher
)
73 : MockConnection(connection_id
, true),
74 dispatcher_(dispatcher
) {}
76 void UnregisterOnConnectionClosed() {
77 LOG(ERROR
) << "Unregistering " << connection_id();
78 dispatcher_
->OnConnectionClosed(connection_id(), QUIC_NO_ERROR
);
81 QuicDispatcher
* dispatcher_
;
84 QuicSession
* CreateSession(QuicDispatcher
* dispatcher
,
85 QuicConnectionId connection_id
,
86 const IPEndPoint
& client_address
,
87 MockSession
** session
) {
88 MockServerConnection
* connection
=
89 new MockServerConnection(connection_id
, dispatcher
);
90 *session
= new MockSession(connection
);
91 ON_CALL(*connection
, SendConnectionClose(_
)).WillByDefault(
93 connection
, &MockServerConnection::UnregisterOnConnectionClosed
)));
94 EXPECT_CALL(*reinterpret_cast<MockConnection
*>((*session
)->connection()),
95 ProcessUdpPacket(_
, client_address
, _
));
100 class QuicDispatcherTest
: public ::testing::Test
{
103 : crypto_config_(QuicCryptoServerConfig::TESTING
,
104 QuicRandom::GetInstance()),
105 dispatcher_(config_
, crypto_config_
, &eps_
),
108 dispatcher_
.Initialize(1);
111 ~QuicDispatcherTest() override
{}
113 MockConnection
* connection1() {
114 return reinterpret_cast<MockConnection
*>(session1_
->connection());
117 MockConnection
* connection2() {
118 return reinterpret_cast<MockConnection
*>(session2_
->connection());
121 void ProcessPacket(IPEndPoint client_address
,
122 QuicConnectionId connection_id
,
123 bool has_version_flag
,
124 const string
& data
) {
125 scoped_ptr
<QuicEncryptedPacket
> packet(ConstructEncryptedPacket(
126 connection_id
, has_version_flag
, false, 1, data
));
127 data_
= string(packet
->data(), packet
->length());
128 dispatcher_
.ProcessPacket(server_address_
, client_address
, *packet
);
131 void ValidatePacket(const QuicEncryptedPacket
& packet
) {
132 EXPECT_EQ(data_
.length(), packet
.AsStringPiece().length());
133 EXPECT_EQ(data_
, packet
.AsStringPiece());
138 QuicCryptoServerConfig crypto_config_
;
139 IPEndPoint server_address_
;
140 TestDispatcher dispatcher_
;
141 MockSession
* session1_
;
142 MockSession
* session2_
;
146 TEST_F(QuicDispatcherTest
, ProcessPackets
) {
147 IPEndPoint
client_address(net::test::Loopback4(), 1);
148 IPAddressNumber any4
;
149 CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &any4
));
150 server_address_
= IPEndPoint(any4
, 5);
152 EXPECT_CALL(dispatcher_
, CreateQuicSession(1, _
, client_address
))
153 .WillOnce(testing::Return(CreateSession(
154 &dispatcher_
, 1, client_address
, &session1_
)));
155 ProcessPacket(client_address
, 1, true, "foo");
156 EXPECT_EQ(client_address
, dispatcher_
.current_client_address());
157 EXPECT_EQ(server_address_
, dispatcher_
.current_server_address());
160 EXPECT_CALL(dispatcher_
, CreateQuicSession(2, _
, client_address
))
161 .WillOnce(testing::Return(CreateSession(
162 &dispatcher_
, 2, client_address
, &session2_
)));
163 ProcessPacket(client_address
, 2, true, "bar");
165 EXPECT_CALL(*reinterpret_cast<MockConnection
*>(session1_
->connection()),
166 ProcessUdpPacket(_
, _
, _
)).Times(1).
167 WillOnce(testing::WithArgs
<2>(Invoke(
168 this, &QuicDispatcherTest::ValidatePacket
)));
169 ProcessPacket(client_address
, 1, false, "eep");
172 TEST_F(QuicDispatcherTest
, Shutdown
) {
173 IPEndPoint
client_address(net::test::Loopback4(), 1);
175 EXPECT_CALL(dispatcher_
, CreateQuicSession(_
, _
, client_address
))
176 .WillOnce(testing::Return(CreateSession(
177 &dispatcher_
, 1, client_address
, &session1_
)));
179 ProcessPacket(client_address
, 1, true, "foo");
181 EXPECT_CALL(*reinterpret_cast<MockConnection
*>(session1_
->connection()),
182 SendConnectionClose(QUIC_PEER_GOING_AWAY
));
184 dispatcher_
.Shutdown();
187 class MockTimeWaitListManager
: public QuicTimeWaitListManager
{
189 MockTimeWaitListManager(QuicPacketWriter
* writer
,
190 QuicServerSessionVisitor
* visitor
,
192 : QuicTimeWaitListManager(writer
, visitor
, eps
, QuicSupportedVersions()) {
195 MOCK_METHOD5(ProcessPacket
, void(const IPEndPoint
& server_address
,
196 const IPEndPoint
& client_address
,
197 QuicConnectionId connection_id
,
198 QuicPacketSequenceNumber sequence_number
,
199 const QuicEncryptedPacket
& packet
));
202 TEST_F(QuicDispatcherTest
, TimeWaitListManager
) {
203 MockTimeWaitListManager
* time_wait_list_manager
=
204 new MockTimeWaitListManager(
205 QuicDispatcherPeer::GetWriter(&dispatcher_
), &dispatcher_
, &eps_
);
206 // dispatcher takes the ownership of time_wait_list_manager.
207 QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_
,
208 time_wait_list_manager
);
209 // Create a new session.
210 IPEndPoint
client_address(net::test::Loopback4(), 1);
211 QuicConnectionId connection_id
= 1;
212 EXPECT_CALL(dispatcher_
, CreateQuicSession(connection_id
, _
, client_address
))
213 .WillOnce(testing::Return(CreateSession(
214 &dispatcher_
, connection_id
, client_address
, &session1_
)));
215 ProcessPacket(client_address
, connection_id
, true, "foo");
217 // Close the connection by sending public reset packet.
218 QuicPublicResetPacket packet
;
219 packet
.public_header
.connection_id
= connection_id
;
220 packet
.public_header
.reset_flag
= true;
221 packet
.public_header
.version_flag
= false;
222 packet
.rejected_sequence_number
= 19191;
223 packet
.nonce_proof
= 132232;
224 scoped_ptr
<QuicEncryptedPacket
> encrypted(
225 QuicFramer::BuildPublicResetPacket(packet
));
226 EXPECT_CALL(*session1_
, OnConnectionClosed(QUIC_PUBLIC_RESET
, true)).Times(1)
227 .WillOnce(WithoutArgs(Invoke(
228 reinterpret_cast<MockServerConnection
*>(session1_
->connection()),
229 &MockServerConnection::UnregisterOnConnectionClosed
)));
230 EXPECT_CALL(*reinterpret_cast<MockConnection
*>(session1_
->connection()),
231 ProcessUdpPacket(_
, _
, _
))
233 reinterpret_cast<MockConnection
*>(session1_
->connection()),
234 &MockConnection::ReallyProcessUdpPacket
));
235 dispatcher_
.ProcessPacket(IPEndPoint(), client_address
, *encrypted
);
236 EXPECT_TRUE(time_wait_list_manager
->IsConnectionIdInTimeWait(connection_id
));
238 // Dispatcher forwards subsequent packets for this connection_id to the time
239 // wait list manager.
240 EXPECT_CALL(*time_wait_list_manager
,
241 ProcessPacket(_
, _
, connection_id
, _
, _
)).Times(1);
242 ProcessPacket(client_address
, connection_id
, true, "foo");
245 TEST_F(QuicDispatcherTest
, StrayPacketToTimeWaitListManager
) {
246 MockTimeWaitListManager
* time_wait_list_manager
=
247 new MockTimeWaitListManager(
248 QuicDispatcherPeer::GetWriter(&dispatcher_
), &dispatcher_
, &eps_
);
249 // dispatcher takes the ownership of time_wait_list_manager.
250 QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_
,
251 time_wait_list_manager
);
253 IPEndPoint
client_address(net::test::Loopback4(), 1);
254 QuicConnectionId connection_id
= 1;
255 // Dispatcher forwards all packets for this connection_id to the time wait
257 EXPECT_CALL(dispatcher_
, CreateQuicSession(_
, _
, _
)).Times(0);
258 EXPECT_CALL(*time_wait_list_manager
,
259 ProcessPacket(_
, _
, connection_id
, _
, _
)).Times(1);
261 ProcessPacket(client_address
, connection_id
, false, "foo");
264 class BlockingWriter
: public QuicPacketWriterWrapper
{
266 BlockingWriter() : write_blocked_(false) {}
268 bool IsWriteBlocked() const override
{ return write_blocked_
; }
269 void SetWritable() override
{ write_blocked_
= false; }
271 WriteResult
WritePacket(const char* buffer
,
273 const IPAddressNumber
& self_client_address
,
274 const IPEndPoint
& peer_client_address
) override
{
275 // It would be quite possible to actually implement this method here with
276 // the fake blocked status, but it would be significantly more work in
277 // Chromium, and since it's not called anyway, don't bother.
278 LOG(DFATAL
) << "Not supported";
279 return WriteResult();
285 class QuicDispatcherWriteBlockedListTest
: public QuicDispatcherTest
{
287 void SetUp() override
{
288 writer_
= new BlockingWriter
;
289 QuicDispatcherPeer::SetPacketWriterFactory(&dispatcher_
,
290 new TestWriterFactory());
291 QuicDispatcherPeer::UseWriter(&dispatcher_
, writer_
);
293 IPEndPoint
client_address(net::test::Loopback4(), 1);
295 EXPECT_CALL(dispatcher_
, CreateQuicSession(_
, _
, client_address
))
296 .WillOnce(testing::Return(CreateSession(
297 &dispatcher_
, 1, client_address
, &session1_
)));
298 ProcessPacket(client_address
, 1, true, "foo");
300 EXPECT_CALL(dispatcher_
, CreateQuicSession(_
, _
, client_address
))
301 .WillOnce(testing::Return(CreateSession(
302 &dispatcher_
, 2, client_address
, &session2_
)));
303 ProcessPacket(client_address
, 2, true, "bar");
305 blocked_list_
= QuicDispatcherPeer::GetWriteBlockedList(&dispatcher_
);
308 void TearDown() override
{
309 EXPECT_CALL(*connection1(), SendConnectionClose(QUIC_PEER_GOING_AWAY
));
310 EXPECT_CALL(*connection2(), SendConnectionClose(QUIC_PEER_GOING_AWAY
));
311 dispatcher_
.Shutdown();
315 writer_
->write_blocked_
= true;
318 void BlockConnection2() {
319 writer_
->write_blocked_
= true;
320 dispatcher_
.OnWriteBlocked(connection2());
324 BlockingWriter
* writer_
;
325 QuicDispatcher::WriteBlockedList
* blocked_list_
;
328 TEST_F(QuicDispatcherWriteBlockedListTest
, BasicOnCanWrite
) {
329 // No OnCanWrite calls because no connections are blocked.
330 dispatcher_
.OnCanWrite();
332 // Register connection 1 for events, and make sure it's notified.
334 dispatcher_
.OnWriteBlocked(connection1());
335 EXPECT_CALL(*connection1(), OnCanWrite());
336 dispatcher_
.OnCanWrite();
338 // It should get only one notification.
339 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
340 dispatcher_
.OnCanWrite();
341 EXPECT_FALSE(dispatcher_
.HasPendingWrites());
344 TEST_F(QuicDispatcherWriteBlockedListTest
, OnCanWriteOrder
) {
345 // Make sure we handle events in order.
348 dispatcher_
.OnWriteBlocked(connection1());
349 dispatcher_
.OnWriteBlocked(connection2());
350 EXPECT_CALL(*connection1(), OnCanWrite());
351 EXPECT_CALL(*connection2(), OnCanWrite());
352 dispatcher_
.OnCanWrite();
354 // Check the other ordering.
356 dispatcher_
.OnWriteBlocked(connection2());
357 dispatcher_
.OnWriteBlocked(connection1());
358 EXPECT_CALL(*connection2(), OnCanWrite());
359 EXPECT_CALL(*connection1(), OnCanWrite());
360 dispatcher_
.OnCanWrite();
363 TEST_F(QuicDispatcherWriteBlockedListTest
, OnCanWriteRemove
) {
364 // Add and remove one connction.
366 dispatcher_
.OnWriteBlocked(connection1());
367 blocked_list_
->erase(connection1());
368 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
369 dispatcher_
.OnCanWrite();
371 // Add and remove one connction and make sure it doesn't affect others.
373 dispatcher_
.OnWriteBlocked(connection1());
374 dispatcher_
.OnWriteBlocked(connection2());
375 blocked_list_
->erase(connection1());
376 EXPECT_CALL(*connection2(), OnCanWrite());
377 dispatcher_
.OnCanWrite();
379 // Add it, remove it, and add it back and make sure things are OK.
381 dispatcher_
.OnWriteBlocked(connection1());
382 blocked_list_
->erase(connection1());
383 dispatcher_
.OnWriteBlocked(connection1());
384 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
385 dispatcher_
.OnCanWrite();
388 TEST_F(QuicDispatcherWriteBlockedListTest
, DoubleAdd
) {
389 // Make sure a double add does not necessitate a double remove.
391 dispatcher_
.OnWriteBlocked(connection1());
392 dispatcher_
.OnWriteBlocked(connection1());
393 blocked_list_
->erase(connection1());
394 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
395 dispatcher_
.OnCanWrite();
397 // Make sure a double add does not result in two OnCanWrite calls.
399 dispatcher_
.OnWriteBlocked(connection1());
400 dispatcher_
.OnWriteBlocked(connection1());
401 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
402 dispatcher_
.OnCanWrite();
405 TEST_F(QuicDispatcherWriteBlockedListTest
, OnCanWriteHandleBlock
) {
406 // Finally make sure if we write block on a write call, we stop calling.
409 dispatcher_
.OnWriteBlocked(connection1());
410 dispatcher_
.OnWriteBlocked(connection2());
411 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
412 Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked
));
413 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
414 dispatcher_
.OnCanWrite();
416 // And we'll resume where we left off when we get another call.
417 EXPECT_CALL(*connection2(), OnCanWrite());
418 dispatcher_
.OnCanWrite();
421 TEST_F(QuicDispatcherWriteBlockedListTest
, LimitedWrites
) {
422 // Make sure we call both writers. The first will register for more writing
423 // but should not be immediately called due to limits.
426 dispatcher_
.OnWriteBlocked(connection1());
427 dispatcher_
.OnWriteBlocked(connection2());
428 EXPECT_CALL(*connection1(), OnCanWrite());
429 EXPECT_CALL(*connection2(), OnCanWrite()).WillOnce(
430 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2
));
431 dispatcher_
.OnCanWrite();
432 EXPECT_TRUE(dispatcher_
.HasPendingWrites());
434 // Now call OnCanWrite again, and connection1 should get its second chance
435 EXPECT_CALL(*connection2(), OnCanWrite());
436 dispatcher_
.OnCanWrite();
437 EXPECT_FALSE(dispatcher_
.HasPendingWrites());
440 TEST_F(QuicDispatcherWriteBlockedListTest
, TestWriteLimits
) {
441 // Finally make sure if we write block on a write call, we stop calling.
444 dispatcher_
.OnWriteBlocked(connection1());
445 dispatcher_
.OnWriteBlocked(connection2());
446 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
447 Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked
));
448 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
449 dispatcher_
.OnCanWrite();
450 EXPECT_TRUE(dispatcher_
.HasPendingWrites());
452 // And we'll resume where we left off when we get another call.
453 EXPECT_CALL(*connection2(), OnCanWrite());
454 dispatcher_
.OnCanWrite();
455 EXPECT_FALSE(dispatcher_
.HasPendingWrites());