blob: 1462f7e9e17f8aca1a1749aead48e94789cfb9d0 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/core/quic_dispatcher.h"
6
7#include <memory>
8#include <ostream>
vasilvv872e7a32019-03-12 16:42:44 -07009#include <string>
bnc463f2352019-10-10 04:49:34 -070010#include <utility>
QUICHE teama6ef0a62019-03-07 20:34:33 -050011
QUICHE teama6ef0a62019-03-07 20:34:33 -050012#include "net/third_party/quiche/src/quic/core/chlo_extractor.h"
13#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
14#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
15#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
16#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
17#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
18#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
19#include "net/third_party/quiche/src/quic/core/quic_packet_writer_wrapper.h"
20#include "net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h"
21#include "net/third_party/quiche/src/quic/core/quic_types.h"
22#include "net/third_party/quiche/src/quic/core/quic_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050023#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
24#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
25#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050026#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
27#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
28#include "net/third_party/quiche/src/quic/test_tools/fake_proof_source.h"
29#include "net/third_party/quiche/src/quic/test_tools/mock_quic_time_wait_list_manager.h"
30#include "net/third_party/quiche/src/quic/test_tools/quic_buffered_packet_store_peer.h"
31#include "net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.h"
32#include "net/third_party/quiche/src/quic/test_tools/quic_dispatcher_peer.h"
33#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
34#include "net/third_party/quiche/src/quic/test_tools/quic_time_wait_list_manager_peer.h"
35#include "net/third_party/quiche/src/quic/tools/quic_simple_crypto_server_stream_helper.h"
bnc4e9283d2019-12-17 07:08:57 -080036#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
dmcardlecf0bfcf2019-12-13 08:08:21 -080037#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
dmcardle8f7df532020-01-07 13:28:57 -080038#include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050039
40using testing::_;
wub89490e02019-12-12 12:45:58 -080041using testing::ByMove;
QUICHE teama6ef0a62019-03-07 20:34:33 -050042using testing::InSequence;
43using testing::Invoke;
44using testing::NiceMock;
45using testing::Return;
46using testing::WithArg;
47using testing::WithoutArgs;
48
49static const size_t kDefaultMaxConnectionsInStore = 100;
50static const size_t kMaxConnectionsWithoutCHLO =
51 kDefaultMaxConnectionsInStore / 2;
52static const int16_t kMaxNumSessionsToCreate = 16;
53
54namespace quic {
55namespace test {
56namespace {
57
58class TestQuicSpdyServerSession : public QuicServerSessionBase {
59 public:
60 TestQuicSpdyServerSession(const QuicConfig& config,
61 QuicConnection* connection,
62 const QuicCryptoServerConfig* crypto_config,
63 QuicCompressedCertsCache* compressed_certs_cache)
64 : QuicServerSessionBase(config,
65 CurrentSupportedVersions(),
66 connection,
67 nullptr,
68 nullptr,
69 crypto_config,
70 compressed_certs_cache),
71 crypto_stream_(QuicServerSessionBase::GetMutableCryptoStream()) {}
72 TestQuicSpdyServerSession(const TestQuicSpdyServerSession&) = delete;
73 TestQuicSpdyServerSession& operator=(const TestQuicSpdyServerSession&) =
74 delete;
75
ianswett6aefa0b2019-12-10 07:26:15 -080076 ~TestQuicSpdyServerSession() override { DeleteConnection(); }
QUICHE teama6ef0a62019-03-07 20:34:33 -050077
fkastenholz5d880a92019-06-21 09:01:56 -070078 MOCK_METHOD2(OnConnectionClosed,
79 void(const QuicConnectionCloseFrame& frame,
QUICHE teama6ef0a62019-03-07 20:34:33 -050080 ConnectionCloseSource source));
81 MOCK_METHOD1(CreateIncomingStream, QuicSpdyStream*(QuicStreamId id));
renjietangbaea59c2019-05-29 15:08:14 -070082 MOCK_METHOD1(CreateIncomingStream, QuicSpdyStream*(PendingStream* pending));
QUICHE teama6ef0a62019-03-07 20:34:33 -050083 MOCK_METHOD0(CreateOutgoingBidirectionalStream, QuicSpdyStream*());
84 MOCK_METHOD0(CreateOutgoingUnidirectionalStream, QuicSpdyStream*());
85
nharpere5e28f92020-01-03 14:10:07 -080086 std::unique_ptr<QuicCryptoServerStreamBase> CreateQuicCryptoServerStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -050087 const QuicCryptoServerConfig* crypto_config,
88 QuicCompressedCertsCache* compressed_certs_cache) override {
nharpere5e28f92020-01-03 14:10:07 -080089 return CreateCryptoServerStream(crypto_config, compressed_certs_cache, this,
90 stream_helper());
QUICHE teama6ef0a62019-03-07 20:34:33 -050091 }
92
93 void SetCryptoStream(QuicCryptoServerStream* crypto_stream) {
94 crypto_stream_ = crypto_stream;
95 }
96
97 QuicCryptoServerStreamBase* GetMutableCryptoStream() override {
98 return crypto_stream_;
99 }
100
101 const QuicCryptoServerStreamBase* GetCryptoStream() const override {
102 return crypto_stream_;
103 }
104
105 QuicCryptoServerStream::Helper* stream_helper() {
106 return QuicServerSessionBase::stream_helper();
107 }
108
109 private:
110 QuicCryptoServerStreamBase* crypto_stream_;
111};
112
113class TestDispatcher : public QuicDispatcher {
114 public:
115 TestDispatcher(const QuicConfig* config,
116 const QuicCryptoServerConfig* crypto_config,
QUICHE teamc65d1d12019-03-19 20:58:04 -0700117 QuicVersionManager* version_manager,
118 QuicRandom* random)
QUICHE teama6ef0a62019-03-07 20:34:33 -0500119 : QuicDispatcher(config,
120 crypto_config,
121 version_manager,
vasilvv0fc587f2019-09-06 13:33:08 -0700122 std::make_unique<MockQuicConnectionHelper>(),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500123 std::unique_ptr<QuicCryptoServerStream::Helper>(
wub662a3d62019-08-16 14:10:50 -0700124 new QuicSimpleCryptoServerStreamHelper()),
vasilvv0fc587f2019-09-06 13:33:08 -0700125 std::make_unique<MockAlarmFactory>(),
wub662a3d62019-08-16 14:10:50 -0700126 kQuicDefaultConnectionIdLength),
127 random_(random) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500128
wub89490e02019-12-12 12:45:58 -0800129 MOCK_METHOD4(
130 CreateQuicSession,
131 std::unique_ptr<QuicSession>(QuicConnectionId connection_id,
132 const QuicSocketAddress& peer_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800133 quiche::QuicheStringPiece alpn,
wub89490e02019-12-12 12:45:58 -0800134 const quic::ParsedQuicVersion& version));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500135
fayang1ed1f762019-06-24 11:40:04 -0700136 MOCK_METHOD1(ShouldCreateOrBufferPacketForConnection,
137 bool(const ReceivedPacketInfo& packet_info));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500138
139 struct TestQuicPerPacketContext : public QuicPerPacketContext {
vasilvvc48c8712019-03-11 13:38:16 -0700140 std::string custom_packet_context;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500141 };
142
143 std::unique_ptr<QuicPerPacketContext> GetPerPacketContext() const override {
vasilvv0fc587f2019-09-06 13:33:08 -0700144 auto test_context = std::make_unique<TestQuicPerPacketContext>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500145 test_context->custom_packet_context = custom_packet_context_;
146 return std::move(test_context);
147 }
148
149 void RestorePerPacketContext(
150 std::unique_ptr<QuicPerPacketContext> context) override {
151 TestQuicPerPacketContext* test_context =
152 static_cast<TestQuicPerPacketContext*>(context.get());
153 custom_packet_context_ = test_context->custom_packet_context;
154 }
155
vasilvvc48c8712019-03-11 13:38:16 -0700156 std::string custom_packet_context_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500157
dschinazi7b9278c2019-05-20 07:36:21 -0700158 using QuicDispatcher::SetAllowShortInitialServerConnectionIds;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500159 using QuicDispatcher::writer;
wub662a3d62019-08-16 14:10:50 -0700160
161 QuicRandom* random_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500162};
163
164// A Connection class which unregisters the session from the dispatcher when
165// sending connection close.
166// It'd be slightly more realistic to do this from the Session but it would
167// involve a lot more mocking.
168class MockServerConnection : public MockQuicConnection {
169 public:
170 MockServerConnection(QuicConnectionId connection_id,
171 MockQuicConnectionHelper* helper,
172 MockAlarmFactory* alarm_factory,
173 QuicDispatcher* dispatcher)
174 : MockQuicConnection(connection_id,
175 helper,
176 alarm_factory,
177 Perspective::IS_SERVER),
178 dispatcher_(dispatcher) {}
179
180 void UnregisterOnConnectionClosed() {
181 QUIC_LOG(ERROR) << "Unregistering " << connection_id();
182 dispatcher_->OnConnectionClosed(connection_id(), QUIC_NO_ERROR,
183 "Unregistering.",
184 ConnectionCloseSource::FROM_SELF);
185 }
186
187 private:
188 QuicDispatcher* dispatcher_;
189};
190
191class QuicDispatcherTest : public QuicTest {
192 public:
193 QuicDispatcherTest()
194 : QuicDispatcherTest(crypto_test_utils::ProofSourceForTesting()) {}
195
QUICHE teama6ef0a62019-03-07 20:34:33 -0500196 explicit QuicDispatcherTest(std::unique_ptr<ProofSource> proof_source)
wub662a3d62019-08-16 14:10:50 -0700197 : version_manager_(AllSupportedVersions()),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500198 crypto_config_(QuicCryptoServerConfig::TESTING,
199 QuicRandom::GetInstance(),
200 std::move(proof_source),
nharper6ebe83b2019-06-13 17:43:52 -0700201 KeyExchangeSource::Default()),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500202 server_address_(QuicIpAddress::Any4(), 5),
QUICHE teamc65d1d12019-03-19 20:58:04 -0700203 dispatcher_(
204 new NiceMock<TestDispatcher>(&config_,
205 &crypto_config_,
206 &version_manager_,
207 mock_helper_.GetRandomGenerator())),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500208 time_wait_list_manager_(nullptr),
209 session1_(nullptr),
210 session2_(nullptr),
fayangb880b4c2019-06-14 12:26:35 -0700211 store_(nullptr),
212 connection_id_(1) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500213
214 void SetUp() override {
215 dispatcher_->InitializeWithWriter(new MockPacketWriter());
216 // Set the counter to some value to start with.
217 QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(
218 dispatcher_.get(), kMaxNumSessionsToCreate);
fayang1ed1f762019-06-24 11:40:04 -0700219 ON_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(_))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500220 .WillByDefault(Return(true));
221 }
222
223 MockQuicConnection* connection1() {
224 if (session1_ == nullptr) {
225 return nullptr;
226 }
227 return reinterpret_cast<MockQuicConnection*>(session1_->connection());
228 }
229
230 MockQuicConnection* connection2() {
231 if (session2_ == nullptr) {
232 return nullptr;
233 }
234 return reinterpret_cast<MockQuicConnection*>(session2_->connection());
235 }
236
237 // Process a packet with an 8 byte connection id,
238 // 6 byte packet number, default path id, and packet number 1,
239 // using the first supported version.
240 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700241 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500242 bool has_version_flag,
vasilvvc48c8712019-03-11 13:38:16 -0700243 const std::string& data) {
dschinazi346b7ce2019-06-05 01:38:18 -0700244 ProcessPacket(peer_address, server_connection_id, has_version_flag, data,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500245 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER);
246 }
247
248 // Process a packet with a default path id, and packet number 1,
249 // using the first supported version.
250 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700251 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500252 bool has_version_flag,
vasilvvc48c8712019-03-11 13:38:16 -0700253 const std::string& data,
dschinazi346b7ce2019-06-05 01:38:18 -0700254 QuicConnectionIdIncluded server_connection_id_included,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500255 QuicPacketNumberLength packet_number_length) {
dschinazi346b7ce2019-06-05 01:38:18 -0700256 ProcessPacket(peer_address, server_connection_id, has_version_flag, data,
257 server_connection_id_included, packet_number_length, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500258 }
259
260 // Process a packet using the first supported version.
261 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700262 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500263 bool has_version_flag,
vasilvvc48c8712019-03-11 13:38:16 -0700264 const std::string& data,
dschinazi346b7ce2019-06-05 01:38:18 -0700265 QuicConnectionIdIncluded server_connection_id_included,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500266 QuicPacketNumberLength packet_number_length,
267 uint64_t packet_number) {
dschinazi346b7ce2019-06-05 01:38:18 -0700268 ProcessPacket(peer_address, server_connection_id, has_version_flag,
fayange3f2f7b2019-09-19 17:01:57 -0700269 CurrentSupportedVersions().front(), data, true,
dschinazi346b7ce2019-06-05 01:38:18 -0700270 server_connection_id_included, packet_number_length,
271 packet_number);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500272 }
273
274 // Processes a packet.
275 void ProcessPacket(QuicSocketAddress peer_address,
dschinazi346b7ce2019-06-05 01:38:18 -0700276 QuicConnectionId server_connection_id,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500277 bool has_version_flag,
278 ParsedQuicVersion version,
vasilvvc48c8712019-03-11 13:38:16 -0700279 const std::string& data,
fayange3f2f7b2019-09-19 17:01:57 -0700280 bool full_padding,
dschinazi346b7ce2019-06-05 01:38:18 -0700281 QuicConnectionIdIncluded server_connection_id_included,
282 QuicPacketNumberLength packet_number_length,
283 uint64_t packet_number) {
284 ProcessPacket(peer_address, server_connection_id, EmptyQuicConnectionId(),
fayange3f2f7b2019-09-19 17:01:57 -0700285 has_version_flag, version, data, full_padding,
dschinazi346b7ce2019-06-05 01:38:18 -0700286 server_connection_id_included, CONNECTION_ID_ABSENT,
287 packet_number_length, packet_number);
288 }
289
290 // Processes a packet.
291 void ProcessPacket(QuicSocketAddress peer_address,
292 QuicConnectionId server_connection_id,
293 QuicConnectionId client_connection_id,
294 bool has_version_flag,
295 ParsedQuicVersion version,
296 const std::string& data,
fayange3f2f7b2019-09-19 17:01:57 -0700297 bool full_padding,
dschinazi346b7ce2019-06-05 01:38:18 -0700298 QuicConnectionIdIncluded server_connection_id_included,
299 QuicConnectionIdIncluded client_connection_id_included,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500300 QuicPacketNumberLength packet_number_length,
301 uint64_t packet_number) {
302 ParsedQuicVersionVector versions(SupportedVersions(version));
303 std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
dschinazi346b7ce2019-06-05 01:38:18 -0700304 server_connection_id, client_connection_id, has_version_flag, false,
fayange3f2f7b2019-09-19 17:01:57 -0700305 packet_number, data, full_padding, server_connection_id_included,
dschinazi346b7ce2019-06-05 01:38:18 -0700306 client_connection_id_included, packet_number_length, &versions));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500307 std::unique_ptr<QuicReceivedPacket> received_packet(
308 ConstructReceivedPacket(*packet, mock_helper_.GetClock()->Now()));
309
dschinazi4fd8cb12019-09-09 16:31:06 -0700310 if (ChloExtractor::Extract(*packet, version, {}, nullptr,
dschinazi346b7ce2019-06-05 01:38:18 -0700311 server_connection_id.length())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500312 // Add CHLO packet to the beginning to be verified first, because it is
313 // also processed first by new session.
dschinazi346b7ce2019-06-05 01:38:18 -0700314 data_connection_map_[server_connection_id].push_front(
vasilvvc48c8712019-03-11 13:38:16 -0700315 std::string(packet->data(), packet->length()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500316 } else {
317 // For non-CHLO, always append to last.
dschinazi346b7ce2019-06-05 01:38:18 -0700318 data_connection_map_[server_connection_id].push_back(
vasilvvc48c8712019-03-11 13:38:16 -0700319 std::string(packet->data(), packet->length()));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500320 }
321 dispatcher_->ProcessPacket(server_address_, peer_address, *received_packet);
322 }
323
324 void ValidatePacket(QuicConnectionId conn_id,
325 const QuicEncryptedPacket& packet) {
326 EXPECT_EQ(data_connection_map_[conn_id].front().length(),
327 packet.AsStringPiece().length());
328 EXPECT_EQ(data_connection_map_[conn_id].front(), packet.AsStringPiece());
329 data_connection_map_[conn_id].pop_front();
330 }
331
wub89490e02019-12-12 12:45:58 -0800332 std::unique_ptr<QuicSession> CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500333 TestDispatcher* dispatcher,
334 const QuicConfig& config,
335 QuicConnectionId connection_id,
dschinazi17d42422019-06-18 16:35:07 -0700336 const QuicSocketAddress& /*peer_address*/,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500337 MockQuicConnectionHelper* helper,
338 MockAlarmFactory* alarm_factory,
339 const QuicCryptoServerConfig* crypto_config,
340 QuicCompressedCertsCache* compressed_certs_cache,
wub89490e02019-12-12 12:45:58 -0800341 TestQuicSpdyServerSession** session_ptr) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500342 MockServerConnection* connection = new MockServerConnection(
343 connection_id, helper, alarm_factory, dispatcher);
344 connection->SetQuicPacketWriter(dispatcher->writer(),
345 /*owns_writer=*/false);
wub89490e02019-12-12 12:45:58 -0800346 auto session = std::make_unique<TestQuicSpdyServerSession>(
347 config, connection, crypto_config, compressed_certs_cache);
348 *session_ptr = session.get();
349 connection->set_visitor(session.get());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500350 ON_CALL(*connection, CloseConnection(_, _, _))
351 .WillByDefault(WithoutArgs(Invoke(
352 connection, &MockServerConnection::UnregisterOnConnectionClosed)));
wub89490e02019-12-12 12:45:58 -0800353 return session;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500354 }
355
356 void CreateTimeWaitListManager() {
357 time_wait_list_manager_ = new MockTimeWaitListManager(
358 QuicDispatcherPeer::GetWriter(dispatcher_.get()), dispatcher_.get(),
359 mock_helper_.GetClock(), &mock_alarm_factory_);
360 // dispatcher_ takes the ownership of time_wait_list_manager_.
361 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
362 time_wait_list_manager_);
363 }
364
vasilvvc48c8712019-03-11 13:38:16 -0700365 std::string SerializeCHLO() {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500366 CryptoHandshakeMessage client_hello;
367 client_hello.set_tag(kCHLO);
368 client_hello.SetStringPiece(kALPN, "hq");
vasilvvc48c8712019-03-11 13:38:16 -0700369 return std::string(client_hello.GetSerialized().AsStringPiece());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500370 }
371
QUICHE teama6ef0a62019-03-07 20:34:33 -0500372 void MarkSession1Deleted() { session1_ = nullptr; }
373
fayangb880b4c2019-06-14 12:26:35 -0700374 void VerifyVersionSupported(ParsedQuicVersion version) {
375 QuicConnectionId connection_id = TestConnectionId(++connection_id_);
376 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
dmcardlecf0bfcf2019-12-13 08:08:21 -0800377 EXPECT_CALL(*dispatcher_,
378 CreateQuicSession(connection_id, client_address,
379 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800380 .WillOnce(Return(ByMove(CreateSession(
fayangb880b4c2019-06-14 12:26:35 -0700381 dispatcher_.get(), config_, connection_id, client_address,
382 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800383 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
fayangb880b4c2019-06-14 12:26:35 -0700384 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
385 ProcessUdpPacket(_, _, _))
386 .WillOnce(WithArg<2>(
387 Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
388 ValidatePacket(connection_id, packet);
389 })));
390 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700391 ShouldCreateOrBufferPacketForConnection(
392 ReceivedPacketInfoConnectionIdEquals(connection_id)));
fayangb880b4c2019-06-14 12:26:35 -0700393 ProcessPacket(client_address, connection_id, true, version, SerializeCHLO(),
fayange3f2f7b2019-09-19 17:01:57 -0700394 true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
fayangb880b4c2019-06-14 12:26:35 -0700395 }
396
397 void VerifyVersionNotSupported(ParsedQuicVersion version) {
398 QuicConnectionId connection_id = TestConnectionId(++connection_id_);
399 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
dmcardlecf0bfcf2019-12-13 08:08:21 -0800400 EXPECT_CALL(*dispatcher_,
401 CreateQuicSession(connection_id, client_address,
402 quiche::QuicheStringPiece("hq"), _))
fayangb880b4c2019-06-14 12:26:35 -0700403 .Times(0);
404 ProcessPacket(client_address, connection_id, true, version, SerializeCHLO(),
fayange3f2f7b2019-09-19 17:01:57 -0700405 true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
fayangb880b4c2019-06-14 12:26:35 -0700406 }
407
QUICHE teama6ef0a62019-03-07 20:34:33 -0500408 MockQuicConnectionHelper mock_helper_;
409 MockAlarmFactory mock_alarm_factory_;
410 QuicConfig config_;
411 QuicVersionManager version_manager_;
412 QuicCryptoServerConfig crypto_config_;
413 QuicSocketAddress server_address_;
414 std::unique_ptr<NiceMock<TestDispatcher>> dispatcher_;
415 MockTimeWaitListManager* time_wait_list_manager_;
416 TestQuicSpdyServerSession* session1_;
417 TestQuicSpdyServerSession* session2_;
vasilvvc48c8712019-03-11 13:38:16 -0700418 std::map<QuicConnectionId, std::list<std::string>> data_connection_map_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500419 QuicBufferedPacketStore* store_;
fayangb880b4c2019-06-14 12:26:35 -0700420 uint64_t connection_id_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500421};
422
423TEST_F(QuicDispatcherTest, TlsClientHelloCreatesSession) {
dschinazi76881f02019-12-09 14:56:14 -0800424 if (CurrentSupportedVersions().front().handshake_protocol !=
425 PROTOCOL_TLS1_3) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500426 return;
427 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500428 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
429
430 EXPECT_CALL(*dispatcher_,
431 CreateQuicSession(TestConnectionId(1), client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800432 quiche::QuicheStringPiece(""), _))
wub89490e02019-12-12 12:45:58 -0800433 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500434 dispatcher_.get(), config_, TestConnectionId(1), client_address,
435 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800436 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500437 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
438 ProcessUdpPacket(_, _, _))
439 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
440 ValidatePacket(TestConnectionId(1), packet);
441 })));
442 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700443 ShouldCreateOrBufferPacketForConnection(
444 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
dschinazi76881f02019-12-09 14:56:14 -0800445 ProcessPacket(client_address, TestConnectionId(1), true,
446 CurrentSupportedVersions().front(), SerializeCHLO(), true,
447 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500448}
449
450TEST_F(QuicDispatcherTest, ProcessPackets) {
451 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
452
453 EXPECT_CALL(*dispatcher_,
454 CreateQuicSession(TestConnectionId(1), client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800455 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800456 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500457 dispatcher_.get(), config_, TestConnectionId(1), client_address,
458 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800459 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500460 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
461 ProcessUdpPacket(_, _, _))
462 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
463 ValidatePacket(TestConnectionId(1), packet);
464 })));
465 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700466 ShouldCreateOrBufferPacketForConnection(
467 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500468 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500469
470 EXPECT_CALL(*dispatcher_,
471 CreateQuicSession(TestConnectionId(2), client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800472 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800473 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500474 dispatcher_.get(), config_, TestConnectionId(2), client_address,
475 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800476 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500477 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
478 ProcessUdpPacket(_, _, _))
479 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
480 ValidatePacket(TestConnectionId(2), packet);
481 })));
482 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700483 ShouldCreateOrBufferPacketForConnection(
484 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(2))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500485 ProcessPacket(client_address, TestConnectionId(2), true, SerializeCHLO());
486
487 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
488 ProcessUdpPacket(_, _, _))
489 .Times(1)
490 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
491 ValidatePacket(TestConnectionId(1), packet);
492 })));
493 ProcessPacket(client_address, TestConnectionId(1), false, "data");
494}
495
496// Regression test of b/93325907.
497TEST_F(QuicDispatcherTest, DispatcherDoesNotRejectPacketNumberZero) {
498 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
499
500 EXPECT_CALL(*dispatcher_,
501 CreateQuicSession(TestConnectionId(1), client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800502 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800503 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500504 dispatcher_.get(), config_, TestConnectionId(1), client_address,
505 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800506 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500507 // Verify both packets 1 and 2 are processed by connection 1.
508 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
509 ProcessUdpPacket(_, _, _))
510 .Times(2)
511 .WillRepeatedly(
512 WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
513 ValidatePacket(TestConnectionId(1), packet);
514 })));
515 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700516 ShouldCreateOrBufferPacketForConnection(
517 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500518 ProcessPacket(
519 client_address, TestConnectionId(1), true,
520 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
521 CurrentSupportedVersions().front().transport_version),
fayange3f2f7b2019-09-19 17:01:57 -0700522 SerializeCHLO(), true, CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
523 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500524 // Packet number 256 with packet number length 1 would be considered as 0 in
525 // dispatcher.
526 ProcessPacket(
527 client_address, TestConnectionId(1), false,
528 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
529 CurrentSupportedVersions().front().transport_version),
fayange3f2f7b2019-09-19 17:01:57 -0700530 "", true, CONNECTION_ID_PRESENT, PACKET_1BYTE_PACKET_NUMBER, 256);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500531}
532
533TEST_F(QuicDispatcherTest, StatelessVersionNegotiation) {
534 CreateTimeWaitListManager();
535 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
536
537 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
dschinazi346b7ce2019-06-05 01:38:18 -0700538 EXPECT_CALL(
539 *time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700540 SendVersionNegotiationPacket(TestConnectionId(1), _, _, _, _, _, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500541 .Times(1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500542 // Pad the CHLO message with enough data to make the packet large enough
543 // to trigger version negotiation.
vasilvvc48c8712019-03-11 13:38:16 -0700544 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500545 DCHECK_LE(1200u, chlo.length());
nharper4fd11052019-06-04 14:23:22 -0700546 ProcessPacket(client_address, TestConnectionId(1), true,
fayange3f2f7b2019-09-19 17:01:57 -0700547 QuicVersionReservedForNegotiation(), chlo, true,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500548 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
549}
550
dschinaziffa83552019-12-17 11:00:23 -0800551TEST_F(QuicDispatcherTest,
552 StatelessVersionNegotiationWithVeryLongConnectionId) {
553 SetQuicRestartFlag(quic_allow_very_long_connection_ids, true);
554 QuicConnectionId connection_id = QuicUtils::CreateRandomConnectionId(33);
555 CreateTimeWaitListManager();
556 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
557
558 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
559 EXPECT_CALL(*time_wait_list_manager_,
560 SendVersionNegotiationPacket(connection_id, _, _, _, _, _, _, _))
561 .Times(1);
562 // Pad the CHLO message with enough data to make the packet large enough
563 // to trigger version negotiation.
564 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
565 DCHECK_LE(1200u, chlo.length());
566 ProcessPacket(client_address, connection_id, true,
567 QuicVersionReservedForNegotiation(), chlo, true,
568 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
569}
570
dschinazi346b7ce2019-06-05 01:38:18 -0700571TEST_F(QuicDispatcherTest, StatelessVersionNegotiationWithClientConnectionId) {
dschinazi346b7ce2019-06-05 01:38:18 -0700572 CreateTimeWaitListManager();
573 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
574
575 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
576 EXPECT_CALL(*time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700577 SendVersionNegotiationPacket(
578 TestConnectionId(1), TestConnectionId(2), _, _, _, _, _, _))
dschinazi346b7ce2019-06-05 01:38:18 -0700579 .Times(1);
580 // Pad the CHLO message with enough data to make the packet large enough
581 // to trigger version negotiation.
582 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
583 DCHECK_LE(1200u, chlo.length());
584 ProcessPacket(client_address, TestConnectionId(1), TestConnectionId(2), true,
fayange3f2f7b2019-09-19 17:01:57 -0700585 QuicVersionReservedForNegotiation(), chlo, true,
dschinazi346b7ce2019-06-05 01:38:18 -0700586 CONNECTION_ID_PRESENT, CONNECTION_ID_PRESENT,
587 PACKET_4BYTE_PACKET_NUMBER, 1);
588}
589
QUICHE teama6ef0a62019-03-07 20:34:33 -0500590TEST_F(QuicDispatcherTest, NoVersionNegotiationWithSmallPacket) {
591 CreateTimeWaitListManager();
592 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
593
594 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
595 EXPECT_CALL(*time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700596 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500597 .Times(0);
vasilvvc48c8712019-03-11 13:38:16 -0700598 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500599 // Truncate to 1100 bytes of payload which results in a packet just
600 // under 1200 bytes after framing, packet, and encryption overhead.
601 DCHECK_LE(1200u, chlo.length());
vasilvvc48c8712019-03-11 13:38:16 -0700602 std::string truncated_chlo = chlo.substr(0, 1100);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500603 DCHECK_EQ(1100u, truncated_chlo.length());
nharper4fd11052019-06-04 14:23:22 -0700604 ProcessPacket(client_address, TestConnectionId(1), true,
fayange3f2f7b2019-09-19 17:01:57 -0700605 QuicVersionReservedForNegotiation(), truncated_chlo, false,
nharper4fd11052019-06-04 14:23:22 -0700606 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500607}
608
609// Disabling CHLO size validation allows the dispatcher to send version
610// negotiation packets in response to a CHLO that is otherwise too small.
611TEST_F(QuicDispatcherTest, VersionNegotiationWithoutChloSizeValidation) {
612 crypto_config_.set_validate_chlo_size(false);
613
614 CreateTimeWaitListManager();
615 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
616
617 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
618 EXPECT_CALL(*time_wait_list_manager_,
dschinazi48ac9192019-07-31 00:07:26 -0700619 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500620 .Times(1);
vasilvvc48c8712019-03-11 13:38:16 -0700621 std::string chlo = SerializeCHLO() + std::string(1200, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500622 // Truncate to 1100 bytes of payload which results in a packet just
623 // under 1200 bytes after framing, packet, and encryption overhead.
624 DCHECK_LE(1200u, chlo.length());
vasilvvc48c8712019-03-11 13:38:16 -0700625 std::string truncated_chlo = chlo.substr(0, 1100);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500626 DCHECK_EQ(1100u, truncated_chlo.length());
nharper4fd11052019-06-04 14:23:22 -0700627 ProcessPacket(client_address, TestConnectionId(1), true,
fayange3f2f7b2019-09-19 17:01:57 -0700628 QuicVersionReservedForNegotiation(), truncated_chlo, true,
nharper4fd11052019-06-04 14:23:22 -0700629 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500630}
631
632TEST_F(QuicDispatcherTest, Shutdown) {
633 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
634
dmcardlecf0bfcf2019-12-13 08:08:21 -0800635 EXPECT_CALL(
636 *dispatcher_,
637 CreateQuicSession(_, client_address, quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800638 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500639 dispatcher_.get(), config_, TestConnectionId(1), client_address,
640 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800641 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500642 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
643 ProcessUdpPacket(_, _, _))
644 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
645 ValidatePacket(TestConnectionId(1), packet);
646 })));
647
648 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700649 ShouldCreateOrBufferPacketForConnection(
650 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500651 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
652
653 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
654 CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
655
656 dispatcher_->Shutdown();
657}
658
659TEST_F(QuicDispatcherTest, TimeWaitListManager) {
660 CreateTimeWaitListManager();
661
662 // Create a new session.
663 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
664 QuicConnectionId connection_id = TestConnectionId(1);
dmcardlecf0bfcf2019-12-13 08:08:21 -0800665 EXPECT_CALL(*dispatcher_,
666 CreateQuicSession(connection_id, client_address,
667 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800668 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500669 dispatcher_.get(), config_, connection_id, client_address,
670 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800671 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500672 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
673 ProcessUdpPacket(_, _, _))
674 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
675 ValidatePacket(TestConnectionId(1), packet);
676 })));
677
678 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700679 ShouldCreateOrBufferPacketForConnection(
680 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500681 ProcessPacket(client_address, connection_id, true, SerializeCHLO());
682
683 // Now close the connection, which should add it to the time wait list.
684 session1_->connection()->CloseConnection(
685 QUIC_INVALID_VERSION,
686 "Server: Packet 2 without version flag before version negotiated.",
687 ConnectionCloseBehavior::SILENT_CLOSE);
688 EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
689
690 // Dispatcher forwards subsequent packets for this connection_id to the time
691 // wait list manager.
692 EXPECT_CALL(*time_wait_list_manager_,
693 ProcessPacket(_, _, connection_id, _, _))
694 .Times(1);
695 EXPECT_CALL(*time_wait_list_manager_,
696 AddConnectionIdToTimeWait(_, _, _, _, _))
697 .Times(0);
698 ProcessPacket(client_address, connection_id, true, "data");
699}
700
701TEST_F(QuicDispatcherTest, NoVersionPacketToTimeWaitListManager) {
702 CreateTimeWaitListManager();
703
704 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
705 QuicConnectionId connection_id = TestConnectionId(1);
706 // Dispatcher forwards all packets for this connection_id to the time wait
707 // list manager.
dmcardlecf0bfcf2019-12-13 08:08:21 -0800708 EXPECT_CALL(*dispatcher_,
709 CreateQuicSession(_, _, quiche::QuicheStringPiece("hq"), _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500710 .Times(0);
fayang9d6231c2019-12-04 07:10:13 -0800711 EXPECT_CALL(*time_wait_list_manager_,
712 ProcessPacket(_, _, connection_id, _, _))
713 .Times(0);
714 EXPECT_CALL(*time_wait_list_manager_,
715 AddConnectionIdToTimeWait(_, _, _, _, _))
716 .Times(0);
717 EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
718 .Times(1);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500719 ProcessPacket(client_address, connection_id, false, SerializeCHLO());
720}
721
fayangd057e662019-07-10 13:29:41 -0700722TEST_F(QuicDispatcherTest,
723 DonotTimeWaitPacketsWithUnknownConnectionIdAndNoVersion) {
724 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
725 CreateTimeWaitListManager();
726
727 char short_packet[22] = {0x70, 0xa7, 0x02, 0x6b};
728 QuicReceivedPacket packet(short_packet, 22, QuicTime::Zero());
729 char valid_size_packet[23] = {0x70, 0xa7, 0x02, 0x6c};
730 QuicReceivedPacket packet2(valid_size_packet, 23, QuicTime::Zero());
731 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
fayang9d6231c2019-12-04 07:10:13 -0800732 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
733 EXPECT_CALL(*time_wait_list_manager_,
734 AddConnectionIdToTimeWait(_, _, _, _, _))
735 .Times(0);
736 // Verify small packet is silently dropped.
737 EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
738 .Times(0);
fayangd057e662019-07-10 13:29:41 -0700739 dispatcher_->ProcessPacket(server_address_, client_address, packet);
fayang9d6231c2019-12-04 07:10:13 -0800740 EXPECT_CALL(*time_wait_list_manager_, SendPublicReset(_, _, _, _, _))
741 .Times(1);
fayangd057e662019-07-10 13:29:41 -0700742 dispatcher_->ProcessPacket(server_address_, client_address, packet2);
743}
744
QUICHE teamc65d1d12019-03-19 20:58:04 -0700745// Makes sure nine-byte connection IDs are replaced by 8-byte ones.
QUICHE team963d57e2019-03-21 10:58:47 -0700746TEST_F(QuicDispatcherTest, LongConnectionIdLengthReplaced) {
dschinazi97da52b2020-01-13 15:44:43 -0800747 if (!CurrentSupportedVersions()[0].AllowsVariableLengthConnectionIds()) {
QUICHE teamc65d1d12019-03-19 20:58:04 -0700748 // When variable length connection IDs are not supported, the connection
749 // fails. See StrayPacketTruncatedConnectionId.
QUICHE team8e2e4532019-03-14 14:37:56 -0700750 return;
751 }
QUICHE team8e2e4532019-03-14 14:37:56 -0700752 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
753
QUICHE teamc65d1d12019-03-19 20:58:04 -0700754 QuicConnectionId bad_connection_id = TestConnectionIdNineBytesLong(2);
dschinazi28c1bf32019-08-19 11:54:46 -0700755 QuicConnectionId fixed_connection_id =
756 QuicUtils::CreateReplacementConnectionId(bad_connection_id);
QUICHE teamc65d1d12019-03-19 20:58:04 -0700757
758 EXPECT_CALL(*dispatcher_,
759 CreateQuicSession(fixed_connection_id, client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800760 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800761 .WillOnce(Return(ByMove(CreateSession(
QUICHE teamc65d1d12019-03-19 20:58:04 -0700762 dispatcher_.get(), config_, fixed_connection_id, client_address,
763 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800764 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teamc65d1d12019-03-19 20:58:04 -0700765 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
766 ProcessUdpPacket(_, _, _))
767 .WillOnce(WithArg<2>(
768 Invoke([this, bad_connection_id](const QuicEncryptedPacket& packet) {
769 ValidatePacket(bad_connection_id, packet);
770 })));
771 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700772 ShouldCreateOrBufferPacketForConnection(
773 ReceivedPacketInfoConnectionIdEquals(bad_connection_id)));
QUICHE teamc65d1d12019-03-19 20:58:04 -0700774 ProcessPacket(client_address, bad_connection_id, true, SerializeCHLO());
QUICHE team8e2e4532019-03-14 14:37:56 -0700775}
776
QUICHE team963d57e2019-03-21 10:58:47 -0700777// Makes sure zero-byte connection IDs are replaced by 8-byte ones.
778TEST_F(QuicDispatcherTest, InvalidShortConnectionIdLengthReplaced) {
dschinazi97da52b2020-01-13 15:44:43 -0800779 if (!CurrentSupportedVersions()[0].AllowsVariableLengthConnectionIds()) {
QUICHE team963d57e2019-03-21 10:58:47 -0700780 // When variable length connection IDs are not supported, the connection
781 // fails. See StrayPacketTruncatedConnectionId.
782 return;
783 }
784 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
785
786 QuicConnectionId bad_connection_id = EmptyQuicConnectionId();
dschinazi28c1bf32019-08-19 11:54:46 -0700787 QuicConnectionId fixed_connection_id =
788 QuicUtils::CreateReplacementConnectionId(bad_connection_id);
QUICHE team963d57e2019-03-21 10:58:47 -0700789
790 // Disable validation of invalid short connection IDs.
dschinazi7b9278c2019-05-20 07:36:21 -0700791 dispatcher_->SetAllowShortInitialServerConnectionIds(true);
QUICHE team963d57e2019-03-21 10:58:47 -0700792 // Note that StrayPacketTruncatedConnectionId covers the case where the
793 // validation is still enabled.
794
795 EXPECT_CALL(*dispatcher_,
796 CreateQuicSession(fixed_connection_id, client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800797 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800798 .WillOnce(Return(ByMove(CreateSession(
QUICHE team963d57e2019-03-21 10:58:47 -0700799 dispatcher_.get(), config_, fixed_connection_id, client_address,
800 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800801 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE team963d57e2019-03-21 10:58:47 -0700802 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
803 ProcessUdpPacket(_, _, _))
804 .WillOnce(WithArg<2>(
805 Invoke([this, bad_connection_id](const QuicEncryptedPacket& packet) {
806 ValidatePacket(bad_connection_id, packet);
807 })));
808 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700809 ShouldCreateOrBufferPacketForConnection(
810 ReceivedPacketInfoConnectionIdEquals(bad_connection_id)));
QUICHE team963d57e2019-03-21 10:58:47 -0700811 ProcessPacket(client_address, bad_connection_id, true, SerializeCHLO());
QUICHE team963d57e2019-03-21 10:58:47 -0700812}
813
QUICHE teamc65d1d12019-03-19 20:58:04 -0700814// Makes sure TestConnectionId(1) creates a new connection and
815// TestConnectionIdNineBytesLong(2) gets replaced.
QUICHE team8e2e4532019-03-14 14:37:56 -0700816TEST_F(QuicDispatcherTest, MixGoodAndBadConnectionIdLengthPackets) {
dschinazi97da52b2020-01-13 15:44:43 -0800817 if (!CurrentSupportedVersions()[0].AllowsVariableLengthConnectionIds()) {
QUICHE team8e2e4532019-03-14 14:37:56 -0700818 return;
819 }
QUICHE teamc65d1d12019-03-19 20:58:04 -0700820
QUICHE team8e2e4532019-03-14 14:37:56 -0700821 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QUICHE teamc65d1d12019-03-19 20:58:04 -0700822 QuicConnectionId bad_connection_id = TestConnectionIdNineBytesLong(2);
dschinazi28c1bf32019-08-19 11:54:46 -0700823 QuicConnectionId fixed_connection_id =
824 QuicUtils::CreateReplacementConnectionId(bad_connection_id);
QUICHE team8e2e4532019-03-14 14:37:56 -0700825
826 EXPECT_CALL(*dispatcher_,
827 CreateQuicSession(TestConnectionId(1), client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800828 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800829 .WillOnce(Return(ByMove(CreateSession(
QUICHE team8e2e4532019-03-14 14:37:56 -0700830 dispatcher_.get(), config_, TestConnectionId(1), client_address,
831 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800832 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE team8e2e4532019-03-14 14:37:56 -0700833 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
834 ProcessUdpPacket(_, _, _))
835 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
836 ValidatePacket(TestConnectionId(1), packet);
837 })));
838 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700839 ShouldCreateOrBufferPacketForConnection(
840 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE team8e2e4532019-03-14 14:37:56 -0700841 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
QUICHE team8e2e4532019-03-14 14:37:56 -0700842
QUICHE teamc65d1d12019-03-19 20:58:04 -0700843 EXPECT_CALL(*dispatcher_,
844 CreateQuicSession(fixed_connection_id, client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800845 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800846 .WillOnce(Return(ByMove(CreateSession(
QUICHE teamc65d1d12019-03-19 20:58:04 -0700847 dispatcher_.get(), config_, fixed_connection_id, client_address,
848 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800849 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_))));
QUICHE teamc65d1d12019-03-19 20:58:04 -0700850 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
851 ProcessUdpPacket(_, _, _))
852 .WillOnce(WithArg<2>(
853 Invoke([this, bad_connection_id](const QuicEncryptedPacket& packet) {
854 ValidatePacket(bad_connection_id, packet);
855 })));
856 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700857 ShouldCreateOrBufferPacketForConnection(
858 ReceivedPacketInfoConnectionIdEquals(bad_connection_id)));
QUICHE teamc65d1d12019-03-19 20:58:04 -0700859 ProcessPacket(client_address, bad_connection_id, true, SerializeCHLO());
QUICHE team8e2e4532019-03-14 14:37:56 -0700860
861 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
862 ProcessUdpPacket(_, _, _))
863 .Times(1)
864 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
865 ValidatePacket(TestConnectionId(1), packet);
866 })));
867 ProcessPacket(client_address, TestConnectionId(1), false, "data");
868}
869
QUICHE teama6ef0a62019-03-07 20:34:33 -0500870TEST_F(QuicDispatcherTest, ProcessPacketWithZeroPort) {
871 CreateTimeWaitListManager();
872
873 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 0);
874
875 // dispatcher_ should drop this packet.
876 EXPECT_CALL(*dispatcher_,
877 CreateQuicSession(TestConnectionId(1), client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800878 quiche::QuicheStringPiece("hq"), _))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500879 .Times(0);
880 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
881 EXPECT_CALL(*time_wait_list_manager_,
882 AddConnectionIdToTimeWait(_, _, _, _, _))
883 .Times(0);
884 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
885}
886
dschinaziee07e472019-06-19 09:56:56 -0700887TEST_F(QuicDispatcherTest, ProcessPacketWithInvalidShortInitialConnectionId) {
dschinazi8b1c45a2019-10-17 08:48:13 -0700888 // Enable a version that supports connection IDs of length different than 8.
dschinaziee07e472019-06-19 09:56:56 -0700889 CreateTimeWaitListManager();
890
891 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
892
893 // dispatcher_ should drop this packet.
dmcardlecf0bfcf2019-12-13 08:08:21 -0800894 EXPECT_CALL(
895 *dispatcher_,
896 CreateQuicSession(_, client_address, quiche::QuicheStringPiece("hq"), _))
dschinaziee07e472019-06-19 09:56:56 -0700897 .Times(0);
898 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
899 EXPECT_CALL(*time_wait_list_manager_,
900 AddConnectionIdToTimeWait(_, _, _, _, _))
901 .Times(0);
902 ProcessPacket(client_address, EmptyQuicConnectionId(), true, SerializeCHLO());
903}
904
QUICHE teama6ef0a62019-03-07 20:34:33 -0500905TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) {
906 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
907 QuicConnectionId connection_id = TestConnectionId(1);
908
909 EXPECT_CALL(*dispatcher_,
910 CreateQuicSession(TestConnectionId(1), client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800911 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -0800912 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500913 dispatcher_.get(), config_, TestConnectionId(1), client_address,
914 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -0800915 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500916 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
917 ProcessUdpPacket(_, _, _))
918 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
919 ValidatePacket(TestConnectionId(1), packet);
920 })));
921
922 // A packet whose packet number is the largest that is allowed to start a
923 // connection.
924 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -0700925 ShouldCreateOrBufferPacketForConnection(
926 ReceivedPacketInfoConnectionIdEquals(connection_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500927 ProcessPacket(client_address, connection_id, true, SerializeCHLO(),
928 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
929 QuicDispatcher::kMaxReasonableInitialPacketNumber);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500930}
931
dschinazi76881f02019-12-09 14:56:14 -0800932TEST_F(QuicDispatcherTest, VersionsChangeInFlight) {
933 for (ParsedQuicVersion version : AllSupportedVersions()) {
934 QuicEnableVersion(version);
935 }
936 ASSERT_EQ(AllSupportedVersions(), CurrentSupportedVersions());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500937
fayangb880b4c2019-06-14 12:26:35 -0700938 VerifyVersionNotSupported(QuicVersionReservedForNegotiation());
939
940 VerifyVersionSupported(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
941 QuicVersionMin().transport_version));
dschinazi76881f02019-12-09 14:56:14 -0800942 VerifyVersionSupported(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO,
943 QuicVersionMax().transport_version));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500944
dschinazi76881f02019-12-09 14:56:14 -0800945 // Turn off version Q099.
946 SetQuicReloadableFlag(quic_enable_version_q099, false);
nharperc32d8ab2019-10-09 11:09:06 -0700947 VerifyVersionNotSupported(
nharpere2515092019-12-05 12:08:19 -0800948 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_99));
nharperc32d8ab2019-10-09 11:09:06 -0700949
dschinazi76881f02019-12-09 14:56:14 -0800950 // Turn on version Q099.
951 SetQuicReloadableFlag(quic_enable_version_q099, true);
nharperc32d8ab2019-10-09 11:09:06 -0700952 VerifyVersionSupported(
nharpere2515092019-12-05 12:08:19 -0800953 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_99));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500954}
955
fayangb54ac5b2019-07-01 10:30:37 -0700956TEST_F(QuicDispatcherTest, RejectDeprecatedVersionsWithVersionNegotiation) {
bnc4e9283d2019-12-17 07:08:57 -0800957 static_assert(QUICHE_ARRAYSIZE(kSupportedTransportVersions) == 6u,
fayangb54ac5b2019-07-01 10:30:37 -0700958 "Please add deprecated versions to this test");
959 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
960 CreateTimeWaitListManager();
961
dschinazi8b1c45a2019-10-17 08:48:13 -0700962 {
963 char packet47[kMinPacketSizeForVersionNegotiation] = {
964 0xC0, 'Q', '0', '4', '7', /*connection ID length byte*/ 0x50};
965 QuicReceivedPacket received_packet47(
966 packet47, kMinPacketSizeForVersionNegotiation, QuicTime::Zero());
967 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
968 EXPECT_CALL(*time_wait_list_manager_,
969 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
970 .Times(1);
971 dispatcher_->ProcessPacket(server_address_, client_address,
972 received_packet47);
973 }
fayang36825da2019-08-21 14:01:27 -0700974
dschinazi8b1c45a2019-10-17 08:48:13 -0700975 {
976 char packet45[kMinPacketSizeForVersionNegotiation] = {
977 0xC0, 'Q', '0', '4', '5', /*connection ID length byte*/ 0x50};
978 QuicReceivedPacket received_packet45(
979 packet45, kMinPacketSizeForVersionNegotiation, QuicTime::Zero());
980 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
981 EXPECT_CALL(*time_wait_list_manager_,
982 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
983 .Times(1);
984 dispatcher_->ProcessPacket(server_address_, client_address,
985 received_packet45);
986 }
987
988 {
989 char packet44[kMinPacketSizeForVersionNegotiation] = {
990 0xFF, 'Q', '0', '4', '4', /*connection ID length byte*/ 0x50};
991 QuicReceivedPacket received_packet44(
992 packet44, kMinPacketSizeForVersionNegotiation, QuicTime::Zero());
993 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
994 EXPECT_CALL(*time_wait_list_manager_,
995 SendVersionNegotiationPacket(_, _, _, _, _, _, _, _))
996 .Times(1);
997 dispatcher_->ProcessPacket(server_address_, client_address,
998 received_packet44);
999 }
fayangb54ac5b2019-07-01 10:30:37 -07001000}
1001
dschinazi30ab6db2019-08-13 14:43:32 -07001002TEST_F(QuicDispatcherTest, VersionNegotiationProbeOld) {
1003 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, false);
dschinazi30ab6db2019-08-13 14:43:32 -07001004 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1005 CreateTimeWaitListManager();
1006 char packet[1200];
1007 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1008 0x6c, 0x7a, 0x20, 0x21};
1009 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1010 packet, sizeof(packet), destination_connection_id_bytes,
1011 sizeof(destination_connection_id_bytes)));
1012 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1013 std::unique_ptr<QuicReceivedPacket> received_packet(
1014 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1015 QuicConnectionId client_connection_id = EmptyQuicConnectionId();
1016 QuicConnectionId server_connection_id(
1017 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1018 bool ietf_quic = true;
1019 bool use_length_prefix =
1020 GetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids);
1021 EXPECT_CALL(
1022 *time_wait_list_manager_,
1023 SendVersionNegotiationPacket(server_connection_id, client_connection_id,
1024 ietf_quic, use_length_prefix, _, _, _, _))
1025 .Times(1);
1026 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1027
1028 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1029}
1030
1031TEST_F(QuicDispatcherTest, VersionNegotiationProbe) {
1032 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, true);
dschinazi30ab6db2019-08-13 14:43:32 -07001033 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1034 CreateTimeWaitListManager();
1035 char packet[1200];
1036 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1037 0x6c, 0x7a, 0x20, 0x21};
1038 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1039 packet, sizeof(packet), destination_connection_id_bytes,
1040 sizeof(destination_connection_id_bytes)));
1041 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1042 std::unique_ptr<QuicReceivedPacket> received_packet(
1043 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1044 QuicConnectionId client_connection_id = EmptyQuicConnectionId();
1045 QuicConnectionId server_connection_id(
1046 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1047 bool ietf_quic = true;
1048 bool use_length_prefix =
1049 GetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids);
1050 EXPECT_CALL(
1051 *time_wait_list_manager_,
1052 SendVersionNegotiationPacket(server_connection_id, client_connection_id,
1053 ietf_quic, use_length_prefix, _, _, _, _))
1054 .Times(1);
1055 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1056
1057 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1058}
1059
dschinazi0185ebb2019-08-14 11:09:35 -07001060// Testing packet writer that saves all packets instead of sending them.
1061// Useful for tests that need access to sent packets.
1062class SavingWriter : public QuicPacketWriterWrapper {
1063 public:
1064 bool IsWriteBlocked() const override { return false; }
1065
1066 WriteResult WritePacket(const char* buffer,
1067 size_t buf_len,
1068 const QuicIpAddress& /*self_client_address*/,
1069 const QuicSocketAddress& /*peer_client_address*/,
1070 PerPacketOptions* /*options*/) override {
1071 packets_.push_back(
1072 QuicEncryptedPacket(buffer, buf_len, /*owns_buffer=*/false).Clone());
1073 return WriteResult(WRITE_STATUS_OK, buf_len);
1074 }
1075
1076 std::vector<std::unique_ptr<QuicEncryptedPacket>>* packets() {
1077 return &packets_;
1078 }
1079
1080 private:
1081 std::vector<std::unique_ptr<QuicEncryptedPacket>> packets_;
1082};
1083
1084TEST_F(QuicDispatcherTest, VersionNegotiationProbeEndToEndOld) {
1085 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, false);
dschinazi0185ebb2019-08-14 11:09:35 -07001086
1087 SavingWriter* saving_writer = new SavingWriter();
1088 // dispatcher_ takes ownership of saving_writer.
1089 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1090
1091 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1092 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1093 &mock_alarm_factory_);
1094 // dispatcher_ takes ownership of time_wait_list_manager.
1095 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1096 time_wait_list_manager);
1097 char packet[1200] = {};
1098 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1099 0x6c, 0x7a, 0x20, 0x21};
1100 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1101 packet, sizeof(packet), destination_connection_id_bytes,
1102 sizeof(destination_connection_id_bytes)));
1103 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1104 std::unique_ptr<QuicReceivedPacket> received_packet(
1105 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1106 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1107
1108 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1109 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1110 ASSERT_EQ(1u, saving_writer->packets()->size());
1111
1112 char source_connection_id_bytes[255] = {};
1113 uint8_t source_connection_id_length = 0;
1114 std::string detailed_error = "foobar";
1115 EXPECT_TRUE(QuicFramer::ParseServerVersionNegotiationProbeResponse(
1116 (*(saving_writer->packets()))[0]->data(),
1117 (*(saving_writer->packets()))[0]->length(), source_connection_id_bytes,
1118 &source_connection_id_length, &detailed_error));
1119 EXPECT_EQ("", detailed_error);
1120
1121 // The source connection ID of the probe response should match the
1122 // destination connection ID of the probe request.
dmcardle8f7df532020-01-07 13:28:57 -08001123 quiche::test::CompareCharArraysWithHexError(
dschinazi0185ebb2019-08-14 11:09:35 -07001124 "parsed probe", source_connection_id_bytes, source_connection_id_length,
1125 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1126}
1127
1128TEST_F(QuicDispatcherTest, VersionNegotiationProbeEndToEnd) {
1129 SetQuicFlag(FLAGS_quic_prober_uses_length_prefixed_connection_ids, true);
dschinazi0185ebb2019-08-14 11:09:35 -07001130
1131 SavingWriter* saving_writer = new SavingWriter();
1132 // dispatcher_ takes ownership of saving_writer.
1133 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1134
1135 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1136 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1137 &mock_alarm_factory_);
1138 // dispatcher_ takes ownership of time_wait_list_manager.
1139 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1140 time_wait_list_manager);
1141 char packet[1200] = {};
1142 char destination_connection_id_bytes[] = {0x56, 0x4e, 0x20, 0x70,
1143 0x6c, 0x7a, 0x20, 0x21};
1144 EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
1145 packet, sizeof(packet), destination_connection_id_bytes,
1146 sizeof(destination_connection_id_bytes)));
1147 QuicEncryptedPacket encrypted(packet, sizeof(packet), false);
1148 std::unique_ptr<QuicReceivedPacket> received_packet(
1149 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1150 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1151
1152 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1153 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1154 ASSERT_EQ(1u, saving_writer->packets()->size());
1155
1156 char source_connection_id_bytes[255] = {};
1157 uint8_t source_connection_id_length = 0;
1158 std::string detailed_error = "foobar";
1159 EXPECT_TRUE(QuicFramer::ParseServerVersionNegotiationProbeResponse(
1160 (*(saving_writer->packets()))[0]->data(),
1161 (*(saving_writer->packets()))[0]->length(), source_connection_id_bytes,
1162 &source_connection_id_length, &detailed_error));
1163 EXPECT_EQ("", detailed_error);
1164
1165 // The source connection ID of the probe response should match the
1166 // destination connection ID of the probe request.
dmcardle8f7df532020-01-07 13:28:57 -08001167 quiche::test::CompareCharArraysWithHexError(
dschinazi0185ebb2019-08-14 11:09:35 -07001168 "parsed probe", source_connection_id_bytes, source_connection_id_length,
1169 destination_connection_id_bytes, sizeof(destination_connection_id_bytes));
1170}
1171
dschinazi5b236be2019-08-19 14:55:22 -07001172TEST_F(QuicDispatcherTest, AndroidConformanceTestOld) {
1173 // TODO(b/139691956) Remove this test once the workaround is removed.
dschinazi5b236be2019-08-19 14:55:22 -07001174 SavingWriter* saving_writer = new SavingWriter();
1175 // dispatcher_ takes ownership of saving_writer.
1176 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1177
1178 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1179 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1180 &mock_alarm_factory_);
1181 // dispatcher_ takes ownership of time_wait_list_manager.
1182 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1183 time_wait_list_manager);
1184 // clang-format off
1185 static const unsigned char packet[] = {
1186 // Android UDP network conformance test packet as it was before this change:
1187 // https://android-review.googlesource.com/c/platform/cts/+/1104285
1188 0x0c, // public flags: 8-byte connection ID, 1-byte packet number
1189 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, // 8-byte connection ID
1190 0x01, // 1-byte packet number
1191 0x00, // private flags
1192 0x07, // PING frame
1193 };
1194 // clang-format on
1195
1196 QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet),
1197 sizeof(packet), false);
1198 std::unique_ptr<QuicReceivedPacket> received_packet(
1199 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1200 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1201
1202 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1203 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1204 ASSERT_EQ(1u, saving_writer->packets()->size());
1205
1206 // The Android UDP network conformance test directly checks that bytes 1-9
1207 // of the response match the connection ID that was sent.
1208 static const char connection_id_bytes[] = {0x71, 0x72, 0x73, 0x74,
1209 0x75, 0x76, 0x77, 0x78};
1210 ASSERT_GE((*(saving_writer->packets()))[0]->length(),
1211 1u + sizeof(connection_id_bytes));
dmcardle8f7df532020-01-07 13:28:57 -08001212 quiche::test::CompareCharArraysWithHexError(
dschinazi5b236be2019-08-19 14:55:22 -07001213 "response connection ID", &(*(saving_writer->packets()))[0]->data()[1],
1214 sizeof(connection_id_bytes), connection_id_bytes,
1215 sizeof(connection_id_bytes));
1216}
1217
dschinazi5b236be2019-08-19 14:55:22 -07001218TEST_F(QuicDispatcherTest, AndroidConformanceTest) {
1219 // WARNING: do not remove or modify this test without making sure that we
1220 // still have adequate coverage for the Android conformance test.
dschinazi5b236be2019-08-19 14:55:22 -07001221 SavingWriter* saving_writer = new SavingWriter();
1222 // dispatcher_ takes ownership of saving_writer.
1223 QuicDispatcherPeer::UseWriter(dispatcher_.get(), saving_writer);
1224
1225 QuicTimeWaitListManager* time_wait_list_manager = new QuicTimeWaitListManager(
1226 saving_writer, dispatcher_.get(), mock_helper_.GetClock(),
1227 &mock_alarm_factory_);
1228 // dispatcher_ takes ownership of time_wait_list_manager.
1229 QuicDispatcherPeer::SetTimeWaitListManager(dispatcher_.get(),
1230 time_wait_list_manager);
1231 // clang-format off
1232 static const unsigned char packet[1200] = {
1233 // Android UDP network conformance test packet as it was after this change:
1234 // https://android-review.googlesource.com/c/platform/cts/+/1104285
1235 0x0d, // public flags: version, 8-byte connection ID, 1-byte packet number
1236 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, // 8-byte connection ID
1237 0xaa, 0xda, 0xca, 0xaa, // reserved-space version number
1238 0x01, // 1-byte packet number
1239 0x00, // private flags
1240 0x07, // PING frame
1241 };
1242 // clang-format on
1243
1244 QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet),
1245 sizeof(packet), false);
1246 std::unique_ptr<QuicReceivedPacket> received_packet(
1247 ConstructReceivedPacket(encrypted, mock_helper_.GetClock()->Now()));
1248 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
1249
1250 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1251 dispatcher_->ProcessPacket(server_address_, client_address, *received_packet);
1252 ASSERT_EQ(1u, saving_writer->packets()->size());
1253
1254 // The Android UDP network conformance test directly checks that bytes 1-9
1255 // of the response match the connection ID that was sent.
1256 static const char connection_id_bytes[] = {0x71, 0x72, 0x73, 0x74,
1257 0x75, 0x76, 0x77, 0x78};
1258 ASSERT_GE((*(saving_writer->packets()))[0]->length(),
1259 1u + sizeof(connection_id_bytes));
dmcardle8f7df532020-01-07 13:28:57 -08001260 quiche::test::CompareCharArraysWithHexError(
dschinazi5b236be2019-08-19 14:55:22 -07001261 "response connection ID", &(*(saving_writer->packets()))[0]->data()[1],
1262 sizeof(connection_id_bytes), connection_id_bytes,
1263 sizeof(connection_id_bytes));
1264}
1265
fayange3f2f7b2019-09-19 17:01:57 -07001266TEST_F(QuicDispatcherTest, DoNotProcessSmallPacket) {
fayange3f2f7b2019-09-19 17:01:57 -07001267 CreateTimeWaitListManager();
1268 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1269
1270 EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
rch9d76c2d2019-12-20 12:19:48 -08001271 if (GetQuicReloadableFlag(quic_drop_small_initial_packets)) {
1272 EXPECT_CALL(*time_wait_list_manager_, SendPacket(_, _, _)).Times(0);
1273 } else {
1274 EXPECT_CALL(*time_wait_list_manager_, SendPacket(_, _, _)).Times(1);
1275 }
1276 EXPECT_CALL(*time_wait_list_manager_,
1277 AddConnectionIdToTimeWait(_, _, _, _, _))
1278 .Times(0);
fayange3f2f7b2019-09-19 17:01:57 -07001279 ProcessPacket(client_address, TestConnectionId(1), true,
1280 CurrentSupportedVersions()[0], SerializeCHLO(), false,
1281 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER, 1);
1282}
1283
1284TEST_F(QuicDispatcherTest, ProcessSmallCoalescedPacket) {
dschinazi76881f02019-12-09 14:56:14 -08001285 SetQuicReloadableFlag(quic_enable_version_q099, true);
fayange3f2f7b2019-09-19 17:01:57 -07001286 CreateTimeWaitListManager();
1287 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1288
1289 EXPECT_CALL(*time_wait_list_manager_, SendPacket(_, _, _)).Times(0);
1290
1291 // clang-format off
1292 char coalesced_packet[1200] = {
1293 // first coalesced packet
1294 // public flags (long header with packet type INITIAL and
1295 // 4-byte packet number)
1296 0xC3,
1297 // version
1298 'Q', '0', '9', '9',
1299 // destination connection ID length
1300 0x08,
1301 // destination connection ID
1302 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
1303 // source connection ID length
1304 0x00,
1305 // long header packet length
1306 0x05,
1307 // packet number
1308 0x12, 0x34, 0x56, 0x78,
1309 // Padding
1310 0x00,
1311 // second coalesced packet
1312 // public flags (long header with packet type ZERO_RTT_PROTECTED and
1313 // 4-byte packet number)
1314 0xC3,
1315 // version
1316 'Q', '0', '9', '9',
1317 // destination connection ID length
1318 0x08,
1319 // destination connection ID
1320 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
1321 // source connection ID length
1322 0x00,
1323 // long header packet length
1324 0x1E,
1325 // packet number
1326 0x12, 0x34, 0x56, 0x79,
1327 };
1328 // clang-format on
1329 QuicReceivedPacket packet(coalesced_packet, 1200, QuicTime::Zero());
1330 dispatcher_->ProcessPacket(server_address_, client_address, packet);
1331}
1332
QUICHE teama6ef0a62019-03-07 20:34:33 -05001333// Verify the stopgap test: Packets with truncated connection IDs should be
1334// dropped.
1335class QuicDispatcherTestStrayPacketConnectionId : public QuicDispatcherTest {};
1336
1337// Packets with truncated connection IDs should be dropped.
1338TEST_F(QuicDispatcherTestStrayPacketConnectionId,
1339 StrayPacketTruncatedConnectionId) {
1340 CreateTimeWaitListManager();
1341
1342 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1343 QuicConnectionId connection_id = TestConnectionId(1);
dmcardlecf0bfcf2019-12-13 08:08:21 -08001344 EXPECT_CALL(*dispatcher_,
1345 CreateQuicSession(_, _, quiche::QuicheStringPiece("hq"), _))
QUICHE teama6ef0a62019-03-07 20:34:33 -05001346 .Times(0);
fayangd4291e42019-05-30 10:31:21 -07001347 if (VersionHasIetfInvariantHeader(
QUICHE team963d57e2019-03-21 10:58:47 -07001348 CurrentSupportedVersions()[0].transport_version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001349 // This IETF packet has invalid connection ID length.
1350 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
1351 .Times(0);
1352 EXPECT_CALL(*time_wait_list_manager_,
1353 AddConnectionIdToTimeWait(_, _, _, _, _))
1354 .Times(0);
1355 } else {
dschinaziee07e472019-06-19 09:56:56 -07001356 // This is a GQUIC packet considered as IETF QUIC packet with short header
1357 // with unacceptable packet number.
QUICHE teama6ef0a62019-03-07 20:34:33 -05001358 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _))
1359 .Times(1);
1360 EXPECT_CALL(*time_wait_list_manager_,
1361 AddConnectionIdToTimeWait(_, _, _, _, _))
1362 .Times(1);
1363 }
1364 ProcessPacket(client_address, connection_id, true, "data",
1365 CONNECTION_ID_ABSENT, PACKET_4BYTE_PACKET_NUMBER);
1366}
1367
1368class BlockingWriter : public QuicPacketWriterWrapper {
1369 public:
1370 BlockingWriter() : write_blocked_(false) {}
1371
1372 bool IsWriteBlocked() const override { return write_blocked_; }
1373 void SetWritable() override { write_blocked_ = false; }
1374
dschinazi17d42422019-06-18 16:35:07 -07001375 WriteResult WritePacket(const char* /*buffer*/,
1376 size_t /*buf_len*/,
1377 const QuicIpAddress& /*self_client_address*/,
1378 const QuicSocketAddress& /*peer_client_address*/,
1379 PerPacketOptions* /*options*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001380 // It would be quite possible to actually implement this method here with
1381 // the fake blocked status, but it would be significantly more work in
1382 // Chromium, and since it's not called anyway, don't bother.
1383 QUIC_LOG(DFATAL) << "Not supported";
1384 return WriteResult();
1385 }
1386
1387 bool write_blocked_;
1388};
1389
1390class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
1391 public:
1392 void SetUp() override {
1393 QuicDispatcherTest::SetUp();
1394 writer_ = new BlockingWriter;
1395 QuicDispatcherPeer::UseWriter(dispatcher_.get(), writer_);
1396
1397 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1398
1399 EXPECT_CALL(*dispatcher_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001400 CreateQuicSession(_, client_address,
1401 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -08001402 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001403 dispatcher_.get(), config_, TestConnectionId(1), client_address,
1404 &helper_, &alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08001405 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001406 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1407 ProcessUdpPacket(_, _, _))
1408 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
1409 ValidatePacket(TestConnectionId(1), packet);
1410 })));
fayang1ed1f762019-06-24 11:40:04 -07001411 EXPECT_CALL(*dispatcher_,
1412 ShouldCreateOrBufferPacketForConnection(
1413 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(1))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001414 ProcessPacket(client_address, TestConnectionId(1), true, SerializeCHLO());
1415
1416 EXPECT_CALL(*dispatcher_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001417 CreateQuicSession(_, client_address,
1418 quiche::QuicheStringPiece("hq"), _))
wub89490e02019-12-12 12:45:58 -08001419 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001420 dispatcher_.get(), config_, TestConnectionId(2), client_address,
1421 &helper_, &alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08001422 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001423 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
1424 ProcessUdpPacket(_, _, _))
1425 .WillOnce(WithArg<2>(Invoke([this](const QuicEncryptedPacket& packet) {
1426 ValidatePacket(TestConnectionId(2), packet);
1427 })));
fayang1ed1f762019-06-24 11:40:04 -07001428 EXPECT_CALL(*dispatcher_,
1429 ShouldCreateOrBufferPacketForConnection(
1430 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(2))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001431 ProcessPacket(client_address, TestConnectionId(2), true, SerializeCHLO());
1432
1433 blocked_list_ = QuicDispatcherPeer::GetWriteBlockedList(dispatcher_.get());
1434 }
1435
1436 void TearDown() override {
1437 if (connection1() != nullptr) {
1438 EXPECT_CALL(*connection1(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
1439 }
1440
1441 if (connection2() != nullptr) {
1442 EXPECT_CALL(*connection2(), CloseConnection(QUIC_PEER_GOING_AWAY, _, _));
1443 }
1444 dispatcher_->Shutdown();
1445 }
1446
1447 // Set the dispatcher's writer to be blocked. By default, all connections use
1448 // the same writer as the dispatcher in this test.
1449 void SetBlocked() {
1450 QUIC_LOG(INFO) << "set writer " << writer_ << " to blocked";
1451 writer_->write_blocked_ = true;
1452 }
1453
1454 // Simulate what happens when connection1 gets blocked when writing.
1455 void BlockConnection1() {
1456 Connection1Writer()->write_blocked_ = true;
1457 dispatcher_->OnWriteBlocked(connection1());
1458 }
1459
1460 BlockingWriter* Connection1Writer() {
1461 return static_cast<BlockingWriter*>(connection1()->writer());
1462 }
1463
1464 // Simulate what happens when connection2 gets blocked when writing.
1465 void BlockConnection2() {
1466 Connection2Writer()->write_blocked_ = true;
1467 dispatcher_->OnWriteBlocked(connection2());
1468 }
1469
1470 BlockingWriter* Connection2Writer() {
1471 return static_cast<BlockingWriter*>(connection2()->writer());
1472 }
1473
1474 protected:
1475 MockQuicConnectionHelper helper_;
1476 MockAlarmFactory alarm_factory_;
1477 BlockingWriter* writer_;
1478 QuicDispatcher::WriteBlockedList* blocked_list_;
1479};
1480
1481TEST_F(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) {
1482 // No OnCanWrite calls because no connections are blocked.
1483 dispatcher_->OnCanWrite();
1484
1485 // Register connection 1 for events, and make sure it's notified.
1486 SetBlocked();
1487 dispatcher_->OnWriteBlocked(connection1());
1488 EXPECT_CALL(*connection1(), OnCanWrite());
1489 dispatcher_->OnCanWrite();
1490
1491 // It should get only one notification.
1492 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1493 dispatcher_->OnCanWrite();
1494 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1495}
1496
1497TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) {
1498 // Make sure we handle events in order.
1499 InSequence s;
1500 SetBlocked();
1501 dispatcher_->OnWriteBlocked(connection1());
1502 dispatcher_->OnWriteBlocked(connection2());
1503 EXPECT_CALL(*connection1(), OnCanWrite());
1504 EXPECT_CALL(*connection2(), OnCanWrite());
1505 dispatcher_->OnCanWrite();
1506
1507 // Check the other ordering.
1508 SetBlocked();
1509 dispatcher_->OnWriteBlocked(connection2());
1510 dispatcher_->OnWriteBlocked(connection1());
1511 EXPECT_CALL(*connection2(), OnCanWrite());
1512 EXPECT_CALL(*connection1(), OnCanWrite());
1513 dispatcher_->OnCanWrite();
1514}
1515
1516TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) {
1517 // Add and remove one connction.
1518 SetBlocked();
1519 dispatcher_->OnWriteBlocked(connection1());
1520 blocked_list_->erase(connection1());
1521 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1522 dispatcher_->OnCanWrite();
1523
1524 // Add and remove one connction and make sure it doesn't affect others.
1525 SetBlocked();
1526 dispatcher_->OnWriteBlocked(connection1());
1527 dispatcher_->OnWriteBlocked(connection2());
1528 blocked_list_->erase(connection1());
1529 EXPECT_CALL(*connection2(), OnCanWrite());
1530 dispatcher_->OnCanWrite();
1531
1532 // Add it, remove it, and add it back and make sure things are OK.
1533 SetBlocked();
1534 dispatcher_->OnWriteBlocked(connection1());
1535 blocked_list_->erase(connection1());
1536 dispatcher_->OnWriteBlocked(connection1());
1537 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
1538 dispatcher_->OnCanWrite();
1539}
1540
1541TEST_F(QuicDispatcherWriteBlockedListTest, DoubleAdd) {
1542 // Make sure a double add does not necessitate a double remove.
1543 SetBlocked();
1544 dispatcher_->OnWriteBlocked(connection1());
1545 dispatcher_->OnWriteBlocked(connection1());
1546 blocked_list_->erase(connection1());
1547 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1548 dispatcher_->OnCanWrite();
1549
1550 // Make sure a double add does not result in two OnCanWrite calls.
1551 SetBlocked();
1552 dispatcher_->OnWriteBlocked(connection1());
1553 dispatcher_->OnWriteBlocked(connection1());
1554 EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
1555 dispatcher_->OnCanWrite();
1556}
1557
1558TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlockConnection1) {
1559 // If the 1st blocked writer gets blocked in OnCanWrite, it will be added back
1560 // into the write blocked list.
1561 InSequence s;
1562 SetBlocked();
1563 dispatcher_->OnWriteBlocked(connection1());
1564 dispatcher_->OnWriteBlocked(connection2());
1565 EXPECT_CALL(*connection1(), OnCanWrite())
1566 .WillOnce(
1567 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection1));
1568 EXPECT_CALL(*connection2(), OnCanWrite());
1569 dispatcher_->OnCanWrite();
1570
1571 // connection1 should be still in the write blocked list.
1572 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1573
1574 // Now call OnCanWrite again, connection1 should get its second chance.
1575 EXPECT_CALL(*connection1(), OnCanWrite());
1576 EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
1577 dispatcher_->OnCanWrite();
1578 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1579}
1580
1581TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlockConnection2) {
1582 // If the 2nd blocked writer gets blocked in OnCanWrite, it will be added back
1583 // into the write blocked list.
1584 InSequence s;
1585 SetBlocked();
1586 dispatcher_->OnWriteBlocked(connection1());
1587 dispatcher_->OnWriteBlocked(connection2());
1588 EXPECT_CALL(*connection1(), OnCanWrite());
1589 EXPECT_CALL(*connection2(), OnCanWrite())
1590 .WillOnce(
1591 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2));
1592 dispatcher_->OnCanWrite();
1593
1594 // connection2 should be still in the write blocked list.
1595 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1596
1597 // Now call OnCanWrite again, connection2 should get its second chance.
1598 EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
1599 EXPECT_CALL(*connection2(), OnCanWrite());
1600 dispatcher_->OnCanWrite();
1601 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1602}
1603
1604TEST_F(QuicDispatcherWriteBlockedListTest,
1605 OnCanWriteHandleBlockBothConnections) {
1606 // Both connections get blocked in OnCanWrite, and added back into the write
1607 // blocked list.
1608 InSequence s;
1609 SetBlocked();
1610 dispatcher_->OnWriteBlocked(connection1());
1611 dispatcher_->OnWriteBlocked(connection2());
1612 EXPECT_CALL(*connection1(), OnCanWrite())
1613 .WillOnce(
1614 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection1));
1615 EXPECT_CALL(*connection2(), OnCanWrite())
1616 .WillOnce(
1617 Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2));
1618 dispatcher_->OnCanWrite();
1619
1620 // Both connections should be still in the write blocked list.
1621 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1622
1623 // Now call OnCanWrite again, both connections should get its second chance.
1624 EXPECT_CALL(*connection1(), OnCanWrite());
1625 EXPECT_CALL(*connection2(), OnCanWrite());
1626 dispatcher_->OnCanWrite();
1627 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1628}
1629
1630TEST_F(QuicDispatcherWriteBlockedListTest, PerConnectionWriterBlocked) {
1631 // By default, all connections share the same packet writer with the
1632 // dispatcher.
1633 EXPECT_EQ(dispatcher_->writer(), connection1()->writer());
1634 EXPECT_EQ(dispatcher_->writer(), connection2()->writer());
1635
1636 // Test the case where connection1 shares the same packet writer as the
1637 // dispatcher, whereas connection2 owns it's packet writer.
1638 // Change connection2's writer.
1639 connection2()->SetQuicPacketWriter(new BlockingWriter, /*owns_writer=*/true);
1640 EXPECT_NE(dispatcher_->writer(), connection2()->writer());
1641
1642 BlockConnection2();
1643 EXPECT_TRUE(dispatcher_->HasPendingWrites());
1644
1645 EXPECT_CALL(*connection2(), OnCanWrite());
1646 dispatcher_->OnCanWrite();
1647 EXPECT_FALSE(dispatcher_->HasPendingWrites());
1648}
1649
1650TEST_F(QuicDispatcherWriteBlockedListTest,
1651 RemoveConnectionFromWriteBlockedListWhenDeletingSessions) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001652 dispatcher_->OnConnectionClosed(connection1()->connection_id(),
1653 QUIC_PACKET_WRITE_ERROR, "Closed by test.",
1654 ConnectionCloseSource::FROM_SELF);
1655
1656 SetBlocked();
1657
1658 ASSERT_FALSE(dispatcher_->HasPendingWrites());
1659 SetBlocked();
1660 dispatcher_->OnWriteBlocked(connection1());
1661 ASSERT_TRUE(dispatcher_->HasPendingWrites());
1662
1663 EXPECT_QUIC_BUG(dispatcher_->DeleteSessions(),
1664 "QuicConnection was in WriteBlockedList before destruction");
1665 MarkSession1Deleted();
1666}
1667
wub0a4b9c52019-05-28 13:18:58 -07001668class BufferedPacketStoreTest : public QuicDispatcherTest {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001669 public:
1670 BufferedPacketStoreTest()
1671 : QuicDispatcherTest(),
1672 server_addr_(QuicSocketAddress(QuicIpAddress::Any4(), 5)),
1673 client_addr_(QuicIpAddress::Loopback4(), 1234),
wub0a4b9c52019-05-28 13:18:58 -07001674 signed_config_(new QuicSignedServerConfig) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -05001675
1676 void SetUp() override {
1677 QuicDispatcherTest::SetUp();
1678 clock_ = QuicDispatcherPeer::GetHelper(dispatcher_.get())->GetClock();
1679
1680 QuicTransportVersion version = AllSupportedTransportVersions().front();
1681 CryptoHandshakeMessage chlo =
1682 crypto_test_utils::GenerateDefaultInchoateCHLO(clock_, version,
1683 &crypto_config_);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001684 // Pass an inchoate CHLO.
1685 crypto_test_utils::GenerateFullCHLO(
1686 chlo, &crypto_config_, server_addr_, client_addr_, version, clock_,
1687 signed_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
1688 &full_chlo_);
1689 }
1690
vasilvvc48c8712019-03-11 13:38:16 -07001691 std::string SerializeFullCHLO() {
1692 return std::string(full_chlo_.GetSerialized().AsStringPiece());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001693 }
1694
1695 protected:
1696 QuicSocketAddress server_addr_;
1697 QuicSocketAddress client_addr_;
1698 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
1699 const QuicClock* clock_;
1700 CryptoHandshakeMessage full_chlo_;
1701};
1702
wub0a4b9c52019-05-28 13:18:58 -07001703TEST_F(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001704 InSequence s;
1705 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1706 QuicConnectionId conn_id = TestConnectionId(1);
1707 // A bunch of non-CHLO should be buffered upon arrival, and the first one
1708 // should trigger ShouldCreateOrBufferPacketForConnection().
fayang1ed1f762019-06-24 11:40:04 -07001709 EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(
1710 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001711 for (size_t i = 1; i <= kDefaultMaxUndecryptablePackets + 1; ++i) {
1712 ProcessPacket(client_address, conn_id, true,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001713 quiche::QuicheStrCat("data packet ", i + 1),
1714 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
1715 /*packet_number=*/i + 1);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001716 }
1717 EXPECT_EQ(0u, dispatcher_->session_map().size())
1718 << "No session should be created before CHLO arrives.";
1719
1720 // Pop out the last packet as it is also be dropped by the store.
1721 data_connection_map_[conn_id].pop_back();
1722 // When CHLO arrives, a new session should be created, and all packets
1723 // buffered should be delivered to the session.
dmcardlecf0bfcf2019-12-13 08:08:21 -08001724 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address,
1725 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08001726 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001727 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1728 &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08001729 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001730
1731 // Only |kDefaultMaxUndecryptablePackets| packets were buffered, and they
1732 // should be delivered in arrival order.
1733 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1734 ProcessUdpPacket(_, _, _))
1735 .Times(kDefaultMaxUndecryptablePackets + 1) // + 1 for CHLO.
1736 .WillRepeatedly(
1737 WithArg<2>(Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1738 ValidatePacket(conn_id, packet);
1739 })));
1740 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1741}
1742
wub0a4b9c52019-05-28 13:18:58 -07001743TEST_F(BufferedPacketStoreTest,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001744 ProcessNonChloPacketsForDifferentConnectionsUptoLimit) {
1745 InSequence s;
1746 // A bunch of non-CHLO should be buffered upon arrival.
1747 size_t kNumConnections = kMaxConnectionsWithoutCHLO + 1;
1748 for (size_t i = 1; i <= kNumConnections; ++i) {
1749 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), i);
1750 QuicConnectionId conn_id = TestConnectionId(i);
1751 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -07001752 ShouldCreateOrBufferPacketForConnection(
1753 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001754 ProcessPacket(client_address, conn_id, true,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001755 quiche::QuicheStrCat("data packet on connection ", i),
QUICHE teama6ef0a62019-03-07 20:34:33 -05001756 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
1757 /*packet_number=*/2);
1758 }
1759
1760 // Pop out the packet on last connection as it shouldn't be enqueued in store
1761 // as well.
1762 data_connection_map_[TestConnectionId(kNumConnections)].pop_front();
1763
1764 // Reset session creation counter to ensure processing CHLO can always
1765 // create session.
1766 QuicDispatcherPeer::set_new_sessions_allowed_per_event_loop(dispatcher_.get(),
1767 kNumConnections);
1768 // Process CHLOs to create session for these connections.
1769 for (size_t i = 1; i <= kNumConnections; ++i) {
1770 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), i);
1771 QuicConnectionId conn_id = TestConnectionId(i);
1772 if (i == kNumConnections) {
1773 EXPECT_CALL(*dispatcher_,
fayang1ed1f762019-06-24 11:40:04 -07001774 ShouldCreateOrBufferPacketForConnection(
1775 ReceivedPacketInfoConnectionIdEquals(conn_id)));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001776 }
1777 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001778 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08001779 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001780 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1781 &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08001782 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001783 // First |kNumConnections| - 1 connections should have buffered
1784 // a packet in store. The rest should have been dropped.
1785 size_t num_packet_to_process = i <= kMaxConnectionsWithoutCHLO ? 2u : 1u;
1786 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1787 ProcessUdpPacket(_, client_address, _))
1788 .Times(num_packet_to_process)
1789 .WillRepeatedly(WithArg<2>(
1790 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1791 ValidatePacket(conn_id, packet);
1792 })));
1793
1794 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1795 }
1796}
1797
1798// Tests that store delivers empty packet list if CHLO arrives firstly.
wub0a4b9c52019-05-28 13:18:58 -07001799TEST_F(BufferedPacketStoreTest, DeliverEmptyPackets) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001800 QuicConnectionId conn_id = TestConnectionId(1);
1801 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
fayang1ed1f762019-06-24 11:40:04 -07001802 EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(
1803 ReceivedPacketInfoConnectionIdEquals(conn_id)));
dmcardlecf0bfcf2019-12-13 08:08:21 -08001804 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address,
1805 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08001806 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001807 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1808 &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08001809 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001810 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1811 ProcessUdpPacket(_, client_address, _));
1812 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1813}
1814
1815// Tests that a retransmitted CHLO arrives after a connection for the
1816// CHLO has been created.
wub0a4b9c52019-05-28 13:18:58 -07001817TEST_F(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001818 InSequence s;
1819 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1820 QuicConnectionId conn_id = TestConnectionId(1);
dmcardlecf0bfcf2019-12-13 08:08:21 -08001821 ProcessPacket(client_address, conn_id, true,
1822 quiche::QuicheStrCat("data packet ", 2), CONNECTION_ID_PRESENT,
1823 PACKET_4BYTE_PACKET_NUMBER,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001824 /*packet_number=*/2);
1825
1826 // When CHLO arrives, a new session should be created, and all packets
1827 // buffered should be delivered to the session.
dmcardlecf0bfcf2019-12-13 08:08:21 -08001828 EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address,
1829 quiche::QuicheStringPiece(), _))
QUICHE teama6ef0a62019-03-07 20:34:33 -05001830 .Times(1) // Only triggered by 1st CHLO.
wub89490e02019-12-12 12:45:58 -08001831 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001832 dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
1833 &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08001834 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001835 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1836 ProcessUdpPacket(_, _, _))
1837 .Times(3) // Triggered by 1 data packet and 2 CHLOs.
1838 .WillRepeatedly(
1839 WithArg<2>(Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1840 ValidatePacket(conn_id, packet);
1841 })));
1842 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1843
1844 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1845}
1846
1847// Tests that expiration of a connection add connection id to time wait list.
wub0a4b9c52019-05-28 13:18:58 -07001848TEST_F(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001849 InSequence s;
1850 CreateTimeWaitListManager();
1851 QuicBufferedPacketStore* store =
1852 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
1853 QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock());
1854
1855 QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
1856 QuicConnectionId conn_id = TestConnectionId(1);
dmcardlecf0bfcf2019-12-13 08:08:21 -08001857 ProcessPacket(client_address, conn_id, true,
1858 quiche::QuicheStrCat("data packet ", 2), CONNECTION_ID_PRESENT,
1859 PACKET_4BYTE_PACKET_NUMBER,
QUICHE teama6ef0a62019-03-07 20:34:33 -05001860 /*packet_number=*/2);
1861
1862 mock_helper_.AdvanceTime(
1863 QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs));
1864 QuicAlarm* alarm = QuicBufferedPacketStorePeer::expiration_alarm(store);
1865 // Cancel alarm as if it had been fired.
1866 alarm->Cancel();
1867 store->OnExpirationTimeout();
1868 // New arrived CHLO will be dropped because this connection is in time wait
1869 // list.
1870 ASSERT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
1871 EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, conn_id, _, _));
1872 ProcessPacket(client_address, conn_id, true, SerializeFullCHLO());
1873}
1874
wub0a4b9c52019-05-28 13:18:58 -07001875TEST_F(BufferedPacketStoreTest, ProcessCHLOsUptoLimitAndBufferTheRest) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001876 // Process more than (|kMaxNumSessionsToCreate| +
1877 // |kDefaultMaxConnectionsInStore|) CHLOs,
1878 // the first |kMaxNumSessionsToCreate| should create connections immediately,
1879 // the next |kDefaultMaxConnectionsInStore| should be buffered,
1880 // the rest should be dropped.
1881 QuicBufferedPacketStore* store =
1882 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
1883 const size_t kNumCHLOs =
1884 kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore + 1;
1885 for (uint64_t conn_id = 1; conn_id <= kNumCHLOs; ++conn_id) {
fayang1ed1f762019-06-24 11:40:04 -07001886 EXPECT_CALL(
1887 *dispatcher_,
1888 ShouldCreateOrBufferPacketForConnection(
1889 ReceivedPacketInfoConnectionIdEquals(TestConnectionId(conn_id))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001890 if (conn_id <= kMaxNumSessionsToCreate) {
1891 EXPECT_CALL(*dispatcher_,
1892 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001893 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08001894 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001895 dispatcher_.get(), config_, TestConnectionId(conn_id),
1896 client_addr_, &mock_helper_, &mock_alarm_factory_,
1897 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
wub89490e02019-12-12 12:45:58 -08001898 &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001899 EXPECT_CALL(
1900 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1901 ProcessUdpPacket(_, _, _))
1902 .WillOnce(WithArg<2>(
1903 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1904 ValidatePacket(TestConnectionId(conn_id), packet);
1905 })));
1906 }
1907 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
1908 SerializeFullCHLO());
1909 if (conn_id <= kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore &&
1910 conn_id > kMaxNumSessionsToCreate) {
1911 EXPECT_TRUE(store->HasChloForConnection(TestConnectionId(conn_id)));
1912 } else {
1913 // First |kMaxNumSessionsToCreate| CHLOs should be passed to new
1914 // connections immediately, and the last CHLO should be dropped as the
1915 // store is full.
1916 EXPECT_FALSE(store->HasChloForConnection(TestConnectionId(conn_id)));
1917 }
1918 }
1919
1920 // Graduately consume buffered CHLOs. The buffered connections should be
1921 // created but the dropped one shouldn't.
1922 for (uint64_t conn_id = kMaxNumSessionsToCreate + 1;
1923 conn_id <= kMaxNumSessionsToCreate + kDefaultMaxConnectionsInStore;
1924 ++conn_id) {
1925 EXPECT_CALL(*dispatcher_,
1926 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001927 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08001928 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001929 dispatcher_.get(), config_, TestConnectionId(conn_id), client_addr_,
1930 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08001931 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001932 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1933 ProcessUdpPacket(_, _, _))
1934 .WillOnce(WithArg<2>(
1935 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1936 ValidatePacket(TestConnectionId(conn_id), packet);
1937 })));
1938 }
1939 EXPECT_CALL(*dispatcher_,
1940 CreateQuicSession(TestConnectionId(kNumCHLOs), client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001941 quiche::QuicheStringPiece(), _))
QUICHE teama6ef0a62019-03-07 20:34:33 -05001942 .Times(0);
1943
1944 while (store->HasChlosBuffered()) {
1945 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
1946 }
1947
1948 EXPECT_EQ(TestConnectionId(static_cast<size_t>(kMaxNumSessionsToCreate) +
1949 kDefaultMaxConnectionsInStore),
1950 session1_->connection_id());
1951}
1952
1953// Duplicated CHLO shouldn't be buffered.
wub0a4b9c52019-05-28 13:18:58 -07001954TEST_F(BufferedPacketStoreTest, BufferDuplicatedCHLO) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05001955 for (uint64_t conn_id = 1; conn_id <= kMaxNumSessionsToCreate + 1;
1956 ++conn_id) {
1957 // Last CHLO will be buffered. Others will create connection right away.
1958 if (conn_id <= kMaxNumSessionsToCreate) {
1959 EXPECT_CALL(*dispatcher_,
1960 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001961 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08001962 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001963 dispatcher_.get(), config_, TestConnectionId(conn_id),
1964 client_addr_, &mock_helper_, &mock_alarm_factory_,
1965 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
wub89490e02019-12-12 12:45:58 -08001966 &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001967 EXPECT_CALL(
1968 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1969 ProcessUdpPacket(_, _, _))
1970 .WillOnce(WithArg<2>(
1971 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
1972 ValidatePacket(TestConnectionId(conn_id), packet);
1973 })));
1974 }
1975 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
1976 SerializeFullCHLO());
1977 }
1978 // Retransmit CHLO on last connection should be dropped.
1979 QuicConnectionId last_connection =
1980 TestConnectionId(kMaxNumSessionsToCreate + 1);
1981 ProcessPacket(client_addr_, last_connection, true, SerializeFullCHLO());
1982
1983 size_t packets_buffered = 2;
1984
1985 // Reset counter and process buffered CHLO.
1986 EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection, client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08001987 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08001988 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05001989 dispatcher_.get(), config_, last_connection, client_addr_,
1990 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08001991 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05001992 // Only one packet(CHLO) should be process.
1993 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
1994 ProcessUdpPacket(_, _, _))
1995 .Times(packets_buffered)
1996 .WillRepeatedly(WithArg<2>(
1997 Invoke([this, last_connection](const QuicEncryptedPacket& packet) {
1998 ValidatePacket(last_connection, packet);
1999 })));
2000 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
2001}
2002
wub0a4b9c52019-05-28 13:18:58 -07002003TEST_F(BufferedPacketStoreTest, BufferNonChloPacketsUptoLimitWithChloBuffered) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002004 uint64_t last_conn_id = kMaxNumSessionsToCreate + 1;
2005 QuicConnectionId last_connection_id = TestConnectionId(last_conn_id);
2006 for (uint64_t conn_id = 1; conn_id <= last_conn_id; ++conn_id) {
2007 // Last CHLO will be buffered. Others will create connection right away.
2008 if (conn_id <= kMaxNumSessionsToCreate) {
2009 EXPECT_CALL(*dispatcher_,
2010 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08002011 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08002012 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002013 dispatcher_.get(), config_, TestConnectionId(conn_id),
2014 client_addr_, &mock_helper_, &mock_alarm_factory_,
2015 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
wub89490e02019-12-12 12:45:58 -08002016 &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002017 EXPECT_CALL(
2018 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2019 ProcessUdpPacket(_, _, _))
2020 .WillRepeatedly(WithArg<2>(
2021 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2022 ValidatePacket(TestConnectionId(conn_id), packet);
2023 })));
2024 }
2025 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
2026 SerializeFullCHLO());
2027 }
2028
2029 // Process another |kDefaultMaxUndecryptablePackets| + 1 data packets. The
2030 // last one should be dropped.
2031 for (uint64_t packet_number = 2;
2032 packet_number <= kDefaultMaxUndecryptablePackets + 2; ++packet_number) {
2033 ProcessPacket(client_addr_, last_connection_id, true, "data packet");
2034 }
2035
2036 // Reset counter and process buffered CHLO.
2037 EXPECT_CALL(*dispatcher_, CreateQuicSession(last_connection_id, client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08002038 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08002039 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002040 dispatcher_.get(), config_, last_connection_id, client_addr_,
2041 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08002042 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002043 // Only CHLO and following |kDefaultMaxUndecryptablePackets| data packets
2044 // should be process.
2045 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2046 ProcessUdpPacket(_, _, _))
2047 .Times(kDefaultMaxUndecryptablePackets + 1)
2048 .WillRepeatedly(WithArg<2>(
2049 Invoke([this, last_connection_id](const QuicEncryptedPacket& packet) {
2050 ValidatePacket(last_connection_id, packet);
2051 })));
2052 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
2053}
2054
2055// Tests that when dispatcher's packet buffer is full, a CHLO on connection
2056// which doesn't have buffered CHLO should be buffered.
wub0a4b9c52019-05-28 13:18:58 -07002057TEST_F(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) {
QUICHE teama6ef0a62019-03-07 20:34:33 -05002058 QuicBufferedPacketStore* store =
2059 QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
2060
2061 uint64_t conn_id = 1;
2062 ProcessPacket(client_addr_, TestConnectionId(conn_id), true, "data packet",
2063 CONNECTION_ID_PRESENT, PACKET_4BYTE_PACKET_NUMBER,
2064 /*packet_number=*/1);
2065 // Fill packet buffer to full with CHLOs on other connections. Need to feed
2066 // extra CHLOs because the first |kMaxNumSessionsToCreate| are going to create
2067 // session directly.
2068 for (conn_id = 2;
2069 conn_id <= kDefaultMaxConnectionsInStore + kMaxNumSessionsToCreate;
2070 ++conn_id) {
2071 if (conn_id <= kMaxNumSessionsToCreate + 1) {
2072 EXPECT_CALL(*dispatcher_,
2073 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08002074 quiche::QuicheStringPiece(), _))
wub89490e02019-12-12 12:45:58 -08002075 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002076 dispatcher_.get(), config_, TestConnectionId(conn_id),
2077 client_addr_, &mock_helper_, &mock_alarm_factory_,
2078 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
wub89490e02019-12-12 12:45:58 -08002079 &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002080 EXPECT_CALL(
2081 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2082 ProcessUdpPacket(_, _, _))
2083 .WillOnce(WithArg<2>(
2084 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2085 ValidatePacket(TestConnectionId(conn_id), packet);
2086 })));
2087 }
2088 ProcessPacket(client_addr_, TestConnectionId(conn_id), true,
2089 SerializeFullCHLO());
2090 }
2091 EXPECT_FALSE(store->HasChloForConnection(
2092 /*connection_id=*/TestConnectionId(1)));
2093
2094 // CHLO on connection 1 should still be buffered.
wub0b2ae542019-10-24 08:32:06 -07002095 ProcessPacket(client_addr_, /*server_connection_id=*/TestConnectionId(1),
2096 true, SerializeFullCHLO());
QUICHE teama6ef0a62019-03-07 20:34:33 -05002097 EXPECT_TRUE(store->HasChloForConnection(
2098 /*connection_id=*/TestConnectionId(1)));
2099}
2100
2101// Regression test for b/117874922.
wub0a4b9c52019-05-28 13:18:58 -07002102TEST_F(BufferedPacketStoreTest, ProcessBufferedChloWithDifferentVersion) {
dschinazi76881f02019-12-09 14:56:14 -08002103 // Turn off versions Q099 and T099, such that the preferred version is not
2104 // supported by the server.
2105 SetQuicReloadableFlag(quic_enable_version_q099, false);
2106 SetQuicReloadableFlag(quic_enable_version_t099, false);
QUICHE teama6ef0a62019-03-07 20:34:33 -05002107 uint64_t last_connection_id = kMaxNumSessionsToCreate + 5;
2108 ParsedQuicVersionVector supported_versions = CurrentSupportedVersions();
2109 for (uint64_t conn_id = 1; conn_id <= last_connection_id; ++conn_id) {
2110 // Last 5 CHLOs will be buffered. Others will create connection right away.
2111 ParsedQuicVersion version =
2112 supported_versions[(conn_id - 1) % supported_versions.size()];
2113 if (conn_id <= kMaxNumSessionsToCreate) {
2114 EXPECT_CALL(*dispatcher_,
2115 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08002116 quiche::QuicheStringPiece(), version))
wub89490e02019-12-12 12:45:58 -08002117 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002118 dispatcher_.get(), config_, TestConnectionId(conn_id),
2119 client_addr_, &mock_helper_, &mock_alarm_factory_,
2120 &crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
wub89490e02019-12-12 12:45:58 -08002121 &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002122 EXPECT_CALL(
2123 *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2124 ProcessUdpPacket(_, _, _))
2125 .WillRepeatedly(WithArg<2>(
2126 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2127 ValidatePacket(TestConnectionId(conn_id), packet);
2128 })));
2129 }
2130 ProcessPacket(client_addr_, TestConnectionId(conn_id), true, version,
fayange3f2f7b2019-09-19 17:01:57 -07002131 SerializeFullCHLO(), true, CONNECTION_ID_PRESENT,
QUICHE teama6ef0a62019-03-07 20:34:33 -05002132 PACKET_4BYTE_PACKET_NUMBER, 1);
2133 }
2134
2135 // Process buffered CHLOs. Verify the version is correct.
2136 for (uint64_t conn_id = kMaxNumSessionsToCreate + 1;
2137 conn_id <= last_connection_id; ++conn_id) {
2138 ParsedQuicVersion version =
2139 supported_versions[(conn_id - 1) % supported_versions.size()];
2140 EXPECT_CALL(*dispatcher_,
2141 CreateQuicSession(TestConnectionId(conn_id), client_addr_,
dmcardlecf0bfcf2019-12-13 08:08:21 -08002142 quiche::QuicheStringPiece(), version))
wub89490e02019-12-12 12:45:58 -08002143 .WillOnce(Return(ByMove(CreateSession(
QUICHE teama6ef0a62019-03-07 20:34:33 -05002144 dispatcher_.get(), config_, TestConnectionId(conn_id), client_addr_,
2145 &mock_helper_, &mock_alarm_factory_, &crypto_config_,
wub89490e02019-12-12 12:45:58 -08002146 QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_))));
QUICHE teama6ef0a62019-03-07 20:34:33 -05002147 EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
2148 ProcessUdpPacket(_, _, _))
2149 .WillRepeatedly(WithArg<2>(
2150 Invoke([this, conn_id](const QuicEncryptedPacket& packet) {
2151 ValidatePacket(TestConnectionId(conn_id), packet);
2152 })));
2153 }
2154 dispatcher_->ProcessBufferedChlos(kMaxNumSessionsToCreate);
2155}
2156
QUICHE teama6ef0a62019-03-07 20:34:33 -05002157} // namespace
2158} // namespace test
2159} // namespace quic