1 /*
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 */
8 #include <quic/api/test/Mocks.h>
9 #include <quic/client/QuicClientTransport.h>
10 #include <quic/server/QuicServer.h>
11
12 #include <folly/portability/GMock.h>
13 #include <folly/portability/GTest.h>
14
15 #include <fizz/crypto/aead/test/Mocks.h>
16 #include <fizz/protocol/clock/test/Mocks.h>
17 #include <folly/futures/Future.h>
18 #include <folly/io/Cursor.h>
19 #include <folly/io/SocketOptionMap.h>
20 #include <folly/io/async/ScopedEventBaseThread.h>
21 #include <folly/io/async/test/MockAsyncUDPSocket.h>
22 #include <quic/QuicConstants.h>
23 #include <quic/codec/DefaultConnectionIdAlgo.h>
24 #include <quic/common/test/TestClientUtils.h>
25 #include <quic/common/test/TestUtils.h>
26 #include <quic/congestion_control/CongestionControllerFactory.h>
27 #include <quic/fizz/client/handshake/FizzClientHandshake.h>
28 #include <quic/fizz/client/handshake/FizzClientQuicHandshakeContext.h>
29 #include <quic/fizz/client/handshake/test/MockQuicPskCache.h>
30 #include <quic/fizz/handshake/FizzCryptoFactory.h>
31 #include <quic/handshake/TransportParameters.h>
32 #include <quic/handshake/test/Mocks.h>
33 #include <quic/happyeyeballs/QuicHappyEyeballsFunctions.h>
34 #include <quic/logging/FileQLogger.h>
35 #include <quic/logging/test/Mocks.h>
36 #include <quic/samples/echo/EchoHandler.h>
37 #include <quic/samples/echo/EchoServer.h>
38 #include <quic/state/test/MockQuicStats.h>
39
40 using namespace testing;
41 using namespace folly;
42 using namespace quic::samples;
43
44 namespace quic {
45 namespace test {
46
47 namespace {
48 std::vector<uint8_t> kInitialDstConnIdVecForRetryTest =
49 {0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08};
50 using PacketDropReason = QuicTransportStatsCallback::PacketDropReason;
51 } // namespace
52
53 MATCHER_P(BufMatches, buf, "") {
54 folly::IOBufEqualTo eq;
55 return eq(*arg, buf);
56 }
57
58 class DestructionCallback
59 : public std::enable_shared_from_this<DestructionCallback> {
60 public:
markDestroyed()61 void markDestroyed() {
62 destroyed_ = true;
63 }
64
isDestroyed()65 bool isDestroyed() {
66 return destroyed_;
67 }
68
69 private:
70 bool destroyed_{false};
71 };
72
73 struct TestingParams {
74 QuicVersion version;
75 uint8_t dstConnIdSize;
76
TestingParamsquic::test::TestingParams77 explicit TestingParams(QuicVersion versionIn, uint8_t dstConnIdSizeIn = 8)
78 : version(versionIn), dstConnIdSize(dstConnIdSizeIn) {}
79 };
80
81 class TestingQuicClientTransport : public QuicClientTransport {
82 public:
TestingQuicClientTransport(folly::EventBase * evb,std::unique_ptr<folly::AsyncUDPSocket> socket,std::shared_ptr<ClientHandshakeFactory> handshakeFactory,size_t connIdSize=kDefaultConnectionIdSize,bool useSplitConnectionCallbacks=false)83 TestingQuicClientTransport(
84 folly::EventBase* evb,
85 std::unique_ptr<folly::AsyncUDPSocket> socket,
86 std::shared_ptr<ClientHandshakeFactory> handshakeFactory,
87 size_t connIdSize = kDefaultConnectionIdSize,
88 bool useSplitConnectionCallbacks = false)
89 : QuicClientTransport(
90 evb,
91 std::move(socket),
92 std::move(handshakeFactory),
93 connIdSize,
94 useSplitConnectionCallbacks) {}
95
~TestingQuicClientTransport()96 ~TestingQuicClientTransport() override {
97 if (destructionCallback_) {
98 destructionCallback_->markDestroyed();
99 }
100 }
101
getConn() const102 const QuicClientConnectionState& getConn() const {
103 return *dynamic_cast<QuicClientConnectionState*>(conn_.get());
104 }
105
getNonConstConn()106 QuicClientConnectionState& getNonConstConn() {
107 return *dynamic_cast<QuicClientConnectionState*>(conn_.get());
108 }
109
getReadCallbacks() const110 const auto& getReadCallbacks() const {
111 return readCallbacks_;
112 }
113
getDeliveryCallbacks() const114 const auto& getDeliveryCallbacks() const {
115 return deliveryCallbacks_;
116 }
117
getConnPendingWriteCallback() const118 auto getConnPendingWriteCallback() const {
119 return connWriteCallback_;
120 }
121
getStreamPendingWriteCallbacks() const122 auto getStreamPendingWriteCallbacks() const {
123 return pendingWriteCallbacks_;
124 }
125
idleTimeout()126 auto& idleTimeout() {
127 return idleTimeout_;
128 }
129
lossTimeout()130 auto& lossTimeout() {
131 return lossTimeout_;
132 }
133
ackTimeout()134 auto& ackTimeout() {
135 return ackTimeout_;
136 }
137
happyEyeballsConnAttemptDelayTimeout()138 auto& happyEyeballsConnAttemptDelayTimeout() {
139 return happyEyeballsConnAttemptDelayTimeout_;
140 }
141
drainTimeout()142 auto& drainTimeout() {
143 return drainTimeout_;
144 }
145
isClosed() const146 bool isClosed() const {
147 return closeState_ == CloseState::CLOSED;
148 }
149
isDraining() const150 bool isDraining() const {
151 return drainTimeout_.isScheduled();
152 }
153
serverInitialParamsSet()154 auto& serverInitialParamsSet() {
155 return getNonConstConn().serverInitialParamsSet_;
156 }
157
peerAdvertisedInitialMaxData()158 auto& peerAdvertisedInitialMaxData() {
159 return getConn().peerAdvertisedInitialMaxData;
160 }
161
peerAdvertisedInitialMaxStreamDataBidiLocal() const162 auto& peerAdvertisedInitialMaxStreamDataBidiLocal() const {
163 return getConn().peerAdvertisedInitialMaxStreamDataBidiLocal;
164 }
165
peerAdvertisedInitialMaxStreamDataBidiRemote() const166 auto& peerAdvertisedInitialMaxStreamDataBidiRemote() const {
167 return getConn().peerAdvertisedInitialMaxStreamDataBidiRemote;
168 }
169
peerAdvertisedInitialMaxStreamDataUni() const170 auto& peerAdvertisedInitialMaxStreamDataUni() const {
171 return getConn().peerAdvertisedInitialMaxStreamDataUni;
172 }
173
setDestructionCallback(std::shared_ptr<DestructionCallback> destructionCallback)174 void setDestructionCallback(
175 std::shared_ptr<DestructionCallback> destructionCallback) {
176 destructionCallback_ = destructionCallback;
177 }
178
invokeOnDataAvailable(const folly::SocketAddress & addr,size_t len,bool truncated)179 void invokeOnDataAvailable(
180 const folly::SocketAddress& addr,
181 size_t len,
182 bool truncated) {
183 onDataAvailable(addr, len, truncated, OnDataAvailableParams());
184 }
185
invokeOnNotifyDataAvailable(folly::AsyncUDPSocket & sock)186 void invokeOnNotifyDataAvailable(folly::AsyncUDPSocket& sock) {
187 onNotifyDataAvailable(sock);
188 }
189
190 private:
191 std::shared_ptr<DestructionCallback> destructionCallback_;
192 };
193
194 using StreamPair = std::pair<std::unique_ptr<folly::IOBuf>, StreamId>;
195
196 class QuicClientTransportIntegrationTest : public TestWithParam<TestingParams> {
197 public:
SetUp()198 void SetUp() override {
199 folly::ssl::init();
200
201 // Fizz is the hostname for the server cert.
202 hostname = "Fizz";
203 serverCtx = test::createServerCtx();
204 serverCtx->setSupportedAlpns({"h1q-fb", "hq"});
205 server_ = createServer(ProcessId::ZERO);
206 serverAddr = server_->getAddress();
207 ON_CALL(clientConnCallback, onTransportReady()).WillByDefault(Invoke([&] {
208 connected_ = true;
209 }));
210
211 clientCtx = createClientContext();
212 verifier = createTestCertificateVerifier();
213 client = createClient();
214 }
215
getVersion()216 QuicVersion getVersion() {
217 return GetParam().version;
218 }
219
createClientContext()220 std::shared_ptr<fizz::client::FizzClientContext> createClientContext() {
221 clientCtx = std::make_shared<fizz::client::FizzClientContext>();
222 clientCtx->setSupportedAlpns({"h1q-fb"});
223 clientCtx->setClock(std::make_shared<NiceMock<fizz::test::MockClock>>());
224 return clientCtx;
225 }
226
createClient()227 std::shared_ptr<TestingQuicClientTransport> createClient() {
228 pskCache_ = std::make_shared<BasicQuicPskCache>();
229
230 auto sock = std::make_unique<folly::AsyncUDPSocket>(&eventbase_);
231 auto fizzClientContext = FizzClientQuicHandshakeContext::Builder()
232 .setFizzClientContext(clientCtx)
233 .setCertificateVerifier(verifier)
234 .setPskCache(pskCache_)
235 .build();
236 client = std::make_shared<TestingQuicClientTransport>(
237 &eventbase_,
238 std::move(sock),
239 std::move(fizzClientContext),
240 GetParam().dstConnIdSize);
241 client->setSupportedVersions({getVersion()});
242 client->setCongestionControllerFactory(
243 std::make_shared<DefaultCongestionControllerFactory>());
244 client->setHostname(hostname);
245 client->addNewPeerAddress(serverAddr);
246 auto transportSettings = client->getTransportSettings();
247 transportSettings.attemptEarlyData = true;
248 client->setTransportSettings(transportSettings);
249 return client;
250 }
251
createServer(ProcessId processId,bool withRetryPacket=false)252 std::shared_ptr<QuicServer> createServer(
253 ProcessId processId,
254 bool withRetryPacket = false) {
255 auto server = QuicServer::createQuicServer();
256 auto transportSettings = server->getTransportSettings();
257 auto statsFactory = std::make_unique<NiceMock<MockQuicStatsFactory>>();
258 ON_CALL(*statsFactory, make()).WillByDefault(Invoke([&]() {
259 auto newStatsCallback = std::make_unique<NiceMock<MockQuicStats>>();
260 statsCallbacks_.push_back(newStatsCallback.get());
261 return newStatsCallback;
262 }));
263 transportSettings.zeroRttSourceTokenMatchingPolicy =
264 ZeroRttSourceTokenMatchingPolicy::LIMIT_IF_NO_EXACT_MATCH;
265 if (withRetryPacket) {
266 std::array<uint8_t, kRetryTokenSecretLength> secret;
267 folly::Random::secureRandom(secret.data(), secret.size());
268 transportSettings.retryTokenSecret = secret;
269 server->setRateLimit([]() { return 0u; }, 1s);
270 }
271 server->setTransportStatsCallbackFactory(std::move(statsFactory));
272 server->setTransportSettings(transportSettings);
273 server->setQuicServerTransportFactory(
274 std::make_unique<EchoServerTransportFactory>());
275 server->setQuicUDPSocketFactory(
276 std::make_unique<QuicSharedUDPSocketFactory>());
277 server->setFizzContext(serverCtx);
278 server->setSupportedVersion({getVersion(), MVFST1});
279 folly::SocketAddress addr("::1", 0);
280 server->setProcessId(processId);
281 server->start(addr, 1);
282 server->waitUntilInitialized();
283 return server;
284 }
285
TearDown()286 void TearDown() override {
287 std::thread t([&] { eventbase_.loopForever(); });
288 SCOPE_EXIT {
289 t.join();
290 };
291 if (connected_) {
292 verifyTransportParameters();
293 }
294 server_->shutdown();
295 server_ = nullptr;
296 eventbase_.runInEventBaseThreadAndWait([&] { client = nullptr; });
297 eventbase_.terminateLoopSoon();
298 }
299
verifyTransportParameters()300 void verifyTransportParameters() {
301 EXPECT_EQ(client->getConn().peerIdleTimeout, kDefaultIdleTimeout);
302 }
303
expectTransportCallbacks()304 void expectTransportCallbacks() {
305 EXPECT_CALL(clientConnCallback, onReplaySafe());
306 }
307
expectStatsCallbacks()308 void expectStatsCallbacks() {
309 quicStats_ = std::make_shared<MockQuicStats>();
310 EXPECT_CALL(*quicStats_, onPacketReceived()).Times(AtLeast(1));
311 EXPECT_CALL(*quicStats_, onPacketSent()).Times(AtLeast(1));
312 EXPECT_CALL(*quicStats_, onNewQuicStream()).Times(1);
313 EXPECT_CALL(*quicStats_, onQuicStreamClosed()).Times(1);
314 EXPECT_CALL(*quicStats_, onRead(_)).Times(AtLeast(1));
315 EXPECT_CALL(*quicStats_, onWrite(_)).Times(AtLeast(1));
316 client->setTransportStatsCallback(quicStats_);
317 }
318
319 folly::Future<StreamPair> sendRequestAndResponse(
320 std::unique_ptr<folly::IOBuf> data,
321 StreamId streamid,
322 MockReadCallback* readCb);
323
324 void sendRequestAndResponseAndWait(
325 folly::IOBuf& expectedData,
326 std::unique_ptr<folly::IOBuf> sendData,
327 StreamId streamid,
328 MockReadCallback* readCb);
329
checkTransportSummaryEvent(const std::shared_ptr<FileQLogger> & qLogger)330 void checkTransportSummaryEvent(const std::shared_ptr<FileQLogger>& qLogger) {
331 std::vector<int> indices =
332 getQLogEventIndices(QLogEventType::TransportSummary, qLogger);
333 EXPECT_EQ(indices.size(), 1);
334 auto tmp = std::move(qLogger->logs[indices[0]]);
335 auto event = dynamic_cast<QLogTransportSummaryEvent*>(tmp.get());
336
337 uint64_t totalCryptoDataWritten = 0;
338 uint64_t totalCryptoDataRecvd = 0;
339
340 if (client->getConn().cryptoState) {
341 totalCryptoDataWritten +=
342 client->getConn().cryptoState->initialStream.currentWriteOffset;
343 totalCryptoDataWritten +=
344 client->getConn().cryptoState->handshakeStream.currentWriteOffset;
345 totalCryptoDataWritten +=
346 client->getConn().cryptoState->oneRttStream.currentWriteOffset;
347 totalCryptoDataRecvd +=
348 client->getConn().cryptoState->initialStream.maxOffsetObserved;
349 totalCryptoDataRecvd +=
350 client->getConn().cryptoState->handshakeStream.maxOffsetObserved;
351 totalCryptoDataRecvd +=
352 client->getConn().cryptoState->oneRttStream.maxOffsetObserved;
353 }
354
355 EXPECT_EQ(
356 event->totalBytesSent, client->getConn().lossState.totalBytesSent);
357 EXPECT_EQ(
358 event->totalBytesRecvd, client->getConn().lossState.totalBytesRecvd);
359 EXPECT_EQ(
360 event->sumCurWriteOffset,
361 client->getConn().flowControlState.sumCurWriteOffset);
362 EXPECT_EQ(
363 event->sumMaxObservedOffset,
364 client->getConn().flowControlState.sumMaxObservedOffset);
365 EXPECT_EQ(
366 event->sumCurStreamBufferLen,
367 client->getConn().flowControlState.sumCurStreamBufferLen);
368 EXPECT_EQ(
369 event->totalBytesRetransmitted,
370 client->getConn().lossState.totalBytesRetransmitted);
371 EXPECT_EQ(
372 event->totalStreamBytesCloned,
373 client->getConn().lossState.totalStreamBytesCloned);
374 EXPECT_EQ(
375 event->totalBytesCloned, client->getConn().lossState.totalBytesCloned);
376 EXPECT_EQ(event->totalCryptoDataWritten, totalCryptoDataWritten);
377 EXPECT_EQ(event->totalCryptoDataRecvd, totalCryptoDataRecvd);
378 }
379
380 protected:
381 std::string hostname;
382 folly::EventBase eventbase_;
383 folly::SocketAddress serverAddr;
384 NiceMock<MockConnectionCallback> clientConnCallback;
385 NiceMock<MockReadCallback> readCb;
386 std::shared_ptr<TestingQuicClientTransport> client;
387 std::shared_ptr<fizz::server::FizzServerContext> serverCtx;
388 std::shared_ptr<fizz::client::FizzClientContext> clientCtx;
389 std::shared_ptr<fizz::CertificateVerifier> verifier;
390 std::shared_ptr<QuicPskCache> pskCache_;
391 std::shared_ptr<QuicServer> server_;
392 bool connected_{false};
393 std::shared_ptr<MockQuicStats> quicStats_;
394 std::vector<MockQuicStats*> statsCallbacks_;
395 };
396
397 class StreamData {
398 public:
399 BufQueue data;
400
401 folly::Promise<StreamPair> promise;
402 StreamId id;
403
StreamData(StreamId id)404 explicit StreamData(StreamId id) : id(id) {}
405
setException(const std::pair<QuicErrorCode,folly::Optional<folly::StringPiece>> & err)406 void setException(
407 const std::pair<QuicErrorCode, folly::Optional<folly::StringPiece>>&
408 err) {
409 promise.setException(std::runtime_error(toString(err)));
410 delete this;
411 }
412
append(std::unique_ptr<folly::IOBuf> buf,bool eof)413 void append(std::unique_ptr<folly::IOBuf> buf, bool eof) {
414 data.append(std::move(buf));
415 if (eof) {
416 promise.setValue(std::make_pair(data.move(), id));
417 delete this;
418 }
419 }
420 };
421
422 folly::Future<StreamPair>
sendRequestAndResponse(std::unique_ptr<folly::IOBuf> data,StreamId streamId,MockReadCallback * readCallback)423 QuicClientTransportIntegrationTest::sendRequestAndResponse(
424 std::unique_ptr<folly::IOBuf> data,
425 StreamId streamId,
426 MockReadCallback* readCallback) {
427 client->setReadCallback(streamId, readCallback);
428 client->writeChain(streamId, data->clone(), true);
429 auto streamData = new StreamData(streamId);
430 auto dataCopy = std::shared_ptr<folly::IOBuf>(std::move(data));
431 EXPECT_CALL(*readCallback, readAvailable(streamId))
432 .WillRepeatedly(
433 Invoke([c = client.get(), id = streamId, streamData, dataCopy](
434 auto) mutable {
435 auto readData = c->read(id, 1000);
436 auto copy = readData->first->clone();
437 LOG(INFO) << "Client received data="
438 << copy->moveToFbString().toStdString()
439 << " on stream=" << id
440 << " read=" << readData->first->computeChainDataLength()
441 << " sent=" << dataCopy->computeChainDataLength();
442 streamData->append(std::move(readData->first), readData->second);
443 }));
444 ON_CALL(*readCallback, readError(streamId, _))
445 .WillByDefault(Invoke([streamData](auto, auto err) mutable {
446 streamData->setException(err);
447 }));
448 return streamData->promise.getFuture().within(30s);
449 }
450
sendRequestAndResponseAndWait(folly::IOBuf & expectedData,std::unique_ptr<folly::IOBuf> sendData,StreamId streamId,MockReadCallback * readCallback)451 void QuicClientTransportIntegrationTest::sendRequestAndResponseAndWait(
452 folly::IOBuf& expectedData,
453 std::unique_ptr<folly::IOBuf> sendData,
454 StreamId streamId,
455 MockReadCallback* readCallback) {
456 auto f = sendRequestAndResponse(sendData->clone(), streamId, readCallback)
457 .thenValue([&](StreamPair buf) {
458 EXPECT_TRUE(folly::IOBufEqualTo()(*buf.first, expectedData));
459 })
460 .ensure([&] { eventbase_.terminateLoopSoon(); });
461 eventbase_.loopForever();
462 std::move(f).get(1s);
463 }
464
TEST_P(QuicClientTransportIntegrationTest,NetworkTest)465 TEST_P(QuicClientTransportIntegrationTest, NetworkTest) {
466 expectTransportCallbacks();
467 expectStatsCallbacks();
468 client->start(&clientConnCallback);
469
470 EXPECT_CALL(clientConnCallback, onTransportReady()).WillOnce(Invoke([&] {
471 CHECK(client->getConn().oneRttWriteCipher);
472 EXPECT_EQ(client->getConn().peerConnectionIds.size(), 1);
473 EXPECT_EQ(
474 *client->getConn().serverConnectionId,
475 client->getConn().peerConnectionIds[0].connId);
476 eventbase_.terminateLoopSoon();
477 }));
478 eventbase_.loopForever();
479
480 auto streamId = client->createBidirectionalStream().value();
481 auto data = IOBuf::copyBuffer("hello");
482 auto expected = std::shared_ptr<IOBuf>(IOBuf::copyBuffer("echo "));
483 expected->prependChain(data->clone());
484 sendRequestAndResponseAndWait(*expected, data->clone(), streamId, &readCb);
485 }
486
TEST_P(QuicClientTransportIntegrationTest,FlowControlLimitedTest)487 TEST_P(QuicClientTransportIntegrationTest, FlowControlLimitedTest) {
488 expectTransportCallbacks();
489 client->start(&clientConnCallback);
490
491 EXPECT_CALL(clientConnCallback, onTransportReady()).WillOnce(Invoke([&] {
492 CHECK(client->getConn().oneRttWriteCipher);
493 eventbase_.terminateLoopSoon();
494 }));
495 eventbase_.loopForever();
496
497 auto streamId = client->createBidirectionalStream().value();
498 client->setStreamFlowControlWindow(streamId, 256);
499 auto data = IOBuf::create(4096);
500 data->append(4096);
501 memset(data->writableData(), 'a', data->length());
502
503 auto expected = std::shared_ptr<IOBuf>(IOBuf::copyBuffer("echo "));
504 expected->prependChain(data->clone());
505 sendRequestAndResponseAndWait(*expected, data->clone(), streamId, &readCb);
506 }
507
TEST_P(QuicClientTransportIntegrationTest,ALPNTest)508 TEST_P(QuicClientTransportIntegrationTest, ALPNTest) {
509 EXPECT_CALL(clientConnCallback, onTransportReady()).WillOnce(Invoke([&] {
510 ASSERT_EQ(client->getAppProtocol(), "h1q-fb");
511 client->close(folly::none);
512 eventbase_.terminateLoopSoon();
513 }));
514 ASSERT_EQ(client->getAppProtocol(), folly::none);
515 client->start(&clientConnCallback);
516 eventbase_.loopForever();
517 }
518
TEST_P(QuicClientTransportIntegrationTest,TLSAlert)519 TEST_P(QuicClientTransportIntegrationTest, TLSAlert) {
520 verifier = nullptr;
521 client = createClient();
522
523 auto qLogger = std::make_shared<FileQLogger>(VantagePoint::Client);
524 client->getNonConstConn().qLogger = qLogger;
525 EXPECT_CALL(clientConnCallback, onConnectionError(_))
526 .WillOnce(Invoke([&](const auto& errorCode) {
527 LOG(ERROR) << "error: " << errorCode.second;
528 const TransportErrorCode* transportError =
529 errorCode.first.asTransportErrorCode();
530 EXPECT_NE(transportError, nullptr);
531 client->close(folly::none);
532 this->checkTransportSummaryEvent(qLogger);
533
534 eventbase_.terminateLoopSoon();
535 }));
536
537 ASSERT_EQ(client->getAppProtocol(), folly::none);
538
539 client->start(&clientConnCallback);
540 eventbase_.loopForever();
541 }
542
TEST_P(QuicClientTransportIntegrationTest,BadServerTest)543 TEST_P(QuicClientTransportIntegrationTest, BadServerTest) {
544 auto qLogger = std::make_shared<FileQLogger>(VantagePoint::Client);
545 client->getNonConstConn().qLogger = qLogger;
546 // Point the client to a bad server.
547 client->addNewPeerAddress(SocketAddress("127.0.0.1", 14114));
548 auto tp = client->getTransportSettings();
549 tp.maxNumPTOs = 4;
550 client->setTransportSettings(tp);
551 EXPECT_CALL(clientConnCallback, onConnectionError(_))
552 .WillOnce(Invoke([&](const auto& errorCode) {
553 LOG(ERROR) << "error: " << errorCode.second;
554 const LocalErrorCode* localError = errorCode.first.asLocalErrorCode();
555 EXPECT_NE(localError, nullptr);
556 this->checkTransportSummaryEvent(qLogger);
557 }));
558 client->start(&clientConnCallback);
559 eventbase_.loop();
560 }
561
TEST_P(QuicClientTransportIntegrationTest,NetworkTestConnected)562 TEST_P(QuicClientTransportIntegrationTest, NetworkTestConnected) {
563 expectTransportCallbacks();
564 auto qLogger = std::make_shared<FileQLogger>(VantagePoint::Client);
565 client->getNonConstConn().qLogger = qLogger;
566 TransportSettings settings;
567 settings.connectUDP = true;
568 client->setTransportSettings(settings);
569 client->start(&clientConnCallback);
570
571 EXPECT_CALL(clientConnCallback, onTransportReady()).WillOnce(Invoke([&] {
572 CHECK(client->getConn().oneRttWriteCipher);
573 eventbase_.terminateLoopSoon();
574 }));
575 eventbase_.loopForever();
576
577 auto streamId = client->createBidirectionalStream().value();
578 auto data = IOBuf::copyBuffer("hello");
579 auto expected = std::shared_ptr<IOBuf>(IOBuf::copyBuffer("echo "));
580 expected->prependChain(data->clone());
581 sendRequestAndResponseAndWait(*expected, data->clone(), streamId, &readCb);
582 }
583
TEST_P(QuicClientTransportIntegrationTest,SetTransportSettingsAfterStart)584 TEST_P(QuicClientTransportIntegrationTest, SetTransportSettingsAfterStart) {
585 expectTransportCallbacks();
586 auto qLogger = std::make_shared<FileQLogger>(VantagePoint::Client);
587 client->getNonConstConn().qLogger = qLogger;
588 TransportSettings settings;
589 settings.connectUDP = true;
590 client->setTransportSettings(settings);
591 client->start(&clientConnCallback);
592
593 EXPECT_CALL(clientConnCallback, onTransportReady()).WillOnce(Invoke([&] {
594 CHECK(client->getConn().oneRttWriteCipher);
595 eventbase_.terminateLoopSoon();
596 }));
597 eventbase_.loopForever();
598
599 auto streamId = client->createBidirectionalStream().value();
600 auto data = IOBuf::copyBuffer("hello");
601 auto expected = std::shared_ptr<IOBuf>(IOBuf::copyBuffer("echo "));
602 expected->prependChain(data->clone());
603 sendRequestAndResponseAndWait(*expected, data->clone(), streamId, &readCb);
604 settings.connectUDP = false;
605 client->setTransportSettings(settings);
606 EXPECT_TRUE(client->getTransportSettings().connectUDP);
607 }
608
TEST_P(QuicClientTransportIntegrationTest,TestZeroRttSuccess)609 TEST_P(QuicClientTransportIntegrationTest, TestZeroRttSuccess) {
610 auto cachedPsk = setupZeroRttOnClientCtx(*clientCtx, hostname);
611 pskCache_->putPsk(hostname, cachedPsk);
612 setupZeroRttOnServerCtx(*serverCtx, cachedPsk);
613 // Change the ctx
614 server_->setFizzContext(serverCtx);
615 folly::Optional<std::string> alpn = std::string("h1q-fb");
616 bool performedValidation = false;
617 client->setEarlyDataAppParamsFunctions(
618 [&](const folly::Optional<std::string>& alpnToValidate, const Buf&) {
619 performedValidation = true;
620 EXPECT_EQ(alpnToValidate, alpn);
621 return true;
622 },
623 []() -> Buf { return nullptr; });
624 client->start(&clientConnCallback);
625 EXPECT_TRUE(performedValidation);
626 CHECK(client->getConn().zeroRttWriteCipher);
627 EXPECT_TRUE(client->serverInitialParamsSet());
628 EXPECT_EQ(
629 client->peerAdvertisedInitialMaxData(), kDefaultConnectionWindowSize);
630 EXPECT_EQ(
631 client->peerAdvertisedInitialMaxStreamDataBidiLocal(),
632 kDefaultStreamWindowSize);
633 EXPECT_EQ(
634 client->peerAdvertisedInitialMaxStreamDataBidiRemote(),
635 kDefaultStreamWindowSize);
636 EXPECT_EQ(
637 client->peerAdvertisedInitialMaxStreamDataUni(),
638 kDefaultStreamWindowSize);
639 EXPECT_CALL(clientConnCallback, onTransportReady()).WillOnce(Invoke([&] {
640 ASSERT_EQ(client->getAppProtocol(), "h1q-fb");
641 CHECK(client->getConn().zeroRttWriteCipher);
642 eventbase_.terminateLoopSoon();
643 }));
644 eventbase_.loopForever();
645
646 EXPECT_TRUE(client->getConn().zeroRttWriteCipher);
647 EXPECT_TRUE(client->good());
648 EXPECT_FALSE(client->replaySafe());
649
650 auto streamId = client->createBidirectionalStream().value();
651 auto data = IOBuf::copyBuffer("hello");
652 auto expected = std::shared_ptr<IOBuf>(IOBuf::copyBuffer("echo "));
653 expected->prependChain(data->clone());
654 EXPECT_CALL(clientConnCallback, onReplaySafe());
655 sendRequestAndResponseAndWait(*expected, data->clone(), streamId, &readCb);
656 EXPECT_FALSE(client->getConn().zeroRttWriteCipher);
657 EXPECT_TRUE(client->getConn().statelessResetToken.has_value());
658 }
659
TEST_P(QuicClientTransportIntegrationTest,ZeroRttRetryPacketTest)660 TEST_P(QuicClientTransportIntegrationTest, ZeroRttRetryPacketTest) {
661 /**
662 * logic extrapolated from TestZeroRttSuccess and RetryPacket tests
663 */
664 auto retryServer = createServer(ProcessId::ONE, true);
665 client->getNonConstConn().peerAddress = retryServer->getAddress();
666
667 SCOPE_EXIT {
668 retryServer->shutdown();
669 retryServer = nullptr;
670 };
671
672 auto cachedPsk = setupZeroRttOnClientCtx(*clientCtx, hostname);
673 pskCache_->putPsk(hostname, cachedPsk);
674 setupZeroRttOnServerCtx(*serverCtx, cachedPsk);
675 // Change the ctx
676 retryServer->setFizzContext(serverCtx);
677
678 std::vector<uint8_t> clientConnIdVec = {};
679 ConnectionId clientConnId(clientConnIdVec);
680
681 ConnectionId initialDstConnId(kInitialDstConnIdVecForRetryTest);
682
683 auto qLogger = std::make_shared<FileQLogger>(VantagePoint::Client);
684 client->getNonConstConn().qLogger = qLogger;
685 client->getNonConstConn().readCodec->setClientConnectionId(clientConnId);
686 client->getNonConstConn().initialDestinationConnectionId = initialDstConnId;
687 client->getNonConstConn().originalDestinationConnectionId = initialDstConnId;
688 client->setCongestionControllerFactory(
689 std::make_shared<DefaultCongestionControllerFactory>());
690 client->setCongestionControl(CongestionControlType::NewReno);
691
692 folly::Optional<std::string> alpn = std::string("h1q-fb");
693 bool performedValidation = false;
694 client->setEarlyDataAppParamsFunctions(
695 [&](const folly::Optional<std::string>& alpnToValidate, const Buf&) {
696 performedValidation = true;
697 EXPECT_EQ(alpnToValidate, alpn);
698 return true;
699 },
700 []() -> Buf { return nullptr; });
701 client->start(&clientConnCallback);
702 EXPECT_TRUE(performedValidation);
703 CHECK(client->getConn().zeroRttWriteCipher);
704 EXPECT_TRUE(client->serverInitialParamsSet());
705 EXPECT_EQ(
706 client->peerAdvertisedInitialMaxData(), kDefaultConnectionWindowSize);
707 EXPECT_EQ(
708 client->peerAdvertisedInitialMaxStreamDataBidiLocal(),
709 kDefaultStreamWindowSize);
710 EXPECT_EQ(
711 client->peerAdvertisedInitialMaxStreamDataBidiRemote(),
712 kDefaultStreamWindowSize);
713 EXPECT_EQ(
714 client->peerAdvertisedInitialMaxStreamDataUni(),
715 kDefaultStreamWindowSize);
716 EXPECT_CALL(clientConnCallback, onTransportReady()).WillOnce(Invoke([&] {
717 ASSERT_EQ(client->getAppProtocol(), "h1q-fb");
718 CHECK(client->getConn().zeroRttWriteCipher);
719 eventbase_.terminateLoopSoon();
720 }));
721 eventbase_.loopForever();
722
723 EXPECT_TRUE(client->getConn().zeroRttWriteCipher);
724 EXPECT_TRUE(client->good());
725 EXPECT_FALSE(client->replaySafe());
726
727 auto streamId = client->createBidirectionalStream().value();
728 auto data = IOBuf::copyBuffer("hello");
729 auto expected = std::shared_ptr<IOBuf>(IOBuf::copyBuffer("echo "));
730 expected->prependChain(data->clone());
731
732 EXPECT_CALL(clientConnCallback, onReplaySafe()).WillOnce(Invoke([&] {
733 EXPECT_TRUE(!client->getConn().retryToken.empty());
734 }));
735 sendRequestAndResponseAndWait(*expected, data->clone(), streamId, &readCb);
736
737 // Check CC is kept after retry recreates QuicClientConnectionState
738 EXPECT_TRUE(client->getConn().congestionControllerFactory);
739 EXPECT_EQ(
740 client->getConn().congestionController->type(),
741 CongestionControlType::NewReno);
742
743 EXPECT_FALSE(client->getConn().zeroRttWriteCipher);
744 EXPECT_TRUE(client->getConn().statelessResetToken.has_value());
745 }
746
TEST_P(QuicClientTransportIntegrationTest,TestZeroRttRejection)747 TEST_P(QuicClientTransportIntegrationTest, TestZeroRttRejection) {
748 expectTransportCallbacks();
749 auto qLogger = std::make_shared<FileQLogger>(VantagePoint::Client);
750 client->getNonConstConn().qLogger = qLogger;
751 auto cachedPsk = setupZeroRttOnClientCtx(*clientCtx, hostname);
752 pskCache_->putPsk(hostname, cachedPsk);
753 // Change the ctx
754 server_->setFizzContext(serverCtx);
755 bool performedValidation = false;
756 client->setEarlyDataAppParamsFunctions(
757 [&](const folly::Optional<std::string>&, const Buf&) {
758 performedValidation = true;
759 return true;
760 },
761 []() -> Buf { return nullptr; });
762 client->start(&clientConnCallback);
763 EXPECT_TRUE(performedValidation);
764 CHECK(client->getConn().zeroRttWriteCipher);
765 EXPECT_TRUE(client->serverInitialParamsSet());
766 EXPECT_EQ(
767 client->peerAdvertisedInitialMaxData(), kDefaultConnectionWindowSize);
768 EXPECT_EQ(
769 client->peerAdvertisedInitialMaxStreamDataBidiLocal(),
770 kDefaultStreamWindowSize);
771 EXPECT_EQ(
772 client->peerAdvertisedInitialMaxStreamDataBidiRemote(),
773 kDefaultStreamWindowSize);
774 EXPECT_EQ(
775 client->peerAdvertisedInitialMaxStreamDataUni(),
776 kDefaultStreamWindowSize);
777 client->serverInitialParamsSet() = false;
778
779 EXPECT_CALL(clientConnCallback, onTransportReady()).WillOnce(Invoke([&] {
780 ASSERT_EQ(client->getAppProtocol(), "h1q-fb");
781 CHECK(client->getConn().zeroRttWriteCipher);
782 eventbase_.terminateLoopSoon();
783 }));
784 eventbase_.loopForever();
785
786 EXPECT_TRUE(client->getConn().zeroRttWriteCipher);
787 EXPECT_TRUE(client->good());
788 EXPECT_FALSE(client->replaySafe());
789
790 auto streamId = client->createBidirectionalStream().value();
791 auto data = IOBuf::copyBuffer("hello");
792 auto expected = std::shared_ptr<IOBuf>(IOBuf::copyBuffer("echo "));
793 expected->prependChain(data->clone());
794 sendRequestAndResponseAndWait(*expected, data->clone(), streamId, &readCb);
795 // Rejection means that we will unset the zero rtt cipher.
796 EXPECT_EQ(client->getConn().zeroRttWriteCipher, nullptr);
797 EXPECT_TRUE(client->serverInitialParamsSet());
798 EXPECT_EQ(
799 client->peerAdvertisedInitialMaxData(), kDefaultConnectionWindowSize);
800 EXPECT_EQ(
801 client->peerAdvertisedInitialMaxStreamDataBidiLocal(),
802 kDefaultStreamWindowSize);
803 EXPECT_EQ(
804 client->peerAdvertisedInitialMaxStreamDataBidiRemote(),
805 kDefaultStreamWindowSize);
806 EXPECT_EQ(
807 client->peerAdvertisedInitialMaxStreamDataUni(),
808 kDefaultStreamWindowSize);
809 EXPECT_TRUE(client->getConn().statelessResetToken.has_value());
810 }
811
TEST_P(QuicClientTransportIntegrationTest,TestZeroRttNotAttempted)812 TEST_P(QuicClientTransportIntegrationTest, TestZeroRttNotAttempted) {
813 expectTransportCallbacks();
814 auto cachedPsk = setupZeroRttOnClientCtx(*clientCtx, hostname);
815 pskCache_->putPsk(hostname, cachedPsk);
816 // Change the ctx
817 server_->setFizzContext(serverCtx);
818 client->getNonConstConn().transportSettings.attemptEarlyData = false;
819 client->setEarlyDataAppParamsFunctions(
820 [&](const folly::Optional<std::string>&, const Buf&) {
821 EXPECT_TRUE(false);
822 return true;
823 },
824 []() -> Buf { return nullptr; });
825 client->start(&clientConnCallback);
826
827 EXPECT_CALL(clientConnCallback, onTransportReady()).WillOnce(Invoke([&] {
828 EXPECT_FALSE(client->getConn().zeroRttWriteCipher);
829 CHECK(client->getConn().oneRttWriteCipher);
830 eventbase_.terminateLoopSoon();
831 }));
832 eventbase_.loopForever();
833
834 auto streamId = client->createBidirectionalStream().value();
835 auto data = IOBuf::copyBuffer("hello");
836 auto expected = std::shared_ptr<IOBuf>(IOBuf::copyBuffer("echo "));
837 expected->prependChain(data->clone());
838 sendRequestAndResponseAndWait(*expected, data->clone(), streamId, &readCb);
839 EXPECT_TRUE(client->serverInitialParamsSet());
840 EXPECT_EQ(
841 client->peerAdvertisedInitialMaxData(), kDefaultConnectionWindowSize);
842 EXPECT_EQ(
843 client->peerAdvertisedInitialMaxStreamDataBidiLocal(),
844 kDefaultStreamWindowSize);
845 EXPECT_EQ(
846 client->peerAdvertisedInitialMaxStreamDataBidiRemote(),
847 kDefaultStreamWindowSize);
848 EXPECT_EQ(
849 client->peerAdvertisedInitialMaxStreamDataUni(),
850 kDefaultStreamWindowSize);
851 }
852
TEST_P(QuicClientTransportIntegrationTest,TestZeroRttInvalidAppParams)853 TEST_P(QuicClientTransportIntegrationTest, TestZeroRttInvalidAppParams) {
854 expectTransportCallbacks();
855 auto cachedPsk = setupZeroRttOnClientCtx(*clientCtx, hostname);
856 pskCache_->putPsk(hostname, cachedPsk);
857 // Change the ctx
858 server_->setFizzContext(serverCtx);
859 bool performedValidation = false;
860 client->setEarlyDataAppParamsFunctions(
861 [&](const folly::Optional<std::string>&, const Buf&) {
862 performedValidation = true;
863 return false;
864 },
865 []() -> Buf { return nullptr; });
866 client->start(&clientConnCallback);
867 EXPECT_TRUE(performedValidation);
868
869 EXPECT_CALL(clientConnCallback, onTransportReady()).WillOnce(Invoke([&] {
870 EXPECT_FALSE(client->getConn().zeroRttWriteCipher);
871 CHECK(client->getConn().oneRttWriteCipher);
872 eventbase_.terminateLoopSoon();
873 }));
874 eventbase_.loopForever();
875
876 auto streamId = client->createBidirectionalStream().value();
877 auto data = IOBuf::copyBuffer("hello");
878 auto expected = std::shared_ptr<IOBuf>(IOBuf::copyBuffer("echo "));
879 expected->prependChain(data->clone());
880 sendRequestAndResponseAndWait(*expected, data->clone(), streamId, &readCb);
881 EXPECT_TRUE(client->serverInitialParamsSet());
882 EXPECT_EQ(
883 client->peerAdvertisedInitialMaxData(), kDefaultConnectionWindowSize);
884 EXPECT_EQ(
885 client->peerAdvertisedInitialMaxStreamDataBidiLocal(),
886 kDefaultStreamWindowSize);
887 EXPECT_EQ(
888 client->peerAdvertisedInitialMaxStreamDataBidiRemote(),
889 kDefaultStreamWindowSize);
890 EXPECT_EQ(
891 client->peerAdvertisedInitialMaxStreamDataUni(),
892 kDefaultStreamWindowSize);
893 }
894
TEST_P(QuicClientTransportIntegrationTest,ChangeEventBase)895 TEST_P(QuicClientTransportIntegrationTest, ChangeEventBase) {
896 NiceMock<MockReadCallback> readCb2;
897 folly::ScopedEventBaseThread newEvb;
898 expectTransportCallbacks();
899 client->start(&clientConnCallback);
900
901 EXPECT_CALL(clientConnCallback, onTransportReady()).WillOnce(Invoke([&] {
902 CHECK(client->getConn().oneRttWriteCipher);
903 eventbase_.terminateLoopSoon();
904 }));
905 eventbase_.loopForever();
906
907 auto streamId = client->createBidirectionalStream().value();
908 auto data = IOBuf::copyBuffer("hello");
909 auto expected = std::shared_ptr<IOBuf>(IOBuf::copyBuffer("echo "));
910 expected->prependChain(data->clone());
911 sendRequestAndResponseAndWait(*expected, data->clone(), streamId, &readCb);
912 EXPECT_TRUE(client->isDetachable());
913 client->detachEventBase();
914 folly::Baton<> baton;
915 bool responseRecvd = false;
916 VLOG(10) << "changing threads";
917 newEvb.getEventBase()->runInEventBaseThreadAndWait([&] {
918 client->attachEventBase(newEvb.getEventBase());
919 auto streamId2 = client->createBidirectionalStream().value();
920 sendRequestAndResponse(data->clone(), streamId2, &readCb2)
921 .thenValue([&](StreamPair buf) {
922 responseRecvd = true;
923 EXPECT_TRUE(folly::IOBufEqualTo()(*buf.first, *expected));
924 })
925 .ensure([&] { baton.post(); });
926 });
927 baton.wait();
928 EXPECT_TRUE(responseRecvd);
929 }
930
TEST_P(QuicClientTransportIntegrationTest,ResetClient)931 TEST_P(QuicClientTransportIntegrationTest, ResetClient) {
932 expectTransportCallbacks();
933 auto server2 = createServer(ProcessId::ONE);
934 SCOPE_EXIT {
935 server2->shutdown();
936 server2 = nullptr;
937 };
938
939 client->start(&clientConnCallback);
940
941 EXPECT_CALL(clientConnCallback, onTransportReady()).WillOnce(Invoke([&] {
942 CHECK(client->getConn().oneRttWriteCipher);
943 eventbase_.terminateLoopSoon();
944 }));
945 eventbase_.loopForever();
946
947 auto streamId = client->createBidirectionalStream().value();
948 auto data = IOBuf::copyBuffer("hello");
949 auto expected = std::shared_ptr<IOBuf>(IOBuf::copyBuffer("echo "));
950 expected->prependChain(data->clone());
951 sendRequestAndResponseAndWait(*expected, data->clone(), streamId, &readCb);
952
953 // change the address to a new server which does not have the connection.
954 auto server2Addr = server2->getAddress();
955 client->getNonConstConn().peerAddress = server2Addr;
956
957 NiceMock<MockReadCallback> readCb2;
958 bool resetRecvd = false;
959 auto streamId2 = client->createBidirectionalStream().value();
960 auto f2 = sendRequestAndResponse(data->clone(), streamId2, &readCb2)
961 .thenValue([&](StreamPair) { resetRecvd = false; })
962 .thenError(
963 folly::tag_t<std::runtime_error>{},
964 [&](const std::runtime_error& e) {
965 LOG(INFO) << e.what();
966 resetRecvd = true;
967 })
968 .ensure([&] { eventbase_.terminateLoopSoon(); });
969 eventbase_.loopForever();
970 std::move(f2).get(5s);
971 EXPECT_TRUE(resetRecvd);
972 }
973
TEST_P(QuicClientTransportIntegrationTest,TestStatelessResetToken)974 TEST_P(QuicClientTransportIntegrationTest, TestStatelessResetToken) {
975 folly::Optional<StatelessResetToken> token1, token2;
976
977 expectTransportCallbacks();
978 auto server2 = createServer(ProcessId::ONE);
979 SCOPE_EXIT {
980 server2->shutdown();
981 server2 = nullptr;
982 };
983
984 client->start(&clientConnCallback);
985
986 EXPECT_CALL(clientConnCallback, onTransportReady()).WillOnce(Invoke([&] {
987 token1 = client->getConn().statelessResetToken;
988 eventbase_.terminateLoopSoon();
989 }));
990 eventbase_.loopForever();
991
992 auto streamId = client->createBidirectionalStream().value();
993 auto data = IOBuf::copyBuffer("hello");
994 auto expected = std::shared_ptr<IOBuf>(IOBuf::copyBuffer("echo "));
995 expected->prependChain(data->clone());
996 sendRequestAndResponseAndWait(*expected, data->clone(), streamId, &readCb);
997
998 // change the address to a new server which does not have the connection.
999 auto server2Addr = server2->getAddress();
1000 client->getNonConstConn().peerAddress = server2Addr;
1001
1002 NiceMock<MockReadCallback> readCb2;
1003 bool resetRecvd = false;
1004 auto streamId2 = client->createBidirectionalStream().value();
1005 sendRequestAndResponse(data->clone(), streamId2, &readCb2)
1006 .thenValue([&](StreamPair) { resetRecvd = false; })
1007 .thenError(
1008 folly::tag_t<std::runtime_error>{},
1009 [&](const std::runtime_error& e) {
1010 LOG(INFO) << e.what();
1011 resetRecvd = true;
1012 token2 = client->getConn().statelessResetToken;
1013 })
1014 .ensure([&] { eventbase_.terminateLoopSoon(); });
1015 eventbase_.loopForever();
1016
1017 EXPECT_TRUE(resetRecvd);
1018 EXPECT_TRUE(token1.has_value());
1019 EXPECT_TRUE(token2.has_value());
1020 EXPECT_EQ(token1.value(), token2.value());
1021 }
1022
TEST_P(QuicClientTransportIntegrationTest,D6DEnabledTest)1023 TEST_P(QuicClientTransportIntegrationTest, D6DEnabledTest) {
1024 expectTransportCallbacks();
1025 TransportSettings settings;
1026 settings.d6dConfig.enabled = true;
1027 client->setTransportSettings(settings);
1028
1029 TransportSettings serverSettings;
1030 serverSettings.d6dConfig.enabled = true;
1031 serverSettings.statelessResetTokenSecret = getRandSecret();
1032 server_->setTransportSettings(serverSettings);
1033
1034 // we only use 1 worker in test
1035 client->start(&clientConnCallback);
1036 EXPECT_EQ(1, statsCallbacks_.size());
1037 EXPECT_CALL(*statsCallbacks_[0], onConnectionD6DStarted())
1038 .WillOnce(Invoke([&] { eventbase_.terminateLoopSoon(); }));
1039 eventbase_.loopForever();
1040 }
1041
1042 INSTANTIATE_TEST_CASE_P(
1043 QuicClientTransportIntegrationTests,
1044 QuicClientTransportIntegrationTest,
1045 ::testing::Values(
1046 TestingParams(QuicVersion::MVFST),
1047 TestingParams(QuicVersion::QUIC_V1),
1048 TestingParams(QuicVersion::QUIC_V1, 0),
1049 TestingParams(QuicVersion::QUIC_DRAFT),
1050 TestingParams(QuicVersion::QUIC_DRAFT, 0)));
1051
1052 // Simulates a simple 1rtt handshake without needing to get any handshake bytes
1053 // from the server.
1054 class FakeOneRttHandshakeLayer : public FizzClientHandshake {
1055 public:
FakeOneRttHandshakeLayer(QuicClientConnectionState * conn,std::shared_ptr<FizzClientQuicHandshakeContext> fizzContext)1056 explicit FakeOneRttHandshakeLayer(
1057 QuicClientConnectionState* conn,
1058 std::shared_ptr<FizzClientQuicHandshakeContext> fizzContext)
1059 : FizzClientHandshake(
1060 conn,
1061 std::move(fizzContext),
1062 std::make_unique<FizzCryptoFactory>()) {}
1063
connectImpl(folly::Optional<std::string> hostname)1064 folly::Optional<CachedServerTransportParameters> connectImpl(
1065 folly::Optional<std::string> hostname) override {
1066 // Look up psk
1067 folly::Optional<QuicCachedPsk> quicCachedPsk = getPsk(hostname);
1068
1069 folly::Optional<CachedServerTransportParameters> transportParams;
1070 if (quicCachedPsk) {
1071 transportParams = std::move(quicCachedPsk->transportParams);
1072 }
1073
1074 getFizzState().sni() = hostname;
1075
1076 connected_ = true;
1077 writeDataToQuicStream(
1078 getClientConn()->cryptoState->initialStream, IOBuf::copyBuffer("CHLO"));
1079 createServerTransportParameters();
1080 return transportParams;
1081 }
1082
createServerTransportParameters()1083 void createServerTransportParameters() {
1084 TransportParameter maxStreamDataBidiLocal = encodeIntegerParameter(
1085 TransportParameterId::initial_max_stream_data_bidi_local,
1086 maxInitialStreamData);
1087 TransportParameter maxStreamDataBidiRemote = encodeIntegerParameter(
1088 TransportParameterId::initial_max_stream_data_bidi_remote,
1089 maxInitialStreamData);
1090 TransportParameter maxStreamDataUni = encodeIntegerParameter(
1091 TransportParameterId::initial_max_stream_data_uni,
1092 maxInitialStreamData);
1093 TransportParameter maxStreamsBidi = encodeIntegerParameter(
1094 TransportParameterId::initial_max_streams_bidi, maxInitialStreamsBidi);
1095 TransportParameter maxStreamsUni = encodeIntegerParameter(
1096 TransportParameterId::initial_max_streams_uni, maxInitialStreamsUni);
1097 TransportParameter maxData = encodeIntegerParameter(
1098 TransportParameterId::initial_max_data, connWindowSize);
1099 std::vector<TransportParameter> parameters;
1100 parameters.push_back(std::move(maxStreamDataBidiLocal));
1101 parameters.push_back(std::move(maxStreamDataBidiRemote));
1102 parameters.push_back(std::move(maxStreamDataUni));
1103 parameters.push_back(std::move(maxStreamsBidi));
1104 parameters.push_back(std::move(maxStreamsUni));
1105 parameters.push_back(std::move(maxData));
1106 parameters.push_back(encodeIntegerParameter(
1107 TransportParameterId::idle_timeout, kDefaultIdleTimeout.count()));
1108 parameters.push_back(encodeIntegerParameter(
1109 TransportParameterId::max_packet_size, maxRecvPacketSize));
1110 ServerTransportParameters params;
1111 StatelessResetToken testStatelessResetToken = generateStatelessResetToken();
1112 TransportParameter statelessReset;
1113 statelessReset.parameter = TransportParameterId::stateless_reset_token;
1114 statelessReset.value = folly::IOBuf::copyBuffer(testStatelessResetToken);
1115 parameters.push_back(std::move(statelessReset));
1116
1117 params.parameters = std::move(parameters);
1118 params_ = std::move(params);
1119 }
1120
setServerTransportParams(ServerTransportParameters params)1121 void setServerTransportParams(ServerTransportParameters params) {
1122 params_ = std::move(params);
1123 }
1124
setOneRttWriteCipher(std::unique_ptr<Aead> oneRttWriteCipher)1125 void setOneRttWriteCipher(std::unique_ptr<Aead> oneRttWriteCipher) {
1126 oneRttWriteCipher_ = std::move(oneRttWriteCipher);
1127 }
1128
setOneRttReadCipher(std::unique_ptr<Aead> oneRttReadCipher)1129 void setOneRttReadCipher(std::unique_ptr<Aead> oneRttReadCipher) {
1130 getClientConn()->readCodec->setOneRttReadCipher(
1131 std::move(oneRttReadCipher));
1132 }
1133
setHandshakeReadCipher(std::unique_ptr<Aead> handshakeReadCipher)1134 void setHandshakeReadCipher(std::unique_ptr<Aead> handshakeReadCipher) {
1135 getClientConn()->readCodec->setHandshakeReadCipher(
1136 std::move(handshakeReadCipher));
1137 }
1138
setHandshakeWriteCipher(std::unique_ptr<Aead> handshakeWriteCipher)1139 void setHandshakeWriteCipher(std::unique_ptr<Aead> handshakeWriteCipher) {
1140 getClientConn()->handshakeWriteCipher = std::move(handshakeWriteCipher);
1141 }
1142
setZeroRttWriteCipher(std::unique_ptr<Aead> zeroRttWriteCipher)1143 void setZeroRttWriteCipher(std::unique_ptr<Aead> zeroRttWriteCipher) {
1144 getClientConn()->zeroRttWriteCipher = std::move(zeroRttWriteCipher);
1145 }
1146
setZeroRttWriteHeaderCipher(std::unique_ptr<PacketNumberCipher> zeroRttWriteHeaderCipher)1147 void setZeroRttWriteHeaderCipher(
1148 std::unique_ptr<PacketNumberCipher> zeroRttWriteHeaderCipher) {
1149 getClientConn()->zeroRttWriteHeaderCipher =
1150 std::move(zeroRttWriteHeaderCipher);
1151 }
1152
setHandshakeReadHeaderCipher(std::unique_ptr<PacketNumberCipher> handshakeReadHeaderCipher)1153 void setHandshakeReadHeaderCipher(
1154 std::unique_ptr<PacketNumberCipher> handshakeReadHeaderCipher) {
1155 getClientConn()->readCodec->setHandshakeHeaderCipher(
1156 std::move(handshakeReadHeaderCipher));
1157 }
1158
setHandshakeWriteHeaderCipher(std::unique_ptr<PacketNumberCipher> handshakeWriteHeaderCipher)1159 void setHandshakeWriteHeaderCipher(
1160 std::unique_ptr<PacketNumberCipher> handshakeWriteHeaderCipher) {
1161 getClientConn()->handshakeWriteHeaderCipher =
1162 std::move(handshakeWriteHeaderCipher);
1163 }
1164
setOneRttWriteHeaderCipher(std::unique_ptr<PacketNumberCipher> oneRttWriteHeaderCipher)1165 void setOneRttWriteHeaderCipher(
1166 std::unique_ptr<PacketNumberCipher> oneRttWriteHeaderCipher) {
1167 oneRttWriteHeaderCipher_ = std::move(oneRttWriteHeaderCipher);
1168 }
1169
setOneRttReadHeaderCipher(std::unique_ptr<PacketNumberCipher> oneRttReadHeaderCipher)1170 void setOneRttReadHeaderCipher(
1171 std::unique_ptr<PacketNumberCipher> oneRttReadHeaderCipher) {
1172 getClientConn()->readCodec->setOneRttHeaderCipher(
1173 std::move(oneRttReadHeaderCipher));
1174 }
1175
setZeroRttRejected(bool rejected)1176 void setZeroRttRejected(bool rejected) {
1177 setZeroRttRejectedForTest(rejected);
1178 if (rejected) {
1179 createServerTransportParameters();
1180 }
1181 }
1182
doHandshake(std::unique_ptr<folly::IOBuf> buf,EncryptionLevel level)1183 void doHandshake(std::unique_ptr<folly::IOBuf> buf, EncryptionLevel level)
1184 override {
1185 EXPECT_EQ(writeBuf.get(), nullptr);
1186 QuicClientConnectionState* conn = getClientConn();
1187 if (!conn->oneRttWriteCipher) {
1188 conn->oneRttWriteCipher = std::move(oneRttWriteCipher_);
1189 conn->oneRttWriteHeaderCipher = std::move(oneRttWriteHeaderCipher_);
1190 }
1191 if (getPhase() == Phase::Initial) {
1192 conn->handshakeWriteCipher = test::createNoOpAead();
1193 conn->handshakeWriteHeaderCipher = test::createNoOpHeaderCipher();
1194 conn->readCodec->setHandshakeReadCipher(test::createNoOpAead());
1195 conn->readCodec->setHandshakeHeaderCipher(test::createNoOpHeaderCipher());
1196 writeDataToQuicStream(
1197 conn->cryptoState->handshakeStream,
1198 IOBuf::copyBuffer("ClientFinished"));
1199 handshakeInitiated();
1200 }
1201 readBuffers[level].append(std::move(buf));
1202 }
1203
connectInvoked()1204 bool connectInvoked() {
1205 return connected_;
1206 }
1207
getServerTransportParams()1208 folly::Optional<ServerTransportParameters> getServerTransportParams()
1209 override {
1210 return params_;
1211 }
1212
triggerOnNewCachedPsk()1213 void triggerOnNewCachedPsk() {
1214 fizz::client::NewCachedPsk psk;
1215 onNewCachedPsk(psk);
1216 }
1217
1218 std::unique_ptr<folly::IOBuf> writeBuf;
1219
1220 bool connected_{false};
1221 QuicVersion negotiatedVersion{QuicVersion::MVFST};
1222 uint64_t maxRecvPacketSize{kDefaultMaxUDPPayload};
1223 uint64_t maxInitialStreamData{kDefaultStreamWindowSize};
1224 uint64_t connWindowSize{kDefaultConnectionWindowSize};
1225 uint64_t maxInitialStreamsBidi{std::numeric_limits<uint32_t>::max()};
1226 uint64_t maxInitialStreamsUni{std::numeric_limits<uint32_t>::max()};
1227 folly::Optional<ServerTransportParameters> params_;
1228 EnumArray<EncryptionLevel, BufQueue> readBuffers{};
1229
1230 std::unique_ptr<Aead> oneRttWriteCipher_;
1231 std::unique_ptr<PacketNumberCipher> oneRttWriteHeaderCipher_;
1232
1233 FizzCryptoFactory cryptoFactory_;
getCryptoFactory() const1234 const CryptoFactory& getCryptoFactory() const override {
1235 return cryptoFactory_;
1236 }
1237
1238 // Implement virtual methods we don't intend to use.
isTLSResumed() const1239 bool isTLSResumed() const override {
1240 throw std::runtime_error("isTLSResumed not implemented");
1241 }
getReadRecordLayerEncryptionLevel()1242 EncryptionLevel getReadRecordLayerEncryptionLevel() override {
1243 throw std::runtime_error(
1244 "getReadRecordLayerEncryptionLevel not implemented");
1245 }
getApplicationProtocol() const1246 const folly::Optional<std::string>& getApplicationProtocol() const override {
1247 throw std::runtime_error("getApplicationProtocol not implemented");
1248 }
processSocketData(folly::IOBufQueue &)1249 void processSocketData(folly::IOBufQueue&) override {
1250 throw std::runtime_error("processSocketData not implemented");
1251 }
matchEarlyParameters()1252 bool matchEarlyParameters() override {
1253 throw std::runtime_error("matchEarlyParameters not implemented");
1254 }
1255 std::pair<std::unique_ptr<Aead>, std::unique_ptr<PacketNumberCipher>>
buildCiphers(CipherKind,folly::ByteRange)1256 buildCiphers(CipherKind, folly::ByteRange) override {
1257 throw std::runtime_error("buildCiphers not implemented");
1258 }
1259 };
1260
1261 class QuicClientTransportTest : public Test {
1262 public:
1263 struct TestReadData {
1264 std::unique_ptr<folly::IOBuf> data;
1265 folly::SocketAddress addr;
1266 folly::Optional<int> err;
1267
TestReadDataquic::test::QuicClientTransportTest::TestReadData1268 TestReadData(folly::ByteRange dataIn, const folly::SocketAddress& addrIn)
1269 : data(folly::IOBuf::copyBuffer(dataIn)), addr(addrIn) {}
1270
TestReadDataquic::test::QuicClientTransportTest::TestReadData1271 explicit TestReadData(int errIn) : err(errIn) {}
1272 };
1273
QuicClientTransportTest()1274 QuicClientTransportTest()
1275 : eventbase_(std::make_unique<folly::EventBase>()) {}
1276
getFizzClientContext()1277 std::shared_ptr<FizzClientQuicHandshakeContext> getFizzClientContext() {
1278 if (!fizzClientContext) {
1279 fizzClientContext =
1280 FizzClientQuicHandshakeContext::Builder()
1281 .setCertificateVerifier(createTestCertificateVerifier())
1282 .setPskCache(getPskCache())
1283 .build();
1284 }
1285
1286 return fizzClientContext;
1287 }
1288
getPskCache()1289 virtual std::shared_ptr<QuicPskCache> getPskCache() {
1290 return nullptr;
1291 }
1292
SetUp()1293 void SetUp() override final {
1294 auto socket = std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(
1295 eventbase_.get());
1296 sock = socket.get();
1297
1298 client = TestingQuicClientTransport::newClient<TestingQuicClientTransport>(
1299 eventbase_.get(), std::move(socket), getFizzClientContext());
1300 destructionCallback = std::make_shared<DestructionCallback>();
1301 client->setDestructionCallback(destructionCallback);
1302 client->setSupportedVersions(
1303 {QuicVersion::MVFST,
1304 MVFST1,
1305 QuicVersion::QUIC_V1,
1306 QuicVersion::QUIC_DRAFT});
1307 connIdAlgo_ = std::make_unique<DefaultConnectionIdAlgo>();
1308 ON_CALL(*sock, resumeRead(_))
1309 .WillByDefault(SaveArg<0>(&networkReadCallback));
1310 ON_CALL(*sock, address()).WillByDefault(ReturnRef(serverAddr));
1311 ON_CALL(*sock, recvmsg(_, _))
1312 .WillByDefault(Invoke([&](struct msghdr* msg, int) -> ssize_t {
1313 DCHECK_GT(msg->msg_iovlen, 0);
1314 if (socketReads.empty()) {
1315 errno = EAGAIN;
1316 return -1;
1317 }
1318 if (socketReads[0].err) {
1319 errno = *socketReads[0].err;
1320 return -1;
1321 }
1322 auto testData = std::move(socketReads[0].data);
1323 testData->coalesce();
1324 size_t testDataLen = testData->length();
1325 memcpy(
1326 msg->msg_iov[0].iov_base, testData->data(), testData->length());
1327 if (msg->msg_name) {
1328 socklen_t msg_len = socketReads[0].addr.getAddress(
1329 static_cast<sockaddr_storage*>(msg->msg_name));
1330 msg->msg_namelen = msg_len;
1331 }
1332 socketReads.pop_front();
1333 return testDataLen;
1334 }));
1335 EXPECT_EQ(client->getConn().selfConnectionIds.size(), 1);
1336 EXPECT_EQ(
1337 client->getConn().selfConnectionIds[0].connId,
1338 *client->getConn().clientConnectionId);
1339 EXPECT_EQ(client->getConn().peerConnectionIds.size(), 0);
1340
1341 SetUpChild();
1342 }
1343
SetUpChild()1344 virtual void SetUpChild() {}
1345
setupCryptoLayer()1346 virtual void setupCryptoLayer() {
1347 // Fake that the handshake has already occured and fix the keys.
1348 mockClientHandshake = new FakeOneRttHandshakeLayer(
1349 &client->getNonConstConn(), getFizzClientContext());
1350 client->getNonConstConn().clientHandshakeLayer = mockClientHandshake;
1351 client->getNonConstConn().handshakeLayer.reset(mockClientHandshake);
1352 setFakeHandshakeCiphers();
1353 // Allow ignoring path mtu for testing negotiation.
1354 client->getNonConstConn().transportSettings.canIgnorePathMTU = true;
1355 }
1356
setFakeHandshakeCiphers()1357 virtual void setFakeHandshakeCiphers() {
1358 auto readAead = test::createNoOpAead();
1359 auto writeAead = test::createNoOpAead();
1360 auto handshakeReadAead = test::createNoOpAead();
1361 auto handshakeWriteAead = test::createNoOpAead();
1362 mockClientHandshake->setHandshakeReadCipher(std::move(handshakeReadAead));
1363 mockClientHandshake->setHandshakeWriteCipher(std::move(handshakeWriteAead));
1364 mockClientHandshake->setOneRttReadCipher(std::move(readAead));
1365 mockClientHandshake->setOneRttWriteCipher(std::move(writeAead));
1366
1367 mockClientHandshake->setHandshakeReadHeaderCipher(
1368 test::createNoOpHeaderCipher());
1369 mockClientHandshake->setHandshakeWriteHeaderCipher(
1370 test::createNoOpHeaderCipher());
1371 mockClientHandshake->setOneRttWriteHeaderCipher(
1372 test::createNoOpHeaderCipher());
1373 mockClientHandshake->setOneRttReadHeaderCipher(
1374 test::createNoOpHeaderCipher());
1375 }
1376
setUpSocketExpectations()1377 virtual void setUpSocketExpectations() {
1378 EXPECT_CALL(*sock, setReuseAddr(false));
1379 EXPECT_CALL(*sock, bind(_, _));
1380 EXPECT_CALL(*sock, setDFAndTurnOffPMTU());
1381 EXPECT_CALL(*sock, setErrMessageCallback(client.get()));
1382 EXPECT_CALL(*sock, resumeRead(client.get()));
1383 EXPECT_CALL(*sock, setErrMessageCallback(nullptr));
1384 EXPECT_CALL(*sock, write(_, _)).Times(AtLeast(1));
1385 }
1386
start()1387 virtual void start() {
1388 EXPECT_CALL(clientConnCallback, onTransportReady());
1389 EXPECT_CALL(clientConnCallback, onReplaySafe());
1390 setUpSocketExpectations();
1391 client->start(&clientConnCallback);
1392 setConnectionIds();
1393 EXPECT_TRUE(client->idleTimeout().isScheduled());
1394
1395 EXPECT_EQ(socketWrites.size(), 1);
1396 EXPECT_TRUE(
1397 verifyLongHeader(*socketWrites.at(0), LongHeader::Types::Initial));
1398 socketWrites.clear();
1399 performFakeHandshake();
1400 EXPECT_TRUE(
1401 client->getConn().readCodec->getStatelessResetToken().has_value());
1402 EXPECT_TRUE(client->getConn().statelessResetToken.has_value());
1403 }
1404
setConnectionIds()1405 void setConnectionIds() {
1406 originalConnId = client->getConn().clientConnectionId;
1407 ServerConnectionIdParams params(0, 0, 0);
1408 serverChosenConnId = *connIdAlgo_->encodeConnectionId(params);
1409 }
1410
recvServerHello(const folly::SocketAddress & addr)1411 void recvServerHello(const folly::SocketAddress& addr) {
1412 auto serverHello = IOBuf::copyBuffer("Fake SHLO");
1413 PacketNum nextPacketNum = initialPacketNum++;
1414 auto& aead = getInitialCipher();
1415 auto packet = packetToBufCleartext(
1416 createCryptoPacket(
1417 *serverChosenConnId,
1418 *originalConnId,
1419 nextPacketNum,
1420 version,
1421 ProtectionType::Initial,
1422 *serverHello,
1423 aead,
1424 0 /* largestAcked */),
1425 aead,
1426 getInitialHeaderCipher(),
1427 nextPacketNum);
1428 deliverData(addr, packet->coalesce());
1429 }
1430
recvServerRetry(const folly::SocketAddress & addr)1431 ConnectionId recvServerRetry(const folly::SocketAddress& addr) {
1432 // Make the server send a retry packet to the client. The server chooses a
1433 // connection id that the client must use in all future initial packets.
1434 std::vector<uint8_t> serverConnIdVec = {
1435 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5};
1436 ConnectionId serverCid(serverConnIdVec);
1437
1438 std::string retryToken = "token";
1439 std::string integrityTag =
1440 "\xd1\x69\x26\xd8\x1f\x6f\x9c\xa2\x95\x3a\x8a\xa4\x57\x5e\x1e\x49";
1441
1442 folly::IOBuf retryPacketBuf;
1443 BufAppender appender(&retryPacketBuf, 100);
1444 appender.writeBE<uint8_t>(0xFF);
1445 appender.writeBE<QuicVersionType>(static_cast<QuicVersionType>(0xFF00001D));
1446 appender.writeBE<uint8_t>(0);
1447 appender.writeBE<uint8_t>(serverConnIdVec.size());
1448 appender.push(serverConnIdVec.data(), serverConnIdVec.size());
1449 appender.push((const uint8_t*)retryToken.data(), retryToken.size());
1450 appender.push((const uint8_t*)integrityTag.data(), integrityTag.size());
1451 deliverData(addr, retryPacketBuf.coalesce());
1452 return serverCid;
1453 }
1454
recvServerHello()1455 void recvServerHello() {
1456 recvServerHello(serverAddr);
1457 }
1458
recvTicket(folly::Optional<uint64_t> offsetOverride=folly::none)1459 void recvTicket(folly::Optional<uint64_t> offsetOverride = folly::none) {
1460 auto negotiatedVersion = *client->getConn().version;
1461 auto ticket = IOBuf::copyBuffer("NST");
1462 auto packet = packetToBuf(createCryptoPacket(
1463 *serverChosenConnId,
1464 *originalConnId,
1465 appDataPacketNum++,
1466 negotiatedVersion,
1467 ProtectionType::KeyPhaseZero,
1468 *ticket,
1469 *createNoOpAead(),
1470 0 /* largestAcked */,
1471 offsetOverride
1472 ? *offsetOverride
1473 : client->getConn().cryptoState->oneRttStream.currentReadOffset));
1474 deliverData(packet->coalesce());
1475 }
1476
performFakeHandshake(const folly::SocketAddress & addr)1477 void performFakeHandshake(const folly::SocketAddress& addr) {
1478 // Create a fake server response to trigger fetching keys.
1479 recvServerHello(addr);
1480 assertWritten(false, LongHeader::Types::Handshake);
1481
1482 verifyTransportParameters(
1483 kDefaultConnectionWindowSize,
1484 kDefaultStreamWindowSize,
1485 kDefaultIdleTimeout,
1486 kDefaultAckDelayExponent,
1487 mockClientHandshake->maxRecvPacketSize);
1488 verifyCiphers();
1489 socketWrites.clear();
1490 }
1491
performFakeHandshake()1492 void performFakeHandshake() {
1493 performFakeHandshake(serverAddr);
1494 }
1495
verifyTransportParameters(uint64_t connFlowControl,uint64_t initialStreamFlowControl,std::chrono::milliseconds idleTimeout,uint64_t ackDelayExponent,uint64_t maxPacketSize)1496 void verifyTransportParameters(
1497 uint64_t connFlowControl,
1498 uint64_t initialStreamFlowControl,
1499 std::chrono::milliseconds idleTimeout,
1500 uint64_t ackDelayExponent,
1501 uint64_t maxPacketSize) {
1502 EXPECT_EQ(
1503 client->getConn().flowControlState.peerAdvertisedMaxOffset,
1504 connFlowControl);
1505 EXPECT_EQ(
1506 client->getConn()
1507 .flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiLocal,
1508 initialStreamFlowControl);
1509 EXPECT_EQ(
1510 client->getConn()
1511 .flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiRemote,
1512 initialStreamFlowControl);
1513
1514 EXPECT_EQ(
1515 client->getConn()
1516 .flowControlState.peerAdvertisedInitialMaxStreamOffsetUni,
1517 initialStreamFlowControl);
1518 EXPECT_EQ(client->getConn().peerIdleTimeout.count(), idleTimeout.count());
1519 EXPECT_EQ(client->getConn().peerAckDelayExponent, ackDelayExponent);
1520 EXPECT_EQ(client->getConn().udpSendPacketLen, maxPacketSize);
1521 }
1522
verifyCiphers()1523 void verifyCiphers() {
1524 EXPECT_NE(client->getConn().oneRttWriteCipher, nullptr);
1525 EXPECT_NE(client->getConn().handshakeWriteCipher, nullptr);
1526 EXPECT_NE(client->getConn().handshakeWriteHeaderCipher, nullptr);
1527 EXPECT_NE(client->getConn().oneRttWriteHeaderCipher, nullptr);
1528
1529 EXPECT_NE(client->getConn().readCodec->getHandshakeHeaderCipher(), nullptr);
1530 EXPECT_NE(client->getConn().readCodec->getOneRttHeaderCipher(), nullptr);
1531 }
1532
deliverDataWithoutErrorCheck(const folly::SocketAddress & addr,folly::ByteRange data,bool writes=true)1533 void deliverDataWithoutErrorCheck(
1534 const folly::SocketAddress& addr,
1535 folly::ByteRange data,
1536 bool writes = true) {
1537 ASSERT_TRUE(networkReadCallback);
1538 socketReads.emplace_back(TestReadData(data, addr));
1539 networkReadCallback->onNotifyDataAvailable(*sock);
1540 if (writes) {
1541 loopForWrites();
1542 }
1543 }
1544
deliverNetworkError(int err)1545 void deliverNetworkError(int err) {
1546 ASSERT_TRUE(networkReadCallback);
1547 socketReads.emplace_back(TestReadData(err));
1548 networkReadCallback->onNotifyDataAvailable(*sock);
1549 }
1550
deliverDataWithoutErrorCheck(folly::ByteRange data,bool writes=true)1551 void deliverDataWithoutErrorCheck(folly::ByteRange data, bool writes = true) {
1552 deliverDataWithoutErrorCheck(serverAddr, std::move(data), writes);
1553 }
1554
deliverData(const folly::SocketAddress & addr,folly::ByteRange data,bool writes=true)1555 void deliverData(
1556 const folly::SocketAddress& addr,
1557 folly::ByteRange data,
1558 bool writes = true) {
1559 deliverDataWithoutErrorCheck(addr, std::move(data), writes);
1560 if (client->getConn().localConnectionError) {
1561 bool idleTimeout = false;
1562 const LocalErrorCode* localError =
1563 client->getConn().localConnectionError->first.asLocalErrorCode();
1564 if (localError) {
1565 idleTimeout = (*localError == LocalErrorCode::IDLE_TIMEOUT);
1566 }
1567 if (!idleTimeout) {
1568 throw std::runtime_error(
1569 toString(client->getConn().localConnectionError->first));
1570 }
1571 }
1572 }
1573
deliverData(folly::ByteRange data,bool writes=true)1574 void deliverData(folly::ByteRange data, bool writes = true) {
1575 deliverData(serverAddr, std::move(data), writes);
1576 }
1577
loopForWrites()1578 void loopForWrites() {
1579 // Loop the evb once to give writes some time to do their thing.
1580 eventbase_->loopOnce(EVLOOP_NONBLOCK);
1581 }
1582
assertWritten(bool shortHeader,folly::Optional<LongHeader::Types> longHeader)1583 void assertWritten(
1584 bool shortHeader,
1585 folly::Optional<LongHeader::Types> longHeader) {
1586 size_t numShort = 0;
1587 size_t numLong = 0;
1588 size_t numOthers = 0;
1589 if (!socketWrites.empty()) {
1590 auto& write = socketWrites.back();
1591 if (shortHeader && verifyShortHeader(*write)) {
1592 numShort++;
1593 } else if (longHeader && verifyLongHeader(*write, *longHeader)) {
1594 numLong++;
1595 } else {
1596 numOthers++;
1597 }
1598 }
1599 if (shortHeader) {
1600 EXPECT_GT(numShort, 0);
1601 }
1602 if (longHeader) {
1603 EXPECT_GT(numLong, 0);
1604 }
1605 EXPECT_EQ(numOthers, 0);
1606 }
1607
parseRegularQuicPacket(CodecResult & codecResult)1608 RegularQuicPacket* parseRegularQuicPacket(CodecResult& codecResult) {
1609 return codecResult.regularPacket();
1610 }
1611
verifyShortPackets(AckBlocks & sentPackets)1612 void verifyShortPackets(AckBlocks& sentPackets) {
1613 AckStates ackStates;
1614 for (auto& write : socketWrites) {
1615 auto packetQueue = bufToQueue(write->clone());
1616 auto codecResult =
1617 makeEncryptedCodec(true)->parsePacket(packetQueue, ackStates);
1618 auto parsedPacket = parseRegularQuicPacket(codecResult);
1619 if (!parsedPacket) {
1620 continue;
1621 }
1622 PacketNum packetNumSent = parsedPacket->header.getPacketSequenceNum();
1623 sentPackets.insert(packetNumSent);
1624 verifyShortHeader(*write);
1625 }
1626 }
1627
verifyLongHeader(folly::IOBuf & buf,typename LongHeader::Types headerType)1628 bool verifyLongHeader(
1629 folly::IOBuf& buf,
1630 typename LongHeader::Types headerType) {
1631 AckStates ackStates;
1632 auto packetQueue = bufToQueue(buf.clone());
1633 auto codecResult =
1634 makeEncryptedCodec(true)->parsePacket(packetQueue, ackStates);
1635 auto parsedPacket = parseRegularQuicPacket(codecResult);
1636 if (!parsedPacket) {
1637 return false;
1638 }
1639 auto longHeader = parsedPacket->header.asLong();
1640 return longHeader && longHeader->getHeaderType() == headerType;
1641 }
1642
verifyShortHeader(folly::IOBuf & buf)1643 bool verifyShortHeader(folly::IOBuf& buf) {
1644 AckStates ackStates;
1645 auto packetQueue = bufToQueue(buf.clone());
1646 auto codecResult =
1647 makeEncryptedCodec(true)->parsePacket(packetQueue, ackStates);
1648 auto parsedPacket = parseRegularQuicPacket(codecResult);
1649 if (!parsedPacket) {
1650 return false;
1651 }
1652 return parsedPacket->header.asShort();
1653 }
1654
makeHandshakeCodec()1655 std::unique_ptr<QuicReadCodec> makeHandshakeCodec() {
1656 FizzCryptoFactory cryptoFactory;
1657 auto codec = std::make_unique<QuicReadCodec>(QuicNodeType::Server);
1658 codec->setClientConnectionId(*originalConnId);
1659 codec->setInitialReadCipher(cryptoFactory.getClientInitialCipher(
1660 *client->getConn().initialDestinationConnectionId, QuicVersion::MVFST));
1661 codec->setInitialHeaderCipher(cryptoFactory.makeClientInitialHeaderCipher(
1662 *client->getConn().initialDestinationConnectionId, QuicVersion::MVFST));
1663 codec->setHandshakeReadCipher(test::createNoOpAead());
1664 codec->setHandshakeHeaderCipher(test::createNoOpHeaderCipher());
1665 return codec;
1666 }
1667
makeEncryptedCodec(bool handshakeCipher=false)1668 std::unique_ptr<QuicReadCodec> makeEncryptedCodec(
1669 bool handshakeCipher = false) {
1670 FizzCryptoFactory cryptoFactory;
1671 auto codec = std::make_unique<QuicReadCodec>(QuicNodeType::Server);
1672 std::unique_ptr<Aead> handshakeReadCipher;
1673 codec->setClientConnectionId(*originalConnId);
1674 codec->setOneRttReadCipher(test::createNoOpAead());
1675 codec->setOneRttHeaderCipher(test::createNoOpHeaderCipher());
1676 codec->setZeroRttReadCipher(test::createNoOpAead());
1677 codec->setZeroRttHeaderCipher(test::createNoOpHeaderCipher());
1678 if (handshakeCipher) {
1679 codec->setInitialReadCipher(cryptoFactory.getClientInitialCipher(
1680 *client->getConn().initialDestinationConnectionId,
1681 QuicVersion::MVFST));
1682 codec->setInitialHeaderCipher(cryptoFactory.makeClientInitialHeaderCipher(
1683 *client->getConn().initialDestinationConnectionId,
1684 QuicVersion::MVFST));
1685 codec->setHandshakeReadCipher(test::createNoOpAead());
1686 codec->setHandshakeHeaderCipher(test::createNoOpHeaderCipher());
1687 }
1688 return codec;
1689 }
1690
getInitialCipher()1691 const Aead& getInitialCipher() {
1692 return *client->getConn().readCodec->getInitialCipher();
1693 }
1694
getInitialHeaderCipher()1695 const PacketNumberCipher& getInitialHeaderCipher() {
1696 return *client->getConn().readCodec->getInitialHeaderCipher();
1697 }
1698
expectQuicStatsPacketDrop(QuicTransportStatsCallback::PacketDropReason expectedReason)1699 void expectQuicStatsPacketDrop(
1700 QuicTransportStatsCallback::PacketDropReason expectedReason) {
1701 auto quicStats = std::make_shared<NiceMock<MockQuicStats>>();
1702 EXPECT_CALL(*quicStats, onPacketDropped(_))
1703 .WillOnce(
1704 Invoke([=](QuicTransportStatsCallback::PacketDropReason reason) {
1705 EXPECT_EQ(expectedReason, reason);
1706 }));
1707 client->setTransportStatsCallback(quicStats);
1708 }
1709
1710 protected:
1711 std::vector<std::unique_ptr<folly::IOBuf>> socketWrites;
1712 std::deque<TestReadData> socketReads;
1713 NiceMock<MockDeliveryCallback> deliveryCallback;
1714 NiceMock<MockReadCallback> readCb;
1715 NiceMock<MockConnectionCallback> clientConnCallback;
1716 folly::test::MockAsyncUDPSocket* sock;
1717 std::shared_ptr<DestructionCallback> destructionCallback;
1718 std::unique_ptr<folly::EventBase> eventbase_;
1719 SocketAddress serverAddr{"127.0.0.1", 443};
1720 AsyncUDPSocket::ReadCallback* networkReadCallback{nullptr};
1721 FakeOneRttHandshakeLayer* mockClientHandshake;
1722 std::shared_ptr<FizzClientQuicHandshakeContext> fizzClientContext;
1723 std::shared_ptr<TestingQuicClientTransport> client;
1724 PacketNum initialPacketNum{0}, handshakePacketNum{0}, appDataPacketNum{0};
1725 std::unique_ptr<ConnectionIdAlgo> connIdAlgo_;
1726 folly::Optional<ConnectionId> originalConnId;
1727 folly::Optional<ConnectionId> serverChosenConnId;
1728 QuicVersion version{QuicVersion::QUIC_V1};
1729 };
1730
TEST_F(QuicClientTransportTest,ReadErrorCloseTransprot)1731 TEST_F(QuicClientTransportTest, ReadErrorCloseTransprot) {
1732 client->onReadError(folly::AsyncSocketException(
1733 folly::AsyncSocketException::INTERNAL_ERROR, "Where you wanna go", -1));
1734 EXPECT_FALSE(client->isClosed());
1735 client->onReadError(folly::AsyncSocketException(
1736 folly::AsyncSocketException::INTERNAL_ERROR,
1737 "He never saw it coming at all",
1738 -1));
1739 eventbase_->loopOnce();
1740 EXPECT_TRUE(client->isClosed());
1741 }
1742
TEST_F(QuicClientTransportTest,FirstPacketProcessedCallback)1743 TEST_F(QuicClientTransportTest, FirstPacketProcessedCallback) {
1744 client->addNewPeerAddress(serverAddr);
1745 client->start(&clientConnCallback);
1746
1747 originalConnId = client->getConn().clientConnectionId;
1748 ServerConnectionIdParams params(0, 0, 0);
1749 client->getNonConstConn().serverConnectionId =
1750 *connIdAlgo_->encodeConnectionId(params);
1751
1752 AckBlocks acks;
1753 acks.insert(0);
1754 auto& aead = getInitialCipher();
1755 auto& headerCipher = getInitialHeaderCipher();
1756 auto ackPacket = packetToBufCleartext(
1757 createAckPacket(
1758 client->getNonConstConn(),
1759 initialPacketNum,
1760 acks,
1761 PacketNumberSpace::Initial,
1762 &aead),
1763 aead,
1764 headerCipher,
1765 initialPacketNum);
1766 initialPacketNum++;
1767 EXPECT_CALL(clientConnCallback, onFirstPeerPacketProcessed()).Times(1);
1768 deliverData(serverAddr, ackPacket->coalesce());
1769 EXPECT_FALSE(client->hasWriteCipher());
1770
1771 // Another ack won't trigger it again:
1772 auto oneMoreAckPacket = packetToBufCleartext(
1773 createAckPacket(
1774 client->getNonConstConn(),
1775 initialPacketNum,
1776 acks,
1777 PacketNumberSpace::Initial,
1778 &aead),
1779 aead,
1780 headerCipher,
1781 initialPacketNum);
1782 initialPacketNum++;
1783 EXPECT_CALL(clientConnCallback, onFirstPeerPacketProcessed()).Times(0);
1784 deliverData(serverAddr, oneMoreAckPacket->coalesce());
1785 EXPECT_FALSE(client->hasWriteCipher());
1786
1787 client->closeNow(folly::none);
1788 }
1789
TEST_F(QuicClientTransportTest,CustomTransportParam)1790 TEST_F(QuicClientTransportTest, CustomTransportParam) {
1791 EXPECT_TRUE(client->setCustomTransportParameter(
1792 std::make_unique<CustomIntegralTransportParameter>(
1793 kCustomTransportParameterThreshold, 0)));
1794 client->closeNow(folly::none);
1795 }
1796
TEST_F(QuicClientTransportTest,CloseSocketOnWriteError)1797 TEST_F(QuicClientTransportTest, CloseSocketOnWriteError) {
1798 client->addNewPeerAddress(serverAddr);
1799 EXPECT_CALL(*sock, write(_, _)).WillOnce(SetErrnoAndReturn(EBADF, -1));
1800 client->start(&clientConnCallback);
1801
1802 EXPECT_FALSE(client->isClosed());
1803 EXPECT_CALL(clientConnCallback, onConnectionError(_));
1804 eventbase_->loopOnce();
1805 EXPECT_TRUE(client->isClosed());
1806 }
1807
TEST_F(QuicClientTransportTest,AddNewPeerAddressSetsPacketSize)1808 TEST_F(QuicClientTransportTest, AddNewPeerAddressSetsPacketSize) {
1809 folly::SocketAddress v4Address("0.0.0.0", 0);
1810 ASSERT_TRUE(v4Address.getFamily() == AF_INET);
1811 client->addNewPeerAddress(v4Address);
1812 EXPECT_EQ(kDefaultV4UDPSendPacketLen, client->getConn().udpSendPacketLen);
1813
1814 folly::SocketAddress v6Address("::", 0);
1815 ASSERT_TRUE(v6Address.getFamily() == AF_INET6);
1816 client->addNewPeerAddress(v6Address);
1817 EXPECT_EQ(kDefaultV6UDPSendPacketLen, client->getConn().udpSendPacketLen);
1818
1819 client->closeNow(folly::none);
1820 }
1821
TEST_F(QuicClientTransportTest,onNetworkSwitchNoReplace)1822 TEST_F(QuicClientTransportTest, onNetworkSwitchNoReplace) {
1823 client->getNonConstConn().oneRttWriteCipher = test::createNoOpAead();
1824 auto mockQLogger = std::make_shared<MockQLogger>(VantagePoint::Client);
1825 client->setQLogger(mockQLogger);
1826
1827 EXPECT_CALL(*mockQLogger, addConnectionMigrationUpdate(true)).Times(0);
1828 client->onNetworkSwitch(nullptr);
1829 client->closeNow(folly::none);
1830 }
1831
TEST_F(QuicClientTransportTest,onNetworkSwitchReplaceAfterHandshake)1832 TEST_F(QuicClientTransportTest, onNetworkSwitchReplaceAfterHandshake) {
1833 client->getNonConstConn().oneRttWriteCipher = test::createNoOpAead();
1834 auto mockQLogger = std::make_shared<MockQLogger>(VantagePoint::Client);
1835 client->setQLogger(mockQLogger);
1836
1837 auto newSocket = std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(
1838 eventbase_.get());
1839 auto newSocketPtr = newSocket.get();
1840 EXPECT_CALL(*sock, pauseRead());
1841 EXPECT_CALL(*sock, close());
1842 EXPECT_CALL(*newSocketPtr, bind(_, _));
1843 EXPECT_CALL(*newSocketPtr, close());
1844
1845 client->setQLogger(mockQLogger);
1846 EXPECT_CALL(*mockQLogger, addConnectionMigrationUpdate(true));
1847 client->onNetworkSwitch(std::move(newSocket));
1848
1849 client->closeNow(folly::none);
1850 }
1851
TEST_F(QuicClientTransportTest,onNetworkSwitchReplaceNoHandshake)1852 TEST_F(QuicClientTransportTest, onNetworkSwitchReplaceNoHandshake) {
1853 auto newSocket = std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(
1854 eventbase_.get());
1855 auto newSocketPtr = newSocket.get();
1856 auto mockQLogger = std::make_shared<MockQLogger>(VantagePoint::Client);
1857 EXPECT_CALL(*mockQLogger, addConnectionMigrationUpdate(true)).Times(0);
1858 EXPECT_CALL(*newSocketPtr, bind(_, _)).Times(0);
1859 client->onNetworkSwitch(std::move(newSocket));
1860 client->closeNow(folly::none);
1861 }
1862
TEST_F(QuicClientTransportTest,SocketClosedDuringOnTransportReady)1863 TEST_F(QuicClientTransportTest, SocketClosedDuringOnTransportReady) {
1864 class ConnectionCallbackThatWritesOnTransportReady
1865 : public QuicSocket::ConnectionCallback {
1866 public:
1867 explicit ConnectionCallbackThatWritesOnTransportReady(
1868 std::shared_ptr<QuicSocket> socket)
1869 : socket_(std::move(socket)) {}
1870
1871 void onTransportReady() noexcept override {
1872 socket_->close(folly::none);
1873 socket_.reset();
1874 onTransportReadyMock();
1875 }
1876
1877 GMOCK_METHOD1_(, noexcept, , onFlowControlUpdate, void(StreamId));
1878 GMOCK_METHOD1_(, noexcept, , onNewBidirectionalStream, void(StreamId));
1879 GMOCK_METHOD1_(, noexcept, , onNewUnidirectionalStream, void(StreamId));
1880 GMOCK_METHOD2_(
1881 ,
1882 noexcept,
1883 ,
1884 onStopSending,
1885 void(StreamId, ApplicationErrorCode));
1886 GMOCK_METHOD0_(, noexcept, , onTransportReadyMock, void());
1887 GMOCK_METHOD0_(, noexcept, , onReplaySafe, void());
1888 GMOCK_METHOD0_(, noexcept, , onConnectionEnd, void());
1889 void onConnectionSetupError(
1890 std::pair<quic::QuicErrorCode, std::string> error) noexcept override {
1891 onConnectionError(std::move(error));
1892 }
1893 GMOCK_METHOD1_(
1894 ,
1895 noexcept,
1896 ,
1897 onConnectionError,
1898 void(std::pair<QuicErrorCode, std::string>));
1899
1900 private:
1901 std::shared_ptr<QuicSocket> socket_;
1902 };
1903
1904 ConnectionCallbackThatWritesOnTransportReady callback(client);
1905 EXPECT_CALL(callback, onTransportReadyMock());
1906 EXPECT_CALL(callback, onReplaySafe()).Times(0);
1907 ON_CALL(*sock, write(_, _))
1908 .WillByDefault(Invoke(
1909 [&](const SocketAddress&, const std::unique_ptr<folly::IOBuf>& buf) {
1910 socketWrites.push_back(buf->clone());
1911 return buf->computeChainDataLength();
1912 }));
1913 ON_CALL(*sock, address()).WillByDefault(ReturnRef(serverAddr));
1914
1915 client->addNewPeerAddress(serverAddr);
1916 setupCryptoLayer();
1917 client->start(&callback);
1918 setConnectionIds();
1919 EXPECT_THROW(recvServerHello(), std::runtime_error);
1920 }
1921
TEST_F(QuicClientTransportTest,NetworkUnreachableIsFatalToConn)1922 TEST_F(QuicClientTransportTest, NetworkUnreachableIsFatalToConn) {
1923 client->addNewPeerAddress(serverAddr);
1924 setupCryptoLayer();
1925 EXPECT_CALL(clientConnCallback, onConnectionError(_));
1926 EXPECT_CALL(*sock, write(_, _)).WillOnce(SetErrnoAndReturn(ENETUNREACH, -1));
1927 client->start(&clientConnCallback);
1928 loopForWrites();
1929 }
1930
TEST_F(QuicClientTransportTest,HappyEyeballsWithSingleV4Address)1931 TEST_F(QuicClientTransportTest, HappyEyeballsWithSingleV4Address) {
1932 auto& conn = client->getConn();
1933
1934 client->setHappyEyeballsEnabled(true);
1935
1936 client->addNewPeerAddress(serverAddr);
1937 EXPECT_EQ(client->getConn().happyEyeballsState.v4PeerAddress, serverAddr);
1938
1939 setupCryptoLayer();
1940
1941 EXPECT_FALSE(conn.happyEyeballsState.finished);
1942 EXPECT_FALSE(conn.peerAddress.isInitialized());
1943 client->start(&clientConnCallback);
1944 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
1945 EXPECT_TRUE(conn.happyEyeballsState.finished);
1946 EXPECT_EQ(conn.peerAddress, serverAddr);
1947 }
1948
TEST_F(QuicClientTransportTest,HappyEyeballsWithSingleV6Address)1949 TEST_F(QuicClientTransportTest, HappyEyeballsWithSingleV6Address) {
1950 auto& conn = client->getConn();
1951
1952 client->setHappyEyeballsEnabled(true);
1953
1954 SocketAddress serverAddrV6{"::1", 443};
1955 client->addNewPeerAddress(serverAddrV6);
1956 EXPECT_EQ(client->getConn().happyEyeballsState.v6PeerAddress, serverAddrV6);
1957
1958 setupCryptoLayer();
1959
1960 EXPECT_FALSE(conn.happyEyeballsState.finished);
1961 EXPECT_FALSE(conn.peerAddress.isInitialized());
1962 client->start(&clientConnCallback);
1963 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
1964 EXPECT_TRUE(conn.happyEyeballsState.finished);
1965 EXPECT_EQ(conn.peerAddress, serverAddrV6);
1966 }
1967
TEST_F(QuicClientTransportTest,IdleTimerResetOnWritingFirstData)1968 TEST_F(QuicClientTransportTest, IdleTimerResetOnWritingFirstData) {
1969 client->addNewPeerAddress(serverAddr);
1970 setupCryptoLayer();
1971 client->start(&clientConnCallback);
1972 loopForWrites();
1973 ASSERT_FALSE(client->getConn().receivedNewPacketBeforeWrite);
1974 ASSERT_TRUE(client->idleTimeout().isScheduled());
1975 }
1976
TEST_F(QuicClientTransportTest,SetQLoggerDcid)1977 TEST_F(QuicClientTransportTest, SetQLoggerDcid) {
1978 client->setQLogger(nullptr);
1979 auto mockQLogger = std::make_shared<MockQLogger>(VantagePoint::Client);
1980
1981 EXPECT_CALL(
1982 *mockQLogger, setDcid(client->getConn().clientChosenDestConnectionId));
1983 client->setQLogger(mockQLogger);
1984 client->closeNow(folly::none);
1985 }
1986
TEST_F(QuicClientTransportTest,CheckQLoggerRefCount)1987 TEST_F(QuicClientTransportTest, CheckQLoggerRefCount) {
1988 auto mockQLogger1 = std::make_shared<MockQLogger>(VantagePoint::Client);
1989 auto mockQLogger2 = std::make_shared<MockQLogger>(VantagePoint::Client);
1990 EXPECT_CALL(
1991 *mockQLogger2, setDcid(client->getConn().clientChosenDestConnectionId))
1992 .Times(AtLeast(1));
1993
1994 // no-op
1995 client->setQLogger(nullptr);
1996 CHECK(client->getQLogger() == nullptr);
1997
1998 // set
1999 client->setQLogger(mockQLogger1);
2000 CHECK_EQ(client->getQLogger(), mockQLogger1);
2001 client->setQLogger(mockQLogger2);
2002 CHECK_EQ(client->getQLogger(), mockQLogger2);
2003
2004 // mix set and unset
2005 client->setQLogger(nullptr);
2006 CHECK_EQ(client->getQLogger(), mockQLogger2);
2007 client->setQLogger(mockQLogger1);
2008 CHECK_EQ(client->getQLogger(), mockQLogger1);
2009 client->setQLogger(nullptr);
2010 CHECK_EQ(client->getQLogger(), mockQLogger1);
2011
2012 // final unset
2013 client->setQLogger(nullptr);
2014 CHECK(client->getQLogger() == nullptr);
2015
2016 client->closeNow(folly::none);
2017 }
2018
TEST_F(QuicClientTransportTest,SwitchServerCidsNoOtherIds)2019 TEST_F(QuicClientTransportTest, SwitchServerCidsNoOtherIds) {
2020 auto originalCid =
2021 ConnectionIdData(ConnectionId(std::vector<uint8_t>{1, 2, 3, 4}), 2);
2022 auto& conn = client->getNonConstConn();
2023 conn.serverConnectionId = originalCid.connId;
2024
2025 conn.peerConnectionIds.push_back(originalCid);
2026 EXPECT_EQ(conn.retireAndSwitchPeerConnectionIds(), false);
2027 EXPECT_EQ(conn.pendingEvents.frames.size(), 0);
2028 EXPECT_EQ(conn.peerConnectionIds.size(), 1);
2029 client->closeNow(folly::none);
2030 }
2031
TEST_F(QuicClientTransportTest,SwitchServerCidsOneOtherCid)2032 TEST_F(QuicClientTransportTest, SwitchServerCidsOneOtherCid) {
2033 auto originalCid =
2034 ConnectionIdData(ConnectionId(std::vector<uint8_t>{1, 2, 3, 4}), 1);
2035 auto secondCid =
2036 ConnectionIdData(ConnectionId(std::vector<uint8_t>{5, 6, 7, 8}), 2);
2037
2038 auto& conn = client->getNonConstConn();
2039 conn.serverConnectionId = originalCid.connId;
2040
2041 conn.peerConnectionIds.push_back(originalCid);
2042 conn.peerConnectionIds.push_back(secondCid);
2043
2044 EXPECT_EQ(conn.retireAndSwitchPeerConnectionIds(), true);
2045 EXPECT_EQ(conn.peerConnectionIds.size(), 1);
2046
2047 EXPECT_EQ(conn.pendingEvents.frames.size(), 1);
2048 auto retireFrame = conn.pendingEvents.frames[0].asRetireConnectionIdFrame();
2049 EXPECT_EQ(retireFrame->sequenceNumber, 1);
2050
2051 auto replacedCid = conn.serverConnectionId;
2052 EXPECT_NE(originalCid.connId, *replacedCid);
2053 EXPECT_EQ(secondCid.connId, *replacedCid);
2054 client->closeNow(folly::none);
2055 }
2056
TEST_F(QuicClientTransportTest,SwitchServerCidsMultipleCids)2057 TEST_F(QuicClientTransportTest, SwitchServerCidsMultipleCids) {
2058 auto originalCid =
2059 ConnectionIdData(ConnectionId(std::vector<uint8_t>{1, 2, 3, 4}), 1);
2060 auto secondCid =
2061 ConnectionIdData(ConnectionId(std::vector<uint8_t>{5, 6, 7, 8}), 2);
2062 auto thirdCid =
2063 ConnectionIdData(ConnectionId(std::vector<uint8_t>{3, 3, 3, 3}), 3);
2064
2065 auto& conn = client->getNonConstConn();
2066 conn.serverConnectionId = originalCid.connId;
2067
2068 conn.peerConnectionIds.push_back(originalCid);
2069 conn.peerConnectionIds.push_back(secondCid);
2070 conn.peerConnectionIds.push_back(thirdCid);
2071
2072 EXPECT_EQ(conn.retireAndSwitchPeerConnectionIds(), true);
2073 EXPECT_EQ(conn.peerConnectionIds.size(), 2);
2074
2075 EXPECT_EQ(conn.pendingEvents.frames.size(), 1);
2076 auto retireFrame = conn.pendingEvents.frames[0].asRetireConnectionIdFrame();
2077 EXPECT_EQ(retireFrame->sequenceNumber, 1);
2078
2079 // Uses the first unused connection id.
2080 auto replacedCid = conn.serverConnectionId;
2081 EXPECT_NE(originalCid.connId, *replacedCid);
2082 EXPECT_EQ(secondCid.connId, *replacedCid);
2083 client->closeNow(folly::none);
2084 }
2085
2086 enum class ServerFirstPacketType : uint8_t { ServerHello, Retry };
2087
2088 class QuicClientTransportHappyEyeballsTest
2089 : public QuicClientTransportTest,
2090 public testing::WithParamInterface<ServerFirstPacketType> {
2091 public:
SetUpChild()2092 void SetUpChild() override {
2093 auto secondSocket =
2094 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(
2095 eventbase_.get());
2096 secondSock = secondSocket.get();
2097
2098 client->setHappyEyeballsEnabled(true);
2099 client->addNewPeerAddress(serverAddrV4);
2100 client->addNewPeerAddress(serverAddrV6);
2101 client->addNewSocket(std::move(secondSocket));
2102
2103 EXPECT_EQ(client->getConn().happyEyeballsState.v6PeerAddress, serverAddrV6);
2104 EXPECT_EQ(client->getConn().happyEyeballsState.v4PeerAddress, serverAddrV4);
2105
2106 setupCryptoLayer();
2107 }
2108
2109 protected:
setupInitialDcidForRetry()2110 void setupInitialDcidForRetry() {
2111 if (GetParam() == ServerFirstPacketType::Retry) {
2112 ConnectionId initialDstConnId(kInitialDstConnIdVecForRetryTest);
2113 client->getNonConstConn().originalDestinationConnectionId =
2114 initialDstConnId;
2115 }
2116 }
2117
firstWinBeforeSecondStart(const SocketAddress & firstAddress,const SocketAddress & secondAddress)2118 void firstWinBeforeSecondStart(
2119 const SocketAddress& firstAddress,
2120 const SocketAddress& secondAddress) {
2121 auto& conn = client->getConn();
2122 setupInitialDcidForRetry();
2123 auto firstPacketType = GetParam();
2124 EXPECT_CALL(*sock, write(firstAddress, _))
2125 .Times(AtLeast(1))
2126 .WillRepeatedly(Invoke([&](const SocketAddress&,
2127 const std::unique_ptr<folly::IOBuf>& buf) {
2128 socketWrites.push_back(buf->clone());
2129 return buf->computeChainDataLength();
2130 }));
2131 EXPECT_CALL(*secondSock, write(_, _)).Times(0);
2132 client->start(&clientConnCallback);
2133 setConnectionIds();
2134
2135 EXPECT_EQ(conn.peerAddress, firstAddress);
2136 EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
2137 EXPECT_TRUE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2138 EXPECT_EQ(socketWrites.size(), 1);
2139 EXPECT_TRUE(
2140 verifyLongHeader(*socketWrites.at(0), LongHeader::Types::Initial));
2141
2142 socketWrites.clear();
2143
2144 EXPECT_FALSE(conn.happyEyeballsState.finished);
2145 if (firstPacketType == ServerFirstPacketType::ServerHello) {
2146 EXPECT_CALL(clientConnCallback, onTransportReady());
2147 EXPECT_CALL(clientConnCallback, onReplaySafe());
2148 }
2149 EXPECT_CALL(*secondSock, write(_, _)).Times(0);
2150 EXPECT_CALL(*secondSock, pauseRead());
2151 EXPECT_CALL(*secondSock, close());
2152 if (firstPacketType == ServerFirstPacketType::Retry) {
2153 recvServerRetry(firstAddress);
2154 } else {
2155 performFakeHandshake(firstAddress);
2156 }
2157 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2158 EXPECT_TRUE(client->getConn().happyEyeballsState.finished);
2159 EXPECT_EQ(client->getConn().originalPeerAddress, firstAddress);
2160 EXPECT_EQ(client->getConn().peerAddress, firstAddress);
2161 }
2162
firstWinAfterSecondStart(const SocketAddress & firstAddress,const SocketAddress & secondAddress)2163 void firstWinAfterSecondStart(
2164 const SocketAddress& firstAddress,
2165 const SocketAddress& secondAddress) {
2166 auto& conn = client->getConn();
2167 auto firstPacketType = GetParam();
2168 setupInitialDcidForRetry();
2169
2170 EXPECT_CALL(*sock, write(firstAddress, _))
2171 .WillRepeatedly(Invoke([&](const SocketAddress&,
2172 const std::unique_ptr<folly::IOBuf>& buf) {
2173 socketWrites.push_back(buf->clone());
2174 return buf->computeChainDataLength();
2175 }));
2176 EXPECT_CALL(*secondSock, write(_, _)).Times(0);
2177 client->start(&clientConnCallback);
2178 setConnectionIds();
2179
2180 EXPECT_EQ(conn.peerAddress, firstAddress);
2181 EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
2182 EXPECT_TRUE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2183 EXPECT_EQ(socketWrites.size(), 1);
2184 EXPECT_TRUE(
2185 verifyLongHeader(*socketWrites.at(0), LongHeader::Types::Initial));
2186
2187 socketWrites.clear();
2188
2189 // Manually expire conn attempt timeout
2190 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2191 client->happyEyeballsConnAttemptDelayTimeout().cancelTimeout();
2192 client->happyEyeballsConnAttemptDelayTimeout().timeoutExpired();
2193 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2194 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2195
2196 // Manually expire loss timeout to trigger write to both first and second
2197 // socket
2198 EXPECT_CALL(*sock, write(firstAddress, _))
2199 .WillOnce(Invoke([&](const SocketAddress&,
2200 const std::unique_ptr<folly::IOBuf>& buf) {
2201 socketWrites.push_back(buf->clone());
2202 return buf->computeChainDataLength();
2203 }));
2204 EXPECT_CALL(*secondSock, write(secondAddress, _));
2205 client->lossTimeout().cancelTimeout();
2206 client->lossTimeout().timeoutExpired();
2207 EXPECT_EQ(socketWrites.size(), 1);
2208 EXPECT_TRUE(
2209 verifyLongHeader(*socketWrites.at(0), LongHeader::Types::Initial));
2210
2211 socketWrites.clear();
2212 EXPECT_FALSE(conn.happyEyeballsState.finished);
2213 if (firstPacketType == ServerFirstPacketType::ServerHello) {
2214 EXPECT_CALL(clientConnCallback, onTransportReady());
2215 EXPECT_CALL(clientConnCallback, onReplaySafe());
2216 }
2217 EXPECT_CALL(*sock, write(firstAddress, _))
2218 .Times(AtLeast(1))
2219 .WillRepeatedly(Invoke([&](const SocketAddress&,
2220 const std::unique_ptr<folly::IOBuf>& buf) {
2221 socketWrites.push_back(buf->clone());
2222 return buf->computeChainDataLength();
2223 }));
2224 EXPECT_CALL(*secondSock, write(_, _)).Times(0);
2225 EXPECT_CALL(*secondSock, pauseRead());
2226 EXPECT_CALL(*secondSock, close());
2227 if (firstPacketType == ServerFirstPacketType::Retry) {
2228 recvServerRetry(firstAddress);
2229 } else {
2230 performFakeHandshake(firstAddress);
2231 }
2232 EXPECT_TRUE(client->getConn().happyEyeballsState.finished);
2233 EXPECT_FALSE(
2234 client->getConn().happyEyeballsState.shouldWriteToSecondSocket);
2235 EXPECT_EQ(client->getConn().originalPeerAddress, firstAddress);
2236 EXPECT_EQ(client->getConn().peerAddress, firstAddress);
2237 }
2238
secondWin(const SocketAddress & firstAddress,const SocketAddress & secondAddress)2239 void secondWin(
2240 const SocketAddress& firstAddress,
2241 const SocketAddress& secondAddress) {
2242 auto& conn = client->getConn();
2243 auto firstPacketType = GetParam();
2244 setupInitialDcidForRetry();
2245
2246 EXPECT_CALL(*sock, write(firstAddress, _))
2247 .WillRepeatedly(Invoke([&](const SocketAddress&,
2248 const std::unique_ptr<folly::IOBuf>& buf) {
2249 socketWrites.push_back(buf->clone());
2250 return buf->computeChainDataLength();
2251 }));
2252 EXPECT_CALL(*secondSock, write(_, _)).Times(0);
2253 client->start(&clientConnCallback);
2254 setConnectionIds();
2255 EXPECT_EQ(conn.peerAddress, firstAddress);
2256 EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
2257 EXPECT_TRUE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2258 EXPECT_EQ(socketWrites.size(), 1);
2259
2260 EXPECT_TRUE(
2261 verifyLongHeader(*socketWrites.at(0), LongHeader::Types::Initial));
2262
2263 socketWrites.clear();
2264
2265 // Manually expire conn attempt timeout
2266 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2267 client->happyEyeballsConnAttemptDelayTimeout().cancelTimeout();
2268 client->happyEyeballsConnAttemptDelayTimeout().timeoutExpired();
2269 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2270 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2271
2272 // Manually expire loss timeout to trigger write to both first and second
2273 // socket
2274 EXPECT_CALL(*sock, write(firstAddress, _));
2275 EXPECT_CALL(*secondSock, write(secondAddress, _))
2276 .WillOnce(Invoke([&](const SocketAddress&,
2277 const std::unique_ptr<folly::IOBuf>& buf) {
2278 socketWrites.push_back(buf->clone());
2279 return buf->computeChainDataLength();
2280 }));
2281 client->lossTimeout().cancelTimeout();
2282 client->lossTimeout().timeoutExpired();
2283 EXPECT_EQ(socketWrites.size(), 1);
2284 EXPECT_TRUE(
2285 verifyLongHeader(*socketWrites.at(0), LongHeader::Types::Initial));
2286
2287 socketWrites.clear();
2288
2289 EXPECT_FALSE(conn.happyEyeballsState.finished);
2290 if (firstPacketType == ServerFirstPacketType::ServerHello) {
2291 EXPECT_CALL(clientConnCallback, onTransportReady());
2292 EXPECT_CALL(clientConnCallback, onReplaySafe());
2293 }
2294 EXPECT_CALL(*sock, write(_, _)).Times(0);
2295 EXPECT_CALL(*sock, pauseRead());
2296 EXPECT_CALL(*sock, close());
2297 EXPECT_CALL(*secondSock, write(secondAddress, _))
2298 .Times(AtLeast(1))
2299 .WillRepeatedly(Invoke([&](const SocketAddress&,
2300 const std::unique_ptr<folly::IOBuf>& buf) {
2301 socketWrites.push_back(buf->clone());
2302 return buf->computeChainDataLength();
2303 }));
2304 if (firstPacketType == ServerFirstPacketType::Retry) {
2305 recvServerRetry(secondAddress);
2306 } else {
2307 performFakeHandshake(secondAddress);
2308 }
2309 EXPECT_TRUE(client->getConn().happyEyeballsState.finished);
2310 EXPECT_FALSE(
2311 client->getConn().happyEyeballsState.shouldWriteToSecondSocket);
2312 EXPECT_EQ(client->getConn().originalPeerAddress, secondAddress);
2313 EXPECT_EQ(client->getConn().peerAddress, secondAddress);
2314 }
2315
secondBindFailure(const SocketAddress & firstAddress,const SocketAddress & secondAddress)2316 void secondBindFailure(
2317 const SocketAddress& firstAddress,
2318 const SocketAddress& secondAddress) {
2319 auto& conn = client->getConn();
2320 setupInitialDcidForRetry();
2321
2322 EXPECT_CALL(*sock, write(firstAddress, _));
2323 EXPECT_CALL(*secondSock, bind(_, _))
2324 .WillOnce(Invoke(
2325 [](const folly::SocketAddress&, auto) { throw std::exception(); }));
2326 client->start(&clientConnCallback);
2327 EXPECT_EQ(conn.peerAddress, firstAddress);
2328 EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
2329 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2330 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2331 EXPECT_TRUE(conn.happyEyeballsState.finished);
2332 }
2333
nonFatalWriteErrorOnFirstBeforeSecondStarts(const SocketAddress & firstAddress,const SocketAddress & secondAddress)2334 void nonFatalWriteErrorOnFirstBeforeSecondStarts(
2335 const SocketAddress& firstAddress,
2336 const SocketAddress& secondAddress) {
2337 auto& conn = client->getConn();
2338 TransportSettings settings;
2339 client->setTransportSettings(settings);
2340 EXPECT_CALL(*sock, write(firstAddress, _))
2341 .WillOnce(SetErrnoAndReturn(EAGAIN, -1));
2342 EXPECT_CALL(*secondSock, write(_, _));
2343 client->start(&clientConnCallback);
2344 EXPECT_EQ(conn.peerAddress, firstAddress);
2345 EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
2346 // Continue trying first socket
2347 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToFirstSocket);
2348 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2349 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2350
2351 EXPECT_CALL(*sock, write(firstAddress, _));
2352 EXPECT_CALL(*secondSock, write(secondAddress, _));
2353 client->lossTimeout().cancelTimeout();
2354 client->lossTimeout().timeoutExpired();
2355 }
2356
fatalWriteErrorOnFirstBeforeSecondStarts(const SocketAddress & firstAddress,const SocketAddress & secondAddress)2357 void fatalWriteErrorOnFirstBeforeSecondStarts(
2358 const SocketAddress& firstAddress,
2359 const SocketAddress& secondAddress) {
2360 auto& conn = client->getConn();
2361 EXPECT_CALL(*sock, write(firstAddress, _))
2362 .WillOnce(SetErrnoAndReturn(EBADF, -1));
2363 // Socket is paused read once during happy eyeballs
2364 // Socket is paused read for the second time when QuicClientTransport dies
2365 EXPECT_CALL(*sock, pauseRead()).Times(2);
2366 EXPECT_CALL(*sock, close()).Times(1);
2367 EXPECT_CALL(*secondSock, write(_, _));
2368 client->start(&clientConnCallback);
2369 EXPECT_EQ(conn.peerAddress, firstAddress);
2370 EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
2371 // Give up first socket
2372 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToFirstSocket);
2373 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2374 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2375
2376 EXPECT_CALL(*sock, write(_, _)).Times(0);
2377 EXPECT_CALL(*secondSock, write(secondAddress, _));
2378 client->lossTimeout().cancelTimeout();
2379 client->lossTimeout().timeoutExpired();
2380 }
2381
fatalReadErrorOnFirstBeforeSecondStarts(FOLLY_MAYBE_UNUSED const SocketAddress & firstAddress,FOLLY_MAYBE_UNUSED const SocketAddress & secondAddress)2382 void fatalReadErrorOnFirstBeforeSecondStarts(
2383 FOLLY_MAYBE_UNUSED const SocketAddress& firstAddress,
2384 FOLLY_MAYBE_UNUSED const SocketAddress& secondAddress) {
2385 #ifdef FOLLY_HAVE_MSG_ERRQUEUE
2386 auto& conn = client->getConn();
2387 EXPECT_CALL(*sock, write(firstAddress, _));
2388 // Socket is paused read once during happy eyeballs
2389 // Socket is paused read for the second time when QuicClientTransport dies
2390 EXPECT_CALL(*sock, pauseRead()).Times(2);
2391 EXPECT_CALL(*sock, close()).Times(1);
2392 client->start(&clientConnCallback);
2393 EXPECT_EQ(conn.peerAddress, firstAddress);
2394 EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
2395 // Give up first socket
2396 union {
2397 struct cmsghdr hdr;
2398 unsigned char buf[CMSG_SPACE(sizeof(sock_extended_err))];
2399 } cmsgbuf;
2400 cmsgbuf.hdr.cmsg_level = SOL_IPV6;
2401 cmsgbuf.hdr.cmsg_type = IPV6_RECVERR;
2402 struct sock_extended_err err {};
2403 err.ee_errno = EBADF;
2404 auto dest = (struct sock_extended_err*)CMSG_DATA(&cmsgbuf.hdr);
2405 *dest = err;
2406 client->errMessage(cmsgbuf.hdr);
2407 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToFirstSocket);
2408 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2409 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2410
2411 EXPECT_CALL(*sock, write(_, _)).Times(0);
2412 EXPECT_CALL(*secondSock, write(secondAddress, _));
2413 client->lossTimeout().cancelTimeout();
2414 client->lossTimeout().timeoutExpired();
2415 #endif
2416 }
2417
nonFatalWriteErrorOnFirstAfterSecondStarts(const SocketAddress & firstAddress,const SocketAddress & secondAddress)2418 void nonFatalWriteErrorOnFirstAfterSecondStarts(
2419 const SocketAddress& firstAddress,
2420 const SocketAddress& secondAddress) {
2421 auto& conn = client->getConn();
2422
2423 EXPECT_CALL(*sock, write(firstAddress, _));
2424 EXPECT_CALL(*secondSock, write(_, _)).Times(0);
2425 client->start(&clientConnCallback);
2426 EXPECT_EQ(conn.peerAddress, firstAddress);
2427 EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
2428 EXPECT_TRUE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2429
2430 // Manually expire conn attempt timeout
2431 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2432 client->happyEyeballsConnAttemptDelayTimeout().cancelTimeout();
2433 client->happyEyeballsConnAttemptDelayTimeout().timeoutExpired();
2434 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2435 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2436
2437 // Manually expire loss timeout to trigger write to both first and second
2438 // socket
2439 EXPECT_CALL(*sock, write(firstAddress, _))
2440 .WillOnce(SetErrnoAndReturn(EAGAIN, -1));
2441 EXPECT_CALL(*secondSock, write(secondAddress, _));
2442 client->lossTimeout().cancelTimeout();
2443 client->lossTimeout().timeoutExpired();
2444
2445 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToFirstSocket);
2446 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2447
2448 EXPECT_CALL(*sock, write(firstAddress, _)).Times(1);
2449 EXPECT_CALL(*secondSock, write(secondAddress, _)).Times(1);
2450 client->lossTimeout().cancelTimeout();
2451 client->lossTimeout().timeoutExpired();
2452 }
2453
fatalWriteErrorOnFirstAfterSecondStarts(const SocketAddress & firstAddress,const SocketAddress & secondAddress)2454 void fatalWriteErrorOnFirstAfterSecondStarts(
2455 const SocketAddress& firstAddress,
2456 const SocketAddress& secondAddress) {
2457 auto& conn = client->getConn();
2458
2459 EXPECT_CALL(*sock, write(firstAddress, _));
2460 EXPECT_CALL(*secondSock, write(_, _)).Times(0);
2461 client->start(&clientConnCallback);
2462 EXPECT_EQ(conn.peerAddress, firstAddress);
2463 EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
2464 EXPECT_TRUE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2465
2466 // Manually expire conn attempt timeout
2467 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2468 client->happyEyeballsConnAttemptDelayTimeout().cancelTimeout();
2469 client->happyEyeballsConnAttemptDelayTimeout().timeoutExpired();
2470 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2471 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2472
2473 // Manually expire loss timeout to trigger write to both first and second
2474 // socket
2475 EXPECT_CALL(*sock, write(firstAddress, _))
2476 .WillOnce(SetErrnoAndReturn(EBADF, -1));
2477 // Socket is paused read once during happy eyeballs
2478 // Socket is paused read for the second time when QuicClientTransport dies
2479 EXPECT_CALL(*sock, pauseRead()).Times(2);
2480 EXPECT_CALL(*sock, close()).Times(1);
2481 EXPECT_CALL(*secondSock, write(secondAddress, _));
2482 client->lossTimeout().cancelTimeout();
2483 client->lossTimeout().timeoutExpired();
2484
2485 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToFirstSocket);
2486 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2487
2488 EXPECT_CALL(*sock, write(_, _)).Times(0);
2489 EXPECT_CALL(*secondSock, write(secondAddress, _)).Times(1);
2490 client->lossTimeout().cancelTimeout();
2491 client->lossTimeout().timeoutExpired();
2492 }
2493
fatalReadErrorOnFirstAfterSecondStarts(FOLLY_MAYBE_UNUSED const SocketAddress & firstAddress,FOLLY_MAYBE_UNUSED const SocketAddress & secondAddress)2494 void fatalReadErrorOnFirstAfterSecondStarts(
2495 FOLLY_MAYBE_UNUSED const SocketAddress& firstAddress,
2496 FOLLY_MAYBE_UNUSED const SocketAddress& secondAddress) {
2497 #ifdef FOLLY_HAVE_MSG_ERRQUEUE
2498 auto& conn = client->getConn();
2499
2500 EXPECT_CALL(*sock, write(firstAddress, _));
2501 EXPECT_CALL(*secondSock, write(_, _)).Times(0);
2502 client->start(&clientConnCallback);
2503 EXPECT_EQ(conn.peerAddress, firstAddress);
2504 EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
2505 EXPECT_TRUE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2506
2507 // Manually expire conn attempt timeout
2508 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2509 client->happyEyeballsConnAttemptDelayTimeout().cancelTimeout();
2510 client->happyEyeballsConnAttemptDelayTimeout().timeoutExpired();
2511 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2512 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2513
2514 EXPECT_CALL(*sock, pauseRead()).Times(2);
2515 EXPECT_CALL(*sock, close()).Times(1);
2516
2517 union {
2518 struct cmsghdr hdr;
2519 unsigned char buf[CMSG_SPACE(sizeof(sock_extended_err))];
2520 } cmsgbuf;
2521 cmsgbuf.hdr.cmsg_level = SOL_IPV6;
2522 cmsgbuf.hdr.cmsg_type = IPV6_RECVERR;
2523 struct sock_extended_err err {};
2524 err.ee_errno = EBADF;
2525 auto dest = (struct sock_extended_err*)CMSG_DATA(&cmsgbuf.hdr);
2526 *dest = err;
2527 client->errMessage(cmsgbuf.hdr);
2528
2529 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToFirstSocket);
2530 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2531
2532 EXPECT_CALL(*sock, write(_, _)).Times(0);
2533 EXPECT_CALL(*secondSock, write(secondAddress, _)).Times(1);
2534 client->lossTimeout().cancelTimeout();
2535 client->lossTimeout().timeoutExpired();
2536 #endif
2537 }
2538
nonFatalWriteErrorOnSecondAfterSecondStarts(const SocketAddress & firstAddress,const SocketAddress & secondAddress)2539 void nonFatalWriteErrorOnSecondAfterSecondStarts(
2540 const SocketAddress& firstAddress,
2541 const SocketAddress& secondAddress) {
2542 auto& conn = client->getConn();
2543
2544 EXPECT_CALL(*sock, write(firstAddress, _));
2545 EXPECT_CALL(*secondSock, write(_, _)).Times(0);
2546 client->start(&clientConnCallback);
2547 EXPECT_EQ(conn.peerAddress, firstAddress);
2548 EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
2549 EXPECT_TRUE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2550
2551 // Manually expire conn attempt timeout
2552 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2553 client->happyEyeballsConnAttemptDelayTimeout().cancelTimeout();
2554 client->happyEyeballsConnAttemptDelayTimeout().timeoutExpired();
2555 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2556 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2557
2558 // Manually expire loss timeout to trigger write to both first and second
2559 // socket
2560 EXPECT_CALL(*sock, write(firstAddress, _));
2561 EXPECT_CALL(*secondSock, write(secondAddress, _))
2562 .WillOnce(SetErrnoAndReturn(EAGAIN, -1));
2563 client->lossTimeout().cancelTimeout();
2564 client->lossTimeout().timeoutExpired();
2565
2566 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToFirstSocket);
2567 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2568
2569 EXPECT_CALL(*sock, write(firstAddress, _)).Times(1);
2570 EXPECT_CALL(*secondSock, write(secondAddress, _)).Times(1);
2571 client->lossTimeout().cancelTimeout();
2572 client->lossTimeout().timeoutExpired();
2573 }
2574
fatalWriteErrorOnSecondAfterSecondStarts(const SocketAddress & firstAddress,const SocketAddress & secondAddress)2575 void fatalWriteErrorOnSecondAfterSecondStarts(
2576 const SocketAddress& firstAddress,
2577 const SocketAddress& secondAddress) {
2578 auto& conn = client->getConn();
2579
2580 EXPECT_CALL(*sock, write(firstAddress, _));
2581 EXPECT_CALL(*secondSock, write(_, _)).Times(0);
2582 client->start(&clientConnCallback);
2583 EXPECT_EQ(conn.peerAddress, firstAddress);
2584 EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
2585 EXPECT_TRUE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2586
2587 // Manually expire conn attempt timeout
2588 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2589 client->happyEyeballsConnAttemptDelayTimeout().cancelTimeout();
2590 client->happyEyeballsConnAttemptDelayTimeout().timeoutExpired();
2591 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2592 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2593
2594 // Manually expire loss timeout to trigger write to both first and second
2595 // socket
2596 EXPECT_CALL(*sock, write(firstAddress, _));
2597 EXPECT_CALL(*secondSock, write(secondAddress, _))
2598 .WillOnce(SetErrnoAndReturn(EBADF, -1));
2599 // Socket is paused read once during happy eyeballs
2600 // Socket is paused read for the second time when QuicClientTransport dies
2601 EXPECT_CALL(*secondSock, pauseRead()).Times(2);
2602 EXPECT_CALL(*secondSock, close()).Times(1);
2603 client->lossTimeout().cancelTimeout();
2604 client->lossTimeout().timeoutExpired();
2605
2606 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToFirstSocket);
2607 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2608
2609 EXPECT_CALL(*sock, write(firstAddress, _)).Times(1);
2610 EXPECT_CALL(*secondSock, write(_, _)).Times(0);
2611 client->lossTimeout().cancelTimeout();
2612 client->lossTimeout().timeoutExpired();
2613 }
2614
fatalReadErrorOnSecondAfterSecondStarts(FOLLY_MAYBE_UNUSED const SocketAddress & firstAddress,FOLLY_MAYBE_UNUSED const SocketAddress & secondAddress)2615 void fatalReadErrorOnSecondAfterSecondStarts(
2616 FOLLY_MAYBE_UNUSED const SocketAddress& firstAddress,
2617 FOLLY_MAYBE_UNUSED const SocketAddress& secondAddress) {
2618 #ifdef FOLLY_HAVE_MSG_ERRQUEUE
2619 auto& conn = client->getConn();
2620
2621 EXPECT_CALL(*sock, write(firstAddress, _));
2622 EXPECT_CALL(*secondSock, write(_, _)).Times(0);
2623 client->start(&clientConnCallback);
2624 EXPECT_EQ(conn.peerAddress, firstAddress);
2625 EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
2626 EXPECT_TRUE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2627
2628 // Manually expire conn attempt timeout
2629 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2630 client->happyEyeballsConnAttemptDelayTimeout().cancelTimeout();
2631 client->happyEyeballsConnAttemptDelayTimeout().timeoutExpired();
2632 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2633 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2634
2635 // Manually expire loss timeout to trigger write to both first and second
2636 // socket
2637 EXPECT_CALL(*sock, write(firstAddress, _));
2638 union {
2639 struct cmsghdr hdr;
2640 unsigned char buf[CMSG_SPACE(sizeof(sock_extended_err))];
2641 } cmsgbuf;
2642 cmsgbuf.hdr.cmsg_level = SOL_IP;
2643 cmsgbuf.hdr.cmsg_type = IP_RECVERR;
2644 struct sock_extended_err err {};
2645 err.ee_errno = EBADF;
2646 auto dest = (struct sock_extended_err*)CMSG_DATA(&cmsgbuf.hdr);
2647 *dest = err;
2648 client->errMessage(cmsgbuf.hdr);
2649 // Socket is paused read once during happy eyeballs
2650 EXPECT_CALL(*secondSock, pauseRead()).Times(1);
2651 EXPECT_CALL(*secondSock, close()).Times(1);
2652 client->lossTimeout().cancelTimeout();
2653 client->lossTimeout().timeoutExpired();
2654
2655 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToFirstSocket);
2656 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2657
2658 EXPECT_CALL(*sock, write(firstAddress, _)).Times(1);
2659 EXPECT_CALL(*secondSock, write(_, _)).Times(0);
2660 client->lossTimeout().cancelTimeout();
2661 client->lossTimeout().timeoutExpired();
2662 #endif
2663 }
2664
nonFatalWriteErrorOnBothAfterSecondStarts(const SocketAddress & firstAddress,const SocketAddress & secondAddress)2665 void nonFatalWriteErrorOnBothAfterSecondStarts(
2666 const SocketAddress& firstAddress,
2667 const SocketAddress& secondAddress) {
2668 auto& conn = client->getConn();
2669
2670 EXPECT_CALL(*sock, write(firstAddress, _));
2671 EXPECT_CALL(*secondSock, write(_, _)).Times(0);
2672 client->start(&clientConnCallback);
2673 EXPECT_EQ(conn.peerAddress, firstAddress);
2674 EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
2675 EXPECT_TRUE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2676
2677 // Manually expire conn attempt timeout
2678 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2679 client->happyEyeballsConnAttemptDelayTimeout().cancelTimeout();
2680 client->happyEyeballsConnAttemptDelayTimeout().timeoutExpired();
2681 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2682 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2683
2684 // Manually expire loss timeout to trigger write to both first and second
2685 // socket
2686 EXPECT_CALL(*sock, write(firstAddress, _))
2687 .WillOnce(SetErrnoAndReturn(EAGAIN, -1));
2688 EXPECT_CALL(*secondSock, write(secondAddress, _))
2689 .WillOnce(SetErrnoAndReturn(EAGAIN, -1));
2690 client->lossTimeout().cancelTimeout();
2691 client->lossTimeout().timeoutExpired();
2692
2693 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToFirstSocket);
2694 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2695
2696 EXPECT_CALL(*sock, write(firstAddress, _)).Times(1);
2697 EXPECT_CALL(*secondSock, write(secondAddress, _)).Times(1);
2698 client->lossTimeout().cancelTimeout();
2699 client->lossTimeout().timeoutExpired();
2700 }
2701
fatalWriteErrorOnBothAfterSecondStarts(const SocketAddress & firstAddress,const SocketAddress & secondAddress)2702 void fatalWriteErrorOnBothAfterSecondStarts(
2703 const SocketAddress& firstAddress,
2704 const SocketAddress& secondAddress) {
2705 auto& conn = client->getConn();
2706
2707 EXPECT_CALL(*sock, write(firstAddress, _));
2708 EXPECT_CALL(*secondSock, write(_, _)).Times(0);
2709 client->start(&clientConnCallback);
2710 EXPECT_EQ(conn.peerAddress, firstAddress);
2711 EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
2712 EXPECT_TRUE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2713
2714 // Manually expire conn attempt timeout
2715 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2716 client->happyEyeballsConnAttemptDelayTimeout().cancelTimeout();
2717 client->happyEyeballsConnAttemptDelayTimeout().timeoutExpired();
2718 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2719 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2720
2721 // Manually expire loss timeout to trigger write to both first and second
2722 // socket
2723 EXPECT_CALL(*sock, write(firstAddress, _))
2724 .WillOnce(SetErrnoAndReturn(EBADF, -1));
2725 EXPECT_CALL(*secondSock, write(secondAddress, _))
2726 .WillOnce(SetErrnoAndReturn(EBADF, -1));
2727 EXPECT_CALL(clientConnCallback, onConnectionError(_));
2728 client->lossTimeout().cancelTimeout();
2729 client->lossTimeout().timeoutExpired();
2730
2731 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToFirstSocket);
2732 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2733 }
2734
fatalReadErrorOnBothAfterSecondStarts(FOLLY_MAYBE_UNUSED const SocketAddress & firstAddress,FOLLY_MAYBE_UNUSED const SocketAddress & secondAddress)2735 void fatalReadErrorOnBothAfterSecondStarts(
2736 FOLLY_MAYBE_UNUSED const SocketAddress& firstAddress,
2737 FOLLY_MAYBE_UNUSED const SocketAddress& secondAddress) {
2738 #ifdef FOLLY_HAVE_MSG_ERRQUEUE
2739 auto& conn = client->getConn();
2740
2741 EXPECT_CALL(*sock, write(firstAddress, _));
2742 EXPECT_CALL(*secondSock, write(_, _)).Times(0);
2743 client->start(&clientConnCallback);
2744 EXPECT_EQ(conn.peerAddress, firstAddress);
2745 EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
2746 EXPECT_TRUE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2747
2748 // Manually expire conn attempt timeout
2749 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2750 client->happyEyeballsConnAttemptDelayTimeout().cancelTimeout();
2751 client->happyEyeballsConnAttemptDelayTimeout().timeoutExpired();
2752 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2753 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
2754
2755 union {
2756 struct cmsghdr hdr;
2757 unsigned char buf[CMSG_SPACE(sizeof(sock_extended_err))];
2758 } cmsgbuf;
2759 cmsgbuf.hdr.cmsg_level = SOL_IP;
2760 cmsgbuf.hdr.cmsg_type = IP_RECVERR;
2761 struct sock_extended_err err {};
2762 err.ee_errno = EBADF;
2763 auto dest = (struct sock_extended_err*)CMSG_DATA(&cmsgbuf.hdr);
2764 *dest = err;
2765 client->errMessage(cmsgbuf.hdr);
2766 cmsgbuf.hdr.cmsg_level = SOL_IPV6;
2767 cmsgbuf.hdr.cmsg_type = IPV6_RECVERR;
2768 client->errMessage(cmsgbuf.hdr);
2769
2770 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToFirstSocket);
2771 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
2772 #endif
2773 }
2774
2775 protected:
2776 folly::test::MockAsyncUDPSocket* secondSock;
2777 SocketAddress serverAddrV4{"127.0.0.1", 443};
2778 SocketAddress serverAddrV6{"::1", 443};
2779 };
2780
2781 INSTANTIATE_TEST_CASE_P(
2782 QuicClientTransportHappyEyeballsTests,
2783 QuicClientTransportHappyEyeballsTest,
2784 ::testing::Values(
2785 ServerFirstPacketType::ServerHello,
2786 ServerFirstPacketType::Retry));
2787
TEST_P(QuicClientTransportHappyEyeballsTest,V6FirstAndV6WinBeforeV4Start)2788 TEST_P(QuicClientTransportHappyEyeballsTest, V6FirstAndV6WinBeforeV4Start) {
2789 firstWinBeforeSecondStart(serverAddrV6, serverAddrV4);
2790 }
2791
TEST_P(QuicClientTransportHappyEyeballsTest,V6FirstAndV6WinAfterV4Start)2792 TEST_P(QuicClientTransportHappyEyeballsTest, V6FirstAndV6WinAfterV4Start) {
2793 firstWinAfterSecondStart(serverAddrV6, serverAddrV4);
2794 }
2795
TEST_P(QuicClientTransportHappyEyeballsTest,V6FirstAndV4Win)2796 TEST_P(QuicClientTransportHappyEyeballsTest, V6FirstAndV4Win) {
2797 secondWin(serverAddrV6, serverAddrV4);
2798 }
2799
TEST_P(QuicClientTransportHappyEyeballsTest,V6FirstAndV4BindFailure)2800 TEST_P(QuicClientTransportHappyEyeballsTest, V6FirstAndV4BindFailure) {
2801 secondBindFailure(serverAddrV6, serverAddrV4);
2802 }
2803
TEST_F(QuicClientTransportHappyEyeballsTest,V6FirstAndV6NonFatalErrorBeforeV4Starts)2804 TEST_F(
2805 QuicClientTransportHappyEyeballsTest,
2806 V6FirstAndV6NonFatalErrorBeforeV4Starts) {
2807 nonFatalWriteErrorOnFirstBeforeSecondStarts(serverAddrV6, serverAddrV4);
2808 }
2809
TEST_F(QuicClientTransportHappyEyeballsTest,V6FirstAndV6FatalErrorBeforeV4Start)2810 TEST_F(
2811 QuicClientTransportHappyEyeballsTest,
2812 V6FirstAndV6FatalErrorBeforeV4Start) {
2813 fatalWriteErrorOnFirstBeforeSecondStarts(serverAddrV6, serverAddrV4);
2814 }
2815
TEST_F(QuicClientTransportHappyEyeballsTest,V6FirstAndV6FatalReadErrorBeforeV4Start)2816 TEST_F(
2817 QuicClientTransportHappyEyeballsTest,
2818 V6FirstAndV6FatalReadErrorBeforeV4Start) {
2819 fatalReadErrorOnFirstBeforeSecondStarts(serverAddrV6, serverAddrV4);
2820 }
2821
TEST_F(QuicClientTransportHappyEyeballsTest,V6FirstAndV6NonFatalErrorAfterV4Starts)2822 TEST_F(
2823 QuicClientTransportHappyEyeballsTest,
2824 V6FirstAndV6NonFatalErrorAfterV4Starts) {
2825 nonFatalWriteErrorOnFirstAfterSecondStarts(serverAddrV6, serverAddrV4);
2826 }
2827
TEST_F(QuicClientTransportHappyEyeballsTest,V6FirstAndV6FatalErrorAfterV4Start)2828 TEST_F(
2829 QuicClientTransportHappyEyeballsTest,
2830 V6FirstAndV6FatalErrorAfterV4Start) {
2831 fatalWriteErrorOnFirstAfterSecondStarts(serverAddrV6, serverAddrV4);
2832 }
2833
TEST_F(QuicClientTransportHappyEyeballsTest,V6FirstAndV6FatalReadErrorAfterV4Start)2834 TEST_F(
2835 QuicClientTransportHappyEyeballsTest,
2836 V6FirstAndV6FatalReadErrorAfterV4Start) {
2837 fatalReadErrorOnFirstAfterSecondStarts(serverAddrV6, serverAddrV4);
2838 }
2839
TEST_F(QuicClientTransportHappyEyeballsTest,V6FirstAndV4NonFatalErrorAfterV4Start)2840 TEST_F(
2841 QuicClientTransportHappyEyeballsTest,
2842 V6FirstAndV4NonFatalErrorAfterV4Start) {
2843 nonFatalWriteErrorOnSecondAfterSecondStarts(serverAddrV6, serverAddrV4);
2844 }
2845
TEST_F(QuicClientTransportHappyEyeballsTest,V6FirstAndV4FatalErrorAfterV4Start)2846 TEST_F(
2847 QuicClientTransportHappyEyeballsTest,
2848 V6FirstAndV4FatalErrorAfterV4Start) {
2849 fatalWriteErrorOnSecondAfterSecondStarts(serverAddrV6, serverAddrV4);
2850 }
2851
TEST_F(QuicClientTransportHappyEyeballsTest,V6FirstAndV4FatalReadErrorAfterV4Start)2852 TEST_F(
2853 QuicClientTransportHappyEyeballsTest,
2854 V6FirstAndV4FatalReadErrorAfterV4Start) {
2855 fatalReadErrorOnSecondAfterSecondStarts(serverAddrV6, serverAddrV4);
2856 }
2857
TEST_F(QuicClientTransportHappyEyeballsTest,V6FirstAndBothNonFatalErrorAfterV4Start)2858 TEST_F(
2859 QuicClientTransportHappyEyeballsTest,
2860 V6FirstAndBothNonFatalErrorAfterV4Start) {
2861 nonFatalWriteErrorOnBothAfterSecondStarts(serverAddrV6, serverAddrV4);
2862 }
2863
TEST_F(QuicClientTransportHappyEyeballsTest,V6FirstAndBothFatalErrorAfterV4Start)2864 TEST_F(
2865 QuicClientTransportHappyEyeballsTest,
2866 V6FirstAndBothFatalErrorAfterV4Start) {
2867 fatalWriteErrorOnBothAfterSecondStarts(serverAddrV6, serverAddrV4);
2868 }
2869
TEST_F(QuicClientTransportHappyEyeballsTest,V6FirstAndBothFatalReadErrorAfterV4Start)2870 TEST_F(
2871 QuicClientTransportHappyEyeballsTest,
2872 V6FirstAndBothFatalReadErrorAfterV4Start) {
2873 fatalReadErrorOnBothAfterSecondStarts(serverAddrV6, serverAddrV4);
2874 }
2875
TEST_P(QuicClientTransportHappyEyeballsTest,V4FirstAndV4WinBeforeV6Start)2876 TEST_P(QuicClientTransportHappyEyeballsTest, V4FirstAndV4WinBeforeV6Start) {
2877 client->setHappyEyeballsCachedFamily(AF_INET);
2878 firstWinBeforeSecondStart(serverAddrV4, serverAddrV6);
2879 }
2880
TEST_P(QuicClientTransportHappyEyeballsTest,V4FirstAndV4WinAfterV6Start)2881 TEST_P(QuicClientTransportHappyEyeballsTest, V4FirstAndV4WinAfterV6Start) {
2882 client->setHappyEyeballsCachedFamily(AF_INET);
2883 firstWinAfterSecondStart(serverAddrV4, serverAddrV6);
2884 }
2885
TEST_P(QuicClientTransportHappyEyeballsTest,V4FirstAndV6Win)2886 TEST_P(QuicClientTransportHappyEyeballsTest, V4FirstAndV6Win) {
2887 client->setHappyEyeballsCachedFamily(AF_INET);
2888 secondWin(serverAddrV4, serverAddrV6);
2889 }
2890
TEST_P(QuicClientTransportHappyEyeballsTest,V4FirstAndV6BindFailure)2891 TEST_P(QuicClientTransportHappyEyeballsTest, V4FirstAndV6BindFailure) {
2892 client->setHappyEyeballsCachedFamily(AF_INET);
2893 secondBindFailure(serverAddrV4, serverAddrV6);
2894 }
2895
TEST_P(QuicClientTransportHappyEyeballsTest,V4FirstAndV4NonFatalErrorBeforeV6Start)2896 TEST_P(
2897 QuicClientTransportHappyEyeballsTest,
2898 V4FirstAndV4NonFatalErrorBeforeV6Start) {
2899 client->setHappyEyeballsCachedFamily(AF_INET);
2900 nonFatalWriteErrorOnFirstBeforeSecondStarts(serverAddrV4, serverAddrV6);
2901 }
2902
TEST_P(QuicClientTransportHappyEyeballsTest,V4FirstAndV4FatalErrorBeforeV6Start)2903 TEST_P(
2904 QuicClientTransportHappyEyeballsTest,
2905 V4FirstAndV4FatalErrorBeforeV6Start) {
2906 client->setHappyEyeballsCachedFamily(AF_INET);
2907 fatalWriteErrorOnFirstBeforeSecondStarts(serverAddrV4, serverAddrV6);
2908 }
2909
TEST_P(QuicClientTransportHappyEyeballsTest,V4FirstAndV4NonFatalErrorAfterV6Start)2910 TEST_P(
2911 QuicClientTransportHappyEyeballsTest,
2912 V4FirstAndV4NonFatalErrorAfterV6Start) {
2913 client->setHappyEyeballsCachedFamily(AF_INET);
2914 nonFatalWriteErrorOnFirstAfterSecondStarts(serverAddrV4, serverAddrV6);
2915 }
2916
TEST_P(QuicClientTransportHappyEyeballsTest,V4FirstAndV4FatalErrorAfterV6Start)2917 TEST_P(
2918 QuicClientTransportHappyEyeballsTest,
2919 V4FirstAndV4FatalErrorAfterV6Start) {
2920 client->setHappyEyeballsCachedFamily(AF_INET);
2921 fatalWriteErrorOnFirstAfterSecondStarts(serverAddrV4, serverAddrV6);
2922 }
2923
TEST_P(QuicClientTransportHappyEyeballsTest,V4FirstAndV6NonFatalErrorAfterV6Start)2924 TEST_P(
2925 QuicClientTransportHappyEyeballsTest,
2926 V4FirstAndV6NonFatalErrorAfterV6Start) {
2927 client->setHappyEyeballsCachedFamily(AF_INET);
2928 nonFatalWriteErrorOnSecondAfterSecondStarts(serverAddrV4, serverAddrV6);
2929 }
2930
TEST_P(QuicClientTransportHappyEyeballsTest,V4FirstAndV6FatalErrorAfterV6Start)2931 TEST_P(
2932 QuicClientTransportHappyEyeballsTest,
2933 V4FirstAndV6FatalErrorAfterV6Start) {
2934 client->setHappyEyeballsCachedFamily(AF_INET);
2935 fatalWriteErrorOnSecondAfterSecondStarts(serverAddrV4, serverAddrV6);
2936 }
2937
TEST_P(QuicClientTransportHappyEyeballsTest,V4FirstAndBothNonFatalErrorAfterV6Start)2938 TEST_P(
2939 QuicClientTransportHappyEyeballsTest,
2940 V4FirstAndBothNonFatalErrorAfterV6Start) {
2941 client->setHappyEyeballsCachedFamily(AF_INET);
2942 nonFatalWriteErrorOnBothAfterSecondStarts(serverAddrV4, serverAddrV6);
2943 }
2944
TEST_P(QuicClientTransportHappyEyeballsTest,V4FirstAndBothFatalErrorAfterV6Start)2945 TEST_P(
2946 QuicClientTransportHappyEyeballsTest,
2947 V4FirstAndBothFatalErrorAfterV6Start) {
2948 client->setHappyEyeballsCachedFamily(AF_INET);
2949 fatalWriteErrorOnBothAfterSecondStarts(serverAddrV4, serverAddrV6);
2950 }
2951
2952 class QuicClientTransportAfterStartTestBase : public QuicClientTransportTest {
2953 public:
SetUpChild()2954 void SetUpChild() override {
2955 client->addNewPeerAddress(serverAddr);
2956 client->setHostname(hostname_);
2957 ON_CALL(*sock, write(_, _))
2958 .WillByDefault(Invoke([&](const SocketAddress&,
2959 const std::unique_ptr<folly::IOBuf>& buf) {
2960 socketWrites.push_back(buf->clone());
2961 return buf->computeChainDataLength();
2962 }));
2963 ON_CALL(*sock, address()).WillByDefault(ReturnRef(serverAddr));
2964
2965 setupCryptoLayer();
2966 start();
2967 client->getNonConstConn().streamManager->setMaxLocalBidirectionalStreams(
2968 std::numeric_limits<uint32_t>::max());
2969 client->getNonConstConn().streamManager->setMaxLocalUnidirectionalStreams(
2970 std::numeric_limits<uint32_t>::max());
2971 }
2972
2973 protected:
2974 std::string hostname_{"TestHost"};
2975 };
2976
2977 class QuicClientTransportAfterStartTest
2978 : public QuicClientTransportAfterStartTestBase,
2979 public testing::WithParamInterface<uint8_t> {};
2980
2981 INSTANTIATE_TEST_CASE_P(
2982 QuicClientZeroLenConnIds,
2983 QuicClientTransportAfterStartTest,
2984 ::Values(0, 8));
2985
2986 class QuicClientTransportVersionAndRetryTest
2987 : public QuicClientTransportAfterStartTestBase {
2988 public:
2989 ~QuicClientTransportVersionAndRetryTest() override = default;
2990
start()2991 void start() override {
2992 client->start(&clientConnCallback);
2993 originalConnId = client->getConn().clientConnectionId;
2994 // create server chosen connId with processId = 0 and workerId = 0
2995 ServerConnectionIdParams params(0, 0, 0);
2996 serverChosenConnId = *connIdAlgo_->encodeConnectionId(params);
2997 // The tests that we do here create streams before crypto is finished,
2998 // so we initialize the peer streams, to allow for this behavior. TODO: when
2999 // 0-rtt support exists, remove this.
3000 client->getNonConstConn()
3001 .flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiLocal =
3002 kDefaultStreamWindowSize;
3003 client->getNonConstConn()
3004 .flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiRemote =
3005 kDefaultStreamWindowSize;
3006 client->getNonConstConn()
3007 .flowControlState.peerAdvertisedInitialMaxStreamOffsetUni =
3008 kDefaultStreamWindowSize;
3009 client->getNonConstConn().flowControlState.peerAdvertisedMaxOffset =
3010 kDefaultConnectionWindowSize;
3011 }
3012 };
3013
3014 class QuicClientVersionParamInvalidTest
3015 : public QuicClientTransportAfterStartTestBase {
3016 public:
3017 ~QuicClientVersionParamInvalidTest() override = default;
3018
start()3019 void start() override {
3020 // force the server to declare that the version negotiated was invalid.;
3021 mockClientHandshake->negotiatedVersion = MVFST2;
3022
3023 client->start(&clientConnCallback);
3024 originalConnId = client->getConn().clientConnectionId;
3025 }
3026 };
3027
TEST_F(QuicClientTransportAfterStartTest,ReadStream)3028 TEST_F(QuicClientTransportAfterStartTest, ReadStream) {
3029 StreamId streamId = client->createBidirectionalStream().value();
3030
3031 client->setReadCallback(streamId, &readCb);
3032 bool dataDelivered = false;
3033 auto expected = IOBuf::copyBuffer("hello");
3034 EXPECT_CALL(readCb, readAvailable(streamId)).WillOnce(Invoke([&](auto) {
3035 auto readData = client->read(streamId, 1000);
3036 auto copy = readData->first->clone();
3037 LOG(INFO) << "Client received data=" << copy->moveToFbString().toStdString()
3038 << " on stream=" << streamId;
3039 EXPECT_TRUE(folly::IOBufEqualTo()((*readData).first, expected));
3040 dataDelivered = true;
3041 eventbase_->terminateLoopSoon();
3042 }));
3043 auto packet = packetToBuf(createStreamPacket(
3044 *serverChosenConnId /* src */,
3045 *originalConnId /* dest */,
3046 appDataPacketNum++,
3047 streamId,
3048 *expected,
3049 0 /* cipherOverhead */,
3050 0 /* largestAcked */));
3051 deliverData(packet->coalesce());
3052 if (!dataDelivered) {
3053 eventbase_->loopForever();
3054 }
3055 EXPECT_TRUE(dataDelivered);
3056 client->close(folly::none);
3057 }
3058
TEST_F(QuicClientTransportAfterStartTest,CleanupReadLoopCounting)3059 TEST_F(QuicClientTransportAfterStartTest, CleanupReadLoopCounting) {
3060 auto streamId = client->createBidirectionalStream().value();
3061 auto& conn = client->getNonConstConn();
3062 auto mockLoopDetectorCallback = std::make_unique<MockLoopDetectorCallback>();
3063 conn.loopDetectorCallback = std::move(mockLoopDetectorCallback);
3064
3065 conn.readDebugState.noReadReason = NoReadReason::RETRIABLE_ERROR;
3066 conn.readDebugState.loopCount = 20;
3067
3068 auto data = IOBuf::copyBuffer("Short Trip Home");
3069 auto packet = packetToBuf(createStreamPacket(
3070 *serverChosenConnId /* src */,
3071 *originalConnId /* dest */,
3072 appDataPacketNum++,
3073 streamId,
3074 *data,
3075 0 /* cipherOverhead */,
3076 0 /* largestAcked */));
3077 deliverData(packet->coalesce());
3078 EXPECT_EQ(NoReadReason::READ_OK, conn.readDebugState.noReadReason);
3079 EXPECT_EQ(0, conn.readDebugState.loopCount);
3080 }
3081
TEST_F(QuicClientTransportAfterStartTest,StaleReadLoopCounting)3082 TEST_F(QuicClientTransportAfterStartTest, StaleReadLoopCounting) {
3083 auto& conn = client->getNonConstConn();
3084 auto mockLoopDetectorCallback = std::make_unique<MockLoopDetectorCallback>();
3085 conn.loopDetectorCallback = std::move(mockLoopDetectorCallback);
3086
3087 auto data = IOBuf::copyBuffer("Short Trip Home");
3088 deliverData(data->coalesce());
3089 EXPECT_EQ(NoReadReason::STALE_DATA, conn.readDebugState.noReadReason);
3090 }
3091
TEST_F(QuicClientTransportAfterStartTest,TruncatedReadLoopCounting)3092 TEST_F(QuicClientTransportAfterStartTest, TruncatedReadLoopCounting) {
3093 auto& conn = client->getNonConstConn();
3094 auto mockLoopDetectorCallback = std::make_unique<MockLoopDetectorCallback>();
3095 auto rawLoopDetectorCallback = mockLoopDetectorCallback.get();
3096 conn.loopDetectorCallback = std::move(mockLoopDetectorCallback);
3097
3098 EXPECT_CALL(
3099 *rawLoopDetectorCallback,
3100 onSuspiciousReadLoops(1, NoReadReason::TRUNCATED));
3101 client->invokeOnDataAvailable(serverAddr, 1000, true);
3102 }
3103
TEST_F(QuicClientTransportAfterStartTest,RetriableErrorLoopCounting)3104 TEST_F(QuicClientTransportAfterStartTest, RetriableErrorLoopCounting) {
3105 auto& conn = client->getNonConstConn();
3106 auto mockLoopDetectorCallback = std::make_unique<MockLoopDetectorCallback>();
3107 auto rawLoopDetectorCallback = mockLoopDetectorCallback.get();
3108 conn.loopDetectorCallback = std::move(mockLoopDetectorCallback);
3109
3110 conn.transportSettings.maxRecvBatchSize = 1;
3111 // Empty socketReads will lead to EAGAIN in mock setup.
3112 EXPECT_CALL(
3113 *rawLoopDetectorCallback,
3114 onSuspiciousReadLoops(1, NoReadReason::RETRIABLE_ERROR));
3115 client->invokeOnNotifyDataAvailable(*sock);
3116 }
3117
TEST_F(QuicClientTransportAfterStartTest,ReadLoopTwice)3118 TEST_F(QuicClientTransportAfterStartTest, ReadLoopTwice) {
3119 auto& conn = client->getNonConstConn();
3120 auto mockLoopDetectorCallback = std::make_unique<MockLoopDetectorCallback>();
3121 auto rawLoopDetectorCallback = mockLoopDetectorCallback.get();
3122 conn.loopDetectorCallback = std::move(mockLoopDetectorCallback);
3123
3124 conn.transportSettings.maxRecvBatchSize = 1;
3125 socketReads.emplace_back(TestReadData(EBADF));
3126 EXPECT_CALL(
3127 *rawLoopDetectorCallback,
3128 onSuspiciousReadLoops(1, NoReadReason::NONRETRIABLE_ERROR));
3129 client->invokeOnNotifyDataAvailable(*sock);
3130 socketReads.clear();
3131
3132 socketReads.emplace_back(TestReadData(EBADF));
3133 EXPECT_CALL(
3134 *rawLoopDetectorCallback,
3135 onSuspiciousReadLoops(2, NoReadReason::NONRETRIABLE_ERROR));
3136 client->invokeOnNotifyDataAvailable(*sock);
3137 }
3138
TEST_F(QuicClientTransportAfterStartTest,NonretriableErrorLoopCounting)3139 TEST_F(QuicClientTransportAfterStartTest, NonretriableErrorLoopCounting) {
3140 auto& conn = client->getNonConstConn();
3141 auto mockLoopDetectorCallback = std::make_unique<MockLoopDetectorCallback>();
3142 auto rawLoopDetectorCallback = mockLoopDetectorCallback.get();
3143 conn.loopDetectorCallback = std::move(mockLoopDetectorCallback);
3144
3145 conn.transportSettings.maxRecvBatchSize = 1;
3146 socketReads.emplace_back(TestReadData(EBADF));
3147 EXPECT_CALL(
3148 *rawLoopDetectorCallback,
3149 onSuspiciousReadLoops(1, NoReadReason::NONRETRIABLE_ERROR));
3150 client->invokeOnNotifyDataAvailable(*sock);
3151 }
3152
TEST_F(QuicClientTransportAfterStartTest,PartialReadLoopCounting)3153 TEST_F(QuicClientTransportAfterStartTest, PartialReadLoopCounting) {
3154 auto streamId = client->createBidirectionalStream().value();
3155 auto& conn = client->getNonConstConn();
3156 auto mockLoopDetectorCallback = std::make_unique<MockLoopDetectorCallback>();
3157 auto rawLoopDetectorCallback = mockLoopDetectorCallback.get();
3158 conn.loopDetectorCallback = std::move(mockLoopDetectorCallback);
3159
3160 auto data = IOBuf::copyBuffer("Short Trip Home");
3161 auto packet = packetToBuf(createStreamPacket(
3162 *serverChosenConnId /* src */,
3163 *originalConnId /* dest */,
3164 appDataPacketNum++,
3165 streamId,
3166 *data,
3167 0 /* cipherOverhead */,
3168 0 /* largestAcked */));
3169
3170 // Read twice in the loop, once success, then fail. Loop detector shouldn't
3171 // fire.
3172 conn.transportSettings.maxRecvBatchSize = 2;
3173 socketReads.emplace_back(TestReadData(packet->coalesce(), serverAddr));
3174 socketReads.emplace_back(TestReadData(EBADF));
3175 EXPECT_CALL(*rawLoopDetectorCallback, onSuspiciousReadLoops(_, _)).Times(0);
3176 client->invokeOnNotifyDataAvailable(*sock);
3177 }
3178
TEST_F(QuicClientTransportAfterStartTest,ReadLoopCountingRecvmmsg)3179 TEST_F(QuicClientTransportAfterStartTest, ReadLoopCountingRecvmmsg) {
3180 auto& conn = client->getNonConstConn();
3181 auto mockLoopDetectorCallback = std::make_unique<MockLoopDetectorCallback>();
3182 auto rawLoopDetectorCallback = mockLoopDetectorCallback.get();
3183 conn.loopDetectorCallback = std::move(mockLoopDetectorCallback);
3184
3185 conn.transportSettings.shouldUseRecvmmsgForBatchRecv = true;
3186 conn.transportSettings.maxRecvBatchSize = 1;
3187 EXPECT_CALL(*sock, recvmmsg(_, 1, _, nullptr))
3188 .WillOnce(Invoke(
3189 [](struct mmsghdr*, unsigned int, unsigned int, struct timespec*) {
3190 errno = EAGAIN;
3191 return -1;
3192 }));
3193 EXPECT_CALL(
3194 *rawLoopDetectorCallback,
3195 onSuspiciousReadLoops(1, NoReadReason::RETRIABLE_ERROR));
3196 client->invokeOnNotifyDataAvailable(*sock);
3197
3198 EXPECT_CALL(*sock, recvmmsg(_, 1, _, nullptr))
3199 .WillOnce(Invoke(
3200 [](struct mmsghdr*, unsigned int, unsigned int, struct timespec*) {
3201 errno = EBADF;
3202 return -1;
3203 }));
3204 EXPECT_CALL(
3205 *rawLoopDetectorCallback,
3206 onSuspiciousReadLoops(2, NoReadReason::NONRETRIABLE_ERROR));
3207 client->invokeOnNotifyDataAvailable(*sock);
3208 }
3209
TEST_F(QuicClientTransportAfterStartTest,ReadStreamMultiplePackets)3210 TEST_F(QuicClientTransportAfterStartTest, ReadStreamMultiplePackets) {
3211 StreamId streamId = client->createBidirectionalStream().value();
3212
3213 client->setReadCallback(streamId, &readCb);
3214 bool dataDelivered = false;
3215 auto data = IOBuf::copyBuffer("hello");
3216
3217 auto expected = data->clone();
3218 expected->prependChain(data->clone());
3219 EXPECT_CALL(readCb, readAvailable(streamId)).WillOnce(Invoke([&](auto) {
3220 auto readData = client->read(streamId, 1000);
3221 auto copy = readData->first->clone();
3222 LOG(INFO) << "Client received data="
3223 << copy->clone()->moveToFbString().toStdString()
3224 << " on stream=" << streamId;
3225 EXPECT_EQ(
3226 copy->moveToFbString().toStdString(),
3227 expected->clone()->moveToFbString().toStdString());
3228 dataDelivered = true;
3229 eventbase_->terminateLoopSoon();
3230 }));
3231 auto packet1 = packetToBuf(createStreamPacket(
3232 *serverChosenConnId /* src */,
3233 *originalConnId /* dest */,
3234 appDataPacketNum++,
3235 streamId,
3236 *data,
3237 0 /* cipherOverhead */,
3238 0 /* largestAcked */,
3239 folly::none /* longHeaderOverride */,
3240 false /* eof */));
3241 auto packet2 = packetToBuf(createStreamPacket(
3242 *serverChosenConnId /* src */,
3243 *originalConnId /* dest */,
3244 appDataPacketNum++,
3245 streamId,
3246 *data,
3247 0 /* cipherOverhead */,
3248 0 /* largestAcked */,
3249 folly::none /* longHeaderOverride */,
3250 true /* eof */,
3251 folly::none /* shortHeaderOverride */,
3252 data->length() /* offset */));
3253
3254 socketReads.emplace_back(TestReadData(packet1->coalesce(), serverAddr));
3255 deliverData(packet2->coalesce());
3256 if (!dataDelivered) {
3257 eventbase_->loopForever();
3258 }
3259 EXPECT_TRUE(dataDelivered);
3260 client->close(folly::none);
3261 }
3262
TEST_F(QuicClientTransportAfterStartTest,ReadStreamWithRetriableError)3263 TEST_F(QuicClientTransportAfterStartTest, ReadStreamWithRetriableError) {
3264 StreamId streamId = client->createBidirectionalStream().value();
3265 client->setReadCallback(streamId, &readCb);
3266 EXPECT_CALL(readCb, readAvailable(_)).Times(0);
3267 EXPECT_CALL(readCb, readError(_, _)).Times(0);
3268 deliverNetworkError(EAGAIN);
3269 client->setReadCallback(streamId, nullptr);
3270 client->close(folly::none);
3271 }
3272
TEST_F(QuicClientTransportAfterStartTest,ReadStreamWithNonRetriableError)3273 TEST_F(QuicClientTransportAfterStartTest, ReadStreamWithNonRetriableError) {
3274 StreamId streamId = client->createBidirectionalStream().value();
3275 client->setReadCallback(streamId, &readCb);
3276 EXPECT_CALL(readCb, readAvailable(_)).Times(0);
3277 // TODO: we currently do not close the socket, but maybe we can in the future.
3278 EXPECT_CALL(readCb, readError(_, _)).Times(0);
3279 deliverNetworkError(EBADF);
3280 client->setReadCallback(streamId, nullptr);
3281 client->close(folly::none);
3282 }
3283
TEST_F(QuicClientTransportAfterStartTest,ReadStreamMultiplePacketsWithRetriableError)3284 TEST_F(
3285 QuicClientTransportAfterStartTest,
3286 ReadStreamMultiplePacketsWithRetriableError) {
3287 StreamId streamId = client->createBidirectionalStream().value();
3288
3289 client->setReadCallback(streamId, &readCb);
3290 bool dataDelivered = false;
3291 auto expected = IOBuf::copyBuffer("hello");
3292 EXPECT_CALL(readCb, readAvailable(streamId)).WillOnce(Invoke([&](auto) {
3293 auto readData = client->read(streamId, 1000);
3294 auto copy = readData->first->clone();
3295 LOG(INFO) << "Client received data=" << copy->moveToFbString().toStdString()
3296 << " on stream=" << streamId;
3297 EXPECT_TRUE(folly::IOBufEqualTo()((*readData).first, expected));
3298 dataDelivered = true;
3299 eventbase_->terminateLoopSoon();
3300 }));
3301 auto packet = packetToBuf(createStreamPacket(
3302 *serverChosenConnId /* src */,
3303 *originalConnId /* dest */,
3304 appDataPacketNum++,
3305 streamId,
3306 *expected,
3307 0 /* cipherOverhead */,
3308 0 /* largestAcked */));
3309
3310 socketReads.emplace_back(TestReadData(packet->coalesce(), serverAddr));
3311 deliverNetworkError(EAGAIN);
3312 if (!dataDelivered) {
3313 eventbase_->loopForever();
3314 }
3315 EXPECT_TRUE(dataDelivered);
3316 client->close(folly::none);
3317 }
3318
TEST_F(QuicClientTransportAfterStartTest,ReadStreamMultiplePacketsWithNonRetriableError)3319 TEST_F(
3320 QuicClientTransportAfterStartTest,
3321 ReadStreamMultiplePacketsWithNonRetriableError) {
3322 StreamId streamId = client->createBidirectionalStream().value();
3323
3324 client->setReadCallback(streamId, &readCb);
3325 auto expected = IOBuf::copyBuffer("hello");
3326 EXPECT_CALL(readCb, readAvailable(streamId)).Times(0);
3327
3328 // TODO: we currently do not close the socket, but maybe we can in the future.
3329 EXPECT_CALL(readCb, readError(_, _)).Times(0);
3330 auto packet = packetToBuf(createStreamPacket(
3331 *serverChosenConnId /* src */,
3332 *originalConnId /* dest */,
3333 appDataPacketNum++,
3334 streamId,
3335 *expected,
3336 0 /* cipherOverhead */,
3337 0 /* largestAcked */));
3338
3339 {
3340 EXPECT_CALL(*sock, pauseRead()).Times(AtLeast(1));
3341 socketReads.emplace_back(TestReadData(packet->coalesce(), serverAddr));
3342 deliverNetworkError(EBADF);
3343 }
3344 client->setReadCallback(streamId, nullptr);
3345 }
3346
TEST_F(QuicClientTransportAfterStartTest,RecvNewConnectionIdValid)3347 TEST_F(QuicClientTransportAfterStartTest, RecvNewConnectionIdValid) {
3348 auto& conn = client->getNonConstConn();
3349 conn.transportSettings.selfActiveConnectionIdLimit = 1;
3350
3351 ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
3352 RegularQuicPacketBuilder builder(
3353 conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
3354 builder.encodePacketHeader();
3355 ASSERT_TRUE(builder.canBuildPacket());
3356
3357 auto token = StatelessResetToken{1, 9, 2, 0};
3358 NewConnectionIdFrame newConnId(1, 0, ConnectionId({2, 4, 2, 3}), token);
3359 writeSimpleFrame(QuicSimpleFrame(newConnId), builder);
3360
3361 auto packet = std::move(builder).buildPacket();
3362 auto data = packetToBuf(packet);
3363
3364 EXPECT_EQ(conn.peerConnectionIds.size(), 1);
3365 deliverData(data->coalesce(), false);
3366 EXPECT_EQ(conn.peerConnectionIds.size(), 2);
3367 EXPECT_EQ(conn.peerConnectionIds[1].connId, newConnId.connectionId);
3368 EXPECT_EQ(conn.peerConnectionIds[1].sequenceNumber, newConnId.sequenceNumber);
3369 EXPECT_EQ(conn.peerConnectionIds[1].token, newConnId.token);
3370 }
3371
TEST_F(QuicClientTransportAfterStartTest,ShortHeaderPacketWithNoFrames)3372 TEST_F(QuicClientTransportAfterStartTest, ShortHeaderPacketWithNoFrames) {
3373 auto qLogger = std::make_shared<FileQLogger>(VantagePoint::Client);
3374 client->getNonConstConn().qLogger = qLogger;
3375 // Use large packet number to make sure packet is long enough to parse
3376 PacketNum nextPacket = 0x11111111;
3377 client->getNonConstConn().clientConnectionId = getTestConnectionId();
3378 auto aead = dynamic_cast<const MockAead*>(
3379 client->getNonConstConn().readCodec->getOneRttReadCipher());
3380 // Override the Aead mock to remove the 20 bytes of dummy data added below
3381 ON_CALL(*aead, _tryDecrypt(_, _, _))
3382 .WillByDefault(Invoke([&](auto& buf, auto, auto) {
3383 buf->trimEnd(20);
3384 return buf->clone();
3385 }));
3386 ShortHeader header(
3387 ProtectionType::KeyPhaseZero,
3388 *client->getConn().clientConnectionId,
3389 nextPacket);
3390 RegularQuicPacketBuilder builder(
3391 client->getConn().udpSendPacketLen,
3392 std::move(header),
3393 0 /* largestAcked */);
3394 builder.encodePacketHeader();
3395 ASSERT_TRUE(builder.canBuildPacket());
3396 auto packet = std::move(builder).buildPacket();
3397 auto buf = packetToBuf(packet);
3398 buf->coalesce();
3399 buf->reserve(0, 200);
3400 buf->append(20);
3401 EXPECT_THROW(deliverData(buf->coalesce()), std::runtime_error);
3402 std::vector<int> indices =
3403 getQLogEventIndices(QLogEventType::PacketDrop, qLogger);
3404 EXPECT_EQ(indices.size(), 1);
3405
3406 auto tmp = std::move(qLogger->logs[indices[0]]);
3407 auto event = dynamic_cast<QLogPacketDropEvent*>(tmp.get());
3408 EXPECT_EQ(
3409 event->dropReason,
3410 QuicTransportStatsCallback::toString(
3411 PacketDropReason::PROTOCOL_VIOLATION));
3412 }
3413
TEST_F(QuicClientTransportAfterStartTest,RecvNewConnectionIdTooManyReceivedIds)3414 TEST_F(
3415 QuicClientTransportAfterStartTest,
3416 RecvNewConnectionIdTooManyReceivedIds) {
3417 auto& conn = client->getNonConstConn();
3418 conn.transportSettings.selfActiveConnectionIdLimit = 0;
3419
3420 ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
3421 RegularQuicPacketBuilder builder(
3422 conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
3423 builder.encodePacketHeader();
3424 ASSERT_TRUE(builder.canBuildPacket());
3425 NewConnectionIdFrame newConnId(
3426 1, 0, ConnectionId({2, 4, 2, 3}), StatelessResetToken());
3427 writeSimpleFrame(QuicSimpleFrame(newConnId), builder);
3428
3429 auto packet = std::move(builder).buildPacket();
3430 auto data = packetToBuf(packet);
3431
3432 EXPECT_EQ(conn.peerConnectionIds.size(), 1);
3433 deliverData(data->coalesce(), false);
3434 EXPECT_EQ(conn.peerConnectionIds.size(), 1);
3435 }
3436
TEST_F(QuicClientTransportAfterStartTest,RecvNewConnectionIdInvalidRetire)3437 TEST_F(QuicClientTransportAfterStartTest, RecvNewConnectionIdInvalidRetire) {
3438 auto& conn = client->getNonConstConn();
3439 conn.transportSettings.selfActiveConnectionIdLimit = 1;
3440
3441 ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
3442 RegularQuicPacketBuilder builder(
3443 conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
3444 builder.encodePacketHeader();
3445 ASSERT_TRUE(builder.canBuildPacket());
3446 NewConnectionIdFrame newConnId(
3447 1, 3, ConnectionId({2, 4, 2, 3}), StatelessResetToken());
3448 writeSimpleFrame(QuicSimpleFrame(newConnId), builder);
3449
3450 auto packet = std::move(builder).buildPacket();
3451 auto data = packetToBuf(packet);
3452
3453 EXPECT_EQ(conn.peerConnectionIds.size(), 1);
3454 EXPECT_THROW(deliverData(data->coalesce()), std::runtime_error);
3455 }
3456
TEST_F(QuicClientTransportAfterStartTest,RecvNewConnectionIdUsing0LenCid)3457 TEST_F(QuicClientTransportAfterStartTest, RecvNewConnectionIdUsing0LenCid) {
3458 auto& conn = client->getNonConstConn();
3459 conn.transportSettings.selfActiveConnectionIdLimit = 2;
3460
3461 conn.serverConnectionId = ConnectionId(std::vector<uint8_t>{});
3462 conn.peerConnectionIds.pop_back();
3463 conn.peerConnectionIds.emplace_back(*conn.serverConnectionId, 0);
3464
3465 ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
3466 RegularQuicPacketBuilder builder(
3467 conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
3468 builder.encodePacketHeader();
3469 ASSERT_TRUE(builder.canBuildPacket());
3470 NewConnectionIdFrame newConnId(
3471 1, 0, ConnectionId({2, 4, 2, 3}), StatelessResetToken());
3472 writeSimpleFrame(QuicSimpleFrame(newConnId), builder);
3473
3474 auto packet = std::move(builder).buildPacket();
3475 auto data = packetToBuf(packet);
3476
3477 EXPECT_EQ(conn.peerConnectionIds.size(), 1);
3478 try {
3479 deliverData(data->coalesce(), false);
3480 FAIL();
3481 } catch (const std::runtime_error& e) {
3482 EXPECT_EQ(std::string(e.what()), "Protocol violation");
3483 }
3484 EXPECT_EQ(conn.peerConnectionIds.size(), 1);
3485 }
3486
TEST_F(QuicClientTransportAfterStartTest,RecvNewConnectionIdNoopValidDuplicate)3487 TEST_F(
3488 QuicClientTransportAfterStartTest,
3489 RecvNewConnectionIdNoopValidDuplicate) {
3490 auto& conn = client->getNonConstConn();
3491 conn.transportSettings.selfActiveConnectionIdLimit = 1;
3492
3493 ConnectionId connId2({5, 5, 5, 5});
3494 conn.peerConnectionIds.emplace_back(connId2, 1);
3495
3496 ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
3497 RegularQuicPacketBuilder builder(
3498 conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
3499 builder.encodePacketHeader();
3500 ASSERT_TRUE(builder.canBuildPacket());
3501 NewConnectionIdFrame newConnId(1, 0, connId2, StatelessResetToken());
3502 writeSimpleFrame(QuicSimpleFrame(newConnId), builder);
3503
3504 auto packet = std::move(builder).buildPacket();
3505 auto data = packetToBuf(packet);
3506
3507 EXPECT_EQ(conn.peerConnectionIds.size(), 2);
3508 deliverData(data->coalesce(), false);
3509 EXPECT_EQ(conn.peerConnectionIds.size(), 2);
3510 }
3511
TEST_F(QuicClientTransportAfterStartTest,RecvNewConnectionIdExceptionInvalidDuplicate)3512 TEST_F(
3513 QuicClientTransportAfterStartTest,
3514 RecvNewConnectionIdExceptionInvalidDuplicate) {
3515 auto& conn = client->getNonConstConn();
3516 conn.transportSettings.selfActiveConnectionIdLimit = 1;
3517
3518 ConnectionId connId2({5, 5, 5, 5});
3519 conn.peerConnectionIds.emplace_back(connId2, 1);
3520
3521 ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
3522 RegularQuicPacketBuilder builder(
3523 conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
3524 builder.encodePacketHeader();
3525 ASSERT_TRUE(builder.canBuildPacket());
3526 NewConnectionIdFrame newConnId(2, 0, connId2, StatelessResetToken());
3527 writeSimpleFrame(QuicSimpleFrame(newConnId), builder);
3528
3529 auto packet = std::move(builder).buildPacket();
3530 auto data = packetToBuf(packet);
3531
3532 EXPECT_EQ(conn.peerConnectionIds.size(), 2);
3533 EXPECT_THROW(deliverData(data->coalesce()), std::runtime_error);
3534 }
3535
TEST_P(QuicClientTransportAfterStartTest,ReadStreamCoalesced)3536 TEST_P(QuicClientTransportAfterStartTest, ReadStreamCoalesced) {
3537 expectQuicStatsPacketDrop(
3538 QuicTransportStatsCallback::PacketDropReason::PARSE_ERROR);
3539 uint8_t connIdSize = GetParam();
3540
3541 client->getNonConstConn().clientConnectionId =
3542 ConnectionId(std::vector<uint8_t>(connIdSize, 1));
3543 setConnectionIds();
3544
3545 StreamId streamId = client->createBidirectionalStream().value();
3546 auto qLogger = std::make_shared<FileQLogger>(VantagePoint::Client);
3547 client->getNonConstConn().qLogger = qLogger;
3548
3549 client->setReadCallback(streamId, &readCb);
3550 bool dataDelivered = false;
3551 auto expected = IOBuf::copyBuffer("hello");
3552 EXPECT_CALL(readCb, readAvailable(streamId)).WillOnce(Invoke([&](auto) {
3553 auto readData = client->read(streamId, 1000);
3554 auto copy = readData->first->clone();
3555 LOG(INFO) << "Client received data=" << copy->moveToFbString().toStdString()
3556 << " on stream=" << streamId;
3557 EXPECT_TRUE(folly::IOBufEqualTo()((*readData).first, expected));
3558 dataDelivered = true;
3559 eventbase_->terminateLoopSoon();
3560 }));
3561
3562 FizzCryptoFactory cryptoFactory;
3563 auto garbage = IOBuf::copyBuffer("garbage");
3564 auto initialCipher = cryptoFactory.getServerInitialCipher(
3565 *serverChosenConnId, QuicVersion::MVFST);
3566 auto firstPacketNum = appDataPacketNum++;
3567 auto packet1 = packetToBufCleartext(
3568 createStreamPacket(
3569 *serverChosenConnId /* src */,
3570 *originalConnId /* dest */,
3571 firstPacketNum,
3572 streamId,
3573 *garbage,
3574 initialCipher->getCipherOverhead(),
3575 0 /* largestAcked */,
3576 std::make_pair(LongHeader::Types::Initial, QuicVersion::MVFST)),
3577 *initialCipher,
3578 getInitialHeaderCipher(),
3579 firstPacketNum);
3580 packet1->coalesce();
3581 auto packet2 = packetToBuf(createStreamPacket(
3582 *serverChosenConnId /* src */,
3583 *originalConnId /* dest */,
3584 firstPacketNum,
3585 streamId,
3586 *expected,
3587 0 /* cipherOverhead */,
3588 0 /* largestAcked */));
3589 packet1->appendChain(std::move(packet2));
3590 deliverData(packet1->coalesce());
3591 if (!dataDelivered) {
3592 eventbase_->loopForever();
3593 }
3594 EXPECT_TRUE(dataDelivered);
3595 client->close(folly::none);
3596 std::vector<int> indices =
3597 getQLogEventIndices(QLogEventType::PacketDrop, qLogger);
3598 EXPECT_EQ(indices.size(), 1);
3599 auto tmp = std::move(qLogger->logs[indices[0]]);
3600 auto event = dynamic_cast<QLogPacketDropEvent*>(tmp.get());
3601 EXPECT_EQ(event->packetSize, 65 + (2 * connIdSize));
3602 EXPECT_EQ(event->dropReason, kParse);
3603 }
3604
TEST_F(QuicClientTransportAfterStartTest,ReadStreamCoalescedMany)3605 TEST_F(QuicClientTransportAfterStartTest, ReadStreamCoalescedMany) {
3606 StreamId streamId = client->createBidirectionalStream().value();
3607
3608 client->setReadCallback(streamId, &readCb);
3609 auto expected = IOBuf::copyBuffer("hello");
3610 EXPECT_CALL(readCb, readAvailable(streamId)).Times(0);
3611 FizzCryptoFactory cryptoFactory;
3612 BufQueue packets;
3613 for (int i = 0; i < kMaxNumCoalescedPackets; i++) {
3614 auto garbage = IOBuf::copyBuffer("garbage");
3615 auto initialCipher = cryptoFactory.getServerInitialCipher(
3616 *serverChosenConnId, QuicVersion::MVFST);
3617 auto packetNum = appDataPacketNum++;
3618 auto packet1 = packetToBufCleartext(
3619 createStreamPacket(
3620 *serverChosenConnId /* src */,
3621 *originalConnId /* dest */,
3622 packetNum,
3623 streamId,
3624 *garbage,
3625 initialCipher->getCipherOverhead(),
3626 0 /* largestAcked */,
3627 std::make_pair(LongHeader::Types::Initial, QuicVersion::MVFST)),
3628 *initialCipher,
3629 getInitialHeaderCipher(),
3630 packetNum);
3631 packets.append(std::move(packet1));
3632 }
3633 auto packet2 = packetToBuf(createStreamPacket(
3634 *serverChosenConnId /* src */,
3635 *originalConnId /* dest */,
3636 appDataPacketNum++,
3637 streamId,
3638 *expected,
3639 0 /* cipherOverhead */,
3640 0 /* largestAcked */));
3641 packets.append(std::move(packet2));
3642 auto data = packets.move();
3643 deliverData(data->coalesce());
3644 eventbase_->loopOnce();
3645 client->close(folly::none);
3646 }
3647
TEST_F(QuicClientTransportAfterStartTest,RecvPathChallengeNoAvailablePeerIds)3648 TEST_F(QuicClientTransportAfterStartTest, RecvPathChallengeNoAvailablePeerIds) {
3649 auto& conn = client->getNonConstConn();
3650
3651 ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
3652 RegularQuicPacketBuilder builder(
3653 conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
3654 builder.encodePacketHeader();
3655 PathChallengeFrame pathChallenge(123);
3656 ASSERT_TRUE(builder.canBuildPacket());
3657 writeSimpleFrame(QuicSimpleFrame(pathChallenge), builder);
3658
3659 auto packet = std::move(builder).buildPacket();
3660 auto data = packetToBuf(packet);
3661
3662 EXPECT_TRUE(conn.pendingEvents.frames.empty());
3663 EXPECT_THROW(deliverData(data->coalesce(), false), std::runtime_error);
3664 }
3665
TEST_F(QuicClientTransportAfterStartTest,RecvPathChallengeAvailablePeerId)3666 TEST_F(QuicClientTransportAfterStartTest, RecvPathChallengeAvailablePeerId) {
3667 auto& conn = client->getNonConstConn();
3668 auto originalCid =
3669 ConnectionIdData(ConnectionId(std::vector<uint8_t>{1, 2, 3, 4}), 1);
3670 auto secondCid =
3671 ConnectionIdData(ConnectionId(std::vector<uint8_t>{5, 6, 7, 8}), 2);
3672
3673 conn.serverConnectionId = originalCid.connId;
3674
3675 conn.peerConnectionIds.push_back(originalCid);
3676 conn.peerConnectionIds.push_back(secondCid);
3677
3678 ShortHeader header(ProtectionType::KeyPhaseZero, *conn.clientConnectionId, 1);
3679 RegularQuicPacketBuilder builder(
3680 conn.udpSendPacketLen, std::move(header), 0 /* largestAcked */);
3681 builder.encodePacketHeader();
3682 PathChallengeFrame pathChallenge(123);
3683 ASSERT_TRUE(builder.canBuildPacket());
3684 writeSimpleFrame(QuicSimpleFrame(pathChallenge), builder);
3685
3686 auto packet = std::move(builder).buildPacket();
3687 auto data = packetToBuf(packet);
3688
3689 EXPECT_TRUE(conn.pendingEvents.frames.empty());
3690 deliverData(data->coalesce(), false);
3691
3692 EXPECT_EQ(conn.pendingEvents.frames.size(), 2);
3693
3694 // The RetireConnectionId frame will be enqueued before the PathResponse.
3695 auto retireFrame = conn.pendingEvents.frames[0].asRetireConnectionIdFrame();
3696 EXPECT_EQ(retireFrame->sequenceNumber, 1);
3697
3698 PathResponseFrame& pathResponse =
3699 *conn.pendingEvents.frames[1].asPathResponseFrame();
3700 EXPECT_EQ(pathResponse.pathData, pathChallenge.pathData);
3701 }
3702
verifyFramePresent(std::vector<std::unique_ptr<folly::IOBuf>> & socketWrites,QuicReadCodec & readCodec,QuicFrame::Type frameType)3703 bool verifyFramePresent(
3704 std::vector<std::unique_ptr<folly::IOBuf>>& socketWrites,
3705 QuicReadCodec& readCodec,
3706 QuicFrame::Type frameType) {
3707 AckStates ackStates;
3708 for (auto& write : socketWrites) {
3709 auto packetQueue = bufToQueue(write->clone());
3710 auto result = readCodec.parsePacket(packetQueue, ackStates);
3711 auto regularPacket = result.regularPacket();
3712 if (!regularPacket) {
3713 continue;
3714 }
3715 for (FOLLY_MAYBE_UNUSED auto& frame : regularPacket->frames) {
3716 if (frame.type() != frameType) {
3717 continue;
3718 }
3719 return true;
3720 }
3721 }
3722 return false;
3723 }
3724
TEST_F(QuicClientTransportAfterStartTest,CloseConnectionWithStreamPending)3725 TEST_F(QuicClientTransportAfterStartTest, CloseConnectionWithStreamPending) {
3726 StreamId streamId = client->createBidirectionalStream().value();
3727 auto qLogger = std::make_shared<FileQLogger>(VantagePoint::Client);
3728 client->getNonConstConn().qLogger = qLogger;
3729 auto expected = IOBuf::copyBuffer("hello");
3730 client->setReadCallback(streamId, &readCb);
3731 client->writeChain(streamId, expected->clone(), true);
3732 loopForWrites();
3733 // ack all the packets
3734 ASSERT_FALSE(client->getConn().outstandings.packets.empty());
3735
3736 AckBlocks acks;
3737 auto start = getFirstOutstandingPacket(
3738 client->getNonConstConn(), PacketNumberSpace::AppData)
3739 ->packet.header.getPacketSequenceNum();
3740 auto end = getLastOutstandingPacket(
3741 client->getNonConstConn(), PacketNumberSpace::AppData)
3742 ->packet.header.getPacketSequenceNum();
3743 acks.insert(start, end);
3744
3745 auto ackPacket = packetToBuf(createAckPacket(
3746 client->getNonConstConn(),
3747 ++appDataPacketNum,
3748 acks,
3749 PacketNumberSpace::AppData));
3750 deliverData(ackPacket->coalesce());
3751 socketWrites.clear();
3752
3753 auto serverReadCodec = makeEncryptedCodec();
3754 EXPECT_CALL(readCb, readError(streamId, _));
3755 client->closeGracefully();
3756 EXPECT_FALSE(verifyFramePresent(
3757 socketWrites, *serverReadCodec, QuicFrame::Type::ConnectionCloseFrame));
3758
3759 // close the stream
3760 auto packet = packetToBuf(createStreamPacket(
3761 *serverChosenConnId /* src */,
3762 *originalConnId /* dest */,
3763 appDataPacketNum++,
3764 streamId,
3765 *expected,
3766 0 /* cipherOverhead */,
3767 0 /* largestAcked */,
3768 folly::none,
3769 true));
3770 socketWrites.clear();
3771 deliverData(packet->coalesce());
3772 EXPECT_TRUE(verifyFramePresent(
3773 socketWrites, *serverReadCodec, QuicFrame::Type::ConnectionCloseFrame));
3774
3775 std::vector<int> indices =
3776 getQLogEventIndices(QLogEventType::ConnectionClose, qLogger);
3777 // expecting that connection close called twice
3778 EXPECT_EQ(indices.size(), 2);
3779
3780 // event called in closeGracefully()
3781 auto tmp = std::move(qLogger->logs[indices[0]]);
3782 auto event = dynamic_cast<QLogConnectionCloseEvent*>(tmp.get());
3783 EXPECT_EQ(event->error, kNoError);
3784 EXPECT_EQ(event->reason, kGracefulExit);
3785 EXPECT_TRUE(event->drainConnection);
3786 EXPECT_FALSE(event->sendCloseImmediately);
3787
3788 // event called in closeImpl(), right before transport is closed
3789 auto tmp2 = std::move(qLogger->logs[indices[1]]);
3790 auto event2 = dynamic_cast<QLogConnectionCloseEvent*>(tmp2.get());
3791 EXPECT_EQ(event2->error, kNoError);
3792 auto reason = folly::to<std::string>(
3793 "Server: ", kNoError, ", Peer: isReset: ", 0, ", Peer: isAbandon: ", 0);
3794 EXPECT_EQ(event2->reason, reason);
3795 EXPECT_TRUE(event2->drainConnection);
3796 EXPECT_TRUE(event2->sendCloseImmediately);
3797 }
3798
TEST_F(QuicClientTransportAfterStartTest,CloseConnectionWithNoStreamPending)3799 TEST_F(QuicClientTransportAfterStartTest, CloseConnectionWithNoStreamPending) {
3800 StreamId streamId = client->createBidirectionalStream().value();
3801
3802 auto expected = IOBuf::copyBuffer("hello");
3803 client->setReadCallback(streamId, &readCb);
3804 client->writeChain(streamId, expected->clone(), true);
3805
3806 loopForWrites();
3807
3808 // ack all the packets
3809 ASSERT_FALSE(client->getConn().outstandings.packets.empty());
3810
3811 AckBlocks acks;
3812 auto start = getFirstOutstandingPacket(
3813 client->getNonConstConn(), PacketNumberSpace::AppData)
3814 ->packet.header.getPacketSequenceNum();
3815 auto end = getLastOutstandingPacket(
3816 client->getNonConstConn(), PacketNumberSpace::AppData)
3817 ->packet.header.getPacketSequenceNum();
3818 acks.insert(start, end);
3819
3820 auto ackPacket = packetToBuf(createAckPacket(
3821 client->getNonConstConn(),
3822 ++appDataPacketNum,
3823 acks,
3824 PacketNumberSpace::AppData));
3825 deliverData(ackPacket->coalesce());
3826 socketWrites.clear();
3827
3828 // close the stream
3829 auto packet = packetToBuf(createStreamPacket(
3830 *serverChosenConnId /* src */,
3831 *originalConnId /* dest */,
3832 appDataPacketNum++,
3833 streamId,
3834 *expected,
3835 0 /* cipherOverhead */,
3836 0 /* largestAcked */,
3837 folly::none,
3838 true));
3839 socketWrites.clear();
3840 deliverData(packet->coalesce());
3841 EXPECT_CALL(readCb, readError(streamId, _));
3842 client->close(folly::none);
3843 EXPECT_TRUE(verifyFramePresent(
3844 socketWrites,
3845 *makeEncryptedCodec(),
3846 QuicFrame::Type::ConnectionCloseFrame));
3847 }
3848
3849 class QuicClientTransportAfterStartTestClose
3850 : public QuicClientTransportAfterStartTestBase,
3851 public testing::WithParamInterface<bool> {};
3852
3853 INSTANTIATE_TEST_CASE_P(
3854 QuicClientTransportAfterStartTestCloseWithError,
3855 QuicClientTransportAfterStartTestClose,
3856 Values(true, false));
3857
TEST_P(QuicClientTransportAfterStartTestClose,CloseConnectionWithErrorCleartext)3858 TEST_P(
3859 QuicClientTransportAfterStartTestClose,
3860 CloseConnectionWithErrorCleartext) {
3861 StreamId streamId = client->createBidirectionalStream().value();
3862 auto qLogger = std::make_shared<FileQLogger>(VantagePoint::Client);
3863 client->getNonConstConn().qLogger = qLogger;
3864 auto expected = IOBuf::copyBuffer("hello");
3865 client->setReadCallback(streamId, &readCb);
3866 client->writeChain(streamId, expected->clone(), true);
3867
3868 loopForWrites();
3869 socketWrites.clear();
3870 EXPECT_CALL(readCb, readError(streamId, _));
3871 if (GetParam()) {
3872 client->close(std::make_pair(
3873 QuicErrorCode(GenericApplicationErrorCode::UNKNOWN),
3874 std::string("stopping")));
3875 EXPECT_TRUE(verifyFramePresent(
3876 socketWrites,
3877 *makeHandshakeCodec(),
3878 QuicFrame::Type::ConnectionCloseFrame));
3879
3880 std::vector<int> indices =
3881 getQLogEventIndices(QLogEventType::ConnectionClose, qLogger);
3882 // expecting that connection close called once
3883 EXPECT_EQ(indices.size(), 1);
3884 auto tmp = std::move(qLogger->logs[indices[0]]);
3885 auto event = dynamic_cast<QLogConnectionCloseEvent*>(tmp.get());
3886 EXPECT_EQ(event->error, "stopping");
3887 EXPECT_EQ(event->reason, "stopping");
3888 EXPECT_TRUE(event->drainConnection);
3889 EXPECT_TRUE(event->sendCloseImmediately);
3890
3891 } else {
3892 client->close(folly::none);
3893 EXPECT_TRUE(verifyFramePresent(
3894 socketWrites,
3895 *makeHandshakeCodec(),
3896 QuicFrame::Type::ConnectionCloseFrame));
3897 std::vector<int> indices =
3898 getQLogEventIndices(QLogEventType::ConnectionClose, qLogger);
3899 // expecting that connection close called once
3900 EXPECT_EQ(indices.size(), 1);
3901 auto tmp = std::move(qLogger->logs[indices[0]]);
3902 auto event = dynamic_cast<QLogConnectionCloseEvent*>(tmp.get());
3903 EXPECT_EQ(event->error, "No Error");
3904 EXPECT_EQ(event->reason, "No Error");
3905 EXPECT_TRUE(event->drainConnection);
3906 EXPECT_TRUE(event->sendCloseImmediately);
3907 }
3908 }
3909
TEST_F(QuicClientTransportAfterStartTest,RecvPostHandshakeData)3910 TEST_F(QuicClientTransportAfterStartTest, RecvPostHandshakeData) {
3911 auto oneRttReadOffset =
3912 client->getConn().cryptoState->oneRttStream.currentReadOffset;
3913 recvTicket();
3914 EXPECT_GT(
3915 client->getConn().cryptoState->oneRttStream.currentReadOffset,
3916 oneRttReadOffset);
3917 }
3918
TEST_F(QuicClientTransportAfterStartTest,RecvRetransmittedHandshakeData)3919 TEST_F(QuicClientTransportAfterStartTest, RecvRetransmittedHandshakeData) {
3920 recvTicket();
3921 auto oneRttReadOffset =
3922 client->getConn().cryptoState->oneRttStream.currentReadOffset;
3923 // Simulate retransmission of the same ticket.
3924 recvTicket(0);
3925 EXPECT_EQ(
3926 client->getConn().cryptoState->oneRttStream.currentReadOffset,
3927 oneRttReadOffset);
3928 }
3929
TEST_F(QuicClientTransportAfterStartTest,RecvAckOfCryptoStream)3930 TEST_F(QuicClientTransportAfterStartTest, RecvAckOfCryptoStream) {
3931 // Simulate ack from server
3932 auto& cryptoState = client->getConn().cryptoState;
3933 EXPECT_GT(cryptoState->initialStream.retransmissionBuffer.size(), 0);
3934 EXPECT_GT(cryptoState->handshakeStream.retransmissionBuffer.size(), 0);
3935 EXPECT_EQ(cryptoState->oneRttStream.retransmissionBuffer.size(), 0);
3936
3937 auto& aead = getInitialCipher();
3938 auto& headerCipher = getInitialHeaderCipher();
3939 // initial
3940 {
3941 AckBlocks acks;
3942 auto start = getFirstOutstandingPacket(
3943 client->getNonConstConn(), PacketNumberSpace::Initial)
3944 ->packet.header.getPacketSequenceNum();
3945 auto end = getLastOutstandingPacket(
3946 client->getNonConstConn(), PacketNumberSpace::Initial)
3947 ->packet.header.getPacketSequenceNum();
3948 acks.insert(start, end);
3949 auto pn = initialPacketNum++;
3950 auto ackPkt = createAckPacket(
3951 client->getNonConstConn(), pn, acks, PacketNumberSpace::Initial, &aead);
3952 deliverData(
3953 packetToBufCleartext(ackPkt, aead, headerCipher, pn)->coalesce());
3954 EXPECT_EQ(cryptoState->initialStream.retransmissionBuffer.size(), 0);
3955 EXPECT_GT(cryptoState->handshakeStream.retransmissionBuffer.size(), 0);
3956 EXPECT_EQ(cryptoState->oneRttStream.retransmissionBuffer.size(), 0);
3957 }
3958 // handshake
3959 {
3960 AckBlocks acks;
3961 auto start = getFirstOutstandingPacket(
3962 client->getNonConstConn(), PacketNumberSpace::Handshake)
3963 ->packet.header.getPacketSequenceNum();
3964 auto end = getLastOutstandingPacket(
3965 client->getNonConstConn(), PacketNumberSpace::Handshake)
3966 ->packet.header.getPacketSequenceNum();
3967 acks.insert(start, end);
3968 auto pn = handshakePacketNum++;
3969 auto ackPkt = createAckPacket(
3970 client->getNonConstConn(), pn, acks, PacketNumberSpace::Handshake);
3971 deliverData(packetToBuf(ackPkt)->coalesce());
3972 EXPECT_EQ(cryptoState->initialStream.retransmissionBuffer.size(), 0);
3973 EXPECT_EQ(cryptoState->handshakeStream.retransmissionBuffer.size(), 0);
3974 EXPECT_EQ(cryptoState->oneRttStream.retransmissionBuffer.size(), 0);
3975 }
3976 }
3977
TEST_F(QuicClientTransportAfterStartTest,RecvOneRttAck)3978 TEST_F(QuicClientTransportAfterStartTest, RecvOneRttAck) {
3979 EXPECT_GT(
3980 client->getConn().cryptoState->initialStream.retransmissionBuffer.size(),
3981 0);
3982 EXPECT_GT(
3983 client->getConn()
3984 .cryptoState->handshakeStream.retransmissionBuffer.size(),
3985 0);
3986
3987 // Client doesn't send one rtt crypto data today
3988 EXPECT_EQ(
3989 client->getConn().cryptoState->oneRttStream.retransmissionBuffer.size(),
3990 0);
3991 StreamId streamId = client->createBidirectionalStream().value();
3992
3993 auto expected = IOBuf::copyBuffer("hello");
3994 client->setReadCallback(streamId, &readCb);
3995 client->writeChain(streamId, expected->clone(), true);
3996 loopForWrites();
3997
3998 AckBlocks sentPackets;
3999 verifyShortPackets(sentPackets);
4000
4001 // Write an AckFrame back to client:
4002 auto ackPacket = packetToBuf(createAckPacket(
4003 client->getNonConstConn(),
4004 ++appDataPacketNum,
4005 sentPackets,
4006 PacketNumberSpace::AppData));
4007 deliverData(ackPacket->coalesce());
4008
4009 // Should have canceled retransmissions
4010 EXPECT_EQ(
4011 client->getConn().cryptoState->initialStream.retransmissionBuffer.size(),
4012 0);
4013 EXPECT_EQ(
4014 client->getConn()
4015 .cryptoState->handshakeStream.retransmissionBuffer.size(),
4016 0);
4017 }
4018
TEST_P(QuicClientTransportAfterStartTestClose,CloseConnectionWithError)4019 TEST_P(QuicClientTransportAfterStartTestClose, CloseConnectionWithError) {
4020 StreamId streamId = client->createBidirectionalStream().value();
4021
4022 auto expected = IOBuf::copyBuffer("hello");
4023 client->setReadCallback(streamId, &readCb);
4024 client->writeChain(streamId, expected->clone(), true);
4025 loopForWrites();
4026 auto packet = packetToBuf(createStreamPacket(
4027 *serverChosenConnId /* src */,
4028 *originalConnId /* dest */,
4029 appDataPacketNum++,
4030 streamId,
4031 *expected,
4032 0 /* cipherOverhead */,
4033 0 /* largestAcked */,
4034 folly::none,
4035 true));
4036 deliverData(packet->coalesce());
4037 socketWrites.clear();
4038 if (GetParam()) {
4039 client->close(std::make_pair(
4040 QuicErrorCode(GenericApplicationErrorCode::UNKNOWN),
4041 std::string("stopping")));
4042 EXPECT_TRUE(verifyFramePresent(
4043 socketWrites,
4044 *makeHandshakeCodec(),
4045 QuicFrame::Type::ConnectionCloseFrame));
4046 } else {
4047 client->close(folly::none);
4048 EXPECT_TRUE(verifyFramePresent(
4049 socketWrites,
4050 *makeHandshakeCodec(),
4051 QuicFrame::Type::ConnectionCloseFrame));
4052 }
4053 }
4054
4055 class QuicClientTransportAfterStartTestTimeout
4056 : public QuicClientTransportAfterStartTestBase,
4057 public testing::WithParamInterface<QuicVersion> {};
4058
4059 INSTANTIATE_TEST_CASE_P(
4060 QuicClientTransportAfterStartTestTimeouts,
4061 QuicClientTransportAfterStartTestTimeout,
4062 Values(QuicVersion::MVFST, QuicVersion::QUIC_V1, QuicVersion::QUIC_DRAFT));
4063
TEST_P(QuicClientTransportAfterStartTestTimeout,HandshakeCipherTimeoutAfterFirstData)4064 TEST_P(
4065 QuicClientTransportAfterStartTestTimeout,
4066 HandshakeCipherTimeoutAfterFirstData) {
4067 client->getNonConstConn().version = GetParam();
4068 StreamId streamId = client->createBidirectionalStream().value();
4069
4070 EXPECT_NE(client->getConn().readCodec->getInitialCipher(), nullptr);
4071 auto expected = IOBuf::copyBuffer("hello");
4072 auto packet = packetToBuf(createStreamPacket(
4073 *serverChosenConnId /* src */,
4074 *originalConnId /* dest */,
4075 appDataPacketNum++,
4076 streamId,
4077 *expected,
4078 0 /* cipherOverhead */,
4079 0 /* largestAcked */,
4080 folly::none,
4081 true));
4082 deliverData(packet->coalesce());
4083 EXPECT_NE(client->getConn().readCodec->getInitialCipher(), nullptr);
4084 EXPECT_FALSE(client->getConn().readCodec->getHandshakeDoneTime().has_value());
4085 }
4086
TEST_F(QuicClientTransportAfterStartTest,IdleTimerResetOnRecvNewData)4087 TEST_F(QuicClientTransportAfterStartTest, IdleTimerResetOnRecvNewData) {
4088 // spend some time looping the evb
4089 for (int i = 0; i < 10; ++i) {
4090 eventbase_->loopOnce(EVLOOP_NONBLOCK);
4091 }
4092 StreamId streamId = client->createBidirectionalStream().value();
4093 auto expected = IOBuf::copyBuffer("hello");
4094 auto packet = packetToBuf(createStreamPacket(
4095 *serverChosenConnId /* src */,
4096 *originalConnId /* dest */,
4097 appDataPacketNum++,
4098 streamId,
4099 *expected,
4100 0 /* cipherOverhead */,
4101 0 /* largestAcked */));
4102
4103 client->idleTimeout().cancelTimeout();
4104 ASSERT_FALSE(client->idleTimeout().isScheduled());
4105 deliverData(packet->coalesce());
4106 ASSERT_TRUE(client->getConn().receivedNewPacketBeforeWrite);
4107 ASSERT_TRUE(client->idleTimeout().isScheduled());
4108
4109 auto packet2 = packetToBuf(createStreamPacket(
4110 *serverChosenConnId /* src */,
4111 *originalConnId /* dest */,
4112 appDataPacketNum++,
4113 streamId,
4114 *expected,
4115 0 /* cipherOverhead */,
4116 0 /* largestAcked */));
4117 client->idleTimeout().cancelTimeout();
4118 ASSERT_FALSE(client->idleTimeout().isScheduled());
4119 deliverData(packet2->coalesce());
4120 ASSERT_TRUE(client->getConn().receivedNewPacketBeforeWrite);
4121 ASSERT_TRUE(client->idleTimeout().isScheduled());
4122 }
4123
TEST_F(QuicClientTransportAfterStartTest,IdleTimerNotResetOnDuplicatePacket)4124 TEST_F(QuicClientTransportAfterStartTest, IdleTimerNotResetOnDuplicatePacket) {
4125 StreamId streamId = client->createBidirectionalStream().value();
4126
4127 auto expected = IOBuf::copyBuffer("hello");
4128 auto packet = packetToBuf(createStreamPacket(
4129 *serverChosenConnId /* src */,
4130 *originalConnId /* dest */,
4131 appDataPacketNum++,
4132 streamId,
4133 *expected,
4134 0 /* cipherOverhead */,
4135 0 /* largestAcked */));
4136
4137 // Writes may cause idle timer to be set, so don't loop for a write.
4138 deliverData(packet->coalesce(), false);
4139
4140 ASSERT_TRUE(client->getConn().receivedNewPacketBeforeWrite);
4141 ASSERT_TRUE(client->idleTimeout().isScheduled());
4142
4143 client->idleTimeout().cancelTimeout();
4144 client->getNonConstConn().receivedNewPacketBeforeWrite = false;
4145 ASSERT_FALSE(client->idleTimeout().isScheduled());
4146 // Try delivering the same packet again
4147 deliverData(packet->coalesce(), false);
4148
4149 ASSERT_FALSE(client->getConn().receivedNewPacketBeforeWrite);
4150 ASSERT_FALSE(client->idleTimeout().isScheduled());
4151 client->closeNow(folly::none);
4152 }
4153
TEST_P(QuicClientTransportAfterStartTestClose,TimeoutsNotSetAfterClose)4154 TEST_P(QuicClientTransportAfterStartTestClose, TimeoutsNotSetAfterClose) {
4155 expectQuicStatsPacketDrop(
4156 QuicTransportStatsCallback::PacketDropReason::CLIENT_STATE_CLOSED);
4157 auto qLogger = std::make_shared<FileQLogger>(VantagePoint::Client);
4158 client->getNonConstConn().qLogger = qLogger;
4159 StreamId streamId = client->createBidirectionalStream().value();
4160
4161 auto expected = IOBuf::copyBuffer("hello");
4162 auto packet = packetToBuf(createStreamPacket(
4163 *serverChosenConnId /* src */,
4164 *originalConnId /* dest */,
4165 appDataPacketNum++,
4166 streamId,
4167 *expected,
4168 0 /* cipherOverhead */,
4169 0 /* largestAcked */));
4170
4171 if (GetParam()) {
4172 client->close(std::make_pair(
4173 QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
4174 std::string("how about no")));
4175 } else {
4176 client->close(folly::none);
4177 }
4178 client->idleTimeout().cancelTimeout();
4179 ASSERT_FALSE(client->idleTimeout().isScheduled());
4180
4181 deliverDataWithoutErrorCheck(packet->coalesce());
4182 ASSERT_FALSE(client->idleTimeout().isScheduled());
4183 ASSERT_FALSE(client->lossTimeout().isScheduled());
4184 ASSERT_FALSE(client->ackTimeout().isScheduled());
4185 ASSERT_TRUE(client->drainTimeout().isScheduled());
4186
4187 std::vector<int> indices =
4188 getQLogEventIndices(QLogEventType::PacketDrop, qLogger);
4189 EXPECT_EQ(indices.size(), 1);
4190 auto tmp = std::move(qLogger->logs[indices[0]]);
4191 auto event = dynamic_cast<QLogPacketDropEvent*>(tmp.get());
4192 EXPECT_EQ(event->packetSize, 0);
4193 EXPECT_EQ(event->dropReason, kAlreadyClosed);
4194 }
4195
TEST_F(QuicClientTransportAfterStartTest,IdleTimerNotResetOnWritingOldData)4196 TEST_F(QuicClientTransportAfterStartTest, IdleTimerNotResetOnWritingOldData) {
4197 StreamId streamId = client->createBidirectionalStream().value();
4198
4199 // There should still be outstanding packets
4200 auto expected = IOBuf::copyBuffer("hello");
4201 client->idleTimeout().cancelTimeout();
4202 ASSERT_FALSE(client->idleTimeout().isScheduled());
4203 client->writeChain(streamId, expected->clone(), false);
4204 loopForWrites();
4205
4206 ASSERT_FALSE(client->getConn().receivedNewPacketBeforeWrite);
4207 ASSERT_FALSE(client->idleTimeout().isScheduled());
4208 client->closeNow(folly::none);
4209 }
4210
TEST_F(QuicClientTransportAfterStartTest,IdleTimerResetNoOutstandingPackets)4211 TEST_F(QuicClientTransportAfterStartTest, IdleTimerResetNoOutstandingPackets) {
4212 // This will clear out all the outstanding packets
4213 AckBlocks sentPackets;
4214 for (auto& packet : client->getNonConstConn().outstandings.packets) {
4215 auto packetNum = packet.packet.header.getPacketSequenceNum();
4216 sentPackets.insert(packetNum);
4217 }
4218 auto ackPacket = packetToBuf(createAckPacket(
4219 client->getNonConstConn(),
4220 ++appDataPacketNum,
4221 sentPackets,
4222 PacketNumberSpace::AppData));
4223 deliverData(ackPacket->coalesce());
4224
4225 // Clear out all the outstanding packets to simulate quiescent state.
4226 client->getNonConstConn().receivedNewPacketBeforeWrite = false;
4227 client->getNonConstConn().outstandings.packets.clear();
4228 client->getNonConstConn().outstandings.packetCount = {};
4229 client->getNonConstConn().outstandings.clonedPacketCount = {};
4230 client->idleTimeout().cancelTimeout();
4231 auto streamId = client->createBidirectionalStream().value();
4232 auto expected = folly::IOBuf::copyBuffer("hello");
4233 client->writeChain(streamId, expected->clone(), false);
4234 loopForWrites();
4235 ASSERT_TRUE(client->idleTimeout().isScheduled());
4236 }
4237
TEST_F(QuicClientTransportAfterStartTest,IdleTimeoutExpired)4238 TEST_F(QuicClientTransportAfterStartTest, IdleTimeoutExpired) {
4239 EXPECT_CALL(*sock, close());
4240 socketWrites.clear();
4241 client->idleTimeout().timeoutExpired();
4242
4243 EXPECT_FALSE(client->idleTimeout().isScheduled());
4244 EXPECT_TRUE(client->isDraining());
4245 EXPECT_TRUE(client->isClosed());
4246
4247 auto serverCodec = makeEncryptedCodec();
4248 // We expect a conn close in a cleartext packet.
4249 EXPECT_FALSE(verifyFramePresent(
4250 socketWrites, *serverCodec, QuicFrame::Type::ConnectionCloseFrame));
4251 EXPECT_FALSE(verifyFramePresent(
4252 socketWrites, *serverCodec, QuicFrame::Type::ConnectionCloseFrame));
4253 EXPECT_TRUE(socketWrites.empty());
4254 }
4255
TEST_F(QuicClientTransportAfterStartTest,RecvDataAfterIdleTimeout)4256 TEST_F(QuicClientTransportAfterStartTest, RecvDataAfterIdleTimeout) {
4257 expectQuicStatsPacketDrop(
4258 QuicTransportStatsCallback::PacketDropReason::CLIENT_STATE_CLOSED);
4259 auto qLogger = std::make_shared<FileQLogger>(VantagePoint::Client);
4260 client->getNonConstConn().qLogger = qLogger;
4261 EXPECT_CALL(*sock, close());
4262 client->idleTimeout().timeoutExpired();
4263
4264 socketWrites.clear();
4265 StreamId streamId = 11;
4266 auto expected = IOBuf::copyBuffer("hello");
4267 auto packet = packetToBuf(createStreamPacket(
4268 *serverChosenConnId /* src */,
4269 *originalConnId /* dest */,
4270 appDataPacketNum++,
4271 streamId,
4272 *expected,
4273 0 /* cipherOverhead */,
4274 0 /* largestAcked */));
4275 deliverData(packet->coalesce());
4276 EXPECT_TRUE(verifyFramePresent(
4277 socketWrites,
4278 *makeEncryptedCodec(true),
4279 QuicFrame::Type::ConnectionCloseFrame));
4280 std::vector<int> indices =
4281 getQLogEventIndices(QLogEventType::PacketDrop, qLogger);
4282 EXPECT_EQ(indices.size(), 1);
4283 auto tmp = std::move(qLogger->logs[indices[0]]);
4284 auto event = dynamic_cast<QLogPacketDropEvent*>(tmp.get());
4285 EXPECT_EQ(event->packetSize, 0);
4286 EXPECT_EQ(event->dropReason, kAlreadyClosed);
4287 }
4288
TEST_F(QuicClientTransportAfterStartTest,InvalidStream)4289 TEST_F(QuicClientTransportAfterStartTest, InvalidStream) {
4290 StreamId streamId = 10;
4291 auto expected = IOBuf::copyBuffer("hello");
4292 auto packet = packetToBuf(createStreamPacket(
4293 *serverChosenConnId /* src */,
4294 *originalConnId /* dest */,
4295 appDataPacketNum++,
4296 streamId,
4297 *expected,
4298 0 /* cipherOverhead */,
4299 0 /* largestAcked */));
4300 EXPECT_THROW(deliverData(packet->coalesce()), std::runtime_error);
4301 }
4302
TEST_F(QuicClientTransportAfterStartTest,WrongCleartextCipher)4303 TEST_F(QuicClientTransportAfterStartTest, WrongCleartextCipher) {
4304 FizzCryptoFactory cryptoFactory;
4305 StreamId streamId = client->createBidirectionalStream().value();
4306
4307 auto expected = IOBuf::copyBuffer("hello");
4308 // Test sending packet with wrong connection id, should drop it, it normally
4309 // throws on getting unencrypted stream data.
4310 PacketNum nextPacketNum = appDataPacketNum++;
4311
4312 auto initialCipher = cryptoFactory.getServerInitialCipher(
4313 *serverChosenConnId, QuicVersion::MVFST);
4314 auto packet = packetToBufCleartext(
4315 createStreamPacket(
4316 *serverChosenConnId /* src */,
4317 *originalConnId /* dest */,
4318 nextPacketNum,
4319 streamId,
4320 *expected,
4321 initialCipher->getCipherOverhead(),
4322 0 /* largestAcked */,
4323 std::make_pair(LongHeader::Types::Initial, QuicVersion::MVFST)),
4324 *initialCipher,
4325 getInitialHeaderCipher(),
4326 nextPacketNum);
4327 deliverData(packet->coalesce());
4328 }
4329
TEST_F(QuicClientTransportAfterStartTest,ReceiveRstStreamNonExistentClientStream)4330 TEST_F(
4331 QuicClientTransportAfterStartTest,
4332 ReceiveRstStreamNonExistentClientStream) {
4333 StreamId streamId = 0x04;
4334 RstStreamFrame rstFrame(streamId, GenericApplicationErrorCode::UNKNOWN, 0);
4335 ShortHeader header(
4336 ProtectionType::KeyPhaseZero, *originalConnId, appDataPacketNum++);
4337 RegularQuicPacketBuilder builder(
4338 client->getConn().udpSendPacketLen,
4339 std::move(header),
4340 0 /* largestAcked */);
4341 builder.encodePacketHeader();
4342 ASSERT_TRUE(builder.canBuildPacket());
4343 writeFrame(rstFrame, builder);
4344 auto packet = packetToBuf(std::move(builder).buildPacket());
4345 EXPECT_THROW(deliverData(packet->coalesce()), std::runtime_error);
4346 }
4347
TEST_F(QuicClientTransportAfterStartTest,ReceiveRstStreamNonExistentAndOtherFrame)4348 TEST_F(
4349 QuicClientTransportAfterStartTest,
4350 ReceiveRstStreamNonExistentAndOtherFrame) {
4351 StreamId serverUnidirectional = 0x03;
4352
4353 // Deliver reset on peer unidirectional stream to close the stream.
4354 RstStreamFrame rstFrame(
4355 serverUnidirectional, GenericApplicationErrorCode::UNKNOWN, 0);
4356 ShortHeader header(
4357 ProtectionType::KeyPhaseZero, *originalConnId, appDataPacketNum++);
4358 RegularQuicPacketBuilder builder(
4359 client->getConn().udpSendPacketLen,
4360 std::move(header),
4361 0 /* largestAcked */);
4362 builder.encodePacketHeader();
4363 writeFrame(rstFrame, builder);
4364 auto packet = packetToBuf(std::move(builder).buildPacket());
4365 deliverData(packet->coalesce());
4366
4367 auto streamId =
4368 client->createBidirectionalStream(false /* replaySafe */).value();
4369
4370 ShortHeader header2(
4371 ProtectionType::KeyPhaseZero, *originalConnId, appDataPacketNum++);
4372 RegularQuicPacketBuilder builder2(
4373 client->getConn().udpSendPacketLen,
4374 std::move(header),
4375 0 /* largestAcked */);
4376 builder2.encodePacketHeader();
4377 writeFrame(rstFrame, builder2);
4378
4379 auto data = folly::IOBuf::copyBuffer("hello");
4380 writeStreamFrameHeader(
4381 builder2,
4382 streamId,
4383 0,
4384 data->computeChainDataLength(),
4385 data->computeChainDataLength(),
4386 false,
4387 folly::none /* skipLenHint */);
4388 writeStreamFrameData(builder2, data->clone(), data->computeChainDataLength());
4389 auto packetObject = std::move(builder2).buildPacket();
4390 auto packet2 = packetToBuf(std::move(packetObject));
4391 deliverData(packet2->coalesce());
4392
4393 auto readData = client->read(streamId, 0);
4394 ASSERT_TRUE(readData.hasValue());
4395 ASSERT_NE(readData.value().first, nullptr);
4396 EXPECT_TRUE(folly::IOBufEqualTo()(*readData.value().first, *data));
4397 }
4398
TEST_F(QuicClientTransportAfterStartTest,ReceiveRstStreamAfterEom)4399 TEST_F(QuicClientTransportAfterStartTest, ReceiveRstStreamAfterEom) {
4400 // A RstStreamFrame will be written to sock when we receive a RstStreamFrame
4401 auto streamId =
4402 client->createBidirectionalStream(false /* replaySafe */).value();
4403 client->setReadCallback(streamId, &readCb);
4404
4405 EXPECT_CALL(readCb, readAvailable(streamId)).WillOnce(Invoke([&](auto id) {
4406 auto readData = client->read(id, 0);
4407 EXPECT_TRUE(readData->second);
4408 }));
4409
4410 // delivers the eof
4411 auto data = IOBuf::copyBuffer("hello");
4412 auto packet = packetToBuf(createStreamPacket(
4413 *serverChosenConnId /* src */,
4414 *originalConnId /* dest */,
4415 appDataPacketNum++,
4416 streamId,
4417 *data,
4418 0 /* cipherOverhead */,
4419 0 /* largestAcked */));
4420 deliverData(packet->coalesce());
4421
4422 EXPECT_CALL(readCb, readError(streamId, _));
4423
4424 RstStreamFrame rstFrame(
4425 streamId, GenericApplicationErrorCode::UNKNOWN, data->length());
4426 ShortHeader header(
4427 ProtectionType::KeyPhaseZero, *originalConnId, appDataPacketNum++);
4428 RegularQuicPacketBuilder builder(
4429 client->getConn().udpSendPacketLen, std::move(header), 0);
4430 builder.encodePacketHeader();
4431 ASSERT_TRUE(builder.canBuildPacket());
4432 writeFrame(rstFrame, builder);
4433 auto packet2 = packetToBuf(std::move(builder).buildPacket());
4434 deliverData(packet2->coalesce());
4435
4436 EXPECT_TRUE(client->getReadCallbacks().empty());
4437 client->close(folly::none);
4438 }
4439
TEST_F(QuicClientTransportAfterStartTest,SetReadCallbackNullRemembersDelivery)4440 TEST_F(
4441 QuicClientTransportAfterStartTest,
4442 SetReadCallbackNullRemembersDelivery) {
4443 // A RstStreamFrame will be written to sock when we receive a RstStreamFrame
4444 auto streamId =
4445 client->createBidirectionalStream(false /* replaySafe */).value();
4446 client->setReadCallback(streamId, &readCb);
4447
4448 EXPECT_CALL(readCb, readAvailable(streamId)).WillOnce(Invoke([&](auto id) {
4449 auto readData = client->read(id, 0);
4450 EXPECT_TRUE(readData->second);
4451 }));
4452
4453 // delivers the eof
4454 auto data = IOBuf::copyBuffer("hello");
4455 auto packet = packetToBuf(createStreamPacket(
4456 *serverChosenConnId /* src */,
4457 *originalConnId /* dest */,
4458 appDataPacketNum++,
4459 streamId,
4460 *data,
4461 0 /* cipherOverhead */,
4462 0 /* largestAcked */));
4463 deliverData(packet->coalesce());
4464
4465 client->setReadCallback(streamId, nullptr);
4466
4467 AckBlocks sentPackets;
4468 auto writeData = IOBuf::copyBuffer("some data");
4469 client->writeChain(streamId, writeData->clone(), true);
4470 loopForWrites();
4471 verifyShortPackets(sentPackets);
4472
4473 // Write an AckFrame back to client:
4474 auto packet2 = packetToBuf(createAckPacket(
4475 client->getNonConstConn(),
4476 ++appDataPacketNum,
4477 sentPackets,
4478 PacketNumberSpace::AppData));
4479 deliverData(packet2->coalesce());
4480
4481 ASSERT_EQ(
4482 client->getNonConstConn().streamManager->getStream(streamId), nullptr);
4483 client->close(folly::none);
4484 }
4485
TEST_F(QuicClientTransportAfterStartTest,StreamClosedIfReadCallbackNull)4486 TEST_F(QuicClientTransportAfterStartTest, StreamClosedIfReadCallbackNull) {
4487 // A RstStreamFrame will be written to sock when we receive a RstStreamFrame
4488 auto streamId =
4489 client->createBidirectionalStream(false /* replaySafe */).value();
4490
4491 AckBlocks sentPackets;
4492 auto writeData = IOBuf::copyBuffer("some data");
4493 client->writeChain(streamId, writeData->clone(), true);
4494 loopForWrites();
4495 verifyShortPackets(sentPackets);
4496
4497 // Write an AckFrame back to client:
4498 auto packet2 = packetToBuf(createAckPacket(
4499 client->getNonConstConn(),
4500 ++appDataPacketNum,
4501 sentPackets,
4502 PacketNumberSpace::AppData));
4503 deliverData(packet2->coalesce());
4504
4505 // delivers the eof. Even though there is no read callback, we still need an
4506 // EOM or error to terminate the stream.
4507 auto data = IOBuf::copyBuffer("hello");
4508 auto packet = packetToBuf(createStreamPacket(
4509 *serverChosenConnId /* src */,
4510 *originalConnId /* dest */,
4511 appDataPacketNum++,
4512 streamId,
4513 *data,
4514 0 /* cipherOverhead */,
4515 0 /* largestAcked */));
4516 deliverData(packet->coalesce());
4517
4518 ASSERT_EQ(
4519 client->getNonConstConn().streamManager->getStream(streamId), nullptr);
4520 client->close(folly::none);
4521 }
4522
TEST_F(QuicClientTransportAfterStartTest,ReceiveAckInvokesDeliveryCallback)4523 TEST_F(QuicClientTransportAfterStartTest, ReceiveAckInvokesDeliveryCallback) {
4524 AckBlocks sentPackets;
4525 auto streamId =
4526 client->createBidirectionalStream(false /* replaySafe */).value();
4527 client->registerDeliveryCallback(streamId, 0, &deliveryCallback);
4528
4529 auto data = IOBuf::copyBuffer("some data");
4530 client->writeChain(streamId, data->clone(), true);
4531 loopForWrites();
4532
4533 verifyShortPackets(sentPackets);
4534
4535 // Write an AckFrame back to client:
4536 auto packet = packetToBuf(createAckPacket(
4537 client->getNonConstConn(),
4538 ++appDataPacketNum,
4539 sentPackets,
4540 PacketNumberSpace::AppData));
4541
4542 EXPECT_CALL(deliveryCallback, onDeliveryAck(streamId, 0, _)).Times(1);
4543 deliverData(packet->coalesce());
4544 client->close(folly::none);
4545 }
4546
TEST_F(QuicClientTransportAfterStartTest,InvokesDeliveryCallbackFinOnly)4547 TEST_F(QuicClientTransportAfterStartTest, InvokesDeliveryCallbackFinOnly) {
4548 AckBlocks sentPackets;
4549 auto streamId =
4550 client->createBidirectionalStream(false /* replaySafe */).value();
4551
4552 auto data = IOBuf::copyBuffer("some data");
4553 client->writeChain(streamId, nullptr, true, &deliveryCallback);
4554 loopForWrites();
4555
4556 verifyShortPackets(sentPackets);
4557 ASSERT_EQ(sentPackets.size(), 1);
4558
4559 // Write an AckFrame back to client:
4560 auto packet = packetToBuf(createAckPacket(
4561 client->getNonConstConn(),
4562 ++appDataPacketNum,
4563 sentPackets,
4564 PacketNumberSpace::AppData));
4565
4566 EXPECT_CALL(deliveryCallback, onDeliveryAck(streamId, _, _)).Times(1);
4567 deliverData(packet->coalesce());
4568 client->close(folly::none);
4569 }
4570
TEST_F(QuicClientTransportAfterStartTest,RegisterDeliveryCallbackForAlreadyDeliveredOffset)4571 TEST_F(
4572 QuicClientTransportAfterStartTest,
4573 RegisterDeliveryCallbackForAlreadyDeliveredOffset) {
4574 AckBlocks sentPackets;
4575
4576 auto streamId =
4577 client->createBidirectionalStream(false /* replaySafe */).value();
4578
4579 auto data = IOBuf::copyBuffer("some data");
4580 client->writeChain(streamId, data->clone(), true);
4581
4582 loopForWrites();
4583 verifyShortPackets(sentPackets);
4584
4585 // Write an AckFrame back to client:
4586 auto packet = packetToBuf(createAckPacket(
4587 client->getNonConstConn(),
4588 ++appDataPacketNum,
4589 sentPackets,
4590 PacketNumberSpace::AppData));
4591 deliverData(packet->coalesce());
4592
4593 // Register a DeliveryCallback for an offset that's already delivered, will
4594 // callback immediately
4595 EXPECT_CALL(deliveryCallback, onDeliveryAck(streamId, 0, _)).Times(1);
4596 client->registerDeliveryCallback(streamId, 0, &deliveryCallback);
4597 eventbase_->loopOnce();
4598 client->close(folly::none);
4599 }
4600
TEST_F(QuicClientTransportAfterStartTest,DeliveryCallbackFromWriteChain)4601 TEST_F(QuicClientTransportAfterStartTest, DeliveryCallbackFromWriteChain) {
4602 AckBlocks sentPackets;
4603 auto streamId =
4604 client->createBidirectionalStream(false /* replaySafe */).value();
4605
4606 // Write 10 bytes of data, and write EOF on an empty stream. So EOF offset is
4607 // 10
4608 auto data = test::buildRandomInputData(10);
4609 client->writeChain(streamId, data->clone(), true, &deliveryCallback);
4610
4611 loopForWrites();
4612 verifyShortPackets(sentPackets);
4613
4614 // Write an AckFrame back to client:
4615 auto packet = packetToBuf(createAckPacket(
4616 client->getNonConstConn(),
4617 ++appDataPacketNum,
4618 sentPackets,
4619 PacketNumberSpace::AppData));
4620
4621 // DeliveryCallback is called, and offset delivered is 10:
4622 EXPECT_CALL(deliveryCallback, onDeliveryAck(streamId, 10, _)).Times(1);
4623 deliverData(packet->coalesce());
4624 client->close(folly::none);
4625 }
4626
TEST_F(QuicClientTransportAfterStartTest,NotifyPendingWrite)4627 TEST_F(QuicClientTransportAfterStartTest, NotifyPendingWrite) {
4628 NiceMock<MockWriteCallback> writeCallback;
4629 EXPECT_CALL(writeCallback, onConnectionWriteReady(_));
4630 client->notifyPendingWriteOnConnection(&writeCallback);
4631 loopForWrites();
4632 client->close(folly::none);
4633 }
4634
TEST_F(QuicClientTransportAfterStartTest,SwitchEvbWhileAsyncEventPending)4635 TEST_F(QuicClientTransportAfterStartTest, SwitchEvbWhileAsyncEventPending) {
4636 NiceMock<MockWriteCallback> writeCallback;
4637 EventBase evb2;
4638 EXPECT_CALL(writeCallback, onConnectionWriteReady(_)).Times(0);
4639 client->notifyPendingWriteOnConnection(&writeCallback);
4640 client->detachEventBase();
4641 client->attachEventBase(&evb2);
4642 loopForWrites();
4643 client->close(folly::none);
4644 }
4645
TEST_F(QuicClientTransportAfterStartTest,StatelessResetClosesTransport)4646 TEST_F(QuicClientTransportAfterStartTest, StatelessResetClosesTransport) {
4647 // Make decrypt fail for the reset token
4648 auto aead = dynamic_cast<const MockAead*>(
4649 client->getNonConstConn().readCodec->getOneRttReadCipher());
4650 ASSERT_TRUE(aead);
4651
4652 // Make the decrypt fail
4653 EXPECT_CALL(*aead, _tryDecrypt(_, _, _))
4654 .WillRepeatedly(Invoke([&](auto&, auto, auto) { return folly::none; }));
4655
4656 auto token = *client->getConn().statelessResetToken;
4657 StatelessResetPacketBuilder builder(kDefaultUDPSendPacketLen, token);
4658 auto packet = std::move(builder).buildPacket();
4659 EXPECT_CALL(clientConnCallback, onConnectionError(_));
4660 deliverDataWithoutErrorCheck(packet->coalesce());
4661 EXPECT_TRUE(client->isClosed());
4662 client.reset();
4663 EXPECT_TRUE(destructionCallback->isDestroyed());
4664 }
4665
TEST_F(QuicClientTransportAfterStartTest,BadStatelessResetWontCloseTransport)4666 TEST_F(QuicClientTransportAfterStartTest, BadStatelessResetWontCloseTransport) {
4667 auto aead = dynamic_cast<const MockAead*>(
4668 client->getNonConstConn().readCodec->getOneRttReadCipher());
4669 ASSERT_TRUE(aead);
4670 // Make the decrypt fail
4671 EXPECT_CALL(*aead, _tryDecrypt(_, _, _))
4672 .WillRepeatedly(Invoke([&](auto&, auto, auto) { return folly::none; }));
4673 // Alter the expected token so it definitely won't match the one in conn
4674 auto token = *client->getConn().statelessResetToken;
4675 token[0] = ~token[0];
4676 StatelessResetPacketBuilder builder(kDefaultUDPSendPacketLen, token);
4677 auto packet = std::move(builder).buildPacket();
4678 // onConnectionError won't be invoked
4679 EXPECT_CALL(clientConnCallback, onConnectionError(_)).Times(0);
4680 deliverDataWithoutErrorCheck(packet->coalesce());
4681 EXPECT_FALSE(client->isClosed());
4682 EXPECT_FALSE(client->isDraining());
4683 client.reset();
4684 EXPECT_FALSE(destructionCallback->isDestroyed());
4685 }
4686
TEST_F(QuicClientTransportVersionAndRetryTest,RetryPacket)4687 TEST_F(QuicClientTransportVersionAndRetryTest, RetryPacket) {
4688 std::vector<uint8_t> clientConnIdVec = {};
4689 ConnectionId clientConnId(clientConnIdVec);
4690
4691 ConnectionId initialDstConnId(kInitialDstConnIdVecForRetryTest);
4692
4693 // Create a stream and attempt to send some data to the server
4694 auto qLogger = std::make_shared<FileQLogger>(VantagePoint::Client);
4695 client->getNonConstConn().qLogger = qLogger;
4696 client->getNonConstConn().readCodec->setClientConnectionId(clientConnId);
4697 client->getNonConstConn().initialDestinationConnectionId = initialDstConnId;
4698 client->getNonConstConn().originalDestinationConnectionId = initialDstConnId;
4699
4700 client->setCongestionControllerFactory(
4701 std::make_shared<DefaultCongestionControllerFactory>());
4702 client->setCongestionControl(CongestionControlType::NewReno);
4703
4704 StreamId streamId = *client->createBidirectionalStream();
4705 auto write = IOBuf::copyBuffer("ice cream");
4706 client->writeChain(streamId, write->clone(), true, nullptr);
4707 loopForWrites();
4708
4709 std::unique_ptr<IOBuf> bytesWrittenToNetwork = nullptr;
4710
4711 EXPECT_CALL(*sock, write(_, _))
4712 .WillRepeatedly(Invoke(
4713 [&](const SocketAddress&, const std::unique_ptr<folly::IOBuf>& buf) {
4714 bytesWrittenToNetwork = buf->clone();
4715 return buf->computeChainDataLength();
4716 }));
4717
4718 auto serverCid = recvServerRetry(serverAddr);
4719 ASSERT_TRUE(bytesWrittenToNetwork);
4720
4721 // Check CC is kept after retry recreates QuicClientConnectionState
4722 EXPECT_TRUE(client->getConn().congestionControllerFactory);
4723 EXPECT_EQ(
4724 client->getConn().congestionController->type(),
4725 CongestionControlType::NewReno);
4726
4727 // Check to see that the server receives an initial packet with the following
4728 // properties:
4729 // 1. The token in the initial packet matches the token sent in the retry
4730 // packet
4731 // 2. The destination connection id matches the connection id that the server
4732 // chose when it sent the retry packet
4733 AckStates ackStates;
4734 auto packetQueue = bufToQueue(bytesWrittenToNetwork->clone());
4735 auto codecResult =
4736 makeEncryptedCodec(true)->parsePacket(packetQueue, ackStates);
4737
4738 auto& regularQuicPacket = *codecResult.regularPacket();
4739 auto& header = *regularQuicPacket.header.asLong();
4740
4741 EXPECT_EQ(header.getHeaderType(), LongHeader::Types::Initial);
4742 EXPECT_TRUE(header.hasToken());
4743 EXPECT_EQ(header.getToken(), std::string("token"));
4744 EXPECT_EQ(header.getDestinationConnId(), serverCid);
4745
4746 eventbase_->loopOnce();
4747 client->close(folly::none);
4748 }
4749
TEST_F(QuicClientTransportVersionAndRetryTest,VersionNegotiationPacketNotSupported)4750 TEST_F(
4751 QuicClientTransportVersionAndRetryTest,
4752 VersionNegotiationPacketNotSupported) {
4753 StreamId streamId = *client->createBidirectionalStream();
4754
4755 client->setReadCallback(streamId, &readCb);
4756
4757 auto write = IOBuf::copyBuffer("no");
4758 client->writeChain(streamId, write->clone(), true, &deliveryCallback);
4759 loopForWrites();
4760 auto packet = VersionNegotiationPacketBuilder(
4761 *client->getConn().initialDestinationConnectionId,
4762 *originalConnId,
4763 {MVFST2})
4764 .buildPacket();
4765 EXPECT_CALL(
4766 readCb,
4767 readError(streamId, IsError(LocalErrorCode::CONNECTION_ABANDONED)));
4768 EXPECT_CALL(deliveryCallback, onCanceled(streamId, write->length()));
4769 EXPECT_THROW(deliverData(packet.second->coalesce()), std::runtime_error);
4770
4771 EXPECT_EQ(client->getConn().oneRttWriteCipher.get(), nullptr);
4772 EXPECT_CALL(clientConnCallback, onTransportReady()).Times(0);
4773 EXPECT_CALL(clientConnCallback, onReplaySafe()).Times(0);
4774 client->close(folly::none);
4775 }
4776
TEST_F(QuicClientTransportVersionAndRetryTest,VersionNegotiationPacketCurrentVersion)4777 TEST_F(
4778 QuicClientTransportVersionAndRetryTest,
4779 VersionNegotiationPacketCurrentVersion) {
4780 StreamId streamId = *client->createBidirectionalStream();
4781
4782 client->setReadCallback(streamId, &readCb);
4783
4784 auto write = IOBuf::copyBuffer("no");
4785 client->writeChain(streamId, write->clone(), true, &deliveryCallback);
4786 loopForWrites();
4787
4788 auto packet = VersionNegotiationPacketBuilder(
4789 *client->getConn().initialDestinationConnectionId,
4790 *originalConnId,
4791 {QuicVersion::MVFST})
4792 .buildPacket();
4793 EXPECT_THROW(deliverData(packet.second->coalesce()), std::runtime_error);
4794 client->close(folly::none);
4795 }
4796
TEST_F(QuicClientTransportVersionAndRetryTest,UnencryptedStreamData)4797 TEST_F(QuicClientTransportVersionAndRetryTest, UnencryptedStreamData) {
4798 StreamId streamId = *client->createBidirectionalStream();
4799 auto expected = IOBuf::copyBuffer("hello");
4800 PacketNum nextPacketNum = appDataPacketNum++;
4801 auto packet = packetToBufCleartext(
4802 createStreamPacket(
4803 *serverChosenConnId /* src */,
4804 *originalConnId /* dest */,
4805 nextPacketNum,
4806 streamId,
4807 *expected,
4808 getInitialCipher().getCipherOverhead(),
4809 0 /* largestAcked */,
4810 std::make_pair(LongHeader::Types::Initial, QuicVersion::MVFST)),
4811 getInitialCipher(),
4812 getInitialHeaderCipher(),
4813 nextPacketNum);
4814 EXPECT_THROW(deliverData(packet->coalesce()), std::runtime_error);
4815 }
4816
TEST_F(QuicClientTransportVersionAndRetryTest,UnencryptedAckData)4817 TEST_F(QuicClientTransportVersionAndRetryTest, UnencryptedAckData) {
4818 AckBlocks acks = {{1, 2}};
4819 auto expected = IOBuf::copyBuffer("hello");
4820 PacketNum nextPacketNum = initialPacketNum++;
4821 LongHeader header(
4822 LongHeader::Types::Initial,
4823 getTestConnectionId(),
4824 *client->getConn().clientConnectionId,
4825 nextPacketNum,
4826 version);
4827 RegularQuicPacketBuilder builder(
4828 kDefaultUDPSendPacketLen, std::move(header), 0 /* largestAcked */);
4829 builder.encodePacketHeader();
4830 DCHECK(builder.canBuildPacket());
4831 AckFrameMetaData ackData(acks, 0us, 0);
4832 writeAckFrame(ackData, builder);
4833 auto packet = packetToBufCleartext(
4834 std::move(builder).buildPacket(),
4835 getInitialCipher(),
4836 getInitialHeaderCipher(),
4837 nextPacketNum);
4838 EXPECT_NO_THROW(deliverData(packet->coalesce()));
4839 }
4840
TEST_F(QuicClientTransportVersionAndRetryTest,UnencryptedPing)4841 TEST_F(QuicClientTransportVersionAndRetryTest, UnencryptedPing) {
4842 PacketNum nextPacketNum = initialPacketNum++;
4843 LongHeader header(
4844 LongHeader::Types::Initial,
4845 getTestConnectionId(),
4846 *client->getConn().clientConnectionId,
4847 nextPacketNum,
4848 version);
4849 RegularQuicPacketBuilder builder(
4850 kDefaultUDPSendPacketLen, std::move(header), 0 /* largestAcked */);
4851 builder.encodePacketHeader();
4852 DCHECK(builder.canBuildPacket());
4853 writeFrame(PingFrame(), builder);
4854 auto packet = packetToBufCleartext(
4855 std::move(builder).buildPacket(),
4856 getInitialCipher(),
4857 getInitialHeaderCipher(),
4858 nextPacketNum);
4859 EXPECT_NO_THROW(deliverData(packet->coalesce()));
4860 }
4861
getHandshakePacketWithFrame(QuicWriteFrame frame,ConnectionId srcConnId,ConnectionId destConnId,const Aead & serverWriteCipher,const PacketNumberCipher & headerCipher)4862 Buf getHandshakePacketWithFrame(
4863 QuicWriteFrame frame,
4864 ConnectionId srcConnId,
4865 ConnectionId destConnId,
4866 const Aead& serverWriteCipher,
4867 const PacketNumberCipher& headerCipher) {
4868 PacketNum packetNum = folly::Random::rand32();
4869 LongHeader header(
4870 LongHeader::Types::Initial,
4871 srcConnId,
4872 destConnId,
4873 packetNum,
4874 QuicVersion::MVFST);
4875 RegularQuicPacketBuilder builder(
4876 kDefaultUDPSendPacketLen,
4877 std::move(header),
4878 packetNum / 2 /* largestAcked */);
4879 builder.encodePacketHeader();
4880 builder.accountForCipherOverhead(serverWriteCipher.getCipherOverhead());
4881 writeFrame(std::move(frame), builder);
4882 return packetToBufCleartext(
4883 std::move(builder).buildPacket(),
4884 serverWriteCipher,
4885 headerCipher,
4886 packetNum);
4887 }
4888
TEST_F(QuicClientTransportVersionAndRetryTest,FrameNotAllowed)4889 TEST_F(QuicClientTransportVersionAndRetryTest, FrameNotAllowed) {
4890 StreamId streamId = *client->createBidirectionalStream();
4891 auto clientConnectionId = *client->getConn().clientConnectionId;
4892 auto serverConnId = *serverChosenConnId;
4893 serverConnId.data()[0] = ~serverConnId.data()[0];
4894
4895 EXPECT_THROW(
4896 deliverData(getHandshakePacketWithFrame(
4897 MaxStreamDataFrame(streamId, 100),
4898 serverConnId /* src */,
4899 clientConnectionId /* dest */,
4900 getInitialCipher(),
4901 getInitialHeaderCipher())
4902 ->coalesce()),
4903 std::runtime_error);
4904 EXPECT_TRUE(client->error());
4905 EXPECT_EQ(client->getConn().clientConnectionId, *originalConnId);
4906 }
4907
TEST_F(QuicClientTransportAfterStartTest,SendReset)4908 TEST_F(QuicClientTransportAfterStartTest, SendReset) {
4909 AckBlocks sentPackets;
4910 StreamId streamId = client->createBidirectionalStream().value();
4911 client->setReadCallback(streamId, &readCb);
4912 client->registerDeliveryCallback(streamId, 100, &deliveryCallback);
4913 EXPECT_CALL(deliveryCallback, onCanceled(streamId, 100));
4914 EXPECT_CALL(readCb, readError(streamId, _));
4915 client->resetStream(streamId, GenericApplicationErrorCode::UNKNOWN);
4916 loopForWrites();
4917 verifyShortPackets(sentPackets);
4918
4919 const auto& readCbs = client->getReadCallbacks();
4920 const auto& conn = client->getConn();
4921 // ReadCallbacks are not affected by reseting send state
4922 EXPECT_EQ(1, readCbs.count(streamId));
4923 // readable list can still be populated after a reset.
4924 EXPECT_FALSE(writableContains(*conn.streamManager, streamId));
4925 auto packet = packetToBuf(createAckPacket(
4926 client->getNonConstConn(),
4927 ++appDataPacketNum,
4928 sentPackets,
4929 PacketNumberSpace::AppData));
4930 deliverData(packet->coalesce());
4931 // Stream is not yet closed because ingress state machine is open
4932 EXPECT_TRUE(conn.streamManager->streamExists(streamId));
4933 client->close(folly::none);
4934 EXPECT_TRUE(client->isClosed());
4935 }
4936
findPacketWithStream(QuicConnectionStateBase & conn,StreamId streamId)4937 RegularQuicWritePacket* findPacketWithStream(
4938 QuicConnectionStateBase& conn,
4939 StreamId streamId) {
4940 auto op = findOutstandingPacket(conn, [=](OutstandingPacket& packet) {
4941 for (auto& frame : packet.packet.frames) {
4942 bool tryPacket = false;
4943 WriteStreamFrame* streamFrame = frame.asWriteStreamFrame();
4944 if (streamFrame) {
4945 tryPacket = streamFrame->streamId == streamId;
4946 }
4947 if (tryPacket) {
4948 return true;
4949 }
4950 }
4951 return false;
4952 });
4953 if (op) {
4954 return &(op->packet);
4955 }
4956 return nullptr;
4957 }
4958
TEST_F(QuicClientTransportAfterStartTest,ResetClearsPendingLoss)4959 TEST_F(QuicClientTransportAfterStartTest, ResetClearsPendingLoss) {
4960 StreamId streamId = client->createBidirectionalStream().value();
4961 client->setReadCallback(streamId, &readCb);
4962 SCOPE_EXIT {
4963 client->close(folly::none);
4964 };
4965 client->writeChain(streamId, IOBuf::copyBuffer("hello"), true);
4966 loopForWrites();
4967 ASSERT_FALSE(client->getConn().outstandings.packets.empty());
4968
4969 RegularQuicWritePacket* forceLossPacket =
4970 CHECK_NOTNULL(findPacketWithStream(client->getNonConstConn(), streamId));
4971 markPacketLoss(client->getNonConstConn(), *forceLossPacket, false);
4972 ASSERT_TRUE(client->getConn().streamManager->hasLoss());
4973
4974 client->resetStream(streamId, GenericApplicationErrorCode::UNKNOWN);
4975 ASSERT_FALSE(client->getConn().streamManager->hasLoss());
4976 }
4977
TEST_F(QuicClientTransportAfterStartTest,LossAfterResetStream)4978 TEST_F(QuicClientTransportAfterStartTest, LossAfterResetStream) {
4979 StreamId streamId = client->createBidirectionalStream().value();
4980 client->setReadCallback(streamId, &readCb);
4981 SCOPE_EXIT {
4982 client->close(folly::none);
4983 };
4984 client->writeChain(streamId, IOBuf::copyBuffer("hello"), true);
4985 loopForWrites();
4986 ASSERT_FALSE(client->getConn().outstandings.packets.empty());
4987
4988 client->resetStream(streamId, GenericApplicationErrorCode::UNKNOWN);
4989
4990 RegularQuicWritePacket* forceLossPacket =
4991 CHECK_NOTNULL(findPacketWithStream(client->getNonConstConn(), streamId));
4992 markPacketLoss(client->getNonConstConn(), *forceLossPacket, false);
4993 auto stream = CHECK_NOTNULL(
4994 client->getNonConstConn().streamManager->getStream(streamId));
4995 ASSERT_TRUE(stream->lossBuffer.empty());
4996 ASSERT_FALSE(client->getConn().streamManager->hasLoss());
4997 }
4998
TEST_F(QuicClientTransportAfterStartTest,SendResetAfterEom)4999 TEST_F(QuicClientTransportAfterStartTest, SendResetAfterEom) {
5000 AckBlocks sentPackets;
5001 StreamId streamId = client->createBidirectionalStream().value();
5002 client->setReadCallback(streamId, &readCb);
5003 client->registerDeliveryCallback(streamId, 100, &deliveryCallback);
5004 EXPECT_CALL(deliveryCallback, onCanceled(streamId, 100));
5005 client->writeChain(streamId, IOBuf::copyBuffer("hello"), true);
5006
5007 client->resetStream(streamId, GenericApplicationErrorCode::UNKNOWN);
5008 loopForWrites();
5009 verifyShortPackets(sentPackets);
5010 const auto& readCbs = client->getReadCallbacks();
5011 const auto& conn = client->getConn();
5012 // ReadCallback are not affected by reseting send state.
5013 EXPECT_EQ(1, readCbs.count(streamId));
5014 // readable list can still be populated after a reset.
5015 EXPECT_FALSE(writableContains(*conn.streamManager, streamId));
5016
5017 auto packet = packetToBuf(createAckPacket(
5018 client->getNonConstConn(),
5019 ++appDataPacketNum,
5020 sentPackets,
5021 PacketNumberSpace::AppData));
5022 deliverData(packet->coalesce());
5023 // Stream still exists since ingress state machine is still open
5024 EXPECT_TRUE(conn.streamManager->streamExists(streamId));
5025 client->close(folly::none);
5026 EXPECT_TRUE(client->isClosed());
5027 }
5028
TEST_F(QuicClientTransportAfterStartTest,HalfClosedLocalToClosed)5029 TEST_F(QuicClientTransportAfterStartTest, HalfClosedLocalToClosed) {
5030 AckBlocks sentPackets;
5031 StreamId streamId = client->createBidirectionalStream().value();
5032 client->setReadCallback(streamId, &readCb);
5033 auto data = test::buildRandomInputData(10);
5034 client->writeChain(streamId, data->clone(), true, &deliveryCallback);
5035 loopForWrites();
5036
5037 verifyShortPackets(sentPackets);
5038
5039 const auto& conn = client->getConn();
5040 EXPECT_CALL(deliveryCallback, onDeliveryAck(streamId, 10, _)).Times(1);
5041 auto ackPacket = packetToBuf(createAckPacket(
5042 client->getNonConstConn(),
5043 ++appDataPacketNum,
5044 sentPackets,
5045 PacketNumberSpace::AppData));
5046 deliverData(ackPacket->coalesce());
5047 EXPECT_FALSE(conn.streamManager->deliverableContains(streamId));
5048
5049 bool dataDelivered = false;
5050 EXPECT_CALL(readCb, readAvailable(streamId)).WillOnce(Invoke([&](auto) {
5051 auto readData = client->read(streamId, 100);
5052 auto copy = readData->first->clone();
5053 dataDelivered = true;
5054 eventbase_->terminateLoopSoon();
5055 }));
5056 auto packet = packetToBuf(createStreamPacket(
5057 *serverChosenConnId /* src */,
5058 *originalConnId /* dest */,
5059 appDataPacketNum++,
5060 streamId,
5061 *data,
5062 0 /* cipherOverhead */,
5063 0 /* largestAcked */));
5064 deliverData(packet->coalesce());
5065 if (!dataDelivered) {
5066 eventbase_->loopForever();
5067 }
5068 EXPECT_TRUE(dataDelivered);
5069 const auto& readCbs = client->getReadCallbacks();
5070 EXPECT_EQ(0, readCbs.count(streamId));
5071 EXPECT_EQ(0, conn.streamManager->readableStreams().count(streamId));
5072 EXPECT_FALSE(conn.streamManager->streamExists(streamId));
5073 client->close(folly::none);
5074 EXPECT_TRUE(client->isClosed());
5075 }
5076
TEST_F(QuicClientTransportAfterStartTest,SendResetSyncOnAck)5077 TEST_F(QuicClientTransportAfterStartTest, SendResetSyncOnAck) {
5078 AckBlocks sentPackets;
5079 StreamId streamId = client->createBidirectionalStream().value();
5080 StreamId streamId2 = client->createBidirectionalStream().value();
5081
5082 NiceMock<MockDeliveryCallback> deliveryCallback2;
5083 auto data = IOBuf::copyBuffer("hello");
5084 client->writeChain(streamId, data->clone(), true, &deliveryCallback);
5085 client->writeChain(streamId2, data->clone(), true, &deliveryCallback2);
5086
5087 EXPECT_CALL(deliveryCallback, onDeliveryAck(streamId, _, _))
5088 .WillOnce(Invoke([&](auto, auto, auto) {
5089 client->resetStream(streamId, GenericApplicationErrorCode::UNKNOWN);
5090 client->resetStream(streamId2, GenericApplicationErrorCode::UNKNOWN);
5091 }));
5092 auto packet1 = packetToBuf(createStreamPacket(
5093 *serverChosenConnId /* src */,
5094 *originalConnId /* dest */,
5095 appDataPacketNum++,
5096 streamId,
5097 *data,
5098 0 /* cipherOverhead */,
5099 0 /* largestAcked */));
5100 auto packet2 = packetToBuf(createStreamPacket(
5101 *serverChosenConnId /* src */,
5102 *originalConnId /* dest */,
5103 appDataPacketNum++,
5104 streamId2,
5105 *data,
5106 0 /* cipherOverhead */,
5107 0 /* largestAcked */));
5108 deliverData(packet1->coalesce());
5109 deliverData(packet2->coalesce());
5110 loopForWrites();
5111 verifyShortPackets(sentPackets);
5112
5113 const auto& readCbs = client->getReadCallbacks();
5114 const auto& conn = client->getConn();
5115 EXPECT_EQ(0, readCbs.count(streamId));
5116 // readable list can still be populated after a reset.
5117 EXPECT_FALSE(writableContains(*conn.streamManager, streamId));
5118 auto packet = packetToBuf(createAckPacket(
5119 client->getNonConstConn(),
5120 ++appDataPacketNum,
5121 sentPackets,
5122 PacketNumberSpace::AppData));
5123 deliverData(packet->coalesce());
5124 // Stream should be closed after it received the ack for rst
5125 EXPECT_FALSE(conn.streamManager->streamExists(streamId));
5126 client->close(folly::none);
5127 EXPECT_TRUE(client->isClosed());
5128 }
5129
TEST_F(QuicClientTransportAfterStartTest,HalfClosedRemoteToClosed)5130 TEST_F(QuicClientTransportAfterStartTest, HalfClosedRemoteToClosed) {
5131 StreamId streamId = client->createBidirectionalStream().value();
5132 client->setReadCallback(streamId, &readCb);
5133 auto data = test::buildRandomInputData(10);
5134 auto packet = packetToBuf(createStreamPacket(
5135 *serverChosenConnId /* src */,
5136 *originalConnId /* dest */,
5137 appDataPacketNum++,
5138 streamId,
5139 *data,
5140 0 /* cipherOverhead */,
5141 0 /* largestAcked */));
5142
5143 bool dataDelivered = false;
5144 EXPECT_CALL(readCb, readAvailable(streamId)).WillOnce(Invoke([&](auto) {
5145 auto readData = client->read(streamId, 100);
5146 auto copy = readData->first->clone();
5147 dataDelivered = true;
5148 eventbase_->terminateLoopSoon();
5149 }));
5150 const auto& conn = client->getConn();
5151 deliverData(packet->coalesce());
5152 if (!dataDelivered) {
5153 eventbase_->loopForever();
5154 }
5155 EXPECT_TRUE(dataDelivered);
5156 const auto& readCbs = client->getReadCallbacks();
5157 EXPECT_EQ(readCbs.count(streamId), 1);
5158 EXPECT_EQ(conn.streamManager->readableStreams().count(streamId), 0);
5159
5160 AckBlocks sentPackets;
5161 client->writeChain(streamId, data->clone(), true, &deliveryCallback);
5162 loopForWrites();
5163
5164 verifyShortPackets(sentPackets);
5165
5166 EXPECT_CALL(deliveryCallback, onDeliveryAck(streamId, 10, _)).Times(1);
5167 auto ackPacket = packetToBuf(createAckPacket(
5168 client->getNonConstConn(),
5169 ++appDataPacketNum,
5170 sentPackets,
5171 PacketNumberSpace::AppData));
5172 deliverData(ackPacket->coalesce());
5173 EXPECT_FALSE(conn.streamManager->hasDeliverable());
5174 EXPECT_FALSE(conn.streamManager->streamExists(streamId));
5175 EXPECT_EQ(readCbs.count(streamId), 0);
5176 client->close(folly::none);
5177 EXPECT_TRUE(client->isClosed());
5178 }
5179
TEST_F(QuicClientTransportAfterStartTest,ReceiveConnectionClose)5180 TEST_F(QuicClientTransportAfterStartTest, ReceiveConnectionClose) {
5181 ShortHeader header(
5182 ProtectionType::KeyPhaseZero, *originalConnId, appDataPacketNum++);
5183 RegularQuicPacketBuilder builder(
5184 client->getConn().udpSendPacketLen, std::move(header), 0);
5185 builder.encodePacketHeader();
5186 ConnectionCloseFrame connClose(
5187 QuicErrorCode(TransportErrorCode::NO_ERROR),
5188 "Stand clear of the closing doors, please");
5189 writeFrame(std::move(connClose), builder);
5190 auto packet = packetToBuf(std::move(builder).buildPacket());
5191 EXPECT_CALL(clientConnCallback, onConnectionEnd());
5192 deliverDataWithoutErrorCheck(packet->coalesce());
5193 // Now the transport should be closed
5194 EXPECT_EQ(
5195 QuicErrorCode(TransportErrorCode::NO_ERROR),
5196 client->getConn().localConnectionError->first);
5197 EXPECT_TRUE(client->isClosed());
5198 EXPECT_TRUE(verifyFramePresent(
5199 socketWrites,
5200 *makeHandshakeCodec(),
5201 QuicFrame::Type::ConnectionCloseFrame));
5202 }
5203
TEST_F(QuicClientTransportAfterStartTest,ReceiveApplicationClose)5204 TEST_F(QuicClientTransportAfterStartTest, ReceiveApplicationClose) {
5205 auto qLogger = std::make_shared<FileQLogger>(VantagePoint::Client);
5206 client->getNonConstConn().qLogger = qLogger;
5207
5208 ShortHeader header(
5209 ProtectionType::KeyPhaseZero, *originalConnId, appDataPacketNum++);
5210 RegularQuicPacketBuilder builder(
5211 client->getConn().udpSendPacketLen, std::move(header), 0);
5212 builder.encodePacketHeader();
5213 ConnectionCloseFrame appClose(
5214 QuicErrorCode(GenericApplicationErrorCode::UNKNOWN),
5215 "Stand clear of the closing doors, please");
5216 writeFrame(std::move(appClose), builder);
5217 auto packet = packetToBuf(std::move(builder).buildPacket());
5218 EXPECT_FALSE(client->isClosed());
5219 socketWrites.clear();
5220
5221 EXPECT_CALL(
5222 clientConnCallback,
5223 onConnectionError(IsAppError(GenericApplicationErrorCode::UNKNOWN)));
5224 deliverDataWithoutErrorCheck(packet->coalesce());
5225 // Now the transport should be closed
5226 EXPECT_EQ(
5227 QuicErrorCode(TransportErrorCode::NO_ERROR),
5228 client->getConn().localConnectionError->first);
5229 EXPECT_TRUE(client->isClosed());
5230 EXPECT_TRUE(verifyFramePresent(
5231 socketWrites,
5232 *makeHandshakeCodec(),
5233 QuicFrame::Type::ConnectionCloseFrame));
5234
5235 std::vector<int> indices =
5236 getQLogEventIndices(QLogEventType::TransportStateUpdate, qLogger);
5237 EXPECT_EQ(indices.size(), 1);
5238 auto tmp = std::move(qLogger->logs[indices[0]]);
5239 auto event = dynamic_cast<QLogTransportStateUpdateEvent*>(tmp.get());
5240 EXPECT_EQ(
5241 event->update,
5242 getPeerClose(
5243 "Client closed by peer reason=Stand clear of the closing doors, please"));
5244 }
5245
TEST_F(QuicClientTransportAfterStartTest,ReceiveApplicationCloseNoError)5246 TEST_F(QuicClientTransportAfterStartTest, ReceiveApplicationCloseNoError) {
5247 ShortHeader header(
5248 ProtectionType::KeyPhaseZero, *originalConnId, appDataPacketNum++);
5249 RegularQuicPacketBuilder builder(
5250 client->getConn().udpSendPacketLen, std::move(header), 0);
5251 builder.encodePacketHeader();
5252 ConnectionCloseFrame appClose(
5253 QuicErrorCode(GenericApplicationErrorCode::NO_ERROR), "No Error");
5254 writeFrame(std::move(appClose), builder);
5255 auto packet = packetToBuf(std::move(builder).buildPacket());
5256 EXPECT_FALSE(client->isClosed());
5257 socketWrites.clear();
5258
5259 EXPECT_CALL(clientConnCallback, onConnectionError(_)).Times(0);
5260 EXPECT_CALL(clientConnCallback, onConnectionEnd());
5261 deliverDataWithoutErrorCheck(packet->coalesce());
5262 // Now the transport should be closed
5263 EXPECT_EQ(
5264 QuicErrorCode(TransportErrorCode::NO_ERROR),
5265 client->getConn().localConnectionError->first);
5266 EXPECT_TRUE(client->isClosed());
5267 EXPECT_TRUE(verifyFramePresent(
5268 socketWrites,
5269 *makeHandshakeCodec(),
5270 QuicFrame::Type::ConnectionCloseFrame));
5271 }
5272
TEST_F(QuicClientTransportAfterStartTest,DestroyWithoutClosing)5273 TEST_F(QuicClientTransportAfterStartTest, DestroyWithoutClosing) {
5274 StreamId streamId = client->createBidirectionalStream().value();
5275
5276 client->setReadCallback(streamId, &readCb);
5277
5278 EXPECT_CALL(clientConnCallback, onConnectionError(_)).Times(0);
5279 EXPECT_CALL(clientConnCallback, onConnectionEnd());
5280
5281 auto write = IOBuf::copyBuffer("no");
5282 client->writeChain(streamId, write->clone(), true, &deliveryCallback);
5283 loopForWrites();
5284
5285 EXPECT_CALL(deliveryCallback, onCanceled(_, _));
5286 EXPECT_CALL(readCb, readError(_, _));
5287 }
5288
TEST_F(QuicClientTransportAfterStartTest,DestroyWhileDraining)5289 TEST_F(QuicClientTransportAfterStartTest, DestroyWhileDraining) {
5290 StreamId streamId = client->createBidirectionalStream().value();
5291
5292 client->setReadCallback(streamId, &readCb);
5293
5294 auto write = IOBuf::copyBuffer("no");
5295 client->writeChain(streamId, write->clone(), true, &deliveryCallback);
5296
5297 loopForWrites();
5298 EXPECT_CALL(clientConnCallback, onConnectionError(_)).Times(0);
5299 EXPECT_CALL(clientConnCallback, onConnectionEnd()).Times(0);
5300 // Go into draining with one active stream.
5301
5302 EXPECT_CALL(deliveryCallback, onCanceled(_, _));
5303 EXPECT_CALL(readCb, readError(_, _));
5304 client->close(folly::none);
5305 }
5306
TEST_F(QuicClientTransportAfterStartTest,CloseNowWhileDraining)5307 TEST_F(QuicClientTransportAfterStartTest, CloseNowWhileDraining) {
5308 // Drain first with no active streams
5309 auto err = std::make_pair<QuicErrorCode, std::string>(
5310 QuicErrorCode(LocalErrorCode::INTERNAL_ERROR),
5311 toString(LocalErrorCode::INTERNAL_ERROR).str());
5312 client->close(err);
5313 EXPECT_TRUE(client->isDraining());
5314 client->closeNow(err);
5315 EXPECT_FALSE(client->isDraining());
5316 client.reset();
5317 EXPECT_TRUE(destructionCallback->isDestroyed());
5318 }
5319
TEST_F(QuicClientTransportAfterStartTest,ExpiredDrainTimeout)5320 TEST_F(QuicClientTransportAfterStartTest, ExpiredDrainTimeout) {
5321 auto err = std::make_pair<QuicErrorCode, std::string>(
5322 QuicErrorCode(LocalErrorCode::INTERNAL_ERROR),
5323 toString(LocalErrorCode::INTERNAL_ERROR).str());
5324 client->close(err);
5325 EXPECT_TRUE(client->isDraining());
5326 EXPECT_FALSE(destructionCallback->isDestroyed());
5327 client->drainTimeout().timeoutExpired();
5328 client.reset();
5329 EXPECT_TRUE(destructionCallback->isDestroyed());
5330 }
5331
TEST_F(QuicClientTransportAfterStartTest,WriteThrowsExceptionWhileDraining)5332 TEST_F(QuicClientTransportAfterStartTest, WriteThrowsExceptionWhileDraining) {
5333 // Drain first with no active streams
5334 auto err = std::make_pair<QuicErrorCode, std::string>(
5335 QuicErrorCode(LocalErrorCode::INTERNAL_ERROR),
5336 toString(LocalErrorCode::INTERNAL_ERROR).str());
5337 EXPECT_CALL(*sock, write(_, _)).WillRepeatedly(SetErrnoAndReturn(EBADF, -1));
5338 client->close(err);
5339 EXPECT_FALSE(client->idleTimeout().isScheduled());
5340 }
5341
TEST_F(QuicClientTransportAfterStartTest,DestroyEvbWhileLossTimeoutActive)5342 TEST_F(QuicClientTransportAfterStartTest, DestroyEvbWhileLossTimeoutActive) {
5343 StreamId streamId = client->createBidirectionalStream().value();
5344
5345 client->setReadCallback(streamId, &readCb);
5346
5347 auto write = IOBuf::copyBuffer("no");
5348 client->writeChain(streamId, write->clone(), true);
5349 loopForWrites();
5350 EXPECT_TRUE(client->lossTimeout().isScheduled());
5351 eventbase_.reset();
5352 }
5353
5354 class TestCCFactory : public CongestionControllerFactory {
5355 public:
makeCongestionController(QuicConnectionStateBase & conn,CongestionControlType type)5356 std::unique_ptr<CongestionController> makeCongestionController(
5357 QuicConnectionStateBase& conn,
5358 CongestionControlType type) override {
5359 EXPECT_EQ(type, CongestionControlType::Cubic);
5360 createdControllers++;
5361 return std::make_unique<Cubic>(conn);
5362 }
5363 int createdControllers{0};
5364 };
5365
TEST_F(QuicClientTransportAfterStartTest,CongestionControlRecreatedWithNewFactory)5366 TEST_F(
5367 QuicClientTransportAfterStartTest,
5368 CongestionControlRecreatedWithNewFactory) {
5369 // Default: Cubic
5370 auto cc = client->getConn().congestionController.get();
5371 EXPECT_EQ(CongestionControlType::Cubic, cc->type());
5372
5373 // Check Cubic CC instance is recreated with new CC factory
5374 auto factory = std::make_shared<TestCCFactory>();
5375 client->setCongestionControllerFactory(factory);
5376 auto newCC = client->getConn().congestionController.get();
5377 EXPECT_EQ(nullptr, newCC);
5378 client->setCongestionControl(CongestionControlType::Cubic);
5379 newCC = client->getConn().congestionController.get();
5380 EXPECT_NE(nullptr, newCC);
5381 EXPECT_EQ(factory->createdControllers, 1);
5382 }
5383
TEST_F(QuicClientTransportAfterStartTest,SetCongestionControl)5384 TEST_F(QuicClientTransportAfterStartTest, SetCongestionControl) {
5385 // Default: Cubic
5386 auto cc = client->getConn().congestionController.get();
5387 EXPECT_EQ(CongestionControlType::Cubic, cc->type());
5388
5389 // Setting CC factory resets CC controller
5390 client->setCongestionControllerFactory(
5391 std::make_shared<DefaultCongestionControllerFactory>());
5392 EXPECT_FALSE(client->getConn().congestionController);
5393
5394 // Set to Cubic explicitly this time
5395 client->setCongestionControl(CongestionControlType::Cubic);
5396 cc = client->getConn().congestionController.get();
5397 EXPECT_EQ(CongestionControlType::Cubic, cc->type());
5398
5399 // Change to Reno
5400 client->setCongestionControl(CongestionControlType::NewReno);
5401 cc = client->getConn().congestionController.get();
5402 EXPECT_EQ(CongestionControlType::NewReno, cc->type());
5403
5404 // Change back to Cubic:
5405 client->setCongestionControl(CongestionControlType::Cubic);
5406 cc = client->getConn().congestionController.get();
5407 EXPECT_EQ(CongestionControlType::Cubic, cc->type());
5408 }
5409
TEST_F(QuicClientTransportAfterStartTest,SetCongestionControlBbr)5410 TEST_F(QuicClientTransportAfterStartTest, SetCongestionControlBbr) {
5411 // Default: Cubic
5412 auto cc = client->getConn().congestionController.get();
5413 EXPECT_EQ(CongestionControlType::Cubic, cc->type());
5414
5415 // Change to BBR, which requires enable pacing first
5416 client->setCongestionControllerFactory(
5417 std::make_shared<DefaultCongestionControllerFactory>());
5418 client->setPacingTimer(TimerHighRes::newTimer(eventbase_.get(), 1ms));
5419 client->getNonConstConn().transportSettings.pacingEnabled = true;
5420 client->setCongestionControl(CongestionControlType::BBR);
5421 cc = client->getConn().congestionController.get();
5422 EXPECT_EQ(CongestionControlType::BBR, cc->type());
5423 }
5424
TEST_F(QuicClientTransportAfterStartTest,PingIsTreatedAsRetransmittable)5425 TEST_F(QuicClientTransportAfterStartTest, PingIsTreatedAsRetransmittable) {
5426 PingFrame pingFrame;
5427 ShortHeader header(
5428 ProtectionType::KeyPhaseZero, *originalConnId, appDataPacketNum++);
5429 RegularQuicPacketBuilder builder(
5430 client->getConn().udpSendPacketLen,
5431 std::move(header),
5432 0 /* largestAcked */);
5433 builder.encodePacketHeader();
5434 writeFrame(pingFrame, builder);
5435 auto packet = packetToBuf(std::move(builder).buildPacket());
5436 deliverData(packet->coalesce());
5437 EXPECT_TRUE(client->getConn().pendingEvents.scheduleAckTimeout);
5438 }
5439
TEST_F(QuicClientTransportAfterStartTest,ReceiveDatagramFrameAndDiscard)5440 TEST_F(QuicClientTransportAfterStartTest, ReceiveDatagramFrameAndDiscard) {
5441 ShortHeader header(
5442 ProtectionType::KeyPhaseZero, *originalConnId, appDataPacketNum++);
5443
5444 RegularQuicPacketBuilder builder(
5445 client->getConn().udpSendPacketLen,
5446 std::move(header),
5447 0 /* largestAcked */);
5448 builder.encodePacketHeader();
5449
5450 StringPiece datagramPayload = "do not rely on me. I am unreliable";
5451 DatagramFrame datagramFrame(
5452 datagramPayload.size(), IOBuf::copyBuffer(datagramPayload));
5453 writeFrame(datagramFrame, builder);
5454 auto packet = packetToBuf(std::move(builder).buildPacket());
5455 deliverData(packet->coalesce());
5456 ASSERT_EQ(client->getConn().datagramState.readBuffer.size(), 0);
5457 }
5458
TEST_F(QuicClientTransportAfterStartTest,ReceiveDatagramFrameAndStore)5459 TEST_F(QuicClientTransportAfterStartTest, ReceiveDatagramFrameAndStore) {
5460 auto& conn = client->getNonConstConn();
5461 conn.datagramState.maxReadFrameSize = std::numeric_limits<uint16_t>::max();
5462 conn.datagramState.maxReadBufferSize = 10;
5463
5464 for (uint64_t i = 0; i < conn.datagramState.maxReadBufferSize * 2; i++) {
5465 ShortHeader header(
5466 ProtectionType::KeyPhaseZero, *originalConnId, appDataPacketNum++);
5467
5468 RegularQuicPacketBuilder builder(
5469 client->getConn().udpSendPacketLen,
5470 std::move(header),
5471 0 /* largestAcked */);
5472 builder.encodePacketHeader();
5473
5474 StringPiece datagramPayload = "do not rely on me. I am unreliable";
5475 DatagramFrame datagramFrame(
5476 datagramPayload.size(), IOBuf::copyBuffer(datagramPayload));
5477 writeFrame(datagramFrame, builder);
5478 auto packet = packetToBuf(std::move(builder).buildPacket());
5479 deliverData(packet->coalesce());
5480 if (i < conn.datagramState.maxReadBufferSize) {
5481 ASSERT_EQ(client->getConn().datagramState.readBuffer.size(), i + 1);
5482 }
5483 }
5484 ASSERT_EQ(
5485 client->getConn().datagramState.readBuffer.size(),
5486 conn.datagramState.maxReadBufferSize);
5487 }
5488
TEST_F(QuicClientTransportAfterStartTest,ReceiveDatagramFrameAndDiscardOldDataFirst)5489 TEST_F(
5490 QuicClientTransportAfterStartTest,
5491 ReceiveDatagramFrameAndDiscardOldDataFirst) {
5492 auto& conn = client->getNonConstConn();
5493 conn.datagramState.maxReadFrameSize = std::numeric_limits<uint16_t>::max();
5494 conn.datagramState.maxReadBufferSize = 1;
5495 auto& transportSettings = client->getNonConstConn().transportSettings;
5496 transportSettings.datagramConfig.recvDropOldDataFirst = true;
5497
5498 // Enqueue first datagram
5499 ShortHeader header1(
5500 ProtectionType::KeyPhaseZero, *originalConnId, appDataPacketNum++);
5501 RegularQuicPacketBuilder builder1(
5502 client->getConn().udpSendPacketLen,
5503 std::move(header1),
5504 0 /* largestAcked */);
5505 builder1.encodePacketHeader();
5506 StringPiece datagramPayload1 = "first";
5507 DatagramFrame datagramFrame1(
5508 datagramPayload1.size(), IOBuf::copyBuffer(datagramPayload1));
5509 writeFrame(datagramFrame1, builder1);
5510 auto packet1 = packetToBuf(std::move(builder1).buildPacket());
5511 deliverData(packet1->coalesce());
5512 ASSERT_EQ(
5513 client->getConn().datagramState.readBuffer.size(),
5514 conn.datagramState.maxReadBufferSize);
5515 // Enqueue second datagram
5516 ShortHeader header2(
5517 ProtectionType::KeyPhaseZero, *originalConnId, appDataPacketNum++);
5518 RegularQuicPacketBuilder builder2(
5519 client->getConn().udpSendPacketLen,
5520 std::move(header2),
5521 0 /* largestAcked */);
5522 builder2.encodePacketHeader();
5523 StringPiece datagramPayload2 = "second";
5524 DatagramFrame datagramFrame2(
5525 datagramPayload2.size(), IOBuf::copyBuffer(datagramPayload2));
5526 writeFrame(datagramFrame2, builder2);
5527 auto packet2 = packetToBuf(std::move(builder2).buildPacket());
5528 deliverData(packet2->coalesce());
5529 ASSERT_EQ(
5530 client->getConn().datagramState.readBuffer.size(),
5531 conn.datagramState.maxReadBufferSize);
5532
5533 auto payload = client->getConn()
5534 .datagramState.readBuffer[0]
5535 .front()
5536 ->clone()
5537 ->moveToFbString();
5538 ASSERT_EQ(payload, "second");
5539 }
5540
TEST_F(QuicClientTransportAfterStartTest,OneCloseFramePerRtt)5541 TEST_F(QuicClientTransportAfterStartTest, OneCloseFramePerRtt) {
5542 auto streamId = client->createBidirectionalStream().value();
5543 auto& conn = client->getNonConstConn();
5544 conn.lossState.srtt = 10s;
5545 EXPECT_CALL(*sock, write(_, _)).WillRepeatedly(Return(100));
5546 loopForWrites();
5547 Mock::VerifyAndClearExpectations(sock);
5548
5549 // Close the client transport. There could be multiple writes given how many
5550 // ciphers we have.
5551 EXPECT_CALL(*sock, write(_, _)).Times(AtLeast(1)).WillRepeatedly(Return(10));
5552 client->close(std::make_pair<QuicErrorCode, std::string>(
5553 QuicErrorCode(LocalErrorCode::INTERNAL_ERROR),
5554 toString(LocalErrorCode::INTERNAL_ERROR).str()));
5555 EXPECT_TRUE(conn.lastCloseSentTime.hasValue());
5556 Mock::VerifyAndClearExpectations(sock);
5557
5558 // Then received some server packet, which won't trigger another close
5559 EXPECT_CALL(*sock, write(_, _)).Times(0);
5560 auto firstData = folly::IOBuf::copyBuffer(
5561 "I got a room full of your posters and your pictures, man");
5562 deliverDataWithoutErrorCheck(packetToBuf(createStreamPacket(
5563 *serverChosenConnId,
5564 *originalConnId,
5565 appDataPacketNum++,
5566 streamId,
5567 *firstData,
5568 0 /* cipherOverhead */,
5569 0 /* largestAcked */))
5570 ->coalesce());
5571 Mock::VerifyAndClearExpectations(sock);
5572
5573 // force the clock:
5574 conn.lastCloseSentTime = Clock::now() - 10s;
5575 conn.lossState.srtt = 1us;
5576 // Receive another server packet
5577 EXPECT_CALL(*sock, write(_, _)).Times(AtLeast(1)).WillRepeatedly(Return(10));
5578 auto secondData = folly::IOBuf::copyBuffer(
5579 "Dear Slim, I wrote to you but you still ain't callin'");
5580 deliverDataWithoutErrorCheck(packetToBuf(createStreamPacket(
5581 *serverChosenConnId,
5582 *originalConnId,
5583 appDataPacketNum++,
5584 streamId,
5585 *secondData,
5586 0 /* cipherOverhead */,
5587 0 /* largestAcked */))
5588 ->coalesce());
5589 }
5590
TEST_F(QuicClientVersionParamInvalidTest,InvalidVersion)5591 TEST_F(QuicClientVersionParamInvalidTest, InvalidVersion) {
5592 EXPECT_THROW(performFakeHandshake(), std::runtime_error);
5593 }
5594
5595 class QuicClientTransportPskCacheTest
5596 : public QuicClientTransportAfterStartTestBase {
5597 public:
SetUpChild()5598 void SetUpChild() override {
5599 QuicClientTransportAfterStartTestBase::SetUpChild();
5600 }
5601
getPskCache()5602 std::shared_ptr<QuicPskCache> getPskCache() override {
5603 mockPskCache_ = std::make_shared<NiceMock<MockQuicPskCache>>();
5604 return mockPskCache_;
5605 }
5606
5607 protected:
5608 std::shared_ptr<MockQuicPskCache> mockPskCache_;
5609 };
5610
TEST_F(QuicClientTransportPskCacheTest,TestOnNewCachedPsk)5611 TEST_F(QuicClientTransportPskCacheTest, TestOnNewCachedPsk) {
5612 std::string appParams = "APP params";
5613 client->setEarlyDataAppParamsFunctions(
5614 [](const folly::Optional<std::string>&, const Buf&) { return true; },
5615 [=]() -> Buf { return folly::IOBuf::copyBuffer(appParams); });
5616 EXPECT_CALL(*mockPskCache_, putPsk(hostname_, _))
5617 .WillOnce(Invoke([=](const std::string&, QuicCachedPsk psk) {
5618 EXPECT_EQ(psk.appParams, appParams);
5619 }));
5620 mockClientHandshake->triggerOnNewCachedPsk();
5621 }
5622
TEST_F(QuicClientTransportPskCacheTest,TestTwoOnNewCachedPsk)5623 TEST_F(QuicClientTransportPskCacheTest, TestTwoOnNewCachedPsk) {
5624 std::string appParams1 = "APP params1";
5625 client->setEarlyDataAppParamsFunctions(
5626 [](const folly::Optional<std::string>&, const Buf&) { return true; },
5627 [=]() -> Buf { return folly::IOBuf::copyBuffer(appParams1); });
5628 EXPECT_CALL(*mockPskCache_, putPsk(hostname_, _))
5629 .WillOnce(Invoke([=](const std::string&, QuicCachedPsk psk) {
5630 auto& params = psk.transportParams;
5631 EXPECT_EQ(params.initialMaxData, kDefaultConnectionWindowSize);
5632 EXPECT_EQ(
5633 params.initialMaxStreamDataBidiLocal, kDefaultStreamWindowSize);
5634 EXPECT_EQ(
5635 params.initialMaxStreamDataBidiRemote, kDefaultStreamWindowSize);
5636 EXPECT_EQ(params.initialMaxStreamDataUni, kDefaultStreamWindowSize);
5637 EXPECT_EQ(psk.appParams, appParams1);
5638 }));
5639 mockClientHandshake->triggerOnNewCachedPsk();
5640
5641 client->getNonConstConn().flowControlState.peerAdvertisedMaxOffset = 1234;
5642 client->getNonConstConn()
5643 .flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiLocal = 123;
5644 client->getNonConstConn()
5645 .flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiRemote = 123;
5646 client->getNonConstConn()
5647 .flowControlState.peerAdvertisedInitialMaxStreamOffsetUni = 123;
5648
5649 std::string appParams2 = "APP params2";
5650 client->setEarlyDataAppParamsFunctions(
5651 [](const folly::Optional<std::string>&, const Buf&) { return true; },
5652 [=]() -> Buf { return folly::IOBuf::copyBuffer(appParams2); });
5653 EXPECT_CALL(*mockPskCache_, putPsk(hostname_, _))
5654 .WillOnce(Invoke([=](const std::string&, QuicCachedPsk psk) {
5655 auto& params = psk.transportParams;
5656 EXPECT_EQ(params.initialMaxData, kDefaultConnectionWindowSize);
5657 EXPECT_EQ(
5658 params.initialMaxStreamDataBidiLocal, kDefaultStreamWindowSize);
5659 EXPECT_EQ(
5660 params.initialMaxStreamDataBidiRemote, kDefaultStreamWindowSize);
5661 EXPECT_EQ(params.initialMaxStreamDataUni, kDefaultStreamWindowSize);
5662 EXPECT_EQ(psk.appParams, appParams2);
5663 }));
5664 mockClientHandshake->triggerOnNewCachedPsk();
5665 }
5666
5667 class QuicZeroRttClientTest : public QuicClientTransportAfterStartTestBase {
5668 public:
5669 ~QuicZeroRttClientTest() override = default;
5670
setFakeHandshakeCiphers()5671 void setFakeHandshakeCiphers() override {
5672 auto readAead = test::createNoOpAead();
5673 auto writeAead = test::createNoOpAead();
5674 auto zeroAead = test::createNoOpAead();
5675 auto handshakeReadAead = test::createNoOpAead();
5676 auto handshakeWriteAead = test::createNoOpAead();
5677 mockClientHandshake->setOneRttReadCipher(std::move(readAead));
5678 mockClientHandshake->setOneRttWriteCipher(std::move(writeAead));
5679 mockClientHandshake->setZeroRttWriteCipher(std::move(zeroAead));
5680 mockClientHandshake->setHandshakeReadCipher(std::move(handshakeReadAead));
5681 mockClientHandshake->setHandshakeWriteCipher(std::move(handshakeWriteAead));
5682
5683 mockClientHandshake->setHandshakeReadHeaderCipher(
5684 test::createNoOpHeaderCipher());
5685 mockClientHandshake->setHandshakeWriteHeaderCipher(
5686 test::createNoOpHeaderCipher());
5687 mockClientHandshake->setOneRttWriteHeaderCipher(
5688 test::createNoOpHeaderCipher());
5689 mockClientHandshake->setOneRttReadHeaderCipher(
5690 test::createNoOpHeaderCipher());
5691 mockClientHandshake->setZeroRttWriteHeaderCipher(
5692 test::createNoOpHeaderCipher());
5693 }
5694
getPskCache()5695 std::shared_ptr<QuicPskCache> getPskCache() override {
5696 if (!mockQuicPskCache_) {
5697 mockQuicPskCache_ = std::make_shared<MockQuicPskCache>();
5698 }
5699 return mockQuicPskCache_;
5700 }
5701
start()5702 void start() override {
5703 TransportSettings clientSettings;
5704 // Ignore path mtu to test negotiation.
5705 clientSettings.canIgnorePathMTU = true;
5706 clientSettings.attemptEarlyData = true;
5707 client->setTransportSettings(clientSettings);
5708 }
5709
startClient()5710 void startClient() {
5711 EXPECT_CALL(clientConnCallback, onTransportReady());
5712 client->start(&clientConnCallback);
5713 setConnectionIds();
5714 EXPECT_EQ(socketWrites.size(), 1);
5715 EXPECT_TRUE(
5716 verifyLongHeader(*socketWrites.at(0), LongHeader::Types::Initial));
5717 socketWrites.clear();
5718 }
5719
zeroRttPacketsOutstanding()5720 bool zeroRttPacketsOutstanding() {
5721 for (auto& packet : client->getNonConstConn().outstandings.packets) {
5722 bool isZeroRtt =
5723 packet.packet.header.getProtectionType() == ProtectionType::ZeroRtt;
5724 if (isZeroRtt) {
5725 return true;
5726 }
5727 }
5728 return false;
5729 }
5730
5731 protected:
5732 std::shared_ptr<MockQuicPskCache> mockQuicPskCache_;
5733 };
5734
TEST_F(QuicZeroRttClientTest,TestReplaySafeCallback)5735 TEST_F(QuicZeroRttClientTest, TestReplaySafeCallback) {
5736 EXPECT_CALL(*mockQuicPskCache_, getPsk(hostname_))
5737 .WillOnce(InvokeWithoutArgs([]() {
5738 QuicCachedPsk quicCachedPsk;
5739 quicCachedPsk.transportParams.initialMaxStreamDataBidiLocal =
5740 kDefaultStreamWindowSize;
5741 quicCachedPsk.transportParams.initialMaxStreamDataBidiRemote =
5742 kDefaultStreamWindowSize;
5743 quicCachedPsk.transportParams.initialMaxStreamDataUni =
5744 kDefaultStreamWindowSize;
5745 quicCachedPsk.transportParams.initialMaxData =
5746 kDefaultConnectionWindowSize;
5747 quicCachedPsk.transportParams.idleTimeout = kDefaultIdleTimeout.count();
5748 quicCachedPsk.transportParams.maxRecvPacketSize =
5749 kDefaultUDPReadBufferSize;
5750 quicCachedPsk.transportParams.initialMaxStreamsBidi =
5751 std::numeric_limits<uint32_t>::max();
5752 quicCachedPsk.transportParams.initialMaxStreamsUni =
5753 std::numeric_limits<uint32_t>::max();
5754 return quicCachedPsk;
5755 }));
5756 bool performedValidation = false;
5757 client->setEarlyDataAppParamsFunctions(
5758 [&](const folly::Optional<std::string>&, const Buf&) {
5759 performedValidation = true;
5760 return true;
5761 },
5762 []() -> Buf { return nullptr; });
5763 startClient();
5764 EXPECT_TRUE(performedValidation);
5765
5766 socketWrites.clear();
5767 auto streamId = client->createBidirectionalStream().value();
5768 client->writeChain(streamId, IOBuf::copyBuffer("hello"), true);
5769 loopForWrites();
5770 EXPECT_TRUE(zeroRttPacketsOutstanding());
5771 assertWritten(false, LongHeader::Types::ZeroRtt);
5772 EXPECT_CALL(clientConnCallback, onReplaySafe());
5773 mockClientHandshake->setZeroRttRejected(false);
5774 recvServerHello();
5775
5776 EXPECT_EQ(client->getConn().zeroRttWriteCipher, nullptr);
5777
5778 // All the data is still there.
5779 EXPECT_TRUE(zeroRttPacketsOutstanding());
5780 // Transport parameters did not change since zero rtt was accepted.
5781 // Except for max packet size.
5782 verifyTransportParameters(
5783 kDefaultConnectionWindowSize,
5784 kDefaultStreamWindowSize,
5785 kDefaultIdleTimeout,
5786 kDefaultAckDelayExponent,
5787 kDefaultMaxUDPPayload);
5788
5789 EXPECT_CALL(*mockQuicPskCache_, putPsk(hostname_, _))
5790 .WillOnce(Invoke([=](const std::string&, QuicCachedPsk psk) {
5791 auto& params = psk.transportParams;
5792 EXPECT_EQ(params.initialMaxData, kDefaultConnectionWindowSize);
5793 EXPECT_EQ(
5794 params.initialMaxStreamDataBidiLocal, kDefaultStreamWindowSize);
5795 EXPECT_EQ(
5796 params.initialMaxStreamDataBidiRemote, kDefaultStreamWindowSize);
5797 EXPECT_EQ(params.initialMaxStreamDataUni, kDefaultStreamWindowSize);
5798 EXPECT_EQ(
5799 params.initialMaxStreamsBidi, std::numeric_limits<uint32_t>::max());
5800 EXPECT_EQ(
5801 params.initialMaxStreamsUni, std::numeric_limits<uint32_t>::max());
5802 }));
5803 mockClientHandshake->triggerOnNewCachedPsk();
5804 }
5805
TEST_F(QuicZeroRttClientTest,TestEarlyRetransmit0Rtt)5806 TEST_F(QuicZeroRttClientTest, TestEarlyRetransmit0Rtt) {
5807 EXPECT_CALL(*mockQuicPskCache_, getPsk(hostname_))
5808 .WillOnce(InvokeWithoutArgs([]() {
5809 QuicCachedPsk quicCachedPsk;
5810 quicCachedPsk.transportParams.initialMaxStreamDataBidiLocal =
5811 kDefaultStreamWindowSize;
5812 quicCachedPsk.transportParams.initialMaxStreamDataBidiRemote =
5813 kDefaultStreamWindowSize;
5814 quicCachedPsk.transportParams.initialMaxStreamDataUni =
5815 kDefaultStreamWindowSize;
5816 quicCachedPsk.transportParams.initialMaxData =
5817 kDefaultConnectionWindowSize;
5818 quicCachedPsk.transportParams.idleTimeout = kDefaultIdleTimeout.count();
5819 quicCachedPsk.transportParams.maxRecvPacketSize =
5820 kDefaultUDPReadBufferSize;
5821 quicCachedPsk.transportParams.initialMaxStreamsBidi =
5822 std::numeric_limits<uint32_t>::max();
5823 quicCachedPsk.transportParams.initialMaxStreamsUni =
5824 std::numeric_limits<uint32_t>::max();
5825 return quicCachedPsk;
5826 }));
5827 auto tp = client->getTransportSettings();
5828 tp.earlyRetransmit0Rtt = true;
5829 client->setTransportSettings(tp);
5830 bool performedValidation = false;
5831 client->setEarlyDataAppParamsFunctions(
5832 [&](const folly::Optional<std::string>&, const Buf&) {
5833 performedValidation = true;
5834 return true;
5835 },
5836 []() -> Buf { return nullptr; });
5837 startClient();
5838 EXPECT_TRUE(performedValidation);
5839
5840 socketWrites.clear();
5841 auto streamId = client->createBidirectionalStream().value();
5842 client->writeChain(streamId, IOBuf::copyBuffer("hello"), true);
5843 loopForWrites();
5844 EXPECT_TRUE(zeroRttPacketsOutstanding());
5845 assertWritten(false, LongHeader::Types::ZeroRtt);
5846 EXPECT_CALL(clientConnCallback, onReplaySafe());
5847 mockClientHandshake->setZeroRttRejected(false);
5848 recvServerHello();
5849
5850 EXPECT_EQ(client->getConn().zeroRttWriteCipher, nullptr);
5851
5852 // All the data is marked lost.
5853 EXPECT_FALSE(zeroRttPacketsOutstanding());
5854 // Transport parameters did not change since zero rtt was accepted.
5855 // Except for max packet size.
5856 verifyTransportParameters(
5857 kDefaultConnectionWindowSize,
5858 kDefaultStreamWindowSize,
5859 kDefaultIdleTimeout,
5860 kDefaultAckDelayExponent,
5861 kDefaultMaxUDPPayload);
5862
5863 EXPECT_CALL(*mockQuicPskCache_, putPsk(hostname_, _))
5864 .WillOnce(Invoke([=](const std::string&, QuicCachedPsk psk) {
5865 auto& params = psk.transportParams;
5866 EXPECT_EQ(params.initialMaxData, kDefaultConnectionWindowSize);
5867 EXPECT_EQ(
5868 params.initialMaxStreamDataBidiLocal, kDefaultStreamWindowSize);
5869 EXPECT_EQ(
5870 params.initialMaxStreamDataBidiRemote, kDefaultStreamWindowSize);
5871 EXPECT_EQ(params.initialMaxStreamDataUni, kDefaultStreamWindowSize);
5872 EXPECT_EQ(
5873 params.initialMaxStreamsBidi, std::numeric_limits<uint32_t>::max());
5874 EXPECT_EQ(
5875 params.initialMaxStreamsUni, std::numeric_limits<uint32_t>::max());
5876 }));
5877 mockClientHandshake->triggerOnNewCachedPsk();
5878 }
5879
TEST_F(QuicZeroRttClientTest,TestZeroRttRejection)5880 TEST_F(QuicZeroRttClientTest, TestZeroRttRejection) {
5881 EXPECT_CALL(*mockQuicPskCache_, getPsk(hostname_))
5882 .WillOnce(InvokeWithoutArgs([]() {
5883 QuicCachedPsk quicCachedPsk;
5884 quicCachedPsk.transportParams.initialMaxStreamDataBidiLocal =
5885 kDefaultStreamWindowSize;
5886 quicCachedPsk.transportParams.initialMaxStreamDataBidiRemote =
5887 kDefaultStreamWindowSize;
5888 quicCachedPsk.transportParams.initialMaxStreamDataUni =
5889 kDefaultStreamWindowSize;
5890 quicCachedPsk.transportParams.initialMaxData =
5891 kDefaultConnectionWindowSize;
5892 quicCachedPsk.transportParams.idleTimeout = kDefaultIdleTimeout.count();
5893 quicCachedPsk.transportParams.maxRecvPacketSize =
5894 kDefaultUDPReadBufferSize;
5895 quicCachedPsk.transportParams.initialMaxStreamsBidi =
5896 std::numeric_limits<uint32_t>::max();
5897 quicCachedPsk.transportParams.initialMaxStreamsUni =
5898 std::numeric_limits<uint32_t>::max();
5899 return quicCachedPsk;
5900 }));
5901 bool performedValidation = false;
5902 client->setEarlyDataAppParamsFunctions(
5903 [&](const folly::Optional<std::string>&, const Buf&) {
5904 performedValidation = true;
5905 return true;
5906 },
5907 []() -> Buf { return nullptr; });
5908 startClient();
5909 EXPECT_TRUE(performedValidation);
5910
5911 socketWrites.clear();
5912 auto streamId = client->createBidirectionalStream().value();
5913 client->writeChain(streamId, IOBuf::copyBuffer("hello"), true);
5914 loopForWrites();
5915 EXPECT_TRUE(zeroRttPacketsOutstanding());
5916 EXPECT_CALL(clientConnCallback, onReplaySafe());
5917 mockClientHandshake->setZeroRttRejected(true);
5918 EXPECT_CALL(*mockQuicPskCache_, removePsk(hostname_));
5919 recvServerHello();
5920 verifyTransportParameters(
5921 kDefaultConnectionWindowSize,
5922 kDefaultStreamWindowSize,
5923 kDefaultIdleTimeout,
5924 kDefaultAckDelayExponent,
5925 mockClientHandshake->maxRecvPacketSize);
5926 // Zero rtt data is declared lost.
5927 EXPECT_FALSE(zeroRttPacketsOutstanding());
5928 EXPECT_EQ(client->getConn().zeroRttWriteCipher, nullptr);
5929 }
5930
TEST_F(QuicZeroRttClientTest,TestZeroRttRejectionWithSmallerFlowControl)5931 TEST_F(QuicZeroRttClientTest, TestZeroRttRejectionWithSmallerFlowControl) {
5932 EXPECT_CALL(*mockQuicPskCache_, getPsk(hostname_))
5933 .WillOnce(InvokeWithoutArgs([]() {
5934 QuicCachedPsk quicCachedPsk;
5935 quicCachedPsk.transportParams.initialMaxStreamDataBidiLocal =
5936 kDefaultStreamWindowSize;
5937 quicCachedPsk.transportParams.initialMaxStreamDataBidiRemote =
5938 kDefaultStreamWindowSize;
5939 quicCachedPsk.transportParams.initialMaxStreamDataUni =
5940 kDefaultStreamWindowSize;
5941 quicCachedPsk.transportParams.initialMaxData =
5942 kDefaultConnectionWindowSize;
5943 quicCachedPsk.transportParams.idleTimeout = kDefaultIdleTimeout.count();
5944 quicCachedPsk.transportParams.maxRecvPacketSize =
5945 kDefaultUDPReadBufferSize;
5946 quicCachedPsk.transportParams.initialMaxStreamsBidi =
5947 std::numeric_limits<uint32_t>::max();
5948 quicCachedPsk.transportParams.initialMaxStreamsUni =
5949 std::numeric_limits<uint32_t>::max();
5950 return quicCachedPsk;
5951 }));
5952 bool performedValidation = false;
5953 client->setEarlyDataAppParamsFunctions(
5954 [&](const folly::Optional<std::string>&, const Buf&) {
5955 performedValidation = true;
5956 return true;
5957 },
5958 []() -> Buf { return nullptr; });
5959 startClient();
5960 EXPECT_TRUE(performedValidation);
5961
5962 mockClientHandshake->maxInitialStreamData = 10;
5963 socketWrites.clear();
5964 auto streamId = client->createBidirectionalStream().value();
5965 client->writeChain(streamId, IOBuf::copyBuffer("hello"), true);
5966 loopForWrites();
5967 EXPECT_TRUE(zeroRttPacketsOutstanding());
5968 mockClientHandshake->setZeroRttRejected(true);
5969 EXPECT_CALL(*mockQuicPskCache_, removePsk(hostname_));
5970 EXPECT_THROW(recvServerHello(), std::runtime_error);
5971 }
5972
5973 class QuicZeroRttHappyEyeballsClientTransportTest
5974 : public QuicZeroRttClientTest {
5975 public:
SetUpChild()5976 void SetUpChild() override {
5977 client->setHostname(hostname_);
5978
5979 auto secondSocket =
5980 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(
5981 eventbase_.get());
5982 secondSock = secondSocket.get();
5983
5984 client->setHappyEyeballsEnabled(true);
5985 client->addNewPeerAddress(firstAddress);
5986 client->addNewPeerAddress(secondAddress);
5987 client->addNewSocket(std::move(secondSocket));
5988
5989 EXPECT_EQ(client->getConn().happyEyeballsState.v6PeerAddress, firstAddress);
5990 EXPECT_EQ(
5991 client->getConn().happyEyeballsState.v4PeerAddress, secondAddress);
5992
5993 setupCryptoLayer();
5994 }
5995
getPskCache()5996 std::shared_ptr<QuicPskCache> getPskCache() override {
5997 if (!mockQuicPskCache_) {
5998 mockQuicPskCache_ = std::make_shared<MockQuicPskCache>();
5999 }
6000 return mockQuicPskCache_;
6001 }
6002
6003 protected:
6004 folly::test::MockAsyncUDPSocket* secondSock;
6005 SocketAddress firstAddress{"::1", 443};
6006 SocketAddress secondAddress{"127.0.0.1", 443};
6007 };
6008
TEST_F(QuicZeroRttHappyEyeballsClientTransportTest,ZeroRttDataIsRetransmittedOverSecondSocket)6009 TEST_F(
6010 QuicZeroRttHappyEyeballsClientTransportTest,
6011 ZeroRttDataIsRetransmittedOverSecondSocket) {
6012 EXPECT_CALL(*mockQuicPskCache_, getPsk(hostname_))
6013 .WillOnce(InvokeWithoutArgs([]() {
6014 QuicCachedPsk quicCachedPsk;
6015 quicCachedPsk.transportParams.initialMaxStreamDataBidiLocal =
6016 kDefaultStreamWindowSize;
6017 quicCachedPsk.transportParams.initialMaxStreamDataBidiRemote =
6018 kDefaultStreamWindowSize;
6019 quicCachedPsk.transportParams.initialMaxStreamDataUni =
6020 kDefaultStreamWindowSize;
6021 quicCachedPsk.transportParams.initialMaxData =
6022 kDefaultConnectionWindowSize;
6023 quicCachedPsk.transportParams.idleTimeout = kDefaultIdleTimeout.count();
6024 quicCachedPsk.transportParams.maxRecvPacketSize =
6025 kDefaultUDPReadBufferSize;
6026 quicCachedPsk.transportParams.initialMaxStreamsBidi =
6027 std::numeric_limits<uint32_t>::max();
6028 quicCachedPsk.transportParams.initialMaxStreamsUni =
6029 std::numeric_limits<uint32_t>::max();
6030 return quicCachedPsk;
6031 }));
6032 client->setEarlyDataAppParamsFunctions(
6033 [&](const folly::Optional<std::string>&, const Buf&) { return true; },
6034 []() -> Buf { return nullptr; });
6035
6036 EXPECT_CALL(*sock, write(firstAddress, _))
6037 .WillRepeatedly(Invoke(
6038 [&](const SocketAddress&, const std::unique_ptr<folly::IOBuf>& buf) {
6039 socketWrites.push_back(buf->clone());
6040 return buf->computeChainDataLength();
6041 }));
6042 EXPECT_CALL(*secondSock, write(_, _)).Times(0);
6043 startClient();
6044 socketWrites.clear();
6045 auto& conn = client->getConn();
6046 EXPECT_EQ(conn.peerAddress, firstAddress);
6047 EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
6048 EXPECT_TRUE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
6049 // Cancel the delay timer because we want to manually fire it
6050 client->happyEyeballsConnAttemptDelayTimeout().cancelTimeout();
6051
6052 auto streamId = client->createBidirectionalStream().value();
6053 client->writeChain(streamId, IOBuf::copyBuffer("hello"), true);
6054 loopForWrites();
6055 EXPECT_TRUE(zeroRttPacketsOutstanding());
6056 assertWritten(false, LongHeader::Types::ZeroRtt);
6057 socketWrites.clear();
6058
6059 // Manually expire conn attempt timeout
6060 EXPECT_FALSE(conn.happyEyeballsState.shouldWriteToSecondSocket);
6061 client->happyEyeballsConnAttemptDelayTimeout().timeoutExpired();
6062 EXPECT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
6063 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
6064 loopForWrites();
6065 // Declared lost
6066 EXPECT_FALSE(zeroRttPacketsOutstanding());
6067
6068 // Manually expire loss timeout to trigger write to both first and second
6069 // socket
6070 EXPECT_CALL(*sock, write(firstAddress, _))
6071 .Times(2)
6072 .WillRepeatedly(Invoke(
6073 [&](const SocketAddress&, const std::unique_ptr<folly::IOBuf>& buf) {
6074 socketWrites.push_back(
6075 folly::IOBuf::copyBuffer(buf->data(), buf->length(), 0, 0));
6076 return buf->length();
6077 }));
6078 EXPECT_CALL(*secondSock, write(secondAddress, _))
6079 .Times(2)
6080 .WillRepeatedly(Invoke(
6081 [&](const SocketAddress&, const std::unique_ptr<folly::IOBuf>& buf) {
6082 socketWrites.push_back(buf->clone());
6083 return buf->computeChainDataLength();
6084 }));
6085 client->lossTimeout().cancelTimeout();
6086 client->lossTimeout().timeoutExpired();
6087 ASSERT_EQ(socketWrites.size(), 4);
6088 EXPECT_TRUE(
6089 verifyLongHeader(*socketWrites.at(0), LongHeader::Types::Initial));
6090 EXPECT_TRUE(
6091 verifyLongHeader(*socketWrites.at(1), LongHeader::Types::Initial));
6092 EXPECT_TRUE(
6093 verifyLongHeader(*socketWrites.at(2), LongHeader::Types::ZeroRtt));
6094 EXPECT_TRUE(
6095 verifyLongHeader(*socketWrites.at(3), LongHeader::Types::ZeroRtt));
6096 }
6097
TEST_F(QuicZeroRttHappyEyeballsClientTransportTest,ZeroRttDataIsRetransmittedOverSecondSocketOnWriteFail)6098 TEST_F(
6099 QuicZeroRttHappyEyeballsClientTransportTest,
6100 ZeroRttDataIsRetransmittedOverSecondSocketOnWriteFail) {
6101 EXPECT_CALL(*mockQuicPskCache_, getPsk(hostname_))
6102 .WillOnce(InvokeWithoutArgs([]() {
6103 QuicCachedPsk quicCachedPsk;
6104 quicCachedPsk.transportParams.initialMaxStreamDataBidiLocal =
6105 kDefaultStreamWindowSize;
6106 quicCachedPsk.transportParams.initialMaxStreamDataBidiRemote =
6107 kDefaultStreamWindowSize;
6108 quicCachedPsk.transportParams.initialMaxStreamDataUni =
6109 kDefaultStreamWindowSize;
6110 quicCachedPsk.transportParams.initialMaxData =
6111 kDefaultConnectionWindowSize;
6112 quicCachedPsk.transportParams.idleTimeout = kDefaultIdleTimeout.count();
6113 quicCachedPsk.transportParams.maxRecvPacketSize =
6114 kDefaultUDPReadBufferSize;
6115 quicCachedPsk.transportParams.initialMaxStreamsBidi =
6116 std::numeric_limits<uint32_t>::max();
6117 quicCachedPsk.transportParams.initialMaxStreamsUni =
6118 std::numeric_limits<uint32_t>::max();
6119 return quicCachedPsk;
6120 }));
6121 client->setEarlyDataAppParamsFunctions(
6122 [&](const folly::Optional<std::string>&, const Buf&) { return true; },
6123 []() -> Buf { return nullptr; });
6124
6125 EXPECT_CALL(*sock, write(firstAddress, _))
6126 .WillOnce(Invoke(
6127 [&](const SocketAddress&, const std::unique_ptr<folly::IOBuf>& buf) {
6128 socketWrites.push_back(buf->clone());
6129 return buf->computeChainDataLength();
6130 }));
6131 startClient();
6132 socketWrites.clear();
6133 auto& conn = client->getConn();
6134 EXPECT_EQ(conn.peerAddress, firstAddress);
6135 EXPECT_EQ(conn.happyEyeballsState.secondPeerAddress, secondAddress);
6136 ASSERT_TRUE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
6137
6138 EXPECT_CALL(*sock, write(firstAddress, _))
6139 .WillOnce(Invoke(
6140 [&](const SocketAddress&, const std::unique_ptr<folly::IOBuf>&) {
6141 errno = EBADF;
6142 return -1;
6143 }));
6144 auto streamId = client->createBidirectionalStream().value();
6145 client->writeChain(streamId, IOBuf::copyBuffer("hello"), true);
6146 loopForWrites();
6147 EXPECT_FALSE(zeroRttPacketsOutstanding());
6148 ASSERT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
6149
6150 ASSERT_TRUE(conn.happyEyeballsState.shouldWriteToSecondSocket);
6151 EXPECT_FALSE(client->happyEyeballsConnAttemptDelayTimeout().isScheduled());
6152
6153 EXPECT_CALL(*secondSock, write(secondAddress, _))
6154 .Times(2)
6155 .WillRepeatedly(Invoke(
6156 [&](const SocketAddress&, const std::unique_ptr<folly::IOBuf>& buf) {
6157 socketWrites.push_back(buf->clone());
6158 return buf->computeChainDataLength();
6159 }));
6160 client->lossTimeout().cancelTimeout();
6161 client->lossTimeout().timeoutExpired();
6162 ASSERT_EQ(socketWrites.size(), 2);
6163 EXPECT_TRUE(
6164 verifyLongHeader(*socketWrites.at(0), LongHeader::Types::Initial));
6165 EXPECT_TRUE(
6166 verifyLongHeader(*socketWrites.at(1), LongHeader::Types::ZeroRtt));
6167 }
6168
6169 class QuicProcessDataTest : public QuicClientTransportAfterStartTestBase,
6170 public testing::WithParamInterface<uint8_t> {
6171 public:
6172 ~QuicProcessDataTest() override = default;
6173
start()6174 void start() override {
6175 // force the server to declare that the version negotiated was invalid.;
6176 mockClientHandshake->negotiatedVersion = QuicVersion::QUIC_V1;
6177 client->setSupportedVersions({QuicVersion::QUIC_V1});
6178 client->start(&clientConnCallback);
6179 setConnectionIds();
6180 }
6181 };
6182
6183 INSTANTIATE_TEST_CASE_P(
6184 QuicClientZeroLenConnIds,
6185 QuicProcessDataTest,
6186 ::Values(0, 8));
6187
TEST_F(QuicProcessDataTest,ProcessDataWithGarbageAtEnd)6188 TEST_F(QuicProcessDataTest, ProcessDataWithGarbageAtEnd) {
6189 expectQuicStatsPacketDrop(
6190 QuicTransportStatsCallback::PacketDropReason::PARSE_ERROR);
6191 auto qLogger = std::make_shared<FileQLogger>(VantagePoint::Client);
6192 client->getNonConstConn().qLogger = qLogger;
6193 auto params = mockClientHandshake->getServerTransportParams();
6194 params->parameters.push_back(encodeConnIdParameter(
6195 TransportParameterId::initial_source_connection_id, *serverChosenConnId));
6196 params->parameters.push_back(encodeConnIdParameter(
6197 TransportParameterId::original_destination_connection_id,
6198 *client->getConn().initialDestinationConnectionId));
6199 mockClientHandshake->setServerTransportParams(std::move(*params));
6200 auto serverHello = IOBuf::copyBuffer("Fake SHLO");
6201 PacketNum nextPacketNum = initialPacketNum++;
6202 auto& aead = getInitialCipher();
6203 auto packet = createCryptoPacket(
6204 *serverChosenConnId,
6205 *originalConnId,
6206 nextPacketNum,
6207 QuicVersion::QUIC_V1,
6208 ProtectionType::Initial,
6209 *serverHello,
6210 aead,
6211 0 /* largestAcked */);
6212 auto packetData = packetToBufCleartext(
6213 packet, aead, getInitialHeaderCipher(), nextPacketNum);
6214 packetData->prependChain(IOBuf::copyBuffer("garbage in"));
6215 deliverData(serverAddr, packetData->coalesce());
6216 verifyTransportParameters(
6217 kDefaultConnectionWindowSize,
6218 kDefaultStreamWindowSize,
6219 kDefaultIdleTimeout,
6220 kDefaultAckDelayExponent,
6221 mockClientHandshake->maxRecvPacketSize);
6222 std::vector<int> indices =
6223 getQLogEventIndices(QLogEventType::PacketDrop, qLogger);
6224 EXPECT_EQ(indices.size(), 1);
6225 auto tmp = std::move(qLogger->logs[indices[0]]);
6226 auto event = dynamic_cast<QLogPacketDropEvent*>(tmp.get());
6227 EXPECT_EQ(event->packetSize, 10);
6228 EXPECT_EQ(event->dropReason, kParse);
6229 }
6230
TEST_F(QuicProcessDataTest,ProcessPendingData)6231 TEST_F(QuicProcessDataTest, ProcessPendingData) {
6232 auto params = mockClientHandshake->getServerTransportParams();
6233 params->parameters.push_back(encodeConnIdParameter(
6234 TransportParameterId::initial_source_connection_id, *serverChosenConnId));
6235 params->parameters.push_back(encodeConnIdParameter(
6236 TransportParameterId::original_destination_connection_id,
6237 *client->getConn().initialDestinationConnectionId));
6238 mockClientHandshake->setServerTransportParams(std::move(*params));
6239 auto serverHello = IOBuf::copyBuffer("Fake SHLO");
6240 PacketNum nextPacketNum = initialPacketNum++;
6241 auto& aead = getInitialCipher();
6242 auto packet = createCryptoPacket(
6243 *serverChosenConnId,
6244 *originalConnId,
6245 nextPacketNum,
6246 QuicVersion::QUIC_V1,
6247 ProtectionType::Initial,
6248 *serverHello,
6249 aead,
6250 0 /* largestAcked */);
6251 auto packetData = packetToBufCleartext(
6252 packet, aead, getInitialHeaderCipher(), nextPacketNum);
6253 deliverData(serverAddr, packetData->coalesce());
6254 verifyTransportParameters(
6255 kDefaultConnectionWindowSize,
6256 kDefaultStreamWindowSize,
6257 kDefaultIdleTimeout,
6258 kDefaultAckDelayExponent,
6259 mockClientHandshake->maxRecvPacketSize);
6260
6261 mockClientHandshake->setOneRttReadCipher(nullptr);
6262 mockClientHandshake->setHandshakeReadCipher(nullptr);
6263 ASSERT_TRUE(client->getConn().pendingOneRttData.empty());
6264 auto streamId1 = client->createBidirectionalStream().value();
6265
6266 auto data = folly::IOBuf::copyBuffer("1RTT data!");
6267 auto streamPacket1 = packetToBuf(createStreamPacket(
6268 *serverChosenConnId /* src */,
6269 *originalConnId /* dest */,
6270 appDataPacketNum++,
6271 streamId1,
6272 *data,
6273 0 /* cipherOverhead */,
6274 0 /* largestAcked */));
6275 deliverData(streamPacket1->coalesce());
6276 EXPECT_EQ(client->getConn().pendingOneRttData.size(), 1);
6277
6278 auto cryptoData = folly::IOBuf::copyBuffer("Crypto data!");
6279 auto cryptoPacket1 = packetToBuf(createCryptoPacket(
6280 *serverChosenConnId,
6281 *originalConnId,
6282 handshakePacketNum++,
6283 QuicVersion::QUIC_V1,
6284 ProtectionType::Handshake,
6285 *cryptoData,
6286 *createNoOpAead(),
6287 0 /* largestAcked */));
6288 deliverData(cryptoPacket1->coalesce());
6289 EXPECT_EQ(client->getConn().pendingOneRttData.size(), 1);
6290 EXPECT_EQ(client->getConn().pendingHandshakeData.size(), 1);
6291
6292 mockClientHandshake->setOneRttReadCipher(createNoOpAead());
6293 auto streamId2 = client->createBidirectionalStream().value();
6294 auto streamPacket2 = packetToBuf(createStreamPacket(
6295 *serverChosenConnId /* src */,
6296 *originalConnId /* dest */,
6297 appDataPacketNum++,
6298 streamId2,
6299 *data,
6300 0 /* cipherOverhead */,
6301 0 /* largestAcked */));
6302 deliverData(streamPacket2->coalesce());
6303 EXPECT_TRUE(client->getConn().pendingOneRttData.empty());
6304 EXPECT_EQ(client->getConn().pendingHandshakeData.size(), 1);
6305
6306 // Set the oneRtt one back to nullptr to make sure we trigger it on handshake
6307 // only.
6308 // mockClientHandshake->setOneRttReadCipher(nullptr);
6309 mockClientHandshake->setHandshakeReadCipher(createNoOpAead());
6310 auto cryptoPacket2 = packetToBuf(createCryptoPacket(
6311 *serverChosenConnId,
6312 *originalConnId,
6313 handshakePacketNum++,
6314 QuicVersion::QUIC_V1,
6315 ProtectionType::Handshake,
6316 *cryptoData,
6317 *createNoOpAead(),
6318 0,
6319 cryptoData->length()));
6320 deliverData(cryptoPacket2->coalesce());
6321 EXPECT_TRUE(client->getConn().pendingHandshakeData.empty());
6322 EXPECT_TRUE(client->getConn().pendingOneRttData.empty());
6323
6324 // Both stream data and crypto data should be there.
6325 auto d1 = client->read(streamId1, 1000);
6326 ASSERT_FALSE(d1.hasError());
6327 auto d2 = client->read(streamId2, 1000);
6328 ASSERT_FALSE(d2.hasError());
6329 EXPECT_TRUE(folly::IOBufEqualTo()(*d1.value().first, *data));
6330 EXPECT_TRUE(folly::IOBufEqualTo()(*d2.value().first, *data));
6331
6332 ASSERT_FALSE(
6333 mockClientHandshake->readBuffers[EncryptionLevel::Handshake].empty());
6334 auto handshakeReadData =
6335 mockClientHandshake->readBuffers[EncryptionLevel::Handshake].move();
6336 cryptoData->prependChain(cryptoData->clone());
6337 EXPECT_TRUE(folly::IOBufEqualTo()(*cryptoData, *handshakeReadData));
6338 }
6339
TEST_F(QuicProcessDataTest,ProcessPendingDataBufferLimit)6340 TEST_F(QuicProcessDataTest, ProcessPendingDataBufferLimit) {
6341 auto params = mockClientHandshake->getServerTransportParams();
6342 params->parameters.push_back(encodeConnIdParameter(
6343 TransportParameterId::initial_source_connection_id, *serverChosenConnId));
6344 params->parameters.push_back(encodeConnIdParameter(
6345 TransportParameterId::original_destination_connection_id,
6346 *client->getConn().initialDestinationConnectionId));
6347 mockClientHandshake->setServerTransportParams(std::move(*params));
6348 auto serverHello = IOBuf::copyBuffer("Fake SHLO");
6349 PacketNum nextPacketNum = initialPacketNum++;
6350 auto& aead = getInitialCipher();
6351 auto packet = createCryptoPacket(
6352 *serverChosenConnId,
6353 *originalConnId,
6354 nextPacketNum,
6355 QuicVersion::QUIC_V1,
6356 ProtectionType::Initial,
6357 *serverHello,
6358 aead,
6359 0 /* largestAcked */);
6360 auto packetData = packetToBufCleartext(
6361 packet, aead, getInitialHeaderCipher(), nextPacketNum);
6362 deliverData(serverAddr, packetData->coalesce());
6363 verifyTransportParameters(
6364 kDefaultConnectionWindowSize,
6365 kDefaultStreamWindowSize,
6366 kDefaultIdleTimeout,
6367 kDefaultAckDelayExponent,
6368 mockClientHandshake->maxRecvPacketSize);
6369
6370 client->getNonConstConn().transportSettings.maxPacketsToBuffer = 2;
6371 auto data = folly::IOBuf::copyBuffer("1RTT data!");
6372 mockClientHandshake->setOneRttReadCipher(nullptr);
6373 ASSERT_TRUE(client->getConn().pendingOneRttData.empty());
6374 auto streamId1 = client->createBidirectionalStream().value();
6375 auto streamPacket1 = packetToBuf(createStreamPacket(
6376 *serverChosenConnId /* src */,
6377 *originalConnId /* dest */,
6378 appDataPacketNum++,
6379 streamId1,
6380 *data,
6381 0 /* cipherOverhead */,
6382 0 /* largestAcked */));
6383 deliverData(streamPacket1->coalesce());
6384 EXPECT_EQ(client->getConn().pendingOneRttData.size(), 1);
6385
6386 auto streamId2 = client->createBidirectionalStream().value();
6387 auto streamPacket2 = packetToBuf(createStreamPacket(
6388 *serverChosenConnId /* src */,
6389 *originalConnId /* dest */,
6390 appDataPacketNum++,
6391 streamId2,
6392 *data,
6393 0 /* cipherOverhead */,
6394 0 /* largestAcked */));
6395 deliverData(streamPacket2->coalesce());
6396 EXPECT_EQ(client->getConn().pendingOneRttData.size(), 2);
6397
6398 auto streamId3 = client->createBidirectionalStream().value();
6399 auto streamPacket3 = packetToBuf(createStreamPacket(
6400 *serverChosenConnId /* src */,
6401 *originalConnId /* dest */,
6402 appDataPacketNum++,
6403 streamId3,
6404 *data,
6405 0 /* cipherOverhead */,
6406 0 /* largestAcked */));
6407 deliverData(streamPacket3->coalesce());
6408 EXPECT_EQ(client->getConn().pendingOneRttData.size(), 2);
6409
6410 mockClientHandshake->setOneRttReadCipher(createNoOpAead());
6411 auto streamId4 = client->createBidirectionalStream().value();
6412 auto streamPacket4 = packetToBuf(createStreamPacket(
6413 *serverChosenConnId /* src */,
6414 *originalConnId /* dest */,
6415 appDataPacketNum++,
6416 streamId4,
6417 *data,
6418 0 /* cipherOverhead */,
6419 0 /* largestAcked */));
6420 deliverData(streamPacket4->coalesce());
6421 EXPECT_TRUE(client->getConn().pendingOneRttData.empty());
6422
6423 // First, second, and fourht stream data should be there.
6424 auto d1 = client->read(streamId1, 1000);
6425 ASSERT_FALSE(d1.hasError());
6426 auto d2 = client->read(streamId2, 1000);
6427 ASSERT_FALSE(d2.hasError());
6428 auto d3 = client->read(streamId3, 1000);
6429 ASSERT_FALSE(d3.hasError());
6430 EXPECT_EQ(d3.value().first, nullptr);
6431 auto d4 = client->read(streamId4, 1000);
6432 ASSERT_FALSE(d4.hasError());
6433 EXPECT_TRUE(folly::IOBufEqualTo()(*d1.value().first, *data));
6434 EXPECT_TRUE(folly::IOBufEqualTo()(*d2.value().first, *data));
6435 EXPECT_TRUE(folly::IOBufEqualTo()(*d4.value().first, *data));
6436 }
6437
TEST_P(QuicProcessDataTest,ProcessDataHeaderOnly)6438 TEST_P(QuicProcessDataTest, ProcessDataHeaderOnly) {
6439 uint8_t connIdSize = GetParam();
6440 client->getNonConstConn().clientConnectionId =
6441 ConnectionId(std::vector<uint8_t>(connIdSize, 1));
6442 setConnectionIds();
6443
6444 auto qLogger = std::make_shared<FileQLogger>(VantagePoint::Client);
6445 client->getNonConstConn().qLogger = qLogger;
6446 auto serverHello = IOBuf::copyBuffer("Fake SHLO");
6447 PacketNum nextPacketNum = initialPacketNum++;
6448 auto& aead = getInitialCipher();
6449 auto largestReceivedPacketNum =
6450 getAckState(client->getConn(), PacketNumberSpace::Handshake)
6451 .largestReceivedPacketNum;
6452 auto packet = createCryptoPacket(
6453 *serverChosenConnId,
6454 *originalConnId,
6455 nextPacketNum,
6456 QuicVersion::QUIC_V1,
6457 ProtectionType::Initial,
6458 *serverHello,
6459 aead,
6460 0 /* largestAcked */);
6461
6462 deliverData(serverAddr, packet.header->coalesce());
6463 EXPECT_EQ(
6464 getAckState(client->getConn(), PacketNumberSpace::Handshake)
6465 .largestReceivedPacketNum,
6466 largestReceivedPacketNum);
6467
6468 std::vector<int> indices =
6469 getQLogEventIndices(QLogEventType::DatagramReceived, qLogger);
6470 EXPECT_EQ(indices.size(), 1);
6471 auto tmp = std::move(qLogger->logs[indices[0]]);
6472 auto event = dynamic_cast<QLogDatagramReceivedEvent*>(tmp.get());
6473 EXPECT_EQ(event->dataLen, 18 + connIdSize);
6474 }
6475
TEST(AsyncUDPSocketTest,CloseMultipleTimes)6476 TEST(AsyncUDPSocketTest, CloseMultipleTimes) {
6477 class EmptyReadCallback : public AsyncUDPSocket::ReadCallback {
6478 public:
6479 void getReadBuffer(void**, size_t*) noexcept override {}
6480 void onDataAvailable(
6481 const folly::SocketAddress&,
6482 size_t,
6483 bool,
6484 OnDataAvailableParams) noexcept override {}
6485 void onReadError(const AsyncSocketException&) noexcept override {}
6486 void onReadClosed() noexcept override {}
6487 };
6488
6489 class EmptyErrMessageCallback : public AsyncUDPSocket::ErrMessageCallback {
6490 public:
6491 void errMessage(const cmsghdr&) noexcept override {}
6492 void errMessageError(const AsyncSocketException&) noexcept override {}
6493 };
6494
6495 EventBase evb;
6496 AsyncUDPSocket socket(&evb);
6497 TransportSettings transportSettings;
6498 EmptyErrMessageCallback errMessageCallback;
6499 EmptyReadCallback readCallback;
6500 happyEyeballsSetUpSocket(
6501 socket,
6502 folly::none,
6503 folly::SocketAddress("127.0.0.1", 12345),
6504 transportSettings,
6505 &errMessageCallback,
6506 &readCallback,
6507 folly::emptySocketOptionMap);
6508
6509 socket.pauseRead();
6510 socket.close();
6511 socket.pauseRead();
6512 socket.close();
6513 }
6514 } // namespace test
6515 } // namespace quic
6516