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_piece.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_test_utils.h" | 21 #include "net/quic/test_tools/quic_test_utils.h" |
| 22 #include "net/test/gtest_util.h" |
21 #include "net/tools/epoll_server/epoll_server.h" | 23 #include "net/tools/epoll_server/epoll_server.h" |
| 24 #include "net/tools/quic/chlo_extractor.h" |
22 #include "net/tools/quic/quic_epoll_alarm_factory.h" | 25 #include "net/tools/quic/quic_epoll_alarm_factory.h" |
23 #include "net/tools/quic/quic_epoll_connection_helper.h" | 26 #include "net/tools/quic/quic_epoll_connection_helper.h" |
24 #include "net/tools/quic/quic_packet_writer_wrapper.h" | 27 #include "net/tools/quic/quic_packet_writer_wrapper.h" |
25 #include "net/tools/quic/quic_simple_server_session_helper.h" | 28 #include "net/tools/quic/quic_simple_server_session_helper.h" |
26 #include "net/tools/quic/quic_time_wait_list_manager.h" | 29 #include "net/tools/quic/quic_time_wait_list_manager.h" |
| 30 #include "net/tools/quic/stateless_rejector.h" |
27 #include "net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h" | 31 #include "net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h" |
28 #include "net/tools/quic/test_tools/quic_dispatcher_peer.h" | 32 #include "net/tools/quic/test_tools/quic_dispatcher_peer.h" |
29 #include "testing/gmock/include/gmock/gmock.h" | 33 #include "testing/gmock/include/gmock/gmock.h" |
| 34 #include "testing/gmock_mutant.h" |
30 #include "testing/gtest/include/gtest/gtest.h" | 35 #include "testing/gtest/include/gtest/gtest.h" |
31 | 36 |
| 37 using base::IntToString; |
32 using base::StringPiece; | 38 using base::StringPiece; |
33 using net::EpollServer; | 39 using net::EpollServer; |
34 using net::test::ConstructEncryptedPacket; | 40 using net::test::ConstructEncryptedPacket; |
35 using net::test::CryptoTestUtils; | 41 using net::test::CryptoTestUtils; |
36 using net::test::MockQuicConnection; | 42 using net::test::MockQuicConnection; |
37 using net::test::MockQuicConnectionHelper; | 43 using net::test::MockQuicConnectionHelper; |
38 using net::test::ValueRestore; | 44 using net::test::ValueRestore; |
| 45 using std::ostream; |
39 using std::string; | 46 using std::string; |
40 using std::vector; | 47 using std::vector; |
| 48 using testing::CreateFunctor; |
41 using testing::DoAll; | 49 using testing::DoAll; |
42 using testing::InSequence; | 50 using testing::InSequence; |
43 using testing::Invoke; | 51 using testing::Invoke; |
44 using testing::WithoutArgs; | 52 using testing::WithoutArgs; |
45 using testing::_; | 53 using testing::_; |
46 | 54 |
| 55 static const size_t kDefaultMaxConnectionsInStore = 100; |
| 56 |
47 namespace net { | 57 namespace net { |
48 namespace test { | 58 namespace test { |
49 namespace { | 59 namespace { |
50 | 60 |
51 class TestQuicSpdyServerSession : public QuicServerSessionBase { | 61 class TestQuicSpdyServerSession : public QuicServerSessionBase { |
52 public: | 62 public: |
53 TestQuicSpdyServerSession(const QuicConfig& config, | 63 TestQuicSpdyServerSession(const QuicConfig& config, |
54 QuicConnection* connection, | 64 QuicConnection* connection, |
55 const QuicCryptoServerConfig* crypto_config, | 65 const QuicCryptoServerConfig* crypto_config, |
56 QuicCompressedCertsCache* compressed_certs_cache) | 66 QuicCompressedCertsCache* compressed_certs_cache) |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 new QuicEpollConnectionHelper(eps, QuicAllocator::BUFFER_POOL)), | 118 new QuicEpollConnectionHelper(eps, QuicAllocator::BUFFER_POOL)), |
109 std::unique_ptr<QuicServerSessionBase::Helper>( | 119 std::unique_ptr<QuicServerSessionBase::Helper>( |
110 new QuicSimpleServerSessionHelper(QuicRandom::GetInstance())), | 120 new QuicSimpleServerSessionHelper(QuicRandom::GetInstance())), |
111 std::unique_ptr<QuicEpollAlarmFactory>( | 121 std::unique_ptr<QuicEpollAlarmFactory>( |
112 new QuicEpollAlarmFactory(eps))) {} | 122 new QuicEpollAlarmFactory(eps))) {} |
113 | 123 |
114 MOCK_METHOD2(CreateQuicSession, | 124 MOCK_METHOD2(CreateQuicSession, |
115 QuicServerSessionBase*(QuicConnectionId connection_id, | 125 QuicServerSessionBase*(QuicConnectionId connection_id, |
116 const IPEndPoint& client_address)); | 126 const IPEndPoint& client_address)); |
117 | 127 |
| 128 MOCK_METHOD1(OnNewConnectionAdded, void(QuicConnectionId connection_id)); |
| 129 |
118 using QuicDispatcher::current_server_address; | 130 using QuicDispatcher::current_server_address; |
119 using QuicDispatcher::current_client_address; | 131 using QuicDispatcher::current_client_address; |
120 }; | 132 }; |
121 | 133 |
122 // A Connection class which unregisters the session from the dispatcher when | 134 // A Connection class which unregisters the session from the dispatcher when |
123 // sending connection close. | 135 // sending connection close. |
124 // It'd be slightly more realistic to do this from the Session but it would | 136 // It'd be slightly more realistic to do this from the Session but it would |
125 // involve a lot more mocking. | 137 // involve a lot more mocking. |
126 class MockServerConnection : public MockQuicConnection { | 138 class MockServerConnection : public MockQuicConnection { |
127 public: | 139 public: |
(...skipping 10 matching lines...) Expand all Loading... |
138 void UnregisterOnConnectionClosed() { | 150 void UnregisterOnConnectionClosed() { |
139 LOG(ERROR) << "Unregistering " << connection_id(); | 151 LOG(ERROR) << "Unregistering " << connection_id(); |
140 dispatcher_->OnConnectionClosed(connection_id(), QUIC_NO_ERROR, | 152 dispatcher_->OnConnectionClosed(connection_id(), QUIC_NO_ERROR, |
141 "Unregistering."); | 153 "Unregistering."); |
142 } | 154 } |
143 | 155 |
144 private: | 156 private: |
145 QuicDispatcher* dispatcher_; | 157 QuicDispatcher* dispatcher_; |
146 }; | 158 }; |
147 | 159 |
148 QuicServerSessionBase* CreateSession( | |
149 QuicDispatcher* dispatcher, | |
150 const QuicConfig& config, | |
151 QuicConnectionId connection_id, | |
152 const IPEndPoint& client_address, | |
153 MockQuicConnectionHelper* helper, | |
154 MockAlarmFactory* alarm_factory, | |
155 const QuicCryptoServerConfig* crypto_config, | |
156 QuicCompressedCertsCache* compressed_certs_cache, | |
157 TestQuicSpdyServerSession** session) { | |
158 MockServerConnection* connection = new MockServerConnection( | |
159 connection_id, helper, alarm_factory, dispatcher); | |
160 *session = new TestQuicSpdyServerSession(config, connection, crypto_config, | |
161 compressed_certs_cache); | |
162 connection->set_visitor(*session); | |
163 ON_CALL(*connection, CloseConnection(_, _, _)) | |
164 .WillByDefault(WithoutArgs(Invoke( | |
165 connection, &MockServerConnection::UnregisterOnConnectionClosed))); | |
166 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>((*session)->connection()), | |
167 ProcessUdpPacket(_, client_address, _)); | |
168 | |
169 return *session; | |
170 } | |
171 | |
172 class QuicDispatcherTest : public ::testing::Test { | 160 class QuicDispatcherTest : public ::testing::Test { |
173 public: | 161 public: |
174 QuicDispatcherTest() | 162 QuicDispatcherTest() |
175 : helper_(&eps_, QuicAllocator::BUFFER_POOL), | 163 : helper_(&eps_, QuicAllocator::BUFFER_POOL), |
176 alarm_factory_(&eps_), | 164 alarm_factory_(&eps_), |
177 version_manager_(QuicSupportedVersions()), | 165 version_manager_(QuicSupportedVersions()), |
178 crypto_config_(QuicCryptoServerConfig::TESTING, | 166 crypto_config_(QuicCryptoServerConfig::TESTING, |
179 QuicRandom::GetInstance(), | 167 QuicRandom::GetInstance(), |
180 CryptoTestUtils::ProofSourceForTesting()), | 168 CryptoTestUtils::ProofSourceForTesting()), |
181 dispatcher_(new TestDispatcher(config_, | 169 dispatcher_(new TestDispatcher(config_, |
182 &crypto_config_, | 170 &crypto_config_, |
183 &version_manager_, | 171 &version_manager_, |
184 &eps_)), | 172 &eps_)), |
185 time_wait_list_manager_(nullptr), | 173 time_wait_list_manager_(nullptr), |
186 session1_(nullptr), | 174 session1_(nullptr), |
187 session2_(nullptr) { | 175 session2_(nullptr), |
| 176 store_(nullptr) {} |
| 177 |
| 178 void SetUp() override { |
188 dispatcher_->InitializeWithWriter(new QuicDefaultPacketWriter(1)); | 179 dispatcher_->InitializeWithWriter(new QuicDefaultPacketWriter(1)); |
189 } | 180 } |
190 | 181 |
191 ~QuicDispatcherTest() override {} | 182 ~QuicDispatcherTest() override {} |
192 | 183 |
193 MockQuicConnection* connection1() { | 184 MockQuicConnection* connection1() { |
194 return reinterpret_cast<MockQuicConnection*>(session1_->connection()); | 185 return reinterpret_cast<MockQuicConnection*>(session1_->connection()); |
195 } | 186 } |
196 | 187 |
197 MockQuicConnection* connection2() { | 188 MockQuicConnection* connection2() { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 QuicConnectionIdLength connection_id_length, | 240 QuicConnectionIdLength connection_id_length, |
250 QuicPacketNumberLength packet_number_length, | 241 QuicPacketNumberLength packet_number_length, |
251 QuicPacketNumber packet_number) { | 242 QuicPacketNumber packet_number) { |
252 QuicVersionVector versions(SupportedVersions(version)); | 243 QuicVersionVector versions(SupportedVersions(version)); |
253 std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket( | 244 std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket( |
254 connection_id, has_version_flag, false, false, 0, packet_number, data, | 245 connection_id, has_version_flag, false, false, 0, packet_number, data, |
255 connection_id_length, packet_number_length, &versions)); | 246 connection_id_length, packet_number_length, &versions)); |
256 std::unique_ptr<QuicReceivedPacket> received_packet( | 247 std::unique_ptr<QuicReceivedPacket> received_packet( |
257 ConstructReceivedPacket(*packet, helper_.GetClock()->Now())); | 248 ConstructReceivedPacket(*packet, helper_.GetClock()->Now())); |
258 | 249 |
259 data_ = string(packet->data(), packet->length()); | 250 if (ChloExtractor::Extract(*packet, versions, nullptr)) { |
| 251 // Add CHLO packet to the beginning to be verified first, because it is |
| 252 // also processed first by new session. |
| 253 data_connection_map_[connection_id].push_front( |
| 254 string(packet->data(), packet->length())); |
| 255 } else { |
| 256 // For non-CHLO, always append to last. |
| 257 data_connection_map_[connection_id].push_back( |
| 258 string(packet->data(), packet->length())); |
| 259 } |
260 dispatcher_->ProcessPacket(server_address_, client_address, | 260 dispatcher_->ProcessPacket(server_address_, client_address, |
261 *received_packet); | 261 *received_packet); |
262 } | 262 } |
263 | 263 |
264 void ValidatePacket(const QuicEncryptedPacket& packet) { | 264 void ValidatePacket(QuicConnectionId conn_id, |
265 EXPECT_EQ(data_.length(), packet.AsStringPiece().length()); | 265 const QuicEncryptedPacket& packet) { |
266 EXPECT_EQ(data_, packet.AsStringPiece()); | 266 EXPECT_EQ(data_connection_map_[conn_id].front().length(), |
| 267 packet.AsStringPiece().length()); |
| 268 EXPECT_EQ(data_connection_map_[conn_id].front(), packet.AsStringPiece()); |
| 269 data_connection_map_[conn_id].pop_front(); |
| 270 } |
| 271 |
| 272 QuicServerSessionBase* CreateSession( |
| 273 QuicDispatcher* dispatcher, |
| 274 const QuicConfig& config, |
| 275 QuicConnectionId connection_id, |
| 276 const IPEndPoint& client_address, |
| 277 MockQuicConnectionHelper* helper, |
| 278 MockAlarmFactory* alarm_factory, |
| 279 const QuicCryptoServerConfig* crypto_config, |
| 280 QuicCompressedCertsCache* compressed_certs_cache, |
| 281 TestQuicSpdyServerSession** session) { |
| 282 MockServerConnection* connection = new MockServerConnection( |
| 283 connection_id, helper, alarm_factory, dispatcher); |
| 284 *session = new TestQuicSpdyServerSession(config, connection, crypto_config, |
| 285 compressed_certs_cache); |
| 286 connection->set_visitor(*session); |
| 287 ON_CALL(*connection, CloseConnection(_, _, _)) |
| 288 .WillByDefault(WithoutArgs(Invoke( |
| 289 connection, &MockServerConnection::UnregisterOnConnectionClosed))); |
| 290 return *session; |
267 } | 291 } |
268 | 292 |
269 void CreateTimeWaitListManager() { | 293 void CreateTimeWaitListManager() { |
270 time_wait_list_manager_ = new MockTimeWaitListManager( | 294 time_wait_list_manager_ = new MockTimeWaitListManager( |
271 QuicDispatcherPeer::GetWriter(dispatcher_.get()), dispatcher_.get(), | 295 QuicDispatcherPeer::GetWriter(dispatcher_.get()), dispatcher_.get(), |
272 &helper_, &alarm_factory_); | 296 &helper_, &alarm_factory_); |
273 // dispatcher_ takes the ownership of time_wait_list_manager_. | 297 // dispatcher_ takes the ownership of time_wait_list_manager_. |
274 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(), | 298 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(), |
275 time_wait_list_manager_); | 299 time_wait_list_manager_); |
276 } | 300 } |
(...skipping 10 matching lines...) Expand all Loading... |
287 QuicEpollAlarmFactory alarm_factory_; | 311 QuicEpollAlarmFactory alarm_factory_; |
288 MockAlarmFactory mock_alarm_factory_; | 312 MockAlarmFactory mock_alarm_factory_; |
289 QuicConfig config_; | 313 QuicConfig config_; |
290 QuicVersionManager version_manager_; | 314 QuicVersionManager version_manager_; |
291 QuicCryptoServerConfig crypto_config_; | 315 QuicCryptoServerConfig crypto_config_; |
292 IPEndPoint server_address_; | 316 IPEndPoint server_address_; |
293 std::unique_ptr<TestDispatcher> dispatcher_; | 317 std::unique_ptr<TestDispatcher> dispatcher_; |
294 MockTimeWaitListManager* time_wait_list_manager_; | 318 MockTimeWaitListManager* time_wait_list_manager_; |
295 TestQuicSpdyServerSession* session1_; | 319 TestQuicSpdyServerSession* session1_; |
296 TestQuicSpdyServerSession* session2_; | 320 TestQuicSpdyServerSession* session2_; |
297 string data_; | 321 std::map<QuicConnectionId, std::list<string>> data_connection_map_; |
| 322 QuicBufferedPacketStore* store_; |
298 }; | 323 }; |
299 | 324 |
300 TEST_F(QuicDispatcherTest, ProcessPackets) { | 325 TEST_F(QuicDispatcherTest, ProcessPackets) { |
301 IPEndPoint client_address(net::test::Loopback4(), 1); | 326 IPEndPoint client_address(net::test::Loopback4(), 1); |
302 server_address_ = IPEndPoint(net::test::Any4(), 5); | 327 server_address_ = IPEndPoint(net::test::Any4(), 5); |
303 | 328 |
304 EXPECT_CALL(*dispatcher_, CreateQuicSession(1, client_address)) | 329 EXPECT_CALL(*dispatcher_, CreateQuicSession(1, client_address)) |
305 .WillOnce(testing::Return(CreateSession( | 330 .WillOnce(testing::Return(CreateSession( |
306 dispatcher_.get(), config_, 1, client_address, &mock_helper_, | 331 dispatcher_.get(), config_, 1, client_address, &mock_helper_, |
307 &mock_alarm_factory_, &crypto_config_, | 332 &mock_alarm_factory_, &crypto_config_, |
308 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); | 333 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); |
| 334 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), |
| 335 ProcessUdpPacket(_, _, _)) |
| 336 .WillOnce(testing::WithArgs<2>(Invoke(CreateFunctor( |
| 337 &QuicDispatcherTest::ValidatePacket, base::Unretained(this), 1)))); |
309 ProcessPacket(client_address, 1, true, false, SerializeCHLO()); | 338 ProcessPacket(client_address, 1, true, false, SerializeCHLO()); |
310 EXPECT_EQ(client_address, dispatcher_->current_client_address()); | 339 EXPECT_EQ(client_address, dispatcher_->current_client_address()); |
311 EXPECT_EQ(server_address_, dispatcher_->current_server_address()); | 340 EXPECT_EQ(server_address_, dispatcher_->current_server_address()); |
312 | 341 |
313 EXPECT_CALL(*dispatcher_, CreateQuicSession(2, client_address)) | 342 EXPECT_CALL(*dispatcher_, CreateQuicSession(2, client_address)) |
314 .WillOnce(testing::Return(CreateSession( | 343 .WillOnce(testing::Return(CreateSession( |
315 dispatcher_.get(), config_, 2, client_address, &mock_helper_, | 344 dispatcher_.get(), config_, 2, client_address, &mock_helper_, |
316 &mock_alarm_factory_, &crypto_config_, | 345 &mock_alarm_factory_, &crypto_config_, |
317 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_))); | 346 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_))); |
| 347 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()), |
| 348 ProcessUdpPacket(_, _, _)) |
| 349 .WillOnce(testing::WithArgs<2>(Invoke(CreateFunctor( |
| 350 &QuicDispatcherTest::ValidatePacket, base::Unretained(this), 2)))); |
318 ProcessPacket(client_address, 2, true, false, SerializeCHLO()); | 351 ProcessPacket(client_address, 2, true, false, SerializeCHLO()); |
319 | 352 |
320 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), | 353 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), |
321 ProcessUdpPacket(_, _, _)) | 354 ProcessUdpPacket(_, _, _)) |
322 .Times(1) | 355 .Times(1) |
323 .WillOnce(testing::WithArgs<2>( | 356 .WillOnce(testing::WithArgs<2>(Invoke(CreateFunctor( |
324 Invoke(this, &QuicDispatcherTest::ValidatePacket))); | 357 &QuicDispatcherTest::ValidatePacket, base::Unretained(this), 1)))); |
325 ProcessPacket(client_address, 1, false, false, "data"); | 358 ProcessPacket(client_address, 1, false, false, "data"); |
326 } | 359 } |
327 | 360 |
328 TEST_F(QuicDispatcherTest, StatelessVersionNegotiation) { | 361 TEST_F(QuicDispatcherTest, StatelessVersionNegotiation) { |
329 IPEndPoint client_address(net::test::Loopback4(), 1); | 362 IPEndPoint client_address(net::test::Loopback4(), 1); |
330 server_address_ = IPEndPoint(net::test::Any4(), 5); | 363 server_address_ = IPEndPoint(net::test::Any4(), 5); |
331 | 364 |
332 EXPECT_CALL(*dispatcher_, CreateQuicSession(1, client_address)).Times(0); | 365 EXPECT_CALL(*dispatcher_, CreateQuicSession(1, client_address)).Times(0); |
333 QuicVersion version = static_cast<QuicVersion>(QuicVersionMin() - 1); | 366 QuicVersion version = static_cast<QuicVersion>(QuicVersionMin() - 1); |
334 ProcessPacket(client_address, 1, true, version, SerializeCHLO(), | 367 ProcessPacket(client_address, 1, true, version, SerializeCHLO(), |
335 PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, 1); | 368 PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, 1); |
336 } | 369 } |
337 | 370 |
338 TEST_F(QuicDispatcherTest, Shutdown) { | 371 TEST_F(QuicDispatcherTest, Shutdown) { |
339 IPEndPoint client_address(net::test::Loopback4(), 1); | 372 IPEndPoint client_address(net::test::Loopback4(), 1); |
340 | 373 |
341 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, client_address)) | 374 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, client_address)) |
342 .WillOnce(testing::Return(CreateSession( | 375 .WillOnce(testing::Return(CreateSession( |
343 dispatcher_.get(), config_, 1, client_address, &mock_helper_, | 376 dispatcher_.get(), config_, 1, client_address, &mock_helper_, |
344 &mock_alarm_factory_, &crypto_config_, | 377 &mock_alarm_factory_, &crypto_config_, |
345 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); | 378 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); |
| 379 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), |
| 380 ProcessUdpPacket(_, _, _)) |
| 381 .WillOnce(testing::WithArgs<2>(Invoke(CreateFunctor( |
| 382 &QuicDispatcherTest::ValidatePacket, base::Unretained(this), 1)))); |
346 | 383 |
347 ProcessPacket(client_address, 1, true, false, SerializeCHLO()); | 384 ProcessPacket(client_address, 1, true, false, SerializeCHLO()); |
348 | 385 |
349 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), | 386 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), |
350 CloseConnection(QUIC_PEER_GOING_AWAY, _, _)); | 387 CloseConnection(QUIC_PEER_GOING_AWAY, _, _)); |
351 | 388 |
352 dispatcher_->Shutdown(); | 389 dispatcher_->Shutdown(); |
353 } | 390 } |
354 | 391 |
355 TEST_F(QuicDispatcherTest, TimeWaitListManager) { | 392 TEST_F(QuicDispatcherTest, TimeWaitListManager) { |
356 CreateTimeWaitListManager(); | 393 CreateTimeWaitListManager(); |
357 | 394 |
358 // Create a new session. | 395 // Create a new session. |
359 IPEndPoint client_address(net::test::Loopback4(), 1); | 396 IPEndPoint client_address(net::test::Loopback4(), 1); |
360 QuicConnectionId connection_id = 1; | 397 QuicConnectionId connection_id = 1; |
361 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) | 398 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) |
362 .WillOnce(testing::Return(CreateSession( | 399 .WillOnce(testing::Return(CreateSession( |
363 dispatcher_.get(), config_, connection_id, client_address, | 400 dispatcher_.get(), config_, connection_id, client_address, |
364 &mock_helper_, &mock_alarm_factory_, &crypto_config_, | 401 &mock_helper_, &mock_alarm_factory_, &crypto_config_, |
365 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); | 402 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); |
| 403 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), |
| 404 ProcessUdpPacket(_, _, _)) |
| 405 .WillOnce(testing::WithArgs<2>(Invoke(CreateFunctor( |
| 406 &QuicDispatcherTest::ValidatePacket, base::Unretained(this), 1)))); |
| 407 |
366 ProcessPacket(client_address, connection_id, true, false, SerializeCHLO()); | 408 ProcessPacket(client_address, connection_id, true, false, SerializeCHLO()); |
367 | 409 |
368 // Close the connection by sending public reset packet. | 410 // Close the connection by sending public reset packet. |
369 QuicPublicResetPacket packet; | 411 QuicPublicResetPacket packet; |
370 packet.public_header.connection_id = connection_id; | 412 packet.public_header.connection_id = connection_id; |
371 packet.public_header.reset_flag = true; | 413 packet.public_header.reset_flag = true; |
372 packet.public_header.version_flag = false; | 414 packet.public_header.version_flag = false; |
373 packet.rejected_packet_number = 19191; | 415 packet.rejected_packet_number = 19191; |
374 packet.nonce_proof = 132232; | 416 packet.nonce_proof = 132232; |
375 std::unique_ptr<QuicEncryptedPacket> encrypted( | 417 std::unique_ptr<QuicEncryptedPacket> encrypted( |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) { | 475 TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) { |
434 IPEndPoint client_address(net::test::Loopback4(), 1); | 476 IPEndPoint client_address(net::test::Loopback4(), 1); |
435 QuicConnectionId connection_id = 1; | 477 QuicConnectionId connection_id = 1; |
436 server_address_ = IPEndPoint(net::test::Any4(), 5); | 478 server_address_ = IPEndPoint(net::test::Any4(), 5); |
437 | 479 |
438 EXPECT_CALL(*dispatcher_, CreateQuicSession(1, client_address)) | 480 EXPECT_CALL(*dispatcher_, CreateQuicSession(1, client_address)) |
439 .WillOnce(testing::Return(CreateSession( | 481 .WillOnce(testing::Return(CreateSession( |
440 dispatcher_.get(), config_, 1, client_address, &mock_helper_, | 482 dispatcher_.get(), config_, 1, client_address, &mock_helper_, |
441 &mock_alarm_factory_, &crypto_config_, | 483 &mock_alarm_factory_, &crypto_config_, |
442 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); | 484 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); |
| 485 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), |
| 486 ProcessUdpPacket(_, _, _)) |
| 487 .WillOnce(testing::WithArgs<2>(Invoke(CreateFunctor( |
| 488 &QuicDispatcherTest::ValidatePacket, base::Unretained(this), 1)))); |
443 // A packet whose packet number is the largest that is allowed to start a | 489 // A packet whose packet number is the largest that is allowed to start a |
444 // connection. | 490 // connection. |
445 ProcessPacket(client_address, connection_id, true, false, SerializeCHLO(), | 491 ProcessPacket(client_address, connection_id, true, false, SerializeCHLO(), |
446 PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, | 492 PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, |
447 kDefaultPathId, | 493 kDefaultPathId, |
448 QuicDispatcher::kMaxReasonableInitialPacketNumber); | 494 QuicDispatcher::kMaxReasonableInitialPacketNumber); |
449 EXPECT_EQ(client_address, dispatcher_->current_client_address()); | 495 EXPECT_EQ(client_address, dispatcher_->current_client_address()); |
450 EXPECT_EQ(server_address_, dispatcher_->current_server_address()); | 496 EXPECT_EQ(server_address_, dispatcher_->current_server_address()); |
451 } | 497 } |
452 | 498 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 } | 575 } |
530 } | 576 } |
531 } | 577 } |
532 return params; | 578 return params; |
533 } | 579 } |
534 | 580 |
535 class QuicDispatcherStatelessRejectTest | 581 class QuicDispatcherStatelessRejectTest |
536 : public QuicDispatcherTest, | 582 : public QuicDispatcherTest, |
537 public ::testing::WithParamInterface<StatelessRejectTestParams> { | 583 public ::testing::WithParamInterface<StatelessRejectTestParams> { |
538 public: | 584 public: |
539 QuicDispatcherStatelessRejectTest() : crypto_stream1_(nullptr) {} | 585 QuicDispatcherStatelessRejectTest() |
| 586 : QuicDispatcherTest(), crypto_stream1_(nullptr) {} |
540 | 587 |
541 ~QuicDispatcherStatelessRejectTest() override { | 588 ~QuicDispatcherStatelessRejectTest() override { |
542 if (crypto_stream1_) { | 589 if (crypto_stream1_) { |
543 delete crypto_stream1_; | 590 delete crypto_stream1_; |
544 } | 591 } |
545 } | 592 } |
546 | 593 |
547 // This test setup assumes that all testing will be done using | 594 // This test setup assumes that all testing will be done using |
548 // crypto_stream1_. | 595 // crypto_stream1_. |
549 void SetUp() override { | 596 void SetUp() override { |
| 597 QuicDispatcherTest::SetUp(); |
550 FLAGS_enable_quic_stateless_reject_support = | 598 FLAGS_enable_quic_stateless_reject_support = |
551 GetParam().enable_stateless_rejects_via_flag; | 599 GetParam().enable_stateless_rejects_via_flag; |
552 } | 600 } |
553 | 601 |
554 // Returns true or false, depending on whether the server will emit | 602 // Returns true or false, depending on whether the server will emit |
555 // a stateless reject, depending upon the parameters of the test. | 603 // a stateless reject, depending upon the parameters of the test. |
556 bool ExpectStatelessReject() { | 604 bool ExpectStatelessReject() { |
557 return GetParam().enable_stateless_rejects_via_flag && | 605 return GetParam().enable_stateless_rejects_via_flag && |
558 !GetParam().crypto_handshake_successful && | 606 !GetParam().crypto_handshake_successful && |
559 GetParam().client_supports_statelesss_rejects; | 607 GetParam().client_supports_statelesss_rejects; |
(...skipping 30 matching lines...) Expand all Loading... |
590 ::testing::ValuesIn(GetStatelessRejectTestParams())); | 638 ::testing::ValuesIn(GetStatelessRejectTestParams())); |
591 | 639 |
592 TEST_P(QuicDispatcherStatelessRejectTest, ParameterizedBasicTest) { | 640 TEST_P(QuicDispatcherStatelessRejectTest, ParameterizedBasicTest) { |
593 CreateTimeWaitListManager(); | 641 CreateTimeWaitListManager(); |
594 | 642 |
595 IPEndPoint client_address(net::test::Loopback4(), 1); | 643 IPEndPoint client_address(net::test::Loopback4(), 1); |
596 QuicConnectionId connection_id = 1; | 644 QuicConnectionId connection_id = 1; |
597 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) | 645 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) |
598 .WillOnce(testing::Return( | 646 .WillOnce(testing::Return( |
599 CreateSessionBasedOnTestParams(connection_id, client_address))); | 647 CreateSessionBasedOnTestParams(connection_id, client_address))); |
600 | 648 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), |
| 649 ProcessUdpPacket(_, _, _)) |
| 650 .WillOnce(testing::WithArgs<2>( |
| 651 Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket, |
| 652 base::Unretained(this), connection_id)))); |
601 // Process the first packet for the connection. | 653 // Process the first packet for the connection. |
602 ProcessPacket(client_address, connection_id, true, false, SerializeCHLO()); | 654 ProcessPacket(client_address, connection_id, true, false, SerializeCHLO()); |
603 if (ExpectStatelessReject()) { | 655 if (ExpectStatelessReject()) { |
604 // If this is a stateless reject, the crypto stream will close the | 656 // If this is a stateless reject, the crypto stream will close the |
605 // connection. | 657 // connection. |
606 session1_->connection()->CloseConnection( | 658 session1_->connection()->CloseConnection( |
607 QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, "stateless reject", | 659 QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, "stateless reject", |
608 ConnectionCloseBehavior::SILENT_CLOSE); | 660 ConnectionCloseBehavior::SILENT_CLOSE); |
609 } | 661 } |
610 | 662 |
611 // Send a second packet and check the results. If this is a stateless reject, | 663 // Send a second packet and check the results. If this is a stateless reject, |
612 // the existing connection_id will go on the time-wait list. | 664 // the existing connection_id will go on the time-wait list. |
613 EXPECT_EQ(ExpectStatelessReject(), | 665 EXPECT_EQ(ExpectStatelessReject(), |
614 time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); | 666 time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); |
615 if (ExpectStatelessReject()) { | 667 if (ExpectStatelessReject()) { |
616 // The second packet will be processed on the time-wait list. | 668 // The second packet will be processed on the time-wait list. |
617 EXPECT_CALL(*time_wait_list_manager_, | 669 EXPECT_CALL(*time_wait_list_manager_, |
618 ProcessPacket(_, _, connection_id, _, _)) | 670 ProcessPacket(_, _, connection_id, _, _)) |
619 .Times(1); | 671 .Times(1); |
620 } else { | 672 } else { |
621 // The second packet will trigger a packet-validation | 673 // The second packet will trigger a packet-validation |
622 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), | 674 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), |
623 ProcessUdpPacket(_, _, _)) | 675 ProcessUdpPacket(_, _, _)) |
624 .Times(1) | 676 .Times(1) |
625 .WillOnce(testing::WithArgs<2>( | 677 .WillOnce(testing::WithArgs<2>( |
626 Invoke(this, &QuicDispatcherTest::ValidatePacket))); | 678 Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket, |
| 679 base::Unretained(this), connection_id)))); |
627 } | 680 } |
628 ProcessPacket(client_address, connection_id, true, false, "data"); | 681 ProcessPacket(client_address, connection_id, true, false, "data"); |
629 } | 682 } |
630 | 683 |
631 TEST_P(QuicDispatcherStatelessRejectTest, CheapRejects) { | 684 TEST_P(QuicDispatcherStatelessRejectTest, CheapRejects) { |
632 FLAGS_quic_use_cheap_stateless_rejects = true; | 685 FLAGS_quic_use_cheap_stateless_rejects = true; |
| 686 FLAGS_quic_buffer_packet_till_chlo = true; |
633 CreateTimeWaitListManager(); | 687 CreateTimeWaitListManager(); |
634 | 688 |
635 IPEndPoint client_address(net::test::Loopback4(), 1); | 689 IPEndPoint client_address(net::test::Loopback4(), 1); |
636 QuicConnectionId connection_id = 1; | 690 QuicConnectionId connection_id = 1; |
637 if (GetParam().enable_stateless_rejects_via_flag) { | 691 if (GetParam().enable_stateless_rejects_via_flag) { |
638 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) | 692 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) |
639 .Times(0); | 693 .Times(0); |
640 } else { | 694 } else { |
641 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) | 695 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) |
642 .WillOnce(testing::Return( | 696 .WillOnce(testing::Return( |
643 CreateSessionBasedOnTestParams(connection_id, client_address))); | 697 CreateSessionBasedOnTestParams(connection_id, client_address))); |
| 698 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), |
| 699 ProcessUdpPacket(_, _, _)) |
| 700 .WillOnce(testing::WithArgs<2>(Invoke(CreateFunctor( |
| 701 &QuicDispatcherTest::ValidatePacket, base::Unretained(this), 1)))); |
644 } | 702 } |
645 | 703 |
646 VLOG(1) << "ExpectStatelessReject: " << ExpectStatelessReject(); | 704 VLOG(1) << "ExpectStatelessReject: " << ExpectStatelessReject(); |
647 VLOG(1) << "Params: " << GetParam(); | 705 VLOG(1) << "Params: " << GetParam(); |
648 // Process the first packet for the connection. | 706 // Process the first packet for the connection. |
649 // clang-format off | 707 // clang-format off |
650 CryptoHandshakeMessage client_hello = CryptoTestUtils::Message( | 708 CryptoHandshakeMessage client_hello = CryptoTestUtils::Message( |
651 "CHLO", | 709 "CHLO", |
652 "AEAD", "AESG", | 710 "AEAD", "AESG", |
653 "KEXS", "C255", | 711 "KEXS", "C255", |
654 "COPT", "SREJ", | 712 "COPT", "SREJ", |
655 "NONC", "1234567890123456789012", | 713 "NONC", "1234567890123456789012", |
656 "VER\0", "Q025", | 714 "VER\0", "Q025", |
657 "$padding", static_cast<int>(kClientHelloMinimumSize), | 715 "$padding", static_cast<int>(kClientHelloMinimumSize), |
658 nullptr); | 716 nullptr); |
659 // clang-format on | 717 // clang-format on |
660 | 718 |
661 ProcessPacket(client_address, connection_id, true, false, | 719 ProcessPacket(client_address, connection_id, true, false, |
662 client_hello.GetSerialized().AsStringPiece().as_string()); | 720 client_hello.GetSerialized().AsStringPiece().as_string()); |
663 | 721 |
664 if (GetParam().enable_stateless_rejects_via_flag) { | 722 if (GetParam().enable_stateless_rejects_via_flag) { |
665 EXPECT_EQ(true, | 723 EXPECT_EQ(true, |
666 time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); | 724 time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); |
667 } | 725 } |
668 } | 726 } |
669 | 727 |
670 TEST_P(QuicDispatcherStatelessRejectTest, BufferNonChlo) { | 728 TEST_P(QuicDispatcherStatelessRejectTest, BufferNonChlo) { |
671 FLAGS_quic_use_cheap_stateless_rejects = true; | 729 FLAGS_quic_use_cheap_stateless_rejects = true; |
| 730 FLAGS_quic_always_log_bugs_for_tests = true; |
672 CreateTimeWaitListManager(); | 731 CreateTimeWaitListManager(); |
673 | 732 |
674 const IPEndPoint client_address(net::test::Loopback4(), 1); | 733 const IPEndPoint client_address(net::test::Loopback4(), 1); |
675 const QuicConnectionId connection_id = 1; | 734 const QuicConnectionId connection_id = 1; |
676 | 735 |
677 if (!GetParam().enable_stateless_rejects_via_flag) { | 736 if (!GetParam().enable_stateless_rejects_via_flag && |
678 // If stateless rejects are not being used, then a connection will be | 737 !FLAGS_quic_buffer_packet_till_chlo) { |
679 // created immediately. | 738 // If stateless rejects are not being used and early arrived packets are not |
| 739 // buffered, then a connection will be created immediately. |
680 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) | 740 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) |
681 .WillOnce(testing::Return( | 741 .WillOnce(testing::Return( |
682 CreateSessionBasedOnTestParams(connection_id, client_address))); | 742 CreateSessionBasedOnTestParams(connection_id, client_address))); |
| 743 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), |
| 744 ProcessUdpPacket(_, client_address, _)) |
| 745 .WillOnce(testing::WithArg<2>( |
| 746 Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket, |
| 747 base::Unretained(this), connection_id)))); |
683 } | 748 } |
684 ProcessPacket(client_address, connection_id, true, false, | 749 bool first_packet_dropped = GetParam().enable_stateless_rejects_via_flag && |
685 "NOT DATA FOR A CHLO"); | 750 !FLAGS_quic_buffer_packet_till_chlo; |
| 751 if (first_packet_dropped) { |
| 752 // Never do stateless reject while |
| 753 // FLAGS_quic_buffer_packet_till_chlo is off. |
| 754 EXPECT_DFATAL( |
| 755 ProcessPacket(client_address, connection_id, true, false, |
| 756 "NOT DATA FOR A CHLO"), |
| 757 "Have to drop packet because buffering non-chlo packet is " |
| 758 "not supported while trying to do stateless reject. " |
| 759 "--gfe2_reloadable_flag_quic_buffer_packet_till_chlo false " |
| 760 "--gfe2_reloadable_flag_quic_use_cheap_stateless_rejects true"); |
| 761 } else { |
| 762 ProcessPacket(client_address, connection_id, true, false, |
| 763 "NOT DATA FOR A CHLO"); |
| 764 } |
686 | 765 |
687 // Process the first packet for the connection. | 766 // Process the first packet for the connection. |
688 // clang-format off | 767 // clang-format off |
689 CryptoHandshakeMessage client_hello = CryptoTestUtils::Message( | 768 CryptoHandshakeMessage client_hello = CryptoTestUtils::Message( |
690 "CHLO", | 769 "CHLO", |
691 "AEAD", "AESG", | 770 "AEAD", "AESG", |
692 "KEXS", "C255", | 771 "KEXS", "C255", |
693 "NONC", "1234567890123456789012", | 772 "NONC", "1234567890123456789012", |
694 "VER\0", "Q025", | 773 "VER\0", "Q025", |
695 "$padding", static_cast<int>(kClientHelloMinimumSize), | 774 "$padding", static_cast<int>(kClientHelloMinimumSize), |
696 nullptr); | 775 nullptr); |
697 // clang-format on | 776 // clang-format on |
698 | 777 |
699 if (GetParam().enable_stateless_rejects_via_flag) { | 778 if (GetParam().enable_stateless_rejects_via_flag || |
| 779 FLAGS_quic_buffer_packet_till_chlo) { |
700 // If stateless rejects are enabled then a connection will be created now | 780 // If stateless rejects are enabled then a connection will be created now |
701 // and the buffered packet will be processed | 781 // and the buffered packet will be processed |
702 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) | 782 EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address)) |
703 .WillOnce(testing::Return( | 783 .WillOnce(testing::Return( |
704 CreateSessionBasedOnTestParams(connection_id, client_address))); | 784 CreateSessionBasedOnTestParams(connection_id, client_address))); |
| 785 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), |
| 786 ProcessUdpPacket(_, client_address, _)) |
| 787 .WillOnce(testing::WithArg<2>( |
| 788 Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket, |
| 789 base::Unretained(this), connection_id)))); |
705 } | 790 } |
706 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), | 791 if (!first_packet_dropped) { |
707 ProcessUdpPacket(_, client_address, _)) | 792 // Expect both packets to be passed to ProcessUdpPacket(). And one of them |
708 .RetiresOnSaturation(); | 793 // is already expected in CreateSessionBasedOnTestParams(). |
| 794 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), |
| 795 ProcessUdpPacket(_, client_address, _)) |
| 796 .WillOnce(testing::WithArg<2>( |
| 797 Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket, |
| 798 base::Unretained(this), connection_id)))) |
| 799 .RetiresOnSaturation(); |
| 800 } else { |
| 801 // Since first packet is dropped, remove it from map to skip |
| 802 // ValidatePacket() on it. |
| 803 data_connection_map_[connection_id].pop_front(); |
| 804 } |
709 ProcessPacket(client_address, connection_id, true, false, | 805 ProcessPacket(client_address, connection_id, true, false, |
710 client_hello.GetSerialized().AsStringPiece().as_string()); | 806 client_hello.GetSerialized().AsStringPiece().as_string()); |
711 EXPECT_FALSE( | 807 EXPECT_FALSE( |
712 time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); | 808 time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); |
713 } | 809 } |
714 | 810 |
715 // Verify the stopgap test: Packets with truncated connection IDs should be | 811 // Verify the stopgap test: Packets with truncated connection IDs should be |
716 // dropped. | 812 // dropped. |
717 class QuicDispatcherTestStrayPacketConnectionId : public QuicDispatcherTest {}; | 813 class QuicDispatcherTestStrayPacketConnectionId : public QuicDispatcherTest {}; |
718 | 814 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
752 LOG(DFATAL) << "Not supported"; | 848 LOG(DFATAL) << "Not supported"; |
753 return WriteResult(); | 849 return WriteResult(); |
754 } | 850 } |
755 | 851 |
756 bool write_blocked_; | 852 bool write_blocked_; |
757 }; | 853 }; |
758 | 854 |
759 class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest { | 855 class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest { |
760 public: | 856 public: |
761 void SetUp() override { | 857 void SetUp() override { |
| 858 QuicDispatcherTest::SetUp(); |
762 writer_ = new BlockingWriter; | 859 writer_ = new BlockingWriter; |
763 QuicDispatcherPeer::UseWriter(dispatcher_.get(), writer_); | 860 QuicDispatcherPeer::UseWriter(dispatcher_.get(), writer_); |
764 | 861 |
765 IPEndPoint client_address(net::test::Loopback4(), 1); | 862 IPEndPoint client_address(net::test::Loopback4(), 1); |
766 | 863 |
767 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, client_address)) | 864 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, client_address)) |
768 .WillOnce(testing::Return(CreateSession( | 865 .WillOnce(testing::Return(CreateSession( |
769 dispatcher_.get(), config_, 1, client_address, &helper_, | 866 dispatcher_.get(), config_, 1, client_address, &helper_, |
770 &alarm_factory_, &crypto_config_, | 867 &alarm_factory_, &crypto_config_, |
771 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); | 868 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); |
| 869 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), |
| 870 ProcessUdpPacket(_, _, _)) |
| 871 .WillOnce(testing::WithArgs<2>(Invoke(CreateFunctor( |
| 872 &QuicDispatcherTest::ValidatePacket, base::Unretained(this), 1)))); |
772 ProcessPacket(client_address, 1, true, false, SerializeCHLO()); | 873 ProcessPacket(client_address, 1, true, false, SerializeCHLO()); |
773 | 874 |
774 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, client_address)) | 875 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, client_address)) |
775 .WillOnce(testing::Return(CreateSession( | 876 .WillOnce(testing::Return(CreateSession( |
776 dispatcher_.get(), config_, 2, client_address, &helper_, | 877 dispatcher_.get(), config_, 2, client_address, &helper_, |
777 &alarm_factory_, &crypto_config_, | 878 &alarm_factory_, &crypto_config_, |
778 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_))); | 879 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_))); |
| 880 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()), |
| 881 ProcessUdpPacket(_, _, _)) |
| 882 .WillOnce(testing::WithArgs<2>(Invoke(CreateFunctor( |
| 883 &QuicDispatcherTest::ValidatePacket, base::Unretained(this), 2)))); |
779 ProcessPacket(client_address, 2, true, false, SerializeCHLO()); | 884 ProcessPacket(client_address, 2, true, false, SerializeCHLO()); |
780 | 885 |
781 blocked_list_ = QuicDispatcherPeer::GetWriteBlockedList(dispatcher_.get()); | 886 blocked_list_ = QuicDispatcherPeer::GetWriteBlockedList(dispatcher_.get()); |
782 } | 887 } |
783 | 888 |
784 void TearDown() override { | 889 void TearDown() override { |
785 EXPECT_CALL(*connection1(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _)); | 890 EXPECT_CALL(*connection1(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _)); |
786 EXPECT_CALL(*connection2(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _)); | 891 EXPECT_CALL(*connection2(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _)); |
787 dispatcher_->Shutdown(); | 892 dispatcher_->Shutdown(); |
788 } | 893 } |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
925 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0); | 1030 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0); |
926 dispatcher_->OnCanWrite(); | 1031 dispatcher_->OnCanWrite(); |
927 EXPECT_TRUE(dispatcher_->HasPendingWrites()); | 1032 EXPECT_TRUE(dispatcher_->HasPendingWrites()); |
928 | 1033 |
929 // And we'll resume where we left off when we get another call. | 1034 // And we'll resume where we left off when we get another call. |
930 EXPECT_CALL(*connection2(), OnCanWrite()); | 1035 EXPECT_CALL(*connection2(), OnCanWrite()); |
931 dispatcher_->OnCanWrite(); | 1036 dispatcher_->OnCanWrite(); |
932 EXPECT_FALSE(dispatcher_->HasPendingWrites()); | 1037 EXPECT_FALSE(dispatcher_->HasPendingWrites()); |
933 } | 1038 } |
934 | 1039 |
| 1040 // Tests that bufferring packets works in stateful reject, expensive stateless |
| 1041 // reject and cheap stateless reject. |
| 1042 struct BufferedPacketStoreTestParams { |
| 1043 BufferedPacketStoreTestParams(bool enable_stateless_rejects_via_flag, |
| 1044 bool support_cheap_stateless_reject) |
| 1045 : enable_stateless_rejects_via_flag(enable_stateless_rejects_via_flag), |
| 1046 support_cheap_stateless_reject(support_cheap_stateless_reject) {} |
| 1047 |
| 1048 friend ostream& operator<<(ostream& os, |
| 1049 const BufferedPacketStoreTestParams& p) { |
| 1050 os << "{ enable_stateless_rejects_via_flag: " |
| 1051 << p.enable_stateless_rejects_via_flag << std::endl; |
| 1052 os << " support_cheap_stateless_reject: " |
| 1053 << p.support_cheap_stateless_reject << " }"; |
| 1054 return os; |
| 1055 } |
| 1056 |
| 1057 // This only enables the stateless reject feature via the feature-flag. |
| 1058 // This should be a no-op if the peer does not support them. |
| 1059 bool enable_stateless_rejects_via_flag; |
| 1060 // Whether to do cheap stateless or not. |
| 1061 bool support_cheap_stateless_reject; |
| 1062 }; |
| 1063 |
| 1064 vector<BufferedPacketStoreTestParams> GetBufferedPacketStoreTestParams() { |
| 1065 vector<BufferedPacketStoreTestParams> params; |
| 1066 for (bool enable_stateless_rejects_via_flag : {true, false}) { |
| 1067 for (bool support_cheap_stateless_reject : {true, false}) { |
| 1068 params.push_back(BufferedPacketStoreTestParams( |
| 1069 enable_stateless_rejects_via_flag, support_cheap_stateless_reject)); |
| 1070 } |
| 1071 } |
| 1072 return params; |
| 1073 } |
| 1074 |
| 1075 // A dispatcher whose stateless rejector will always ACCEPTs CHLO. |
| 1076 class BufferedPacketStoreTest |
| 1077 : public QuicDispatcherTest, |
| 1078 public ::testing::WithParamInterface<BufferedPacketStoreTestParams> { |
| 1079 public: |
| 1080 BufferedPacketStoreTest() |
| 1081 : QuicDispatcherTest(), client_addr_(Loopback4(), 1234) { |
| 1082 FLAGS_quic_buffer_packet_till_chlo = true; |
| 1083 FLAGS_quic_use_cheap_stateless_rejects = |
| 1084 GetParam().support_cheap_stateless_reject; |
| 1085 FLAGS_enable_quic_stateless_reject_support = |
| 1086 GetParam().enable_stateless_rejects_via_flag; |
| 1087 } |
| 1088 |
| 1089 void SetUp() override { |
| 1090 QuicDispatcherTest::SetUp(); |
| 1091 clock_ = QuicDispatcherPeer::GetHelper(dispatcher_.get())->GetClock(); |
| 1092 |
| 1093 QuicVersion version = QuicSupportedVersions().front(); |
| 1094 CryptoHandshakeMessage chlo = CryptoTestUtils::GenerateDefaultInchoateCHLO( |
| 1095 clock_, version, &crypto_config_); |
| 1096 chlo.SetVector(net::kCOPT, net::QuicTagVector{net::kSREJ}); |
| 1097 // Pass an inchoate CHLO. |
| 1098 CryptoTestUtils::GenerateFullCHLO( |
| 1099 chlo, &crypto_config_, server_ip_, client_addr_, version, clock_, |
| 1100 &proof_, QuicDispatcherPeer::GetCache(dispatcher_.get()), &full_chlo_); |
| 1101 } |
| 1102 |
| 1103 string SerializeFullCHLO() { |
| 1104 return full_chlo_.GetSerialized().AsStringPiece().as_string(); |
| 1105 } |
| 1106 |
| 1107 protected: |
| 1108 IPAddress server_ip_; |
| 1109 IPEndPoint client_addr_; |
| 1110 QuicCryptoProof proof_; |
| 1111 const QuicClock* clock_; |
| 1112 CryptoHandshakeMessage full_chlo_; |
| 1113 }; |
| 1114 |
| 1115 INSTANTIATE_TEST_CASE_P( |
| 1116 BufferedPacketStoreTests, |
| 1117 BufferedPacketStoreTest, |
| 1118 ::testing::ValuesIn(GetBufferedPacketStoreTestParams())); |
| 1119 |
| 1120 TEST_P(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) { |
| 1121 InSequence s; |
| 1122 IPEndPoint client_address(Loopback4(), 1); |
| 1123 server_address_ = IPEndPoint(Any4(), 5); |
| 1124 QuicConnectionId conn_id = 1; |
| 1125 // A bunch of non-CHLO should be buffered upon arrival, and the first one |
| 1126 // should trigger OnNewConnectionAdded(). |
| 1127 EXPECT_CALL(*dispatcher_, OnNewConnectionAdded(conn_id)).Times(1); |
| 1128 for (size_t i = 1; i <= kDefaultMaxUndecryptablePackets + 1; ++i) { |
| 1129 ProcessPacket(client_address, conn_id, true, false, |
| 1130 "data packet " + IntToString(i + 1), |
| 1131 PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, |
| 1132 kDefaultPathId, |
| 1133 /*packet_number=*/i + 1); |
| 1134 } |
| 1135 EXPECT_EQ(0u, dispatcher_->session_map().size()) |
| 1136 << "No session should be created before CHLO arrives."; |
| 1137 |
| 1138 // Pop out the last packet as it is also be dropped by the store. |
| 1139 data_connection_map_[conn_id].pop_back(); |
| 1140 // When CHLO arrives, a new session should be created, and all packets |
| 1141 // buffered should be delivered to the session. |
| 1142 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address)) |
| 1143 .WillOnce(testing::Return(CreateSession( |
| 1144 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_, |
| 1145 &mock_alarm_factory_, &crypto_config_, |
| 1146 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); |
| 1147 |
| 1148 // Only |kDefaultMaxUndecryptablePackets| packets were buffered, and they |
| 1149 // should be delivered in arrival order. |
| 1150 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), |
| 1151 ProcessUdpPacket(_, _, _)) |
| 1152 .Times(kDefaultMaxUndecryptablePackets + 1) // + 1 for CHLO. |
| 1153 .WillRepeatedly(testing::WithArg<2>( |
| 1154 Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket, |
| 1155 base::Unretained(this), conn_id)))); |
| 1156 ProcessPacket(client_address, conn_id, true, false, SerializeFullCHLO()); |
| 1157 } |
| 1158 |
| 1159 TEST_P(BufferedPacketStoreTest, |
| 1160 ProcessNonChloPacketsForDifferentConnectionsUptoLimit) { |
| 1161 InSequence s; |
| 1162 server_address_ = IPEndPoint(Any4(), 5); |
| 1163 // A bunch of non-CHLO should be buffered upon arrival. |
| 1164 for (size_t i = 1; i <= kDefaultMaxConnectionsInStore + 1; ++i) { |
| 1165 IPEndPoint client_address(Loopback4(), i); |
| 1166 QuicConnectionId conn_id = i; |
| 1167 if (i <= kDefaultMaxConnectionsInStore) { |
| 1168 // As they are on different connection, they should trigger |
| 1169 // OnNewConnectionAdded(). The last packet should be dropped. |
| 1170 EXPECT_CALL(*dispatcher_, OnNewConnectionAdded(conn_id)); |
| 1171 } |
| 1172 ProcessPacket(client_address, conn_id, true, false, |
| 1173 "data packet on connection " + IntToString(i), |
| 1174 PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, |
| 1175 kDefaultPathId, |
| 1176 /*packet_number=*/2); |
| 1177 } |
| 1178 |
| 1179 // Pop out the packet on last connection as it shouldn't be enqueued in store |
| 1180 // as well. |
| 1181 data_connection_map_[kDefaultMaxConnectionsInStore + 1].pop_front(); |
| 1182 |
| 1183 // Process CHLOs. |
| 1184 for (size_t i = 1; i <= kDefaultMaxConnectionsInStore + 1; ++i) { |
| 1185 IPEndPoint client_address(Loopback4(), i); |
| 1186 QuicConnectionId conn_id = i; |
| 1187 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address)) |
| 1188 .WillOnce(testing::Return(CreateSession( |
| 1189 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_, |
| 1190 &mock_alarm_factory_, &crypto_config_, |
| 1191 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); |
| 1192 if (conn_id == kDefaultMaxConnectionsInStore + 1) { |
| 1193 // The last CHLO should trigger OnNewConnectionAdded() since it's the |
| 1194 // first packet arrives on that connection. |
| 1195 EXPECT_CALL(*dispatcher_, OnNewConnectionAdded(conn_id)); |
| 1196 } |
| 1197 // First |kDefaultMaxConnectionsInStore| connections should have buffered |
| 1198 // a packet in store. The rest should have been dropped. |
| 1199 if (i <= kDefaultMaxConnectionsInStore) { |
| 1200 EXPECT_CALL( |
| 1201 *reinterpret_cast<MockQuicConnection*>(session1_->connection()), |
| 1202 ProcessUdpPacket(_, client_address, _)) |
| 1203 .Times(2) |
| 1204 .WillRepeatedly(testing::WithArg<2>( |
| 1205 Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket, |
| 1206 base::Unretained(this), conn_id)))); |
| 1207 } |
| 1208 ProcessPacket(client_address, conn_id, true, false, SerializeFullCHLO()); |
| 1209 } |
| 1210 } |
| 1211 |
| 1212 // Tests that store delivers empty packet list if CHLO arrives firstly. |
| 1213 TEST_P(BufferedPacketStoreTest, DeliverEmptyPackets) { |
| 1214 QuicConnectionId conn_id = 1; |
| 1215 IPEndPoint client_address(Loopback4(), 1); |
| 1216 EXPECT_CALL(*dispatcher_, OnNewConnectionAdded(conn_id)); |
| 1217 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address)) |
| 1218 .WillOnce(testing::Return(CreateSession( |
| 1219 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_, |
| 1220 &mock_alarm_factory_, &crypto_config_, |
| 1221 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); |
| 1222 ProcessPacket(client_address, conn_id, true, false, SerializeFullCHLO()); |
| 1223 } |
| 1224 |
| 1225 // Tests that by the time a retransmitted CHLO arrives, a connection for the |
| 1226 // CHLO should already be created. |
| 1227 TEST_P(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) { |
| 1228 InSequence s; |
| 1229 IPEndPoint client_address(Loopback4(), 1); |
| 1230 server_address_ = IPEndPoint(Any4(), 5); |
| 1231 QuicConnectionId conn_id = 1; |
| 1232 ProcessPacket(client_address, conn_id, true, false, |
| 1233 "data packet " + IntToString(2), PACKET_8BYTE_CONNECTION_ID, |
| 1234 PACKET_6BYTE_PACKET_NUMBER, kDefaultPathId, |
| 1235 /*packet_number=*/2); |
| 1236 |
| 1237 // When CHLO arrives, a new session should be created, and all packets |
| 1238 // buffered should be delivered to the session. |
| 1239 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address)) |
| 1240 .Times(1) // Only triggered by 1st CHLO. |
| 1241 .WillOnce(testing::Return(CreateSession( |
| 1242 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_, |
| 1243 &mock_alarm_factory_, &crypto_config_, |
| 1244 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))); |
| 1245 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()), |
| 1246 ProcessUdpPacket(_, _, _)) |
| 1247 .Times(3) // Triggered by 1 data packet and 2 CHLOs. |
| 1248 .WillRepeatedly(testing::WithArg<2>( |
| 1249 Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket, |
| 1250 base::Unretained(this), conn_id)))); |
| 1251 ProcessPacket(client_address, conn_id, true, false, SerializeFullCHLO()); |
| 1252 |
| 1253 ProcessPacket(client_address, conn_id, true, false, SerializeFullCHLO()); |
| 1254 } |
| 1255 |
| 1256 // Tests that expiration of a connection add connection id to time wait list. |
| 1257 TEST_P(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) { |
| 1258 InSequence s; |
| 1259 CreateTimeWaitListManager(); |
| 1260 QuicBufferedPacketStore* store = |
| 1261 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get()); |
| 1262 QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock()); |
| 1263 |
| 1264 IPEndPoint client_address(Loopback4(), 1); |
| 1265 server_address_ = IPEndPoint(Any4(), 5); |
| 1266 QuicConnectionId conn_id = 1; |
| 1267 ProcessPacket(client_address, conn_id, true, false, |
| 1268 "data packet " + IntToString(2), PACKET_8BYTE_CONNECTION_ID, |
| 1269 PACKET_6BYTE_PACKET_NUMBER, kDefaultPathId, |
| 1270 /*packet_number=*/2); |
| 1271 |
| 1272 mock_helper_.AdvanceTime( |
| 1273 QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs)); |
| 1274 QuicAlarm* alarm = QuicBufferedPacketStorePeer::expiration_alarm(store); |
| 1275 // Cancel alarm as if it had been fired. |
| 1276 alarm->Cancel(); |
| 1277 store->OnExpirationTimeout(); |
| 1278 // New arrived CHLO will be dropped because this connection is in time wait |
| 1279 // list. |
| 1280 ASSERT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id)); |
| 1281 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, conn_id, _, _)); |
| 1282 ProcessPacket(client_address, conn_id, true, false, SerializeFullCHLO()); |
| 1283 } |
| 1284 |
935 } // namespace | 1285 } // namespace |
936 } // namespace test | 1286 } // namespace test |
937 } // namespace net | 1287 } // namespace net |
OLD | NEW |