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
9 #include <quic/api/QuicTransportFunctions.h>
10
11 #include <folly/io/async/test/MockAsyncUDPSocket.h>
12 #include <quic/api/test/Mocks.h>
13 #include <quic/common/test/TestUtils.h>
14 #include <quic/fizz/server/handshake/FizzServerQuicHandshakeContext.h>
15 #include <quic/logging/FileQLogger.h>
16 #include <quic/logging/QLoggerConstants.h>
17 #include <quic/server/state/ServerStateMachine.h>
18 #include <quic/state/test/MockQuicStats.h>
19 #include <quic/state/test/Mocks.h>
20
21 #include <gtest/gtest.h>
22
23 using namespace folly;
24 using namespace testing;
25
26 namespace quic {
27 namespace test {
28
writeProbingDataToSocketForTest(folly::AsyncUDPSocket & sock,QuicConnectionStateBase & conn,uint8_t probesToSend,const Aead & aead,const PacketNumberCipher & headerCipher,QuicVersion version)29 uint64_t writeProbingDataToSocketForTest(
30 folly::AsyncUDPSocket& sock,
31 QuicConnectionStateBase& conn,
32 uint8_t probesToSend,
33 const Aead& aead,
34 const PacketNumberCipher& headerCipher,
35 QuicVersion version) {
36 FrameScheduler scheduler = std::move(FrameScheduler::Builder(
37 conn,
38 EncryptionLevel::AppData,
39 PacketNumberSpace::AppData,
40 "test")
41 .streamFrames()
42 .cryptoFrames())
43 .build();
44 return writeProbingDataToSocket(
45 sock,
46 conn,
47 *conn.clientConnectionId,
48 *conn.serverConnectionId,
49 ShortHeaderBuilder(),
50 EncryptionLevel::AppData,
51 PacketNumberSpace::AppData,
52 scheduler,
53 probesToSend,
54 aead,
55 headerCipher,
56 version);
57 }
58
writeCryptoDataProbesToSocketForTest(folly::AsyncUDPSocket & sock,QuicConnectionStateBase & conn,uint8_t probesToSend,const Aead & aead,const PacketNumberCipher & headerCipher,QuicVersion version,LongHeader::Types type=LongHeader::Types::Initial)59 void writeCryptoDataProbesToSocketForTest(
60 folly::AsyncUDPSocket& sock,
61 QuicConnectionStateBase& conn,
62 uint8_t probesToSend,
63 const Aead& aead,
64 const PacketNumberCipher& headerCipher,
65 QuicVersion version,
66 LongHeader::Types type = LongHeader::Types::Initial) {
67 auto encryptionLevel =
68 protectionTypeToEncryptionLevel(longHeaderTypeToProtectionType(type));
69 auto pnSpace = LongHeader::typeToPacketNumberSpace(type);
70 auto scheduler = std::move(FrameScheduler::Builder(
71 conn, encryptionLevel, pnSpace, "Crypto")
72 .cryptoFrames())
73 .build();
74 writeProbingDataToSocket(
75 sock,
76 conn,
77 *conn.clientConnectionId,
78 *conn.serverConnectionId,
79 LongHeaderBuilder(type),
80 protectionTypeToEncryptionLevel(longHeaderTypeToProtectionType(type)),
81 LongHeader::typeToPacketNumberSpace(type),
82 scheduler,
83 probesToSend,
84 aead,
85 headerCipher,
86 version);
87 }
88
buildEmptyPacket(QuicServerConnectionState & conn,PacketNumberSpace pnSpace,bool shortHeader=false)89 auto buildEmptyPacket(
90 QuicServerConnectionState& conn,
91 PacketNumberSpace pnSpace,
92 bool shortHeader = false) {
93 folly::Optional<PacketHeader> header;
94 if (shortHeader) {
95 header = ShortHeader(
96 ProtectionType::KeyPhaseZero,
97 *conn.clientConnectionId,
98 conn.ackStates.appDataAckState.nextPacketNum);
99 } else {
100 if (pnSpace == PacketNumberSpace::Initial) {
101 header = LongHeader(
102 LongHeader::Types::Initial,
103 *conn.clientConnectionId,
104 *conn.serverConnectionId,
105 conn.ackStates.initialAckState.nextPacketNum,
106 *conn.version);
107 } else if (pnSpace == PacketNumberSpace::Handshake) {
108 header = LongHeader(
109 LongHeader::Types::Handshake,
110 *conn.clientConnectionId,
111 *conn.serverConnectionId,
112 conn.ackStates.handshakeAckState.nextPacketNum,
113 *conn.version);
114 } else if (pnSpace == PacketNumberSpace::AppData) {
115 header = LongHeader(
116 LongHeader::Types::ZeroRtt,
117 *conn.clientConnectionId,
118 *conn.serverConnectionId,
119 conn.ackStates.appDataAckState.nextPacketNum,
120 *conn.version);
121 }
122 }
123 RegularQuicPacketBuilder builder(
124 conn.udpSendPacketLen,
125 std::move(*header),
126 getAckState(conn, pnSpace).largestAckedByPeer.value_or(0));
127 builder.encodePacketHeader();
128 DCHECK(builder.canBuildPacket());
129 return std::move(builder).buildPacket();
130 }
131
getEncodedSize(const RegularQuicPacketBuilder::Packet & packet)132 uint64_t getEncodedSize(const RegularQuicPacketBuilder::Packet& packet) {
133 // calculate size as the plaintext size
134 uint32_t encodedSize = 0;
135 if (packet.header) {
136 encodedSize += packet.header->computeChainDataLength();
137 }
138 if (packet.body) {
139 encodedSize += packet.body->computeChainDataLength();
140 }
141 return encodedSize;
142 }
143
getEncodedBodySize(const RegularQuicPacketBuilder::Packet & packet)144 uint64_t getEncodedBodySize(const RegularQuicPacketBuilder::Packet& packet) {
145 // calculate size as the plaintext size
146 uint32_t encodedBodySize = 0;
147 if (packet.body) {
148 encodedBodySize += packet.body->computeChainDataLength();
149 }
150 return encodedBodySize;
151 }
152
153 class QuicTransportFunctionsTest : public Test {
154 public:
SetUp()155 void SetUp() override {
156 aead = test::createNoOpAead();
157 headerCipher = test::createNoOpHeaderCipher();
158 transportInfoCb_ = std::make_unique<NiceMock<MockQuicStats>>();
159 }
160
createConn()161 std::unique_ptr<QuicServerConnectionState> createConn() {
162 auto conn = std::make_unique<QuicServerConnectionState>(
163 FizzServerQuicHandshakeContext::Builder().build());
164 conn->serverConnectionId = getTestConnectionId();
165 conn->clientConnectionId = getTestConnectionId();
166 conn->version = QuicVersion::MVFST;
167 conn->flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiLocal =
168 kDefaultStreamWindowSize;
169 conn->flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiRemote =
170 kDefaultStreamWindowSize;
171 conn->flowControlState.peerAdvertisedInitialMaxStreamOffsetUni =
172 kDefaultStreamWindowSize;
173 conn->flowControlState.peerAdvertisedMaxOffset =
174 kDefaultConnectionWindowSize;
175 conn->statsCallback = transportInfoCb_.get();
176 conn->initialWriteCipher = createNoOpAead();
177 conn->initialHeaderCipher = createNoOpHeaderCipher();
178 conn->streamManager->setMaxLocalBidirectionalStreams(
179 kDefaultMaxStreamsBidirectional);
180 conn->streamManager->setMaxLocalUnidirectionalStreams(
181 kDefaultMaxStreamsUnidirectional);
182 return conn;
183 }
184
getVersion(QuicServerConnectionState & conn)185 QuicVersion getVersion(QuicServerConnectionState& conn) {
186 return conn.version.value_or(*conn.originalVersion);
187 }
188
189 std::unique_ptr<Aead> aead;
190 std::unique_ptr<PacketNumberCipher> headerCipher;
191 std::unique_ptr<MockQuicStats> transportInfoCb_;
192 };
193
TEST_F(QuicTransportFunctionsTest,PingPacketGoesToOPList)194 TEST_F(QuicTransportFunctionsTest, PingPacketGoesToOPList) {
195 auto conn = createConn();
196 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
197 packet.packet.frames.push_back(PingFrame());
198 EXPECT_EQ(0, conn->outstandings.packets.size());
199 updateConnection(
200 *conn,
201 folly::none,
202 packet.packet,
203 Clock::now(),
204 50,
205 0,
206 false /* isDSRPacket */);
207 EXPECT_EQ(1, conn->outstandings.packets.size());
208 // But it won't set loss detection alarm
209 EXPECT_FALSE(conn->pendingEvents.setLossDetectionAlarm);
210 }
211
TEST_F(QuicTransportFunctionsTest,TestUpdateConnection)212 TEST_F(QuicTransportFunctionsTest, TestUpdateConnection) {
213 auto conn = createConn();
214 auto mockCongestionController =
215 std::make_unique<NiceMock<MockCongestionController>>();
216 auto rawCongestionController = mockCongestionController.get();
217 conn->congestionController = std::move(mockCongestionController);
218 conn->qLogger = std::make_shared<quic::FileQLogger>(VantagePoint::Client);
219 // Builds a fake packet to test with.
220 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
221
222 auto stream1Id =
223 conn->streamManager->createNextBidirectionalStream().value()->id;
224 auto stream2Id =
225 conn->streamManager->createNextBidirectionalStream().value()->id;
226 auto stream1 = conn->streamManager->findStream(stream1Id);
227 auto stream2 = conn->streamManager->findStream(stream2Id);
228
229 auto buf = IOBuf::copyBuffer("hey whats up");
230 EXPECT_CALL(*transportInfoCb_, onPacketRetransmission()).Times(2);
231 writeDataToQuicStream(*stream1, buf->clone(), true);
232 writeDataToQuicStream(*stream2, buf->clone(), true);
233
234 WriteStreamFrame writeStreamFrame1(stream1->id, 0, 5, false);
235 WriteStreamFrame writeStreamFrame2(stream2->id, 0, 12, true);
236 packet.packet.frames.push_back(std::move(writeStreamFrame1));
237 packet.packet.frames.push_back(std::move(writeStreamFrame2));
238
239 auto currentNextInitialPacketNum =
240 conn->ackStates.initialAckState.nextPacketNum;
241 auto currentNextHandshakePacketNum =
242 conn->ackStates.handshakeAckState.nextPacketNum;
243 auto currentNextAppDataPacketNum =
244 conn->ackStates.appDataAckState.nextPacketNum;
245 EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(1);
246 EXPECT_CALL(*rawCongestionController, isAppLimited())
247 .Times(1)
248 .WillOnce(Return(true));
249 updateConnection(
250 *conn,
251 folly::none,
252 packet.packet,
253 TimePoint{},
254 getEncodedSize(packet),
255 getEncodedBodySize(packet),
256 false /* isDSRPacket */);
257
258 EXPECT_EQ(
259 conn->ackStates.initialAckState.nextPacketNum,
260 currentNextInitialPacketNum);
261 EXPECT_GT(
262 conn->ackStates.handshakeAckState.nextPacketNum,
263 currentNextHandshakePacketNum);
264 EXPECT_EQ(
265 conn->ackStates.appDataAckState.nextPacketNum,
266 currentNextAppDataPacketNum);
267 EXPECT_TRUE(conn->outstandings.packets.back().isAppLimited);
268
269 EXPECT_EQ(stream1->currentWriteOffset, 5);
270 EXPECT_EQ(stream2->currentWriteOffset, 13);
271 EXPECT_EQ(conn->flowControlState.sumCurWriteOffset, 17);
272
273 IOBufEqualTo eq;
274
275 EXPECT_EQ(stream1->retransmissionBuffer.size(), 1);
276 auto& rt1 = *stream1->retransmissionBuffer.at(0);
277 EXPECT_EQ(rt1.offset, 0);
278 EXPECT_TRUE(eq(*IOBuf::copyBuffer("hey w"), *rt1.data.front()));
279
280 EXPECT_EQ(stream2->retransmissionBuffer.size(), 1);
281 auto& rt2 = *stream2->retransmissionBuffer.at(0);
282 EXPECT_EQ(rt2.offset, 0);
283 EXPECT_TRUE(eq(*buf, *rt2.data.front()));
284 EXPECT_TRUE(rt2.eof);
285
286 // Testing retransmission
287 stream1->lossBuffer.push_back(std::move(rt1));
288 stream1->retransmissionBuffer.clear();
289 stream2->lossBuffer.push_back(std::move(rt2));
290 stream2->retransmissionBuffer.clear();
291 conn->streamManager->addLoss(stream1->id);
292 conn->streamManager->addLoss(stream2->id);
293
294 // Write the remainder of the data with retransmission
295 auto packet2 = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
296 WriteStreamFrame writeStreamFrame3(stream1->id, 5, 7, true);
297 WriteStreamFrame writeStreamFrame4(stream1->id, 0, 5, false);
298 WriteStreamFrame writeStreamFrame5(stream2->id, 0, 6, false);
299 packet2.packet.frames.push_back(std::move(writeStreamFrame3));
300 packet2.packet.frames.push_back(std::move(writeStreamFrame4));
301 packet2.packet.frames.push_back(std::move(writeStreamFrame5));
302
303 EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(1);
304 currentNextInitialPacketNum = conn->ackStates.initialAckState.nextPacketNum;
305 currentNextHandshakePacketNum =
306 conn->ackStates.handshakeAckState.nextPacketNum;
307 currentNextAppDataPacketNum = conn->ackStates.appDataAckState.nextPacketNum;
308 EXPECT_CALL(*rawCongestionController, isAppLimited())
309 .Times(1)
310 .WillOnce(Return(false));
311 updateConnection(
312 *conn,
313 folly::none,
314 packet2.packet,
315 TimePoint(),
316 getEncodedSize(packet2),
317 getEncodedBodySize(packet2),
318 false /* isDSRPacket */);
319 EXPECT_EQ(
320 conn->ackStates.initialAckState.nextPacketNum,
321 currentNextInitialPacketNum);
322 EXPECT_GT(
323 conn->ackStates.handshakeAckState.nextPacketNum,
324 currentNextHandshakePacketNum);
325 EXPECT_EQ(
326 conn->ackStates.appDataAckState.nextPacketNum,
327 currentNextAppDataPacketNum);
328 EXPECT_FALSE(conn->outstandings.packets.back().isAppLimited);
329
330 EXPECT_EQ(stream1->currentWriteOffset, 13);
331 EXPECT_EQ(stream2->currentWriteOffset, 13);
332 EXPECT_EQ(conn->flowControlState.sumCurWriteOffset, 24);
333
334 EXPECT_EQ(stream1->lossBuffer.size(), 0);
335 EXPECT_EQ(stream1->retransmissionBuffer.size(), 2);
336 auto& rt3 = *stream1->retransmissionBuffer.at(5);
337 EXPECT_TRUE(eq(IOBuf::copyBuffer("hats up"), rt3.data.move()));
338
339 auto& rt4 = *stream1->retransmissionBuffer.at(0);
340 EXPECT_TRUE(eq(*IOBuf::copyBuffer("hey w"), *rt4.data.front()));
341
342 // loss buffer should be split into 2. Part in retransmission buffer and
343 // part remains in loss buffer.
344 EXPECT_EQ(stream2->lossBuffer.size(), 1);
345 EXPECT_EQ(stream2->retransmissionBuffer.size(), 1);
346 auto& rt5 = *stream2->retransmissionBuffer.at(0);
347 EXPECT_TRUE(eq(*IOBuf::copyBuffer("hey wh"), *rt5.data.front()));
348 EXPECT_EQ(rt5.offset, 0);
349 EXPECT_EQ(rt5.eof, 0);
350
351 auto& rt6 = stream2->lossBuffer.front();
352 EXPECT_TRUE(eq(*IOBuf::copyBuffer("ats up"), *rt6.data.front()));
353 EXPECT_EQ(rt6.offset, 6);
354 EXPECT_EQ(rt6.eof, 1);
355
356 // verify handshake packets stored in QLogger
357 std::shared_ptr<quic::FileQLogger> qLogger =
358 std::dynamic_pointer_cast<quic::FileQLogger>(conn->qLogger);
359 std::vector<int> indices =
360 getQLogEventIndices(QLogEventType::PacketSent, qLogger);
361 EXPECT_EQ(indices.size(), 2);
362
363 for (int i = 0; i < 2; ++i) {
364 auto p1 = std::move(qLogger->logs[indices[i]]);
365 auto event = dynamic_cast<QLogPacketEvent*>(p1.get());
366 EXPECT_EQ(event->packetType, toQlogString(LongHeader::Types::Handshake));
367 EXPECT_EQ(event->packetSize, getEncodedSize(packet));
368 EXPECT_EQ(event->eventType, QLogEventType::PacketSent);
369
370 if (i == 0) {
371 EXPECT_EQ(event->frames.size(), 2);
372 auto frame = static_cast<StreamFrameLog*>(event->frames[0].get());
373 EXPECT_EQ(frame->streamId, stream1->id);
374 EXPECT_EQ(frame->offset, 0);
375 EXPECT_EQ(frame->len, 5);
376 EXPECT_FALSE(frame->fin);
377 } else if (i == 1) {
378 EXPECT_EQ(event->frames.size(), 3);
379 auto frame = static_cast<StreamFrameLog*>(event->frames[0].get());
380 EXPECT_EQ(frame->streamId, stream1->id);
381 EXPECT_EQ(frame->offset, 5);
382 EXPECT_EQ(frame->len, 7);
383 EXPECT_TRUE(frame->fin);
384 }
385 }
386 }
387
TEST_F(QuicTransportFunctionsTest,TestUpdateConnectionPacketRetrans)388 TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionPacketRetrans) {
389 const IOBufEqualTo eq;
390
391 auto conn = createConn();
392 auto mockCongestionController =
393 std::make_unique<NiceMock<MockCongestionController>>();
394 auto rawCongestionController = mockCongestionController.get();
395 conn->congestionController = std::move(mockCongestionController);
396 conn->qLogger = std::make_shared<quic::FileQLogger>(VantagePoint::Client);
397
398 // two streams, both writing "hey whats up"
399 auto stream1Id =
400 conn->streamManager->createNextBidirectionalStream().value()->id;
401 auto stream2Id =
402 conn->streamManager->createNextBidirectionalStream().value()->id;
403 auto stream1 = conn->streamManager->findStream(stream1Id);
404 auto stream2 = conn->streamManager->findStream(stream2Id);
405 auto buf = IOBuf::copyBuffer("hey whats up");
406 writeDataToQuicStream(*stream1, buf->clone(), true /* eof */);
407 writeDataToQuicStream(*stream2, buf->clone(), true /* eof */);
408 WriteStreamFrame writeStreamFrame1(stream1->id, 0, 12, true /* eom */);
409 WriteStreamFrame writeStreamFrame2(stream2->id, 0, 12, true /* eom */);
410 EXPECT_EQ(stream1->currentWriteOffset, 0);
411 EXPECT_EQ(stream2->currentWriteOffset, 0);
412 EXPECT_EQ(conn->flowControlState.sumCurWriteOffset, 0);
413
414 // add both stream frames into AppData packet1
415 auto packet1 = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
416 packet1.packet.frames.push_back(writeStreamFrame1);
417 packet1.packet.frames.push_back(writeStreamFrame2);
418
419 // mimic send, call updateConnection
420 auto currentNextInitialPacketNum =
421 conn->ackStates.initialAckState.nextPacketNum;
422 auto currentNextHandshakePacketNum =
423 conn->ackStates.handshakeAckState.nextPacketNum;
424 auto currentNextAppDataPacketNum =
425 conn->ackStates.appDataAckState.nextPacketNum;
426 EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(1);
427 EXPECT_CALL(*rawCongestionController, isAppLimited())
428 .Times(1)
429 .WillOnce(Return(true));
430 updateConnection(
431 *conn,
432 folly::none,
433 packet1.packet,
434 TimePoint{},
435 getEncodedSize(packet1),
436 getEncodedBodySize(packet1),
437 false /* isDSRPacket */);
438
439 // appData packet number should increase
440 EXPECT_EQ(
441 conn->ackStates.initialAckState.nextPacketNum,
442 currentNextInitialPacketNum); // no change
443 EXPECT_EQ(
444 conn->ackStates.handshakeAckState.nextPacketNum,
445 currentNextHandshakePacketNum); // no change
446 EXPECT_GT(
447 conn->ackStates.appDataAckState.nextPacketNum,
448 currentNextAppDataPacketNum); // increased
449 EXPECT_TRUE(conn->outstandings.packets.back().isAppLimited);
450
451 // offsets should be 13 (len + EOF) and 24 (bytes without EOF)
452 EXPECT_EQ(stream1->currentWriteOffset, 13); // len (12) + EOF (1)
453 EXPECT_EQ(stream2->currentWriteOffset, 13); // len (12) + EOF (1)
454 EXPECT_EQ(conn->flowControlState.sumCurWriteOffset, 24); // sum(len)
455
456 // verify retransmission buffer and mark stream bytes in packet1 lost
457 {
458 ASSERT_EQ(stream1->retransmissionBuffer.size(), 1);
459 auto& rt = *stream1->retransmissionBuffer.at(0);
460 EXPECT_EQ(rt.offset, 0);
461 EXPECT_TRUE(eq(*buf, *rt.data.front()));
462 EXPECT_TRUE(rt.eof);
463 stream1->lossBuffer.push_back(std::move(rt));
464 }
465 {
466 ASSERT_EQ(stream2->retransmissionBuffer.size(), 1);
467 auto& rt = *stream2->retransmissionBuffer.at(0);
468 EXPECT_EQ(rt.offset, 0);
469 EXPECT_TRUE(eq(*buf, *rt.data.front()));
470 EXPECT_TRUE(rt.eof);
471 stream2->lossBuffer.push_back(std::move(rt));
472 }
473 stream1->retransmissionBuffer.clear();
474 stream2->retransmissionBuffer.clear();
475 conn->streamManager->addLoss(stream1->id);
476 conn->streamManager->addLoss(stream2->id);
477
478 // retransmit the lost frames in AppData packet2
479 auto packet2 = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
480 packet2.packet.frames.push_back(writeStreamFrame1);
481 packet2.packet.frames.push_back(writeStreamFrame2);
482
483 // mimic send, call updateConnection
484 EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(1);
485 currentNextInitialPacketNum = conn->ackStates.initialAckState.nextPacketNum;
486 currentNextHandshakePacketNum =
487 conn->ackStates.handshakeAckState.nextPacketNum;
488 currentNextAppDataPacketNum = conn->ackStates.appDataAckState.nextPacketNum;
489 EXPECT_CALL(*rawCongestionController, isAppLimited())
490 .Times(1)
491 .WillOnce(Return(false));
492 updateConnection(
493 *conn,
494 folly::none,
495 packet2.packet,
496 TimePoint(),
497 getEncodedSize(packet2),
498 getEncodedBodySize(packet2),
499 false /* isDSRPacket */);
500 EXPECT_EQ(
501 conn->ackStates.initialAckState.nextPacketNum,
502 currentNextInitialPacketNum); // no change
503 EXPECT_EQ(
504 conn->ackStates.handshakeAckState.nextPacketNum,
505 currentNextHandshakePacketNum); // no change
506 EXPECT_GT(
507 conn->ackStates.appDataAckState.nextPacketNum,
508 currentNextAppDataPacketNum); // increased
509 EXPECT_FALSE(conn->outstandings.packets.back().isAppLimited);
510
511 // since retransmission with no new data, no change in offsets
512 EXPECT_EQ(stream1->currentWriteOffset, 13); // len (12) + EOF (1)
513 EXPECT_EQ(stream2->currentWriteOffset, 13); // len (12) + EOF (1)
514 EXPECT_EQ(conn->flowControlState.sumCurWriteOffset, 24); // sum(len)
515
516 // check loss state
517 CHECK_EQ(
518 conn->lossState.totalBytesSent,
519 getEncodedSize(packet1) + getEncodedSize(packet2));
520 CHECK_EQ(
521 conn->lossState.totalBodyBytesSent,
522 getEncodedBodySize(packet1) + getEncodedBodySize(packet2));
523 CHECK_EQ(conn->lossState.totalPacketsSent, 2);
524
525 // totalStreamBytesSent:
526 // the first packet contained 12 + 12
527 // the second packet contained 12 + 12
528 // total = 48
529 EXPECT_EQ(conn->lossState.totalStreamBytesSent, 48); // sum(len)
530
531 // totalNewStreamBytesSent: just sum(len)
532 EXPECT_EQ(conn->lossState.totalNewStreamBytesSent, 24);
533 EXPECT_EQ(
534 conn->lossState.totalNewStreamBytesSent,
535 conn->flowControlState.sumCurWriteOffset);
536 }
537
TEST_F(QuicTransportFunctionsTest,TestUpdateConnectionPacketRetransWithNewData)538 TEST_F(
539 QuicTransportFunctionsTest,
540 TestUpdateConnectionPacketRetransWithNewData) {
541 const IOBufEqualTo eq;
542
543 auto conn = createConn();
544 auto mockCongestionController =
545 std::make_unique<NiceMock<MockCongestionController>>();
546 auto rawCongestionController = mockCongestionController.get();
547 conn->congestionController = std::move(mockCongestionController);
548 conn->qLogger = std::make_shared<quic::FileQLogger>(VantagePoint::Client);
549
550 // three streams, all writing "hey whats up"
551 //
552 // streams1 and 2 EOF after writing buffer, stream3 does not
553 //
554 // frames:
555 // stream1,frame1 contains the entire string with EOM
556 // stream2,frame1 contains "hey w", and thus no EOM
557 // stream3,frame1 contains the entire string, but no EOM given no EOF yet
558 //
559 // we'll write additional data to stream3 later
560 auto stream1Id =
561 conn->streamManager->createNextBidirectionalStream().value()->id;
562 auto stream2Id =
563 conn->streamManager->createNextBidirectionalStream().value()->id;
564 auto stream3Id =
565 conn->streamManager->createNextBidirectionalStream().value()->id;
566 auto stream1 = conn->streamManager->findStream(stream1Id);
567 auto stream2 = conn->streamManager->findStream(stream2Id);
568 auto stream3 = conn->streamManager->findStream(stream3Id);
569 auto buf = IOBuf::copyBuffer("hey whats up");
570 writeDataToQuicStream(*stream1, buf->clone(), true /* eof */);
571 writeDataToQuicStream(*stream2, buf->clone(), true /* eof */);
572 writeDataToQuicStream(*stream3, buf->clone(), false /* eof */);
573 WriteStreamFrame writeStreamFrame1(stream1->id, 0, 12, true /* eom */);
574 WriteStreamFrame writeStreamFrame2(stream2->id, 0, 5, false /* eom */);
575 WriteStreamFrame writeStreamFrame3(stream3->id, 0, 12, false /* eom */);
576 EXPECT_EQ(stream1->currentWriteOffset, 0);
577 EXPECT_EQ(stream2->currentWriteOffset, 0);
578 EXPECT_EQ(stream3->currentWriteOffset, 0);
579 EXPECT_EQ(conn->flowControlState.sumCurWriteOffset, 0);
580
581 // add all stream frames into AppData packet1
582 auto packet1 = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
583 packet1.packet.frames.push_back(writeStreamFrame1);
584 packet1.packet.frames.push_back(writeStreamFrame2);
585 packet1.packet.frames.push_back(writeStreamFrame3);
586
587 // mimic send, call updateConnection
588 auto currentNextInitialPacketNum =
589 conn->ackStates.initialAckState.nextPacketNum;
590 auto currentNextHandshakePacketNum =
591 conn->ackStates.handshakeAckState.nextPacketNum;
592 auto currentNextAppDataPacketNum =
593 conn->ackStates.appDataAckState.nextPacketNum;
594 EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(1);
595 EXPECT_CALL(*rawCongestionController, isAppLimited())
596 .Times(1)
597 .WillOnce(Return(true));
598 updateConnection(
599 *conn,
600 folly::none,
601 packet1.packet,
602 TimePoint{},
603 getEncodedSize(packet1),
604 getEncodedBodySize(packet1),
605 false /* isDSRPacket */);
606
607 // appData packet number should increase
608 EXPECT_EQ(
609 conn->ackStates.initialAckState.nextPacketNum,
610 currentNextInitialPacketNum); // no change
611 EXPECT_EQ(
612 conn->ackStates.handshakeAckState.nextPacketNum,
613 currentNextHandshakePacketNum); // no change
614 EXPECT_GT(
615 conn->ackStates.appDataAckState.nextPacketNum,
616 currentNextAppDataPacketNum); // increased
617 EXPECT_TRUE(conn->outstandings.packets.back().isAppLimited);
618
619 // check offsets
620 EXPECT_EQ(stream1->currentWriteOffset, 13); // len (12) + EOF (1)
621 EXPECT_EQ(stream2->currentWriteOffset, 5); // len (5)
622 EXPECT_EQ(stream3->currentWriteOffset, 12); // len (12)
623 EXPECT_EQ(conn->flowControlState.sumCurWriteOffset, 29); // sum(len)
624
625 // verify retransmission buffer and mark stream bytes in packet1 lost
626 {
627 ASSERT_EQ(stream1->retransmissionBuffer.size(), 1);
628 auto& rt = *stream1->retransmissionBuffer.at(0);
629 EXPECT_EQ(rt.offset, 0);
630 EXPECT_TRUE(eq(*buf, *rt.data.front()));
631 EXPECT_TRUE(rt.eof);
632 stream1->lossBuffer.push_back(std::move(rt));
633 }
634 {
635 ASSERT_EQ(stream2->retransmissionBuffer.size(), 1);
636 auto& rt = *stream2->retransmissionBuffer.at(0);
637 EXPECT_EQ(rt.offset, 0);
638 EXPECT_TRUE(eq(*IOBuf::copyBuffer("hey w"), *rt.data.front()));
639 EXPECT_FALSE(rt.eof);
640 stream2->lossBuffer.push_back(std::move(rt));
641 }
642 {
643 ASSERT_EQ(stream3->retransmissionBuffer.size(), 1);
644 auto& rt = *stream3->retransmissionBuffer.at(0);
645 EXPECT_EQ(rt.offset, 0);
646 EXPECT_TRUE(eq(*buf, *rt.data.front()));
647 EXPECT_FALSE(rt.eof);
648 stream3->lossBuffer.push_back(std::move(rt));
649 }
650 stream1->retransmissionBuffer.clear();
651 stream2->retransmissionBuffer.clear();
652 stream3->retransmissionBuffer.clear();
653 conn->streamManager->addLoss(stream1->id);
654 conn->streamManager->addLoss(stream2->id);
655 conn->streamManager->addLoss(stream3->id);
656
657 // add some additional data
658 // write a "?" to stream3 and set eof
659 auto buf2 = IOBuf::copyBuffer("?");
660 writeDataToQuicStream(*stream3, buf->clone(), true /* eof */);
661
662 // packet2 contains orignally transmitted frames + new data frames
663 auto packet2 = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
664 packet2.packet.frames.push_back(writeStreamFrame1);
665 packet2.packet.frames.push_back(writeStreamFrame2);
666 packet2.packet.frames.push_back(writeStreamFrame3);
667 packet2.packet.frames.push_back(WriteStreamFrame(
668 stream2->id, 5 /* offset */, 7 /* len */, true /* eom */));
669 packet2.packet.frames.push_back(WriteStreamFrame(
670 stream3->id, 12 /* offset */, 1 /* len */, true /* eom */));
671
672 // mimic send, call updateConnection
673 EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(1);
674 currentNextInitialPacketNum = conn->ackStates.initialAckState.nextPacketNum;
675 currentNextHandshakePacketNum =
676 conn->ackStates.handshakeAckState.nextPacketNum;
677 currentNextAppDataPacketNum = conn->ackStates.appDataAckState.nextPacketNum;
678 EXPECT_CALL(*rawCongestionController, isAppLimited())
679 .Times(1)
680 .WillOnce(Return(false));
681 updateConnection(
682 *conn,
683 folly::none,
684 packet2.packet,
685 TimePoint(),
686 getEncodedSize(packet2),
687 getEncodedBodySize(packet2),
688 false /* isDSRPacket */);
689 EXPECT_EQ(
690 conn->ackStates.initialAckState.nextPacketNum,
691 currentNextInitialPacketNum); // no change
692 EXPECT_EQ(
693 conn->ackStates.handshakeAckState.nextPacketNum,
694 currentNextHandshakePacketNum); // no change
695 EXPECT_GT(
696 conn->ackStates.appDataAckState.nextPacketNum,
697 currentNextAppDataPacketNum); // increased
698 EXPECT_FALSE(conn->outstandings.packets.back().isAppLimited);
699
700 // check offsets
701 EXPECT_EQ(stream1->currentWriteOffset, 13); // len (12) + EOF (1)
702 EXPECT_EQ(stream2->currentWriteOffset, 13); // len (12) + EOF (1)
703 EXPECT_EQ(stream3->currentWriteOffset, 14); // len (13) + EOF (1)
704 EXPECT_EQ(conn->flowControlState.sumCurWriteOffset, 37); // sum(len)
705
706 // check loss state
707 CHECK_EQ(
708 conn->lossState.totalBytesSent,
709 getEncodedSize(packet1) + getEncodedSize(packet2));
710 CHECK_EQ(
711 conn->lossState.totalBodyBytesSent,
712 getEncodedBodySize(packet1) + getEncodedBodySize(packet2));
713 CHECK_EQ(conn->lossState.totalPacketsSent, 2);
714
715 // totalStreamBytesSent:
716 // the first packet contained 12 + 5 + 12 stream bytes
717 // the second packet contained 12 + 12 + 13 stream bytes
718 // total = 66
719 EXPECT_EQ(conn->lossState.totalStreamBytesSent, 66); // sum(len)
720
721 // totalNewStreamBytesSent: just sum(len)
722 EXPECT_EQ(conn->lossState.totalNewStreamBytesSent, 37);
723 EXPECT_EQ(
724 conn->lossState.totalNewStreamBytesSent,
725 conn->flowControlState.sumCurWriteOffset);
726 }
727
TEST_F(QuicTransportFunctionsTest,TestUpdateConnectionD6DNotConsumeSendPing)728 TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionD6DNotConsumeSendPing) {
729 auto conn = createConn();
730 conn->pendingEvents.sendPing = true; // Simulate application sendPing()
731 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
732 packet.packet.frames.push_back(PingFrame());
733 auto packetNum = packet.packet.header.getPacketSequenceNum();
734 conn->d6d.lastProbe = D6DProbePacket(packetNum, 50);
735 updateConnection(
736 *conn,
737 folly::none,
738 packet.packet,
739 Clock::now(),
740 50,
741 0,
742 false /* isDSRPacket */);
743 EXPECT_EQ(1, conn->outstandings.packets.size());
744 EXPECT_TRUE(conn->outstandings.packets.front().metadata.isD6DProbe);
745 EXPECT_EQ(1, conn->d6d.outstandingProbes);
746 // sendPing should still be active since d6d probe should be "hidden" from
747 // application
748 EXPECT_TRUE(conn->pendingEvents.sendPing);
749 }
750
TEST_F(QuicTransportFunctionsTest,TestUpdateConnectionD6DNeedsAppDataPNSpace)751 TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionD6DNeedsAppDataPNSpace) {
752 auto conn = createConn();
753 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
754 packet.packet.frames.push_back(PingFrame());
755 auto packetNum = packet.packet.header.getPacketSequenceNum();
756 conn->d6d.lastProbe = D6DProbePacket(packetNum, 50);
757 updateConnection(
758 *conn,
759 folly::none,
760 packet.packet,
761 Clock::now(),
762 50,
763 0,
764 false /* isDSRPacket */);
765 EXPECT_EQ(1, conn->outstandings.packets.size());
766 EXPECT_FALSE(conn->outstandings.packets.front().metadata.isD6DProbe);
767 EXPECT_EQ(0, conn->d6d.outstandingProbes);
768 }
769
TEST_F(QuicTransportFunctionsTest,TestUpdateConnectionPacketSorting)770 TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionPacketSorting) {
771 auto conn = createConn();
772 conn->qLogger = std::make_shared<quic::FileQLogger>(VantagePoint::Client);
773 conn->ackStates.initialAckState.nextPacketNum = 0;
774 conn->ackStates.handshakeAckState.nextPacketNum = 1;
775 conn->ackStates.appDataAckState.nextPacketNum = 2;
776 auto initialPacket = buildEmptyPacket(*conn, PacketNumberSpace::Initial);
777 auto handshakePacket = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
778 auto appDataPacket = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
779
780 auto stream = conn->streamManager->createNextBidirectionalStream().value();
781 writeDataToQuicStream(
782 *stream,
783 folly::IOBuf::copyBuffer("The sun is cold and the rain is hard."),
784 true);
785 WriteStreamFrame writeStreamFrame(stream->id, 0, 5, false);
786 initialPacket.packet.frames.push_back(writeStreamFrame);
787 handshakePacket.packet.frames.push_back(writeStreamFrame);
788 appDataPacket.packet.frames.push_back(writeStreamFrame);
789
790 updateConnection(
791 *conn,
792 folly::none,
793 handshakePacket.packet,
794 TimePoint{},
795 getEncodedSize(handshakePacket),
796 getEncodedBodySize(handshakePacket),
797 false /* isDSRPacket */);
798 updateConnection(
799 *conn,
800 folly::none,
801 initialPacket.packet,
802 TimePoint{},
803 getEncodedSize(initialPacket),
804 getEncodedBodySize(initialPacket),
805 false /* isDSRPacket */);
806 updateConnection(
807 *conn,
808 folly::none,
809 appDataPacket.packet,
810 TimePoint{},
811 getEncodedSize(appDataPacket),
812 getEncodedBodySize(appDataPacket),
813 false /* isDSRPacket */);
814 // verify qLogger added correct logs
815 std::shared_ptr<quic::FileQLogger> qLogger =
816 std::dynamic_pointer_cast<quic::FileQLogger>(conn->qLogger);
817 std::vector<int> indices =
818 getQLogEventIndices(QLogEventType::PacketSent, qLogger);
819 EXPECT_EQ(indices.size(), 3);
820
821 auto l1 = std::move(qLogger->logs[indices[0]]);
822 auto l2 = std::move(qLogger->logs[indices[1]]);
823 auto l3 = std::move(qLogger->logs[indices[2]]);
824 auto event1 = dynamic_cast<QLogPacketEvent*>(l1.get());
825 auto event2 = dynamic_cast<QLogPacketEvent*>(l2.get());
826 auto event3 = dynamic_cast<QLogPacketEvent*>(l3.get());
827
828 EXPECT_EQ(event1->packetType, toQlogString(LongHeader::Types::Handshake));
829 EXPECT_EQ(event2->packetType, toQlogString(LongHeader::Types::Initial));
830 EXPECT_EQ(event3->packetType, toQlogString(LongHeader::Types::ZeroRtt));
831
832 EXPECT_EQ(3, conn->outstandings.packets.size());
833 auto& firstHeader = conn->outstandings.packets.front().packet.header;
834 auto firstPacketNum = firstHeader.getPacketSequenceNum();
835 EXPECT_EQ(0, firstPacketNum);
836 EXPECT_EQ(1, event1->packetNum);
837
838 EXPECT_EQ(PacketNumberSpace::Initial, firstHeader.getPacketNumberSpace());
839
840 auto& lastHeader = conn->outstandings.packets.back().packet.header;
841
842 auto lastPacketNum = lastHeader.getPacketSequenceNum();
843
844 EXPECT_EQ(2, lastPacketNum);
845 EXPECT_EQ(2, event3->packetNum);
846
847 EXPECT_EQ(PacketNumberSpace::AppData, lastHeader.getPacketNumberSpace());
848 }
849
TEST_F(QuicTransportFunctionsTest,TestUpdateConnectionFinOnly)850 TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionFinOnly) {
851 auto conn = createConn();
852 conn->qLogger = std::make_shared<quic::FileQLogger>(VantagePoint::Client);
853 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
854 auto stream1 = conn->streamManager->createNextBidirectionalStream().value();
855
856 writeDataToQuicStream(*stream1, nullptr, true);
857 packet.packet.frames.push_back(WriteStreamFrame(stream1->id, 0, 0, true));
858 updateConnection(
859 *conn,
860 folly::none,
861 packet.packet,
862 TimePoint(),
863 getEncodedSize(packet),
864 getEncodedBodySize(packet),
865 false /* isDSRPacket */);
866
867 // verify QLogger contains correct packet information
868 std::shared_ptr<quic::FileQLogger> qLogger =
869 std::dynamic_pointer_cast<quic::FileQLogger>(conn->qLogger);
870 std::vector<int> indices =
871 getQLogEventIndices(QLogEventType::PacketSent, qLogger);
872 EXPECT_EQ(indices.size(), 1);
873 auto tmp = std::move(qLogger->logs[indices[0]]);
874
875 auto event = dynamic_cast<QLogPacketEvent*>(tmp.get());
876 EXPECT_EQ(event->packetType, toQlogString(LongHeader::Types::Handshake));
877 EXPECT_EQ(event->packetSize, getEncodedSize(packet));
878 EXPECT_EQ(event->eventType, QLogEventType::PacketSent);
879
880 // verify QLogger contains correct frame information
881 EXPECT_EQ(event->frames.size(), 1);
882 auto frame = static_cast<StreamFrameLog*>(event->frames[0].get());
883 EXPECT_EQ(frame->streamId, stream1->id);
884 EXPECT_EQ(frame->offset, 0);
885 EXPECT_EQ(frame->len, 0);
886 EXPECT_TRUE(frame->fin);
887
888 EXPECT_EQ(stream1->retransmissionBuffer.size(), 1);
889 auto& rt1 = *stream1->retransmissionBuffer.at(0);
890
891 EXPECT_EQ(stream1->currentWriteOffset, 1);
892 EXPECT_EQ(rt1.offset, 0);
893 EXPECT_EQ(rt1.data.front()->computeChainDataLength(), 0);
894 EXPECT_TRUE(rt1.eof);
895 }
896
TEST_F(QuicTransportFunctionsTest,TestUpdateConnectionAllBytesExceptFin)897 TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionAllBytesExceptFin) {
898 auto conn = createConn();
899 conn->qLogger = std::make_shared<quic::FileQLogger>(VantagePoint::Client);
900 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
901
902 auto stream1 = conn->streamManager->createNextUnidirectionalStream().value();
903
904 auto buf = IOBuf::copyBuffer("Bluberries are purple");
905 writeDataToQuicStream(*stream1, buf->clone(), true);
906
907 packet.packet.frames.push_back(
908 WriteStreamFrame(stream1->id, 0, buf->computeChainDataLength(), false));
909 updateConnection(
910 *conn,
911 folly::none,
912 packet.packet,
913 TimePoint(),
914 getEncodedSize(packet),
915 getEncodedBodySize(packet),
916 false /* isDSRPacket */);
917
918 // verify QLogger contains correct packet information
919 std::shared_ptr<quic::FileQLogger> qLogger =
920 std::dynamic_pointer_cast<quic::FileQLogger>(conn->qLogger);
921 std::vector<int> indices =
922 getQLogEventIndices(QLogEventType::PacketSent, qLogger);
923 EXPECT_EQ(indices.size(), 1);
924 auto tmp = std::move(qLogger->logs[indices[0]]);
925 auto event = dynamic_cast<QLogPacketEvent*>(tmp.get());
926
927 EXPECT_EQ(event->packetType, toQlogString(LongHeader::Types::Handshake));
928 EXPECT_EQ(event->packetSize, getEncodedSize(packet));
929 EXPECT_EQ(event->eventType, QLogEventType::PacketSent);
930
931 // verify QLogger contains correct frame information
932 EXPECT_EQ(event->frames.size(), 1);
933 auto frame = static_cast<StreamFrameLog*>(event->frames[0].get());
934 EXPECT_EQ(frame->streamId, stream1->id);
935 EXPECT_EQ(frame->offset, 0);
936 EXPECT_EQ(frame->len, buf->computeChainDataLength());
937 EXPECT_FALSE(frame->fin);
938
939 EXPECT_EQ(stream1->currentWriteOffset, buf->computeChainDataLength());
940
941 EXPECT_EQ(stream1->retransmissionBuffer.size(), 1);
942 auto& rt1 = *stream1->retransmissionBuffer.at(0);
943 EXPECT_EQ(rt1.offset, 0);
944 EXPECT_EQ(
945 rt1.data.front()->computeChainDataLength(),
946 buf->computeChainDataLength());
947 EXPECT_FALSE(rt1.eof);
948 }
949
TEST_F(QuicTransportFunctionsTest,TestUpdateConnectionEmptyAckWriteResult)950 TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionEmptyAckWriteResult) {
951 auto conn = createConn();
952 conn->qLogger = std::make_shared<quic::FileQLogger>(VantagePoint::Client);
953 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
954 // None of the largestAckScheduled should be changed. But since
955 // buildEmptyPacket() builds a Handshake packet, we use handshakeAckState to
956 // verify.
957 auto currentPendingLargestAckScheduled =
958 conn->ackStates.handshakeAckState.largestAckScheduled;
959 updateConnection(
960 *conn,
961 folly::none,
962 packet.packet,
963 TimePoint(),
964 getEncodedSize(packet),
965 getEncodedBodySize(packet),
966 false /* isDSRPacket */);
967
968 // verify QLogger contains correct packet information
969 std::shared_ptr<quic::FileQLogger> qLogger =
970 std::dynamic_pointer_cast<quic::FileQLogger>(conn->qLogger);
971 std::vector<int> indices =
972 getQLogEventIndices(QLogEventType::PacketSent, qLogger);
973 EXPECT_EQ(indices.size(), 1);
974 auto tmp = std::move(qLogger->logs[indices[0]]);
975 auto event = dynamic_cast<QLogPacketEvent*>(tmp.get());
976 EXPECT_EQ(event->packetType, toQlogString(LongHeader::Types::Handshake));
977 EXPECT_EQ(event->packetSize, getEncodedSize(packet));
978 EXPECT_EQ(event->eventType, QLogEventType::PacketSent);
979
980 EXPECT_EQ(
981 currentPendingLargestAckScheduled,
982 conn->ackStates.handshakeAckState.largestAckScheduled);
983 }
984
TEST_F(QuicTransportFunctionsTest,TestUpdateConnectionPureAckCounter)985 TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionPureAckCounter) {
986 auto conn = createConn();
987 conn->qLogger = std::make_shared<quic::FileQLogger>(VantagePoint::Client);
988 auto stream = conn->streamManager->createNextBidirectionalStream().value();
989 writeDataToQuicStream(*stream, nullptr, true);
990 EXPECT_EQ(0, conn->outstandings.packetCount[PacketNumberSpace::Handshake]);
991
992 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
993 auto packetEncodedSize =
994 packet.header ? packet.header->computeChainDataLength() : 0;
995 packetEncodedSize += packet.body ? packet.body->computeChainDataLength() : 0;
996
997 WriteAckFrame ackFrame;
998 ackFrame.ackBlocks.emplace_back(0, 100);
999 packet.packet.frames.push_back(std::move(ackFrame));
1000 updateConnection(
1001 *conn,
1002 folly::none,
1003 packet.packet,
1004 TimePoint(),
1005 getEncodedSize(packet),
1006 getEncodedBodySize(packet),
1007 false /* isDSRPacket */);
1008
1009 auto nonHandshake = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
1010 packetEncodedSize =
1011 nonHandshake.header ? nonHandshake.header->computeChainDataLength() : 0;
1012 packetEncodedSize +=
1013 nonHandshake.body ? nonHandshake.body->computeChainDataLength() : 0;
1014 auto stream1 = conn->streamManager->createNextBidirectionalStream().value();
1015 writeDataToQuicStream(*stream1, nullptr, true);
1016
1017 conn->pendingEvents.resets.emplace(
1018 1, RstStreamFrame(1, GenericApplicationErrorCode::UNKNOWN, 0));
1019 auto packet2 = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
1020 RstStreamFrame rstFrame(1, GenericApplicationErrorCode::UNKNOWN, 0);
1021 packet2.packet.frames.push_back(std::move(rstFrame));
1022
1023 updateConnection(
1024 *conn,
1025 folly::none,
1026 packet2.packet,
1027 TimePoint(),
1028 getEncodedSize(packet),
1029 getEncodedBodySize(packet),
1030 false /* isDSRPacket */);
1031
1032 // verify QLogger contains correct packet and frame information
1033 std::shared_ptr<quic::FileQLogger> qLogger =
1034 std::dynamic_pointer_cast<quic::FileQLogger>(conn->qLogger);
1035 std::vector<int> indices =
1036 getQLogEventIndices(QLogEventType::PacketSent, qLogger);
1037 EXPECT_EQ(indices.size(), 2);
1038 for (int i = 0; i < 2; ++i) {
1039 auto tmp = std::move(qLogger->logs[indices[i]]);
1040 auto event = dynamic_cast<QLogPacketEvent*>(tmp.get());
1041 EXPECT_EQ(event->packetType, toQlogString(LongHeader::Types::Handshake));
1042 EXPECT_EQ(event->packetSize, getEncodedSize(packet));
1043 EXPECT_EQ(event->frames.size(), 1);
1044 }
1045 }
1046
TEST_F(QuicTransportFunctionsTest,TestPaddingPureAckPacketIsStillPureAck)1047 TEST_F(QuicTransportFunctionsTest, TestPaddingPureAckPacketIsStillPureAck) {
1048 auto conn = createConn();
1049 conn->qLogger = std::make_shared<quic::FileQLogger>(VantagePoint::Client);
1050 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
1051 auto packetEncodedSize =
1052 packet.header ? packet.header->computeChainDataLength() : 0;
1053 packetEncodedSize += packet.body ? packet.body->computeChainDataLength() : 0;
1054
1055 WriteAckFrame ackFrame;
1056 ackFrame.ackBlocks.emplace_back(0, 100);
1057 packet.packet.frames.push_back(std::move(ackFrame));
1058 packet.packet.frames.push_back(PaddingFrame());
1059 updateConnection(
1060 *conn,
1061 folly::none,
1062 packet.packet,
1063 TimePoint(),
1064 getEncodedSize(packet),
1065 getEncodedBodySize(packet),
1066 false /* isDSRPacket */);
1067
1068 // verify QLogger contains correct packet and frames information
1069 std::shared_ptr<quic::FileQLogger> qLogger =
1070 std::dynamic_pointer_cast<quic::FileQLogger>(conn->qLogger);
1071 std::vector<int> indices =
1072 getQLogEventIndices(QLogEventType::PacketSent, qLogger);
1073 EXPECT_EQ(indices.size(), 1);
1074 auto tmp = std::move(qLogger->logs[indices[0]]);
1075
1076 auto event = dynamic_cast<QLogPacketEvent*>(tmp.get());
1077 EXPECT_EQ(event->packetType, toQlogString(LongHeader::Types::Handshake));
1078 EXPECT_EQ(event->packetSize, getEncodedSize(packet));
1079 EXPECT_EQ(event->eventType, QLogEventType::PacketSent);
1080 EXPECT_EQ(event->frames.size(), 2);
1081 }
1082
TEST_F(QuicTransportFunctionsTest,TestImplicitAck)1083 TEST_F(QuicTransportFunctionsTest, TestImplicitAck) {
1084 auto conn = createConn();
1085 auto data = IOBuf::copyBuffer("totally real crypto data");
1086 data->coalesce();
1087
1088 auto initialStream =
1089 getCryptoStream(*conn->cryptoState, EncryptionLevel::Initial);
1090 ASSERT_TRUE(initialStream->writeBuffer.empty());
1091 ASSERT_TRUE(initialStream->retransmissionBuffer.empty());
1092 ASSERT_TRUE(initialStream->lossBuffer.empty());
1093 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Initial);
1094 packet.packet.frames.push_back(WriteCryptoFrame(0, data->length()));
1095 initialStream->writeBuffer.append(data->clone());
1096 updateConnection(
1097 *conn,
1098 folly::none,
1099 packet.packet,
1100 TimePoint(),
1101 getEncodedSize(packet),
1102 getEncodedBodySize(packet),
1103 false /* isDSRPacket */);
1104 EXPECT_EQ(1, conn->outstandings.packetCount[PacketNumberSpace::Initial]);
1105 EXPECT_EQ(0, conn->outstandings.packetCount[PacketNumberSpace::Handshake]);
1106 EXPECT_EQ(1, conn->outstandings.packets.size());
1107 EXPECT_EQ(1, initialStream->retransmissionBuffer.size());
1108
1109 packet = buildEmptyPacket(*conn, PacketNumberSpace::Initial);
1110 packet.packet.frames.push_back(
1111 WriteCryptoFrame(data->length(), data->length()));
1112 packet.packet.frames.push_back(
1113 WriteCryptoFrame(data->length() * 2, data->length()));
1114 initialStream->writeBuffer.append(data->clone());
1115 initialStream->writeBuffer.append(data->clone());
1116 updateConnection(
1117 *conn,
1118 folly::none,
1119 packet.packet,
1120 TimePoint(),
1121 getEncodedSize(packet),
1122 getEncodedBodySize(packet),
1123 false /* isDSRPacket */);
1124 EXPECT_EQ(2, conn->outstandings.packetCount[PacketNumberSpace::Initial]);
1125 EXPECT_EQ(0, conn->outstandings.packetCount[PacketNumberSpace::Handshake]);
1126 EXPECT_EQ(2, conn->outstandings.packets.size());
1127 EXPECT_EQ(3, initialStream->retransmissionBuffer.size());
1128 EXPECT_TRUE(initialStream->writeBuffer.empty());
1129 EXPECT_TRUE(initialStream->lossBuffer.empty());
1130
1131 // Fake loss.
1132 Buf firstBuf =
1133 initialStream->retransmissionBuffer.find(0)->second->data.move();
1134 initialStream->retransmissionBuffer.erase(0);
1135 initialStream->lossBuffer.emplace_back(std::move(firstBuf), 0, false);
1136 conn->outstandings.packets.pop_front();
1137 conn->outstandings.packetCount[PacketNumberSpace::Initial]--;
1138
1139 auto handshakeStream =
1140 getCryptoStream(*conn->cryptoState, EncryptionLevel::Handshake);
1141 ASSERT_TRUE(handshakeStream->writeBuffer.empty());
1142 ASSERT_TRUE(handshakeStream->retransmissionBuffer.empty());
1143 ASSERT_TRUE(handshakeStream->lossBuffer.empty());
1144 packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
1145 packet.packet.frames.push_back(WriteCryptoFrame(0, data->length()));
1146 handshakeStream->writeBuffer.append(data->clone());
1147 updateConnection(
1148 *conn,
1149 folly::none,
1150 packet.packet,
1151 TimePoint(),
1152 getEncodedSize(packet),
1153 getEncodedBodySize(packet),
1154 false /* isDSRPacket */);
1155 EXPECT_EQ(1, conn->outstandings.packetCount[PacketNumberSpace::Initial]);
1156 EXPECT_EQ(1, conn->outstandings.packetCount[PacketNumberSpace::Handshake]);
1157 EXPECT_EQ(2, conn->outstandings.packets.size());
1158 EXPECT_EQ(1, handshakeStream->retransmissionBuffer.size());
1159
1160 packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
1161 packet.packet.frames.push_back(
1162 WriteCryptoFrame(data->length(), data->length()));
1163 handshakeStream->writeBuffer.append(data->clone());
1164 updateConnection(
1165 *conn,
1166 folly::none,
1167 packet.packet,
1168 TimePoint(),
1169 getEncodedSize(packet),
1170 getEncodedBodySize(packet),
1171 false /* isDSRPacket */);
1172 EXPECT_EQ(1, conn->outstandings.packetCount[PacketNumberSpace::Initial]);
1173 EXPECT_EQ(2, conn->outstandings.packetCount[PacketNumberSpace::Handshake]);
1174 EXPECT_EQ(3, conn->outstandings.packets.size());
1175 EXPECT_EQ(2, handshakeStream->retransmissionBuffer.size());
1176 EXPECT_TRUE(handshakeStream->writeBuffer.empty());
1177 EXPECT_TRUE(handshakeStream->lossBuffer.empty());
1178
1179 // Fake loss.
1180 firstBuf = handshakeStream->retransmissionBuffer.find(0)->second->data.move();
1181 handshakeStream->retransmissionBuffer.erase(0);
1182 handshakeStream->lossBuffer.emplace_back(std::move(firstBuf), 0, false);
1183 auto& op = conn->outstandings.packets.front();
1184 ASSERT_EQ(
1185 op.packet.header.getPacketNumberSpace(), PacketNumberSpace::Handshake);
1186 auto frame = op.packet.frames[0].asWriteCryptoFrame();
1187 EXPECT_EQ(frame->offset, 0);
1188 conn->outstandings.packets.pop_front();
1189 conn->outstandings.packetCount[PacketNumberSpace::Handshake]--;
1190
1191 implicitAckCryptoStream(*conn, EncryptionLevel::Initial);
1192 EXPECT_EQ(0, conn->outstandings.packetCount[PacketNumberSpace::Initial]);
1193 EXPECT_EQ(1, conn->outstandings.packetCount[PacketNumberSpace::Handshake]);
1194 EXPECT_EQ(1, conn->outstandings.packets.size());
1195 EXPECT_TRUE(initialStream->retransmissionBuffer.empty());
1196 EXPECT_TRUE(initialStream->writeBuffer.empty());
1197 EXPECT_TRUE(initialStream->lossBuffer.empty());
1198
1199 implicitAckCryptoStream(*conn, EncryptionLevel::Handshake);
1200 EXPECT_EQ(0, conn->outstandings.packetCount[PacketNumberSpace::Initial]);
1201 EXPECT_EQ(0, conn->outstandings.packetCount[PacketNumberSpace::Handshake]);
1202 EXPECT_TRUE(conn->outstandings.packets.empty());
1203 EXPECT_TRUE(handshakeStream->retransmissionBuffer.empty());
1204 EXPECT_TRUE(handshakeStream->writeBuffer.empty());
1205 EXPECT_TRUE(handshakeStream->lossBuffer.empty());
1206 }
1207
TEST_F(QuicTransportFunctionsTest,TestUpdateConnectionHandshakeCounter)1208 TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionHandshakeCounter) {
1209 auto conn = createConn();
1210 conn->qLogger = std::make_shared<quic::FileQLogger>(VantagePoint::Client);
1211 auto stream = conn->streamManager->createNextBidirectionalStream().value();
1212 writeDataToQuicStream(*stream, nullptr, true);
1213 EXPECT_EQ(0, conn->outstandings.packetCount[PacketNumberSpace::Handshake]);
1214
1215 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
1216 auto packetEncodedSize =
1217 packet.header ? packet.header->computeChainDataLength() : 0;
1218 packetEncodedSize += packet.body ? packet.body->computeChainDataLength() : 0;
1219
1220 packet.packet.frames.push_back(WriteCryptoFrame(0, 0));
1221 updateConnection(
1222 *conn,
1223 folly::none,
1224 packet.packet,
1225 TimePoint(),
1226 getEncodedSize(packet),
1227 getEncodedBodySize(packet),
1228 false /* isDSRPacket */);
1229 EXPECT_EQ(1, conn->outstandings.packetCount[PacketNumberSpace::Handshake]);
1230
1231 auto nonHandshake = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
1232 packetEncodedSize =
1233 nonHandshake.header ? nonHandshake.header->computeChainDataLength() : 0;
1234 packetEncodedSize +=
1235 nonHandshake.body ? nonHandshake.body->computeChainDataLength() : 0;
1236 auto stream1 = conn->streamManager->createNextBidirectionalStream().value();
1237 writeDataToQuicStream(*stream1, nullptr, true);
1238
1239 nonHandshake.packet.frames.push_back(
1240 WriteStreamFrame(stream1->id, 0, 0, true));
1241 updateConnection(
1242 *conn,
1243 folly::none,
1244 nonHandshake.packet,
1245 TimePoint(),
1246 getEncodedSize(packet),
1247 getEncodedBodySize(packet),
1248 false /* isDSRPacket */);
1249
1250 // verify QLogger contains correct packet information
1251 std::shared_ptr<quic::FileQLogger> qLogger =
1252 std::dynamic_pointer_cast<quic::FileQLogger>(conn->qLogger);
1253 std::vector<int> indices =
1254 getQLogEventIndices(QLogEventType::PacketSent, qLogger);
1255 EXPECT_EQ(indices.size(), 2);
1256 std::vector<std::string> packetTypes = {
1257 std::string(toQlogString(LongHeader::Types::Handshake)),
1258 std::string(toQlogString(LongHeader::Types::ZeroRtt))};
1259 for (int i = 0; i < 2; ++i) {
1260 auto tmp = std::move(qLogger->logs[indices[i]]);
1261 auto event = dynamic_cast<QLogPacketEvent*>(tmp.get());
1262 EXPECT_EQ(event->packetType, packetTypes[i]);
1263 EXPECT_EQ(event->packetSize, packetEncodedSize);
1264 EXPECT_EQ(event->eventType, QLogEventType::PacketSent);
1265
1266 if (i == 0) {
1267 EXPECT_EQ(event->frames.size(), 1);
1268 auto gotFrame = static_cast<CryptoFrameLog*>(event->frames[0].get());
1269 gotFrame->offset = 0;
1270 gotFrame->len = 0;
1271 } else if (i == 1) {
1272 EXPECT_EQ(event->frames.size(), 1);
1273 auto gotFrame = static_cast<StreamFrameLog*>(event->frames[0].get());
1274 EXPECT_EQ(gotFrame->streamId, stream1->id);
1275 EXPECT_EQ(gotFrame->offset, 0);
1276 EXPECT_EQ(gotFrame->len, 0);
1277 EXPECT_TRUE(gotFrame->fin);
1278 EXPECT_EQ(
1279 1, conn->outstandings.packetCount[PacketNumberSpace::Handshake]);
1280 }
1281 }
1282 }
1283
TEST_F(QuicTransportFunctionsTest,TestUpdateConnectionForOneRttCryptoData)1284 TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionForOneRttCryptoData) {
1285 auto conn = createConn();
1286 conn->qLogger = std::make_shared<quic::FileQLogger>(VantagePoint::Client);
1287 auto stream = conn->streamManager->createNextBidirectionalStream().value();
1288 writeDataToQuicStream(*stream, nullptr, true);
1289 EXPECT_EQ(0, conn->outstandings.packetCount[PacketNumberSpace::Handshake]);
1290
1291 // Packet with CryptoFrame in AppData pn space
1292 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData, true);
1293 auto packetEncodedSize =
1294 packet.header ? packet.header->computeChainDataLength() : 0;
1295 packetEncodedSize += packet.body ? packet.body->computeChainDataLength() : 0;
1296
1297 packet.packet.frames.push_back(WriteCryptoFrame(0, 0));
1298 updateConnection(
1299 *conn,
1300 folly::none,
1301 packet.packet,
1302 TimePoint(),
1303 getEncodedSize(packet),
1304 getEncodedBodySize(packet),
1305 false /* isDSRPacket */);
1306
1307 EXPECT_EQ(0, conn->outstandings.packetCount[PacketNumberSpace::Handshake]);
1308 EXPECT_EQ(1, conn->outstandings.packets.size());
1309
1310 auto nonHandshake = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
1311 packetEncodedSize =
1312 nonHandshake.header ? nonHandshake.header->computeChainDataLength() : 0;
1313 packetEncodedSize +=
1314 nonHandshake.body ? nonHandshake.body->computeChainDataLength() : 0;
1315 auto stream1 = conn->streamManager->createNextBidirectionalStream().value();
1316 writeDataToQuicStream(*stream1, nullptr, true);
1317
1318 nonHandshake.packet.frames.push_back(
1319 WriteStreamFrame(stream1->id, 0, 0, true));
1320 updateConnection(
1321 *conn,
1322 folly::none,
1323 nonHandshake.packet,
1324 TimePoint(),
1325 getEncodedSize(packet),
1326 getEncodedBodySize(packet),
1327 false /* isDSRPacket */);
1328
1329 // verify QLogger contains correct packet information
1330 std::shared_ptr<quic::FileQLogger> qLogger =
1331 std::dynamic_pointer_cast<quic::FileQLogger>(conn->qLogger);
1332 std::vector<int> indices =
1333 getQLogEventIndices(QLogEventType::PacketSent, qLogger);
1334 EXPECT_EQ(indices.size(), 2);
1335 std::vector<std::string> packetTypes = {
1336 kShortHeaderPacketType.str(),
1337 std::string(toQlogString(LongHeader::Types::ZeroRtt))};
1338 for (int i = 0; i < 2; ++i) {
1339 auto tmp = std::move(qLogger->logs[indices[i]]);
1340 auto event = dynamic_cast<QLogPacketEvent*>(tmp.get());
1341 EXPECT_EQ(event->packetType, packetTypes[i]);
1342 EXPECT_EQ(event->packetSize, getEncodedSize(packet));
1343 EXPECT_EQ(event->eventType, QLogEventType::PacketSent);
1344
1345 if (i == 0) {
1346 EXPECT_EQ(event->frames.size(), 1);
1347 auto frame = static_cast<CryptoFrameLog*>(event->frames[0].get());
1348 EXPECT_EQ(frame->offset, 0);
1349 EXPECT_EQ(frame->len, 0);
1350 } else if (i == 1) {
1351 EXPECT_EQ(event->frames.size(), 1);
1352 auto frame = static_cast<StreamFrameLog*>(event->frames[0].get());
1353 EXPECT_EQ(frame->streamId, stream1->id);
1354 EXPECT_EQ(frame->offset, 0);
1355 EXPECT_EQ(frame->len, 0);
1356 EXPECT_TRUE(frame->fin);
1357 }
1358 }
1359
1360 EXPECT_EQ(0, conn->outstandings.packetCount[PacketNumberSpace::Handshake]);
1361 EXPECT_EQ(2, conn->outstandings.packets.size());
1362 }
1363
TEST_F(QuicTransportFunctionsTest,TestUpdateConnectionWithPureAck)1364 TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionWithPureAck) {
1365 auto conn = createConn();
1366 conn->qLogger = std::make_shared<quic::FileQLogger>(VantagePoint::Client);
1367 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
1368 auto mockPacer = std::make_unique<NiceMock<MockPacer>>();
1369 auto rawPacer = mockPacer.get();
1370 conn->pacer = std::move(mockPacer);
1371 auto mockCongestionController =
1372 std::make_unique<NiceMock<MockCongestionController>>();
1373 auto rawController = mockCongestionController.get();
1374 conn->congestionController = std::move(mockCongestionController);
1375 EXPECT_EQ(0, conn->lossState.totalPacketsSent);
1376 EXPECT_EQ(0, conn->lossState.totalAckElicitingPacketsSent);
1377 EXPECT_EQ(0, conn->outstandings.packets.size());
1378 ASSERT_EQ(0, conn->lossState.totalBytesAcked);
1379 WriteAckFrame ackFrame;
1380 ackFrame.ackBlocks.emplace_back(0, 10);
1381 packet.packet.frames.push_back(std::move(ackFrame));
1382 EXPECT_CALL(*rawController, onPacketSent(_)).Times(0);
1383 EXPECT_CALL(*rawPacer, onPacketSent()).Times(0);
1384 updateConnection(
1385 *conn,
1386 folly::none,
1387 packet.packet,
1388 TimePoint(),
1389 getEncodedSize(packet),
1390 getEncodedBodySize(packet),
1391 false /* isDSRPacket */);
1392 EXPECT_EQ(1, conn->lossState.totalPacketsSent);
1393 EXPECT_EQ(0, conn->lossState.totalAckElicitingPacketsSent);
1394 EXPECT_EQ(0, conn->outstandings.packets.size());
1395 EXPECT_EQ(0, conn->lossState.totalBytesAcked);
1396 std::shared_ptr<quic::FileQLogger> qLogger =
1397 std::dynamic_pointer_cast<quic::FileQLogger>(conn->qLogger);
1398 // verify QLogger contains correct packet information
1399 std::vector<int> indices =
1400 getQLogEventIndices(QLogEventType::PacketSent, qLogger);
1401 EXPECT_EQ(indices.size(), 1);
1402 auto tmp = std::move(qLogger->logs[indices[0]]);
1403 auto event = dynamic_cast<QLogPacketEvent*>(tmp.get());
1404 EXPECT_EQ(event->packetType, toQlogString(LongHeader::Types::Handshake));
1405 EXPECT_EQ(event->packetSize, getEncodedSize(packet));
1406 EXPECT_EQ(event->eventType, QLogEventType::PacketSent);
1407 // verify QLogger contains correct frame information
1408 EXPECT_EQ(event->frames.size(), 1);
1409 auto frame = static_cast<WriteAckFrameLog*>(event->frames[0].get());
1410 EXPECT_EQ(frame->ackBlocks.size(), 1);
1411 }
1412
TEST_F(QuicTransportFunctionsTest,TestUpdateConnectionWithBytesStats)1413 TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionWithBytesStats) {
1414 auto conn = createConn();
1415 conn->qLogger = std::make_shared<quic::FileQLogger>(VantagePoint::Client);
1416 auto stream = conn->streamManager->createNextBidirectionalStream().value();
1417 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
1418 // This is clearly not 555 bytes. I just need some data inside the packet.
1419 writeDataToQuicStream(
1420 *stream, folly::IOBuf::copyBuffer("Im gonna cut your hair."), true);
1421 WriteStreamFrame writeStreamFrame(stream->id, 0, 5, false);
1422 packet.packet.frames.push_back(std::move(writeStreamFrame));
1423 conn->lossState.totalBytesSent = 13579;
1424 conn->lossState.totalBodyBytesSent = 13000;
1425 conn->lossState.inflightBytes = 16000;
1426 auto currentTime = Clock::now();
1427 conn->lossState.lastAckedTime = currentTime - 123s;
1428 conn->lossState.adjustedLastAckedTime = currentTime - 123s;
1429 conn->lossState.lastAckedPacketSentTime = currentTime - 234s;
1430 conn->lossState.totalBytesSentAtLastAck = 10000;
1431 conn->lossState.totalBytesAckedAtLastAck = 5000;
1432 conn->lossState.totalPacketsSent = 20;
1433 conn->lossState.totalAckElicitingPacketsSent = 15;
1434 updateConnection(
1435 *conn,
1436 folly::none,
1437 packet.packet,
1438 TimePoint(),
1439 555,
1440 500,
1441 false /* isDSRPacket */);
1442 EXPECT_EQ(21, conn->lossState.totalPacketsSent);
1443 EXPECT_EQ(16, conn->lossState.totalAckElicitingPacketsSent);
1444
1445 // verify QLogger contains correct packet information
1446 std::shared_ptr<quic::FileQLogger> qLogger =
1447 std::dynamic_pointer_cast<quic::FileQLogger>(conn->qLogger);
1448 std::vector<int> indices =
1449 getQLogEventIndices(QLogEventType::PacketSent, qLogger);
1450 EXPECT_EQ(indices.size(), 1);
1451 auto tmp = std::move(qLogger->logs[indices[0]]);
1452 auto event = dynamic_cast<QLogPacketEvent*>(tmp.get());
1453
1454 EXPECT_EQ(event->packetType, toQlogString(LongHeader::Types::Handshake));
1455 EXPECT_EQ(event->packetSize, 555);
1456 EXPECT_EQ(event->eventType, QLogEventType::PacketSent);
1457
1458 EXPECT_EQ(
1459 13579 + 555,
1460 getFirstOutstandingPacket(*conn, PacketNumberSpace::Handshake)
1461 ->metadata.totalBytesSent);
1462 EXPECT_EQ(
1463 13000 + 500,
1464 getFirstOutstandingPacket(*conn, PacketNumberSpace::Handshake)
1465 ->metadata.totalBodyBytesSent);
1466 EXPECT_EQ(
1467 16000 + 555,
1468 getFirstOutstandingPacket(*conn, PacketNumberSpace::Handshake)
1469 ->metadata.inflightBytes);
1470 EXPECT_EQ(
1471 1,
1472 getFirstOutstandingPacket(*conn, PacketNumberSpace::Handshake)
1473 ->metadata.packetsInflight);
1474 EXPECT_EQ(
1475 555,
1476 getFirstOutstandingPacket(*conn, PacketNumberSpace::Handshake)
1477 ->metadata.encodedSize);
1478 EXPECT_EQ(
1479 500,
1480 getFirstOutstandingPacket(*conn, PacketNumberSpace::Handshake)
1481 ->metadata.encodedBodySize);
1482 EXPECT_EQ(
1483 20 + 1,
1484 getFirstOutstandingPacket(*conn, PacketNumberSpace::Handshake)
1485 ->metadata.totalPacketsSent);
1486 EXPECT_EQ(
1487 15 + 1,
1488 getFirstOutstandingPacket(*conn, PacketNumberSpace::Handshake)
1489 ->metadata.totalAckElicitingPacketsSent);
1490
1491 EXPECT_TRUE(getFirstOutstandingPacket(*conn, PacketNumberSpace::Handshake)
1492 ->lastAckedPacketInfo.has_value());
1493 EXPECT_EQ(
1494 currentTime - 123s,
1495 getFirstOutstandingPacket(*conn, PacketNumberSpace::Handshake)
1496 ->lastAckedPacketInfo->ackTime);
1497 EXPECT_EQ(
1498 currentTime -= 234s,
1499 getFirstOutstandingPacket(*conn, PacketNumberSpace::Handshake)
1500 ->lastAckedPacketInfo->sentTime);
1501 EXPECT_EQ(
1502 10000,
1503 getFirstOutstandingPacket(*conn, PacketNumberSpace::Handshake)
1504 ->lastAckedPacketInfo->totalBytesSent);
1505 EXPECT_EQ(
1506 5000,
1507 getFirstOutstandingPacket(*conn, PacketNumberSpace::Handshake)
1508 ->lastAckedPacketInfo->totalBytesAcked);
1509 }
1510
TEST_F(QuicTransportFunctionsTest,TestUpdateConnectionWithCloneResult)1511 TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionWithCloneResult) {
1512 auto conn = createConn();
1513 conn->qLogger = std::make_shared<quic::FileQLogger>(VantagePoint::Client);
1514 auto mockCongestionController =
1515 std::make_unique<NiceMock<MockCongestionController>>();
1516 auto rawCongestionController = mockCongestionController.get();
1517 conn->congestionController = std::move(mockCongestionController);
1518 ShortHeader shortHeader(
1519 ProtectionType::KeyPhaseZero,
1520 *conn->clientConnectionId,
1521 conn->ackStates.appDataAckState.nextPacketNum);
1522 auto thisMoment = Clock::now();
1523 MockClock::mockNow = [=]() { return thisMoment; };
1524 RegularQuicWritePacket writePacket(std::move(shortHeader));
1525 // Add a dummy frame into the packet so we don't treat it as pureAck
1526 auto maxDataAmt = 1000 + conn->flowControlState.advertisedMaxOffset;
1527 MaxDataFrame maxDataFrame(maxDataAmt);
1528 conn->pendingEvents.connWindowUpdate = true;
1529 writePacket.frames.push_back(std::move(maxDataFrame));
1530 PacketEvent event(PacketNumberSpace::AppData, 1);
1531 conn->outstandings.packetEvents.insert(event);
1532 auto futureMoment = thisMoment + 50ms;
1533 MockClock::mockNow = [=]() { return futureMoment; };
1534 EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(1);
1535 updateConnection(
1536 *conn,
1537 event,
1538 std::move(writePacket),
1539 MockClock::now(),
1540 1500,
1541 1400,
1542 false /* isDSRPacket */);
1543 // verify QLogger contains correct packet information
1544 std::shared_ptr<quic::FileQLogger> qLogger =
1545 std::dynamic_pointer_cast<quic::FileQLogger>(conn->qLogger);
1546
1547 std::vector<int> indices =
1548 getQLogEventIndices(QLogEventType::PacketSent, qLogger);
1549 EXPECT_EQ(indices.size(), 1);
1550 auto tmp = std::move(qLogger->logs[indices[0]]);
1551 auto qLogEvent = dynamic_cast<QLogPacketEvent*>(tmp.get());
1552 EXPECT_EQ(qLogEvent->packetType, kShortHeaderPacketType.str());
1553 EXPECT_EQ(qLogEvent->packetSize, 1500);
1554 EXPECT_EQ(qLogEvent->eventType, QLogEventType::PacketSent);
1555
1556 // verify QLogger contains correct frame information
1557 EXPECT_EQ(qLogEvent->frames.size(), 1);
1558 auto frame = static_cast<MaxDataFrameLog*>(qLogEvent->frames[0].get());
1559 EXPECT_EQ(frame->maximumData, maxDataAmt);
1560 EXPECT_EQ(
1561 futureMoment,
1562 getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)
1563 ->metadata.time);
1564 EXPECT_EQ(
1565 1500,
1566 getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)
1567 ->metadata.encodedSize);
1568 EXPECT_EQ(
1569 1400,
1570 getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)
1571 ->metadata.encodedBodySize);
1572 EXPECT_EQ(
1573 event,
1574 *getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)
1575 ->associatedEvent);
1576 EXPECT_TRUE(conn->pendingEvents.setLossDetectionAlarm);
1577 }
1578
TEST_F(QuicTransportFunctionsTest,TestUpdateConnectionStreamWindowUpdate)1579 TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionStreamWindowUpdate) {
1580 auto conn = createConn();
1581 conn->qLogger = std::make_shared<quic::FileQLogger>(VantagePoint::Client);
1582 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
1583 auto stream = conn->streamManager->createNextBidirectionalStream().value();
1584 MaxStreamDataFrame streamWindowUpdate(stream->id, 0);
1585 conn->streamManager->queueWindowUpdate(stream->id);
1586 packet.packet.frames.push_back(std::move(streamWindowUpdate));
1587 updateConnection(
1588 *conn,
1589 folly::none,
1590 packet.packet,
1591 TimePoint(),
1592 getEncodedSize(packet),
1593 getEncodedBodySize(packet),
1594 false /* isDSRPacket */);
1595
1596 // verify QLogger contains correct packet information
1597 std::shared_ptr<quic::FileQLogger> qLogger =
1598 std::dynamic_pointer_cast<quic::FileQLogger>(conn->qLogger);
1599 std::vector<int> indices =
1600 getQLogEventIndices(QLogEventType::PacketSent, qLogger);
1601 EXPECT_EQ(indices.size(), 1);
1602 auto tmp = std::move(qLogger->logs[indices[0]]);
1603 auto event = dynamic_cast<QLogPacketEvent*>(tmp.get());
1604
1605 EXPECT_EQ(event->packetType, toQlogString(LongHeader::Types::Handshake));
1606 EXPECT_EQ(event->packetSize, getEncodedSize(packet));
1607 EXPECT_EQ(event->eventType, QLogEventType::PacketSent);
1608
1609 // verify QLogger contains correct frame information
1610 EXPECT_EQ(event->frames.size(), 1);
1611 auto frame = static_cast<MaxStreamDataFrameLog*>(event->frames[0].get());
1612 EXPECT_EQ(frame->streamId, stream->id);
1613 EXPECT_EQ(frame->maximumData, 0);
1614 }
1615
TEST_F(QuicTransportFunctionsTest,TestUpdateConnectionConnWindowUpdate)1616 TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionConnWindowUpdate) {
1617 auto conn = createConn();
1618 conn->qLogger = std::make_shared<quic::FileQLogger>(VantagePoint::Client);
1619 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
1620 conn->pendingEvents.connWindowUpdate = true;
1621 MaxDataFrame connWindowUpdate(conn->flowControlState.advertisedMaxOffset);
1622 packet.packet.frames.push_back(std::move(connWindowUpdate));
1623 updateConnection(
1624 *conn,
1625 folly::none,
1626 packet.packet,
1627 TimePoint(),
1628 getEncodedSize(packet),
1629 getEncodedBodySize(packet),
1630 false /* isDSRPacket */);
1631
1632 // verify QLogger contains correct packet information
1633 std::shared_ptr<quic::FileQLogger> qLogger =
1634 std::dynamic_pointer_cast<quic::FileQLogger>(conn->qLogger);
1635 std::vector<int> indices =
1636 getQLogEventIndices(QLogEventType::PacketSent, qLogger);
1637 EXPECT_EQ(indices.size(), 1);
1638 auto tmp = std::move(qLogger->logs[indices[0]]);
1639 auto event = dynamic_cast<QLogPacketEvent*>(tmp.get());
1640
1641 EXPECT_EQ(event->packetType, toQlogString(LongHeader::Types::Handshake));
1642 EXPECT_EQ(event->packetSize, getEncodedSize(packet));
1643 EXPECT_EQ(event->eventType, QLogEventType::PacketSent);
1644 // verify QLogger contains correct frame information
1645 EXPECT_EQ(event->frames.size(), 1);
1646 auto frame = static_cast<MaxDataFrameLog*>(event->frames[0].get());
1647 EXPECT_EQ(frame->maximumData, conn->flowControlState.advertisedMaxOffset);
1648 }
1649
TEST_F(QuicTransportFunctionsTest,TestStreamDetailsEmptyPacket)1650 TEST_F(QuicTransportFunctionsTest, TestStreamDetailsEmptyPacket) {
1651 auto conn = createConn();
1652 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
1653 updateConnection(
1654 *conn,
1655 folly::none,
1656 packet.packet,
1657 TimePoint(),
1658 getEncodedSize(packet),
1659 getEncodedBodySize(packet),
1660 false /* isDSRPacket */);
1661 // Since there is no ACK eliciting frame in this packet, it is not included as
1662 // an outstanding packet
1663 EXPECT_EQ(0, conn->outstandings.packets.size());
1664 }
1665
TEST_F(QuicTransportFunctionsTest,TestStreamDetailsControlPacket)1666 TEST_F(QuicTransportFunctionsTest, TestStreamDetailsControlPacket) {
1667 auto conn = createConn();
1668 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
1669 auto stream = conn->streamManager->createNextBidirectionalStream().value();
1670 StreamDataBlockedFrame blockedFrame(stream->id, 1000);
1671 packet.packet.frames.push_back(blockedFrame);
1672 packet.packet.frames.push_back(PingFrame());
1673 updateConnection(
1674 *conn,
1675 folly::none,
1676 packet.packet,
1677 TimePoint(),
1678 getEncodedSize(packet),
1679 getEncodedBodySize(packet),
1680 false /* isDSRPacket */);
1681 // If we have only control frames sent, there should be no stream data in the
1682 // outstanding packet.
1683 ASSERT_EQ(1, conn->outstandings.packets.size());
1684 auto detailsPerStream =
1685 getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
1686 ->metadata.maybeDetailsPerStream;
1687 EXPECT_EQ(true, detailsPerStream.has_value());
1688 EXPECT_EQ(0, detailsPerStream->getDetails().size());
1689 }
1690
TEST_F(QuicTransportFunctionsTest,TestStreamDetailsAppDataPacketSingleStream)1691 TEST_F(QuicTransportFunctionsTest, TestStreamDetailsAppDataPacketSingleStream) {
1692 auto conn = createConn();
1693 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
1694 auto stream = conn->streamManager->createNextBidirectionalStream().value();
1695 writeDataToQuicStream(*stream, folly::IOBuf::copyBuffer("abcdefghij"), true);
1696 WriteStreamFrame writeStreamFrame(
1697 stream->id, 0 /* offset */, 10 /* length */, false /* fin */);
1698 packet.packet.frames.push_back(writeStreamFrame);
1699 updateConnection(
1700 *conn,
1701 folly::none,
1702 packet.packet,
1703 TimePoint(),
1704 getEncodedSize(packet),
1705 getEncodedBodySize(packet),
1706 false /* isDSRPacket */);
1707
1708 ASSERT_EQ(1, conn->outstandings.packets.size());
1709 auto detailsPerStream =
1710 getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
1711 ->metadata.maybeDetailsPerStream->getDetails();
1712 EXPECT_EQ(1, detailsPerStream.size());
1713 auto streamDetail = detailsPerStream[stream->id];
1714 EXPECT_EQ(false, streamDetail.finObserved);
1715 EXPECT_EQ(10, streamDetail.streamBytesSent);
1716 EXPECT_EQ(10, streamDetail.newStreamBytesSent);
1717 EXPECT_EQ(0, streamDetail.maybeFirstNewStreamByteOffset.value());
1718 }
1719
TEST_F(QuicTransportFunctionsTest,TestStreamDetailsAppDataPacketSingleStreamMultipleFrames)1720 TEST_F(
1721 QuicTransportFunctionsTest,
1722 TestStreamDetailsAppDataPacketSingleStreamMultipleFrames) {
1723 auto conn = createConn();
1724 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
1725 auto stream = conn->streamManager->createNextBidirectionalStream().value();
1726 writeDataToQuicStream(
1727 *stream, folly::IOBuf::copyBuffer("abcdefghijklmno"), true);
1728 WriteStreamFrame writeStreamFrame1(
1729 stream->id, 0 /* offset */, 10 /* length */, false /* fin */);
1730 WriteStreamFrame writeStreamFrame2(
1731 stream->id, 10 /* offset */, 5 /* length */, true /* fin */);
1732 packet.packet.frames.push_back(writeStreamFrame1);
1733 packet.packet.frames.push_back(writeStreamFrame2);
1734 updateConnection(
1735 *conn,
1736 folly::none,
1737 packet.packet,
1738 TimePoint(),
1739 getEncodedSize(packet),
1740 getEncodedBodySize(packet),
1741 false /* isDSRPacket */);
1742
1743 ASSERT_EQ(1, conn->outstandings.packets.size());
1744 auto detailsPerStream =
1745 getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
1746 ->metadata.maybeDetailsPerStream->getDetails();
1747 EXPECT_EQ(1, detailsPerStream.size());
1748 auto streamDetail = detailsPerStream[stream->id];
1749 EXPECT_EQ(true, streamDetail.finObserved);
1750 EXPECT_EQ(15, streamDetail.streamBytesSent);
1751 EXPECT_EQ(15, streamDetail.newStreamBytesSent);
1752 EXPECT_EQ(0, streamDetail.maybeFirstNewStreamByteOffset.value());
1753 }
1754
TEST_F(QuicTransportFunctionsTest,TestStreamDetailsAppDataPacketSingleStreamRetransmit)1755 TEST_F(
1756 QuicTransportFunctionsTest,
1757 TestStreamDetailsAppDataPacketSingleStreamRetransmit) {
1758 auto conn = createConn();
1759 auto stream = conn->streamManager->createNextBidirectionalStream().value();
1760
1761 writeDataToQuicStream(*stream, folly::IOBuf::copyBuffer("abcdefghij"), true);
1762 uint64_t frame1Offset = 0;
1763 uint64_t frame1Len = 10;
1764 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
1765 WriteStreamFrame frame1(stream->id, frame1Offset, frame1Len, false /* fin */);
1766 packet.packet.frames.push_back(frame1);
1767 updateConnection(
1768 *conn,
1769 folly::none,
1770 packet.packet,
1771 TimePoint(),
1772 getEncodedSize(packet),
1773 getEncodedBodySize(packet),
1774 false /* isDSRPacket */);
1775
1776 ASSERT_EQ(1, conn->outstandings.packets.size());
1777
1778 // The first outstanding packet is the one with new data
1779 auto detailsPerStream =
1780 getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
1781 ->metadata.maybeDetailsPerStream->getDetails();
1782 EXPECT_EQ(1, detailsPerStream.size());
1783 auto streamDetail = detailsPerStream[stream->id];
1784 EXPECT_EQ(false, streamDetail.finObserved);
1785 EXPECT_EQ(frame1Len, streamDetail.streamBytesSent);
1786 EXPECT_EQ(frame1Len, streamDetail.newStreamBytesSent);
1787 EXPECT_EQ(frame1Offset, streamDetail.maybeFirstNewStreamByteOffset.value());
1788
1789 // retransmit the same frame1 again.
1790 packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
1791 packet.packet.frames.push_back(frame1);
1792 updateConnection(
1793 *conn,
1794 folly::none,
1795 packet.packet,
1796 TimePoint(),
1797 getEncodedSize(packet),
1798 getEncodedBodySize(packet),
1799 false /* isDSRPacket */);
1800
1801 ASSERT_EQ(2, conn->outstandings.packets.size());
1802
1803 // The second outstanding packet is the one with retransmit data
1804 detailsPerStream = getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)
1805 ->metadata.maybeDetailsPerStream->getDetails();
1806 EXPECT_EQ(1, detailsPerStream.size());
1807 streamDetail = detailsPerStream[stream->id];
1808 EXPECT_EQ(false, streamDetail.finObserved);
1809 EXPECT_EQ(frame1Len, streamDetail.streamBytesSent);
1810 EXPECT_EQ(0, streamDetail.newStreamBytesSent);
1811 EXPECT_FALSE(streamDetail.maybeFirstNewStreamByteOffset.has_value());
1812
1813 // Retransmit frame1 and send new data in frame2.
1814 writeDataToQuicStream(
1815 *stream, folly::IOBuf::copyBuffer("klmnopqrstuvwxy"), true);
1816 uint64_t frame2Offset = 10;
1817 uint64_t frame2Len = 15;
1818 packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
1819 WriteStreamFrame frame2(stream->id, frame2Offset, frame2Len, false /* fin */);
1820 packet.packet.frames.push_back(frame1);
1821 packet.packet.frames.push_back(frame2);
1822 updateConnection(
1823 *conn,
1824 folly::none,
1825 packet.packet,
1826 TimePoint(),
1827 getEncodedSize(packet),
1828 getEncodedBodySize(packet),
1829 false /* isDSRPacket */);
1830
1831 ASSERT_EQ(3, conn->outstandings.packets.size());
1832
1833 // The third outstanding packet will have both new and retransmitted data.
1834 detailsPerStream = getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)
1835 ->metadata.maybeDetailsPerStream->getDetails();
1836 EXPECT_EQ(1, detailsPerStream.size());
1837 streamDetail = detailsPerStream[stream->id];
1838 EXPECT_EQ(false, streamDetail.finObserved);
1839 EXPECT_EQ(frame1Len + frame2Len, streamDetail.streamBytesSent);
1840 EXPECT_EQ(frame2Len, streamDetail.newStreamBytesSent);
1841 EXPECT_EQ(frame2Offset, streamDetail.maybeFirstNewStreamByteOffset.value());
1842
1843 // Retransmit frame1 aand frame2.
1844 packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
1845 packet.packet.frames.push_back(frame1);
1846 packet.packet.frames.push_back(frame2);
1847 updateConnection(
1848 *conn,
1849 folly::none,
1850 packet.packet,
1851 TimePoint(),
1852 getEncodedSize(packet),
1853 getEncodedBodySize(packet),
1854 false /* isDSRPacket */);
1855
1856 ASSERT_EQ(4, conn->outstandings.packets.size());
1857
1858 // The forth outstanding packet will have only retransmit data.
1859 detailsPerStream = getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)
1860 ->metadata.maybeDetailsPerStream->getDetails();
1861 EXPECT_EQ(1, detailsPerStream.size());
1862 streamDetail = detailsPerStream[stream->id];
1863 EXPECT_EQ(false, streamDetail.finObserved);
1864 EXPECT_EQ(frame1Len + frame2Len, streamDetail.streamBytesSent);
1865 EXPECT_EQ(0, streamDetail.newStreamBytesSent);
1866 EXPECT_FALSE(streamDetail.maybeFirstNewStreamByteOffset.has_value());
1867 }
1868
TEST_F(QuicTransportFunctionsTest,TestStreamDetailsAppDataPacketMultipleStreams)1869 TEST_F(
1870 QuicTransportFunctionsTest,
1871 TestStreamDetailsAppDataPacketMultipleStreams) {
1872 auto conn = createConn();
1873 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
1874 auto stream1Id =
1875 conn->streamManager->createNextBidirectionalStream().value()->id;
1876 auto stream2Id =
1877 conn->streamManager->createNextBidirectionalStream().value()->id;
1878 auto stream1 = conn->streamManager->findStream(stream1Id);
1879 auto stream2 = conn->streamManager->findStream(stream2Id);
1880 EXPECT_NE(nullptr, stream1);
1881 EXPECT_NE(nullptr, stream2);
1882
1883 auto buf = IOBuf::copyBuffer("hey whats up");
1884 writeDataToQuicStream(*stream1, buf->clone(), true);
1885 writeDataToQuicStream(*stream2, buf->clone(), true);
1886
1887 WriteStreamFrame writeStreamFrame1(stream1->id, 0, 5, false),
1888 writeStreamFrame2(stream2->id, 0, 12, true);
1889 packet.packet.frames.push_back(writeStreamFrame1);
1890 packet.packet.frames.push_back(writeStreamFrame2);
1891
1892 updateConnection(
1893 *conn,
1894 folly::none,
1895 packet.packet,
1896 TimePoint(),
1897 getEncodedSize(packet),
1898 getEncodedBodySize(packet),
1899 false /* isDSRPacket */);
1900
1901 ASSERT_EQ(1, conn->outstandings.packets.size());
1902 auto detailsPerStream =
1903 getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)
1904 ->metadata.maybeDetailsPerStream->getDetails();
1905 EXPECT_EQ(2, detailsPerStream.size());
1906 auto stream1Detail = detailsPerStream[stream1Id];
1907 auto stream2Detail = detailsPerStream[stream2Id];
1908
1909 EXPECT_EQ(false, stream1Detail.finObserved);
1910 EXPECT_EQ(5, stream1Detail.streamBytesSent);
1911 EXPECT_EQ(5, stream1Detail.newStreamBytesSent);
1912 EXPECT_EQ(0, stream1Detail.maybeFirstNewStreamByteOffset.value());
1913
1914 EXPECT_EQ(true, stream2Detail.finObserved);
1915 EXPECT_EQ(12, stream2Detail.streamBytesSent);
1916 EXPECT_EQ(12, stream2Detail.newStreamBytesSent);
1917 EXPECT_EQ(0, stream2Detail.maybeFirstNewStreamByteOffset.value());
1918 }
1919
TEST_F(QuicTransportFunctionsTest,WriteQuicDataToSocketWithCC)1920 TEST_F(QuicTransportFunctionsTest, WriteQuicDataToSocketWithCC) {
1921 auto conn = createConn();
1922 conn->udpSendPacketLen = 30;
1923 auto mockCongestionController =
1924 std::make_unique<NiceMock<MockCongestionController>>();
1925 auto rawCongestionController = mockCongestionController.get();
1926 conn->congestionController = std::move(mockCongestionController);
1927
1928 EventBase evb;
1929 auto socket =
1930 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
1931 auto rawSocket = socket.get();
1932
1933 auto stream1 = conn->streamManager->createNextBidirectionalStream().value();
1934 auto buf =
1935 IOBuf::copyBuffer("0123456789012012345678901201234567890120123456789012");
1936 writeDataToQuicStream(*stream1, buf->clone(), true);
1937
1938 uint64_t writableBytes = 30;
1939 EXPECT_CALL(*rawCongestionController, getWritableBytes())
1940 .WillRepeatedly(
1941 InvokeWithoutArgs([&writableBytes]() { return writableBytes; }));
1942 EXPECT_CALL(*rawSocket, write(_, _))
1943 .WillRepeatedly(Invoke([&](const SocketAddress&,
1944 const std::unique_ptr<folly::IOBuf>& iobuf) {
1945 EXPECT_LE(iobuf->computeChainDataLength(), 30);
1946 writableBytes -= iobuf->computeChainDataLength();
1947 return iobuf->computeChainDataLength();
1948 }));
1949 EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(1);
1950 EXPECT_CALL(*transportInfoCb_, onWrite(_));
1951 writeQuicDataToSocket(
1952 *rawSocket,
1953 *conn,
1954 *conn->clientConnectionId,
1955 *conn->serverConnectionId,
1956 *aead,
1957 *headerCipher,
1958 getVersion(*conn),
1959 conn->transportSettings.writeConnectionDataPacketsLimit);
1960 }
1961
TEST_F(QuicTransportFunctionsTest,WriteQuicdataToSocketWithPacer)1962 TEST_F(QuicTransportFunctionsTest, WriteQuicdataToSocketWithPacer) {
1963 auto conn = createConn();
1964 auto mockPacer = std::make_unique<NiceMock<MockPacer>>();
1965 auto rawPacer = mockPacer.get();
1966 conn->pacer = std::move(mockPacer);
1967
1968 EventBase evb;
1969 auto socket =
1970 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
1971 auto rawSocket = socket.get();
1972
1973 auto stream1 = conn->streamManager->createNextBidirectionalStream().value();
1974 auto buf =
1975 IOBuf::copyBuffer("0123456789012012345678901201234567890120123456789012");
1976 writeDataToQuicStream(*stream1, buf->clone(), true);
1977
1978 EXPECT_CALL(*rawPacer, onPacketSent()).Times(1);
1979 EXPECT_CALL(*transportInfoCb_, onWrite(_));
1980 writeQuicDataToSocket(
1981 *rawSocket,
1982 *conn,
1983 *conn->clientConnectionId,
1984 *conn->serverConnectionId,
1985 *aead,
1986 *headerCipher,
1987 getVersion(*conn),
1988 conn->transportSettings.writeConnectionDataPacketsLimit);
1989 }
1990
TEST_F(QuicTransportFunctionsTest,WriteQuicDataToSocketLimitTest)1991 TEST_F(QuicTransportFunctionsTest, WriteQuicDataToSocketLimitTest) {
1992 auto conn = createConn();
1993 auto mockCongestionController =
1994 std::make_unique<NiceMock<MockCongestionController>>();
1995 auto rawCongestionController = mockCongestionController.get();
1996 conn->congestionController = std::move(mockCongestionController);
1997 conn->udpSendPacketLen = aead->getCipherOverhead() + 50;
1998
1999 EventBase evb;
2000 auto socket =
2001 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
2002 auto rawSocket = socket.get();
2003 auto stream1 = conn->streamManager->createNextBidirectionalStream().value();
2004 // ~50 bytes
2005 auto buf =
2006 IOBuf::copyBuffer("0123456789012012345678901201234567890120123456789012");
2007 writeDataToQuicStream(*stream1, buf->clone(), false);
2008 uint64_t writableBytes = 30;
2009 EXPECT_CALL(*rawCongestionController, getWritableBytes())
2010 .WillRepeatedly(
2011 InvokeWithoutArgs([&writableBytes]() { return writableBytes; }));
2012
2013 // Limit to zero
2014 conn->transportSettings.writeConnectionDataPacketsLimit = 0;
2015 EXPECT_CALL(*rawSocket, write(_, _)).Times(0);
2016 EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(0);
2017 EXPECT_CALL(*transportInfoCb_, onWrite(_)).Times(0);
2018 auto res = writeQuicDataToSocket(
2019 *rawSocket,
2020 *conn,
2021 *conn->clientConnectionId,
2022 *conn->serverConnectionId,
2023 *aead,
2024 *headerCipher,
2025 getVersion(*conn),
2026 conn->transportSettings.writeConnectionDataPacketsLimit);
2027 EXPECT_EQ(0, res.packetsWritten);
2028 EXPECT_EQ(0, res.probesWritten);
2029
2030 // Normal limit
2031 conn->pendingEvents.numProbePackets[PacketNumberSpace::Initial] = 0;
2032 conn->pendingEvents.numProbePackets[PacketNumberSpace::Handshake] = 0;
2033 conn->pendingEvents.numProbePackets[PacketNumberSpace::AppData] = 0;
2034 conn->transportSettings.writeConnectionDataPacketsLimit =
2035 kDefaultWriteConnectionDataPacketLimit;
2036 EXPECT_CALL(*rawSocket, write(_, _))
2037 .Times(1)
2038 .WillOnce(Invoke([&](const SocketAddress&,
2039 const std::unique_ptr<folly::IOBuf>& iobuf) {
2040 writableBytes -= iobuf->computeChainDataLength();
2041 return iobuf->computeChainDataLength();
2042 }));
2043 EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(1);
2044 EXPECT_CALL(*transportInfoCb_, onWrite(_)).Times(1);
2045 res = writeQuicDataToSocket(
2046 *rawSocket,
2047 *conn,
2048 *conn->clientConnectionId,
2049 *conn->serverConnectionId,
2050 *aead,
2051 *headerCipher,
2052 getVersion(*conn),
2053 conn->transportSettings.writeConnectionDataPacketsLimit);
2054
2055 EXPECT_EQ(1, res.packetsWritten);
2056 EXPECT_EQ(0, res.probesWritten);
2057
2058 // Probing can exceed packet limit. In practice we limit it to
2059 // kPacketToSendForPTO
2060 conn->pendingEvents.numProbePackets[PacketNumberSpace::AppData] =
2061 kDefaultWriteConnectionDataPacketLimit * 2;
2062 writeDataToQuicStream(*stream1, buf->clone(), true);
2063 writableBytes = 10000;
2064 EXPECT_CALL(*rawCongestionController, getWritableBytes())
2065 .WillRepeatedly(
2066 InvokeWithoutArgs([&writableBytes]() { return writableBytes; }));
2067 EXPECT_CALL(*rawSocket, write(_, _))
2068 .Times(kDefaultWriteConnectionDataPacketLimit * 2)
2069 .WillRepeatedly(Invoke([&](const SocketAddress&,
2070 const std::unique_ptr<folly::IOBuf>& iobuf) {
2071 return iobuf->computeChainDataLength();
2072 }));
2073 EXPECT_CALL(*rawCongestionController, onPacketSent(_))
2074 .Times(kDefaultWriteConnectionDataPacketLimit * 2);
2075 EXPECT_CALL(*transportInfoCb_, onWrite(_))
2076 .Times(kDefaultWriteConnectionDataPacketLimit * 2);
2077 res = writeQuicDataToSocket(
2078 *rawSocket,
2079 *conn,
2080 *conn->clientConnectionId,
2081 *conn->serverConnectionId,
2082 *aead,
2083 *headerCipher,
2084 getVersion(*conn),
2085 conn->transportSettings.writeConnectionDataPacketsLimit);
2086
2087 EXPECT_EQ(0, res.packetsWritten);
2088 EXPECT_EQ(kDefaultWriteConnectionDataPacketLimit * 2, res.probesWritten);
2089 }
2090
TEST_F(QuicTransportFunctionsTest,WriteQuicDataToSocketWhenInFlightBytesAreLimited)2091 TEST_F(
2092 QuicTransportFunctionsTest,
2093 WriteQuicDataToSocketWhenInFlightBytesAreLimited) {
2094 auto conn = createConn();
2095 conn->oneRttWriteCipher = test::createNoOpAead();
2096 auto mockCongestionController =
2097 std::make_unique<NiceMock<MockCongestionController>>();
2098 auto rawCongestionController = mockCongestionController.get();
2099 conn->congestionController = std::move(mockCongestionController);
2100
2101 EventBase evb;
2102 auto socket =
2103 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
2104 auto rawSocket = socket.get();
2105
2106 auto stream1 = conn->streamManager->createNextBidirectionalStream().value();
2107 auto buf =
2108 IOBuf::copyBuffer("0123456789012012345678901201234567890120123456789012");
2109 writeDataToQuicStream(*stream1, buf->clone(), true);
2110
2111 conn->writableBytesLimit = 100;
2112 uint64_t writableBytes = 5 * *conn->writableBytesLimit;
2113
2114 EXPECT_CALL(*rawCongestionController, getWritableBytes())
2115 .WillRepeatedly(
2116 InvokeWithoutArgs([&writableBytes]() { return writableBytes; }));
2117 EXPECT_CALL(*rawSocket, write(_, _))
2118 .WillRepeatedly(Invoke([&](const SocketAddress&,
2119 const std::unique_ptr<folly::IOBuf>& iobuf) {
2120 EXPECT_LE(
2121 iobuf->computeChainDataLength(),
2122 *conn->writableBytesLimit - conn->lossState.totalBytesSent);
2123 writableBytes -= iobuf->computeChainDataLength();
2124 return iobuf->computeChainDataLength();
2125 }));
2126 EXPECT_NE(WriteDataReason::NO_WRITE, shouldWriteData(*conn));
2127 writeQuicDataToSocket(
2128 *rawSocket,
2129 *conn,
2130 *conn->clientConnectionId,
2131 *conn->serverConnectionId,
2132 *aead,
2133 *headerCipher,
2134 getVersion(*conn),
2135 conn->transportSettings.writeConnectionDataPacketsLimit);
2136 EXPECT_EQ(WriteDataReason::NO_WRITE, shouldWriteData(*conn));
2137 }
2138
TEST_F(QuicTransportFunctionsTest,WriteQuicDataToSocketWithNoBytesForHeader)2139 TEST_F(QuicTransportFunctionsTest, WriteQuicDataToSocketWithNoBytesForHeader) {
2140 auto conn = createConn();
2141 auto mockCongestionController =
2142 std::make_unique<NiceMock<MockCongestionController>>();
2143 auto rawCongestionController = mockCongestionController.get();
2144 conn->congestionController = std::move(mockCongestionController);
2145
2146 EventBase evb;
2147 auto socket =
2148 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
2149 auto rawSocket = socket.get();
2150
2151 auto stream1 = conn->streamManager->createNextBidirectionalStream().value();
2152 auto buf = IOBuf::copyBuffer("0123456789012");
2153 writeDataToQuicStream(*stream1, buf->clone(), true);
2154
2155 EXPECT_CALL(*rawCongestionController, getWritableBytes())
2156 .WillRepeatedly(Return(0));
2157 EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(0);
2158 writeQuicDataToSocket(
2159 *rawSocket,
2160 *conn,
2161 *conn->clientConnectionId,
2162 *conn->serverConnectionId,
2163 *aead,
2164 *headerCipher,
2165 getVersion(*conn),
2166 conn->transportSettings.writeConnectionDataPacketsLimit);
2167 // No header space left. Should send nothing.
2168 EXPECT_TRUE(conn->outstandings.packets.empty());
2169 }
2170
TEST_F(QuicTransportFunctionsTest,WriteQuicDataToSocketRetxBufferSorted)2171 TEST_F(QuicTransportFunctionsTest, WriteQuicDataToSocketRetxBufferSorted) {
2172 EventBase evb;
2173 NiceMock<folly::test::MockAsyncUDPSocket> socket(&evb);
2174 auto conn = createConn();
2175 auto stream = conn->streamManager->createNextBidirectionalStream().value();
2176 auto buf1 = IOBuf::copyBuffer("Whatsapp");
2177 writeDataToQuicStream(*stream, std::move(buf1), false);
2178 writeQuicDataToSocket(
2179 socket,
2180 *conn,
2181 *conn->clientConnectionId,
2182 *conn->serverConnectionId,
2183 *aead,
2184 *headerCipher,
2185 getVersion(*conn),
2186 conn->transportSettings.writeConnectionDataPacketsLimit);
2187 EXPECT_EQ(1, stream->retransmissionBuffer.size());
2188
2189 auto buf2 = IOBuf::copyBuffer("Google Buzz");
2190 writeDataToQuicStream(*stream, std::move(buf2), false);
2191 writeQuicDataToSocket(
2192 socket,
2193 *conn,
2194 *conn->clientConnectionId,
2195 *conn->serverConnectionId,
2196 *aead,
2197 *headerCipher,
2198 getVersion(*conn),
2199 conn->transportSettings.writeConnectionDataPacketsLimit);
2200 EXPECT_EQ(2, stream->retransmissionBuffer.size());
2201 }
2202
TEST_F(QuicTransportFunctionsTest,NothingWritten)2203 TEST_F(QuicTransportFunctionsTest, NothingWritten) {
2204 auto conn = createConn();
2205 auto mockCongestionController =
2206 std::make_unique<NiceMock<MockCongestionController>>();
2207 auto rawCongestionController = mockCongestionController.get();
2208 conn->congestionController = std::move(mockCongestionController);
2209
2210 EventBase evb;
2211 auto socket =
2212 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
2213 auto rawSocket = socket.get();
2214
2215 // 18 isn't enough to write 3 ack blocks, but is enough to write a pure
2216 // header packet, which we shouldn't write
2217 EXPECT_CALL(*rawCongestionController, getWritableBytes())
2218 .WillRepeatedly(Return(18));
2219
2220 addAckStatesWithCurrentTimestamps(conn->ackStates.initialAckState, 0, 1000);
2221 addAckStatesWithCurrentTimestamps(
2222 conn->ackStates.initialAckState, 1500, 2000);
2223 addAckStatesWithCurrentTimestamps(
2224 conn->ackStates.initialAckState, 2500, 3000);
2225 auto res = writeQuicDataToSocket(
2226 *rawSocket,
2227 *conn,
2228 *conn->clientConnectionId,
2229 *conn->serverConnectionId,
2230 *aead,
2231 *headerCipher,
2232 getVersion(*conn),
2233 conn->transportSettings.writeConnectionDataPacketsLimit);
2234 EXPECT_EQ(0, res.packetsWritten);
2235 EXPECT_EQ(0, res.probesWritten);
2236 }
2237
getFirstFrameInOutstandingPackets(const std::deque<OutstandingPacket> & outstandingPackets,QuicWriteFrame::Type frameType)2238 const QuicWriteFrame& getFirstFrameInOutstandingPackets(
2239 const std::deque<OutstandingPacket>& outstandingPackets,
2240 QuicWriteFrame::Type frameType) {
2241 for (const auto& packet : outstandingPackets) {
2242 for (const auto& frame : packet.packet.frames) {
2243 if (frame.type() == frameType) {
2244 return frame;
2245 }
2246 }
2247 }
2248 throw std::runtime_error("Frame not present");
2249 }
2250
TEST_F(QuicTransportFunctionsTest,WriteBlockedFrameWhenBlocked)2251 TEST_F(QuicTransportFunctionsTest, WriteBlockedFrameWhenBlocked) {
2252 auto conn = createConn();
2253 EventBase evb;
2254 auto socket =
2255 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
2256 auto rawSocket = socket.get();
2257 auto stream1 = conn->streamManager->createNextBidirectionalStream().value();
2258 auto buf = buildRandomInputData(200);
2259 writeDataToQuicStream(*stream1, buf->clone(), true);
2260
2261 auto originalNextSeq = conn->ackStates.appDataAckState.nextPacketNum;
2262 uint64_t sentBytes = 0;
2263 EXPECT_CALL(*rawSocket, write(_, _))
2264 .WillRepeatedly(Invoke([&](const SocketAddress&,
2265 const std::unique_ptr<folly::IOBuf>& iobuf) {
2266 auto len = iobuf->computeChainDataLength();
2267 sentBytes += len;
2268 return len;
2269 }));
2270
2271 // Artificially Block the stream
2272 stream1->flowControlState.peerAdvertisedMaxOffset = 10;
2273 // writes blocked frame in additionally
2274 EXPECT_CALL(*transportInfoCb_, onWrite(_)).Times(2);
2275 writeQuicDataToSocket(
2276 *rawSocket,
2277 *conn,
2278 *conn->clientConnectionId,
2279 *conn->serverConnectionId,
2280 *aead,
2281 *headerCipher,
2282 getVersion(*conn),
2283 conn->transportSettings.writeConnectionDataPacketsLimit);
2284 EXPECT_LT(sentBytes, 200);
2285
2286 EXPECT_GT(conn->ackStates.appDataAckState.nextPacketNum, originalNextSeq);
2287 auto blocked = *getFirstFrameInOutstandingPackets(
2288 conn->outstandings.packets,
2289 QuicWriteFrame::Type::StreamDataBlockedFrame)
2290 .asStreamDataBlockedFrame();
2291 EXPECT_EQ(blocked.streamId, stream1->id);
2292
2293 // Since everything is blocked, we shouldn't write a blocked again, so we
2294 // won't have any new packets to write if we trigger a write.
2295 auto previousPackets = conn->outstandings.packets.size();
2296 EXPECT_CALL(*transportInfoCb_, onWrite(_)).Times(0);
2297 writeQuicDataToSocket(
2298 *rawSocket,
2299 *conn,
2300 *conn->clientConnectionId,
2301 *conn->serverConnectionId,
2302 *aead,
2303 *headerCipher,
2304 getVersion(*conn),
2305 conn->transportSettings.writeConnectionDataPacketsLimit);
2306 EXPECT_EQ(previousPackets, conn->outstandings.packets.size());
2307 }
2308
TEST_F(QuicTransportFunctionsTest,WriteProbingNewData)2309 TEST_F(QuicTransportFunctionsTest, WriteProbingNewData) {
2310 auto conn = createConn();
2311 // writeProbingDataToSocketForTest writes ShortHeader, thus it writes at
2312 // AppTraffic level
2313 auto currentPacketSeqNum = conn->ackStates.appDataAckState.nextPacketNum;
2314 auto mockCongestionController =
2315 std::make_unique<NiceMock<MockCongestionController>>();
2316 auto rawCongestionController = mockCongestionController.get();
2317 conn->congestionController = std::move(mockCongestionController);
2318 EventBase evb;
2319 auto socket =
2320 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
2321 auto rawSocket = socket.get();
2322 auto stream1 = conn->streamManager->createNextBidirectionalStream().value();
2323 auto buf = buildRandomInputData(conn->udpSendPacketLen * 2);
2324 writeDataToQuicStream(*stream1, buf->clone(), true /* eof */);
2325
2326 auto currentStreamWriteOffset = stream1->currentWriteOffset;
2327 EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(1);
2328 EXPECT_CALL(*rawSocket, write(_, _))
2329 .WillOnce(Invoke([&](const SocketAddress&,
2330 const std::unique_ptr<folly::IOBuf>& iobuf) {
2331 auto len = iobuf->computeChainDataLength();
2332 EXPECT_EQ(conn->udpSendPacketLen - aead->getCipherOverhead(), len);
2333 return len;
2334 }));
2335 writeProbingDataToSocketForTest(
2336 *rawSocket, *conn, 1, *aead, *headerCipher, getVersion(*conn));
2337 EXPECT_LT(currentPacketSeqNum, conn->ackStates.appDataAckState.nextPacketNum);
2338 EXPECT_FALSE(conn->outstandings.packets.empty());
2339 EXPECT_EQ(
2340 conn->outstandings.packets.back().packet.header.getPacketSequenceNum(),
2341 currentPacketSeqNum + 1);
2342 EXPECT_TRUE(conn->pendingEvents.setLossDetectionAlarm);
2343 EXPECT_GT(stream1->currentWriteOffset, currentStreamWriteOffset);
2344 EXPECT_FALSE(stream1->retransmissionBuffer.empty());
2345 }
2346
TEST_F(QuicTransportFunctionsTest,WriteProbingOldData)2347 TEST_F(QuicTransportFunctionsTest, WriteProbingOldData) {
2348 auto conn = createConn();
2349 conn->congestionController.reset();
2350 EventBase evb;
2351 auto socket =
2352 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
2353 auto rawSocket = socket.get();
2354 EXPECT_CALL(*rawSocket, write(_, _)).WillRepeatedly(Return(100));
2355 auto capturingAead = std::make_unique<MockAead>();
2356 auto stream = conn->streamManager->createNextBidirectionalStream().value();
2357 auto buf = folly::IOBuf::copyBuffer("Where you wanna go");
2358 writeDataToQuicStream(*stream, buf->clone(), true);
2359
2360 folly::IOBuf pktBodyCaptured;
2361 EXPECT_CALL(*capturingAead, _inplaceEncrypt(_, _, _))
2362 .WillRepeatedly(Invoke([&](auto& buf, auto, auto) {
2363 if (buf) {
2364 pktBodyCaptured.prependChain(buf->clone());
2365 return buf->clone();
2366 } else {
2367 return folly::IOBuf::create(0);
2368 }
2369 }));
2370 EXPECT_EQ(
2371 1,
2372 writeProbingDataToSocketForTest(
2373 *rawSocket, *conn, 1, *aead, *headerCipher, getVersion(*conn)));
2374 // Now we have no new data, let's probe again, and verify the same old data
2375 // is sent.
2376 folly::IOBuf secondBodyCaptured;
2377 EXPECT_CALL(*capturingAead, _inplaceEncrypt(_, _, _))
2378 .WillRepeatedly(Invoke([&](auto& buf, auto, auto) {
2379 if (buf) {
2380 secondBodyCaptured.prependChain(buf->clone());
2381 return buf->clone();
2382 } else {
2383 return folly::IOBuf::create(0);
2384 }
2385 }));
2386 EXPECT_EQ(
2387 1,
2388 writeProbingDataToSocketForTest(
2389 *rawSocket, *conn, 1, *aead, *headerCipher, getVersion(*conn)));
2390 // Verify two pacekts have the same body
2391 EXPECT_TRUE(folly::IOBufEqualTo()(pktBodyCaptured, secondBodyCaptured));
2392 }
2393
TEST_F(QuicTransportFunctionsTest,WriteProbingCryptoData)2394 TEST_F(QuicTransportFunctionsTest, WriteProbingCryptoData) {
2395 QuicServerConnectionState conn(
2396 FizzServerQuicHandshakeContext::Builder().build());
2397 conn.serverConnectionId = getTestConnectionId();
2398 conn.clientConnectionId = getTestConnectionId();
2399 // writeCryptoDataProbesToSocketForTest writes Initial LongHeader, thus it
2400 // writes at Initial level.
2401 auto currentPacketSeqNum = conn.ackStates.initialAckState.nextPacketNum;
2402 // Replace real congestionController with MockCongestionController:
2403 auto mockCongestionController =
2404 std::make_unique<NiceMock<MockCongestionController>>();
2405 auto rawCongestionController = mockCongestionController.get();
2406 conn.congestionController = std::move(mockCongestionController);
2407 EventBase evb;
2408 auto socket =
2409 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
2410 auto rawSocket = socket.get();
2411 auto cryptoStream = &conn.cryptoState->initialStream;
2412 auto buf = buildRandomInputData(conn.udpSendPacketLen * 2);
2413 writeDataToQuicStream(*cryptoStream, buf->clone());
2414
2415 auto currentStreamWriteOffset = cryptoStream->currentWriteOffset;
2416 EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(1);
2417 EXPECT_CALL(*rawSocket, write(_, _))
2418 .WillOnce(Invoke([&](const SocketAddress&,
2419 const std::unique_ptr<folly::IOBuf>& iobuf) {
2420 auto len = iobuf->computeChainDataLength();
2421 EXPECT_EQ(conn.udpSendPacketLen - aead->getCipherOverhead(), len);
2422 return len;
2423 }));
2424 writeCryptoDataProbesToSocketForTest(
2425 *rawSocket, conn, 1, *aead, *headerCipher, getVersion(conn));
2426 EXPECT_LT(currentPacketSeqNum, conn.ackStates.initialAckState.nextPacketNum);
2427 EXPECT_FALSE(conn.outstandings.packets.empty());
2428 EXPECT_TRUE(conn.pendingEvents.setLossDetectionAlarm);
2429 EXPECT_GT(cryptoStream->currentWriteOffset, currentStreamWriteOffset);
2430 EXPECT_FALSE(cryptoStream->retransmissionBuffer.empty());
2431 }
2432
TEST_F(QuicTransportFunctionsTest,ProbingNotFallbackToPingWhenNoQuota)2433 TEST_F(QuicTransportFunctionsTest, ProbingNotFallbackToPingWhenNoQuota) {
2434 auto conn = createConn();
2435 auto mockCongestionController =
2436 std::make_unique<NiceMock<MockCongestionController>>();
2437 auto rawCongestionController = mockCongestionController.get();
2438 conn->congestionController = std::move(mockCongestionController);
2439 EventBase evb;
2440 auto socket =
2441 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
2442 auto rawSocket = socket.get();
2443 EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(0);
2444 EXPECT_CALL(*rawSocket, write(_, _)).Times(0);
2445 uint8_t probesToSend = 0;
2446 EXPECT_EQ(
2447 0,
2448 writeProbingDataToSocketForTest(
2449 *rawSocket,
2450 *conn,
2451 probesToSend,
2452 *aead,
2453 *headerCipher,
2454 getVersion(*conn)));
2455 }
2456
TEST_F(QuicTransportFunctionsTest,ProbingFallbackToPing)2457 TEST_F(QuicTransportFunctionsTest, ProbingFallbackToPing) {
2458 auto conn = createConn();
2459 EventBase evb;
2460 auto socket =
2461 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
2462 auto rawSocket = socket.get();
2463 EXPECT_CALL(*rawSocket, write(_, _))
2464 .Times(1)
2465 .WillOnce(Invoke([&](const SocketAddress&,
2466 const std::unique_ptr<folly::IOBuf>& iobuf) {
2467 return iobuf->computeChainDataLength();
2468 }));
2469 uint8_t probesToSend = 1;
2470 EXPECT_EQ(
2471 1,
2472 writeProbingDataToSocketForTest(
2473 *rawSocket,
2474 *conn,
2475 probesToSend,
2476 *aead,
2477 *headerCipher,
2478 getVersion(*conn)));
2479 // Ping is the only non-retransmittable packet that will go into OP list
2480 EXPECT_EQ(1, conn->outstandings.packets.size());
2481 }
2482
TEST_F(QuicTransportFunctionsTest,TestCryptoWritingIsHandshakeInOutstanding)2483 TEST_F(QuicTransportFunctionsTest, TestCryptoWritingIsHandshakeInOutstanding) {
2484 auto conn = createConn();
2485 auto cryptoStream = &conn->cryptoState->initialStream;
2486 auto buf = buildRandomInputData(200);
2487 writeDataToQuicStream(*cryptoStream, buf->clone());
2488 EventBase evb;
2489 auto socket =
2490 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
2491 auto rawSocket = socket.get();
2492 auto res = writeCryptoAndAckDataToSocket(
2493 *rawSocket,
2494 *conn,
2495 *conn->clientConnectionId,
2496 *conn->serverConnectionId,
2497 LongHeader::Types::Initial,
2498 *conn->initialWriteCipher,
2499 *conn->initialHeaderCipher,
2500 getVersion(*conn),
2501 conn->transportSettings.writeConnectionDataPacketsLimit);
2502
2503 EXPECT_EQ(1, res.packetsWritten);
2504 EXPECT_EQ(0, res.probesWritten);
2505 ASSERT_EQ(1, conn->outstandings.packets.size());
2506 EXPECT_TRUE(getFirstOutstandingPacket(*conn, PacketNumberSpace::Initial)
2507 ->metadata.isHandshake);
2508 }
2509
TEST_F(QuicTransportFunctionsTest,NoCryptoProbeWriteIfNoProbeCredit)2510 TEST_F(QuicTransportFunctionsTest, NoCryptoProbeWriteIfNoProbeCredit) {
2511 auto conn = createConn();
2512 auto cryptoStream = &conn->cryptoState->initialStream;
2513 auto buf = buildRandomInputData(200);
2514 writeDataToQuicStream(*cryptoStream, buf->clone());
2515 EventBase evb;
2516 auto socket =
2517 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
2518 auto rawSocket = socket.get();
2519 auto res = writeCryptoAndAckDataToSocket(
2520 *rawSocket,
2521 *conn,
2522 *conn->clientConnectionId,
2523 *conn->serverConnectionId,
2524 LongHeader::Types::Initial,
2525 *conn->initialWriteCipher,
2526 *conn->initialHeaderCipher,
2527 getVersion(*conn),
2528 conn->transportSettings.writeConnectionDataPacketsLimit);
2529
2530 EXPECT_EQ(1, res.packetsWritten);
2531 EXPECT_EQ(0, res.probesWritten);
2532 ASSERT_EQ(1, conn->outstandings.packets.size());
2533 EXPECT_TRUE(getFirstOutstandingPacket(*conn, PacketNumberSpace::Initial)
2534 ->metadata.isHandshake);
2535 ASSERT_EQ(1, cryptoStream->retransmissionBuffer.size());
2536 ASSERT_TRUE(cryptoStream->writeBuffer.empty());
2537
2538 conn->pendingEvents.numProbePackets[PacketNumberSpace::Initial] = 0;
2539 conn->pendingEvents.numProbePackets[PacketNumberSpace::Handshake] = 0;
2540 conn->pendingEvents.numProbePackets[PacketNumberSpace::AppData] = 0;
2541 res = writeCryptoAndAckDataToSocket(
2542 *rawSocket,
2543 *conn,
2544 *conn->clientConnectionId,
2545 *conn->serverConnectionId,
2546 LongHeader::Types::Initial,
2547 *conn->initialWriteCipher,
2548 *conn->initialHeaderCipher,
2549 getVersion(*conn),
2550 conn->transportSettings.writeConnectionDataPacketsLimit);
2551
2552 EXPECT_EQ(0, res.packetsWritten);
2553 EXPECT_EQ(0, res.probesWritten);
2554 }
2555
TEST_F(QuicTransportFunctionsTest,ResetNumProbePackets)2556 TEST_F(QuicTransportFunctionsTest, ResetNumProbePackets) {
2557 auto conn = createConn();
2558 EventBase evb;
2559 auto socket =
2560 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
2561 auto rawSocket = socket.get();
2562
2563 conn->pendingEvents.numProbePackets[PacketNumberSpace::Initial] = 2;
2564 writeCryptoAndAckDataToSocket(
2565 *rawSocket,
2566 *conn,
2567 *conn->clientConnectionId,
2568 *conn->serverConnectionId,
2569 LongHeader::Types::Initial,
2570 *conn->initialWriteCipher,
2571 *conn->initialHeaderCipher,
2572 getVersion(*conn),
2573 conn->transportSettings.writeConnectionDataPacketsLimit);
2574 EXPECT_FALSE(conn->pendingEvents.anyProbePackets());
2575
2576 conn->handshakeWriteCipher = createNoOpAead();
2577 conn->handshakeWriteHeaderCipher = createNoOpHeaderCipher();
2578 conn->pendingEvents.numProbePackets[PacketNumberSpace::Handshake] = 2;
2579 writeCryptoAndAckDataToSocket(
2580 *rawSocket,
2581 *conn,
2582 *conn->clientConnectionId,
2583 *conn->serverConnectionId,
2584 LongHeader::Types::Handshake,
2585 *conn->handshakeWriteCipher,
2586 *conn->handshakeWriteHeaderCipher,
2587 getVersion(*conn),
2588 conn->transportSettings.writeConnectionDataPacketsLimit);
2589 EXPECT_FALSE(conn->pendingEvents.anyProbePackets());
2590
2591 conn->oneRttWriteCipher = createNoOpAead();
2592 conn->oneRttWriteHeaderCipher = createNoOpHeaderCipher();
2593 conn->pendingEvents.numProbePackets[PacketNumberSpace::AppData] = 2;
2594 writeQuicDataToSocket(
2595 *rawSocket,
2596 *conn,
2597 *conn->clientConnectionId,
2598 *conn->serverConnectionId,
2599 *conn->oneRttWriteCipher,
2600 *conn->oneRttWriteHeaderCipher,
2601 getVersion(*conn),
2602 conn->transportSettings.writeConnectionDataPacketsLimit);
2603 EXPECT_FALSE(conn->pendingEvents.anyProbePackets());
2604 }
2605
TEST_F(QuicTransportFunctionsTest,WritePureAckWhenNoWritableBytes)2606 TEST_F(QuicTransportFunctionsTest, WritePureAckWhenNoWritableBytes) {
2607 auto conn = createConn();
2608 auto mockCongestionController =
2609 std::make_unique<NiceMock<MockCongestionController>>();
2610 auto rawCongestionController = mockCongestionController.get();
2611 conn->congestionController = std::move(mockCongestionController);
2612
2613 EventBase evb;
2614 auto socket =
2615 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
2616 auto rawSocket = socket.get();
2617
2618 auto stream1 = conn->streamManager->createNextBidirectionalStream().value();
2619 auto buf = IOBuf::copyBuffer("0123456789012");
2620 writeDataToQuicStream(*stream1, buf->clone(), true);
2621
2622 addAckStatesWithCurrentTimestamps(conn->ackStates.appDataAckState, 0, 100);
2623 conn->ackStates.appDataAckState.needsToSendAckImmediately = true;
2624 conn->ackStates.appDataAckState.largestAckScheduled = 50;
2625
2626 EXPECT_CALL(*rawCongestionController, getWritableBytes())
2627 .WillRepeatedly(Return(0));
2628
2629 EXPECT_CALL(*rawSocket, write(_, _))
2630 .WillRepeatedly(Invoke([&](const SocketAddress&,
2631 const std::unique_ptr<folly::IOBuf>& iobuf) {
2632 EXPECT_LE(iobuf->computeChainDataLength(), 30);
2633 return iobuf->computeChainDataLength();
2634 }));
2635 EXPECT_CALL(*rawCongestionController, onPacketSent(_)).Times(0);
2636 auto res = writeQuicDataToSocket(
2637 *rawSocket,
2638 *conn,
2639 *conn->clientConnectionId,
2640 *conn->serverConnectionId,
2641 *aead,
2642 *headerCipher,
2643 getVersion(*conn),
2644 conn->transportSettings.writeConnectionDataPacketsLimit);
2645 EXPECT_GT(res.packetsWritten, 0);
2646 EXPECT_EQ(0, conn->outstandings.packets.size());
2647 }
2648
TEST_F(QuicTransportFunctionsTest,ShouldWriteDataTest)2649 TEST_F(QuicTransportFunctionsTest, ShouldWriteDataTest) {
2650 auto conn = createConn();
2651
2652 auto mockCongestionController =
2653 std::make_unique<NiceMock<MockCongestionController>>();
2654 auto rawCongestionController = mockCongestionController.get();
2655 EXPECT_CALL(*rawCongestionController, getWritableBytes())
2656 .WillRepeatedly(Return(1500));
2657 conn->congestionController = std::move(mockCongestionController);
2658
2659 EventBase evb;
2660 auto socket =
2661 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
2662 auto rawSocket = socket.get();
2663
2664 // Pure acks without an oneRttCipher
2665 CHECK(!conn->oneRttWriteCipher);
2666 conn->ackStates.appDataAckState.needsToSendAckImmediately = true;
2667 addAckStatesWithCurrentTimestamps(conn->ackStates.appDataAckState, 1, 20);
2668 EXPECT_EQ(WriteDataReason::NO_WRITE, shouldWriteData(*conn));
2669
2670 conn->oneRttWriteCipher = test::createNoOpAead();
2671 EXPECT_CALL(*transportInfoCb_, onCwndBlocked()).Times(0);
2672 EXPECT_NE(WriteDataReason::NO_WRITE, shouldWriteData(*conn));
2673
2674 auto stream1 = conn->streamManager->createNextBidirectionalStream().value();
2675 auto buf = IOBuf::copyBuffer("0123456789");
2676 writeDataToQuicStream(*stream1, buf->clone(), false);
2677 EXPECT_NE(WriteDataReason::NO_WRITE, shouldWriteData(*conn));
2678
2679 writeQuicDataToSocket(
2680 *rawSocket,
2681 *conn,
2682 *conn->clientConnectionId,
2683 *conn->serverConnectionId,
2684 *aead,
2685 *headerCipher,
2686 getVersion(*conn),
2687 conn->transportSettings.writeConnectionDataPacketsLimit);
2688 EXPECT_EQ(WriteDataReason::NO_WRITE, shouldWriteData(*conn));
2689
2690 // Congestion control
2691 EXPECT_CALL(*rawCongestionController, getWritableBytes())
2692 .WillRepeatedly(Return(0));
2693 EXPECT_CALL(*transportInfoCb_, onCwndBlocked());
2694 writeDataToQuicStream(*stream1, buf->clone(), true);
2695 EXPECT_EQ(WriteDataReason::NO_WRITE, shouldWriteData(*conn));
2696
2697 EXPECT_CALL(*transportInfoCb_, onCwndBlocked());
2698 writeQuicDataToSocket(
2699 *rawSocket,
2700 *conn,
2701 *conn->clientConnectionId,
2702 *conn->serverConnectionId,
2703 *aead,
2704 *headerCipher,
2705 getVersion(*conn),
2706 conn->transportSettings.writeConnectionDataPacketsLimit);
2707 EXPECT_EQ(WriteDataReason::NO_WRITE, shouldWriteData(*conn));
2708 }
2709
TEST_F(QuicTransportFunctionsTest,ShouldWriteDataTestDuringPathValidation)2710 TEST_F(QuicTransportFunctionsTest, ShouldWriteDataTestDuringPathValidation) {
2711 auto conn = createConn();
2712
2713 // Create the CC.
2714 auto mockCongestionController =
2715 std::make_unique<NiceMock<MockCongestionController>>();
2716 auto rawCongestionController = mockCongestionController.get();
2717 conn->congestionController = std::move(mockCongestionController);
2718 conn->oneRttWriteCipher = test::createNoOpAead();
2719
2720 // Create an outstandingPathValidation + limiter so this will be applied.
2721 auto pathValidationLimiter = std::make_unique<MockPendingPathRateLimiter>();
2722 MockPendingPathRateLimiter* rawLimiter = pathValidationLimiter.get();
2723 conn->pathValidationLimiter = std::move(pathValidationLimiter);
2724 conn->outstandingPathValidation = PathChallengeFrame(1000);
2725
2726 // Have stream data queued up during the test so there's something TO write.
2727 auto stream1 = conn->streamManager->createNextBidirectionalStream().value();
2728 auto buf = IOBuf::copyBuffer("0123456789");
2729 writeDataToQuicStream(*stream1, buf->clone(), false);
2730
2731 // Only case that we allow the write; both CC / PathLimiter have
2732 // writablebytes
2733 EXPECT_CALL(*rawCongestionController, getWritableBytes()).WillOnce(Return(1));
2734 EXPECT_CALL(*rawLimiter, currentCredit(_, _)).WillOnce(Return(1));
2735
2736 EXPECT_CALL(*transportInfoCb_, onCwndBlocked()).Times(0);
2737 EXPECT_NE(WriteDataReason::NO_WRITE, shouldWriteData(*conn));
2738
2739 // CC has writableBytes, but PathLimiter doesn't.
2740 EXPECT_CALL(*rawCongestionController, getWritableBytes()).WillOnce(Return(1));
2741 EXPECT_CALL(*rawLimiter, currentCredit(_, _)).WillOnce(Return(0));
2742
2743 EXPECT_CALL(*transportInfoCb_, onCwndBlocked());
2744 EXPECT_EQ(WriteDataReason::NO_WRITE, shouldWriteData(*conn));
2745
2746 // PathLimiter has writableBytes, CC doesn't
2747 EXPECT_CALL(*rawCongestionController, getWritableBytes()).WillOnce(Return(0));
2748 EXPECT_CALL(*rawLimiter, currentCredit(_, _)).WillOnce(Return(1));
2749
2750 EXPECT_CALL(*transportInfoCb_, onCwndBlocked());
2751 EXPECT_EQ(WriteDataReason::NO_WRITE, shouldWriteData(*conn));
2752
2753 // Neither PathLimiter or CC have writablebytes
2754 EXPECT_CALL(*rawCongestionController, getWritableBytes()).WillOnce(Return(0));
2755 EXPECT_CALL(*rawLimiter, currentCredit(_, _)).WillOnce(Return(0));
2756
2757 EXPECT_CALL(*transportInfoCb_, onCwndBlocked());
2758 EXPECT_EQ(WriteDataReason::NO_WRITE, shouldWriteData(*conn));
2759 }
2760
TEST_F(QuicTransportFunctionsTest,ShouldWriteStreamsNoCipher)2761 TEST_F(QuicTransportFunctionsTest, ShouldWriteStreamsNoCipher) {
2762 auto conn = createConn();
2763 auto mockCongestionController =
2764 std::make_unique<NiceMock<MockCongestionController>>();
2765 auto rawCongestionController = mockCongestionController.get();
2766 EXPECT_CALL(*rawCongestionController, getWritableBytes())
2767 .WillRepeatedly(Return(1500));
2768 conn->congestionController = std::move(mockCongestionController);
2769
2770 auto stream1 = conn->streamManager->createNextBidirectionalStream().value();
2771 auto buf = IOBuf::copyBuffer("0123456789");
2772 writeDataToQuicStream(*stream1, buf->clone(), false);
2773 EXPECT_EQ(WriteDataReason::NO_WRITE, shouldWriteData(*conn));
2774 }
2775
TEST_F(QuicTransportFunctionsTest,ShouldWritePureAcksNoCipher)2776 TEST_F(QuicTransportFunctionsTest, ShouldWritePureAcksNoCipher) {
2777 auto conn = createConn();
2778 auto mockCongestionController =
2779 std::make_unique<NiceMock<MockCongestionController>>();
2780 auto rawCongestionController = mockCongestionController.get();
2781 EXPECT_CALL(*rawCongestionController, getWritableBytes())
2782 .WillRepeatedly(Return(1500));
2783 conn->congestionController = std::move(mockCongestionController);
2784
2785 conn->ackStates.appDataAckState.needsToSendAckImmediately = true;
2786 addAckStatesWithCurrentTimestamps(conn->ackStates.appDataAckState, 1, 20);
2787 EXPECT_EQ(WriteDataReason::NO_WRITE, shouldWriteData(*conn));
2788 }
2789
TEST_F(QuicTransportFunctionsTest,ShouldWriteDataNoConnFlowControl)2790 TEST_F(QuicTransportFunctionsTest, ShouldWriteDataNoConnFlowControl) {
2791 auto conn = createConn();
2792 conn->oneRttWriteCipher = test::createNoOpAead();
2793 auto mockCongestionController =
2794 std::make_unique<NiceMock<MockCongestionController>>();
2795 auto rawCongestionController = mockCongestionController.get();
2796 EXPECT_CALL(*rawCongestionController, getWritableBytes())
2797 .WillRepeatedly(Return(1500));
2798 auto stream1 = conn->streamManager->createNextBidirectionalStream().value();
2799 auto buf = IOBuf::copyBuffer("0123456789");
2800 writeDataToQuicStream(*stream1, buf->clone(), false);
2801 EXPECT_NE(WriteDataReason::NO_WRITE, shouldWriteData(*conn));
2802 // Artificially limit the connection flow control.
2803 conn->flowControlState.peerAdvertisedMaxOffset = 0;
2804 EXPECT_EQ(WriteDataReason::NO_WRITE, shouldWriteData(*conn));
2805 }
2806
TEST_F(QuicTransportFunctionsTest,HasAckDataToWriteCipherAndAckStateMatch)2807 TEST_F(QuicTransportFunctionsTest, HasAckDataToWriteCipherAndAckStateMatch) {
2808 auto conn = createConn();
2809 EXPECT_FALSE(hasAckDataToWrite(*conn));
2810 conn->initialWriteCipher = test::createNoOpAead();
2811 EXPECT_FALSE(hasAckDataToWrite(*conn));
2812 conn->ackStates.appDataAckState.needsToSendAckImmediately = true;
2813 conn->ackStates.appDataAckState.acks.insert(0, 100);
2814 EXPECT_FALSE(hasAckDataToWrite(*conn));
2815 conn->ackStates.initialAckState.needsToSendAckImmediately = true;
2816 conn->ackStates.initialAckState.acks.insert(0, 100);
2817 EXPECT_TRUE(hasAckDataToWrite(*conn));
2818 }
2819
TEST_F(QuicTransportFunctionsTest,HasAckDataToWriteNoImmediateAcks)2820 TEST_F(QuicTransportFunctionsTest, HasAckDataToWriteNoImmediateAcks) {
2821 auto conn = createConn();
2822 conn->oneRttWriteCipher = test::createNoOpAead();
2823 conn->ackStates.appDataAckState.acks.insert(0, 100);
2824 conn->ackStates.appDataAckState.needsToSendAckImmediately = false;
2825 EXPECT_FALSE(hasAckDataToWrite(*conn));
2826 conn->ackStates.appDataAckState.needsToSendAckImmediately = true;
2827 EXPECT_TRUE(hasAckDataToWrite(*conn));
2828 }
2829
TEST_F(QuicTransportFunctionsTest,HasAckDataToWriteNoAcksScheduled)2830 TEST_F(QuicTransportFunctionsTest, HasAckDataToWriteNoAcksScheduled) {
2831 auto conn = createConn();
2832 conn->oneRttWriteCipher = test::createNoOpAead();
2833 conn->ackStates.initialAckState.needsToSendAckImmediately = true;
2834 EXPECT_FALSE(hasAckDataToWrite(*conn));
2835 }
2836
TEST_F(QuicTransportFunctionsTest,HasAckDataToWrite)2837 TEST_F(QuicTransportFunctionsTest, HasAckDataToWrite) {
2838 auto conn = createConn();
2839 conn->oneRttWriteCipher = test::createNoOpAead();
2840 conn->ackStates.initialAckState.needsToSendAckImmediately = true;
2841 conn->ackStates.initialAckState.acks.insert(0);
2842 EXPECT_TRUE(hasAckDataToWrite(*conn));
2843 }
2844
TEST_F(QuicTransportFunctionsTest,HasAckDataToWriteMismatch)2845 TEST_F(QuicTransportFunctionsTest, HasAckDataToWriteMismatch) {
2846 // When one ack space has needsToSendAckImmediately = true and another has
2847 // hasAckToSchedule = true, but no ack space has both of them to true, we
2848 // should not send.
2849 auto conn = createConn();
2850 EXPECT_FALSE(hasAckDataToWrite(*conn));
2851 conn->ackStates.initialAckState.needsToSendAckImmediately = true;
2852 EXPECT_FALSE(hasAckDataToWrite(*conn));
2853 conn->ackStates.handshakeAckState.acks.insert(0, 10);
2854 conn->handshakeWriteCipher = test::createNoOpAead();
2855 EXPECT_FALSE(hasAckDataToWrite(*conn));
2856 }
2857
TEST_F(QuicTransportFunctionsTest,HasCryptoDataToWrite)2858 TEST_F(QuicTransportFunctionsTest, HasCryptoDataToWrite) {
2859 auto conn = createConn();
2860 conn->cryptoState->initialStream.lossBuffer.emplace_back(
2861 folly::IOBuf::copyBuffer("Grab your coat and get your hat"), 0, false);
2862 EXPECT_EQ(WriteDataReason::CRYPTO_STREAM, hasNonAckDataToWrite(*conn));
2863 conn->initialWriteCipher.reset();
2864 EXPECT_EQ(WriteDataReason::NO_WRITE, hasNonAckDataToWrite(*conn));
2865 }
2866
TEST_F(QuicTransportFunctionsTest,HasControlFramesToWrite)2867 TEST_F(QuicTransportFunctionsTest, HasControlFramesToWrite) {
2868 auto conn = createConn();
2869 conn->streamManager->queueBlocked(1, 100);
2870 EXPECT_EQ(WriteDataReason::NO_WRITE, hasNonAckDataToWrite(*conn));
2871
2872 conn->oneRttWriteCipher = test::createNoOpAead();
2873 EXPECT_EQ(WriteDataReason::BLOCKED, hasNonAckDataToWrite(*conn));
2874 }
2875
TEST_F(QuicTransportFunctionsTest,FlowControlBlocked)2876 TEST_F(QuicTransportFunctionsTest, FlowControlBlocked) {
2877 auto conn = createConn();
2878 conn->flowControlState.peerAdvertisedMaxOffset = 1000;
2879 conn->flowControlState.sumCurWriteOffset = 1000;
2880 EXPECT_EQ(WriteDataReason::NO_WRITE, hasNonAckDataToWrite(*conn));
2881 }
2882
TEST_F(QuicTransportFunctionsTest,HasAppDataToWrite)2883 TEST_F(QuicTransportFunctionsTest, HasAppDataToWrite) {
2884 auto conn = createConn();
2885 conn->flowControlState.peerAdvertisedMaxOffset = 1000;
2886 conn->flowControlState.sumCurWriteOffset = 800;
2887 QuicStreamState stream(0, *conn);
2888 writeDataToQuicStream(stream, folly::IOBuf::copyBuffer("I'm a devil"), true);
2889 conn->streamManager->addWritable(stream);
2890 EXPECT_EQ(WriteDataReason::NO_WRITE, hasNonAckDataToWrite(*conn));
2891
2892 conn->oneRttWriteCipher = test::createNoOpAead();
2893 EXPECT_EQ(WriteDataReason::STREAM, hasNonAckDataToWrite(*conn));
2894 }
2895
TEST_F(QuicTransportFunctionsTest,HasDatagramsToWrite)2896 TEST_F(QuicTransportFunctionsTest, HasDatagramsToWrite) {
2897 auto conn = createConn();
2898 conn->oneRttWriteCipher = test::createNoOpAead();
2899 EXPECT_EQ(WriteDataReason::NO_WRITE, hasNonAckDataToWrite(*conn));
2900 conn->datagramState.writeBuffer.emplace_back(
2901 folly::IOBuf::copyBuffer("I'm an unreliable Datagram"));
2902 EXPECT_EQ(WriteDataReason::DATAGRAM, hasNonAckDataToWrite(*conn));
2903 }
2904
TEST_F(QuicTransportFunctionsTest,UpdateConnectionCloneCounterAppData)2905 TEST_F(QuicTransportFunctionsTest, UpdateConnectionCloneCounterAppData) {
2906 auto conn = createConn();
2907 ASSERT_EQ(
2908 0, conn->outstandings.clonedPacketCount[PacketNumberSpace::AppData]);
2909 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
2910 auto connWindowUpdate =
2911 MaxDataFrame(conn->flowControlState.advertisedMaxOffset);
2912 conn->pendingEvents.connWindowUpdate = true;
2913 packet.packet.frames.emplace_back(connWindowUpdate);
2914 PacketEvent packetEvent(PacketNumberSpace::AppData, 100);
2915 conn->outstandings.packetEvents.insert(packetEvent);
2916 updateConnection(
2917 *conn,
2918 packetEvent,
2919 packet.packet,
2920 TimePoint(),
2921 123,
2922 100,
2923 false /* isDSRPacket */);
2924 EXPECT_EQ(
2925 0, conn->outstandings.clonedPacketCount[PacketNumberSpace::Initial]);
2926 EXPECT_EQ(
2927 0, conn->outstandings.clonedPacketCount[PacketNumberSpace::Handshake]);
2928 EXPECT_EQ(
2929 1, conn->outstandings.clonedPacketCount[PacketNumberSpace::AppData]);
2930 }
2931
TEST_F(QuicTransportFunctionsTest,UpdateConnectionCloneCounterHandshake)2932 TEST_F(QuicTransportFunctionsTest, UpdateConnectionCloneCounterHandshake) {
2933 auto conn = createConn();
2934 ASSERT_EQ(
2935 0, conn->outstandings.clonedPacketCount[PacketNumberSpace::Handshake]);
2936 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
2937 auto connWindowUpdate =
2938 MaxDataFrame(conn->flowControlState.advertisedMaxOffset);
2939 conn->pendingEvents.connWindowUpdate = true;
2940 packet.packet.frames.emplace_back(connWindowUpdate);
2941 PacketEvent packetEvent(PacketNumberSpace::AppData, 100);
2942 conn->outstandings.packetEvents.insert(packetEvent);
2943 updateConnection(
2944 *conn,
2945 packetEvent,
2946 packet.packet,
2947 TimePoint(),
2948 123,
2949 123,
2950 false /* isDSRPacket */);
2951 EXPECT_EQ(
2952 0, conn->outstandings.clonedPacketCount[PacketNumberSpace::Initial]);
2953 EXPECT_EQ(
2954 1, conn->outstandings.clonedPacketCount[PacketNumberSpace::Handshake]);
2955 EXPECT_EQ(
2956 0, conn->outstandings.clonedPacketCount[PacketNumberSpace::AppData]);
2957 }
2958
TEST_F(QuicTransportFunctionsTest,UpdateConnectionCloneCounterInitial)2959 TEST_F(QuicTransportFunctionsTest, UpdateConnectionCloneCounterInitial) {
2960 auto conn = createConn();
2961 ASSERT_EQ(
2962 0, conn->outstandings.clonedPacketCount[PacketNumberSpace::Initial]);
2963 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Initial);
2964 auto connWindowUpdate =
2965 MaxDataFrame(conn->flowControlState.advertisedMaxOffset);
2966 conn->pendingEvents.connWindowUpdate = true;
2967 packet.packet.frames.emplace_back(connWindowUpdate);
2968 PacketEvent packetEvent(PacketNumberSpace::AppData, 100);
2969 conn->outstandings.packetEvents.insert(packetEvent);
2970 updateConnection(
2971 *conn,
2972 packetEvent,
2973 packet.packet,
2974 TimePoint(),
2975 123,
2976 123,
2977 false /* isDSRPacket */);
2978 EXPECT_EQ(
2979 1, conn->outstandings.clonedPacketCount[PacketNumberSpace::Initial]);
2980 EXPECT_EQ(
2981 0, conn->outstandings.clonedPacketCount[PacketNumberSpace::Handshake]);
2982 EXPECT_EQ(
2983 0, conn->outstandings.clonedPacketCount[PacketNumberSpace::AppData]);
2984 }
2985
TEST_F(QuicTransportFunctionsTest,ClearBlockedFromPendingEvents)2986 TEST_F(QuicTransportFunctionsTest, ClearBlockedFromPendingEvents) {
2987 auto conn = createConn();
2988 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
2989 auto stream = conn->streamManager->createNextBidirectionalStream().value();
2990 StreamDataBlockedFrame blockedFrame(stream->id, 1000);
2991 packet.packet.frames.push_back(blockedFrame);
2992 conn->streamManager->queueBlocked(stream->id, 1000);
2993 updateConnection(
2994 *conn,
2995 folly::none,
2996 packet.packet,
2997 TimePoint(),
2998 getEncodedSize(packet),
2999 getEncodedBodySize(packet),
3000 false /* isDSRPacket */);
3001 EXPECT_FALSE(conn->streamManager->hasBlocked());
3002 EXPECT_FALSE(conn->outstandings.packets.empty());
3003 EXPECT_EQ(0, conn->outstandings.numClonedPackets());
3004 }
3005
TEST_F(QuicTransportFunctionsTest,ClonedBlocked)3006 TEST_F(QuicTransportFunctionsTest, ClonedBlocked) {
3007 auto conn = createConn();
3008 PacketEvent packetEvent(
3009 PacketNumberSpace::AppData,
3010 conn->ackStates.appDataAckState.nextPacketNum);
3011 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
3012 auto stream = conn->streamManager->createNextBidirectionalStream().value();
3013 StreamDataBlockedFrame blockedFrame(stream->id, 1000);
3014 packet.packet.frames.emplace_back(blockedFrame);
3015 conn->outstandings.packetEvents.insert(packetEvent);
3016 // This shall not crash
3017 updateConnection(
3018 *conn,
3019 packetEvent,
3020 packet.packet,
3021 TimePoint(),
3022 getEncodedSize(packet),
3023 getEncodedBodySize(packet),
3024 false /* isDSRPacket */);
3025 EXPECT_FALSE(conn->outstandings.packets.empty());
3026 EXPECT_EQ(
3027 1, conn->outstandings.clonedPacketCount[PacketNumberSpace::AppData]);
3028 }
3029
TEST_F(QuicTransportFunctionsTest,TwoConnWindowUpdateWillCrash)3030 TEST_F(QuicTransportFunctionsTest, TwoConnWindowUpdateWillCrash) {
3031 auto conn = createConn();
3032 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
3033 MaxDataFrame connWindowUpdate(
3034 1000 + conn->flowControlState.advertisedMaxOffset);
3035 packet.packet.frames.emplace_back(connWindowUpdate);
3036 packet.packet.frames.emplace_back(connWindowUpdate);
3037 conn->pendingEvents.connWindowUpdate = true;
3038 EXPECT_DEATH(
3039 updateConnection(
3040 *conn,
3041 folly::none,
3042 packet.packet,
3043 TimePoint(),
3044 getEncodedSize(packet),
3045 getEncodedBodySize(packet),
3046 false /* isDSRPacket */),
3047 ".*Send more than one connection window update.*");
3048 }
3049
TEST_F(QuicTransportFunctionsTest,WriteStreamFrameIsNotPureAck)3050 TEST_F(QuicTransportFunctionsTest, WriteStreamFrameIsNotPureAck) {
3051 auto conn = createConn();
3052 auto stream = conn->streamManager->createNextBidirectionalStream().value();
3053 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
3054 writeDataToQuicStream(
3055 *stream, folly::IOBuf::copyBuffer("I feel like a million bucks."), true);
3056 WriteStreamFrame writeStreamFrame(stream->id, 0, 5, false);
3057 packet.packet.frames.push_back(std::move(writeStreamFrame));
3058 updateConnection(
3059 *conn,
3060 folly::none,
3061 packet.packet,
3062 TimePoint(),
3063 getEncodedSize(packet),
3064 getEncodedBodySize(packet),
3065 false /* isDSRPacket */);
3066 EXPECT_FALSE(conn->outstandings.packets.empty());
3067 }
3068
TEST_F(QuicTransportFunctionsTest,ClearRstFromPendingEvents)3069 TEST_F(QuicTransportFunctionsTest, ClearRstFromPendingEvents) {
3070 auto conn = createConn();
3071 auto stream = conn->streamManager->createNextBidirectionalStream().value();
3072 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
3073 RstStreamFrame rstStreamFrame(
3074 stream->id, GenericApplicationErrorCode::UNKNOWN, 0);
3075 packet.packet.frames.push_back(rstStreamFrame);
3076 conn->pendingEvents.resets.emplace(stream->id, rstStreamFrame);
3077 updateConnection(
3078 *conn,
3079 folly::none,
3080 packet.packet,
3081 TimePoint(),
3082 getEncodedSize(packet),
3083 getEncodedBodySize(packet),
3084 false /* isDSRPacket */);
3085 EXPECT_TRUE(conn->pendingEvents.resets.empty());
3086 EXPECT_FALSE(conn->outstandings.packets.empty());
3087 EXPECT_EQ(0, conn->outstandings.numClonedPackets());
3088 }
3089
TEST_F(QuicTransportFunctionsTest,ClonedRst)3090 TEST_F(QuicTransportFunctionsTest, ClonedRst) {
3091 auto conn = createConn();
3092 PacketEvent packetEvent(
3093 PacketNumberSpace::AppData,
3094 conn->ackStates.appDataAckState.nextPacketNum);
3095 auto stream = conn->streamManager->createNextBidirectionalStream().value();
3096 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
3097 RstStreamFrame rstStreamFrame(
3098 stream->id, GenericApplicationErrorCode::UNKNOWN, 0);
3099 packet.packet.frames.emplace_back(std::move(rstStreamFrame));
3100 conn->outstandings.packetEvents.insert(packetEvent);
3101 // This shall not crash
3102 updateConnection(
3103 *conn,
3104 packetEvent,
3105 packet.packet,
3106 TimePoint(),
3107 getEncodedSize(packet),
3108 getEncodedBodySize(packet),
3109 false /* isDSRPacket */);
3110 EXPECT_FALSE(conn->outstandings.packets.empty());
3111 EXPECT_EQ(1, conn->outstandings.numClonedPackets());
3112 }
3113
TEST_F(QuicTransportFunctionsTest,TotalBytesSentUpdate)3114 TEST_F(QuicTransportFunctionsTest, TotalBytesSentUpdate) {
3115 auto conn = createConn();
3116 conn->lossState.totalBytesSent = 1234;
3117 conn->lossState.totalBodyBytesSent = 1000;
3118 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
3119 updateConnection(
3120 *conn,
3121 folly::none,
3122 packet.packet,
3123 TimePoint{},
3124 4321,
3125 4000,
3126 false /* isDSRPacket */);
3127 EXPECT_EQ(5555, conn->lossState.totalBytesSent);
3128 EXPECT_EQ(5000, conn->lossState.totalBodyBytesSent);
3129 }
3130
TEST_F(QuicTransportFunctionsTest,TotalPacketsSentUpdate)3131 TEST_F(QuicTransportFunctionsTest, TotalPacketsSentUpdate) {
3132 const auto startTotalPacketsSent = 1234;
3133 auto conn = createConn();
3134 conn->lossState.totalPacketsSent = startTotalPacketsSent;
3135 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
3136 updateConnection(
3137 *conn,
3138 folly::none,
3139 packet.packet,
3140 TimePoint{},
3141 4321,
3142 0,
3143 false /* isDSRPacket */);
3144 EXPECT_EQ(startTotalPacketsSent + 1, conn->lossState.totalPacketsSent);
3145 }
3146
TEST_F(QuicTransportFunctionsTest,TimeoutBasedRetxCountUpdate)3147 TEST_F(QuicTransportFunctionsTest, TimeoutBasedRetxCountUpdate) {
3148 auto conn = createConn();
3149 auto stream = conn->streamManager->createNextBidirectionalStream().value();
3150 conn->lossState.timeoutBasedRtxCount = 246;
3151 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
3152 RstStreamFrame rstStreamFrame(
3153 stream->id, GenericApplicationErrorCode::UNKNOWN, 0);
3154 packet.packet.frames.push_back(rstStreamFrame);
3155 PacketEvent packetEvent(PacketNumberSpace::AppData, 100);
3156 conn->outstandings.packetEvents.insert(packetEvent);
3157 updateConnection(
3158 *conn,
3159 packetEvent,
3160 packet.packet,
3161 TimePoint(),
3162 0,
3163 0,
3164 false /* isDSRPacket */);
3165 EXPECT_EQ(247, conn->lossState.timeoutBasedRtxCount);
3166 }
3167
TEST_F(QuicTransportFunctionsTest,WriteLimitBytRttFraction)3168 TEST_F(QuicTransportFunctionsTest, WriteLimitBytRttFraction) {
3169 auto conn = createConn();
3170 conn->lossState.srtt = 150ms;
3171 auto mockCongestionController =
3172 std::make_unique<NiceMock<MockCongestionController>>();
3173 auto rawCongestionController = mockCongestionController.get();
3174 conn->congestionController = std::move(mockCongestionController);
3175
3176 EventBase evb;
3177 auto socket =
3178 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
3179 auto rawSocket = socket.get();
3180
3181 auto stream1 = conn->streamManager->createNextBidirectionalStream().value();
3182 auto buf = buildRandomInputData(2048 * 1024);
3183 writeDataToQuicStream(*stream1, buf->clone(), true);
3184
3185 EXPECT_CALL(*rawSocket, write(_, _)).WillRepeatedly(Return(1));
3186 EXPECT_CALL(*rawCongestionController, getWritableBytes())
3187 .WillRepeatedly(Return(50));
3188 auto res = writeQuicDataToSocket(
3189 *rawSocket,
3190 *conn,
3191 *conn->clientConnectionId,
3192 *conn->serverConnectionId,
3193 *aead,
3194 *headerCipher,
3195 getVersion(*conn),
3196 500 /* packetLimit */);
3197
3198 EXPECT_GT(500, res.packetsWritten);
3199 EXPECT_EQ(res.probesWritten, 0);
3200 }
3201
TEST_F(QuicTransportFunctionsTest,CongestionControlWritableBytesRoundUp)3202 TEST_F(QuicTransportFunctionsTest, CongestionControlWritableBytesRoundUp) {
3203 auto conn = createConn();
3204 conn->udpSendPacketLen = 2000;
3205 auto mockCongestionController =
3206 std::make_unique<NiceMock<MockCongestionController>>();
3207 auto rawCongestionController = mockCongestionController.get();
3208 conn->congestionController = std::move(mockCongestionController);
3209
3210 EXPECT_CALL(*rawCongestionController, getWritableBytes()).WillOnce(Return(1));
3211 EXPECT_EQ(conn->udpSendPacketLen, congestionControlWritableBytes(*conn));
3212
3213 EXPECT_CALL(*rawCongestionController, getWritableBytes())
3214 .WillOnce(Return(1000));
3215 EXPECT_EQ(conn->udpSendPacketLen, congestionControlWritableBytes(*conn));
3216
3217 EXPECT_CALL(*rawCongestionController, getWritableBytes()).WillOnce(Return(0));
3218 EXPECT_EQ(0, congestionControlWritableBytes(*conn));
3219
3220 EXPECT_CALL(*rawCongestionController, getWritableBytes())
3221 .WillOnce(Return(2000));
3222 EXPECT_EQ(conn->udpSendPacketLen, congestionControlWritableBytes(*conn));
3223
3224 EXPECT_CALL(*rawCongestionController, getWritableBytes())
3225 .WillOnce(Return(2001));
3226 EXPECT_EQ(conn->udpSendPacketLen * 2, congestionControlWritableBytes(*conn));
3227 }
3228
TEST_F(QuicTransportFunctionsTest,HandshakeConfirmedDropCipher)3229 TEST_F(QuicTransportFunctionsTest, HandshakeConfirmedDropCipher) {
3230 auto conn = createConn();
3231 conn->readCodec = std::make_unique<QuicReadCodec>(QuicNodeType::Server);
3232 EventBase evb;
3233 auto socket =
3234 std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
3235 auto initialStream =
3236 getCryptoStream(*conn->cryptoState, EncryptionLevel::Initial);
3237 auto handshakeStream =
3238 getCryptoStream(*conn->cryptoState, EncryptionLevel::Handshake);
3239 writeDataToQuicStream(
3240 *initialStream, folly::IOBuf::copyBuffer("LittleRemedies"));
3241 writeDataToQuicStream(
3242 *handshakeStream,
3243 folly::IOBuf::copyBuffer("Where should I join the meeting"));
3244 ASSERT_NE(nullptr, conn->initialWriteCipher);
3245 conn->handshakeWriteCipher = createNoOpAead();
3246 conn->readCodec->setInitialReadCipher(createNoOpAead());
3247 conn->readCodec->setInitialHeaderCipher(createNoOpHeaderCipher());
3248 conn->readCodec->setHandshakeReadCipher(createNoOpAead());
3249 conn->readCodec->setHandshakeHeaderCipher(createNoOpHeaderCipher());
3250 conn->oneRttWriteCipher = createNoOpAead();
3251 conn->oneRttWriteHeaderCipher = createNoOpHeaderCipher();
3252 conn->readCodec->setOneRttReadCipher(createNoOpAead());
3253 conn->readCodec->setOneRttHeaderCipher(createNoOpHeaderCipher());
3254 writeCryptoDataProbesToSocketForTest(
3255 *socket,
3256 *conn,
3257 1,
3258 *aead,
3259 *headerCipher,
3260 getVersion(*conn),
3261 LongHeader::Types::Initial);
3262 writeCryptoDataProbesToSocketForTest(
3263 *socket,
3264 *conn,
3265 1,
3266 *aead,
3267 *headerCipher,
3268 getVersion(*conn),
3269 LongHeader::Types::Handshake);
3270 ASSERT_FALSE(initialStream->retransmissionBuffer.empty());
3271 ASSERT_FALSE(handshakeStream->retransmissionBuffer.empty());
3272 initialStream->insertIntoLossBuffer(std::make_unique<StreamBuffer>(
3273 folly::IOBuf::copyBuffer(
3274 "I don't see the dialup info in the meeting invite"),
3275 0,
3276 false));
3277 handshakeStream->insertIntoLossBuffer(std::make_unique<StreamBuffer>(
3278 folly::IOBuf::copyBuffer("Traffic Protocol Weekly Sync"), 0, false));
3279
3280 handshakeConfirmed(*conn);
3281 EXPECT_TRUE(initialStream->writeBuffer.empty());
3282 EXPECT_TRUE(initialStream->retransmissionBuffer.empty());
3283 EXPECT_TRUE(initialStream->lossBuffer.empty());
3284 EXPECT_TRUE(handshakeStream->writeBuffer.empty());
3285 EXPECT_TRUE(handshakeStream->retransmissionBuffer.empty());
3286 EXPECT_TRUE(handshakeStream->lossBuffer.empty());
3287 EXPECT_EQ(nullptr, conn->initialWriteCipher);
3288 EXPECT_EQ(nullptr, conn->handshakeWriteCipher);
3289 EXPECT_EQ(nullptr, conn->readCodec->getInitialCipher());
3290 EXPECT_EQ(nullptr, conn->readCodec->getInitialHeaderCipher());
3291 EXPECT_EQ(nullptr, conn->readCodec->getHandshakeReadCipher());
3292 EXPECT_EQ(nullptr, conn->readCodec->getHandshakeHeaderCipher());
3293 }
3294
TEST_F(QuicTransportFunctionsTest,ProbeWriteNewFunctionalFrames)3295 TEST_F(QuicTransportFunctionsTest, ProbeWriteNewFunctionalFrames) {
3296 auto conn = createConn();
3297 conn->udpSendPacketLen = 1200;
3298 EventBase evb;
3299 auto sock = std::make_unique<NiceMock<folly::test::MockAsyncUDPSocket>>(&evb);
3300 auto rawSocket = sock.get();
3301
3302 EXPECT_CALL(*rawSocket, write(_, _))
3303 .WillRepeatedly(Invoke([&](const SocketAddress&,
3304 const std::unique_ptr<folly::IOBuf>& iobuf) {
3305 return iobuf->computeChainDataLength();
3306 }));
3307
3308 auto stream = conn->streamManager->createNextBidirectionalStream().value();
3309 auto buf = folly::IOBuf::copyBuffer("Drug facts");
3310 writeDataToQuicStream(*stream, buf->clone(), true);
3311 writeQuicDataToSocket(
3312 *rawSocket,
3313 *conn,
3314 *conn->clientConnectionId,
3315 *conn->serverConnectionId,
3316 *aead,
3317 *headerCipher,
3318 getVersion(*conn),
3319 conn->transportSettings.writeConnectionDataPacketsLimit);
3320 ASSERT_EQ(1, stream->retransmissionBuffer.size());
3321
3322 conn->pendingEvents.numProbePackets[PacketNumberSpace::AppData] = 1;
3323 conn->flowControlState.windowSize *= 2;
3324 conn->flowControlState.timeOfLastFlowControlUpdate = Clock::now() - 20s;
3325 maybeSendConnWindowUpdate(*conn, Clock::now());
3326 writeQuicDataToSocket(
3327 *rawSocket,
3328 *conn,
3329 *conn->clientConnectionId,
3330 *conn->serverConnectionId,
3331 *aead,
3332 *headerCipher,
3333 getVersion(*conn),
3334 1 /* limit to 1 packet */);
3335 EXPECT_EQ(2, conn->outstandings.packets.size());
3336 EXPECT_EQ(1, conn->outstandings.packets[1].packet.frames.size());
3337 EXPECT_EQ(
3338 QuicWriteFrame::Type::MaxDataFrame,
3339 conn->outstandings.packets[1].packet.frames[0].type());
3340 }
3341
TEST_F(QuicTransportFunctionsTest,WriteWithInplaceBuilder)3342 TEST_F(QuicTransportFunctionsTest, WriteWithInplaceBuilder) {
3343 auto conn = createConn();
3344 conn->transportSettings.dataPathType = DataPathType::ContinuousMemory;
3345 auto simpleBufAccessor =
3346 std::make_unique<SimpleBufAccessor>(conn->udpSendPacketLen * 16);
3347 auto outputBuf = simpleBufAccessor->obtain();
3348 auto bufPtr = outputBuf.get();
3349 simpleBufAccessor->release(std::move(outputBuf));
3350 conn->bufAccessor = simpleBufAccessor.get();
3351 conn->transportSettings.batchingMode = QuicBatchingMode::BATCHING_MODE_GSO;
3352 EventBase evb;
3353 folly::test::MockAsyncUDPSocket mockSock(&evb);
3354 EXPECT_CALL(mockSock, getGSO()).WillRepeatedly(Return(true));
3355 auto stream = conn->streamManager->createNextBidirectionalStream().value();
3356 auto buf = folly::IOBuf::copyBuffer("Andante in C minor");
3357 writeDataToQuicStream(*stream, buf->clone(), true);
3358 EXPECT_CALL(mockSock, write(_, _))
3359 .Times(1)
3360 .WillOnce(Invoke([&](const SocketAddress&,
3361 const std::unique_ptr<folly::IOBuf>& sockBuf) {
3362 EXPECT_GT(bufPtr->length(), 0);
3363 EXPECT_GE(sockBuf->length(), buf->length());
3364 EXPECT_EQ(sockBuf.get(), bufPtr);
3365 EXPECT_TRUE(folly::IOBufEqualTo()(*sockBuf, *bufPtr));
3366 EXPECT_FALSE(sockBuf->isChained());
3367 return sockBuf->computeChainDataLength();
3368 }));
3369 writeQuicDataToSocket(
3370 mockSock,
3371 *conn,
3372 *conn->clientConnectionId,
3373 *conn->serverConnectionId,
3374 *aead,
3375 *headerCipher,
3376 getVersion(*conn),
3377 conn->transportSettings.writeConnectionDataPacketsLimit);
3378 EXPECT_EQ(0, bufPtr->length());
3379 EXPECT_EQ(0, bufPtr->headroom());
3380 }
3381
TEST_F(QuicTransportFunctionsTest,WriteWithInplaceBuilderRollbackBuf)3382 TEST_F(QuicTransportFunctionsTest, WriteWithInplaceBuilderRollbackBuf) {
3383 auto conn = createConn();
3384 conn->transportSettings.dataPathType = DataPathType::ContinuousMemory;
3385 auto simpleBufAccessor =
3386 std::make_unique<SimpleBufAccessor>(conn->udpSendPacketLen * 16);
3387 auto outputBuf = simpleBufAccessor->obtain();
3388 auto bufPtr = outputBuf.get();
3389 simpleBufAccessor->release(std::move(outputBuf));
3390 conn->bufAccessor = simpleBufAccessor.get();
3391 conn->transportSettings.batchingMode = QuicBatchingMode::BATCHING_MODE_GSO;
3392 EventBase evb;
3393 folly::test::MockAsyncUDPSocket mockSock(&evb);
3394 EXPECT_CALL(mockSock, getGSO()).WillRepeatedly(Return(true));
3395 EXPECT_CALL(mockSock, write(_, _)).Times(0);
3396 writeQuicDataToSocket(
3397 mockSock,
3398 *conn,
3399 *conn->clientConnectionId,
3400 *conn->serverConnectionId,
3401 *aead,
3402 *headerCipher,
3403 getVersion(*conn),
3404 conn->transportSettings.writeConnectionDataPacketsLimit);
3405 EXPECT_EQ(0, bufPtr->length());
3406 EXPECT_EQ(0, bufPtr->headroom());
3407 }
3408
TEST_F(QuicTransportFunctionsTest,WriteWithInplaceBuilderGSOMultiplePackets)3409 TEST_F(QuicTransportFunctionsTest, WriteWithInplaceBuilderGSOMultiplePackets) {
3410 auto conn = createConn();
3411 conn->transportSettings.dataPathType = DataPathType::ContinuousMemory;
3412 auto simpleBufAccessor =
3413 std::make_unique<SimpleBufAccessor>(conn->udpSendPacketLen * 16);
3414 auto outputBuf = simpleBufAccessor->obtain();
3415 auto bufPtr = outputBuf.get();
3416 simpleBufAccessor->release(std::move(outputBuf));
3417 conn->bufAccessor = simpleBufAccessor.get();
3418 conn->transportSettings.batchingMode = QuicBatchingMode::BATCHING_MODE_GSO;
3419 EventBase evb;
3420 folly::test::MockAsyncUDPSocket mockSock(&evb);
3421 EXPECT_CALL(mockSock, getGSO()).WillRepeatedly(Return(true));
3422 auto stream = conn->streamManager->createNextBidirectionalStream().value();
3423 auto buf = buildRandomInputData(conn->udpSendPacketLen * 10);
3424 writeDataToQuicStream(*stream, buf->clone(), true);
3425 EXPECT_CALL(mockSock, writeGSO(_, _, _))
3426 .Times(1)
3427 .WillOnce(Invoke([&](const folly::SocketAddress&,
3428 const std::unique_ptr<folly::IOBuf>& sockBuf,
3429 int gso) {
3430 EXPECT_LE(gso, conn->udpSendPacketLen);
3431 EXPECT_GT(bufPtr->length(), 0);
3432 EXPECT_EQ(sockBuf.get(), bufPtr);
3433 EXPECT_TRUE(folly::IOBufEqualTo()(*sockBuf, *bufPtr));
3434 EXPECT_FALSE(sockBuf->isChained());
3435 return sockBuf->length();
3436 }));
3437 writeQuicDataToSocket(
3438 mockSock,
3439 *conn,
3440 *conn->clientConnectionId,
3441 *conn->serverConnectionId,
3442 *aead,
3443 *headerCipher,
3444 getVersion(*conn),
3445 conn->transportSettings.writeConnectionDataPacketsLimit);
3446 EXPECT_EQ(0, bufPtr->length());
3447 EXPECT_EQ(0, bufPtr->headroom());
3448 }
3449
TEST_F(QuicTransportFunctionsTest,WriteProbingWithInplaceBuilder)3450 TEST_F(QuicTransportFunctionsTest, WriteProbingWithInplaceBuilder) {
3451 auto conn = createConn();
3452 conn->transportSettings.dataPathType = DataPathType::ContinuousMemory;
3453 conn->transportSettings.batchingMode = QuicBatchingMode::BATCHING_MODE_GSO;
3454 EventBase evb;
3455 folly::test::MockAsyncUDPSocket mockSock(&evb);
3456 EXPECT_CALL(mockSock, getGSO()).WillRepeatedly(Return(true));
3457
3458 SimpleBufAccessor bufAccessor(
3459 conn->udpSendPacketLen * conn->transportSettings.maxBatchSize);
3460 conn->bufAccessor = &bufAccessor;
3461 auto buf = bufAccessor.obtain();
3462 auto bufPtr = buf.get();
3463 bufAccessor.release(std::move(buf));
3464
3465 auto stream = conn->streamManager->createNextBidirectionalStream().value();
3466 auto inputBuf = buildRandomInputData(
3467 conn->udpSendPacketLen *
3468 conn->transportSettings.writeConnectionDataPacketsLimit);
3469 writeDataToQuicStream(*stream, inputBuf->clone(), true);
3470 EXPECT_CALL(mockSock, writeGSO(_, _, _))
3471 .Times(1)
3472 .WillOnce(Invoke([&](const folly::SocketAddress&,
3473 const std::unique_ptr<folly::IOBuf>& sockBuf,
3474 int gso) {
3475 EXPECT_LE(gso, conn->udpSendPacketLen);
3476 EXPECT_GE(
3477 bufPtr->length(),
3478 conn->udpSendPacketLen *
3479 conn->transportSettings.writeConnectionDataPacketsLimit);
3480 EXPECT_EQ(sockBuf.get(), bufPtr);
3481 EXPECT_TRUE(folly::IOBufEqualTo()(*sockBuf, *bufPtr));
3482 EXPECT_FALSE(sockBuf->isChained());
3483 return sockBuf->length();
3484 }));
3485 writeQuicDataToSocket(
3486 mockSock,
3487 *conn,
3488 *conn->clientConnectionId,
3489 *conn->serverConnectionId,
3490 *aead,
3491 *headerCipher,
3492 getVersion(*conn),
3493 conn->transportSettings.writeConnectionDataPacketsLimit + 1);
3494 ASSERT_EQ(0, bufPtr->length());
3495 ASSERT_EQ(0, bufPtr->headroom());
3496 EXPECT_GE(conn->outstandings.packets.size(), 5);
3497 // Make sure there no more new data to write:
3498 StreamFrameScheduler streamScheduler(*conn);
3499 ASSERT_FALSE(streamScheduler.hasPendingData());
3500
3501 // The first packet has be a full packet
3502 auto firstPacketSize =
3503 conn->outstandings.packets.front().metadata.encodedSize;
3504 auto outstandingPacketsCount = conn->outstandings.packets.size();
3505 ASSERT_EQ(firstPacketSize, conn->udpSendPacketLen);
3506 EXPECT_CALL(mockSock, write(_, _))
3507 .Times(1)
3508 .WillOnce(Invoke([&](const folly::SocketAddress&,
3509 const std::unique_ptr<folly::IOBuf>& buf) {
3510 EXPECT_FALSE(buf->isChained());
3511 EXPECT_EQ(buf->length(), firstPacketSize);
3512 return buf->length();
3513 }));
3514 writeProbingDataToSocketForTest(
3515 mockSock,
3516 *conn,
3517 1 /* probesToSend */,
3518 *aead,
3519 *headerCipher,
3520 getVersion(*conn));
3521 EXPECT_EQ(conn->outstandings.packets.size(), outstandingPacketsCount + 1);
3522 EXPECT_EQ(0, bufPtr->length());
3523 EXPECT_EQ(0, bufPtr->headroom());
3524
3525 // Clone again, this time 2 pacckets.
3526 EXPECT_CALL(mockSock, writeGSO(_, _, _))
3527 .Times(1)
3528 .WillOnce(Invoke([&](const folly::SocketAddress&,
3529 const std::unique_ptr<folly::IOBuf>& buf,
3530 int gso) {
3531 EXPECT_FALSE(buf->isChained());
3532 EXPECT_EQ(conn->udpSendPacketLen, gso);
3533 EXPECT_EQ(buf->length(), conn->udpSendPacketLen * 2);
3534 return buf->length();
3535 }));
3536 writeProbingDataToSocketForTest(
3537 mockSock,
3538 *conn,
3539 2 /* probesToSend */,
3540 *aead,
3541 *headerCipher,
3542 getVersion(*conn));
3543 EXPECT_EQ(0, bufPtr->length());
3544 EXPECT_EQ(0, bufPtr->headroom());
3545 EXPECT_EQ(conn->outstandings.packets.size(), outstandingPacketsCount + 3);
3546 }
3547
TEST_F(QuicTransportFunctionsTest,WriteD6DProbesWithInplaceBuilder)3548 TEST_F(QuicTransportFunctionsTest, WriteD6DProbesWithInplaceBuilder) {
3549 auto conn = createConn();
3550 conn->transportSettings.dataPathType = DataPathType::ContinuousMemory;
3551 conn->d6d.currentProbeSize = 1450;
3552 conn->pendingEvents.d6d.sendProbePacket = true;
3553 auto simpleBufAccessor =
3554 std::make_unique<SimpleBufAccessor>(kDefaultMaxUDPPayload * 16);
3555 auto outputBuf = simpleBufAccessor->obtain();
3556 auto bufPtr = outputBuf.get();
3557 simpleBufAccessor->release(std::move(outputBuf));
3558 conn->bufAccessor = simpleBufAccessor.get();
3559 conn->transportSettings.batchingMode = QuicBatchingMode::BATCHING_MODE_GSO;
3560 EventBase evb;
3561 folly::test::MockAsyncUDPSocket mockSock(&evb);
3562 EXPECT_CALL(mockSock, getGSO()).WillRepeatedly(Return(true));
3563 EXPECT_CALL(mockSock, write(_, _))
3564 .Times(1)
3565 .WillOnce(Invoke([&](const SocketAddress&,
3566 const std::unique_ptr<folly::IOBuf>& sockBuf) {
3567 EXPECT_EQ(sockBuf->length(), conn->d6d.currentProbeSize);
3568 EXPECT_EQ(sockBuf.get(), bufPtr);
3569 EXPECT_TRUE(folly::IOBufEqualTo()(*sockBuf, *bufPtr));
3570 EXPECT_FALSE(sockBuf->isChained());
3571 return sockBuf->computeChainDataLength();
3572 }));
3573 writeD6DProbeToSocket(
3574 mockSock,
3575 *conn,
3576 *conn->clientConnectionId,
3577 *conn->serverConnectionId,
3578 *aead,
3579 *headerCipher,
3580 getVersion(*conn));
3581 EXPECT_EQ(0, bufPtr->length());
3582 EXPECT_EQ(0, bufPtr->headroom());
3583 }
3584
TEST_F(QuicTransportFunctionsTest,UpdateConnectionWithBufferMeta)3585 TEST_F(QuicTransportFunctionsTest, UpdateConnectionWithBufferMeta) {
3586 auto conn = createConn();
3587 // Builds a fake packet to test with.
3588 auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
3589
3590 auto streamId =
3591 conn->streamManager->createNextBidirectionalStream().value()->id;
3592 auto stream = conn->streamManager->findStream(streamId);
3593 EXPECT_TRUE(stream->retransmissionBufMetas.empty());
3594 writeDataToQuicStream(
3595 *stream, IOBuf::copyBuffer("Wear a face mask please!"), false /* eof */);
3596 BufferMeta bufMeta(2000);
3597 writeBufMetaToQuicStream(*stream, bufMeta, true /* eof */);
3598 EXPECT_TRUE(stream->writeBufMeta.eof);
3599 EXPECT_EQ(2000, stream->writeBufMeta.length);
3600 auto bufMetaStartingOffset = stream->writeBufMeta.offset;
3601 WriteStreamFrame writeStreamFrame(
3602 streamId, bufMetaStartingOffset, 1000, false /* fin */);
3603 writeStreamFrame.fromBufMeta = true;
3604 packet.packet.frames.push_back(writeStreamFrame);
3605
3606 updateConnection(
3607 *conn,
3608 folly::none,
3609 packet.packet,
3610 TimePoint(),
3611 getEncodedSize(packet),
3612 getEncodedBodySize(packet),
3613 true /* dsr */);
3614 EXPECT_EQ(1000 + bufMetaStartingOffset, stream->writeBufMeta.offset);
3615 EXPECT_EQ(1000, stream->writeBufMeta.length);
3616 EXPECT_FALSE(stream->retransmissionBufMetas.empty());
3617 auto retxBufMetaIter =
3618 stream->retransmissionBufMetas.find(bufMetaStartingOffset);
3619 EXPECT_NE(retxBufMetaIter, stream->retransmissionBufMetas.end());
3620 EXPECT_EQ(bufMetaStartingOffset, retxBufMetaIter->second.offset);
3621 EXPECT_EQ(1000, retxBufMetaIter->second.length);
3622 EXPECT_FALSE(retxBufMetaIter->second.eof);
3623 EXPECT_TRUE(conn->outstandings.packets.back().isDSRPacket);
3624
3625 // Manually lose this packet:
3626 stream->lossBufMetas.push_back(retxBufMetaIter->second);
3627 stream->retransmissionBufMetas.erase(retxBufMetaIter);
3628 ASSERT_FALSE(stream->lossBufMetas.empty());
3629 ASSERT_TRUE(stream->retransmissionBufMetas.empty());
3630
3631 // Retransmit it:
3632 auto retxPacket = buildEmptyPacket(*conn, PacketNumberSpace::AppData);
3633 // Retx of the stream looks exactly the same
3634 retxPacket.packet.frames.push_back(writeStreamFrame);
3635 updateConnection(
3636 *conn,
3637 folly::none,
3638 retxPacket.packet,
3639 TimePoint(),
3640 getEncodedSize(retxPacket),
3641 getEncodedBodySize(packet),
3642 true /* dsr */);
3643 EXPECT_TRUE(stream->lossBufMetas.empty());
3644 retxBufMetaIter = stream->retransmissionBufMetas.find(bufMetaStartingOffset);
3645 EXPECT_NE(retxBufMetaIter, stream->retransmissionBufMetas.end());
3646 EXPECT_EQ(bufMetaStartingOffset, retxBufMetaIter->second.offset);
3647 EXPECT_EQ(1000, retxBufMetaIter->second.length);
3648 EXPECT_FALSE(retxBufMetaIter->second.eof);
3649 EXPECT_TRUE(conn->outstandings.packets.back().isDSRPacket);
3650 }
3651
3652 } // namespace test
3653 } // namespace quic
3654