mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-11-22 16:02:34 +03:00
Convert IntervalSet from throwing exceptions to using CHECKs with Expected error handling
Summary: This commit converts IntervalSet to use CHECKs instead of throwing exceptions and provides safe tryInsert methods that return quic::Expected for error handling. **Core Problem Solved:** IntervalSet was throwing `std::invalid_argument` exceptions in two scenarios: 1. When constructing an Interval with `start > end` 2. When interval bounds exceed the maximum allowed value This change eliminates exceptions in favor of CHECKs (for internal validation) and Expected-based error handling (for caller validation). **Implementation Details:** **1. IntervalSet Core Changes:** - Replaced `throw std::invalid_argument` with `CHECK_LE` in Interval constructor - Replaced `throw std::invalid_argument` with `CHECK_LE` in `insert(start, end)` - Added `IntervalSetError` enum for error classification - Added `folly::Expected` include **2. Safe API Layer:** - Added `tryInsert(interval)` method returning `Expected<Unit, IntervalSetError>` - Added `tryInsert(start, end)` method with pre-validation - Added `tryInsert(point)` method - Added static `Interval::tryCreate()` method for safe interval construction **3. Updated Code:** - **QuicWriteCodec.cpp**: Updated `fillFrameWithPacketReceiveTimestamps` to use `tryInsert` - Returns `QuicError` if interval validation fails - Maintains existing error handling patterns - **QuicTransportFunctions.cpp**: Updated `implicitAckCryptoStream` to use `tryInsert` - Logs errors and continues processing other packets - Robust error handling for crypto stream implicit acks Reviewed By: kvtsoy Differential Revision: D76792362 fbshipit-source-id: 5bd7c22e69a91d60cc41c603a1f2380893f4c8a0
This commit is contained in:
committed by
Facebook GitHub Bot
parent
8f8be8d5d0
commit
d3e8fe246a
@@ -2147,7 +2147,15 @@ void implicitAckCryptoStream(
|
|||||||
implicitAck.implicit = true;
|
implicitAck.implicit = true;
|
||||||
for (const auto& op : conn.outstandings.packets) {
|
for (const auto& op : conn.outstandings.packets) {
|
||||||
if (op.packet.header.getPacketNumberSpace() == packetNumSpace) {
|
if (op.packet.header.getPacketNumberSpace() == packetNumSpace) {
|
||||||
ackBlocks.insert(op.packet.header.getPacketSequenceNum());
|
auto insertResult =
|
||||||
|
ackBlocks.tryInsert(op.packet.header.getPacketSequenceNum());
|
||||||
|
if (insertResult.hasError()) {
|
||||||
|
LOG(ERROR) << "Failed to insert packet number into ack blocks: "
|
||||||
|
<< static_cast<int>(insertResult.error());
|
||||||
|
// Continue processing other packets - this shouldn't happen in normal
|
||||||
|
// operation
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ackBlocks.empty()) {
|
if (ackBlocks.empty()) {
|
||||||
|
|||||||
@@ -410,8 +410,13 @@ quic::Expected<void, QuicError> QuicClientTransportLite::processUdpPacketData(
|
|||||||
|
|
||||||
// Add the packet to the AckState associated with the packet number space.
|
// Add the packet to the AckState associated with the packet number space.
|
||||||
auto& ackState = getAckState(*conn_, pnSpace);
|
auto& ackState = getAckState(*conn_, pnSpace);
|
||||||
uint64_t distanceFromExpectedPacketNum =
|
auto addResult = addPacketToAckState(*conn_, ackState, packetNum, udpPacket);
|
||||||
addPacketToAckState(*conn_, ackState, packetNum, udpPacket);
|
if (!addResult.has_value()) {
|
||||||
|
return quic::make_unexpected(QuicError(
|
||||||
|
TransportErrorCode::INTERNAL_ERROR,
|
||||||
|
"Failed to add packet to ack state"));
|
||||||
|
}
|
||||||
|
uint64_t distanceFromExpectedPacketNum = addResult.value();
|
||||||
if (distanceFromExpectedPacketNum > 0) {
|
if (distanceFromExpectedPacketNum > 0) {
|
||||||
QUIC_STATS(conn_->statsCallback, onOutOfOrderPacketReceived);
|
QUIC_STATS(conn_->statsCallback, onOutOfOrderPacketReceived);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -347,7 +347,12 @@ fillFrameWithPacketReceiveTimestamps(
|
|||||||
if (pktsAdded == maxRecvTimestampsToSend) {
|
if (pktsAdded == maxRecvTimestampsToSend) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
receivedPktNumsIntervalSet.insert(recvdPkt.pktNum);
|
auto insertResult = receivedPktNumsIntervalSet.tryInsert(recvdPkt.pktNum);
|
||||||
|
if (insertResult.hasError()) {
|
||||||
|
return quic::make_unexpected(QuicError(
|
||||||
|
QuicErrorCode(TransportErrorCode::INTERNAL_ERROR),
|
||||||
|
"Failed to insert packet number into interval set"));
|
||||||
|
}
|
||||||
pktsAdded++;
|
pktsAdded++;
|
||||||
}
|
}
|
||||||
auto prevPktNum = largestAckedPacketNum;
|
auto prevPktNum = largestAckedPacketNum;
|
||||||
|
|||||||
@@ -9,9 +9,13 @@ mvfst_cpp_library(
|
|||||||
"IntervalSet-inl.h",
|
"IntervalSet-inl.h",
|
||||||
],
|
],
|
||||||
exported_deps = [
|
exported_deps = [
|
||||||
|
":expected",
|
||||||
":optional",
|
":optional",
|
||||||
"//folly:likely",
|
"//folly:likely",
|
||||||
],
|
],
|
||||||
|
exported_external_deps = [
|
||||||
|
"glog",
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
mvfst_cpp_library(
|
mvfst_cpp_library(
|
||||||
|
|||||||
@@ -94,9 +94,7 @@ bool IntervalSet<T, Unit, Container>::contains(const T& start, const T& end)
|
|||||||
|
|
||||||
template <typename T, T Unit, template <typename... I> class Container>
|
template <typename T, T Unit, template <typename... I> class Container>
|
||||||
void IntervalSet<T, Unit, Container>::insert(const T& startIt, const T& endIt) {
|
void IntervalSet<T, Unit, Container>::insert(const T& startIt, const T& endIt) {
|
||||||
if (startIt > endIt) {
|
CHECK_LE(startIt, endIt) << "Trying to insert invalid interval";
|
||||||
throw std::invalid_argument("Trying to insert invalid interval");
|
|
||||||
}
|
|
||||||
insert(Interval<T, Unit>(startIt, endIt));
|
insert(Interval<T, Unit>(startIt, endIt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,4 +126,37 @@ template <typename T, T Unit, template <typename... I> class Container>
|
|||||||
uint64_t IntervalSet<T, Unit, Container>::insertVersion() const {
|
uint64_t IntervalSet<T, Unit, Container>::insertVersion() const {
|
||||||
return insertVersion_;
|
return insertVersion_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, T Unit, template <typename... I> class Container>
|
||||||
|
Expected<void, IntervalSetError> IntervalSet<T, Unit, Container>::tryInsert(
|
||||||
|
const Interval<T, Unit>& interval) {
|
||||||
|
// The interval constructor already validated the bounds, so we can safely
|
||||||
|
// insert
|
||||||
|
insert(interval);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, T Unit, template <typename... I> class Container>
|
||||||
|
Expected<void, IntervalSetError> IntervalSet<T, Unit, Container>::tryInsert(
|
||||||
|
const T& start,
|
||||||
|
const T& end) {
|
||||||
|
// Validate the bounds before creating the interval
|
||||||
|
if (start > end) {
|
||||||
|
return quic::make_unexpected(IntervalSetError::InvalidInterval);
|
||||||
|
}
|
||||||
|
if (end > std::numeric_limits<T>::max() - interval_type::unitValue()) {
|
||||||
|
return quic::make_unexpected(IntervalSetError::IntervalBoundTooLarge);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Safe to create and insert the interval
|
||||||
|
insert(Interval<T, Unit>(start, end));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, T Unit, template <typename... I> class Container>
|
||||||
|
Expected<void, IntervalSetError> IntervalSet<T, Unit, Container>::tryInsert(
|
||||||
|
const T& point) {
|
||||||
|
return tryInsert(point, point);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace quic
|
} // namespace quic
|
||||||
|
|||||||
@@ -9,17 +9,25 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <exception>
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include <folly/Likely.h>
|
#include <folly/Likely.h>
|
||||||
|
#include <glog/logging.h>
|
||||||
|
#include <quic/common/Expected.h>
|
||||||
|
|
||||||
namespace quic {
|
namespace quic {
|
||||||
|
|
||||||
constexpr uint64_t kDefaultIntervalSetVersion = 0;
|
constexpr uint64_t kDefaultIntervalSetVersion = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error codes for IntervalSet operations
|
||||||
|
*/
|
||||||
|
enum class IntervalSetError : uint8_t {
|
||||||
|
InvalidInterval, // start > end
|
||||||
|
IntervalBoundTooLarge // interval bound exceeds max allowed value
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T, T Unit = (T)1>
|
template <typename T, T Unit = (T)1>
|
||||||
struct Interval {
|
struct Interval {
|
||||||
T start;
|
T start;
|
||||||
@@ -30,12 +38,21 @@ struct Interval {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Interval(const T& s, const T& e) : start(s), end(e) {
|
Interval(const T& s, const T& e) : start(s), end(e) {
|
||||||
if (start > end) {
|
CHECK_LE(start, end) << "Trying to construct invalid interval";
|
||||||
throw std::invalid_argument("Trying to construct invalid interval");
|
CHECK_LE(end, std::numeric_limits<T>::max() - unitValue())
|
||||||
|
<< "Interval bound too large";
|
||||||
}
|
}
|
||||||
if (end > std::numeric_limits<T>::max() - unitValue()) {
|
|
||||||
throw std::invalid_argument("Interval bound too large");
|
// Safe constructor that returns Expected instead of CHECKing
|
||||||
|
[[nodiscard]] static quic::Expected<Interval<T, Unit>, IntervalSetError>
|
||||||
|
tryCreate(const T& s, const T& e) {
|
||||||
|
if (s > e) {
|
||||||
|
return quic::make_unexpected(IntervalSetError::InvalidInterval);
|
||||||
}
|
}
|
||||||
|
if (e > std::numeric_limits<T>::max() - unitValue()) {
|
||||||
|
return quic::make_unexpected(IntervalSetError::IntervalBoundTooLarge);
|
||||||
|
}
|
||||||
|
return Interval<T, Unit>{s, e};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(Interval& rhs) const {
|
bool operator==(Interval& rhs) const {
|
||||||
@@ -95,6 +112,16 @@ class IntervalSet : private Container<Interval<T, Unit>> {
|
|||||||
|
|
||||||
void insert(const T& point);
|
void insert(const T& point);
|
||||||
|
|
||||||
|
// Safe versions that return Expected instead of CHECKing
|
||||||
|
[[nodiscard]] Expected<void, IntervalSetError> tryInsert(
|
||||||
|
const Interval<T, Unit>& interval);
|
||||||
|
|
||||||
|
[[nodiscard]] Expected<void, IntervalSetError> tryInsert(
|
||||||
|
const T& start,
|
||||||
|
const T& end);
|
||||||
|
|
||||||
|
[[nodiscard]] Expected<void, IntervalSetError> tryInsert(const T& point);
|
||||||
|
|
||||||
void withdraw(const Interval<T, Unit>& interval);
|
void withdraw(const Interval<T, Unit>& interval);
|
||||||
|
|
||||||
[[nodiscard]] bool contains(const T& start, const T& end) const;
|
[[nodiscard]] bool contains(const T& start, const T& end) const;
|
||||||
|
|||||||
@@ -158,9 +158,10 @@ TEST(IntervalSet, insertWithMergeAtEdge) {
|
|||||||
|
|
||||||
TEST(IntervalSet, insertBoundTooLarge) {
|
TEST(IntervalSet, insertBoundTooLarge) {
|
||||||
IntervalSet<uint32_t, 10> set;
|
IntervalSet<uint32_t, 10> set;
|
||||||
EXPECT_THROW(
|
// This should CHECK-fail since end - start > 10
|
||||||
set.insert(0, std::numeric_limits<uint32_t>::max() - 9),
|
EXPECT_DEATH(
|
||||||
std::invalid_argument);
|
set.insert(0, std::numeric_limits<uint32_t>::max() - 9), "Check failed");
|
||||||
|
// This should work fine since end - start == 10
|
||||||
set.insert(0, std::numeric_limits<uint32_t>::max() - 10);
|
set.insert(0, std::numeric_limits<uint32_t>::max() - 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,3 +403,77 @@ TEST(IntervalSet, equalityComparatorNotEqualDiffIntervals2) {
|
|||||||
EXPECT_FALSE(set1 == set2);
|
EXPECT_FALSE(set1 == set2);
|
||||||
EXPECT_TRUE(set1 != set2);
|
EXPECT_TRUE(set1 != set2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(IntervalSet, tryInsertValidInterval) {
|
||||||
|
IntervalSet<int> set;
|
||||||
|
auto result = set.tryInsert(1, 5);
|
||||||
|
EXPECT_TRUE(result.has_value());
|
||||||
|
EXPECT_EQ(1, set.size());
|
||||||
|
EXPECT_TRUE(set.contains(1, 5));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(IntervalSet, tryInsertValidPoint) {
|
||||||
|
IntervalSet<int> set;
|
||||||
|
auto result = set.tryInsert(10);
|
||||||
|
EXPECT_TRUE(result.has_value());
|
||||||
|
EXPECT_EQ(1, set.size());
|
||||||
|
EXPECT_TRUE(set.contains(10, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(IntervalSet, tryInsertInvalidInterval) {
|
||||||
|
IntervalSet<int> set;
|
||||||
|
// start > end should return error
|
||||||
|
auto result = set.tryInsert(10, 5);
|
||||||
|
EXPECT_TRUE(result.hasError());
|
||||||
|
EXPECT_EQ(IntervalSetError::InvalidInterval, result.error());
|
||||||
|
EXPECT_EQ(0, set.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(IntervalSet, tryInsertBoundTooLarge) {
|
||||||
|
IntervalSet<uint32_t, 10> set;
|
||||||
|
// This should return error instead of CHECK-failing
|
||||||
|
auto result = set.tryInsert(0, std::numeric_limits<uint32_t>::max() - 9);
|
||||||
|
EXPECT_TRUE(result.hasError());
|
||||||
|
EXPECT_EQ(IntervalSetError::IntervalBoundTooLarge, result.error());
|
||||||
|
EXPECT_EQ(0, set.size());
|
||||||
|
|
||||||
|
// This should succeed
|
||||||
|
auto result2 = set.tryInsert(0, std::numeric_limits<uint32_t>::max() - 10);
|
||||||
|
EXPECT_TRUE(result2.has_value());
|
||||||
|
EXPECT_EQ(1, set.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(IntervalSet, tryInsertWithMerging) {
|
||||||
|
IntervalSet<int> set;
|
||||||
|
auto result1 = set.tryInsert(1, 3);
|
||||||
|
EXPECT_TRUE(result1.has_value());
|
||||||
|
|
||||||
|
auto result2 = set.tryInsert(5, 7);
|
||||||
|
EXPECT_TRUE(result2.has_value());
|
||||||
|
|
||||||
|
// Insert overlapping interval
|
||||||
|
auto result3 = set.tryInsert(2, 6);
|
||||||
|
EXPECT_TRUE(result3.has_value());
|
||||||
|
|
||||||
|
EXPECT_EQ(1, set.size());
|
||||||
|
EXPECT_TRUE(set.contains(1, 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(IntervalSet, tryCreateInterval) {
|
||||||
|
// Test the static tryCreate method
|
||||||
|
auto result1 = Interval<int>::tryCreate(1, 5);
|
||||||
|
EXPECT_TRUE(result1.has_value());
|
||||||
|
EXPECT_EQ(1, result1->start);
|
||||||
|
EXPECT_EQ(5, result1->end);
|
||||||
|
|
||||||
|
// Test invalid interval
|
||||||
|
auto result2 = Interval<int>::tryCreate(10, 5);
|
||||||
|
EXPECT_TRUE(result2.hasError());
|
||||||
|
EXPECT_EQ(IntervalSetError::InvalidInterval, result2.error());
|
||||||
|
|
||||||
|
// Test bound too large
|
||||||
|
auto result3 = Interval<uint32_t, 10>::tryCreate(
|
||||||
|
0, std::numeric_limits<uint32_t>::max() - 9);
|
||||||
|
EXPECT_TRUE(result3.hasError());
|
||||||
|
EXPECT_EQ(IntervalSetError::IntervalBoundTooLarge, result3.error());
|
||||||
|
}
|
||||||
|
|||||||
@@ -541,8 +541,13 @@ void updateAckState(
|
|||||||
TimePoint receiveTimePoint) {
|
TimePoint receiveTimePoint) {
|
||||||
ReceivedUdpPacket packet;
|
ReceivedUdpPacket packet;
|
||||||
packet.timings.receiveTimePoint = receiveTimePoint;
|
packet.timings.receiveTimePoint = receiveTimePoint;
|
||||||
uint64_t distance =
|
auto addResult =
|
||||||
addPacketToAckState(conn, getAckState(conn, pnSpace), packetNum, packet);
|
addPacketToAckState(conn, getAckState(conn, pnSpace), packetNum, packet);
|
||||||
|
if (!addResult.has_value()) {
|
||||||
|
LOG(FATAL) << "Failed to add packet to ack state in test: "
|
||||||
|
<< static_cast<int>(addResult.error());
|
||||||
|
}
|
||||||
|
uint64_t distance = addResult.value();
|
||||||
updateAckSendStateOnRecvPacket(
|
updateAckSendStateOnRecvPacket(
|
||||||
conn,
|
conn,
|
||||||
getAckState(conn, pnSpace),
|
getAckState(conn, pnSpace),
|
||||||
|
|||||||
@@ -1262,8 +1262,14 @@ quic::Expected<void, QuicError> onServerReadDataFromOpen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto& ackState = getAckState(conn, packetNumberSpace);
|
auto& ackState = getAckState(conn, packetNumberSpace);
|
||||||
uint64_t distanceFromExpectedPacketNum =
|
auto addResult =
|
||||||
addPacketToAckState(conn, ackState, packetNum, readData.udpPacket);
|
addPacketToAckState(conn, ackState, packetNum, readData.udpPacket);
|
||||||
|
if (!addResult.has_value()) {
|
||||||
|
return quic::make_unexpected(QuicError(
|
||||||
|
TransportErrorCode::INTERNAL_ERROR,
|
||||||
|
"Failed to add packet to ack state"));
|
||||||
|
}
|
||||||
|
uint64_t distanceFromExpectedPacketNum = addResult.value();
|
||||||
if (distanceFromExpectedPacketNum > 0) {
|
if (distanceFromExpectedPacketNum > 0) {
|
||||||
QUIC_STATS(conn.statsCallback, onOutOfOrderPacketReceived);
|
QUIC_STATS(conn.statsCallback, onOutOfOrderPacketReceived);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -210,7 +210,13 @@ quic::Expected<AckEvent, QuicError> processAckFrame(
|
|||||||
// If we hit a packet which has been declared lost we need to count the
|
// If we hit a packet which has been declared lost we need to count the
|
||||||
// spurious loss and ignore all other processing.
|
// spurious loss and ignore all other processing.
|
||||||
if (ackedPacketIterator->declaredLost) {
|
if (ackedPacketIterator->declaredLost) {
|
||||||
|
auto modifyResult =
|
||||||
modifyStateForSpuriousLoss(conn, *ackedPacketIterator);
|
modifyStateForSpuriousLoss(conn, *ackedPacketIterator);
|
||||||
|
if (!modifyResult.has_value()) {
|
||||||
|
return quic::make_unexpected(QuicError(
|
||||||
|
TransportErrorCode::INTERNAL_ERROR,
|
||||||
|
"Failed to modify state for spurious loss"));
|
||||||
|
}
|
||||||
QUIC_STATS(conn.statsCallback, onPacketSpuriousLoss);
|
QUIC_STATS(conn.statsCallback, onPacketSpuriousLoss);
|
||||||
if (spuriousLossEvent) {
|
if (spuriousLossEvent) {
|
||||||
spuriousLossEvent->addSpuriousPacket(
|
spuriousLossEvent->addSpuriousPacket(
|
||||||
@@ -705,7 +711,7 @@ void updateEcnCountEchoed(
|
|||||||
std::max(ackState.ecnCECountEchoed, readAckFrame.ecnCECount);
|
std::max(ackState.ecnCECountEchoed, readAckFrame.ecnCECount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void modifyStateForSpuriousLoss(
|
Expected<void, IntervalSetError> modifyStateForSpuriousLoss(
|
||||||
QuicConnectionStateBase& conn,
|
QuicConnectionStateBase& conn,
|
||||||
OutstandingPacketWrapper& spuriouslyLostPacket) {
|
OutstandingPacketWrapper& spuriouslyLostPacket) {
|
||||||
CHECK_GT(conn.outstandings.declaredLostCount, 0);
|
CHECK_GT(conn.outstandings.declaredLostCount, 0);
|
||||||
@@ -734,8 +740,11 @@ void modifyStateForSpuriousLoss(
|
|||||||
if (stream) {
|
if (stream) {
|
||||||
stream->removeFromLossBuffer(
|
stream->removeFromLossBuffer(
|
||||||
streamFrame->offset, streamFrame->len, streamFrame->fin);
|
streamFrame->offset, streamFrame->len, streamFrame->fin);
|
||||||
stream->updateAckedIntervals(
|
auto updateResult = stream->updateAckedIntervals(
|
||||||
streamFrame->offset, streamFrame->len, streamFrame->fin);
|
streamFrame->offset, streamFrame->len, streamFrame->fin);
|
||||||
|
if (!updateResult.has_value()) {
|
||||||
|
return quic::make_unexpected(updateResult.error());
|
||||||
|
}
|
||||||
conn.streamManager->updateWritableStreams(*stream);
|
conn.streamManager->updateWritableStreams(*stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -743,5 +752,6 @@ void modifyStateForSpuriousLoss(
|
|||||||
}
|
}
|
||||||
CHECK_GT(conn.outstandings.declaredLostCount, 0);
|
CHECK_GT(conn.outstandings.declaredLostCount, 0);
|
||||||
conn.outstandings.declaredLostCount--;
|
conn.outstandings.declaredLostCount--;
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
} // namespace quic
|
} // namespace quic
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <quic/QuicConstants.h>
|
#include <quic/QuicConstants.h>
|
||||||
#include <quic/codec/Types.h>
|
#include <quic/codec/Types.h>
|
||||||
#include <quic/common/Expected.h>
|
#include <quic/common/Expected.h>
|
||||||
|
#include <quic/common/IntervalSet.h>
|
||||||
#include <quic/state/StateData.h>
|
#include <quic/state/StateData.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
@@ -124,7 +125,7 @@ void updateEcnCountEchoed(
|
|||||||
* Modifies the state in the QuicConnectionStateBase when a packet that
|
* Modifies the state in the QuicConnectionStateBase when a packet that
|
||||||
* was marked as lost is acked.
|
* was marked as lost is acked.
|
||||||
*/
|
*/
|
||||||
void modifyStateForSpuriousLoss(
|
[[nodiscard]] Expected<void, IntervalSetError> modifyStateForSpuriousLoss(
|
||||||
QuicConnectionStateBase& conn,
|
QuicConnectionStateBase& conn,
|
||||||
OutstandingPacketWrapper& spuriouslyLostPacket);
|
OutstandingPacketWrapper& spuriouslyLostPacket);
|
||||||
} // namespace quic
|
} // namespace quic
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ mvfst_cpp_library(
|
|||||||
"//quic/common:buf_accessor",
|
"//quic/common:buf_accessor",
|
||||||
"//quic/common:circular_deque",
|
"//quic/common:circular_deque",
|
||||||
"//quic/common:expected",
|
"//quic/common:expected",
|
||||||
|
"//quic/common:interval_set",
|
||||||
"//quic/common:optional",
|
"//quic/common:optional",
|
||||||
"//quic/congestion_control:congestion_controller",
|
"//quic/congestion_control:congestion_controller",
|
||||||
"//quic/congestion_control:packet_processor",
|
"//quic/congestion_control:packet_processor",
|
||||||
@@ -167,6 +168,7 @@ mvfst_cpp_library(
|
|||||||
"//quic:constants",
|
"//quic:constants",
|
||||||
"//quic/codec:types",
|
"//quic/codec:types",
|
||||||
"//quic/common:expected",
|
"//quic/common:expected",
|
||||||
|
"//quic/common:interval_set",
|
||||||
"//quic/common:optional",
|
"//quic/common:optional",
|
||||||
"//quic/congestion_control:congestion_controller",
|
"//quic/congestion_control:congestion_controller",
|
||||||
],
|
],
|
||||||
@@ -207,6 +209,8 @@ mvfst_cpp_library(
|
|||||||
"//quic:constants",
|
"//quic:constants",
|
||||||
"//quic/codec:pktbuilder",
|
"//quic/codec:pktbuilder",
|
||||||
"//quic/codec:types",
|
"//quic/codec:types",
|
||||||
|
"//quic/common:expected",
|
||||||
|
"//quic/common:interval_set",
|
||||||
"//quic/common:network_data",
|
"//quic/common:network_data",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -395,7 +395,7 @@ uint64_t maximumConnectionIdsToIssue(const QuicConnectionStateBase& conn) {
|
|||||||
return maximumIdsToIssue;
|
return maximumIdsToIssue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t addPacketToAckState(
|
Expected<uint64_t, IntervalSetError> addPacketToAckState(
|
||||||
QuicConnectionStateBase& conn,
|
QuicConnectionStateBase& conn,
|
||||||
AckState& ackState,
|
AckState& ackState,
|
||||||
const PacketNum packetNum,
|
const PacketNum packetNum,
|
||||||
@@ -407,7 +407,10 @@ uint64_t addPacketToAckState(
|
|||||||
ackState.largestRecvdPacketNum = std::max<PacketNum>(
|
ackState.largestRecvdPacketNum = std::max<PacketNum>(
|
||||||
ackState.largestRecvdPacketNum.value_or(packetNum), packetNum);
|
ackState.largestRecvdPacketNum.value_or(packetNum), packetNum);
|
||||||
auto preInsertVersion = ackState.acks.insertVersion();
|
auto preInsertVersion = ackState.acks.insertVersion();
|
||||||
ackState.acks.insert(packetNum);
|
auto insertResult = ackState.acks.tryInsert(packetNum);
|
||||||
|
if (!insertResult.has_value()) {
|
||||||
|
return quic::make_unexpected(insertResult.error());
|
||||||
|
}
|
||||||
if (preInsertVersion == ackState.acks.insertVersion()) {
|
if (preInsertVersion == ackState.acks.insertVersion()) {
|
||||||
QUIC_STATS(conn.statsCallback, onDuplicatedPacketReceived);
|
QUIC_STATS(conn.statsCallback, onDuplicatedPacketReceived);
|
||||||
}
|
}
|
||||||
@@ -446,7 +449,7 @@ uint64_t addPacketToAckState(
|
|||||||
return (packetNum > expectedNextPacket) ? packetNum - expectedNextPacket
|
return (packetNum > expectedNextPacket) ? packetNum - expectedNextPacket
|
||||||
: expectedNextPacket - packetNum;
|
: expectedNextPacket - packetNum;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return uint64_t{0};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include <quic/QuicConstants.h>
|
#include <quic/QuicConstants.h>
|
||||||
#include <quic/codec/QuicPacketBuilder.h>
|
#include <quic/codec/QuicPacketBuilder.h>
|
||||||
#include <quic/codec/Types.h>
|
#include <quic/codec/Types.h>
|
||||||
|
#include <quic/common/Expected.h>
|
||||||
|
#include <quic/common/IntervalSet.h>
|
||||||
#include <quic/common/NetworkData.h>
|
#include <quic/common/NetworkData.h>
|
||||||
#include <quic/state/StateData.h>
|
#include <quic/state/StateData.h>
|
||||||
|
|
||||||
@@ -65,7 +67,7 @@ void increaseNextPacketNum(
|
|||||||
* Update largestReceivedUdpPacketNum in ackState with packetNum. Return the
|
* Update largestReceivedUdpPacketNum in ackState with packetNum. Return the
|
||||||
* distance from the next packet number we expect to receive.
|
* distance from the next packet number we expect to receive.
|
||||||
*/
|
*/
|
||||||
uint64_t addPacketToAckState(
|
[[nodiscard]] Expected<uint64_t, IntervalSetError> addPacketToAckState(
|
||||||
QuicConnectionStateBase& conn,
|
QuicConnectionStateBase& conn,
|
||||||
AckState& ackState,
|
AckState& ackState,
|
||||||
const PacketNum packetNum,
|
const PacketNum packetNum,
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include <quic/QuicConstants.h>
|
#include <quic/QuicConstants.h>
|
||||||
#include <quic/codec/Types.h>
|
#include <quic/codec/Types.h>
|
||||||
|
#include <quic/common/Expected.h>
|
||||||
|
#include <quic/common/IntervalSet.h>
|
||||||
#include <quic/dsr/DSRPacketizationRequestSender.h>
|
#include <quic/dsr/DSRPacketizationRequestSender.h>
|
||||||
#include <quic/mvfst-config.h>
|
#include <quic/mvfst-config.h>
|
||||||
#include <quic/priority/PriorityQueue.h>
|
#include <quic/priority/PriorityQueue.h>
|
||||||
@@ -211,7 +213,8 @@ struct QuicStreamLike {
|
|||||||
// egress packets that contains a *new* STREAM frame for this stream.
|
// egress packets that contains a *new* STREAM frame for this stream.
|
||||||
uint64_t numPacketsTxWithNewData{0};
|
uint64_t numPacketsTxWithNewData{0};
|
||||||
|
|
||||||
void updateAckedIntervals(uint64_t offset, uint64_t len, bool eof) {
|
[[nodiscard]] Expected<void, IntervalSetError>
|
||||||
|
updateAckedIntervals(uint64_t offset, uint64_t len, bool eof) {
|
||||||
// When there's an EOF we count the byte of 1 past the end as having been
|
// When there's an EOF we count the byte of 1 past the end as having been
|
||||||
// ACKed, since this is useful for delivery APIs.
|
// ACKed, since this is useful for delivery APIs.
|
||||||
int lenAdjustment = [eof]() {
|
int lenAdjustment = [eof]() {
|
||||||
@@ -224,7 +227,7 @@ struct QuicStreamLike {
|
|||||||
if (lenAdjustment && len == 0) {
|
if (lenAdjustment && len == 0) {
|
||||||
LOG(FATAL) << "ACK for empty stream frame with no fin.";
|
LOG(FATAL) << "ACK for empty stream frame with no fin.";
|
||||||
}
|
}
|
||||||
ackedIntervals.insert(offset, offset + len - lenAdjustment);
|
return ackedIntervals.tryInsert(offset, offset + len - lenAdjustment);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -145,10 +145,15 @@ quic::Expected<void, QuicError> sendAckSMHandler(
|
|||||||
<< " offset=" << ackedBuffer->second->offset
|
<< " offset=" << ackedBuffer->second->offset
|
||||||
<< " len=" << ackedBuffer->second->data.chainLength()
|
<< " len=" << ackedBuffer->second->data.chainLength()
|
||||||
<< " eof=" << ackedBuffer->second->eof << " " << stream.conn;
|
<< " eof=" << ackedBuffer->second->eof << " " << stream.conn;
|
||||||
stream.updateAckedIntervals(
|
auto updateResult = stream.updateAckedIntervals(
|
||||||
ackedBuffer->second->offset,
|
ackedBuffer->second->offset,
|
||||||
ackedBuffer->second->data.chainLength(),
|
ackedBuffer->second->data.chainLength(),
|
||||||
ackedBuffer->second->eof);
|
ackedBuffer->second->eof);
|
||||||
|
if (!updateResult.has_value()) {
|
||||||
|
return quic::make_unexpected(QuicError(
|
||||||
|
TransportErrorCode::INTERNAL_ERROR,
|
||||||
|
"Failed to update acked intervals"));
|
||||||
|
}
|
||||||
stream.retransmissionBuffer.erase(ackedBuffer);
|
stream.retransmissionBuffer.erase(ackedBuffer);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -162,10 +167,15 @@ quic::Expected<void, QuicError> sendAckSMHandler(
|
|||||||
<< " offset=" << ackedBuffer->second.offset
|
<< " offset=" << ackedBuffer->second.offset
|
||||||
<< " len=" << ackedBuffer->second.length
|
<< " len=" << ackedBuffer->second.length
|
||||||
<< " eof=" << ackedBuffer->second.eof << " " << stream.conn;
|
<< " eof=" << ackedBuffer->second.eof << " " << stream.conn;
|
||||||
stream.updateAckedIntervals(
|
auto updateResult = stream.updateAckedIntervals(
|
||||||
ackedBuffer->second.offset,
|
ackedBuffer->second.offset,
|
||||||
ackedBuffer->second.length,
|
ackedBuffer->second.length,
|
||||||
ackedBuffer->second.eof);
|
ackedBuffer->second.eof);
|
||||||
|
if (!updateResult.has_value()) {
|
||||||
|
return quic::make_unexpected(QuicError(
|
||||||
|
TransportErrorCode::INTERNAL_ERROR,
|
||||||
|
"Failed to update acked intervals"));
|
||||||
|
}
|
||||||
stream.retransmissionBufMetas.erase(ackedBuffer);
|
stream.retransmissionBufMetas.erase(ackedBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -345,7 +345,7 @@ TEST_F(QuicResetSentStateTest, ReliableRstAckNoReduction) {
|
|||||||
stream.readBuffer.emplace_back(
|
stream.readBuffer.emplace_back(
|
||||||
folly::IOBuf::copyBuffer("One more thing"), 0xABCD, false);
|
folly::IOBuf::copyBuffer("One more thing"), 0xABCD, false);
|
||||||
RstStreamFrame frame(id, GenericApplicationErrorCode::UNKNOWN, 0);
|
RstStreamFrame frame(id, GenericApplicationErrorCode::UNKNOWN, 0);
|
||||||
stream.updateAckedIntervals(0, 3, false);
|
ASSERT_TRUE(stream.updateAckedIntervals(0, 3, false).has_value());
|
||||||
auto result = sendRstAckSMHandler(stream, 5);
|
auto result = sendRstAckSMHandler(stream, 5);
|
||||||
ASSERT_FALSE(result.hasError());
|
ASSERT_FALSE(result.hasError());
|
||||||
|
|
||||||
@@ -370,7 +370,7 @@ TEST_F(QuicResetSentStateTest, ReliableRstAckReduction) {
|
|||||||
stream.readBuffer.emplace_back(
|
stream.readBuffer.emplace_back(
|
||||||
folly::IOBuf::copyBuffer("One more thing"), 0xABCD, false);
|
folly::IOBuf::copyBuffer("One more thing"), 0xABCD, false);
|
||||||
RstStreamFrame frame(id, GenericApplicationErrorCode::UNKNOWN, 0);
|
RstStreamFrame frame(id, GenericApplicationErrorCode::UNKNOWN, 0);
|
||||||
stream.updateAckedIntervals(0, 1, false);
|
ASSERT_TRUE(stream.updateAckedIntervals(0, 1, false).has_value());
|
||||||
auto result = sendRstAckSMHandler(stream, 1);
|
auto result = sendRstAckSMHandler(stream, 1);
|
||||||
ASSERT_FALSE(result.hasError());
|
ASSERT_FALSE(result.hasError());
|
||||||
|
|
||||||
@@ -434,7 +434,7 @@ TEST_F(QuicResetSentStateTest, ResetSentToClosedTransition1) {
|
|||||||
StreamId id = 5;
|
StreamId id = 5;
|
||||||
QuicStreamState stream(id, *conn);
|
QuicStreamState stream(id, *conn);
|
||||||
stream.sendState = StreamSendState::ResetSent;
|
stream.sendState = StreamSendState::ResetSent;
|
||||||
stream.updateAckedIntervals(0, 5, false);
|
ASSERT_TRUE(stream.updateAckedIntervals(0, 5, false).has_value());
|
||||||
auto result = sendRstAckSMHandler(stream, 5);
|
auto result = sendRstAckSMHandler(stream, 5);
|
||||||
ASSERT_FALSE(result.hasError());
|
ASSERT_FALSE(result.hasError());
|
||||||
EXPECT_EQ(stream.sendState, StreamSendState::Closed);
|
EXPECT_EQ(stream.sendState, StreamSendState::Closed);
|
||||||
@@ -447,7 +447,7 @@ TEST_F(QuicResetSentStateTest, ResetSentToClosedTransition2) {
|
|||||||
StreamId id = 5;
|
StreamId id = 5;
|
||||||
QuicStreamState stream(id, *conn);
|
QuicStreamState stream(id, *conn);
|
||||||
stream.sendState = StreamSendState::ResetSent;
|
stream.sendState = StreamSendState::ResetSent;
|
||||||
stream.updateAckedIntervals(0, 4, false);
|
ASSERT_TRUE(stream.updateAckedIntervals(0, 4, false).has_value());
|
||||||
auto result = sendRstAckSMHandler(stream, 5);
|
auto result = sendRstAckSMHandler(stream, 5);
|
||||||
ASSERT_FALSE(result.hasError());
|
ASSERT_FALSE(result.hasError());
|
||||||
EXPECT_EQ(stream.sendState, StreamSendState::ResetSent);
|
EXPECT_EQ(stream.sendState, StreamSendState::ResetSent);
|
||||||
|
|||||||
@@ -73,12 +73,14 @@ TEST_P(AddPacketToAckStateTest, FirstPacketNotOutOfOrder) {
|
|||||||
/**
|
/**
|
||||||
* We skip setting the getAckState(conn,
|
* We skip setting the getAckState(conn,
|
||||||
* GetParam()).largestReceivedUdpPacketNum to simulate that we haven't
|
* GetParam()).largestReceivedUdpPacketNum to simulate that we haven't
|
||||||
* received any packets yet. `addPacketToAckState()` should return false for
|
* received any packets yet. `addPacketToAckState()` should return distance 0
|
||||||
* the first packet received.
|
* for the first packet received.
|
||||||
*/
|
*/
|
||||||
PacketNum firstPacket = folly::Random::rand32(1, 100);
|
PacketNum firstPacket = folly::Random::rand32(1, 100);
|
||||||
EXPECT_FALSE(addPacketToAckState(
|
auto result = addPacketToAckState(
|
||||||
conn, getAckState(conn, GetParam()), firstPacket, buildPacketMinimal()));
|
conn, getAckState(conn, GetParam()), firstPacket, buildPacketMinimal());
|
||||||
|
ASSERT_TRUE(result.has_value());
|
||||||
|
EXPECT_EQ(result.value(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(AddPacketToAckStateTest, ReceiveNew) {
|
TEST_P(AddPacketToAckStateTest, ReceiveNew) {
|
||||||
@@ -90,7 +92,8 @@ TEST_P(AddPacketToAckStateTest, ReceiveNew) {
|
|||||||
PacketNum newReceived = currentLargestReceived + 1;
|
PacketNum newReceived = currentLargestReceived + 1;
|
||||||
auto distance = addPacketToAckState(
|
auto distance = addPacketToAckState(
|
||||||
conn, getAckState(conn, GetParam()), newReceived, buildPacketMinimal());
|
conn, getAckState(conn, GetParam()), newReceived, buildPacketMinimal());
|
||||||
EXPECT_EQ(distance, 0);
|
ASSERT_TRUE(distance.has_value());
|
||||||
|
EXPECT_EQ(distance.value(), 0);
|
||||||
EXPECT_GT(
|
EXPECT_GT(
|
||||||
*getAckState(conn, GetParam()).largestRecvdPacketNum,
|
*getAckState(conn, GetParam()).largestRecvdPacketNum,
|
||||||
currentLargestReceived);
|
currentLargestReceived);
|
||||||
@@ -105,7 +108,8 @@ TEST_P(AddPacketToAckStateTest, ReceiveNewWithGap) {
|
|||||||
PacketNum newReceived = currentLargestReceived + 3;
|
PacketNum newReceived = currentLargestReceived + 3;
|
||||||
auto distance = addPacketToAckState(
|
auto distance = addPacketToAckState(
|
||||||
conn, getAckState(conn, GetParam()), newReceived, buildPacketMinimal());
|
conn, getAckState(conn, GetParam()), newReceived, buildPacketMinimal());
|
||||||
EXPECT_EQ(distance, 2); // newReceived is 2 after the expected pkt num
|
ASSERT_TRUE(distance.has_value());
|
||||||
|
EXPECT_EQ(distance.value(), 2); // newReceived is 2 after the expected pkt num
|
||||||
EXPECT_GT(
|
EXPECT_GT(
|
||||||
*getAckState(conn, GetParam()).largestRecvdPacketNum,
|
*getAckState(conn, GetParam()).largestRecvdPacketNum,
|
||||||
currentLargestReceived);
|
currentLargestReceived);
|
||||||
@@ -120,7 +124,9 @@ TEST_P(AddPacketToAckStateTest, ReceiveOld) {
|
|||||||
PacketNum newReceived = currentLargestReceived - 1;
|
PacketNum newReceived = currentLargestReceived - 1;
|
||||||
auto distance = addPacketToAckState(
|
auto distance = addPacketToAckState(
|
||||||
conn, getAckState(conn, GetParam()), newReceived, buildPacketMinimal());
|
conn, getAckState(conn, GetParam()), newReceived, buildPacketMinimal());
|
||||||
EXPECT_EQ(distance, 2); // newReceived is 2 before the expected pkt num
|
ASSERT_TRUE(distance.has_value());
|
||||||
|
EXPECT_EQ(
|
||||||
|
distance.value(), 2); // newReceived is 2 before the expected pkt num
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
*getAckState(conn, GetParam()).largestRecvdPacketNum,
|
*getAckState(conn, GetParam()).largestRecvdPacketNum,
|
||||||
currentLargestReceived);
|
currentLargestReceived);
|
||||||
@@ -135,7 +141,9 @@ TEST_P(AddPacketToAckStateTest, ReceiveOldWithGap) {
|
|||||||
PacketNum newReceived = currentLargestReceived - 5;
|
PacketNum newReceived = currentLargestReceived - 5;
|
||||||
auto distance = addPacketToAckState(
|
auto distance = addPacketToAckState(
|
||||||
conn, getAckState(conn, GetParam()), newReceived, buildPacketMinimal());
|
conn, getAckState(conn, GetParam()), newReceived, buildPacketMinimal());
|
||||||
EXPECT_EQ(distance, 6); // newReceived is 6 before the expected pkt num
|
ASSERT_TRUE(distance.has_value());
|
||||||
|
EXPECT_EQ(
|
||||||
|
distance.value(), 6); // newReceived is 6 before the expected pkt num
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
*getAckState(conn, GetParam()).largestRecvdPacketNum,
|
*getAckState(conn, GetParam()).largestRecvdPacketNum,
|
||||||
currentLargestReceived);
|
currentLargestReceived);
|
||||||
@@ -159,7 +167,8 @@ TEST_P(AddPacketToAckStateTest, ReceiveWithECN) {
|
|||||||
packet.tosValue = kEcnECT0;
|
packet.tosValue = kEcnECT0;
|
||||||
auto distance = addPacketToAckState(
|
auto distance = addPacketToAckState(
|
||||||
conn, getAckState(conn, GetParam()), ++nextPacketNum, packet);
|
conn, getAckState(conn, GetParam()), ++nextPacketNum, packet);
|
||||||
EXPECT_EQ(distance, 0);
|
ASSERT_TRUE(distance.has_value());
|
||||||
|
EXPECT_EQ(distance.value(), 0);
|
||||||
|
|
||||||
// Seen 1 ECT0, 0 ECT1, 0 CE.
|
// Seen 1 ECT0, 0 ECT1, 0 CE.
|
||||||
EXPECT_EQ(getAckState(conn, GetParam()).ecnCECountReceived, 0);
|
EXPECT_EQ(getAckState(conn, GetParam()).ecnCECountReceived, 0);
|
||||||
@@ -172,7 +181,8 @@ TEST_P(AddPacketToAckStateTest, ReceiveWithECN) {
|
|||||||
packet.tosValue = kEcnECT1;
|
packet.tosValue = kEcnECT1;
|
||||||
auto distance = addPacketToAckState(
|
auto distance = addPacketToAckState(
|
||||||
conn, getAckState(conn, GetParam()), ++nextPacketNum, packet);
|
conn, getAckState(conn, GetParam()), ++nextPacketNum, packet);
|
||||||
EXPECT_EQ(distance, 0);
|
ASSERT_TRUE(distance.has_value());
|
||||||
|
EXPECT_EQ(distance.value(), 0);
|
||||||
|
|
||||||
// Seen 1 ECT0, 1 ECT1, 0 CE.
|
// Seen 1 ECT0, 1 ECT1, 0 CE.
|
||||||
EXPECT_EQ(getAckState(conn, GetParam()).ecnCECountReceived, 0);
|
EXPECT_EQ(getAckState(conn, GetParam()).ecnCECountReceived, 0);
|
||||||
@@ -185,7 +195,8 @@ TEST_P(AddPacketToAckStateTest, ReceiveWithECN) {
|
|||||||
packet.tosValue = kEcnCE;
|
packet.tosValue = kEcnCE;
|
||||||
auto distance = addPacketToAckState(
|
auto distance = addPacketToAckState(
|
||||||
conn, getAckState(conn, GetParam()), ++nextPacketNum, packet);
|
conn, getAckState(conn, GetParam()), ++nextPacketNum, packet);
|
||||||
EXPECT_EQ(distance, 0);
|
ASSERT_TRUE(distance.has_value());
|
||||||
|
EXPECT_EQ(distance.value(), 0);
|
||||||
|
|
||||||
// Seen 1 ECT0, 1 ECT1, 1 CE.
|
// Seen 1 ECT0, 1 ECT1, 1 CE.
|
||||||
EXPECT_EQ(getAckState(conn, GetParam()).ecnCECountReceived, 1);
|
EXPECT_EQ(getAckState(conn, GetParam()).ecnCECountReceived, 1);
|
||||||
@@ -198,7 +209,8 @@ TEST_P(AddPacketToAckStateTest, ReceiveWithECN) {
|
|||||||
packet.tosValue = kEcnCE;
|
packet.tosValue = kEcnCE;
|
||||||
auto distance = addPacketToAckState(
|
auto distance = addPacketToAckState(
|
||||||
conn, getAckState(conn, GetParam()), ++nextPacketNum, packet);
|
conn, getAckState(conn, GetParam()), ++nextPacketNum, packet);
|
||||||
EXPECT_EQ(distance, 0);
|
ASSERT_TRUE(distance.has_value());
|
||||||
|
EXPECT_EQ(distance.value(), 0);
|
||||||
|
|
||||||
// Seen 1 ECT0, 1 ECT1, 2 CE.
|
// Seen 1 ECT0, 1 ECT1, 2 CE.
|
||||||
EXPECT_EQ(getAckState(conn, GetParam()).ecnCECountReceived, 2);
|
EXPECT_EQ(getAckState(conn, GetParam()).ecnCECountReceived, 2);
|
||||||
|
|||||||
@@ -703,7 +703,7 @@ TEST(StreamDataTest, AllBytesAckedTillNotStartAtZero) {
|
|||||||
QuicStreamState state(0, qcsb);
|
QuicStreamState state(0, qcsb);
|
||||||
|
|
||||||
EXPECT_TRUE(state.ackedIntervals.empty());
|
EXPECT_TRUE(state.ackedIntervals.empty());
|
||||||
state.updateAckedIntervals(1, 5, false);
|
ASSERT_TRUE(state.updateAckedIntervals(1, 5, false).has_value());
|
||||||
EXPECT_EQ(state.allBytesAckedTill(5), false);
|
EXPECT_EQ(state.allBytesAckedTill(5), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -712,7 +712,7 @@ TEST(StreamDataTest, AllBytesAckedTillNotEnoughLength) {
|
|||||||
QuicStreamState state(0, qcsb);
|
QuicStreamState state(0, qcsb);
|
||||||
|
|
||||||
EXPECT_TRUE(state.ackedIntervals.empty());
|
EXPECT_TRUE(state.ackedIntervals.empty());
|
||||||
state.updateAckedIntervals(0, 5, false);
|
ASSERT_TRUE(state.updateAckedIntervals(0, 5, false).has_value());
|
||||||
EXPECT_EQ(state.allBytesAckedTill(5), false);
|
EXPECT_EQ(state.allBytesAckedTill(5), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -721,7 +721,7 @@ TEST(StreamDataTest, AllBytesAckedPass) {
|
|||||||
QuicStreamState state(0, qcsb);
|
QuicStreamState state(0, qcsb);
|
||||||
|
|
||||||
EXPECT_TRUE(state.ackedIntervals.empty());
|
EXPECT_TRUE(state.ackedIntervals.empty());
|
||||||
state.updateAckedIntervals(0, 6, false);
|
ASSERT_TRUE(state.updateAckedIntervals(0, 6, false).has_value());
|
||||||
EXPECT_EQ(state.allBytesAckedTill(5), true);
|
EXPECT_EQ(state.allBytesAckedTill(5), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -730,8 +730,8 @@ TEST(StreamDataTest, AllBytesAckedDisjointIntervals) {
|
|||||||
QuicStreamState state(0, qcsb);
|
QuicStreamState state(0, qcsb);
|
||||||
|
|
||||||
EXPECT_TRUE(state.ackedIntervals.empty());
|
EXPECT_TRUE(state.ackedIntervals.empty());
|
||||||
state.updateAckedIntervals(0, 2, false);
|
ASSERT_TRUE(state.updateAckedIntervals(0, 2, false).has_value());
|
||||||
state.updateAckedIntervals(3, 5, false);
|
ASSERT_TRUE(state.updateAckedIntervals(3, 5, false).has_value());
|
||||||
EXPECT_EQ(state.allBytesAckedTill(5), false);
|
EXPECT_EQ(state.allBytesAckedTill(5), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user