mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-04-18 17:24:03 +03:00
Summary: - as title Reviewed By: lnicco Differential Revision: D33513410 fbshipit-source-id: 282b6f512cf83b9abb7990402661135b658f7bd1
330 lines
9.6 KiB
C++
330 lines
9.6 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 <folly/Expected.h>
|
|
#include <folly/io/async/AsyncUDPSocket.h>
|
|
|
|
#include <quic/QuicException.h>
|
|
#include <quic/api/IoBufQuicBatch.h>
|
|
#include <quic/api/QuicPacketScheduler.h>
|
|
#include <quic/api/QuicSocket.h>
|
|
#include <quic/state/StateData.h>
|
|
|
|
// Function to schedule writing data to socket. Return number of packets
|
|
// successfully scheduled
|
|
namespace quic {
|
|
|
|
struct DataPathResult {
|
|
bool buildSuccess{false};
|
|
bool writeSuccess{false};
|
|
folly::Optional<SchedulingResult> result;
|
|
uint64_t encodedSize{0};
|
|
uint64_t encodedBodySize{0};
|
|
|
|
static DataPathResult makeBuildFailure() {
|
|
return DataPathResult();
|
|
}
|
|
|
|
static DataPathResult makeWriteResult(
|
|
bool writeSuc,
|
|
SchedulingResult&& res,
|
|
uint64_t encodedSizeIn,
|
|
uint64_t encodedBodySizeIn) {
|
|
return DataPathResult(
|
|
writeSuc, std::move(res), encodedSizeIn, encodedBodySizeIn);
|
|
}
|
|
|
|
private:
|
|
explicit DataPathResult() = default;
|
|
|
|
explicit DataPathResult(
|
|
bool writeSuc,
|
|
SchedulingResult&& res,
|
|
uint64_t encodedSizeIn,
|
|
uint64_t encodedBodySizeIn)
|
|
: buildSuccess(true),
|
|
writeSuccess(writeSuc),
|
|
result(std::move(res)),
|
|
encodedSize(encodedSizeIn),
|
|
encodedBodySize(encodedBodySizeIn) {}
|
|
};
|
|
|
|
using DataPathFunc = std::function<DataPathResult(
|
|
QuicConnectionStateBase&,
|
|
PacketHeader,
|
|
PacketNumberSpace,
|
|
PacketNum,
|
|
uint64_t,
|
|
QuicPacketScheduler&,
|
|
uint64_t,
|
|
IOBufQuicBatch&,
|
|
const Aead&,
|
|
const PacketNumberCipher&)>;
|
|
|
|
using HeaderBuilder = std::function<PacketHeader(
|
|
const ConnectionId& srcConnId,
|
|
const ConnectionId& dstConnId,
|
|
PacketNum packetNum,
|
|
QuicVersion version,
|
|
const std::string& token)>;
|
|
|
|
using WritableBytesFunc =
|
|
std::function<uint64_t(const QuicConnectionStateBase& conn)>;
|
|
|
|
// Encapsulating the return value for the write functions.
|
|
// Useful because probes can go over the packet limit.
|
|
struct WriteQuicDataResult {
|
|
uint64_t packetsWritten{};
|
|
uint64_t probesWritten{};
|
|
uint64_t bytesWritten{};
|
|
};
|
|
|
|
/**
|
|
* Attempts to write data from all frames in the QUIC connection into the UDP
|
|
* socket supplied with the aead and the headerCipher.
|
|
*/
|
|
WriteQuicDataResult writeQuicDataToSocket(
|
|
folly::AsyncUDPSocket& sock,
|
|
QuicConnectionStateBase& connection,
|
|
const ConnectionId& srcConnId,
|
|
const ConnectionId& dstConnId,
|
|
const Aead& aead,
|
|
const PacketNumberCipher& headerCipher,
|
|
QuicVersion version,
|
|
uint64_t packetLimit,
|
|
TimePoint writeLoopBeginTime = Clock::now());
|
|
|
|
/**
|
|
* Writes only the crypto and ack frames to the socket.
|
|
*
|
|
* return the number of packets written to socket.
|
|
*/
|
|
WriteQuicDataResult writeCryptoAndAckDataToSocket(
|
|
folly::AsyncUDPSocket& sock,
|
|
QuicConnectionStateBase& connection,
|
|
const ConnectionId& srcConnId,
|
|
const ConnectionId& dstConnId,
|
|
LongHeader::Types packetType,
|
|
Aead& cleartextCipher,
|
|
const PacketNumberCipher& headerCipher,
|
|
QuicVersion version,
|
|
uint64_t packetLimit,
|
|
const std::string& token = std::string());
|
|
|
|
/**
|
|
* Writes out all the data streams without writing out crypto streams.
|
|
* This is useful when the crypto stream still needs to be sent in separate
|
|
* packets and cannot use the encryption of the data key.
|
|
*/
|
|
WriteQuicDataResult writeQuicDataExceptCryptoStreamToSocket(
|
|
folly::AsyncUDPSocket& socket,
|
|
QuicConnectionStateBase& connection,
|
|
const ConnectionId& srcConnId,
|
|
const ConnectionId& dstConnId,
|
|
const Aead& aead,
|
|
const PacketNumberCipher& headerCipher,
|
|
QuicVersion version,
|
|
uint64_t packetLimit);
|
|
|
|
/**
|
|
* Writes frame data including zero rtt data to the socket with the supplied
|
|
* zero rtt cipher.
|
|
*/
|
|
uint64_t writeZeroRttDataToSocket(
|
|
folly::AsyncUDPSocket& socket,
|
|
QuicConnectionStateBase& connection,
|
|
const ConnectionId& srcConnId,
|
|
const ConnectionId& dstConnId,
|
|
const Aead& aead,
|
|
const PacketNumberCipher& headerCipher,
|
|
QuicVersion version,
|
|
uint64_t packetLimit);
|
|
|
|
/**
|
|
* Whether we should and can write data.
|
|
*
|
|
*/
|
|
WriteDataReason shouldWriteData(const QuicConnectionStateBase& conn);
|
|
bool hasAckDataToWrite(const QuicConnectionStateBase& conn);
|
|
WriteDataReason hasNonAckDataToWrite(const QuicConnectionStateBase& conn);
|
|
|
|
/**
|
|
* Invoked when the written stream data was new stream data.
|
|
*/
|
|
void handleNewStreamDataWritten(
|
|
QuicStreamLike& stream,
|
|
uint64_t frameLen,
|
|
bool frameFin);
|
|
|
|
/**
|
|
* Invoked when the stream data written was retransmitted data.
|
|
*/
|
|
void handleRetransmissionWritten(
|
|
QuicStreamLike& stream,
|
|
uint64_t frameOffset,
|
|
uint64_t frameLen,
|
|
bool frameFin,
|
|
std::deque<StreamBuffer>::iterator lossBufferIter);
|
|
|
|
/**
|
|
* Update the connection and stream state after stream data is written and deal
|
|
* with new data, as well as retranmissions. Returns true if the data sent is
|
|
* new data.
|
|
*/
|
|
bool handleStreamWritten(
|
|
QuicConnectionStateBase& conn,
|
|
QuicStreamLike& stream,
|
|
uint64_t frameOffset,
|
|
uint64_t frameLen,
|
|
bool frameFin,
|
|
PacketNum packetNum,
|
|
PacketNumberSpace packetNumberSpace);
|
|
|
|
bool handleStreamBufMetaWritten(
|
|
QuicConnectionStateBase& conn,
|
|
QuicStreamState& stream,
|
|
uint64_t frameOffset,
|
|
uint64_t frameLen,
|
|
bool frameFin,
|
|
PacketNum packetNum,
|
|
PacketNumberSpace packetNumberSpace);
|
|
|
|
/**
|
|
* Update the connection state after sending a new packet.
|
|
*/
|
|
void updateConnection(
|
|
QuicConnectionStateBase& conn,
|
|
folly::Optional<PacketEvent> packetEvent,
|
|
RegularQuicWritePacket packet,
|
|
TimePoint time,
|
|
uint32_t encodedSize,
|
|
uint32_t encodedBodySize,
|
|
bool isDSRPacket);
|
|
|
|
/**
|
|
* Returns the minimum available bytes window out of path validation rate
|
|
* limiting, 0-rtt total bytes sent limiting, and the congestion controller.
|
|
*/
|
|
uint64_t congestionControlWritableBytes(const QuicConnectionStateBase& conn);
|
|
|
|
uint64_t unlimitedWritableBytes(const QuicConnectionStateBase&);
|
|
|
|
void writeCloseCommon(
|
|
folly::AsyncUDPSocket& sock,
|
|
QuicConnectionStateBase& connection,
|
|
PacketHeader&& header,
|
|
folly::Optional<std::pair<QuicErrorCode, std::string>> closeDetails,
|
|
const Aead& aead,
|
|
const PacketNumberCipher& headerCipher);
|
|
|
|
/**
|
|
* Writes a LongHeader packet with a close frame.
|
|
* The close frame type written depends on the type of error in closeDetails.
|
|
*/
|
|
void writeLongClose(
|
|
folly::AsyncUDPSocket& sock,
|
|
QuicConnectionStateBase& connection,
|
|
const ConnectionId& srcConnId,
|
|
const ConnectionId& dstConnId,
|
|
LongHeader::Types headerType,
|
|
folly::Optional<std::pair<QuicErrorCode, std::string>> closeDetails,
|
|
const Aead& aead,
|
|
const PacketNumberCipher& headerCipher,
|
|
QuicVersion);
|
|
|
|
/**
|
|
* Write a short header packet with a close frame.
|
|
* The close frame type written depends on the type of error in closeDetails.
|
|
*/
|
|
void writeShortClose(
|
|
folly::AsyncUDPSocket& sock,
|
|
QuicConnectionStateBase& connection,
|
|
const ConnectionId& connId,
|
|
folly::Optional<std::pair<QuicErrorCode, std::string>> closeDetails,
|
|
const Aead& aead,
|
|
const PacketNumberCipher& headerCipher);
|
|
|
|
/**
|
|
* Encrypts the packet header for the header type.
|
|
* This will overwrite the header with the encrypted header form. It will verify
|
|
* whether or not there are enough bytes to sample for the header encryption
|
|
* from the encryptedBody via a CHECK.
|
|
*/
|
|
void encryptPacketHeader(
|
|
HeaderForm headerForm,
|
|
uint8_t* header,
|
|
size_t headerLen,
|
|
const uint8_t* encryptedBody,
|
|
size_t bodyLen,
|
|
const PacketNumberCipher& headerCipher);
|
|
|
|
/**
|
|
* Writes the connections data to the socket using the header
|
|
* builder as well as the scheduler. This will write the amount of
|
|
* data allowed by the writableBytesFunc and will only write a maximum
|
|
* number of packetLimit packets at each invocation.
|
|
*/
|
|
WriteQuicDataResult writeConnectionDataToSocket(
|
|
folly::AsyncUDPSocket& sock,
|
|
QuicConnectionStateBase& connection,
|
|
const ConnectionId& srcConnId,
|
|
const ConnectionId& dstConnId,
|
|
HeaderBuilder builder,
|
|
PacketNumberSpace pnSpace,
|
|
QuicPacketScheduler& scheduler,
|
|
const WritableBytesFunc& writableBytesFunc,
|
|
uint64_t packetLimit,
|
|
const Aead& aead,
|
|
const PacketNumberCipher& headerCipher,
|
|
QuicVersion version,
|
|
TimePoint writeLoopBeginTime,
|
|
const std::string& token = std::string());
|
|
|
|
uint64_t writeProbingDataToSocket(
|
|
folly::AsyncUDPSocket& sock,
|
|
QuicConnectionStateBase& connection,
|
|
const ConnectionId& srcConnId,
|
|
const ConnectionId& dstConnId,
|
|
const HeaderBuilder& builder,
|
|
EncryptionLevel encryptionLevel,
|
|
PacketNumberSpace pnSpace,
|
|
FrameScheduler scheduler,
|
|
uint8_t probesToSend,
|
|
const Aead& aead,
|
|
const PacketNumberCipher& headerCipher,
|
|
QuicVersion version,
|
|
const std::string& token = std::string());
|
|
|
|
uint64_t writeD6DProbeToSocket(
|
|
folly::AsyncUDPSocket& sock,
|
|
QuicConnectionStateBase& connection,
|
|
const ConnectionId& srcConnId,
|
|
const ConnectionId& dstConnId,
|
|
const Aead& aead,
|
|
const PacketNumberCipher& headerCipher,
|
|
QuicVersion version);
|
|
|
|
HeaderBuilder LongHeaderBuilder(LongHeader::Types packetType);
|
|
HeaderBuilder ShortHeaderBuilder();
|
|
|
|
void maybeSendStreamLimitUpdates(QuicConnectionStateBase& conn);
|
|
|
|
void implicitAckCryptoStream(
|
|
QuicConnectionStateBase& conn,
|
|
EncryptionLevel encryptionLevel);
|
|
void handshakeConfirmed(QuicConnectionStateBase& conn);
|
|
bool hasInitialOrHandshakeCiphers(QuicConnectionStateBase& conn);
|
|
|
|
bool writeLoopTimeLimit(
|
|
TimePoint loopBeginTime,
|
|
const QuicConnectionStateBase& connection);
|
|
|
|
} // namespace quic
|