1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-11-22 16:02:34 +03:00
Files
mvfst/quic/state/QuicStateFunctions.h
Matt Joras d3e8fe246a 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
2025-08-19 10:47:24 -07:00

128 lines
3.9 KiB
C++

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <quic/QuicConstants.h>
#include <quic/codec/QuicPacketBuilder.h>
#include <quic/codec/Types.h>
#include <quic/common/Expected.h>
#include <quic/common/IntervalSet.h>
#include <quic/common/NetworkData.h>
#include <quic/state/StateData.h>
namespace quic {
void updateAckSendStateOnRecvPacket(
QuicConnectionStateBase& conn,
AckState& ackState,
uint64_t distanceFromExpectedPacketNum,
bool pktHasRetransmittableData,
bool pktHasCryptoData,
bool initPktNumSpace = false);
void updateAckStateOnAckTimeout(QuicConnectionStateBase& conn);
void updateAckSendStateOnSentPacketWithAcks(
QuicConnectionStateBase& conn,
AckState& ackState,
PacketNum largestAckScheduled);
void updateRtt(
QuicConnectionStateBase& conn,
const std::chrono::microseconds rttSample,
const std::chrono::microseconds ackDelay);
bool isConnectionPaced(const QuicConnectionStateBase& conn) noexcept;
AckState& getAckState(
QuicConnectionStateBase& conn,
PacketNumberSpace pnSpace) noexcept;
const AckState& getAckState(
const QuicConnectionStateBase& conn,
PacketNumberSpace pnSpace) noexcept;
const AckState* getAckStatePtr(
const QuicConnectionStateBase& conn,
PacketNumberSpace pnSpace) noexcept;
AckStateVersion currentAckStateVersion(
const QuicConnectionStateBase& conn) noexcept;
PacketNum getNextPacketNum(
const QuicConnectionStateBase& conn,
PacketNumberSpace pnSpace) noexcept;
void increaseNextPacketNum(
QuicConnectionStateBase& conn,
PacketNumberSpace pnSpace,
bool dsrPacket = false) noexcept;
/**
* Update largestReceivedUdpPacketNum in ackState with packetNum. Return the
* distance from the next packet number we expect to receive.
*/
[[nodiscard]] Expected<uint64_t, IntervalSetError> addPacketToAckState(
QuicConnectionStateBase& conn,
AckState& ackState,
const PacketNum packetNum,
const ReceivedUdpPacket& udpPacket);
std::deque<OutstandingPacketWrapper>::iterator getNextOutstandingPacket(
QuicConnectionStateBase& conn,
PacketNumberSpace packetNumberSpace,
std::deque<OutstandingPacketWrapper>::iterator from);
std::deque<OutstandingPacketWrapper>::iterator getFirstOutstandingPacket(
QuicConnectionStateBase& conn,
PacketNumberSpace packetNumberSpace);
std::deque<OutstandingPacketWrapper>::reverse_iterator getLastOutstandingPacket(
QuicConnectionStateBase& conn,
PacketNumberSpace packetNumberSpace,
bool includeDeclaredLost = false,
bool includeScheduledForDestruction = false);
bool hasReceivedUdpPackets(const QuicConnectionStateBase& conn) noexcept;
bool hasReceivedUdpPacketsAtLastCloseSent(
const QuicConnectionStateBase& conn) noexcept;
bool hasNotReceivedNewPacketsSinceLastCloseSent(
const QuicConnectionStateBase& conn) noexcept;
void updateLargestReceivedUdpPacketsAtLastCloseSent(
QuicConnectionStateBase& conn) noexcept;
Optional<TimePoint>& getLossTime(
QuicConnectionStateBase& conn,
PacketNumberSpace pnSpace) noexcept;
bool canSetLossTimerForAppData(const QuicConnectionStateBase& conn) noexcept;
std::pair<Optional<TimePoint>, PacketNumberSpace> earliestLossTimer(
const QuicConnectionStateBase& conn) noexcept;
std::pair<Optional<TimePoint>, PacketNumberSpace> earliestTimeAndSpace(
const EnumArray<PacketNumberSpace, Optional<TimePoint>>& times,
bool considerAppData) noexcept;
uint64_t maximumConnectionIdsToIssue(const QuicConnectionStateBase& conn);
bool checkCustomRetransmissionProfilesEnabled(
const QuicConnectionStateBase& conn);
/**
* Checks if the retransmission policy on the stream group prohibits
* retransmissions.
*/
bool streamRetransmissionDisabled(
QuicConnectionStateBase& conn,
const QuicStreamState& stream);
} // namespace quic