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