OLD | NEW |
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 <memory> | 7 #include <memory> |
8 #include <ostream> | 8 #include <ostream> |
9 #include <string> | 9 #include <string> |
10 | 10 |
11 #include "base/macros.h" | 11 #include "base/macros.h" |
12 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
13 #include "net/quic/core/crypto/crypto_handshake.h" | 13 #include "net/quic/core/crypto/crypto_handshake.h" |
14 #include "net/quic/core/crypto/quic_crypto_server_config.h" | 14 #include "net/quic/core/crypto/quic_crypto_server_config.h" |
15 #include "net/quic/core/crypto/quic_random.h" | 15 #include "net/quic/core/crypto/quic_random.h" |
16 #include "net/quic/core/quic_crypto_stream.h" | 16 #include "net/quic/core/quic_crypto_stream.h" |
17 #include "net/quic/core/quic_flags.h" | 17 #include "net/quic/core/quic_flags.h" |
18 #include "net/quic/core/quic_utils.h" | 18 #include "net/quic/core/quic_utils.h" |
19 #include "net/quic/test_tools/crypto_test_utils.h" | 19 #include "net/quic/test_tools/crypto_test_utils.h" |
20 #include "net/quic/test_tools/quic_buffered_packet_store_peer.h" | 20 #include "net/quic/test_tools/quic_buffered_packet_store_peer.h" |
| 21 #include "net/quic/test_tools/quic_crypto_server_config_peer.h" |
21 #include "net/quic/test_tools/quic_test_utils.h" | 22 #include "net/quic/test_tools/quic_test_utils.h" |
| 23 #include "net/quic/test_tools/quic_time_wait_list_manager_peer.h" |
22 #include "net/test/gtest_util.h" | 24 #include "net/test/gtest_util.h" |
23 #include "net/tools/epoll_server/epoll_server.h" | 25 #include "net/tools/epoll_server/epoll_server.h" |
24 #include "net/tools/quic/chlo_extractor.h" | 26 #include "net/tools/quic/chlo_extractor.h" |
25 #include "net/tools/quic/quic_epoll_alarm_factory.h" | 27 #include "net/tools/quic/quic_epoll_alarm_factory.h" |
26 #include "net/tools/quic/quic_epoll_connection_helper.h" | 28 #include "net/tools/quic/quic_epoll_connection_helper.h" |
27 #include "net/tools/quic/quic_packet_writer_wrapper.h" | 29 #include "net/tools/quic/quic_packet_writer_wrapper.h" |
28 #include "net/tools/quic/quic_simple_crypto_server_stream_helper.h" | 30 #include "net/tools/quic/quic_simple_crypto_server_stream_helper.h" |
29 #include "net/tools/quic/quic_time_wait_list_manager.h" | 31 #include "net/tools/quic/quic_time_wait_list_manager.h" |
30 #include "net/tools/quic/stateless_rejector.h" | 32 #include "net/tools/quic/stateless_rejector.h" |
31 #include "net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h" | 33 #include "net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h" |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 "Unregistering."); | 164 "Unregistering."); |
163 } | 165 } |
164 | 166 |
165 private: | 167 private: |
166 QuicDispatcher* dispatcher_; | 168 QuicDispatcher* dispatcher_; |
167 }; | 169 }; |
168 | 170 |
169 class QuicDispatcherTest : public ::testing::Test { | 171 class QuicDispatcherTest : public ::testing::Test { |
170 public: | 172 public: |
171 QuicDispatcherTest() | 173 QuicDispatcherTest() |
| 174 : QuicDispatcherTest(CryptoTestUtils::ProofSourceForTesting()) {} |
| 175 |
| 176 explicit QuicDispatcherTest(std::unique_ptr<ProofSource> proof_source) |
172 : helper_(&eps_, QuicAllocator::BUFFER_POOL), | 177 : helper_(&eps_, QuicAllocator::BUFFER_POOL), |
173 alarm_factory_(&eps_), | 178 alarm_factory_(&eps_), |
174 version_manager_(AllSupportedVersions()), | 179 version_manager_(AllSupportedVersions()), |
175 crypto_config_(QuicCryptoServerConfig::TESTING, | 180 crypto_config_(QuicCryptoServerConfig::TESTING, |
176 QuicRandom::GetInstance(), | 181 QuicRandom::GetInstance(), |
177 CryptoTestUtils::ProofSourceForTesting()), | 182 std::move(proof_source)), |
178 dispatcher_(new TestDispatcher(config_, | 183 dispatcher_(new TestDispatcher(config_, |
179 &crypto_config_, | 184 &crypto_config_, |
180 &version_manager_, | 185 &version_manager_, |
181 &eps_)), | 186 &eps_)), |
182 time_wait_list_manager_(nullptr), | 187 time_wait_list_manager_(nullptr), |
183 session1_(nullptr), | 188 session1_(nullptr), |
184 session2_(nullptr), | 189 session2_(nullptr), |
185 store_(nullptr) {} | 190 store_(nullptr) {} |
186 | 191 |
187 void SetUp() override { | 192 void SetUp() override { |
(...skipping 1023 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1211 // Reset session creation counter to ensure processing CHLO can always | 1216 // Reset session creation counter to ensure processing CHLO can always |
1212 // create session. | 1217 // create session. |
1213 QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(dispatcher_.get(), | 1218 QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(dispatcher_.get(), |
1214 kNumConnections); | 1219 kNumConnections); |
1215 // Process CHLOs to create session for these connections. | 1220 // Process CHLOs to create session for these connections. |
1216 for (size_t i = 1; i <= kNumConnections; ++i) { | 1221 for (size_t i = 1; i <= kNumConnections; ++i) { |
1217 IPEndPoint client_address(Loopback4(), i); | 1222 IPEndPoint client_address(Loopback4(), i); |
1218 QuicConnectionId conn_id = i; | 1223 QuicConnectionId conn_id = i; |
1219 if (FLAGS_quic_create_session_after_insertion && | 1224 if (FLAGS_quic_create_session_after_insertion && |
1220 conn_id == kNumConnections) { | 1225 conn_id == kNumConnections) { |
| 1226 // The last CHLO should trigger ShouldCreateOrBufferPacketForConnection() |
| 1227 // since it's the |
| 1228 // first packet arrives on that connection. |
1221 EXPECT_CALL(*dispatcher_, | 1229 EXPECT_CALL(*dispatcher_, |
1222 ShouldCreateOrBufferPacketForConnection(conn_id)); | 1230 ShouldCreateOrBufferPacketForConnection(conn_id)); |
1223 } | 1231 } |
1224 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address)) | 1232 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address)) |
1225 .WillOnce(testing::Return(CreateSession( | 1233 .WillOnce(testing::Return(CreateSession( |
1226 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_, | 1234 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_, |
1227 &mock_alarm_factory_, &crypto_config_, | 1235 &mock_alarm_factory_, &crypto_config_, |
1228 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); | 1236 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); |
1229 if (!FLAGS_quic_create_session_after_insertion && | 1237 if (!FLAGS_quic_create_session_after_insertion && |
1230 conn_id == kNumConnections) { | 1238 conn_id == kNumConnections) { |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1524 ProcessPacket(client_addr_, conn_id, true, false, SerializeFullCHLO()); | 1532 ProcessPacket(client_addr_, conn_id, true, false, SerializeFullCHLO()); |
1525 } | 1533 } |
1526 EXPECT_FALSE(store->HasChloForConnection(/*connection_id=*/1)); | 1534 EXPECT_FALSE(store->HasChloForConnection(/*connection_id=*/1)); |
1527 | 1535 |
1528 // CHLO on connection 1 should still be buffered. | 1536 // CHLO on connection 1 should still be buffered. |
1529 ProcessPacket(client_addr_, /*connection_id=*/1, true, false, | 1537 ProcessPacket(client_addr_, /*connection_id=*/1, true, false, |
1530 SerializeFullCHLO()); | 1538 SerializeFullCHLO()); |
1531 EXPECT_TRUE(store->HasChloForConnection(/*connection_id=*/1)); | 1539 EXPECT_TRUE(store->HasChloForConnection(/*connection_id=*/1)); |
1532 } | 1540 } |
1533 | 1541 |
| 1542 // Implementation of ProofSource which delegates to a ProofSourceForTesting, |
| 1543 // except that when the async GetProof is called, it captures the call and |
| 1544 // allows tests to see that a call is pending, which they can then cause to |
| 1545 // complete at a time of their choosing. |
| 1546 class FakeProofSource : public ProofSource { |
| 1547 public: |
| 1548 FakeProofSource() : delegate_(CryptoTestUtils::ProofSourceForTesting()) {} |
| 1549 |
| 1550 // Before this object is "active", all calls to GetProof will be delegated |
| 1551 // immediately. Once "active", the async ones will be intercepted. This |
| 1552 // distinction is necessary to ensure that GetProof can be called without |
| 1553 // interference during test case setup. |
| 1554 void Activate() { active_ = true; } |
| 1555 |
| 1556 bool GetProof(const IPAddress& server_ip, |
| 1557 const string& hostname, |
| 1558 const string& server_config, |
| 1559 QuicVersion quic_version, |
| 1560 StringPiece chlo_hash, |
| 1561 scoped_refptr<ProofSource::Chain>* out_chain, |
| 1562 string* out_signature, |
| 1563 string* out_leaf_cert_sct) override { |
| 1564 return delegate_->GetProof(server_ip, hostname, server_config, quic_version, |
| 1565 chlo_hash, out_chain, out_signature, |
| 1566 out_leaf_cert_sct); |
| 1567 } |
| 1568 |
| 1569 void GetProof(const IPAddress& server_ip, |
| 1570 const string& hostname, |
| 1571 const string& server_config, |
| 1572 QuicVersion quic_version, |
| 1573 StringPiece chlo_hash, |
| 1574 std::unique_ptr<ProofSource::Callback> callback) override { |
| 1575 if (!active_) { |
| 1576 scoped_refptr<Chain> chain; |
| 1577 string signature; |
| 1578 string leaf_cert_sct; |
| 1579 const bool ok = |
| 1580 GetProof(server_ip, hostname, server_config, quic_version, |
| 1581 chlo_hash.as_string(), &chain, &signature, &leaf_cert_sct); |
| 1582 callback->Run(ok, chain, signature, leaf_cert_sct, |
| 1583 /* details = */ nullptr); |
| 1584 return; |
| 1585 } |
| 1586 |
| 1587 params_.push_back(Params{server_ip, hostname, server_config, quic_version, |
| 1588 chlo_hash.as_string(), std::move(callback)}); |
| 1589 } |
| 1590 |
| 1591 int NumPendingCallbacks() const { return params_.size(); } |
| 1592 |
| 1593 void InvokePendingCallback(int n) { |
| 1594 CHECK(NumPendingCallbacks() > n); |
| 1595 |
| 1596 const Params& params = params_[n]; |
| 1597 |
| 1598 scoped_refptr<ProofSource::Chain> chain; |
| 1599 string signature; |
| 1600 string leaf_cert_sct; |
| 1601 const bool ok = delegate_->GetProof(params.server_ip, params.hostname, |
| 1602 params.server_config, |
| 1603 params.quic_version, params.chlo_hash, |
| 1604 &chain, &signature, &leaf_cert_sct); |
| 1605 |
| 1606 params.callback->Run(ok, chain, signature, leaf_cert_sct, |
| 1607 /* details = */ nullptr); |
| 1608 params_.erase(params_.begin() + n); |
| 1609 } |
| 1610 |
| 1611 private: |
| 1612 std::unique_ptr<ProofSource> delegate_; |
| 1613 bool active_ = false; |
| 1614 |
| 1615 struct Params { |
| 1616 IPAddress server_ip; |
| 1617 string hostname; |
| 1618 string server_config; |
| 1619 QuicVersion quic_version; |
| 1620 string chlo_hash; |
| 1621 std::unique_ptr<ProofSource::Callback> callback; |
| 1622 }; |
| 1623 |
| 1624 std::vector<Params> params_; |
| 1625 }; |
| 1626 |
| 1627 // Test which exercises the async GetProof codepaths, especially in the context |
| 1628 // of stateless rejection. |
| 1629 class AsyncGetProofTest : public QuicDispatcherTest { |
| 1630 public: |
| 1631 AsyncGetProofTest() |
| 1632 : QuicDispatcherTest( |
| 1633 std::unique_ptr<FakeProofSource>(new FakeProofSource())), |
| 1634 client_addr_(net::test::Loopback4(), 1234), |
| 1635 crypto_config_peer_(&crypto_config_) { |
| 1636 FLAGS_enable_async_get_proof = true; |
| 1637 FLAGS_quic_buffer_packet_till_chlo = true; |
| 1638 FLAGS_enable_quic_stateless_reject_support = true; |
| 1639 FLAGS_quic_use_cheap_stateless_rejects = true; |
| 1640 FLAGS_quic_create_session_after_insertion = true; |
| 1641 } |
| 1642 |
| 1643 void SetUp() override { |
| 1644 QuicDispatcherTest::SetUp(); |
| 1645 |
| 1646 clock_ = QuicDispatcherPeer::GetHelper(dispatcher_.get())->GetClock(); |
| 1647 QuicVersion version = AllSupportedVersions().front(); |
| 1648 chlo_ = CryptoTestUtils::GenerateDefaultInchoateCHLO(clock_, version, |
| 1649 &crypto_config_); |
| 1650 chlo_.SetVector(net::kCOPT, net::QuicTagVector{net::kSREJ}); |
| 1651 // Pass an inchoate CHLO. |
| 1652 CryptoTestUtils::GenerateFullCHLO( |
| 1653 chlo_, &crypto_config_, server_ip_, client_addr_, version, clock_, |
| 1654 &proof_, QuicDispatcherPeer::GetCache(dispatcher_.get()), &full_chlo_); |
| 1655 |
| 1656 GetFakeProofSource()->Activate(); |
| 1657 } |
| 1658 |
| 1659 FakeProofSource* GetFakeProofSource() const { |
| 1660 return static_cast<FakeProofSource*>(crypto_config_peer_.GetProofSource()); |
| 1661 } |
| 1662 |
| 1663 string SerializeFullCHLO() { |
| 1664 return full_chlo_.GetSerialized().AsStringPiece().as_string(); |
| 1665 } |
| 1666 |
| 1667 string SerializeCHLO() { |
| 1668 return chlo_.GetSerialized().AsStringPiece().as_string(); |
| 1669 } |
| 1670 |
| 1671 // Sets up a session, and crypto stream based on the test parameters. |
| 1672 QuicServerSessionBase* GetSession(QuicConnectionId connection_id) { |
| 1673 auto it = sessions_.find(connection_id); |
| 1674 if (it != sessions_.end()) { |
| 1675 return it->second.session; |
| 1676 } |
| 1677 |
| 1678 TestQuicSpdyServerSession* session; |
| 1679 CreateSession(dispatcher_.get(), config_, connection_id, client_addr_, |
| 1680 &mock_helper_, &mock_alarm_factory_, &crypto_config_, |
| 1681 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session); |
| 1682 |
| 1683 std::unique_ptr<MockQuicCryptoServerStream> crypto_stream( |
| 1684 new MockQuicCryptoServerStream( |
| 1685 crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()), |
| 1686 session, session->stream_helper())); |
| 1687 session->SetCryptoStream(crypto_stream.get()); |
| 1688 crypto_stream->SetPeerSupportsStatelessRejects(true); |
| 1689 const bool ok = |
| 1690 sessions_ |
| 1691 .insert(std::make_pair( |
| 1692 connection_id, SessionInfo{session, std::move(crypto_stream)})) |
| 1693 .second; |
| 1694 CHECK(ok); |
| 1695 return session; |
| 1696 } |
| 1697 |
| 1698 protected: |
| 1699 const IPEndPoint client_addr_; |
| 1700 |
| 1701 private: |
| 1702 QuicCryptoServerConfigPeer crypto_config_peer_; |
| 1703 IPAddress server_ip_; |
| 1704 QuicCryptoProof proof_; |
| 1705 const QuicClock* clock_; |
| 1706 CryptoHandshakeMessage chlo_; |
| 1707 CryptoHandshakeMessage full_chlo_; |
| 1708 |
| 1709 struct SessionInfo { |
| 1710 TestQuicSpdyServerSession* session; |
| 1711 std::unique_ptr<MockQuicCryptoServerStream> crypto_stream; |
| 1712 }; |
| 1713 std::map<QuicConnectionId, SessionInfo> sessions_; |
| 1714 }; |
| 1715 |
| 1716 // Test a simple situation of connections which the StatelessRejector will |
| 1717 // accept. |
| 1718 TEST_F(AsyncGetProofTest, BasicAccept) { |
| 1719 QuicConnectionId conn_id = 1; |
| 1720 |
| 1721 testing::MockFunction<void(int check_point)> check; |
| 1722 { |
| 1723 InSequence s; |
| 1724 |
| 1725 EXPECT_CALL(check, Call(1)); |
| 1726 EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id)); |
| 1727 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_addr_)) |
| 1728 .WillOnce(testing::Return(GetSession(conn_id))); |
| 1729 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>( |
| 1730 GetSession(conn_id)->connection()), |
| 1731 ProcessUdpPacket(_, _, _)) |
| 1732 .WillOnce(testing::WithArg<2>( |
| 1733 Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket, |
| 1734 base::Unretained(this), conn_id)))); |
| 1735 |
| 1736 EXPECT_CALL(check, Call(2)); |
| 1737 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>( |
| 1738 GetSession(conn_id)->connection()), |
| 1739 ProcessUdpPacket(_, _, _)) |
| 1740 .WillOnce(testing::WithArg<2>( |
| 1741 Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket, |
| 1742 base::Unretained(this), conn_id)))); |
| 1743 } |
| 1744 |
| 1745 // Send a CHLO that the StatelessRejector will accept. |
| 1746 ProcessPacket(client_addr_, conn_id, true, false, SerializeFullCHLO()); |
| 1747 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); |
| 1748 |
| 1749 check.Call(1); |
| 1750 // Complete the ProofSource::GetProof call and verify that a session is |
| 1751 // created. |
| 1752 GetFakeProofSource()->InvokePendingCallback(0); |
| 1753 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0); |
| 1754 |
| 1755 check.Call(2); |
| 1756 // Verify that a data packet gets processed immediately. |
| 1757 ProcessPacket(client_addr_, conn_id, true, false, "My name is Data"); |
| 1758 } |
| 1759 |
| 1760 // Test a simple situation of connections which the StatelessRejector will |
| 1761 // reject. |
| 1762 TEST_F(AsyncGetProofTest, BasicReject) { |
| 1763 CreateTimeWaitListManager(); |
| 1764 |
| 1765 QuicConnectionId conn_id = 1; |
| 1766 |
| 1767 testing::MockFunction<void(int check_point)> check; |
| 1768 { |
| 1769 InSequence s; |
| 1770 EXPECT_CALL(check, Call(1)); |
| 1771 EXPECT_CALL(*time_wait_list_manager_, |
| 1772 AddConnectionIdToTimeWait(conn_id, _, true, _)); |
| 1773 EXPECT_CALL(*time_wait_list_manager_, |
| 1774 ProcessPacket(_, client_addr_, conn_id, _, _)); |
| 1775 |
| 1776 EXPECT_CALL(check, Call(2)); |
| 1777 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_addr_)) |
| 1778 .Times(0); |
| 1779 EXPECT_CALL(*time_wait_list_manager_, |
| 1780 ProcessPacket(_, client_addr_, conn_id, _, _)); |
| 1781 } |
| 1782 |
| 1783 // Send a CHLO that the StatelessRejector will reject. |
| 1784 ProcessPacket(client_addr_, conn_id, true, false, SerializeCHLO()); |
| 1785 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); |
| 1786 |
| 1787 // Complete the ProofSource::GetProof call and verify that the connection and |
| 1788 // packet are processed by the time wait list manager. |
| 1789 check.Call(1); |
| 1790 GetFakeProofSource()->InvokePendingCallback(0); |
| 1791 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0); |
| 1792 |
| 1793 // Verify that a data packet is passed to the time wait list manager. |
| 1794 check.Call(2); |
| 1795 ProcessPacket(client_addr_, conn_id, true, false, "My name is Data"); |
| 1796 } |
| 1797 |
| 1798 // Test a situation with multiple interleaved connections which the |
| 1799 // StatelessRejector will accept. |
| 1800 TEST_F(AsyncGetProofTest, MultipleAccept) { |
| 1801 QuicConnectionId conn_id_1 = 1; |
| 1802 QuicConnectionId conn_id_2 = 2; |
| 1803 QuicBufferedPacketStore* store = |
| 1804 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get()); |
| 1805 |
| 1806 testing::MockFunction<void(int check_point)> check; |
| 1807 { |
| 1808 InSequence s; |
| 1809 EXPECT_CALL(check, Call(1)); |
| 1810 EXPECT_CALL(*dispatcher_, |
| 1811 ShouldCreateOrBufferPacketForConnection(conn_id_2)); |
| 1812 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_2, client_addr_)) |
| 1813 .WillOnce(testing::Return(GetSession(conn_id_2))); |
| 1814 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>( |
| 1815 GetSession(conn_id_2)->connection()), |
| 1816 ProcessUdpPacket(_, _, _)) |
| 1817 .WillOnce(testing::WithArg<2>( |
| 1818 Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket, |
| 1819 base::Unretained(this), conn_id_2)))); |
| 1820 |
| 1821 EXPECT_CALL(check, Call(2)); |
| 1822 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>( |
| 1823 GetSession(conn_id_2)->connection()), |
| 1824 ProcessUdpPacket(_, _, _)) |
| 1825 .WillOnce(testing::WithArg<2>( |
| 1826 Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket, |
| 1827 base::Unretained(this), conn_id_2)))); |
| 1828 |
| 1829 EXPECT_CALL(check, Call(3)); |
| 1830 EXPECT_CALL(*dispatcher_, |
| 1831 ShouldCreateOrBufferPacketForConnection(conn_id_1)); |
| 1832 |
| 1833 EXPECT_CALL(check, Call(4)); |
| 1834 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_1, client_addr_)) |
| 1835 .WillOnce(testing::Return(GetSession(conn_id_1))); |
| 1836 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>( |
| 1837 GetSession(conn_id_1)->connection()), |
| 1838 ProcessUdpPacket(_, _, _)) |
| 1839 .WillRepeatedly(testing::WithArg<2>( |
| 1840 Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket, |
| 1841 base::Unretained(this), conn_id_1)))); |
| 1842 } |
| 1843 |
| 1844 // Send a CHLO that the StatelessRejector will accept. |
| 1845 ProcessPacket(client_addr_, conn_id_1, true, false, SerializeFullCHLO()); |
| 1846 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); |
| 1847 |
| 1848 // Send another CHLO that the StatelessRejector will accept. |
| 1849 ProcessPacket(client_addr_, conn_id_2, true, false, SerializeFullCHLO()); |
| 1850 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2); |
| 1851 |
| 1852 // Complete the second ProofSource::GetProof call and verify that a session is |
| 1853 // created. |
| 1854 check.Call(1); |
| 1855 GetFakeProofSource()->InvokePendingCallback(1); |
| 1856 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); |
| 1857 |
| 1858 // Verify that a data packet on that connection gets processed immediately. |
| 1859 check.Call(2); |
| 1860 ProcessPacket(client_addr_, conn_id_2, true, false, "My name is Data"); |
| 1861 |
| 1862 // Verify that a data packet on the other connection does not get processed |
| 1863 // yet. |
| 1864 check.Call(3); |
| 1865 ProcessPacket(client_addr_, conn_id_1, true, false, "My name is Data"); |
| 1866 EXPECT_TRUE(store->HasBufferedPackets(conn_id_1)); |
| 1867 EXPECT_FALSE(store->HasBufferedPackets(conn_id_2)); |
| 1868 |
| 1869 // Complete the first ProofSource::GetProof call and verify that a session is |
| 1870 // created and the buffered packet is processed. |
| 1871 check.Call(4); |
| 1872 GetFakeProofSource()->InvokePendingCallback(0); |
| 1873 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0); |
| 1874 } |
| 1875 |
| 1876 // Test a situation with multiple interleaved connections which the |
| 1877 // StatelessRejector will reject. |
| 1878 TEST_F(AsyncGetProofTest, MultipleReject) { |
| 1879 CreateTimeWaitListManager(); |
| 1880 |
| 1881 QuicConnectionId conn_id_1 = 1; |
| 1882 QuicConnectionId conn_id_2 = 2; |
| 1883 QuicBufferedPacketStore* store = |
| 1884 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get()); |
| 1885 |
| 1886 testing::MockFunction<void(int check_point)> check; |
| 1887 { |
| 1888 InSequence s; |
| 1889 |
| 1890 EXPECT_CALL(check, Call(1)); |
| 1891 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_2, client_addr_)) |
| 1892 .Times(0); |
| 1893 EXPECT_CALL(*time_wait_list_manager_, |
| 1894 AddConnectionIdToTimeWait(conn_id_2, _, true, _)); |
| 1895 EXPECT_CALL(*time_wait_list_manager_, |
| 1896 ProcessPacket(_, client_addr_, conn_id_2, _, _)); |
| 1897 |
| 1898 EXPECT_CALL(check, Call(2)); |
| 1899 EXPECT_CALL(*time_wait_list_manager_, |
| 1900 ProcessPacket(_, client_addr_, conn_id_2, _, _)); |
| 1901 |
| 1902 EXPECT_CALL(check, Call(3)); |
| 1903 EXPECT_CALL(*dispatcher_, |
| 1904 ShouldCreateOrBufferPacketForConnection(conn_id_1)); |
| 1905 |
| 1906 EXPECT_CALL(check, Call(4)); |
| 1907 EXPECT_CALL(*time_wait_list_manager_, |
| 1908 AddConnectionIdToTimeWait(conn_id_1, _, true, _)); |
| 1909 EXPECT_CALL(*time_wait_list_manager_, |
| 1910 ProcessPacket(_, client_addr_, conn_id_1, _, _)); |
| 1911 } |
| 1912 |
| 1913 // Send a CHLO that the StatelessRejector will reject. |
| 1914 ProcessPacket(client_addr_, conn_id_1, true, false, SerializeCHLO()); |
| 1915 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); |
| 1916 |
| 1917 // Send another CHLO that the StatelessRejector will reject. |
| 1918 ProcessPacket(client_addr_, conn_id_2, true, false, SerializeCHLO()); |
| 1919 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2); |
| 1920 |
| 1921 // Complete the second ProofSource::GetProof call and verify that the |
| 1922 // connection and packet are processed by the time wait manager. |
| 1923 check.Call(1); |
| 1924 GetFakeProofSource()->InvokePendingCallback(1); |
| 1925 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); |
| 1926 |
| 1927 // Verify that a data packet on that connection gets processed immediately by |
| 1928 // the time wait manager. |
| 1929 check.Call(2); |
| 1930 ProcessPacket(client_addr_, conn_id_2, true, false, "My name is Data"); |
| 1931 |
| 1932 // Verify that a data packet on the first connection gets buffered. |
| 1933 check.Call(3); |
| 1934 ProcessPacket(client_addr_, conn_id_1, true, false, "My name is Data"); |
| 1935 EXPECT_TRUE(store->HasBufferedPackets(conn_id_1)); |
| 1936 EXPECT_FALSE(store->HasBufferedPackets(conn_id_2)); |
| 1937 |
| 1938 // Complete the first ProofSource::GetProof call and verify that the CHLO is |
| 1939 // processed by the time wait manager and the remaining packets are discarded. |
| 1940 check.Call(4); |
| 1941 GetFakeProofSource()->InvokePendingCallback(0); |
| 1942 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0); |
| 1943 EXPECT_FALSE(store->HasBufferedPackets(conn_id_1)); |
| 1944 EXPECT_FALSE(store->HasBufferedPackets(conn_id_2)); |
| 1945 } |
| 1946 |
| 1947 // Test a situation with multiple identical CHLOs which the StatelessRejector |
| 1948 // will reject. |
| 1949 TEST_F(AsyncGetProofTest, MultipleIdenticalReject) { |
| 1950 CreateTimeWaitListManager(); |
| 1951 |
| 1952 QuicConnectionId conn_id_1 = 1; |
| 1953 QuicBufferedPacketStore* store = |
| 1954 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get()); |
| 1955 |
| 1956 testing::MockFunction<void(int check_point)> check; |
| 1957 { |
| 1958 InSequence s; |
| 1959 EXPECT_CALL(check, Call(1)); |
| 1960 EXPECT_CALL(*dispatcher_, |
| 1961 ShouldCreateOrBufferPacketForConnection(conn_id_1)); |
| 1962 |
| 1963 EXPECT_CALL(check, Call(2)); |
| 1964 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_1, client_addr_)) |
| 1965 .Times(0); |
| 1966 EXPECT_CALL(*time_wait_list_manager_, |
| 1967 AddConnectionIdToTimeWait(conn_id_1, _, true, _)); |
| 1968 EXPECT_CALL(*time_wait_list_manager_, |
| 1969 ProcessPacket(_, client_addr_, conn_id_1, _, _)); |
| 1970 } |
| 1971 |
| 1972 // Send a CHLO that the StatelessRejector will reject. |
| 1973 ProcessPacket(client_addr_, conn_id_1, true, false, SerializeCHLO()); |
| 1974 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); |
| 1975 EXPECT_FALSE(store->HasBufferedPackets(conn_id_1)); |
| 1976 |
| 1977 // Send an identical CHLO which should get buffered. |
| 1978 check.Call(1); |
| 1979 ProcessPacket(client_addr_, conn_id_1, true, false, SerializeCHLO()); |
| 1980 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); |
| 1981 EXPECT_TRUE(store->HasBufferedPackets(conn_id_1)); |
| 1982 |
| 1983 // Complete the ProofSource::GetProof call and verify that the CHLO is |
| 1984 // rejected and the copy is discarded. |
| 1985 check.Call(2); |
| 1986 GetFakeProofSource()->InvokePendingCallback(0); |
| 1987 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0); |
| 1988 EXPECT_FALSE(store->HasBufferedPackets(conn_id_1)); |
| 1989 } |
| 1990 |
| 1991 // Test dispatcher behavior when packets time out of the buffer while CHLO |
| 1992 // validation is still pending. |
| 1993 TEST_F(AsyncGetProofTest, BufferTimeout) { |
| 1994 CreateTimeWaitListManager(); |
| 1995 |
| 1996 QuicConnectionId conn_id = 1; |
| 1997 QuicBufferedPacketStore* store = |
| 1998 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get()); |
| 1999 QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock()); |
| 2000 |
| 2001 testing::MockFunction<void(int check_point)> check; |
| 2002 { |
| 2003 InSequence s; |
| 2004 EXPECT_CALL(check, Call(1)); |
| 2005 EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id)); |
| 2006 |
| 2007 EXPECT_CALL(check, Call(2)); |
| 2008 EXPECT_CALL(*time_wait_list_manager_, |
| 2009 ProcessPacket(_, client_addr_, conn_id, _, _)); |
| 2010 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_addr_)) |
| 2011 .Times(0); |
| 2012 } |
| 2013 |
| 2014 // Send a CHLO that the StatelessRejector will accept. |
| 2015 ProcessPacket(client_addr_, conn_id, true, false, SerializeFullCHLO()); |
| 2016 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); |
| 2017 EXPECT_FALSE(store->HasBufferedPackets(conn_id)); |
| 2018 |
| 2019 // Send a data packet that will get buffered |
| 2020 check.Call(1); |
| 2021 ProcessPacket(client_addr_, conn_id, true, false, "My name is Data"); |
| 2022 EXPECT_TRUE(store->HasBufferedPackets(conn_id)); |
| 2023 |
| 2024 // Pretend that enough time has gone by for the packets to get expired out of |
| 2025 // the buffer |
| 2026 mock_helper_.AdvanceTime( |
| 2027 QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs)); |
| 2028 QuicBufferedPacketStorePeer::expiration_alarm(store)->Cancel(); |
| 2029 store->OnExpirationTimeout(); |
| 2030 EXPECT_FALSE(store->HasBufferedPackets(conn_id)); |
| 2031 EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id)); |
| 2032 |
| 2033 // Now allow the CHLO validation to complete, and verify that no connection |
| 2034 // gets created. |
| 2035 check.Call(2); |
| 2036 GetFakeProofSource()->InvokePendingCallback(0); |
| 2037 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0); |
| 2038 EXPECT_FALSE(store->HasBufferedPackets(conn_id)); |
| 2039 EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id)); |
| 2040 } |
| 2041 |
| 2042 // Test behavior when packets time out of the buffer *and* the connection times |
| 2043 // out of the time wait manager while CHLO validation is still pending. This |
| 2044 // *should* be impossible, but anything can happen with timing conditions. |
| 2045 TEST_F(AsyncGetProofTest, TimeWaitTimeout) { |
| 2046 QuicConnectionId conn_id = 1; |
| 2047 QuicBufferedPacketStore* store = |
| 2048 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get()); |
| 2049 QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock()); |
| 2050 CreateTimeWaitListManager(); |
| 2051 QuicTimeWaitListManagerPeer::set_clock(time_wait_list_manager_, |
| 2052 mock_helper_.GetClock()); |
| 2053 |
| 2054 testing::MockFunction<void(int check_point)> check; |
| 2055 { |
| 2056 InSequence s; |
| 2057 EXPECT_CALL(check, Call(1)); |
| 2058 EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id)); |
| 2059 |
| 2060 EXPECT_CALL(check, Call(2)); |
| 2061 EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id)); |
| 2062 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_addr_)) |
| 2063 .WillOnce(testing::Return(GetSession(conn_id))); |
| 2064 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>( |
| 2065 GetSession(conn_id)->connection()), |
| 2066 ProcessUdpPacket(_, _, _)) |
| 2067 .WillOnce(testing::WithArg<2>( |
| 2068 Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket, |
| 2069 base::Unretained(this), conn_id)))); |
| 2070 } |
| 2071 |
| 2072 // Send a CHLO that the StatelessRejector will accept. |
| 2073 ProcessPacket(client_addr_, conn_id, true, false, SerializeFullCHLO()); |
| 2074 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1); |
| 2075 EXPECT_FALSE(store->HasBufferedPackets(conn_id)); |
| 2076 |
| 2077 // Send a data packet that will get buffered |
| 2078 check.Call(1); |
| 2079 ProcessPacket(client_addr_, conn_id, true, false, "My name is Data"); |
| 2080 EXPECT_TRUE(store->HasBufferedPackets(conn_id)); |
| 2081 |
| 2082 // Pretend that enough time has gone by for the packets to get expired out of |
| 2083 // the buffer |
| 2084 mock_helper_.AdvanceTime( |
| 2085 QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs)); |
| 2086 QuicBufferedPacketStorePeer::expiration_alarm(store)->Cancel(); |
| 2087 store->OnExpirationTimeout(); |
| 2088 EXPECT_FALSE(store->HasBufferedPackets(conn_id)); |
| 2089 EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id)); |
| 2090 |
| 2091 // Pretend that enough time has gone by for the connection ID to be removed |
| 2092 // from the time wait manager |
| 2093 mock_helper_.AdvanceTime( |
| 2094 QuicTimeWaitListManagerPeer::time_wait_period(time_wait_list_manager_)); |
| 2095 QuicTimeWaitListManagerPeer::expiration_alarm(time_wait_list_manager_) |
| 2096 ->Cancel(); |
| 2097 time_wait_list_manager_->CleanUpOldConnectionIds(); |
| 2098 EXPECT_FALSE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id)); |
| 2099 |
| 2100 // Now allow the CHLO validation to complete. Expect that a connection is |
| 2101 // indeed created, since QUIC has forgotten that this connection ever existed. |
| 2102 // This is a miniscule corner case which should never happen in the wild, so |
| 2103 // really we are just verifying that the dispatcher does not explode in this |
| 2104 // situation. |
| 2105 check.Call(2); |
| 2106 GetFakeProofSource()->InvokePendingCallback(0); |
| 2107 ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0); |
| 2108 EXPECT_FALSE(store->HasBufferedPackets(conn_id)); |
| 2109 EXPECT_FALSE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id)); |
| 2110 } |
| 2111 |
1534 } // namespace | 2112 } // namespace |
1535 } // namespace test | 2113 } // namespace test |
1536 } // namespace net | 2114 } // namespace net |
OLD | NEW |