Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Side by Side Diff: net/tools/quic/quic_dispatcher_test.cc

Issue 1128103007: Protected by FLAGS_enable_quic_stateless_reject_support. Add support (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@Added_support_for_stateless_time_wait_93412303
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/tools/quic/quic_dispatcher.cc ('k') | net/tools/quic/quic_server_session.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/tools/quic/quic_dispatcher.h" 5 #include "net/tools/quic/quic_dispatcher.h"
6 6
7 #include <ostream>
7 #include <string> 8 #include <string>
8 9
9 #include "base/strings/string_piece.h" 10 #include "base/strings/string_piece.h"
10 #include "net/quic/crypto/crypto_handshake.h" 11 #include "net/quic/crypto/crypto_handshake.h"
11 #include "net/quic/crypto/quic_crypto_server_config.h" 12 #include "net/quic/crypto/quic_crypto_server_config.h"
12 #include "net/quic/crypto/quic_random.h" 13 #include "net/quic/crypto/quic_random.h"
13 #include "net/quic/quic_connection_helper.h" 14 #include "net/quic/quic_connection_helper.h"
14 #include "net/quic/quic_crypto_stream.h" 15 #include "net/quic/quic_crypto_stream.h"
15 #include "net/quic/quic_flags.h" 16 #include "net/quic/quic_flags.h"
16 #include "net/quic/quic_utils.h" 17 #include "net/quic/quic_utils.h"
17 #include "net/quic/test_tools/quic_test_utils.h" 18 #include "net/quic/test_tools/quic_test_utils.h"
18 #include "net/tools/epoll_server/epoll_server.h" 19 #include "net/tools/epoll_server/epoll_server.h"
19 #include "net/tools/quic/quic_epoll_connection_helper.h" 20 #include "net/tools/quic/quic_epoll_connection_helper.h"
20 #include "net/tools/quic/quic_packet_writer_wrapper.h" 21 #include "net/tools/quic/quic_packet_writer_wrapper.h"
21 #include "net/tools/quic/quic_time_wait_list_manager.h" 22 #include "net/tools/quic/quic_time_wait_list_manager.h"
22 #include "net/tools/quic/test_tools/quic_dispatcher_peer.h" 23 #include "net/tools/quic/test_tools/quic_dispatcher_peer.h"
23 #include "net/tools/quic/test_tools/quic_test_utils.h" 24 #include "net/tools/quic/test_tools/quic_test_utils.h"
24 #include "testing/gmock/include/gmock/gmock.h" 25 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h" 26 #include "testing/gtest/include/gtest/gtest.h"
26 27
27 using base::StringPiece; 28 using base::StringPiece;
28 using net::EpollServer; 29 using net::EpollServer;
29 using net::test::ConstructEncryptedPacket; 30 using net::test::ConstructEncryptedPacket;
30 using net::test::MockConnection; 31 using net::test::MockConnection;
31 using net::test::MockSession; 32 using net::test::MockSession;
32 using net::test::ValueRestore; 33 using net::test::ValueRestore;
33 using std::string; 34 using std::string;
35 using std::vector;
34 using testing::DoAll; 36 using testing::DoAll;
35 using testing::InSequence; 37 using testing::InSequence;
36 using testing::Invoke; 38 using testing::Invoke;
37 using testing::WithoutArgs; 39 using testing::WithoutArgs;
38 using testing::_; 40 using testing::_;
39 41
40 namespace net { 42 namespace net {
41 namespace tools { 43 namespace tools {
42 namespace test { 44 namespace test {
43 namespace { 45 namespace {
44 46
45 class TestServerSession : public QuicServerSession { 47 class TestServerSession : public QuicServerSession {
46 public: 48 public:
47 TestServerSession(const QuicConfig& config, QuicConnection* connection) 49 TestServerSession(const QuicConfig& config, QuicConnection* connection)
48 : QuicServerSession(config, connection, nullptr) {} 50 : QuicServerSession(config, connection, nullptr) {}
49 ~TestServerSession() override{}; 51 ~TestServerSession() override{};
50 52
51 MOCK_METHOD2(OnConnectionClosed, void(QuicErrorCode error, bool from_peer)); 53 MOCK_METHOD2(OnConnectionClosed, void(QuicErrorCode error, bool from_peer));
52 MOCK_METHOD1(CreateIncomingDataStream, QuicDataStream*(QuicStreamId id)); 54 MOCK_METHOD1(CreateIncomingDataStream, QuicDataStream*(QuicStreamId id));
53 MOCK_METHOD0(CreateOutgoingDataStream, QuicDataStream*()); 55 MOCK_METHOD0(CreateOutgoingDataStream, QuicDataStream*());
54 56
57 void SetCryptoStream(QuicCryptoServerStream* crypto_stream) {
58 crypto_stream_ = crypto_stream;
59 }
60
61 QuicCryptoServerStream* GetCryptoStream() override { return crypto_stream_; }
62
55 private: 63 private:
64 QuicCryptoServerStream* crypto_stream_;
65
56 DISALLOW_COPY_AND_ASSIGN(TestServerSession); 66 DISALLOW_COPY_AND_ASSIGN(TestServerSession);
57 }; 67 };
58 68
59 class TestDispatcher : public QuicDispatcher { 69 class TestDispatcher : public QuicDispatcher {
60 public: 70 public:
61 explicit TestDispatcher(const QuicConfig& config, 71 TestDispatcher(const QuicConfig& config,
62 const QuicCryptoServerConfig* crypto_config, 72 const QuicCryptoServerConfig* crypto_config,
63 EpollServer* eps) 73 EpollServer* eps)
64 : QuicDispatcher(config, 74 : QuicDispatcher(config,
65 crypto_config, 75 crypto_config,
66 QuicSupportedVersions(), 76 QuicSupportedVersions(),
67 new QuicDispatcher::DefaultPacketWriterFactory(), 77 new QuicDispatcher::DefaultPacketWriterFactory(),
68 new QuicEpollConnectionHelper(eps)) { 78 new QuicEpollConnectionHelper(eps)) {}
69 }
70 79
71 MOCK_METHOD3(CreateQuicSession, 80 MOCK_METHOD3(CreateQuicSession,
72 QuicServerSession*(QuicConnectionId connection_id, 81 QuicServerSession*(QuicConnectionId connection_id,
73 const IPEndPoint& server_address, 82 const IPEndPoint& server_address,
74 const IPEndPoint& client_address)); 83 const IPEndPoint& client_address));
75 84
76 using QuicDispatcher::current_server_address; 85 using QuicDispatcher::current_server_address;
77 using QuicDispatcher::current_client_address; 86 using QuicDispatcher::current_client_address;
78 }; 87 };
79 88
80 // A Connection class which unregisters the session from the dispatcher 89 // A Connection class which unregisters the session from the dispatcher when
81 // when sending connection close. 90 // sending connection close.
82 // It'd be slightly more realistic to do this from the Session but it would 91 // It'd be slightly more realistic to do this from the Session but it would
83 // involve a lot more mocking. 92 // involve a lot more mocking.
84 class MockServerConnection : public MockConnection { 93 class MockServerConnection : public MockConnection {
85 public: 94 public:
86 MockServerConnection(QuicConnectionId connection_id, 95 MockServerConnection(QuicConnectionId connection_id,
87 QuicDispatcher* dispatcher) 96 QuicDispatcher* dispatcher)
88 : MockConnection(connection_id, Perspective::IS_SERVER), 97 : MockConnection(connection_id, Perspective::IS_SERVER),
89 dispatcher_(dispatcher) {} 98 dispatcher_(dispatcher) {}
90 99
91 void UnregisterOnConnectionClosed() { 100 void UnregisterOnConnectionClosed() {
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 // Dispatcher forwards all packets for this connection_id to the time wait 291 // Dispatcher forwards all packets for this connection_id to the time wait
283 // list manager. 292 // list manager.
284 EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, _)).Times(0); 293 EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, _)).Times(0);
285 EXPECT_CALL(*time_wait_list_manager_, 294 EXPECT_CALL(*time_wait_list_manager_,
286 ProcessPacket(_, _, connection_id, _, _)).Times(1); 295 ProcessPacket(_, _, connection_id, _, _)).Times(1);
287 EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _, _)) 296 EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _, _))
288 .Times(1); 297 .Times(1);
289 ProcessPacket(client_address, connection_id, false, "data"); 298 ProcessPacket(client_address, connection_id, false, "data");
290 } 299 }
291 300
301 // Enables mocking of the handshake-confirmation for stateless rejects.
302 class MockQuicCryptoServerStream : public QuicCryptoServerStream {
303 public:
304 MockQuicCryptoServerStream(const QuicCryptoServerConfig& crypto_config,
305 QuicSession* session)
306 : QuicCryptoServerStream(&crypto_config, session) {}
307 void set_handshake_confirmed_for_testing(bool handshake_confirmed) {
308 handshake_confirmed_ = handshake_confirmed;
309 }
310
311 private:
312 DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStream);
313 };
314
315 struct StatelessRejectTestParams {
316 StatelessRejectTestParams(bool enable_stateless_rejects_via_flag,
317 bool use_stateless_rejects_if_peer_supported,
318 bool client_supports_statelesss_rejects,
319 bool crypto_handshake_successful)
320 : enable_stateless_rejects_via_flag(enable_stateless_rejects_via_flag),
321 use_stateless_rejects_if_peer_supported(
322 use_stateless_rejects_if_peer_supported),
323 client_supports_statelesss_rejects(client_supports_statelesss_rejects),
324 crypto_handshake_successful(crypto_handshake_successful) {}
325
326 friend std::ostream& operator<<(std::ostream& os,
327 const StatelessRejectTestParams& p) {
328 os << " enable_stateless_rejects_via_flag: "
329 << p.enable_stateless_rejects_via_flag << std::endl;
330 os << "{ use_stateless_rejects_if_peer_supported: "
331 << p.use_stateless_rejects_if_peer_supported << std::endl;
332 os << "{ client_supports_statelesss_rejects: "
333 << p.client_supports_statelesss_rejects << std::endl;
334 os << " crypto_handshake_successful: " << p.crypto_handshake_successful
335 << " }";
336 return os;
337 }
338
339 // This only enables the stateless reject feature via the feature-flag.
340 // It does not force the crypto server to emit stateless rejects.
341 bool enable_stateless_rejects_via_flag;
342 // If true, this forces the server to send a stateless reject when rejecting
343 // messages. This should be a no-op if enable_stateless_rejects_via_flag is
344 // false or the peer does not support them.
345 bool use_stateless_rejects_if_peer_supported;
346 // Whether or not the client supports stateless rejects.
347 bool client_supports_statelesss_rejects;
348 // Should the initial crypto handshake succeed or not.
349 bool crypto_handshake_successful;
350 };
351
352 // Constructs various test permutations for stateless rejects.
353 vector<StatelessRejectTestParams> GetStatelessRejectTestParams() {
354 vector<StatelessRejectTestParams> params;
355 for (bool enable_stateless_rejects_via_flag : {true, false}) {
356 for (bool use_stateless_rejects_if_peer_supported : {true, false}) {
357 for (bool client_supports_statelesss_rejects : {true, false}) {
358 for (bool crypto_handshake_successful : {true, false}) {
359 params.push_back(StatelessRejectTestParams(
360 enable_stateless_rejects_via_flag,
361 use_stateless_rejects_if_peer_supported,
362 client_supports_statelesss_rejects, crypto_handshake_successful));
363 }
364 }
365 }
366 }
367 return params;
368 }
369
370 class QuicDispatcherStatelessRejectTest
371 : public QuicDispatcherTest,
372 public ::testing::WithParamInterface<StatelessRejectTestParams> {
373 public:
374 QuicDispatcherStatelessRejectTest() : crypto_stream1_(nullptr) {}
375
376 ~QuicDispatcherStatelessRejectTest() override {
377 if (crypto_stream1_) {
378 delete crypto_stream1_;
379 }
380 }
381
382 // This test setup assumes that all testing will be done using
383 // crypto_stream1_.
384 void SetUp() override {
385 FLAGS_enable_quic_stateless_reject_support =
386 GetParam().enable_stateless_rejects_via_flag;
387 }
388
389 // Returns true or false, depending on whether the server will emit
390 // a stateless reject, depending upon the parameters of the test.
391 bool ExpectStatelessReject() {
392 return GetParam().enable_stateless_rejects_via_flag &&
393 GetParam().use_stateless_rejects_if_peer_supported &&
394 !GetParam().crypto_handshake_successful &&
395 GetParam().client_supports_statelesss_rejects;
396 }
397
398 // Sets up dispatcher_, sesession1_, and crypto_stream1_ based on
399 // the test parameters.
400 QuicServerSession* CreateSessionBasedOnTestParams(
401 QuicConnectionId connection_id,
402 const IPEndPoint& client_address) {
403 CreateSession(&dispatcher_, config_, connection_id, client_address,
404 &session1_);
405
406 crypto_stream1_ = new MockQuicCryptoServerStream(crypto_config_, session1_);
407 session1_->SetCryptoStream(crypto_stream1_);
408 crypto_stream1_->set_use_stateless_rejects_if_peer_supported(
409 GetParam().use_stateless_rejects_if_peer_supported);
410 crypto_stream1_->set_handshake_confirmed_for_testing(
411 GetParam().crypto_handshake_successful);
412 crypto_stream1_->set_peer_supports_stateless_rejects(
413 GetParam().client_supports_statelesss_rejects);
414 return session1_;
415 }
416
417 MockQuicCryptoServerStream* crypto_stream1_;
418 };
419
292 TEST_F(QuicDispatcherTest, ProcessPacketWithZeroPort) { 420 TEST_F(QuicDispatcherTest, ProcessPacketWithZeroPort) {
293 CreateTimeWaitListManager(); 421 CreateTimeWaitListManager();
294 422
295 IPEndPoint client_address(net::test::Loopback4(), 0); 423 IPEndPoint client_address(net::test::Loopback4(), 0);
296 server_address_ = IPEndPoint(net::test::Any4(), 5); 424 server_address_ = IPEndPoint(net::test::Any4(), 5);
297 425
298 // dispatcher_ should drop this packet. 426 // dispatcher_ should drop this packet.
299 EXPECT_CALL(dispatcher_, CreateQuicSession(1, _, client_address)).Times(0); 427 EXPECT_CALL(dispatcher_, CreateQuicSession(1, _, client_address)).Times(0);
300 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0); 428 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
301 EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _, _)) 429 EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _, _))
(...skipping 30 matching lines...) Expand all
332 ProcessPacket(_, _, connection_id, _, _)).Times(1); 460 ProcessPacket(_, _, connection_id, _, _)).Times(1);
333 EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _, _)) 461 EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _, _))
334 .Times(1); 462 .Times(1);
335 // A packet whose sequence number is one to large to be allowed to start a 463 // A packet whose sequence number is one to large to be allowed to start a
336 // connection. 464 // connection.
337 ProcessPacket(client_address, connection_id, true, "data", 465 ProcessPacket(client_address, connection_id, true, "data",
338 PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_SEQUENCE_NUMBER, 466 PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_SEQUENCE_NUMBER,
339 QuicDispatcher::kMaxReasonableInitialSequenceNumber + 1); 467 QuicDispatcher::kMaxReasonableInitialSequenceNumber + 1);
340 } 468 }
341 469
470 INSTANTIATE_TEST_CASE_P(QuicDispatcherStatelessRejectTests,
471 QuicDispatcherStatelessRejectTest,
472 ::testing::ValuesIn(GetStatelessRejectTestParams()));
473
474 // Parameterized test for stateless rejects. Should test all
475 // combinations of enabling/disabling, reject/no-reject for stateless
476 // rejects.
477 TEST_P(QuicDispatcherStatelessRejectTest, ParameterizedBasicTest) {
478 CreateTimeWaitListManager();
479
480 IPEndPoint client_address(net::test::Loopback4(), 1);
481 QuicConnectionId connection_id = 1;
482 EXPECT_CALL(dispatcher_, CreateQuicSession(connection_id, _, client_address))
483 .WillOnce(testing::Return(
484 CreateSessionBasedOnTestParams(connection_id, client_address)));
485
486 // Process the first packet for the connection.
487 if (ExpectStatelessReject()) {
488 // If this is a stateless reject, we expect the connection to close.
489 EXPECT_CALL(*session1_, OnConnectionClosed(_, _))
490 .Times(1)
491 .WillOnce(WithoutArgs(Invoke(
492 reinterpret_cast<MockServerConnection*>(session1_->connection()),
493 &MockServerConnection::UnregisterOnConnectionClosed)));
494 }
495 ProcessPacket(client_address, connection_id, true, "foo");
496
497 // Send a second packet and check the results. If this is a stateless reject,
498 // the existing connection_id will go on the time-wait list.
499 EXPECT_EQ(ExpectStatelessReject(),
500 time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
501 if (ExpectStatelessReject()) {
502 // The second packet will be processed on the time-wait list.
503 EXPECT_CALL(*time_wait_list_manager_,
504 ProcessPacket(_, _, connection_id, _, _)).Times(1);
505 } else {
506 // The second packet will trigger a packet-validation
507 EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
508 ProcessUdpPacket(_, _, _))
509 .Times(1)
510 .WillOnce(testing::WithArgs<2>(
511 Invoke(this, &QuicDispatcherTest::ValidatePacket)));
512 }
513 ProcessPacket(client_address, connection_id, true, "foo");
514 }
515
342 // Verify the stopgap test: Packets with truncated connection IDs should be 516 // Verify the stopgap test: Packets with truncated connection IDs should be
343 // dropped. 517 // dropped.
344 class QuicDispatcherTestStrayPacketConnectionId 518 class QuicDispatcherTestStrayPacketConnectionId
345 : public QuicDispatcherTest, 519 : public QuicDispatcherTest,
346 public ::testing::WithParamInterface<QuicConnectionIdLength> {}; 520 public ::testing::WithParamInterface<QuicConnectionIdLength> {};
347 521
348 // Packets with truncated connection IDs should be dropped. 522 // Packets with truncated connection IDs should be dropped.
349 TEST_P(QuicDispatcherTestStrayPacketConnectionId, 523 TEST_P(QuicDispatcherTestStrayPacketConnectionId,
350 StrayPacketTruncatedConnectionId) { 524 StrayPacketTruncatedConnectionId) {
351 const QuicConnectionIdLength connection_id_length = GetParam(); 525 const QuicConnectionIdLength connection_id_length = GetParam();
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 // And we'll resume where we left off when we get another call. 735 // And we'll resume where we left off when we get another call.
562 EXPECT_CALL(*connection2(), OnCanWrite()); 736 EXPECT_CALL(*connection2(), OnCanWrite());
563 dispatcher_.OnCanWrite(); 737 dispatcher_.OnCanWrite();
564 EXPECT_FALSE(dispatcher_.HasPendingWrites()); 738 EXPECT_FALSE(dispatcher_.HasPendingWrites());
565 } 739 }
566 740
567 } // namespace 741 } // namespace
568 } // namespace test 742 } // namespace test
569 } // namespace tools 743 } // namespace tools
570 } // namespace net 744 } // namespace net
OLDNEW
« no previous file with comments | « net/tools/quic/quic_dispatcher.cc ('k') | net/tools/quic/quic_server_session.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698