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_utils.h"
15 #include "net/quic/test_tools/quic_test_utils.h"
16 #include "net/tools/epoll_server/epoll_server.h"
17 #include "net/tools/quic/quic_packet_writer_wrapper.h"
18 #include "net/tools/quic/quic_time_wait_list_manager.h"
19 #include "net/tools/quic/test_tools/quic_dispatcher_peer.h"
20 #include "net/tools/quic/test_tools/quic_test_utils.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 using base::StringPiece
;
25 using net::EpollServer
;
26 using net::test::MockSession
;
27 using net::tools::test::MockConnection
;
31 using testing::Invoke
;
32 using testing::InSequence
;
33 using testing::Return
;
34 using testing::WithoutArgs
;
41 class TestDispatcher
: public QuicDispatcher
{
43 explicit TestDispatcher(const QuicConfig
& config
,
44 const QuicCryptoServerConfig
& crypto_config
,
46 : QuicDispatcher(config
, crypto_config
, QuicSupportedVersions(), eps
) {
49 MOCK_METHOD3(CreateQuicSession
, QuicSession
*(
50 QuicConnectionId connection_id
,
51 const IPEndPoint
& server_address
,
52 const IPEndPoint
& client_address
));
53 using QuicDispatcher::write_blocked_list
;
56 // A Connection class which unregisters the session from the dispatcher
57 // when sending connection close.
58 // It'd be slightly more realistic to do this from the Session but it would
59 // involve a lot more mocking.
60 class MockServerConnection
: public MockConnection
{
62 MockServerConnection(QuicConnectionId connection_id
,
63 QuicDispatcher
* dispatcher
)
64 : MockConnection(connection_id
, true),
65 dispatcher_(dispatcher
) {}
67 void UnregisterOnConnectionClosed() {
68 LOG(ERROR
) << "Unregistering " << connection_id();
69 dispatcher_
->OnConnectionClosed(connection_id(), QUIC_NO_ERROR
);
72 QuicDispatcher
* dispatcher_
;
75 QuicSession
* CreateSession(QuicDispatcher
* dispatcher
,
76 QuicConnectionId connection_id
,
77 const IPEndPoint
& addr
,
78 MockSession
** session
) {
79 MockServerConnection
* connection
=
80 new MockServerConnection(connection_id
, dispatcher
);
81 *session
= new MockSession(connection
);
82 ON_CALL(*connection
, SendConnectionClose(_
)).WillByDefault(
84 connection
, &MockServerConnection::UnregisterOnConnectionClosed
)));
85 EXPECT_CALL(*reinterpret_cast<MockConnection
*>((*session
)->connection()),
86 ProcessUdpPacket(_
, addr
, _
));
91 class QuicDispatcherTest
: public ::testing::Test
{
94 : crypto_config_(QuicCryptoServerConfig::TESTING
,
95 QuicRandom::GetInstance()),
96 dispatcher_(config_
, crypto_config_
, &eps_
),
99 dispatcher_
.Initialize(1);
102 virtual ~QuicDispatcherTest() {}
104 MockConnection
* connection1() {
105 return reinterpret_cast<MockConnection
*>(session1_
->connection());
108 MockConnection
* connection2() {
109 return reinterpret_cast<MockConnection
*>(session2_
->connection());
112 QuicEncryptedPacket
* ConstructEncryptedPacket(
113 QuicConnectionId connection_id
,
116 QuicPacketSequenceNumber sequence_number
,
117 const string
& data
) {
118 QuicPacketHeader header
;
119 header
.public_header
.connection_id
= connection_id
;
120 header
.public_header
.connection_id_length
= PACKET_8BYTE_CONNECTION_ID
;
121 header
.public_header
.version_flag
= version_flag
;
122 header
.public_header
.reset_flag
= reset_flag
;
123 header
.public_header
.sequence_number_length
= PACKET_6BYTE_SEQUENCE_NUMBER
;
124 header
.packet_sequence_number
= sequence_number
;
125 header
.entropy_flag
= false;
126 header
.entropy_hash
= 0;
127 header
.fec_flag
= false;
128 header
.is_in_fec_group
= NOT_IN_FEC_GROUP
;
129 header
.fec_group
= 0;
130 QuicStreamFrame
stream_frame(1, false, 0, MakeIOVector(data
));
131 QuicFrame
frame(&stream_frame
);
133 frames
.push_back(frame
);
134 QuicFramer
framer(QuicSupportedVersions(), QuicTime::Zero(), false);
135 scoped_ptr
<QuicPacket
> packet(
136 framer
.BuildUnsizedDataPacket(header
, frames
).packet
);
137 EXPECT_TRUE(packet
!= NULL
);
138 QuicEncryptedPacket
* encrypted
= framer
.EncryptPacket(ENCRYPTION_NONE
,
141 EXPECT_TRUE(encrypted
!= NULL
);
142 data_
= string(encrypted
->data(), encrypted
->length());
146 void ProcessPacket(IPEndPoint addr
,
147 QuicConnectionId connection_id
,
148 bool has_version_flag
,
149 const string
& data
) {
150 scoped_ptr
<QuicEncryptedPacket
> packet(ConstructEncryptedPacket(
151 connection_id
, has_version_flag
, false, 1, data
));
152 dispatcher_
.ProcessPacket(IPEndPoint(), addr
, *packet
.get());
155 void ValidatePacket(const QuicEncryptedPacket
& packet
) {
156 EXPECT_EQ(data_
.length(), packet
.AsStringPiece().length());
157 EXPECT_EQ(data_
, packet
.AsStringPiece());
162 QuicCryptoServerConfig crypto_config_
;
163 TestDispatcher dispatcher_
;
164 MockSession
* session1_
;
165 MockSession
* session2_
;
169 TEST_F(QuicDispatcherTest
, ProcessPackets
) {
170 IPEndPoint
addr(net::test::Loopback4(), 1);
172 EXPECT_CALL(dispatcher_
, CreateQuicSession(1, _
, addr
))
173 .WillOnce(testing::Return(CreateSession(
174 &dispatcher_
, 1, addr
, &session1_
)));
175 ProcessPacket(addr
, 1, true, "foo");
177 EXPECT_CALL(dispatcher_
, CreateQuicSession(2, _
, addr
))
178 .WillOnce(testing::Return(CreateSession(
179 &dispatcher_
, 2, addr
, &session2_
)));
180 ProcessPacket(addr
, 2, true, "bar");
182 EXPECT_CALL(*reinterpret_cast<MockConnection
*>(session1_
->connection()),
183 ProcessUdpPacket(_
, _
, _
)).Times(1).
184 WillOnce(testing::WithArgs
<2>(Invoke(
185 this, &QuicDispatcherTest::ValidatePacket
)));
186 ProcessPacket(addr
, 1, false, "eep");
189 TEST_F(QuicDispatcherTest
, Shutdown
) {
190 IPEndPoint
addr(net::test::Loopback4(), 1);
192 EXPECT_CALL(dispatcher_
, CreateQuicSession(_
, _
, addr
))
193 .WillOnce(testing::Return(CreateSession(
194 &dispatcher_
, 1, addr
, &session1_
)));
196 ProcessPacket(addr
, 1, true, "foo");
198 EXPECT_CALL(*reinterpret_cast<MockConnection
*>(session1_
->connection()),
199 SendConnectionClose(QUIC_PEER_GOING_AWAY
));
201 dispatcher_
.Shutdown();
204 class MockTimeWaitListManager
: public QuicTimeWaitListManager
{
206 MockTimeWaitListManager(QuicPacketWriter
* writer
,
207 QuicServerSessionVisitor
* visitor
,
209 : QuicTimeWaitListManager(writer
, visitor
, eps
, QuicSupportedVersions()) {
212 MOCK_METHOD4(ProcessPacket
, void(const IPEndPoint
& server_address
,
213 const IPEndPoint
& client_address
,
214 QuicConnectionId connection_id
,
215 QuicPacketSequenceNumber sequence_number
));
218 TEST_F(QuicDispatcherTest
, TimeWaitListManager
) {
219 MockTimeWaitListManager
* time_wait_list_manager
=
220 new MockTimeWaitListManager(
221 QuicDispatcherPeer::GetWriter(&dispatcher_
), &dispatcher_
, &eps_
);
222 // dispatcher takes the ownership of time_wait_list_manager.
223 QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_
,
224 time_wait_list_manager
);
225 // Create a new session.
226 IPEndPoint
addr(net::test::Loopback4(), 1);
227 QuicConnectionId connection_id
= 1;
228 EXPECT_CALL(dispatcher_
, CreateQuicSession(connection_id
, _
, addr
))
229 .WillOnce(testing::Return(CreateSession(
230 &dispatcher_
, connection_id
, addr
, &session1_
)));
231 ProcessPacket(addr
, connection_id
, true, "foo");
233 // Close the connection by sending public reset packet.
234 QuicPublicResetPacket packet
;
235 packet
.public_header
.connection_id
= connection_id
;
236 packet
.public_header
.reset_flag
= true;
237 packet
.public_header
.version_flag
= false;
238 packet
.rejected_sequence_number
= 19191;
239 packet
.nonce_proof
= 132232;
240 scoped_ptr
<QuicEncryptedPacket
> encrypted(
241 QuicFramer::BuildPublicResetPacket(packet
));
242 EXPECT_CALL(*session1_
, OnConnectionClosed(QUIC_PUBLIC_RESET
, true)).Times(1)
243 .WillOnce(WithoutArgs(Invoke(
244 reinterpret_cast<MockServerConnection
*>(session1_
->connection()),
245 &MockServerConnection::UnregisterOnConnectionClosed
)));
246 EXPECT_CALL(*reinterpret_cast<MockConnection
*>(session1_
->connection()),
247 ProcessUdpPacket(_
, _
, _
))
249 reinterpret_cast<MockConnection
*>(session1_
->connection()),
250 &MockConnection::ReallyProcessUdpPacket
));
251 dispatcher_
.ProcessPacket(IPEndPoint(), addr
, *encrypted
);
252 EXPECT_TRUE(time_wait_list_manager
->IsConnectionIdInTimeWait(connection_id
));
254 // Dispatcher forwards subsequent packets for this connection_id to the time
255 // wait list manager.
256 EXPECT_CALL(*time_wait_list_manager
,
257 ProcessPacket(_
, _
, connection_id
, _
)).Times(1);
258 ProcessPacket(addr
, connection_id
, true, "foo");
261 TEST_F(QuicDispatcherTest
, StrayPacketToTimeWaitListManager
) {
262 MockTimeWaitListManager
* time_wait_list_manager
=
263 new MockTimeWaitListManager(
264 QuicDispatcherPeer::GetWriter(&dispatcher_
), &dispatcher_
, &eps_
);
265 // dispatcher takes the ownership of time_wait_list_manager.
266 QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_
,
267 time_wait_list_manager
);
269 IPEndPoint
addr(net::test::Loopback4(), 1);
270 QuicConnectionId connection_id
= 1;
271 // Dispatcher forwards all packets for this connection_id to the time wait
273 EXPECT_CALL(dispatcher_
, CreateQuicSession(_
, _
, _
)).Times(0);
274 EXPECT_CALL(*time_wait_list_manager
,
275 ProcessPacket(_
, _
, connection_id
, _
)).Times(1);
277 ProcessPacket(addr
, connection_id
, false, "foo");
280 class BlockingWriter
: public QuicPacketWriterWrapper
{
282 BlockingWriter() : write_blocked_(false) {}
284 virtual bool IsWriteBlocked() const OVERRIDE
{ return write_blocked_
; }
285 virtual void SetWritable() OVERRIDE
{ write_blocked_
= false; }
287 virtual WriteResult
WritePacket(
290 const IPAddressNumber
& self_address
,
291 const IPEndPoint
& peer_address
) OVERRIDE
{
292 if (write_blocked_
) {
293 return WriteResult(WRITE_STATUS_BLOCKED
, EAGAIN
);
295 return QuicPacketWriterWrapper::WritePacket(
296 buffer
, buf_len
, self_address
, peer_address
);
303 class QuicDispatcherWriteBlockedListTest
: public QuicDispatcherTest
{
305 virtual void SetUp() {
306 writer_
= new BlockingWriter
;
307 QuicDispatcherPeer::UseWriter(&dispatcher_
, writer_
);
309 IPEndPoint
addr(net::test::Loopback4(), 1);
311 EXPECT_CALL(dispatcher_
, CreateQuicSession(_
, _
, addr
))
312 .WillOnce(testing::Return(CreateSession(
313 &dispatcher_
, 1, addr
, &session1_
)));
314 ProcessPacket(addr
, 1, true, "foo");
316 EXPECT_CALL(dispatcher_
, CreateQuicSession(_
, _
, addr
))
317 .WillOnce(testing::Return(CreateSession(
318 &dispatcher_
, 2, addr
, &session2_
)));
319 ProcessPacket(addr
, 2, true, "bar");
321 blocked_list_
= dispatcher_
.write_blocked_list();
324 virtual void TearDown() {
325 EXPECT_CALL(*connection1(), SendConnectionClose(QUIC_PEER_GOING_AWAY
));
326 EXPECT_CALL(*connection2(), SendConnectionClose(QUIC_PEER_GOING_AWAY
));
327 dispatcher_
.Shutdown();
331 writer_
->write_blocked_
= true;
334 void BlockConnection2() {
335 writer_
->write_blocked_
= true;
336 dispatcher_
.OnWriteBlocked(connection2());
340 BlockingWriter
* writer_
;
341 QuicDispatcher::WriteBlockedList
* blocked_list_
;
344 TEST_F(QuicDispatcherWriteBlockedListTest
, BasicOnCanWrite
) {
345 // No OnCanWrite calls because no connections are blocked.
346 dispatcher_
.OnCanWrite();
348 // Register connection 1 for events, and make sure it's notified.
350 dispatcher_
.OnWriteBlocked(connection1());
351 EXPECT_CALL(*connection1(), OnCanWrite());
352 dispatcher_
.OnCanWrite();
354 // It should get only one notification.
355 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
356 dispatcher_
.OnCanWrite();
357 EXPECT_FALSE(dispatcher_
.HasPendingWrites());
360 TEST_F(QuicDispatcherWriteBlockedListTest
, OnCanWriteOrder
) {
361 // Make sure we handle events in order.
364 dispatcher_
.OnWriteBlocked(connection1());
365 dispatcher_
.OnWriteBlocked(connection2());
366 EXPECT_CALL(*connection1(), OnCanWrite());
367 EXPECT_CALL(*connection2(), OnCanWrite());
368 dispatcher_
.OnCanWrite();
370 // Check the other ordering.
372 dispatcher_
.OnWriteBlocked(connection2());
373 dispatcher_
.OnWriteBlocked(connection1());
374 EXPECT_CALL(*connection2(), OnCanWrite());
375 EXPECT_CALL(*connection1(), OnCanWrite());
376 dispatcher_
.OnCanWrite();
379 TEST_F(QuicDispatcherWriteBlockedListTest
, OnCanWriteRemove
) {
380 // Add and remove one connction.
382 dispatcher_
.OnWriteBlocked(connection1());
383 blocked_list_
->erase(connection1());
384 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
385 dispatcher_
.OnCanWrite();
387 // Add and remove one connction and make sure it doesn't affect others.
389 dispatcher_
.OnWriteBlocked(connection1());
390 dispatcher_
.OnWriteBlocked(connection2());
391 blocked_list_
->erase(connection1());
392 EXPECT_CALL(*connection2(), OnCanWrite());
393 dispatcher_
.OnCanWrite();
395 // Add it, remove it, and add it back and make sure things are OK.
397 dispatcher_
.OnWriteBlocked(connection1());
398 blocked_list_
->erase(connection1());
399 dispatcher_
.OnWriteBlocked(connection1());
400 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
401 dispatcher_
.OnCanWrite();
404 TEST_F(QuicDispatcherWriteBlockedListTest
, DoubleAdd
) {
405 // Make sure a double add does not necessitate a double remove.
407 dispatcher_
.OnWriteBlocked(connection1());
408 dispatcher_
.OnWriteBlocked(connection1());
409 blocked_list_
->erase(connection1());
410 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
411 dispatcher_
.OnCanWrite();
413 // Make sure a double add does not result in two OnCanWrite calls.
415 dispatcher_
.OnWriteBlocked(connection1());
416 dispatcher_
.OnWriteBlocked(connection1());
417 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
418 dispatcher_
.OnCanWrite();
421 TEST_F(QuicDispatcherWriteBlockedListTest
, OnCanWriteHandleBlock
) {
422 // Finally make sure if we write block on a write call, we stop calling.
425 dispatcher_
.OnWriteBlocked(connection1());
426 dispatcher_
.OnWriteBlocked(connection2());
427 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
428 Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked
));
429 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
430 dispatcher_
.OnCanWrite();
432 // And we'll resume where we left off when we get another call.
433 EXPECT_CALL(*connection2(), OnCanWrite());
434 dispatcher_
.OnCanWrite();
437 TEST_F(QuicDispatcherWriteBlockedListTest
, LimitedWrites
) {
438 // Make sure we call both writers. The first will register for more writing
439 // but should not be immediately called due to limits.
442 dispatcher_
.OnWriteBlocked(connection1());
443 dispatcher_
.OnWriteBlocked(connection2());
444 EXPECT_CALL(*connection1(), OnCanWrite());
445 EXPECT_CALL(*connection2(), OnCanWrite()).WillOnce(
446 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2
));
447 dispatcher_
.OnCanWrite();
448 EXPECT_TRUE(dispatcher_
.HasPendingWrites());
450 // Now call OnCanWrite again, and connection1 should get its second chance
451 EXPECT_CALL(*connection2(), OnCanWrite());
452 dispatcher_
.OnCanWrite();
453 EXPECT_FALSE(dispatcher_
.HasPendingWrites());
456 TEST_F(QuicDispatcherWriteBlockedListTest
, TestWriteLimits
) {
457 // Finally make sure if we write block on a write call, we stop calling.
460 dispatcher_
.OnWriteBlocked(connection1());
461 dispatcher_
.OnWriteBlocked(connection2());
462 EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
463 Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked
));
464 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
465 dispatcher_
.OnCanWrite();
466 EXPECT_TRUE(dispatcher_
.HasPendingWrites());
468 // And we'll resume where we left off when we get another call.
469 EXPECT_CALL(*connection2(), OnCanWrite());
470 dispatcher_
.OnCanWrite();
471 EXPECT_FALSE(dispatcher_
.HasPendingWrites());